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

Comments

Projects
None yet
4 participants
@jethrogb

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 SSL/TLS label Apr 12, 2017

@chr-b

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

jethrogb commented Jan 8, 2018

Problem remains

@stale stale bot removed the stale label Jan 9, 2018

@bagder

This comment has been minimized.

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

This comment has been minimized.

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

This comment has been minimized.

jethrogb commented Feb 20, 2018

@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 in f022c91 Apr 30, 2018

@lock lock bot locked as resolved and limited conversation to collaborators Jul 29, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.