Importing SSL certificates on the Java Keystore (JKS)


The mechanism usually adopted for the protection of end-to-end data on the Internet is based on the use of Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), both of which are cryptographic protocols that allow communication safer and integrity of data over TCP/IP, encrypt the communication from the source to the destination transport layer.

A typical TLS/SSL (for example via internet browser) provides an authentication type called unilateral: only the server is authenticated (the client knows the identity of the server), but not vice versa (the client remains anonymous and authenticated). The client (Web browser, EmailUI, Java Client, etc …) validates the server certificate by checking the digital signature of server certificates, verifying that it is valid and recognized by a known Certificate Authority using a public key encryption.

 Figure 1 illustrates the case where the browser establishes a connection to a website (or web application) that exposes a certificate from a Certificate Authority not recognized. The user can take certain actions, whether to continue or abandon the connection, it is also possible for the user, consider instructing your browser to trust the certificate.

Figura 1 - Alert del Browser per Certificate Authority non riconosciuta

Figure 1 - Alert of the Browser for Certificate Authority not recognized

Figure 2 shows the details are on the chain of certification (Certificate Chain). The browser (in this case Safari) has all the reasons to issue a warning, in effect, the Certificate Authority (CA) has indicated a pure invention.

Figura 2 - Dettagli del certificato SSL

Figure 2 - Detail of the SSL Certificate

If you’d like to make TLS/SSL connections using software written in Java (as a client), you must ensure that all Certificate Chain (or certificate chain) is satisfied or at least should have to trust the certificate . The Java platform uses a system called Java Keystore for the management of security or rather, storage and administration of all that revolves around digital certificates (Public/Private Key, Root CA, CSR, etc …). The default implementation is based on the Java Keystore file, it is a proprietary format called JKS. For those wishing to know more about security in Java, I recommend reading JDK 6 Security-related APIs & Developer Guides.

The Java platform provides two basic types of Java Keystore that I prefer to divide as follows:

  • Server side: Java Keystore that usually contains the pairs of public/private key certificates used by the server. The name is usually attributed to this repository keystore;
  • Client side: Java keystore containing the certificates that are used only by applications that act as a client. The name usually given to this repository and trustStore.

The default location of both the keystore is <java-home>/lib/security/. For simplicity, during the course of the article I will refer generically to keystore name.

The classic mistake that we encounter when the Certificate Chain is not met, is an exception of the type shown below. The exception is triggered because it was not found a valid Certification Path to the SSL connection request executed.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

Come on now in practice and see how to deal with a similar scenario taking as an example a recent article posted on my blog, which showed how to implement a SOAP Java client for SugarCRM system. Examples of connection (see article) to a SOAP service using the HTTP protocol. If we did use the HTTPS protocol to connect to a SOAP service, we would go meet the exception shown above. The solution is very simple, you must import the SSL certificate on your Java Keystore and mark it as trusted. The operation consists of the following elementary steps:

  1. Export/Save the server certificate in format DER (Distinguished Encoding Rules) or X.509 on your machine that will perform the SSL connection;
  2. Importing the server certificate on the Java Keystore.

Export the server certificate can be accomplished in several ways, perhaps the easiest way is through a common browser (Firefox, Internet Explore, Safari, etc …). Publishing the post that explains how to do this with Mozilla Firefox: Exporting to File Server Certificate in Firefox 3. Similarly, you can proceed to export the server certificate using the most common browser.

The method that I prefer to export the server certificate in DER format is to use the openssl tool (see command below).

echo |\
openssl s_client -connect sugarcrm-fe-1.local:443 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | \
openssl x509 -outform der -out /tmp/sugarcrm-fe-1.local.der

Once you have the server certificate, you must import it on the Java Keystore using the appropriate tool named keytool (keytool-Key and Certificate Management Tool). I remember that the keystore is the container of digital certificates. The scenario proposed here is based, custom keystore to a file, created from importing the server certificate, we leave intact the system keystore.

keytool -import -keystore /Users/amusarra/.mykeystore \
-alias sugarcrm-fe-1 -v -file Desktop/sugarcrm-fe-1.local

The command shown above, will create a new keystore (password protected) within the server certificate will be identified with the alias sugarcrm-fe-1. The alias uniquely identifies the item just inserted, if we wanted to do a check on the success of the operation of the import, just run the following command:

keytool -list -keystore /Users/amusarra/.mykeystore \
-v -alias sugarcrm-fe-1

The output of above command will look like as shown below:

Alias name: sugarcrm-fe-1
Creation date: May 2, 2011
Entry type: trustedCertEntry

Owner: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local,
OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
Serial number: 1
Valid from: Thu Apr 28 02:18:12 CEST 2011 until: Sun Apr 25 02:18:12 CEST 2021
Certificate fingerprints:
     MD5:  CC:4A:D4:6E:DC:01:60:1D:79:FA:CD:8A:46:5F:CC:48
     SHA1: A5:44:B9:C7:0A:41:0C:92:46:C6:9D:6D:77:0B:89:35:ED:E9:1C:AD
     Signature algorithm name: SHA1withRSA
     Version: 1

In the event that the server certificate was not imported successfully, the previous command would respond with the following exception:

keytool error:
java.lang.Exception: Alias <sugarcrm-fe> does not exist
java.lang.Exception: Alias <sugarcrm-fe> does not exist
    at sun.security.tools.KeyTool.doPrintEntry(KeyTool.java:1339)
    at sun.security.tools.KeyTool.doCommands(KeyTool.java:869)
    at sun.security.tools.KeyTool.run(KeyTool.java:172)
    at sun.security.tools.KeyTool.main(KeyTool.java:166)

At this point everything is ready to perform successfully connect to the service SOAP over HTTPS. Because we used a custom keystore instead of exploiting the system, you must instruct the JVM about the keystore to be used, not even a bad idea to set a debug level over the SSL connection. The two arguments that must be passed to the JVM are therefore:

-Djavax.net.debug=ssl
-Djavax.net.ssl.trustStore=/Users/amusarra/.mykeystore

As the Java application acts as a client, you must specify the location of the keystore (remember to be kind trustStore) through the property java.net.ssl.trustStore.

The debug option can help you understand any problems in case of failure, it is useful for those who want to better understand the operation of the TLS / SSL, it draws all the messages exchanged between the client and the server to complete the handshake. Followed by an extract of the output against the execution of the class SugarCRMSoapClient.java but change the endpoint address at https://sugarcrm-fe-1.local/crm-6.1/service/v2/soap.php?wsdl

Through a practical example and I would also realistic enough, we saw how simple and immediate import digital certificates in the Java Keystore, so that applications work correctly.

I think this is my third article created to respond to questions or problems raised by my colleagues!

keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: /Users/amusarra/.mykeystore
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: EMAILADDRESS=info@sugarcrm-fe-1.local,
CN=sugarcrm-fe-1.local, OU=Research Development,
O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Issuer:  EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Algorithm: RSA; Serial number: 0x1
  Valid from Thu Apr 28 02:18:12 CEST 2011 until Sun Apr 25 02:18:12 CEST 2021

trigger seeding of SecureRandom
done seeding SecureRandom
*** ClientHello, TLSv1
RandomCookie:  GMT: 1287446936 bytes = { 34, 19, 132, 181, 138, 114, 13,
67, 100, 111, 100, 155, 35, 132, 108, 102, 110, 106, 128, 57, 200, 147,
175, 25, 246, 233, 34, 252 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA,
SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA,
SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
***
Thread-2, WRITE: TLSv1 Handshake, length = 81
Thread-2, WRITE: SSLv2 client hello message, length = 110
Thread-2, READ: TLSv1 Handshake, length = 81
*** ServerHello, TLSv1
RandomCookie:  GMT: 1287126586 bytes = { 72, 54, 32, 71, 9, 157, 75, 184,
3, 159, 95, 8, 18, 248, 108, 249, 179, 60, 205, 184, 204, 135, 186, 220,
27, 85, 249, 234 }
Session ID:  {116, 147, 251, 240, 232, 125, 76, 210, 112, 151, 13,
181, 7, 214, 55, 176, 224, 217, 109, 201, 161, 74, 143, 121, 131,
243, 108, 67, 131, 234, 146, 232}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
Thread-2, READ: TLSv1 Handshake, length = 1484
*** Certificate chain
chain [0] = [
[
  Version: V1
  Subject: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local,
OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 4096 bits
  modulus: 8027142309184580181165847677029426633214754078003759815426876
85293215600656132119778686073861448440626986882469379232984072851534463520
18325441288568133145387170109806353233631082021605339971510561262203242740
78307947239417239633029107273682201967984685272509448411609722527933446350
55918234578745856629515337728940982589703027293942988170613441271688911660
69762683263953403322683456690226470741799474704382776226873825494609402390
72693542287588215034771548006899103813169868373935038762384493733844944158
52659434703986779316888612522163711433463948775434712084653698002329763637
  public exponent: 65537
  Validity: [From: Thu Apr 28 02:18:12 CEST 2011,
               To: Sun Apr 25 02:18:12 CEST 2021]
  Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  SerialNumber: [    01]

]

Importazione Certificati SSL sul Java Keystore (JKS)


Il meccanismo solitamente adottato per la protezione dei dati End-To-End sulla rete internet è basato sull’utilizzo del protocollo Transport Layer Security (TLS) e il suo predecessore Secure Sockets Layer (SSL), entrambi sono dei protocolli crittografici che permettono una comunicazione sicura e una integrità dei dati su reti TCP/IP, cifrano la comunicazione dalla sorgente alla destinazione sul livello di trasporto.

Una tipica connessione TLS/SSL (per esempio via browser internet) prevede un tipo di autenticazione denominata unilaterale : solo il server è autenticato (il client conosce l’identità del server), ma non vice-versa (il client rimane anonimo e non autenticato). Il client (browser web, EmailUI, Java Client, etc…) valida il certificato del server controllando la firma digitale dei certificati del server, verificando che questa sia valida e riconosciuta da una Certificate Authority conosciuta utilizzando una cifratura a chiave pubblica.

In Figura 1 è illustrato il caso in cui il browser stabilisce una connessione verso un sito web (o applicazione web) che espone un certificato rilasciato da una Certificate Authority non riconosciuta. E’ lasciata all’utente l’azione da intraprendere, se continuare o abbandonare la connessione, è inoltre possibile per l’utente, istruire il browser affinché consideri trusty (fidato) il certificato.

Figura 1 - Alert del Browser per Certificate Authority non riconosciuta

Figura 1 - Alert del Browser per Certificate Authority non riconosciuta

In Figura 2 sono invece illustrati i dettagli sulla catena di certificazione (Certificate Chain). Il browser (in questo caso Safari) ha tutte la ragioni a emettere un warning, in effetti, la CA (Certificate Authority)  indicata è di pura invenzione.

Figura 2 - Dettagli del certificato SSL

Figura 2 - Dettagli del certificato SSL

Nel caso in cui volessimo compiere connessioni TLS/SSL attraverso un software scritto in Java (in qualità di client), è necessario accertarsi che tutta la Certificate Chain (o catena di certificazione) sia soddisfatta o comunque bisogna far in modo da considerare affidabile il certificato. La piattaforma Java utilizza un sistema denominato Java Keystore per la gestione della sicurezza o meglio, per lo storage e amministrazione di tutto ciò che ruota intorno ai certificati digitali (Public/Private Key, Root CA, CSR, etc…). L’implementazione di default del Java Keystore è basata su file, quest’ultimo è in un formato proprietario denominato JKS. Per coloro che volessero approfondire l’argomento sicurezza in Java, consiglio la lettura di JDK 6 Security-related APIs & Developer Guides.

La piattaforma Java prevede due tipi di Java Keystore che preferisco suddividere nel seguente modo:

  • Server side: Java Keystore che contiene solitamente le coppie di chiavi pubbliche/private dei certificati utilizzati dall’applicazione server. Il nome solitamente attribuito a questo repository è keystore;
  • Client side: Java Keystore che contiene i soli certificati utilizzati dalle applicazioni che agiscono come client. Il nome solitamente attribuito a questo repository è trustStore.

La locazione predefinita di entrambi i keystore è <java-home>/lib/security/. Per ragioni di semplicità, durante il corso dell’articolo farò riferimento in modo generico al nome keystore.

Il classico errore cui si va incontro quando la Certificate Chain non è soddisfatta, è un eccezione del tipo indicato di seguito. L’eccezione è scatena perché non è stata trovata una Certification Path valida per la richiesta di connessione SSL eseguita.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

Andiamo subito nel pratico e vediamo come affrontare uno scenario simile prendendo come esempio un recente articolo pubblicato sul mio blog, che mostrava come realizzare un client Java SOAP per il sistema di CRM SugarCRM. Gli esempi di connessione (mostrati nell’articolo) al servizio SOAP utilizzano il protocollo HTTP. Qualora facessimo uso del protocollo HTTPS per la connessione al servizio SOAP, andremmo incontro all’eccezione mostrata in precedenza. La soluzione al problema è molto semplice, occorre importare il certificato SSL sul proprio Java Keystore e segnarlo come affidabile. L’operazione è composta dai seguenti passi elementari:

  1. Esportazione/Salvataggio del certificato server in formato DER (Distinguished Encoding Rules) X.509 sulla propria macchina o su quella che eseguirà la connessione SSL;
  2. Importazione del certificato server sul Java Keystore.

L’esportazione del certificato server può essere eseguita in svariati modi, forse la via più semplice è attraverso un comune browser (Firefox, Internet Explore, Safari, etc…). Riporto il post che spiega come eseguire l’operazione con Mozilla Firefox: Exporting Server Certificate to File in Firefox 3. In modo analogo è possibile procedere con l’esportazione del certificato server utilizzando i più comuni browser.

Il metodo da me preferito per esportare il certificato server in formato DER è l’utilizzo del tool openssl. E’ più che sufficiente una sola linea di comando, per motivi di leggibilità, riporto il comando suddiviso in 4 linee:

echo |\
openssl s_client -connect sugarcrm-fe-1.local:443 2>&1 |\
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | \
openssl x509 -outform der -out /tmp/sugarcrm-fe-1.local.der

Una volta ottenuto il certificato server, occorre importare quest’ultimo sul Java Keystore utilizzando l’apposito tool che prende il nome di keytool (keytool-Key and Certificate Management Tool). Ricordo che il keystore è il contenitore dei certificati digitali. Ognuno di voi potrebbe avere le configurazioni più disparate riguardo il Java Keystore, lo scenario qui proposto è quello base, keystore su file e su file custom, ovvero, creato dall’importazione del certificato server, lasciamo intatto il keystore di sistema.

keytool -import -keystore /Users/amusarra/.mykeystore \
-alias sugarcrm-fe-1 -v -file Desktop/sugarcrm-fe-1.local

Il comando sopra illustrato, creerà un nuovo keystore (protetto da password) all’interno del quale finirà il certificato server identificato con l’alias sugarcrm-fe-1. L’alias identifica in modo univoco l’item appena inserito, se volessimo fare un controllo sul buon esito dell’operazione dell’import, è sufficiente eseguire il seguente comando:

keytool -list -keystore /Users/amusarra/.mykeystore \
-v -alias sugarcrm-fe-1

L’output del precedente comando sarà simile a quanto illustrato a seguire:

Alias name: sugarcrm-fe-1
Creation date: May 2, 2011
Entry type: trustedCertEntry

Owner: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local,
OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
Serial number: 1
Valid from: Thu Apr 28 02:18:12 CEST 2011 until: Sun Apr 25 02:18:12 CEST 2021
Certificate fingerprints:
     MD5:  CC:4A:D4:6E:DC:01:60:1D:79:FA:CD:8A:46:5F:CC:48
     SHA1: A5:44:B9:C7:0A:41:0C:92:46:C6:9D:6D:77:0B:89:35:ED:E9:1C:AD
     Signature algorithm name: SHA1withRSA
     Version: 1

Nel caso in cui il certificato server non fosse stato importato con successo, il precedente comando avrebbe risposto con la seguente eccezione:

keytool error:
java.lang.Exception: Alias <sugarcrm-fe> does not exist
java.lang.Exception: Alias <sugarcrm-fe> does not exist
    at sun.security.tools.KeyTool.doPrintEntry(KeyTool.java:1339)
    at sun.security.tools.KeyTool.doCommands(KeyTool.java:869)
    at sun.security.tools.KeyTool.run(KeyTool.java:172)
    at sun.security.tools.KeyTool.main(KeyTool.java:166)

A questo punto tutto è pronto per poter eseguire con successo la connessione al servizio SOAP over HTTPS. Poiché abbiamo utilizzato un keystore custom invece di sfruttare quello di sistema, è necessario istruire la JVM circa il keystore da utilizzare, non sarebbe neppure una cattiva idea quella d’impostare un livello di debug sulla sola connessione SSL. I due argomenti che devono essere passati alla JVM sono quindi:

-Djavax.net.debug=ssl
-Djavax.net.ssl.trustStore=/Users/amusarra/.mykeystore

Dato che l’applicazione Java agisce in qualità di client, occorre specificare la locazione del keystore (che ricordo essere di tipo trustStore) attraverso la proprietà java.net.ssl.trustStore.

L’opzione di debug può aiutare a capire eventuali problemi in caso di malfunzionamento, è comuque utile per coloro che vogliono capire meglio il funzionamento del protocollo TLS/SSL, vengono tracciati tutti i messaggi scambiati tra il client ed il server per portare a termine la fase di handshake. A seguire un estratto dell’output a fronte dell’esecuzione della classe SugarCRMSoapClient.java, cambiando però l’indirizzo dell’endpoint in https://sugarcrm-fe-1.local/crm-6.1/service/v2/soap.php?wsdl

Attraverso un esempio pratico e direi pure abbastanza realistico, abbiamo visto come sia semplice e immediato importare certificati digitali sul Java Keystore affinché le applicazioni SSL funzionino in maniera corretta.

Credo che questo sia il mio terzo articolo nato per rispondere alle domande e/o problemi posti da miei colleghi!!!

keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: /Users/amusarra/.mykeystore
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
  Subject: EMAILADDRESS=info@sugarcrm-fe-1.local,
CN=sugarcrm-fe-1.local, OU=Research Development,
O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Issuer:  EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Algorithm: RSA; Serial number: 0x1
  Valid from Thu Apr 28 02:18:12 CEST 2011 until Sun Apr 25 02:18:12 CEST 2021

trigger seeding of SecureRandom
done seeding SecureRandom
*** ClientHello, TLSv1
RandomCookie:  GMT: 1287446936 bytes = { 34, 19, 132, 181, 138, 114, 13,
67, 100, 111, 100, 155, 35, 132, 108, 102, 110, 106, 128, 57, 200, 147,
175, 25, 246, 233, 34, 252 }
Session ID:  {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA,
SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA,
SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods:  { 0 }
***
Thread-2, WRITE: TLSv1 Handshake, length = 81
Thread-2, WRITE: SSLv2 client hello message, length = 110
Thread-2, READ: TLSv1 Handshake, length = 81
*** ServerHello, TLSv1
RandomCookie:  GMT: 1287126586 bytes = { 72, 54, 32, 71, 9, 157, 75, 184,
3, 159, 95, 8, 18, 248, 108, 249, 179, 60, 205, 184, 204, 135, 186, 220,
27, 85, 249, 234 }
Session ID:  {116, 147, 251, 240, 232, 125, 76, 210, 112, 151, 13,
181, 7, 214, 55, 176, 224, 217, 109, 201, 161, 74, 143, 121, 131,
243, 108, 67, 131, 234, 146, 232}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
%% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
Thread-2, READ: TLSv1 Handshake, length = 1484
*** Certificate chain
chain [0] = [
[
  Version: V1
  Subject: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local,
OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5

  Key:  Sun RSA public key, 4096 bits
  modulus: 8027142309184580181165847677029426633214754078003759815426876
85293215600656132119778686073861448440626986882469379232984072851534463520
18325441288568133145387170109806353233631082021605339971510561262203242740
78307947239417239633029107273682201967984685272509448411609722527933446350
55918234578745856629515337728940982589703027293942988170613441271688911660
69762683263953403322683456690226470741799474704382776226873825494609402390
72693542287588215034771548006899103813169868373935038762384493733844944158
52659434703986779316888612522163711433463948775434712084653698002329763637
  public exponent: 65537
  Validity: [From: Thu Apr 28 02:18:12 CEST 2011,
               To: Sun Apr 25 02:18:12 CEST 2021]
  Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com,
OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT
  SerialNumber: [    01]

]

Google Mail POP3 SSL con Fetchmail


Nel corso di quest’articolo vedremo come sia possibile in maniera semplice e veloce riuscire a compiere il download delle email da un account GMail. Il client di posta che utilizzeremo per il download delle nostre email sarà Fetchmail (BerliOS, 2010).

Il servizio di posta elettronica di Google offre diversi modi di accesso alla propria casella, oltre alla consueta Web Mail. Il servizio GMail, ha ben cinque altri metodi di accesso:

  • POP3 (Internet Engineering Task Force – IETF, 1996)
  • IMAP4 (Internet Engineering Task Force – IETF, 2003)
  • Notifier (Google, 2010)
  • Google Apps Sync for Microsoft Outlook® (Google, 2010)

Il metodo di accesso preso in considerazione per lo scopo di quest’articolo è il primo, frutteremo quindi il protocollo POP3. GMail supporta unicamente una connessione protetta SSL (Wikipedia, 2010).

Requisiti

  • Sistema Operativo della famiglia Unix/Linux/BSD
  • Il proprio account GMail deve essere configurato per consentire l’accesso alla casella attraverso il protocollo POP3. E’ possibile verificare le impostazioni del POP3 attraverso il panello: Impostazioni -> Inoltro e POP/IMAP (vedi Figure 1).
  • OpenSSL Toolkit (OpenSSL Project, 1998)
  • Fetchmail con il supporto SSL. Per essere sicuri del supporto SSL da parte di fetchmail è possibile eseguire il comando illustrato al Listing 1.
Impostazioni GMail Account

Figure 1 Impostazioni protocollo POP3 per l’account GMail

$ ldd /usr/bin/fetchmail
linux-gate.so.1 =>  (0x00202000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0x00ded000)
libkrb4.so.2 => /usr/lib/libkrb4.so.2 (0x00b99000)
libdes425.so.3 => /usr/lib/libdes425.so.3 (0x00bb8000)
libssl.so.6 => /lib/libssl.so.6 (0x00714000)

libcrypto.so.6 => /lib/libcrypto.so.6 (0x0028c000)
libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00698000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00c02000)
/lib/ld-linux.so.2 (0x00a33000)
libsepol.so.1 => /lib/libsepol.so.1 (0x00c1c000)
… 

$ otool -L /usr/bin/fetchmail
/usr/bin/fetchmail:
/usr/lib/libresolv.9.dylib (current version 38.0.0)
/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos
/usr/lib/libssl.0.9.8.dylib (current version 0.9.8)

/usr/lib/libcrypto.0.9.8.dylib (current version 0.9.8)
/usr/lib/libSystem.B.dylib (current version 125.0.0

Listing 1 Verifica del supporto SSL di fetchmail

Nel listing precedente ho evidenziato gli item che dovreste vedere qualora il supporto SSL per fetchmail sia disponibile. Per la stesura dell’articolo ho utilizzato il mio fidato Mac Book Pro, ecco il motivo per cui compare anche il comando otool, l’equivalente del comando ldd di Unix/Linux.

Recupero dei certificati

Il prossimo passo richiede il recupero dei certificati utilizzati da GMail, per questo compito utilizzeremo OpenSSL Toolkit. Generalmente i sistemi Unix dedicano una determina locazione del file system come repository dei certificati, solitamente /usr/share/ssl/certs/.

Per lo scopo dell’articolo ho deciso d’usare come repository dei certificati la directory certs collocata all’interno della propria home directory, quindi: ~/.certs.

Provando a eseguire una connessione a GMail prima del recupero dei certificati, si otterrà un errore di verifica del certificato (vedi Listing 2). Nel listato è evidenziato l’errore sul lookup del certificato, oltre ad essere evidenziata la cosiddetta Certificate chain, in altre parole, la catena di certificazione.

Sempre utilizzando OpenSSL, procediamo con il recupero dei certificati SSL in formato PEM (Privacy Enhanced Mail Certificate) (Wikipedia, 2010). I certificati da recuperare sono quelli che fanno parte della Certificate chain. Il primo della lista è il certificato della Root Certificate Authority (Wikipedia, 2009).

  • /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
  • /C=US/O=Google Inc/CN=Google Internet Authority
  • /C=US/ST=California/L=Mountain View/O=Google Inc/CN=pop.gmail.com
$ openssl s_client -connect pop.gmail.com:995 

depth=1 /C=US/O=Google Inc/CN=Google Internet Authority
verify error:num=20:unable to get local issuer certificate

verify return:0

Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=pop.gmail.com
i:/C=US/O=Google Inc/CN=Google Internet Authority
1 s:/C=US/O=Google Inc/CN=Google Internet Authority
i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

Listing 2 Connessione a GMail via POP3 utilizzando OpenSSL

Procedendo con ordine, iniziamo con il download del Root Certificate direttamente dal sito di GeoTrust collocandolo in ~/.certs/. Ricordo che il formato del certificato è PEM (Base-64 encoded DER X.509).

$ curl -o ~/.certs/Equifax_Secure_Certificate_Authority.pem http://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Certificate_Authority.cer

Listing 3 Download di Equifax Secure Certificate Authority via curl.

Dopo aver ottenuto il certificato potremmo toglierci lo sfizio d’effettuare delle verifiche e accertare che le informazioni estratte siano conformi con quanto dichiarato sul sito di GeoTrust (http://www.geotrust.com/resources/root-certificates/).

Per l’operazione di verifica sul certificato è sempre possibile utilizzare i comandi OpenSSL (vedi Listing 4 e Figure 2).

$ openssl x509 -in .certs/Equifax_Secure_Certificate_Authority.pem -fingerprint -subject -issuer -serial -hash –noout 

SHA1Fingerprint=D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A
subject= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
issuer= /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
serial=35DEF4CF
594f1775

Listing 4 Verifica di alcune informazioni sul Root Certificate Authority.

GeoTrust Root Certificate

Figure 2 GeoTrust Root Certificates Page.

A questo punto non resta che ottenere i rimanenti due certificati (sempre in formato PEM), entrambi di proprietà di Google. Procediamo con il salvataggio dei certificati in ~/.certs, sempre utilizzando i comandi OpenSSL con l’aiuto di sed.

$ echo |\
openssl s_client -connect pop.gmail.com:995 -showcerts 2>&1 |\
sed -ne ‘/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p’

Listing 5 Comando per il retrieve dei certificati Google.

I certificati (visibili nel Listing 6) sono stati estratti secondo l’ordine dettato dalla Certificate chain:

  • /C=US/ST=California/L=Mountain View/O=Google Inc/CN=pop.gmail.com
  • /C=US/O=Google Inc/CN=Google Internet Authority

Salviamo i due certificati in ~/.certs/ chiamandoli rispettivamente:

  • pop.gmail.com.pem
  • GoogleInternetAuthority.pem

Ricordo che i certificati devono essere salvati comprendendo le intestazioni d’inizio e fine certificato.

Adesso che abbiamo tutti i certificati memorizzati nella directory ~/.certs, abbiamo solo bisogno di un “rimaneggiamento” in modo che OpenSSL e fetchmail siano in grado di leggerli e utilizzarli.

—–BEGIN CERTIFICATE—– 

MIIDWjCCAsOgAwIBAgIKFNMahgADAAASkDANBgkqhkiG9w0BAQUFADBGMQswCQYD
VQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZR29vZ2xlIElu
dGVybmV0IEF1dGhvcml0eTAeFw0xMDA0MjIyMDExMjNaFw0xMTA0MjIyMDIxMjNa
MGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1N
b3VudGFpbiBWaWV3MRMwEQYDVQQKEwpHb29nbGUgSW5jMRYwFAYDVQQDEw1wb3Au
Z21haWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC701lFBdiiC0BB
JEo2U1wmmS6Gv+qr4bjG6xeCSgb0UGI2vN1ifYyrf/wj1jBLupou+Ds+s0zLzE5Y
vsADQvu+pkDXoOcnK2YxiOiuZaGOSRKC2b0rbg4oYyS1TogEBcX+KpUxWQNpccW6
FPzpSVtmiG4azMUIR0mM2HERnwke/wIDAQABo4IBLDCCASgwHQYDVR0OBBYEFJr4/CBophXvQNM/AFWw8zu5EXKiMB8GA1UdIwQYMBaAFL/AMOv1QxE+Z7qekfv8atrj
axIkMFsGA1UdHwRUMFIwUKBOoEyGSmh0dHA6Ly93d3cuZ3N0YXRpYy5jb20vR29v
Z2xlSW50ZXJuZXRBdXRob3JpdHkvR29vZ2xlSW50ZXJuZXRBdXRob3JpdHkuY3Js
MGYGCCsGAQUFBwEBBFowWDBWBggrBgEFBQcwAoZKaHR0cDovL3d3dy5nc3RhdGlj
LmNvbS9Hb29nbGVJbnRlcm5ldEF1dGhvcml0eS9Hb29nbGVJbnRlcm5ldEF1dGhv
cml0eS5jcnQwIQYJKwYBBAGCNxQCBBQeEgBXAGUAYgBTAGUAcgB2AGUAcjANBgkq
hkiG9w0BAQUFAAOBgQDETrSXXdPv8yvPZ5cR8yupyXlHzUvA5rNVFzOmBE/QCrNx
wLHDMP36+axPMWp+uraNfsc798zHES0GDgz+P97KItu8T75ysvjUUpWKeeuHcYHh
QSGi5iYB7XxEB9oCnSC9tpq8el2/mWFvVJSO69bO+zDOqgFPJ/GZYIxWgglMqA==
—–END CERTIFICATE—–

—–BEGIN CERTIFICATE—–

MIICsDCCAhmgAwIBAgIDC2dxMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwNjA4MjA0MzI3WhcNMTMwNjA3MTk0MzI3
WjBGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZ
R29vZ2xlIEludGVybmV0IEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEAye23pIucV+eEPkB9hPSP0XFjU5nneXQUr0SZMyCSjXvlKAy6rWxJfoNf
NFlOCnowzdDXxFdF7dWq1nMmzq0yE7jXDx07393cCDaob1FEm8rWIFJztyaHNWrb
qeXUWaUr/GcZOfqTGBhs3t0lig4zFEfC7wFQeeT9adGnwKziV28CAwEAAaOBozCB
oDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFL/AMOv1QxE+Z7qekfv8atrjaxIk
MB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYB
Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v
Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde
BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN
0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml
UUIuOss4jHg7y/j7lYe8vJD5UDI=

—–END CERTIFICATE—–

Listing 6 Certificati ottenuti dal comando precedente.

$ c_rehash ~/.certs/Doing /Users/amusarra/.certs/ 

Equifax_Secure_Certificate_Authority.pem => 594f1775.0
GoogleInternetAuthority.pem => d9b7a851.0
pop.gmail.com.pem => 34ceaf75.0

Listing 7 Rehash dei certificati.

Test dei certificati

Prima di procedere con la configurazione di fetchmail, dobbiamo verificare che la connessione SSL verso GMail funzioni correttamente con i certificati a nostra disposizione. Sempre con OpenSSL facciamo una connessione verso il server pop.gmail.com utilizzando la porta TCP 995.

$ openssl s_client -connect pop.gmail.com:995 -CApath ~/.certs/ 

depth=2 /C=US/O=Equifax/OU=Equifax Secure Certificate Authority
verify return:1
depth=1 /C=US/O=Google Inc/CN=Google Internet Authority
verify return:1
depth=0 /C=US/ST=California/L=Mountain View/O=Google Inc/CN=pop.gmail.com
verify return:1

SSL-Session:
Protocol  : TLSv1
Cipher    : RC4-MD5
Session-ID: 660484ECDF89B1312C001861E83A4ABDF0F9559BA5EEABC334F74F6EC7E6EDF6
Start Time: 1292108636
Timeout   : 300 (sec)
Verify return code: 0 (ok)

+OK Gpop ready for requests from 217.201.92.244 rd13pf5325370bkb.24

Listing 8 Connessione al server POP3 di GMail.

Per ragioni di spazio ho omesso dal Listing 8 parecchi dati di output, la cosa importante da notare è il verify return code uguale a zero, possiamo quindi affermare che il test ha avuto esito positivo.

Configurazione di Fetchmail

Abbiamo bisogno di configurare il file ~/.fetchmailrc in modo da controllare automaticamente ogni 5 minuti se abbiamo posta, e se sì per scaricarla. Per la configurazione di fetchmail ho intenzione di usare il nome utente amusarra (locale sul mio sistema Mac OS X) e l’indirizzo GMail antonio.musarra@gmail.com.

# set username
set postmaster “amusarra”# set polling time (5 minutes)
set daemon 600 

poll pop.gmail.com with proto POP3 user ‘antonio.musarra@gmail.com’ there with password ‘secret’ is amusarra here options ssl sslcertck sslcertpath /Users/amusarra/.certs/

Listing 9 File di configurazione Fetchmail ~/.fetchmailrc

Ora possiamo fare una prova in modo verboso per vedere se tutto funziona per come ci aspettiamo. Le mail saranno scaricate nella propria casella di posta di sistema, la locazione della casella dipende dalla configurazione del vostro sistema (nel mio caso in /var/mail/amusarra).

$ fetchmail -d0 -vk pop.gmail.com 

fetchmail: 6.3.11 querying pop.gmail.com (protocol POP3) at Sun, 12 Dec 2010 00:30:53 +0100 (CET): poll started
Trying to connect to 74.125.43.109/995…connected.
fetchmail: Issuer Organization: Google Inc
fetchmail: Issuer CommonName: Google Internet Authority
fetchmail: Server CommonName: pop.gmail.com
fetchmail: pop.gmail.com key fingerprint: 6B:C4:63:05:87:1E:72:88:ED:81:C5:A2:51:6B:B7:B6

fetchmail: POP3< +OK Gpop ready for requests from 217.201.92.244 x19pf5342523bkc.15
fetchmail: POP3> CAPA
fetchmail: POP3< +OK Capability list follows
fetchmail: POP3< USER
fetchmail: POP3> USER antonio.musarra@gmail.com
fetchmail: POP3< +OK send PASS
fetchmail: POP3> PASS *
fetchmail: POP3< +OK Welcome.
fetchmail: POP3> STAT
fetchmail: POP3< +OK 0 0
fetchmail: No mail for antonio.musarra@gmail.com at pop.gmail.com
fetchmail: POP3> QUIT
fetchmail: POP3< +OK Farewell.
fetchmail: 6.3.11 querying pop.gmail.com (protocol POP3) at Sun, 12 Dec 2010 00:30:58 +0100 (CET): poll completed
fetchmail: normal termination, status 0

Listing 10 Output del comando fetchmail.

L’output del comando fetchmail dimostra la corretta configurazione di fetchmail, in particolare ho evidenziato la Certificate chain. Per questione di completezza, nel prossimo listing è mostrato un esempio di download e lettura di una mail dalla mia casella di posta.

$ fetchmail -d0 -vk pop.gmail.com 

fetchmail: POP3< .1 message for antonio.musarra@gmail.com at pop.gmail.com (22731 octets).
fetchmail: POP3> LIST 1
fetchmail: POP3< +OK 1 22731
fetchmail: POP3> RETR 1
fetchmail: POP3< +OK message follows
reading message antonio.musarra@gmail.com@gmail-pop.l.google.com:1 of 1 (22731 octets)
Trying to connect to 127.0.0.1/25…connected.
fetchmail: SMTP< 220 amusarra-mobile.local ESMTP Postfix
fetchmail: SMTP> EHLO amusarra-mobile.local
fetchmail: SMTP< 250-amusarra-mobile.local
fetchmail: SMTP> MAIL FROM:<prvs=954dcdfd4=Antonio.Musarra@altran.it> SIZE=22731
fetchmail: SMTP< 250 2.1.0 Ok
fetchmail: SMTP> RCPT TO:<amusarra@localhost>
fetchmail: SMTP< 250 2.1.5 Ok
fetchmail: SMTP> DATA
fetchmail: SMTP< 354 End data with <CR><LF>.<CR><LF>
fetchmail: SMTP>. (EOM)
fetchmail: SMTP< 250 2.0.0 Ok: queued as 886B86E1017
fetchmail: POP3> QUIT
fetchmail: POP3< +OK Farewell.
fetchmail: SMTP> QUIT
fetchmail: SMTP< 221 2.0.0 Bye
fetchmail: 6.3.11 querying pop.gmail.com (protocol POP3) at Sun, 12 Dec 2010 00:45:22 +0100 (CET): poll completed
fetchmail: normal termination, status 0

$ mail

Mail version 8.1 6/6/93.  Type ? for help.
“/var/mail/amusarra”: 1 message 1 new
>N  1 antonio.musarra@altr  Sun Dec 12 00:45 377/23230 “Test”
Message 1:
From prvs=954dcdfd4=Antonio.Musarra@altran.it  Sun Dec 12 00:45:21 2010
X-Original-To: amusarra@localhost
Delivered-To: amusarra@localhost.local
Delivered-To: antonio.musarra@gmail.com
From: Antonio Musarra <antonio.musarra@altran.it>
Content-Type: multipart/alternative; boundary=Apple Mail-11-271232042
Subject: Test
Date: Sun, 12 Dec 2010 00:44:04 +0100
To: Antonio Musarra <antonio.musarra@gmail.com>
Mime-Version: 1.0 (Apple Message framework v1082)
X-Mailer: Apple Mail (2.1082)
X-OriginalArrivalTime: 11 Dec 2010 23:44:15.0549 (UTC) FILETIME=[5201F6D0:01CB998D]

Listing 11 Download e lettura di una mail.

Works Cited

Wikipedia. (2010, December 2010). X.509. (Wikipedia, Produttore) Tratto da X.509: http://en.wikipedia.org/wiki/X.509

Wikipedia. (2009, October 8). Certificate Authority. (Wikipedia, Produttore) Tratto da Certificate Authority: http://en.wikipedia.org/wiki/Certificate_Authority

Wikipedia. (2010, December 6). Transport Layer Security. (Wikipedia, Produttore) Tratto da Transport Layer Security: http://en.wikipedia.org/wiki/Transport_Layer_Security

BerliOS. (2010, Oct 16). Fetchmail. (M. Andree, Produttore, & BerliOS) Tratto da Fetchmail: http://fetchmail.berlios.de/

Google. (2010). Che Cos’è Google Apps Sync ? (Google, Produttore, & Google) Tratto da Google: http://mail.google.com/support/bin/answer.py?hl=it&answer=153866

Google. (2010). Informazioni su GMail Notifier. (Google, Produttore, & Google) Tratto da http://mail.google.com/support/bin/answer.py?hl=it&answer=9429

Internet Engineering Task Force – IETF. (1996, May). RFC 1939 Post Office Protocol – Version 3. (J. Myers, C. Mellon, & M. Rose, Produttori) Tratto da IETF Tools: http://tools.ietf.org/html/rfc1939

Internet Engineering Task Force – IETF. (2003, March). RFC 3501 Internet Message Access Protocol – Version 4rev1. (M. Crispin, Produttore) Tratto da IETF Tools: http://tools.ietf.org/html/rfc3501

OpenSSL Project. (1998, December 23). OpenSSL Cryptography and SSL/TLS Toolkit. (M. J. Cox, R. S. Engelschall, S. Henson, B. Laurie, Produttori, & OpenSSL) Tratto da OpenSSL Cryptography and SSL/TLS Toolkit: http://www.openssl.org

Google Mail POP3 SSL con Fetchmail (versione PDF)


Nel corso di quest’articolo vedremo come sia possibile in maniera semplice e veloce riuscire a compiere il download delle email da un account GMail. Il client di posta che utilizzeremo per il download delle nostre email sarà Fetchmail (BerliOS, 2010).

E’ disponibile la versione italiana in formato PDF sul mio slideshare account: http://www.slideshare.net/amusarra/google-mail-pop3-ssl-con-fetchmail

Bye,
Antonio.