I am in the following situation. I need to set up a 2-way integration with an external system. The admin of the external system required me to send two CSRs, one to be used to generate a client certificate, the other to generate a server certificate. They sent me the corresponding certificates. I set up the channel me->they with success (i.e.: I can invoke their service supplying my client certificate), but I can't set up the inverse channel correctly (i.e.: I can't make my Apache accept their client certificate without complaining).
Together with my server certificate (let's call it my-server.pem) they also sent me their own client certificate (let's call it their-client.pem). This certificate (their-client.pem) is emitted by a "self-signed" CA, that is a CA that is not among those well-known CAs already available in my Linux system. I don't have this certificate and I was not yet able to get it from the external system admins (they are reluctant... let's put aside any comment on this please... >-|)
This is how I set up my VirtualHost in Apache:
SSLEngine on
SSLCertificateFile /path/to/my-server.pem
SSLCertificateKeyFile /path/to/my-server-secret-key.key
SSLVerifyClient require
SSLCACertificateFile /path/to/their-client.pem
SSLVerifyDepth 0
Since I don't have the CA certificate and since it's perfectly fine for me to say "just trust that client certificate, nobody else!", I put the client certificate itself as the SSLCACertificateFile
, as suggested in the answer to:
https://security.stackexchange.com/questions/36069/use-client-certificate-using-self-signed-ca-while-using-web-certificate-of-a-pub
However, this doesn't seem to work. The error they see on their side is:
javax.net.ssl.SSLException: Received fatal alert: unknown_ca
After enabling the SSL log and setting it to debug, what I see on my side is:
[ssl:debug] [pid 3396] ssl_engine_kernel.c(1381): [client <their-ip>:41474] AH02275: Certificate Verification, depth 1, CRL checking mode: none [subject: CN=Test CA,OU=Foo,O=Bar,C=it / issuer: CN=Test CA,OU=Foo,O=Bar,C=it / serial: 1BFE / notbefore: Dec 6 15:22:45 2010 GMT / notafter: Dec 6 15:21:52 2020 GMT]
[ssl:info] [pid 3396] [client <their-IP>:41474] AH02276: Certificate Verification: Error (19): self signed certificate in certificate chain [subject: CN=Test CA,OU=Foo,O=Bar,C=it / issuer: CN=Test CA,OU=Foo,O=Bar,C=it / serial: 1BFE / notbefore: Dec 6 15:22:45 2010 GMT / notafter: Dec 6 15:21:52 2020 GMT]
[ssl:info] [pid 3396] [client <their-IP>:41474] AH02008: SSL library error 1 in handshake (server my-server.com:443)
[ssl:info] [pid 3396] SSL Library Error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
[ssl:info] [pid 3396] [client <their-IP>:41474] AH01998: Connection closed to child 54 with abortive shutdown (server my-server.com:443)
In other words, it's still trying to validate the dummy CA of the client certificate. I also tried to change SSLVerifyDepth
to 1, with no luck (same error).
If I disable the client certificate request (by changing the SSLVerifyClient
value), the invocation goes fine, but I don't think it's the correct way to go.
A very similar question is: How can I make apache request a client SSL certificate without needing to verify it against a known CA?
However I'm not sure I understand the accepted solution. First of all, the client certificate I must validate is not self-signed (it's issued by an unknown CA).
Secondly, from what I understand from Apache/mod_ssl documentation, SSLVerifyCLient optional_no_ca
actually disables strong client certificate authentication, because it makes it optional.
Third, the possibility to create a fake certificate with the same DN of the missing root CA certificate sounds like a workaround for forcing the client to send its client certificate, but in my case I don't think my problem is the client not sending me the certificate, but rather the Apache inability to fully validate it correctly.
Any suggestion on this topic would be very helpful.