I have been working on a site that enforces mutually authenticated SSL using apache 2.0.46. I have compiled it from source using the following commands passed to the ./configure script: ./configure --enable-so --enable-ssl --with-ssl=/usr/local/ssl /usr/local/ssl contains openssl version 0.9.7b which I compiled from source using the default build configuration. I have tried both servlets and cgi and all I can get is the user certificate, not the certificate chain. I have tried looking at the mod_ssl code, and cannot figure out why the +ExportCertData directive will only tell apache to forward on the user certificate, not the chain.
This is all Greek to me (i.e., it would take me a long time to figure out how to test), but it looks like there is an off-by-one error in ssl_engine_vars.c that messes up the lookup of the cert chain info. I'll attach a patch to test in just a sec. The latest mod_ssl for Apache 1.3 has this change too. I'd wager that backtracking that line of code in prior releases of the original mod_ssl would show that it got fixed after we imported it into Apache 2.0.
Created attachment 7231 [details] proposed fix for cert chain variable problem
The patch posted previously has been committed to Apache 2.1-dev and proposed for merge to 2.0.48-dev.
I tried the patch and got the same results. I do not think that the patch fixed the problem.
Then I suppose more changes are required :( The change in the patch corrected a blatant error which has also been fixed in the mod_ssl project for 1.3. Do you have any setup hints for testing this scenario? Perhaps you can point to some documentation?
This is what I do... to compile apache(2.0.47). I am using openSSL 0.9.7b, compiled from source, and installed in /usr/local/ssl. ./configure --enable-so --enable-ssl --with-ssl=/usr/local/ssl gmake gmake install to configure apache create a test cert for apache, set up ssl.conf properly. open browser, point to test-cgi. observe that certificate chain is not listed in the output. This proves to me that the certificate chain is not being passed to the CGI, and therefore would not be passed to a servlet either. I am most interested in getting apache to pass the entire certificate chain to a servlet, but am using cgi's to test with right now. This is because it is easier to test, and takes the tomcat connector stuff out of the equation. Please let me know what more help I may be.
I'm stuck at the point of getting a certificate chain passed from the client. (No idea how to do that yet :) ). I see SSL_CLIENT_CERT being set but with the following patch to one of the mod_ssl files I see that OpenSSL is telling mod_ssl that there are zero certificates in the chain. Try testing with this patch to see if OpenSSL has provided mod_ssl with a chain. If it hasn't, you'll see something like I did: [debug] ssl_engine_kernel.c(1064): [client 9.65.78.133] got peer certificate chain (0/8245458/8252f50) where the 0 after "chain (" is the number of certificates in the chain returned by OpenSSL... Index: modules/ssl/ssl_engine_kernel.c =================================================================== RCS file: /home/cvs/httpd-2.0/modules/ssl/ssl_engine_kernel.c,v retrieving revision 1.82.2.6 diff -u -r1.82.2.6 ssl_engine_kernel.c --- modules/ssl/ssl_engine_kernel.c 16 May 2003 18:12:18 -0000 1.82.2.6 +++ modules/ssl/ssl_engine_kernel.c 16 Jul 2003 17:28:03 -0000 @@ -1059,6 +1061,9 @@ apr_table_setn(env, "SSL_CLIENT_CERT", val); if ((peer_certs = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl))) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "got peer certificate chain (%d/%pp/%pp)", + sk_X509_num(peer_certs), peer_certs, ssl); for (i = 0; i < sk_X509_num(peer_certs); i++) { var = apr_psprintf(r->pool, "SSL_CLIENT_CERT_CHAIN_%d", i); val = ssl_var_lookup(r->pool, r->server, r->connection, @@ -1067,6 +1072,10 @@ apr_table_setn(env, var, val); } } + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "SSL library returned no peer certificate chain"); } }
Confirmed fixed in 2.0.46 + Jeff's off-by-one patch. Mark, you did have "SSLOptions +ExportCertData" set in the right context? (Mozilla doesn't seem to send the CA certs included in an imported PKCS#12 ccert for me, neither will "openssl s_client"; maybe MSIE does it, I had to hack my own code to reproduce this)