#include "mainwindow.h"
#include <QMessageBox>
 
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{	
	this->_layout = new QVBoxLayout(this);
	this->_headerLayout = new QHBoxLayout();
	this->_contentLayout = new QHBoxLayout();
 
	this->_layout->addLayout(this->_headerLayout);
	this->_layout->addLayout(this->_contentLayout);
 
	this->_forward = new QPushButton("-->>");
	this->_back = new QPushButton("<<--");
	this->_go = new QPushButton("Go!");
	this->_reload = new QPushButton("@");
	this->_addTab = new QPushButton("+");
 
	this->_url = new QLineEdit();
 
	this->_headerLayout->addWidget(this->_addTab);
	this->_headerLayout->addWidget(this->_back);
	this->_headerLayout->addWidget(this->_forward);
	this->_headerLayout->addWidget(this->_reload);
	this->_headerLayout->addWidget(this->_url);
	this->_headerLayout->addWidget(this->_go);
 
	this->_webViews = new QList<QWebView*>();
	this->_tabs = new QTabWidget();
 
	this->_contentLayout->addWidget(this->_tabs);
 
	QObject::connect(this->_addTab, SIGNAL(clicked()), this, SLOT(AddWebTab()));
	QObject::connect(this->_url, SIGNAL(returnPressed()), this, SLOT(ReturnPressed()));
	QObject::connect(this->_go, SIGNAL(clicked()), this, SLOT(ReturnPressed()));
	QObject::connect(this->_tabs, SIGNAL(currentChanged(int)), this, SLOT(ChangeTab(int)));
 
	this->AddWebTab();
}
 
MainWindow::~MainWindow()
{
 
}
 
void MainWindow::ChangeTab(int index)
{
	this->setWindowTitle( this->_webViews->at(index)->title() );
	this->_url->setText( this->_webViews->at(index)->url().toString() );
}
 
void MainWindow::AddWebTab(const QUrl& url)
{
	int index = this->_tabs->count();
 
	this->_webViews->append(new QWebView());
	this->_webViews->at(index)->load(url);
	this->_tabs->addTab(this->_webViews->at(index), "");
 
	QObject::connect(this->_webViews->at(index), SIGNAL(linkClicked(const QUrl&)), this, SLOT(AddWebTab(const QUrl&)));
	QObject::connect(this->_webViews->at(index), SIGNAL(titleChanged(const QString&)), this, SLOT(TitleChanged(const QString&)));
	QObject::connect(this->_webViews->at(index), SIGNAL(urlChanged(const QUrl&)), this, SLOT(URLChanged(const QUrl&)));
	QObject::connect(this->_reload, SIGNAL(clicked()), this->_webViews->at(index), SLOT(reload()));
	QObject::connect(this->_back, SIGNAL(clicked()), this->_webViews->at(index), SLOT(back()));
	QObject::connect(this->_forward, SIGNAL(clicked()), this->_webViews->at(index), SLOT(forward()));
}
 
void MainWindow::URLChanged(const QUrl& title)
{
	QWebView* qw = qobject_cast<QWebView*>(QObject::sender());
	int index = this->_webViews->indexOf(qw);
 
	if( index == this->_tabs->currentIndex() )
	{
		this->_url->setText( title.toString() );
	}
}
 
void MainWindow::TitleChanged(const QString& title)
{
	QWebView* qw = qobject_cast<QWebView*>(QObject::sender());
	int index = this->_webViews->indexOf(qw);	
 
	this->_tabs->setTabText(index, title);
 
	if( index == this->_tabs->currentIndex() )
	{
		this->setWindowTitle(title);
	}
}
 
void MainWindow::ReturnPressed()
{
	QString url = this->_url->text().trimmed().toLower();
	QString goTo;
 
	if( url.contains(" ") || !url.contains(".") )
	{
		goTo = "http://www.google.it/search?q=" + url.replace(" ", "+");
	}
	else 
	{
		if( !url.startsWith("https://") && !url.startsWith("http://") )
		{
			goTo = QString("http://" + url);
		}
		else 
		{
			goTo = url;
		}
	}
 
	int index = this->_tabs->currentIndex();
	this->_webViews->at(index)->load(goTo);
}

using System;
using Gtk;
using Mono.WebBrowser;
using System.Text;
using System.Text.RegularExpressions;
 
using System.Collections.Generic;
 
namespace SharpBrowser
{
	public static class Helpers
	{
		public static String AsURL(this String url)
		{
			url = url.Trim().ToLower();
			String goTo = "";
 
			if( url.Contains(" ") || !url.Contains(".") )
			{
				goTo = "http://www.google.it/search?q=" + url.Replace(" ", "+");
			}
			else 
			{
				if( !url.StartsWith("http://") && !url.StartsWith("https://") )
				{
					goTo = "http://" + url;
				}
				else 
				{
					goTo = url;
				}
			}
 
			return goTo;
		}
	}
 
	public class MainWindow : Window
	{
		private static MainWindow _MainInstance;
		public static MainWindow GetInstance()
		{
			if( MainWindow._MainInstance == null )
			{
				MainWindow._MainInstance = new MainWindow("#Browser");
			}
 
			return MainWindow._MainInstance;
		}
 
		private Notebook _tabs;
 
		private List<WebView> _webViews;
		private List<ScrolledWindow> _scrolledWindows;
 
		private Button _forward;
		private Button _back;
		private Button _reload;
		private Button _go;
		private Button _add;
 
		private Entry _url;
 
		private MainWindow(String title) : base(title)
		{
			this._tabs = new Notebook();
			this._webViews = new List<WebView>();
			this._scrolledWindows = new List<ScrolledWindow>();
 
			this._add = new Button("+");
			this._back = new Button("<<--");
			this._forward = new Button("-->>");
			this._reload = new Button("@");
			this._url = new Entry();
			this._go = new Button("Go!");
 
			this._tabs.SwitchPage += MainWindow._SwitchPage;
 
			this._add.Clicked += MainWindow._AddClicked;
			this._back.Clicked += MainWindow._BackClicked;
			this._forward.Clicked += MainWindow._ForwardClicked;
			this._reload.Clicked += MainWindow._ReloadClicked;
			this._url.Activated += MainWindow._GoClicked;
			this._go.Clicked += MainWindow._GoClicked;
 
			this._tabs.Scrollable = true;
		}
 
		public void buildHeader(ref VBox vbox)
		{
			HBox hb = new HBox();
 
			hb.PackStart(this._add, false, false, 3);
			hb.PackStart(this._back, false, false, 3);
			hb.PackStart(this._forward, false, false, 3);
			hb.PackStart(this._reload, false, false, 3);
			hb.PackStart(this._url, true, true, 3);
			hb.PackStart(this._go, false, false, 3);
 
			this._url.IsEditable = true;
			this._url.Visibility = true;
 
			vbox.PackStart(hb, false, false, 3);
		}
 
		public void buildContent(ref VBox vbox)
		{
			vbox.PackStart(this._tabs, true, true, 3);
			this._addNewTab();
		}
 
		private void _addNewTab(String url = "about:blank")
		{
			WebView aWebView = new WebView();
			aWebView.TitleChanged += MainWindow._TitleChanged;
			aWebView.LoadFinished += MainWindow._LoadFinished;
 
			ScrolledWindow aScrolledWindow = new ScrolledWindow();
			aScrolledWindow.Add(aWebView);
 
			this._tabs.AppendPage(aScrolledWindow, new Label("Tab"));
			this._webViews.Add(aWebView);
			this._scrolledWindows.Add(aScrolledWindow);
 
			aWebView.Show();
			aScrolledWindow.Show();
		}
 
		public static void _TitleChanged(System.Object o, TitleChangedArgs args)
		{
			WebView webView = (WebView)o;
			Int32 index = MainWindow.GetInstance()._webViews.IndexOf(webView);
			MainWindow.GetInstance()._tabs.SetTabLabelText(MainWindow.GetInstance()._scrolledWindows[index], webView.Title);
 
			if( index == MainWindow.GetInstance()._tabs.CurrentPage )
			{
				MainWindow.GetInstance().Title = webView.Title;
			}
		}
 
		public static void _LoadFinished(System.Object o, LoadFinishedArgs args)
		{
			Int32 index = MainWindow.GetInstance()._webViews.IndexOf((WebView)o);
 
			if( index == MainWindow.GetInstance()._tabs.CurrentPage )
			{
				MainWindow.GetInstance()._url.Text = MainWindow.GetInstance()._webViews[index].Uri;
			}
		}
 
		private static void _AddClicked(System.Object sender, EventArgs args) 
		{
			MainWindow.GetInstance()._addNewTab();
		}
 
		private static void _BackClicked(System.Object sender, EventArgs args) 
		{
			Int32 index = MainWindow.GetInstance()._tabs.CurrentPage;
			WebView aWebView = MainWindow.GetInstance()._webViews[index];
 
			if( aWebView.CanGoBack() == true )
			{
				aWebView.GoBack();
			}
		}
 
		private static void _ForwardClicked(System.Object sender, EventArgs args) 
		{
			Int32 index = MainWindow.GetInstance()._tabs.CurrentPage;
			WebView aWebView = MainWindow.GetInstance()._webViews[index];
 
			if( aWebView.CanGoForward() == true )
			{
				aWebView.GoForward();
			}
		}
 
		private static void _ReloadClicked(System.Object sender, EventArgs args) 
		{
			Int32 index = MainWindow.GetInstance()._tabs.CurrentPage;
			WebView aWebView = MainWindow.GetInstance()._webViews[index];
 
			aWebView.Reload();
		}
 
		private static void _GoClicked(System.Object sender, EventArgs args) 
		{
			Int32 index = MainWindow.GetInstance()._tabs.CurrentPage;
			WebView aWebView = MainWindow.GetInstance()._webViews[index];
 
			aWebView.Open(MainWindow.GetInstance()._url.Text.AsURL());
		}
 
		private static void _SwitchPage(System.Object sender, SwitchPageArgs args)
		{
			Int32 index = MainWindow.GetInstance()._tabs.CurrentPage;
			System.Console.WriteLine( "CurrentPage:" + index + " WebViewsCount:" + MainWindow.GetInstance()._webViews.Count );
 
			String entryText = "";
			String title = "#Browser";
			if( MainWindow.GetInstance()._webViews.Count > index && index > -1 )
			{
				entryText = (MainWindow.GetInstance()._webViews[index].Uri != null) ? MainWindow.GetInstance()._webViews[index].Uri : entryText;
				title = (MainWindow.GetInstance()._webViews[index].Title != null) ? MainWindow.GetInstance()._webViews[index].Title : title;
			}
 
			MainWindow.GetInstance()._url.Text = entryText;
			MainWindow.GetInstance().Title = title;
		}
	}
 
	public class MainClass
	{
		public static void Main (string[] args)
		{
			Application.Init ();
 
			MainWindow mw = MainWindow.GetInstance();
			mw.Maximize();
			mw.DeleteEvent += MainClass._DeleteEvent;
 
			VBox vbox = new VBox();
 
			mw.buildHeader(ref vbox);
			mw.buildContent(ref vbox);
 
			mw.Add(vbox);
			mw.ShowAll();
			mw.Show();
			Application.Run ();
		}
 
		private static void _DeleteEvent(System.Object sender, DeleteEventArgs args)
		{
			Application.Quit();
		}
	}
}

Il libro in questione edito da No Starch Inc. il 1 novembre 2010 e scritto da Michael Kerrisk si presenta come una vera e propria bibbia della GNU C Library e della Single Unix Specification aggiornata alla versione 3, SUSv3.

Il testo che conta 1552 pagine e 63 capitoli si apre con un capitolo dedicato alla nascita del primo sistema operativo UNIX nei laboratori Bell, una divisione di AT&T, ad opera di Ken Thompson. Il testo sottolinea come la data di nascita del primo sistema UNIX combaci con l’anno di nascita di Linus Torvalds.

I capitoli che compongono il libro, in ogni caso, sono i seguenti:

  1. History and Standards
  2. Fundamental concepts
  3. System programming concepts
  4. File I/O: The universal I/O Model
  5. File I/O: Further details
  6. Processes
  7. Memory allocation
  8. Users and groups
  9. Process credentials
  10. Time
  11. System limits and options
  12. System and process information
  13. File I/O buffering
  14. File Systems
  15. File attributes
  16. Extended attributes
  17. Access contrli lists
  18. Directories and links
  19. Monitoring file events
  20. Signal: fundamental concepts
  21. Signal: signal handlers
  22. Signal: advanced features
  23. Timers and sleeping
  24. Process creation
  25. Monitoring child processes
  26. Program execution
  27. Process creation and process execution in more detail
  28. Threads: Introduction
  29. Threads: Threads Synchronization
  30. Threads: Thread safety and Per-thread storage
  31. Threads: Thread cancellation
  32. Threads: Further details
  33. Process groups, sessions and job contrli
  34. Process priorities and scheduling
  35. Process resources
  36. Daemons
  37. Writing secure privileged programs
  38. Capabilities
  39. Login accounting
  40. Fundamentals of shared libraries
  41. Advanced features of shared libraries
  42. Interprocess communication overview
  43. Pipes and FIFOs
  44. Introduction to System V IPC
  45. System V Message queues
  46. System V semaphores
  47. System V Shared memory
  48. Memory Mapping
  49. Virtual memory Operations
  50. Introduction to POSIX IPC
  51. POSIX Message Queues
  52. POSIX Semaphores
  53. POSIX Shared memory
  54. File locking
  55. Sockets: introduction
  56. Sockets: UNIX Domain
  57. Sockets: Fundamentals od TCP/IP networks
  58. Sockets: Internet domains
  59. Sockets: Server design
  60. Sockets: Advanced topics
  61. Terminals
  62. Alternative I/O Models
  63. Pseudoterminals

E Nell’appendice troviamo:

  1. Tracing system calls
  2. Parsing command-line options
  3. Casting the NULL pointer
  4. Kernel configuration
  5. Further sources of information
  6. Sliutions to selected exercises

Possiamo renderci conto della bonta’ del testo attraverso vari commenti posti all’inizio del libro ad opera di alcuni dei maggiori esperti in circolazione del campo software.

“Se dovessi scegliere un libro da tenere con me mentre scrivo software per Linux, sarebbe questo.”
-Martin Landers, Software Engineer, Google.

“Il nuovo libro di Michael Kerrisk e’ un esempio di bellezza. Un libro di cui puoi essere fiero solamente tenendolo nella libreria ma che pur stando li’ ha una sua utilita’”
- Serge Hallyn, Linux Kernel Developer

“Ho trovato The Linux Programming Interface molto utile e torno a sfogliarlo molto frequentemente. Coloro che hanno il desiderio di sviluppare per Linux si sentiranno allo stesso modo.”
- Jake Edge, LWM.net

“Il libro di Michael e’ una sorta di bestia, tutto cio’ a cui posso ragionevolmente pensare riguardo l’argomento e’ presente nel suo libro descritta in maniera maniacale e completa, e’ davvero un piacere leggerlo.”
- Federico Lucifredi, Slashdot.org

Il libro e` disponibile su Amazon.it a questo indirizzo:

Assicuriamoci di aver installato sulla nostra macchina il pacchetto mysqlclient e dopo aver salvato in un file .sh il seguente script con conseguente modifica dei parametri propri del server mysql ci bastera` richiamarlo con sh $nomescript.sh

#!/bin/bash
DATE=$(date +%Y_%m_%d)
 
DUMPS_PATH="/directory/radice/backup/"
 
TAR_BIN=$(which tar)
MYSQL_BIN=$(which mysql)
MYSQLDUMP_BIN=$(which mysqldump)
MKDIR_BIN=$(which mkdir)
RM_BIN=$(which rm)
 
MY_USER="username"
MY_PASS="password"
MY_HOST="hostnameDB"
 
MY_DATABASES=$($MYSQL_BIN -u $MY_USER -p$MY_PASS -h $MY_HOST -Bse 'SHOW DATABASES')
 
if [ ! -d "$DUMPS_PATH/mysql/$DATE" ]; then
 $MKDIR_BIN -p "$DUMPS_PATH/mysql/$DATE"
fi
 
for DB in $MY_DATABASES; do
 if [ "$DB" != "information_schema" ] && [ "$DB" != "mysql" ]; then
  $MYSQLDUMP_BIN -u $MY_USER -p$MY_PASS -h $MY_HOST $DB > "$DUMPS_PATH/mysql/$DATE/$DB.sql"
 fi
done
 
$TAR_BIN --lzma -cf "$DUMPS_PATH/mysql/$DATE.tar.lzma" "$DUMPS_PATH/mysql/$DATE"
$RM_BIN -fr "$DUMPS_PATH/mysql/$DATE"

Salvare lo script in un file .sh nella directory radice della propria collezione musicale

#!/bin/bash
 
LEN=${#1}
LENN=$LEN-4
FOR=${1:$LENN:$LEN}
P=$(pwd)
 
if [ "$FOR" == ".ogg" ]; then 
 exit
else
 NAME=${1:0:$LENN}
 
 if [ "$FOR" == ".mp3" ] || [ "$FOR" == ".wma" ] || [ "$FOR" == ".m4a" ]; then
  ffmpeg -i "$1" -acodec libvorbis "$NAME.ogg"
 fi
 rm "$P/$1"
fi

e richiamarlo con

find . -name '*' -exec sh script_name {} \;

OpenSSH e` un suite di programmi per la comunicazione sicura e criptata fra computer. Di norma l’autenticazione puo` avvenire mediante l’utilizzo di username e password per identificare l’utente. Ma c`e` un modo piu` sicuro di ottenere lo stesso risultato, l’autenticazione attraverso chiave pubblica e privata, che permette a un amministratore di sistema di dormire sonni tranquilli almeno per quanto concerne la possibilita` che utenti di sistema possano usare password deboli e non molto resistenti ad attacchi di brute force[1].
Un’altro dei vantaggi legato all’autenticazione attraverso chiavi pubbliche e` quello di poter usare la stessa chiave pubblica per effettuare il login su piu` server sshd con una sola chiave privata.

Per quanti desiderassero avere maggiori dettagli che esulano dallo scopo di questo tutorial sul funzionamento del sistema di autenticazione descritto rimando a questo indirizzo: http://www.ietf.org/rfc/rfc4716.txt

A questo punto sul computer che sara` client creiamo la nostra keypair digitando nella shell:

ssh-keygen -b 4096 -f $nome_da_dare_al_file -C "Nome cognome"
ssh-copy-id -i $nome_dato_al_file.pub $username_remoto@hostname

In questo modo la chiave sara` aggiunta al file ~/.ssh/authorized_keys, insieme alle chiavi pubbliche degli altri utenti autorizzati a loggare in quell’account a cui fa capo la directory home in cui risiede quel file.

Quindi apriamo il file /etc/ssh/sshd_config controlliamo di avere i seguenti valori per i seguenti parametri:

IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
IgnoreUserKnownHosts yes
 
DSAAuthentication yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
 
AllowUsers $nome_utente_1 $nome_utente_2 $nome_utente_XYZ
ChallengeResponseAuthentication no
LoginGraceTime 50s
MaxAuthTries 3
PasswordAuthentication no
PermitEmptyPasswords no
PermitRootLogin no
StrictModes yes
Subsystem sftp /usr/libexec/sftp-server
UsePrivilegeSeparation yes
PermitUserEnvironment yes
PrintMotd no
UseDNS no

Facciamo ripartire il demone sshd e logghiamo quindi utilizzando il metodo appena implementato.

[1] e` comunque da assicurare il fatto che le chiavi private degli utenti siano ben conservate sui rispettivi computer, una pratica accettabile potrebbe essere per esempio quella di dare alle chiavi private permessi 500 e di scegliere una password per decriptare la chiave privata abbastanza resistente.

Nel caso in cui dovessimo trovarci ad avere a che fare con la gestione di un server aziendale o personale su Linux potremmo avere come unica via d’accesso al terminale SSHd ora SSHd e` davvero uno strumento potente ma oltre ad esserlo per noi lo e` anche per potenziali droidi, gente senza sonno che cerca sempre di trovare il modo di infastidire cristiani pacifici come noi.
Come possiamo fare in modo di allontanare questa minaccia dai nostri server? Una delle precauzioni da adottare e` senza dubbio quella di disabilitare l’accesso l’accesso come root a SSHd. Comunque allontaniamo definitivamente il pericolo di brute force e una volta root diamo il comando:

iptables -N BF_SSHD
iptables -A BF_SSHD -p tcp --dport 22 -m state --state NEW -j BF_SSHD
iptables -A BF_SSHD -m recent --set --name SSH
iptables -A BF_SSHD -m recent --update --seconds 120 --hitcount 3 --name BF_SSHD -j DROP

Con questi comandi ogni volta che un utente cerchera` di connettersi per almeno 3 volte nell’arco di 120 secondi al nostro demone SSHd iptables fara` il suo dovere droppando tutte le connessioni provenienti da quell’IP.

Nel caso abbiate problemi con la diffusioni di dati personali sensibili temporanei o meno e vogliate prevenire che questi siano inviati insieme alle vostre mail da un smtpd come postfix ogni volta che inviate mail a qualcuno dovrete dire a postfix di ignorarne la presenza e di desistere dall’includerli.

Per prima cosa dovrete essere sicuri di aver compilato/installato o che sia presente out-of-the-box in /etc/postfix/dynamicmaps.cf il modulo “regexp”

Dovrete poi aggiungere al file /etc/postfix/main.cf la direttiva

header_checks = regexp:/etc/postfix/header_checks

A questo punto aprite il file /etc/postfix/header_checks e pastate questo contenuto all’interno:

/^Received: from .*/ IGNORE
/^X-Mailer: .*/ IGNORE
/^X-originating-IP: .*/ IGNORE
/^X-Sender-ID: .*/ IGNORE
/^X-Sender-IP: .*/ IGNORE

D’ora in avanti dati come il vostro indirizzo di posta o informazioni sul software usato per inviare mail non saranno piu` accompagnatori delle vostre mail

Supponiamo che un giorno volessimo implementare un sistema di sicurezza basato sull’autenticazione dell’utente attraverso certificati emessi e firmati da una nostra Certificate Authority, quello che ci serve in pratica è acquisire dimestichezza con:

  • OpenSSL > 0.9.8j
  • Apache HTTPd > 2.2.12
  • mod_ssl
  • Le API del nostro linguaggio preferito per OpenSSL
Questa guida ci porterà man mano a implementare un sistema di sicurezza del genere partendo da questo articolo che spiega come mettere su la Certificate Authority che servirà poi a firmare i certificati degli utenti.
Bene, a questo punto supponete per 10 minuti di chiamarvi “mia_CA”, andiamo a vedere i comandi da utilizzare per costruire il tutto.
Per prima cosa creiamo una directory chiamata “mia_CA” nella nostra home o in qualsiasi altro posto, diamo per scontato che vogliamo creare tutto ciò partendo dalla nostra home digitiamo il comando

"mkdir ~/mia_CA"

A questo punto apriamo il file /etc/ssl/openssl.cnf con il nostro editor di testo preferito e andiamo a modificare questi valori

default_ca = CA_default (prima)
default_ca = mia_CA (dopo)
 
[ CA_default ] (prima)
[ mia_CA ] (dopo)
 
dir = ./demoCA (prima)
dir = /home/mia_CA/CA (dopo)
 
default_days = 365 (prima)
default_days = 3650 (dopo)
 
default_bits = 1024 (prima)
default_bits = 4096 (dopo)

Ci sono altri parametri
Successivamente scavando nel file troveremo anche altri campi che potremmo voler editare non è comunque un’azione obbligata, in realtà sono campi che servono per dare dei valori predefiniti in modo che alla creazione di un certificato non ci tocchi scrivere di continuo gli stessi valori, ma saranno modificabili laddove ce ne sia bisogno alla creazione di ogni certificato, ma comunque se proprio vogliamo facciamo attenzione a due parametri solamente a un certo punto abbiamo “nsCaRevocationUrl” questo deve essere un indirizzo valido a un file chiamato “CRL” Certificate Revocation List, in pratica quando ci troviamo a dover dialogare con qualcosa che si identifica attraverso un certificato dobbiamo sapere se quel certificato è ancora valido o meno, non si tratta della data di scadenza, si tratta di revoca, facciamo un esempio, oggi assumiamo un dipendente, Callisto Tanzi, gli diamo un certificato e domani Callisto scappa con i dati della nostra azienda più il certificato, domani parla con qualcuno e si identifica attraverso il certificato emesso dalla nostra certificate authority, ora, come fa a sapere l’interlocutore del caro Callisto che egli non è più rappresentante della nostra azienda? Ecludiamo metodi barbari come il telefono e la mail, a noi serve un processo automatizzato non possiamo ricevere 2000 telefonate per verificare un nostro utente, sennò potremmo verificare le identità senza bisogno di certificati, bene, l’interlocutore a questo punto manda una richiesta alla URL (impressa a fuoco nel certificato) a cui trovare la CRL e nota che quel certificato non è più valido, bene, abbiamo salvato delle persone che stavano per essere fregate e ci siamo risparmiati delle grane a causa del fatto di aver mandato in giro un figuro come Callisto senza avvisare nessuno della sua non autorità di rappresentarci. Questo è un concetto chiave per una Certificate Authority, state attenti, il primo principio di un sistema basato su SSL è proprio questo, il fatto di sapere chi è il nostro interlocutore perchè certificato nella propria identità da un’azienda. Molte CA pubbliche quando emettono un certificato che poi viene mostrato sul sito delle aziende che lo posseggono mettono in bella vista cifre di assicurazione (10,000 USD Rewards), quelle cifre sono destinate a voi nel caso in cui a causa di una verifica pressappochista da parte della CA emittente doveste venire truffati. Attenzione quindi alla CRL e all’emissione di certificati su larga scala. Fate sempre le vostre verifiche.

Il secondo parametro a cui dobbiamo prestare attenzione è il common name, il common name è il nome dell’entità che stiamo certificando, nel caso di una persona potrebbe essere il nome e cognome o l’indirizzo di posta elettronica, nel caso di un sito web potrebbe essere la url https://www.kyxz.me avrebbe come CommonName www.francescoallara.it, evitate di emettere certificati che includano una wildcard per il vostro bene per esempio *.kyxz.me

Per il resto comunque facciamo attenzione a dare un valore a quei parametri il cui nome finisce per _default per non dover fare successivamente operazioni ricorsive.

A questo punto diamo uno sguardo alle estensioni, se notiamo nel file openssl.cnf abbiamo di fronte varie sezioni che cominciano per esempio con

[ v3_ca ] 
[ v3_req ] 
[ usr_cert ]

Bene, queste sono scorciatoie per decidere di volta in volta che ruolo e come puo` essere usato il certificato una volta emesso, v3_ca per esempio contiene un parametro

basicConstraint = CA:true

che ci dice che il certificato puo` essere usato per firmare altre richieste di richieste di certificato, cosa per il quale potremmo anche settare il parametro “nsCertType”, che a sua volta puo` contenere ben 4 valori diversi che sono

nsCertType = email, server, user, objsign
  • email: il certificato verra` usato per verificare un indirizzo di posta
  • server: per verificare un server (o un virtualhost, un dominio, solo da apache 2.2.12 compilato con openssl da 0.9.8j in poi, ovvero con il supporto a SNI (Server Name Indication)
  • user: Il certificato viene utilizzato per confermare l’identita` di un utente
  • objsign: Il certoficato viene usato per firmare e quindi verificare altre richieste di certificato

Sebbene sia possibile dare piu` valori a nsCertType io consiglierei di far si` di avere a disposizione piu` “estensioni” e di crearne delle proprie per avere la massima flessibilita` successivamente alla firma di ogni certificato potremmo caricare l’estensione con i parametri piu` adatti a quel certificato dando a “openssl” cli il parametro -extensions %nome_estensione% per esempio -extensions v3_ca

Bene a questo punto dopo aver smanettato iniziamo a dare i comandi

#dobbiamo entrare nella directory che conterra` tutti i file della nostra Certificate Authority
cd ~/mia_CA
 
#Questa directory conterra` il certificato e la key privata della nostra Certificate Authority 
mkdir CA (sì dinuovo)
 
#Ora creiamo la struttura per accogliere le richieste, i certificati e le chiavi dei nostri utenti
mkdir server
mkdir server/certificates
mkdir server/requests
mkdir server/keys
mkdir users
mkdir users/certificates
mkdir users/requests
mkdir users/keys
 
#Questo file conterra` il seriale dell'ultimo certificato emesso, incrementandosi ogni volta che emettiamo un certificato
echo 0001 >> serial
 
#in questa directory verranno copiati in automatico tutti i certificati emessi
mkdir newcerts
 
#In questo file di testo verranno scritte in automatico le informazioni riguardanti i certificati emessi di volta in volta
touch index.txt
touch index.txt.attr
 
#i comandi per creare il certificato, richiesta, chiave privata
 
#questo crea una chiave privata
#successivamente avremo bisogno per ogni richiesta di certificato, alla firma, di inserire la password che ora decideremo per questa chiave privata,
#possiamo ovviare a tutto cio` creando temporaneamente una copia pubblica/non decriptata di questa chiave che poi elimineremo con
#openssl rsa -in CA/mia_CA.key -out CA/mia_CA_nopwd.key
openssl genrsa -des3 -rand /dev/random -out CA/mia_CA.key 4096
 
#a questo punto generiamo la richiesta di certificato, ci verranno chiesti vari parametri inseriamo i dati o facciamo affidamento su quelli che abbiamo inserito precedentemente nei vari _default per openssl.cnf
openssl req -new -key CA/mia_CA.key -out CA/mia_CA.csr
 
#bene self-firmiamo la nostra richiesta di certificato in modo da avere un certificato autorizzato a firmare nuove richieste di certificato dando il comando
openssl x509 -extensions v3_ca -req -in CA/mia_CA.csr -out CA/mia_CA.pem -signkey CA/mia_CA.key (o -signkey CA/mia_CA_nopwd.key)

Bene a questo punto se abbiamo fatto tutto come si deve avremo la nostra Certificate Authority con cui emettere certificati e tenere sotto controllo l’identità di chi ci deve rappresentare.