Pages

Friday, September 9, 2011

PKIX path building Faild for SSL in JBoss

Enabling SSL on JBoss. Using CA signed Certificate. PKIX path building Faild.

Exception at TCP connection sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Background Information:
  • I am using JBoss 4.2.2.GA server with SSL enabled. ( {jboss_server_path}\deploy\jboss-web.deployer\server.xml )
  <Connector port="28443" address="${jboss.bind.address}"   

   maxThreads="250" maxHttpHeaderSize="8192"

   emptySessionPath="true" protocol="HTTP/1.1"

   enableLookups="false" redirectPort="8443" acceptCount="100"

   connectionTimeout="20000" disableUploadTimeout="true"

   strategy="ms" scheme="https" secure="true"    

   clientAuth="false"

   SSLEnabled="true"

   keystoreFile="C:/Java/jboss-4.2.2.GA/server/{your_server_folder}/conf/server.keystore"

   keystorePass="your_password_here"        

   truststoreFile="C:/Java/jboss-4.2.2.GA/server/{your_server_folder}/conf/server.truststore"

   truststorePass="your_password_here"
   sslProtocol="TLS" />

  • I used the java keytool to generate the private keystore (server.keystore) and public truststore (server.truststore). 
  • I generated the CSR using java keytool and then supplied it to www.comodo.com to buy a SSL certificate (CA Signed Certificate)
  • On Comodo, I selected "Server Software" as "Tomcat". Because JBoss uses tomcat as the web container for SSL.
  • Received 5 files from Comodo (1 Domain crt, 3 intermediate certificates and 1 Root Certificate)
  • Imported them into my server.truststore successfully
  • Then I imported the CA certificates supplied by our host server that we are trying to connect to using our JBoss server.

Error Message:
When I started up my server, I got this error:

Exception at TCP connection sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I tried to find information on the Google. Did find a very good example as well which I will mention below. But this example was not directly relevant to my situation. SO, this is why I am writing this blog to help people who are stuck in same situation as mine. :)

Explanation Of why error happened and what it means?

What this error means is that the certificate received from host server (other server you are trying to connect to) during the SSL Handshake is not available or did not match to certificates in our Truststore (server.truststore). 

This error happens when we are doing the SSL handshake.
Simple, as JSSE does not have ability to handle popup messages and cannot interact automatically to accept the certificate, it throws this error by default. So, the certificate we received for doing the ssl handshake does not exist in our truststore or do not match to any one in our truststore.

How to fix this error?
Fixing this error is simple. Simply import the Certificate that is sent by the host server while connecting to it. Import this certificate to your truststore (server.truststore) file. Then restart the JBoss server again. This time it should pass the SSL Handshake.

You had already imported the certificates supplied by your host server (into your truststore) and still it threw the "PKIX path building failed" error?


Reason 1:

This means the certificate supplied by your host server to be imported in your trust store is different from what [certificate] they actually have in their truststore. Obviously, their actual certificate was not imported by us into our truststore. Therefore, failing on SSL handshake.


Reason 2:

Another reason for the failure could be that we are using CA signed certificates for our server identity. But (other party's) host server is using self signed certificate. 

Easiest way is that either both parties should have self-signed certificate for their ssl identification OR both parties should have CA signed certificates.


Important Tip:

Following communications can happen and setup is straight forward:

Client (With Self-signed certificate)  <-----------> Host Server (with Self-signed certificate)

Client (With Self-signed certificate)  <-----------> Host Server (with CA-signed certificate)

In this type of communication, you will use two files: server.keystore and server.truststore.



Special case:

Following communications CANNOT happen straightaway:

1) Client (With CA-signed certificate)  <-----------> Host Server (with CA-signed certificate)
Tomcat has a glitch in their code. So for this type of communication to happen, you need to use only one keystore file and you don't need truststore file as a separate file. Import all the CA certificates in  your server.keystore file. The order that you import is important as well.

To start with, your server.keystore will only have your private key. then import the other certificates in following order:
CA Root Certificate
CA Intermediate Certificate
Your Domain Certificate -- You should use same alias you had used for private certificate. This way a correct reply is stored in the certificate

Host Server's CA Root Certificate
Host Server's Intermediate Certificate
Host Server's Domain Certificate

2) Client (With CA-signed certificate)  <-----------> Host Server (with Self-signed certificate)

same as explained above. Only difference is that you will import only one self-signed certificate of Host server, into your server.keystore file.

  
Reason 3:


Check your Host Server's IP address again. If you are using INET then you may have your internal IP different than the Public IP. Same applies to the hosting server that you are trying to connect to. Make sure that the public certificate in your truststore belongs to the right server and you are connecting to the same server for which you have certificate in your truststore.

Reason 4:


May be you still have old ssl certificates of the host server in your system-wide keystore such as cacerts and/or jssecacerts. Usual location of these files : C:\Java\jdk6\jre-lib\security folder
So, please make sure that these cacerts and jssecacerts do NOT contain your host server's certificate. 
The host server's certificate should only be imported in your server.keystore or server.truststore files that you are using in your JBoss.


How to turn on the SSL debugging in JBoss?
You need to add this to your JAVA_OPTIONS in your JBoss run.bat. Or if you have a batch file that does environment before running the run.bat batch file then you can add this command to your this jboss startup batch file:

REM to turn ON the SSL debugging in JBoss
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

this will turn on the ssl debugging on ssl handshake process and will be verbose in which keymanager and trustmanager will be used.


if you want all debugging information on start up then you can use following command:
set JAVA_OPTS=%JAVA_OPTS% -Djavax.net.debug=all -Djava.security.debug=access:stack

The above commands will give you more information to fix the error.


The following is only for awareness.. if you use Jboss then you do NOT need to do any of the following:

Reference:
Very Useful blog by Leeland for this error: http://dreamingthings.blogspot.com/2006/12/no-more-unable-to-find-valid.html

In this blog, they are talking same error. But they are not using the JBoss server. They are using JSSE directly to connect to their host server. Therefore, they talk about importing the certificates in the JAVA_HOME\lib\security\cacerts using the InstallCert.java written by andreas.

However, their link to download the InstallCert.java is broken. You can easily find this java file somewhere else or download it from this blog of mine.

Steps to run the InstallCert.java
  1. Download the InstallCert.java from here
  2. Open a "command prompt" or "command console"
  3. In your command prompt, go to your "JAVA_HOME\lib\security\" folder
  4. Using Windows explorer, create this package in this folder mentioned in step 2: \com\aw\ad\util
  5. In your command prompt, go to this newly created package: "JAVA_HOME\lib\security\com\aw\ad\util"
  6. copy the downloaded file InstallCert.java here
  7. In your command prompt, compile this java file: javac InstallCert.java
  8. In your command prompt, now go up to the level: "JAVA_HOME\lib\security\"
  9.  run this command to execute the InstallCert program: java com.aw.ad.util.InstallCert {your_host_name}:{port} 
  10. you have to mention the full path [com.aw.ad.util] for running the InstallCert
  11. Then it will ask you if you wish to add the certificate to the cacaerts? type 1 at command prompt and press enter. 
  12. It will add the certificate to cacerts now, and will tell you how many certificates it imported.
Please correct me if I made any mistake in this blog. I hope this helps someone who is stuck with bloody painful ssl implementation in JBoss. :)
 

No comments:

Post a Comment