Reputation: 307
I'm trying to get nginx to verify client certificate issued through the following chain, with self-signed root: Root CA => Signing CA => Subordinate CA => Client cert.
I installed root_CA.crt on the server, and on the client side, the certs are concatenated with cat client.crt subordinate_CA.crt signing_CA.crt > cert-chain.pem
. My nginx setting looks like this:
ssl_client_certificate /path/to/root_CA.crt;
ssl_verify_client on;
ssl_verify_depth 3;
I tried to connect with curl -k server.url:443 --cert cert-chain.pem
but it gives me error curl: (35) error reading X.509 key or certificate file
. If I try that with --key client.key
then it gives me 400 Bad Request
. I also tried to test with openssl s_client
and the result is similar.
I've verified that the nginx setting works if I have no intermediate CA, i.e., Root CA => Client cert. It also works if my intermediate CA certs are installed on the server and only the leaf cert is on the client side. However, in our case, the Signing CA and Subordinate CA certs cannot be installed on server ahead of time. Any idea what to try next?
Upvotes: 1
Views: 2675
Reputation: 37495
I eventually got this fine to work with a curl 7.52.1 built against openssl (ie. just the version of curl currently available in debian stable).
I needed to combine the two .cer for my issuing chain into a single one:
cat caroot.cer caissuing.cer > cachain.cer
(the order is important, the root cert must be first, then any certs that rely on earlier certs, etc)
and my private client key and the signed pem:
cat private.key private.pem > private-combined.pem
then I was able to access the server using:
curl --cacert cachain.cer --cert-type pem --cert private-combined.pem
(Every other combination I tried of doing this failed with various unhelpful errors from curl, openssl or the server.)
Upvotes: 0
Reputation: 7985
I've found that curl does not correctly send intermediate certificates, even if they're included in the pem (or .p12) file.
You can verify this by doing a packet capture on the traffic going towards the server (tcpdump -A ... dst port 443). You'll be able to see the text forms of the certificate subjects and issues in the capture. You'll see the client certificate (subject and its immediate intermediate issuer), but nothing further up the chain.
Try using openssl s_client to verify:
openssl s_client -connect www.example.com:443 -cert client.crt -key client.key -CAFile cert-chain.pem
And type:
GET / HTTP/1.0<return>
<return>
Upvotes: 1