Ajouter un certificat pour les connexions SSL Java

Symptôme

Dans le cas par exemple d’une connexion en LDAPS (LDAP via SSL) on a de bonne chance de se prendre ce genre d’erreur :

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
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:150)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1584)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:174)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:168)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:848)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:106)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
    ...

Note que c’est la même pour les accès à des Web-Service en HTTPS via Axis

Explication

Cette erreur vient du fait que le client n’accepte pas le certificat du serveur. Les histoires des certificats sont manifestement un poil compliqué mais bon, grosso modo, il faut ajouter le certif du serveur à la politique sécurité du client.

Sachant qu’on parle du JRE utilisé par le serveur JBoss !

Solution 1

Solution “manuelle”, testé chez La Poste et GMC. Les exemples donner sont sous Linux mais ça fonctionne de la même façon sous Windows (j’ai testé). La commande keytool est dans les binaire de java. Sous Windows elle est peut-être pas dans le classpath.

En tant que ‘‘root’’, exécuter la commande :

keytool -importcert -keystore "/usr/lib/jvm/java-6-sun/jre/lib/security/jssecacerts" -trustcacerts -alias "nom.dusitequipublielecertif.fr" -file mon-certificat.cer

Attention le chemin de le JRE est pas toujours le même ! Sous linux pour le connaître facilement taper:

update-alternatives --list java

C’est évident mais on sait jamais, s’il y a plusieurs JRE sur le serveur, il faut exécuter sur celle qu’utilise JBoss !!

La commande keytool devrait donner un truc du genre, le mot de passe est changeit

Tapez le mot de passe du Keystore :  
Ressaisissez le nouveau mot de passe : 
Propriétaire : CN=A10.blabla.test, L=PARIS, C=FR
Émetteur : CN=A10.blabla.test, L=PARIS, C=FR
Numéro de série : 9397247ec5cf9e4f
Valide du : Tue Jul 27 01:23:59 CEST 2010 au : Thu Jul 26 01:23:59 CEST 2012
Empreintes du certificat :
	 MD5 :  27:73:2E:FF:8F:AB:3A:2D:1F:47:42:A5:97:49:CF:74
	 SHA1 : 31:83:A1:FB:AE:69:91:F3:14:BF:5C:A8:67:2A:FD:CA:83:A6:5B:9A
	 Nom de l'algorithme de signature : MD5withRSA
	 Version : 4
Faire confiance à ce certificat ? [non] :  oui
Certificat ajouté au Keystore

Après les appels https sur le serveur dont vous venez d’enregistrer le certificat devrait passer tout seul :p

Solution 2

Donc le truc à faire c’est d’aller récupérer la classe InstallCert.java de la compiler puis de l’exécuter avec en paramètre le serveur que vous voulez accéder en SSL :

javac -g InstallCert.java
java InstallCert your-ldap-server.somewhere.edu:636
cp jssecacerts $JAVA_HOME/lib/security

En gros, on compile et on execute. Ca va créer un ~KeyStore dans “jssecacerts” et y placer le certificat de votre serveur. Après, pour que le client appelé depuis Cameleon soit capable de retrouver ce certificat, il faut le placer dans le ~KeyStore par défaut de la JRE utilisé par le serveur Cameleon.

Je vous invite vivement à vérifier le ~JAVA_HOME dans le .bat ou .sh de lancement de JBoss. Une fois que vous êtes sur du JAVA_HOME, le ~KeyStore par défaut est dans ~JAVA_HOME/lib/security. Vous y recopiez le contenu de “jssecacerts”.

On redémarre le JBoss et hop ça fonctionne normalement !

Liens

Par ordre d’intérêt :