SSL user authentication not working in Apache

apache-2.2opensslssl

I'm facing a problem with authenticating clients through their ssl certificates which seems similar to a lot of problems I found throughout the net – unfortunately to no solution.

Setup is: apache 2.2, mod_ssl, openssl on Debian linux. I have a client using a Globalsign PersonalSign certificate to authenticate. I have setup SSLCACertificatePath I think correctly since apache debug tells me:

[Thu May 10 15:31:35 2012] [debug] ssl_engine_init.c(1196): CA certificate: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
[Thu May 10 15:31:35 2012] [debug] ssl_engine_init.c(1196): CA certificate: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2
[Thu May 10 15:31:35 2012] [debug] ssl_engine_init.c(1196): CA certificate: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2
[Thu May 10 15:31:35 2012] [debug] ssl_engine_init.c(1196): CA certificate: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA

I don't know why both certificates are twice in this list. Hashes are symlinked correctly via c_rehash utility.

Now the client authenticates (I copy the what I think are relevant entries from the debug log):

Certificate Verification: depth: 1, subject: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2, issuer: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
Certificate Verification: Error (20): unable to get local issuer certificate
OpenSSL: Write: SSLv3 read client certificate B
OpenSSL: Exit: error in SSLv3 read client certificate B
Re-negotiation handshake failed: Not accepted by client!?

which to my limited understanding means he is failing to get the issuer certificate for the intermediate GlobalSign PersonalSign 1 CA – G2 certificate. In fact the issuer_hash of this certificate matches the hash of the GlobalSign Root CA which is indeed found in the SSLCACertificatePath correctly symlinked with this very hash and mentioned earlier in the log as loaded.

So I'm stuck. Any ideas anyone?

Edit:

If I verify the user's certificate through the openssl commandline utility it works:

# openssl verify -CApath conf/ssl.user.crt/ test.pem  
test.pem: OK

(conf/ssl.user.crt is my SSLCACertificatePath)

Best Answer

Solved it. turns out it was a permissions problem:

I have set up a similar setting on a clean Debian Squeeze machine and it worked right from the start. The difference in debug output was:

[debug] ssl_engine_kernel.c(1321): [client 80.252.98.156] Certificate Verification: depth: 2, subject: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA, issuer: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA 
[debug] ssl_engine_kernel.c(1321): [client 80.252.98.156] Certificate Verification: depth: 1, subject: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2, issuer: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
[debug] ssl_engine_kernel.c(1321): [client 80.252.98.156] Certificate Verification: depth: 0, subject: /CN=kettensaege@massaker.de/emailAddress=kettensaege@massaker.de, issuer: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2

on the 'good' side, vs:

[debug] ssl_engine_kernel.c(1321): [client 80.252.98.156] Certificate Verification: depth: 1, subject: /C=BE/O=GlobalSign nv-sa/CN=GlobalSign PersonalSign 1 CA - G2, issuer: /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
[error] [client 80.252.98.156] Certificate Verification: Error (20): unable to get local issuer certificate

on the 'bad' side.

The main difference between the two setups are the permissions for the /conf dir of the apache installation where the CA-certs reside. For security reasons we have the permissions set to 750 and the dir owned by root. Moving the CA files to a dir readable (or to be precise 'executable' to be used in path) made the problem disappear.

So it seems that though mod_ssl claims to read the certificates at server startup it still needs access to the hashed files while running (and having dropped it's root privileges).