4
votes

I'm trying to set up a test environment for our application that uses X.509 client authentication over HTTPS in Tomcat 6.0. The servlet code is expecting to get a certificate chain as an array of X509Certificate objects using the javax.servlet.request.X509Certificate of the servlet request. However, this array only contains a single item (the client certificate), where I'm expecting it to have two (the client certificate and the root CA certificate that signed it).

Here's what I've done so far:

  1. Generate a self-signed CA certificate using openssl.
  2. Import the CA certificate as a trusted root certificate into a newly create Java keystore.
  3. Configure the Tomcat HTTPS connector to require client authentication using the keystore created in step 2 as the truststore:
    • clientAuth="true"
    • truststoreFile="<path_to_truststore>"
  4. Generate a new client certificate using openssl and sign it with the CA certificate.
  5. Start Tomcat.
  6. Install the client certificate in Chrome and navigate to my server's homepage. Stepping through the code in debug, I can see that the array returned as the javax.servlet.request.X509Certificate attribute only has the client certificate.

I know that Tomcat is picking up the root CA certificate from the truststore because when I delete it from the truststore, I get an SSL connection error. It's just not making it into the servlet request like the documentation says it should. Am I missing any additional configuration here? Perhaps Tomcat (or Java or JSSE) is expecting some additional X509 V3 extensions or something?

Any help is appreciated!

EDIT

Looks like my setup is legit, and this falls into the category of unusual but expected behavior due to a simplified test environment. In an enterprise scenario it's unlikely that the root certificate authority is going to be directly signing client certificates for individual users. Clearly when this code was written and tested, there was at least one intermediate CA involved in the trust chain.

2

2 Answers

3
votes

What your are seeing is what is expected: Chrome is not sending the CA.

During the TSL Handshake when authenticating the client, the server will send a list of acceptable CAs as part of its CertificateRequest Message (RFC), the browser will then present a Certificate signed by one of these CAs.

ADD

btw, a great way of debugging an SSL connection client side is to use the fantastic openssl tools

openssl s_client -connect ssl.server.com:443

or for SSLV3 only servers

openssl s_client -connect ssl.server.com:443 -ssl3

This will print (among other things) the list of acceptable CAs.

To debug the server side add this to the JVM command line -Djavax.net.debug=ssl

0
votes

The identity keystore should contain the cert signed by the CA ; not the self-signed cert. The CA root should be in the truststore.

Also, what is the purpose of step 4 ?