Reputation: 563
I am using nginx for my web server with client certificate authentication. The relevant part of the config is:
ssl_certificate /usr/local/etc/nginx/certs/ssl.crt;
ssl_certificate_key /usr/local/etc/nginx/certs/ssl.key;
ssl_client_certificate /usr/local/etc/nginx/certs/server_chain.crt;
ssl_verify_client on;
ssl_verify_depth 2;
The client certificates are signed by another server that has a certificate from a root CA. I.e, I want to accept clients that have a certificate chain as follows:
CA -> intermediate CA -> client
Therefore the file server_chain.crt is made by:
cat intermediate_ca.crt root_ca.crt > server_chain.crt
Now, I can sucessfully access the server by issuing the command:
openssl s_client -connect localhost:443 -tls1 -cert client.crt \
-key client.key -CApath root_ca.crt -state -debug`
and then typing GET /api
But if I try to reach the same service by using:
curl -v -s -k --key client.key --cert client.crt https://localhost/api
I get:
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.6.0</center>
</body>
</html>
I also can not access the localhost/api
page from a web browser with a client certificate installed. Something that works if I turn off client verification.
Any ideas on what's wrong?
Upvotes: 4
Views: 11240
Reputation: 21
Could you try specifying the path. Old version of curl seems to have some bug:
curl -v -s -k --key ./client.key --cert ./client.crt https://localhost/api
Upvotes: 2
Reputation: 8005
This might have changed since then, but as of today, the installed curl can use client side certificates. But because it's linking to Mac OS's SSL libraries there's a couple of gotchas:
cat client.key client.crt intermediate_ca.crt > bundle.pem
openssl pkcs12 -export -in bundle.pem -out bundle.p12
Run curl with the --cert bundle.p12:*password*
option
The showstopper gotcha. Either curl or the underlying libraries do NOT correctly send intermediate certificates: only the client-side certificate is sent. You can verify this with a packet capture on packets going towards the server: the issuer and subject names are visible in cleartext.
Upvotes: 1
Reputation: 563
Ok, so the error was totally unrelated to nginx. Turns out curl has no engine for running ssl by default on OS X. Therefore, curl never sent any certificate to the server.
Upvotes: 4