-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

All,

I'm following up because I was able to get the following working. In
case anyone else wants to get this all working, the information is all
in (roughly) one place.

1. Apache httpd terminates SSL
2. Apache httpd performs client certificate verification
3. mod_jk forwards client certificate to Tomcat
4. My code fetches the client X509Certificate from the request
5. My code loads the CA used to sign the client certificate from a file
6. My code verifies the client certificate is valid given the
   CA's public key

Steps 1-2 were taken care of by loosely following the instructions
provided here:

http://it.toolbox.com/blogs/securitymonkey/howto-securing-a-website-with-client-ssl-certificates-11500

Setting "SSLVerifyClient optional" will allow my code to check for the
certificate, verify it, and then take a different action than usual for
authentication purposes (which was the original goal of this exercise).

Step 3 (getting mod_jk to deliver the client certificate to Tomcat)
required only:

  SSLOptions +ExportCertData

While technically not a mod_jk option, mod_jk can't actually send the
client cert to Tomcat unless this options is set. "SSLOptions
+StdEnvVars" is not sufficient.

Steps 4-6 are easy once you get the incantations right. The key to
loading the CA cert was:

import java.io.FileInputStream;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateFactory;

..

  // Load the CA Certificate
  FileInputStream inStream = null;
  Certificate caCert = null;

  try
  {
    // Confusingly, the ca.crt file is in OpenSSL format, not PKCS12
    inStream = new FileInputStream("ca.crt");
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    caCert = (Certificate)cf.generateCertificate(inStream);
  }
  finally
  {
    if(null != inStream) try { inStream.close(); }
    catch (IOException ioe) { ioe.printStackTrace(); }
  }

  // Load the client certificate
  Object cert =
request.getAttribute("javax.servlet.request.X509Certificate");

  if (cert instanceof X509Certificate[])
  {
    X509Certificate[] certs = (X509Certificate[])cert;

    for(int i=0; i<certs.length; ++i)
    {
      try
      {
        certs[i].verify(caCert.getPublicKey());

        // Verified

      } catch (Exception e) {

        // Not verified

      }
    }
  }

That's all the Java code that's required, which is pretty cool.

It seems pretty slow right now, but I'm working remotely, so it could be
network issues. Certainly loading the CA certificate /once/ and caching
it will speed things up.

Thanks to Rainer for his help figuring out the Apache httpd/mod_jk stuff.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrh23IACgkQ9CaO5/Lv0PDVwwCgl+xa3WphGAHlOXWVf68kYXfA
/ncAn0vvzWQ38X2jmWLSjwEYy7CQhAfn
=kGEX
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to