StartTLS e SSL/TLS
Iniziamo ad aumentare la sicurezza del nostro demone slapd impostando le funzionalità di encryption del canale
Considerazioni iniziali
Il servizio di directory LDAP al momento risulta funzionante, ma viene erogato soltanto nella forma non cifrata, ovvero non sicura, questo comporta che chiunque riuscisse ad intercettare la nostra comunicazione tra il demone slapd ed i nostri client potrebbe avere avere accesso alle informazioni trasmesse, come ad esempio alle password che al momento vengono trasmesse sul canale in chiaro.
Potrebbe essere utile impostare il nostro demone in ascolto sia sulla porta TCP 636 equivalente ad LDAP over SSL, che sulla porta TCP 389 con attivo lo StartTLS, lasciandoci così la libertà di scegliere cosa far passare su un canale piuttosto che sull'altro; in aggiunta ci permetterà di poter abilitare il canale "non cifrato" sulla porta 389 ed effettuare uno switch successivo su una connessione SSL/TLS tramite il comando StartTLS.
Diagramma architetturale
Di seguito un semplice diagramma architetturale di esempio di cosa si vuole implementare.

Come potete vedere il nostro demone LDAP erogherà il servizio sia sulla porta TCP 636 con connessione cifrata, che sulla porta TCP 389, dove a seconda delle policy che andremo a vedere, potremo decidere se erogare il servizio "in chiaro" oppure obbligare i nostri client ad eseguire lo StartTLS sempre sulla porta 389. Si è deciso in questo semplice esempio di abilitare verso il mondo esterno il solo canale cifrato, ma comunque si potrebbe benissimo abilitare anche il canale sulla porta 389 obbligando i client ad effettuare lo StartTLS.
Creazione dei certificati
Per prima cosa bisogna creare i certificati SSL per poter cifrare la connessione. Per queste operazioni useremo per comodità il programma CA.pl e la sua man page, che come vedremo ci guiderà sulle operazioni da effettuare.
Creazione della CA
Come primo step dovremo creare l'alberatura della nostra Certification Autorities, prima di fare questo bisogna ricordarsi che il programma CA.pl crea nella directory corrente la cartella demoCA con all'interno tutti i nostri file, in alternativa le impostazioni di default possono essere cambiate andando a modificare il file di configurazione /usr/lib/ssl/openssl.cnf (link simbolico a /etc/ssl/openssl.cnf), ad esempio potrebbe essere utile andare a modificare la validità temporale del certificato server, che di default vale 365 giorni (default_days). Iniziamo...
$ /usr/lib/ssl/misc/CA.pl -newca
Da questo otterremo il seguente listato dove verranno poste una serie di domande a cui rispondere
CA certificate filename (or enter to create)
Making CA certificate ...
Generating a 1024 bit RSA private key
............++++++
.............................................................++++++
writing new private key to './demoCA/private/cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:IT
State or Province Name (full name) [Some-State]:Italy
Locality Name (eg, city) []:Torino
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example.com
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Amedeo Salvati
Email Address []:amedeo@example.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
97:a6:58:4d:91:42:56:f5
Validity
Not Before: Apr 13 12:18:38 2011 GMT
Not After : Apr 12 12:18:38 2014 GMT
Subject:
countryName = IT
stateOrProvinceName = Italy
organizationName = Example.com
commonName = Amedeo Salvati
emailAddress = amedeo@example.com
X509v3 extensions:
X509v3 Subject Key Identifier:
DB:E4:02:CE:88:1E:50:59:7D:D8:71:9E:04:37:33:2F:8B:0B:4F:E7
X509v3 Authority Key Identifier:
keyid:DB:E4:02:CE:88:1E:50:59:7D:D8:71:9E:04:37:33:2F:8B:0B:4F:E7
DirName:/C=IT/ST=Italy/O=Example.com/CN=Amedeo Salvati/emailAddress=amedeo@example.com
serial:97:A6:58:4D:91:42:56:F5
X509v3 Basic Constraints:
CA:TRUE
Certificate is to be certified until Apr 12 12:18:38 2014 GMT (1095 days)
Write out database with 1 new entries
Data Base Updated
Come potete vedere gli imput richiesti e valorizzati sono il Coutry Name (IT), lo State or Province Name (Italy), il Locality Name (Torino), l'Organization Name (Example.com), il Common Name (Amedeo Salvati) e l'Email Address (amedeo@example.com).
Creazione della richiesta di nuovo certificato
Adesso procediamo con la richiesta di un nuovo certificato.
$ /usr/lib/ssl/misc/CA.pl -newreq
Altre domande a cui rispondere
Generating a 1024 bit RSA private key ...............++++++ ...................++++++ writing new private key to 'newkey.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:IT State or Province Name (full name) [Some-State]:Italy Locality Name (eg, city) []:Torino Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example.com Organizational Unit Name (eg, section) []: Common Name (eg, YOUR name) []:example.com Email Address []:amedeo@example.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Request is in newreq.pem, private key is in newkey.pem
Anche qui ci verranno richieste alcune informazioni, che nello specifico sono Country Name (IT), State or Province Name (Italy), Locality Name (Torino), Organization Name (Example.com), Email Address (amedeo@example.com) e molto importante il Common Name che in questo caso bisogna impostarlo al nome del DN (suffix del database di backend) principale che nel nostro caso corrisponde a example.com
Firma del nuovo certificato
Adesso non ci rimane che firmare il nostro certificato appena creato. Vediamo come fare
$ /usr/lib/ssl/misc/CA.pl -signreq
Dove otterremo un listato di questa tipologia
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number:
97:a6:58:4d:91:42:56:f6
Validity
Not Before: Apr 13 12:21:13 2011 GMT
Not After : Apr 12 12:21:13 2012 GMT
Subject:
countryName = IT
stateOrProvinceName = Italy
localityName = Torino
organizationName = Example.com
commonName = example.com
emailAddress = amedeo@example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
96:25:63:4B:0F:BF:98:E1:49:9A:98:61:0C:46:B5:C0:39:37:20:3B
X509v3 Authority Key Identifier:
keyid:DB:E4:02:CE:88:1E:50:59:7D:D8:71:9E:04:37:33:2F:8B:0B:4F:E7
Certificate is to be certified until Apr 12 12:21:13 2012 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Signed certificate is in newcert.pem
Da ricordarsi che verranno utilizzati i parametri presenti nel file /usr/lib/ssl/openssl.cnf (link simbolico a /etc/ssl/openssl.cnf).
Rimozione della passphrase dalla chiave
Se lo si desidera si può togliere dal certificato appena creato la passphrase in modo tale da non doverla immettere ad ogni riavvio del servizio slapd. Per fare questo si può eseguire il comando
$ openssl rsa < newkey.pem > nopwkey.pem
Installazione dei nuovi certificati
Ora non ci resta che provisionare i nuovi certificati e configurare il nostro demone slapd ed i nostri client ad utilizzare una connessione SSL/TLS. Iniziamo con il copiare i certificati nella directory principale /usr/local/etc/openldap di configurazione del demone slapd.
cp newcert.pem /usr/local/etc/openldap/example.com.cert.pem cp nopwkey.pem /usr/local/etc/openldap/example.com.key.pem
Adesso predisponiamo l'ambiente a riconoscere la nostra nuova Certification Autorities come se fosse una CA ufficialmente riconosciuta, per fare questo su ubuntu provvederemo a creare la directory Example.com sotto /usr/share/ca-certificates e qui dentro ci metteremo il nostro certificato con estenzione crt in modo da poter lanciare il comando dpkg-reconfigure ca-certificates
$ sudo mkdir /usr/share/ca-certificates/Example.com $ sudo cp demoCA/cacert.pem /usr/share/ca-certificates/Example.com/Example.com-CA.crt $ sudo chmod a+r /usr/share/ca-certificates/Example.com/Example.com-CA.crt $ sudo dpkg-reconfigure ca-certificates
Dove vi chiederà per prima cosa se dare fiducia alle nuove CA

E successivamente potremo selezionare la nostra nuova CA

Da non preoccuparsi se l'installazione del cacerts per java andrà in errore, questo perchè nel nostro certificato sono presenti più informazioni di quante se ne aspetta il tool di riconfigurazione. Da notare che il file crt appena creato dovrà essere accessibile in lettura da chiunque.
Modifiche da apportare al file slapd.conf
Siamo giunti al punto di dover configurare il nostro demone slapd, in modo da dirgli di caricare le chiavi create per poter avviare una sessione StartTLS o direttamente TLS. La differenza sta nel fatto che possiamo lasciare aperta la connessione ldap verso la porta TCP 389 ed una volta che il client si sarà collegato si potrà effettuare lo StartTLS passando così ad una connessione cifrata, oppure si potrà direttamente permettere la sola connessione verso la porta TCP 636 che sarà direttamente cifrata in TLS, senza passaggi intermedi
Prima della configurazione del database immettere le direttive
########### # SSL/TLS # ########### TLSCACertificatePath /etc/ssl/certs TLSCertificateFile /usr/local/etc/openldap/example.com.cert.pem TLSCertificateKeyFile /usr/local/etc/openldap/example.com.key.pem security ssf=128
Modifiche da apportare al file ldap.conf
Sul file ldap.conf le modifiche da apportare sono poche, ovvero basta soltanto dirgli che la directory contenente i certificati validi è la /etc/ssl/certs.
Per fare questo basta aggiungere la direttiva
# TLS TLS_CACERTDIR /etc/ssl/certs
In aggiunta se non si vuole installare il certificato tramite il comando "dpkg-reconfigure ca-certificates", possiamo impostare la direttiva TLS_REQCERT ad allow, in modo tale da permettere lo stesso la connessione al nostro client, ma diminuendo così la sicurezza della nostra infrastruttura perchè anche a fronte di un certificato server non valido il nostro client invece che interrompere la connessione continuerà la sessione ignorando il certificato non trusted. Se desiderate effettuare una connessione del genere immettere la direttiva:
TLS_REQCERT allow
Verifica della connessione
Non ci resta che provare a collegarci in TLS e verificare che tutto funzioni per il meglio.
Avvio di slapd
Prima di collegarci al nostro demone dobbiamo dirgli di porsi in ascolto anche sulla porta TCP 636 per le sessioni LDAP Over SSL-TLS, e per fare questo basterà passare il parametro "-h" all'avvio del demone.
$ sudo /usr/local/libexec/slapd \ -f /usr/local/etc/openldap/slapd.conf \ -h "ldap:/// ldaps:///"
Connessione con StartTLS
Proviamo ad avviare una sessione StartTLS con l'applicativo ldapsearch
$ ldapsearch -x -w passwordSegreta \ -D 'cn=Admin,dc=example,dc=com' \ -H ldap://example.com '(uid=amedeo)' -ZZ
Dove otterremo l'output seguente
# extended LDIF # # LDAPv3 # base <dc=example,dc=com> (default) with scope subtree # filter: (uid=amedeo) # requesting: ALL # # amedeo, people, example.com dn: uid=amedeo,ou=people,dc=example,dc=com uid: amedeo ou: people sn: Amedeo cn: Amedeo Salvati displayName: Amedeo Salvati mail: amedeo@example.com userPassword:: cGFzc3dvcmQ= objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson # search result search: 3 result: 0 Success # numResponses: 2 # numEntries: 1
Mentre se invece avviamo cerchiamo di effettuare la stessa operazione senza lo StartTLS, ovvero omettendo i parametri -ZZ, otterremo il seguente errore
ldap_bind: Confidentiality required (13)
additional info: confidentiality required
Questo perchè abbiamo immesso la direttiva security ssf=128
Connessione in SSL-TLS
Se vogliamo collegarci direttamente in SSL-TLS basterà puntare verso la porta TCP 636
$ ldapsearch -x -w passwordSegreta \
-D 'cn=Admin,dc=example,dc=com' \
-H ldaps://example.com '(uid=amedeo)'
