#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); } |
Esempio di codice GTK# e WebKitGTK
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(); } } } |
Recensione: The Linux Programming Interface
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:
- History and Standards
- Fundamental concepts
- System programming concepts
- File I/O: The universal I/O Model
- File I/O: Further details
- Processes
- Memory allocation
- Users and groups
- Process credentials
- Time
- System limits and options
- System and process information
- File I/O buffering
- File Systems
- File attributes
- Extended attributes
- Access contrli lists
- Directories and links
- Monitoring file events
- Signal: fundamental concepts
- Signal: signal handlers
- Signal: advanced features
- Timers and sleeping
- Process creation
- Monitoring child processes
- Program execution
- Process creation and process execution in more detail
- Threads: Introduction
- Threads: Threads Synchronization
- Threads: Thread safety and Per-thread storage
- Threads: Thread cancellation
- Threads: Further details
- Process groups, sessions and job contrli
- Process priorities and scheduling
- Process resources
- Daemons
- Writing secure privileged programs
- Capabilities
- Login accounting
- Fundamentals of shared libraries
- Advanced features of shared libraries
- Interprocess communication overview
- Pipes and FIFOs
- Introduction to System V IPC
- System V Message queues
- System V semaphores
- System V Shared memory
- Memory Mapping
- Virtual memory Operations
- Introduction to POSIX IPC
- POSIX Message Queues
- POSIX Semaphores
- POSIX Shared memory
- File locking
- Sockets: introduction
- Sockets: UNIX Domain
- Sockets: Fundamentals od TCP/IP networks
- Sockets: Internet domains
- Sockets: Server design
- Sockets: Advanced topics
- Terminals
- Alternative I/O Models
- Pseudoterminals
E Nell’appendice troviamo:
- Tracing system calls
- Parsing command-line options
- Casting the NULL pointer
- Kernel configuration
- Further sources of information
- 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:
Semplice script per effettuare il dump di tutti i database MySQL
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" |
Convertire file audio a vorbis con uno script BASH usando ffmpeg
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 {} \; |
Configuriamo SSHd in modo da permettere il login usando chiavi pubbliche/private
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.
Bloccare potenziali attacchi di brute force usando iptables
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.
Prevenire che postfix invii dati sensibili negli headers insieme alle nostre email
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
Creazione e gestione di un sistema di sicurezza basato su SSL – Parte 1: Creazione di una certificate authority
- OpenSSL > 0.9.8j
- Apache HTTPd > 2.2.12
- mod_ssl
- Le API del nostro linguaggio preferito per OpenSSL
"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.