Discussion:
How to send an intermediate for a client certificate to the server.
James Short
2018-10-31 16:54:22 UTC
Permalink
I'm trying to test mTLS with curl/nginx. The server side client
verification is going fine as my system ca-certs has the relevant root for
the server cert/inter chain nginx is sending to curl. However, I have a
client cert/inter chain that I'm passing via --cert and only the client
cert (first pem entry) is sent to the server.

With openssl s_client, I can use -CAfile to include the intermediate as it
is only used for client cert verification. With curl, if I put the
intermediate for the client cert in a file and point to it with --cacert,
then *server* certificate validation fails because the root for the server
cert validation is no longer there.

The workaround is to concatenate my system root and my client cert
intermediate into a new file and point to it with --cacert. This tells me
that --cacert is used for building/verifying both server and client
certificate chains.

Is this expected? Is there a simpler way to ensure that my client cert and
intermediate are sent to the server for mTLS verification?

curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.34 zlib/1.2.7
libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3
pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz
unix-sockets

Thanks,

-James
Daniel Stenberg
2018-11-01 15:53:26 UTC
Permalink
Post by James Short
I'm trying to test mTLS with curl/nginx. The server side client
verification is going fine as my system ca-certs has the relevant root for
the server cert/inter chain nginx is sending to curl. However, I have a
client cert/inter chain that I'm passing via --cert and only the client cert
(first pem entry) is sent to the server.
(Let me first preface this reply by saying that I'm far from an expert in TLS
and client certs.)

This is probably curl functionality that is TLS backend dependent. You're
using a curl built to use NSS, so maybe there's a bug there.

But also: your curl version (7.29.0) is over five years old. We have quite
literaly fixed thousands of bugs since that was released, and maybe we
improved in this area as well.
Post by James Short
With openssl s_client, I can use -CAfile to include the intermediate as it
is only used for client cert verification. With curl, if I put the
intermediate for the client cert in a file and point to it with --cacert,
then *server* certificate validation fails because the root for the server
cert validation is no longer there.
Right, because curl's --cacert option is the CA bundle used for verifying the
server.
Post by James Short
The workaround is to concatenate my system root and my client cert
intermediate into a new file and point to it with --cacert. This tells me
that --cacert is used for building/verifying both server and client
certificate chains.
That surprises me, and might also be a TLS backend specific thing. I would've
expected a work-around to concatenate them for the --cert option.
--
/ daniel.haxx.se
-----------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-users
Et
Kamil Dudka
2018-11-01 16:46:23 UTC
Permalink
This post might be inappropriate. Click to display it.
James Short
2018-11-01 21:15:51 UTC
Permalink
Thanks for your response!

I got the 7.29.0 source and compiled with openssl instead and I just can
include the cert/inter chain in --cert and it works fine.

I guess NSS does things in contention with the curl documentation :(. I'm
limited to this curl as it is in our yum repos. I might add a new one with
updated curl and have it compiled with OpenSSL instead.
Post by James Short
Post by Daniel Stenberg
Post by James Short
I'm trying to test mTLS with curl/nginx. The server side client
verification is going fine as my system ca-certs has the relevant root
for
Post by Daniel Stenberg
Post by James Short
the server cert/inter chain nginx is sending to curl. However, I have
a
Post by Daniel Stenberg
Post by James Short
client cert/inter chain that I'm passing via --cert and only the client
cert (first pem entry) is sent to the server.
(Let me first preface this reply by saying that I'm far from an expert in
TLS and client certs.)
This is probably curl functionality that is TLS backend dependent. You're
using a curl built to use NSS, so maybe there's a bug there.
But also: your curl version (7.29.0) is over five years old. We have
quite
Post by Daniel Stenberg
literaly fixed thousands of bugs since that was released, and maybe we
improved in this area as well.
Post by James Short
With openssl s_client, I can use -CAfile to include the intermediate
as it
Post by Daniel Stenberg
Post by James Short
is only used for client cert verification. With curl, if I put the
intermediate for the client cert in a file and point to it with
--cacert,
Post by Daniel Stenberg
Post by James Short
then *server* certificate validation fails because the root for the
server
Post by Daniel Stenberg
Post by James Short
cert validation is no longer there.
Right, because curl's --cacert option is the CA bundle used for verifying
the server.
Post by James Short
The workaround is to concatenate my system root and my client cert
intermediate into a new file and point to it with --cacert. This
tells me
Post by Daniel Stenberg
Post by James Short
that --cacert is used for building/verifying both server and client
certificate chains.
That surprises me, and might also be a TLS backend specific thing. I
would've expected a work-around to concatenate them for the --cert
option.
https://github.com/curl/curl/issues/851
The ability of libcurl to load certificates from files is limited when it uses
NSS for TLS. Not that I tried it myself but you should be able to import the
certificates to the native NSS database and control the trust more precisely.
Kamil
Kamil Dudka
2018-11-02 08:23:47 UTC
Permalink
Post by James Short
Thanks for your response!
I got the 7.29.0 source and compiled with openssl instead and I just can
include the cert/inter chain in --cert and it works fine.
I guess NSS does things in contention with the curl documentation :(. I'm
limited to this curl as it is in our yum repos. I might add a new one with
updated curl and have it compiled with OpenSSL instead.
The downside of this solution is that you will need to handle security updates
of (lib)curl yourself from now on.

Kamil
Post by James Short
Post by James Short
Post by Daniel Stenberg
Post by James Short
I'm trying to test mTLS with curl/nginx. The server side client
verification is going fine as my system ca-certs has the relevant root
for
Post by Daniel Stenberg
Post by James Short
the server cert/inter chain nginx is sending to curl. However, I have
a
Post by Daniel Stenberg
Post by James Short
client cert/inter chain that I'm passing via --cert and only the client
cert (first pem entry) is sent to the server.
(Let me first preface this reply by saying that I'm far from an expert in
TLS and client certs.)
This is probably curl functionality that is TLS backend dependent. You're
using a curl built to use NSS, so maybe there's a bug there.
But also: your curl version (7.29.0) is over five years old. We have
quite
Post by Daniel Stenberg
literaly fixed thousands of bugs since that was released, and maybe we
improved in this area as well.
Post by James Short
With openssl s_client, I can use -CAfile to include the intermediate
as it
Post by Daniel Stenberg
Post by James Short
is only used for client cert verification. With curl, if I put the
intermediate for the client cert in a file and point to it with
--cacert,
Post by Daniel Stenberg
Post by James Short
then *server* certificate validation fails because the root for the
server
Post by Daniel Stenberg
Post by James Short
cert validation is no longer there.
Right, because curl's --cacert option is the CA bundle used for verifying
the server.
Post by James Short
The workaround is to concatenate my system root and my client cert
intermediate into a new file and point to it with --cacert. This
tells me
Post by Daniel Stenberg
Post by James Short
that --cacert is used for building/verifying both server and client
certificate chains.
That surprises me, and might also be a TLS backend specific thing. I
would've expected a work-around to concatenate them for the --cert
option.
https://github.com/curl/curl/issues/851
The ability of libcurl to load certificates from files is limited when it uses
NSS for TLS. Not that I tried it myself but you should be able to import the
certificates to the native NSS database and control the trust more precisely.
Kamil
-----------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-users
Etiquette: https://cur

Loading...