Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difference in sending TLS client cert with Issuer DN list mismatch #1411

Closed
jethrogb opened this issue Apr 11, 2017 · 6 comments
Closed

Difference in sending TLS client cert with Issuer DN list mismatch #1411

jethrogb opened this issue Apr 11, 2017 · 6 comments

Comments

@jethrogb
Copy link
Contributor

jethrogb commented Apr 11, 2017

TLS servers may request a certificate from the client. This request includes a list of 0 or more acceptable issuer DNs. The client may use this list to determine which certificate to send. In curl, when the specified client certificate doesn't match any of the server-specified DNs, the OpenSSL and GnuTLS backends behave differently.

I did this

Here I'm running a simple TLS server that requests client certificates with an issuer CN=serv.

$ openssl req -new -x509 -keyout s.key -newkey rsa:2048 -subj /CN=serv -out s.crt -nodes
$ openssl s_server -CAfile s.crt -cert s.crt -key s.key -www -verify 1 > /dev/null 2>&1 &

(Note: you can have the server send an empty issuer DN list by omitting the -CAfile s.crt parameters.)

Generate a client cert with a different issuer (CN=clnt):

$ openssl req -new -x509 -keyout c.key -newkey rsa:2048 -subj /CN=clnt -out c.crt -nodes

Try connecting with the OpenSSL backend:

$ ./curl --version
curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 OpenSSL/1.0.2g zlib/1.2.8 libidn2/0.10 libpsl/0.11.0 (+libicu/55.1) libssh2/1.5.0 nghttp2/1.7.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS Debug TrackMemory IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 
$ ./curl -k https://localhost:4433 --cert c.crt --key c.key 
*snip*
-----BEGIN CERTIFICATE-----
MII...*snip*
-----END CERTIFICATE-----
*snip*

The client certificate is sent.

With the GnuTLS backend:

$ ./curl --version
curl 7.52.1 (x86_64-pc-linux-gnu) libcurl/7.52.1 GnuTLS/3.4.10 zlib/1.2.8 libidn2/0.10 libpsl/0.11.0 (+libicu/55.1) libssh2/1.5.0 nghttp2/1.7.1 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS Debug TrackMemory IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 
$ ./curl -k https://localhost:4433 --cert c.crt --key c.key 
*snip*
no client certificate available
*snip*

No client certificate is sent.

I expected the following

I expected that GnuTLS and OpenSSL backends would behave the same. In particular, I would have a preference for the GnuTLS backend behaving like the OpenSSL backend. To do that, look at cert_callback in gnutls-cli.

curl/libcurl version

See above

operating system

Ubuntu 16.04

@bagder bagder added the TLS label Apr 12, 2017
@chr-b
Copy link

chr-b commented Jul 12, 2017

I just ran into the same problem.

I think the appropriate solution in the GnuTLS backend would be to make use of gnutls_certificate_set_retrieve_function. This allows to specify the certificate and private key that should be used by the client in the TLS handshake.

@stale
Copy link

stale bot commented Jan 8, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jan 8, 2018
@jethrogb
Copy link
Contributor Author

jethrogb commented Jan 8, 2018

Problem remains

@stale stale bot removed the stale label Jan 9, 2018
@bagder
Copy link
Member

bagder commented Jan 9, 2018

It seems nobody is capable of working on this issue for now, making it subject to get added to the KNOWN_BUGS document and the issue to be closed (for now) on github,

@ksuszka
Copy link

ksuszka commented Feb 20, 2018

Wouldn't it be enough to add GNUTLS_FORCE_CLIENT_CERT flag to gnutls_init function call in

rc = gnutls_init(&BACKEND->session, init_flags);
as it is described here (the end of paragraph): https://www.gnutls.org/manual/html_node/Certificate-credentials.html#Client-certificate-authentication

In the case a single certificate is available and the server does not specify a signer’s list, then that certificate is always sent. It is, however possible, to send a certificate even when the advertised CA list by the server contains CAs other than its signer. That can be achieved using the GNUTLS_FORCE_CLIENT_CERT flag in gnutls_init.

@jethrogb
Copy link
Contributor Author

@ksuszka yes it sounds like that may be an even easier fix. It looks like that flag was added in GnuTLS Version 3.5.0 (released 2016-05-09).

@bagder bagder closed this as completed in f022c91 Apr 30, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Jul 29, 2018
jethrogb added a commit to jethrogb/curl that referenced this issue Feb 20, 2020
TLS servers may request a certificate from the client. This request includes a list of 0 or more acceptable issuer DNs. The client may use this list to determine which certificate to send. GnuTLS's default behavior is to not send a client certificate if there is no match. However, OpenSSL's default behavior is to send the configured certificate. The `GNUTLS_FORCE_CLIENT_CERT` flag mimics OpenSSL behavior.

Fixes curl#1411
bagder pushed a commit that referenced this issue Feb 21, 2020
TLS servers may request a certificate from the client. This request
includes a list of 0 or more acceptable issuer DNs. The client may use
this list to determine which certificate to send. GnuTLS's default
behavior is to not send a client certificate if there is no
match. However, OpenSSL's default behavior is to send the configured
certificate. The `GNUTLS_FORCE_CLIENT_CERT` flag mimics OpenSSL
behavior.

Authored-by: jethrogb on github
Fixes #1411
Closes #4958
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging a pull request may close this issue.

4 participants