Bug 733794

Summary: curl --cert no longer accepts certificate chains
Product: [Fedora] Fedora Reporter: JJ Keijser <jan.just.keijser>
Component: nssAssignee: Elio Maldonado Batiz <emaldona>
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: unspecified    
Version: 14CC: bloch, emaldona, kdudka, kengert, paul, pdowler.cadc, rrelyea
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-08-16 13:10:38 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description JJ Keijser 2011-08-26 21:29:25 UTC
Description of problem:

curl --cert no longer accepts certificate chains when connecting to a secure site. versions of curl linked against openssl do support this

Version-Release number of selected component (if applicable):
7.20.1-5.fc13

the same bug is present in fc14 and rhel6

How reproducible:
always

Steps to Reproduce:
1. set up a secure website that requires client auth using a custom CA
2. create a sub CA from this custom CA and create a client cert, signed by the sub CA
3. create a certificate chain file by concatenating the cert + subCA file
(in my case I use an X509 RFC3820 proxy certificate)
4. connect to a remote site:
  curl -v -3 --cert certchain.pem --key userkey.pem --cacert <full-path-to-CA-cert> <remotehost>


Actual results:
 curl -v -3 --cert /tmp/x509up_u7651 --key /tmp/x509up_u7651 --cacert /home/janjust/.globus/certificates/16da7552.0 https://grasveld.nikhef.nl:9000
* About to connect() to grasveld.nikhef.nl port 9000 (#0)
*   Trying 194.171.97.21... connected
* Connected to grasveld.nikhef.nl (194.171.97.21) port 9000 (#0)
* Initializing NSS with certpath: /etc/pki/nssdb
*   CAfile: /home/janjust/.globus/certificates/16da7552.0
  CApath: none
* NSS: client certificate: PEM Token #1:x509up_u7651
* 	subject: CN=proxy,CN=Jan Just Keijser,O=nikhef,O=users,O=dutchgrid
* 	start date: Aug 26 21:17:34 2011 GMT
* 	expire date: Aug 27 09:22:34 2011 GMT
* 	common name: proxy
* 	issuer: CN=Jan Just Keijser,O=nikhef,O=users,O=dutchgrid
* SSL error: SSL_ERROR_BAD_CERT_ALERT
* Closing connection #0
curl: (58) SSL error: SSL_ERROR_BAD_CERT_ALERT


Expected results:
Enter GRID pass phrase:
Your identity: /O=dutchgrid/O=users/O=nikhef/CN=Jan Just Keijser
Creating temporary proxy .............................................................................................. Done
Contacting  voms.grid.sara.nl:30000 [/O=dutchgrid/O=hosts/OU=sara.nl/CN=voms.grid.sara.nl] "pvier" Done
Creating proxy ............................................... Done
Your proxy is valid until Sat Aug 27 11:22:34 2011

ardeche [janjust] > . /global/ices/lcg/current/etc/profile.d/grid-env.sh

ardeche [janjust] > curl -v -3 --cert /tmp/x509up_u7651 --key /tmp/x509up_u7651 --cacert /user/janjust/.globus/certificates/16da7552.0 https://grasveld.nikhef.nl:9000
* About to connect() to grasveld.nikhef.nl port 9000
*   Trying 194.171.97.21... connected
* Connected to grasveld.nikhef.nl (194.171.97.21) port 9000
* successfully set certificate verify locations:
*   CAfile: /user/janjust/.globus/certificates/16da7552.0
  CApath: none
* SSLv3, TLS handshake, Client hello (1):
SSLv3, TLS handshake, Server hello (2):
SSLv3, TLS handshake, CERT (11):
SSLv3, TLS handshake, Request CERT (13):
SSLv3, TLS handshake, Server finished (14):
SSLv3, TLS handshake, CERT (11):
SSLv3, TLS handshake, Client key exchange (16):
SSLv3, TLS handshake, CERT verify (15):
SSLv3, TLS change cipher, Client hello (1):
SSLv3, TLS handshake, Finished (20):
SSLv3, TLS change cipher, Client hello (1):
SSLv3, TLS handshake, Finished (20):
SSL connection using AES256-SHA
* Server certificate:
* 	 subject: /O=dutchgrid/O=hosts/OU=nikhef.nl/CN=grasveld.nikhef.nl
* 	 start date: 2010-09-27 00:00:00 GMT
* 	 expire date: 2011-09-27 14:46:26 GMT
* 	 subjectAltName: grasveld.nikhef.nl matched
* 	 issuer: /C=NL/O=NIKHEF/CN=NIKHEF medium-security certification auth
* SSL certificate verify ok.
> GET / HTTP/1.1
> User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
> Host: grasveld.nikhef.nl:9000
> Accept: */*
> 
< HTTP/1.1 200 OK
[...]

Additional info:

Comment 1 Kamil Dudka 2011-08-26 23:43:49 UTC
CA certificates need to be loaded by --cacert.

Comment 2 JJ Keijser 2011-09-12 08:05:20 UTC
this is not about a CA cert for the client, it's about which certs are presented to the server; when using Curl/openssl it is sufficient to supply the entire cert chain using '--cert': curl then presents this entire chain to the SSL server.

When using Curl/NSS I have to split the cert chain into a cert and the remainder, add the remaining certs to either --capath or to a stackec CA.pem file and then connect to the SSL server.

The annoying thing about this is that the behaviour of curl is now depending on how it is linked (i.e. using NSS or using OpenSSL); when scripting things using curl I now have to determine how curl is linked first.

Comment 3 Kamil Dudka 2011-09-12 11:36:12 UTC
(In reply to comment #2)
> When using Curl/NSS I have to split the cert chain into a cert and the
> remainder, add the remaining certs to either --capath or to a stackec CA.pem
> file and then connect to the SSL server.

Does it work this way for both OpenSSL and NSS?

Comment 4 JJ Keijser 2011-09-12 13:34:58 UTC
with curl/openssl you can only get it workign if you specify
  curl --cert  <certificate chain>

similarly, with curl/nss you need to create a stacked certificate file and specify it using
  curl --cacert <all CA certs>

Comment 5 Kamil Dudka 2011-09-14 10:54:21 UTC
JJ, could you please create a self-contained test-case we can try with both OpenSSL and NSS?

Comment 6 JJ Keijser 2011-09-15 14:30:43 UTC
hmmm I set up a test CA, sub-CA , server cert, client cert etc and then ran a simple test on all platforms; it turns out that the following worked on all platforms:
- stacking all required certs into a single file
- creating the *right* hash for all required certs in a --capath directory also works

so the options
$ curl -v --cert ./client.pem --key ./client.pem --cacert ./stacked.pem \
   https://127.0.0.1:4433 
or
$ curl -v --cert ./client.pem --key ./client.pem --capath <somedir> \
   https://127.0.0.1:4433 

work everywhere. The first time I tried this the wrong hash was created, as openssl 1 uses different hashes compared to openssl 0.9.8 ...

It's still a pity that the old method (pass a chain using --cert) can no longer be used, but at least I now have a single procedure for both curl/openssl and curl/nss.

Comment 7 Kamil Dudka 2011-09-15 14:53:01 UTC
(In reply to comment #6)
> It's still a pity that the old method (pass a chain using --cert) can no longer
> be used, but at least I now have a single procedure for both curl/openssl and
> curl/nss.

Then it is probably an OpenSSL-specific feature.  I doubt libcurl documentation guarantees something like that to work.  What about GnuTLS?  Could you please try it with curl/GnuTLS?  I do not have a testing setup myself...

Comment 8 JJ Keijser 2011-11-02 14:31:10 UTC
I've written a testscript which can be used stand-alone; I've tested it against curl/openssl, curl/nss, curl/gnutls and curl/polarssl on FC154. See
  http://www.nikhef.nl/pub/projects/grid/gridwiki/index.php/Funny_Curly_things
for details.

Comment 9 Kamil Dudka 2011-11-02 21:39:59 UTC
(In reply to comment #8)
> I've written a testscript which can be used stand-alone; I've tested it against
> curl/openssl, curl/nss, curl/gnutls and curl/polarssl on FC154. See
>   http://www.nikhef.nl/pub/projects/grid/gridwiki/index.php/Funny_Curly_things
> for details.

Thank you for this research, JJ.

Elio, is this kind of certs something that we can address in libnsspem?

Comment 10 Patrick Dowler 2012-07-13 22:41:52 UTC
Just confirming that this issue is still present in Fedora 16 (curl/NSS). The work-around of presenting the rest of the chain via the --cacert option does work with the system curl (curl-7.21.7-7.fc16.x86_64). The problem with the workaround is that in the general case you really need to include all the certs from the system CA bundle as well as this option effects validating server certificates.

Is anyone looking at solutions here? The recommended use for proxy certificates in the grid community appears to be to include at least one additional certificate from the chain (the self-signing issuer) in the file; by extension one could include other non-root certificates necessary to verify back to a trusted root CA.

Comment 11 Fedora End Of Life 2012-08-16 13:10:42 UTC
This message is a notice that Fedora 14 is now at end of life. Fedora 
has stopped maintaining and issuing updates for Fedora 14. It is 
Fedora's policy to close all bug reports from releases that are no 
longer maintained.  At this time, all open bugs with a Fedora 'version'
of '14' have been closed as WONTFIX.

(Please note: Our normal process is to give advanced warning of this 
occurring, but we forgot to do that. A thousand apologies.)

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, feel free to reopen 
this bug and simply change the 'version' to a later Fedora version.

Bug Reporter: Thank you for reporting this issue and we are sorry that 
we were unable to fix it before Fedora 14 reached end of life. If you 
would still like to see this bug fixed and are able to reproduce it 
against a later version of Fedora, you are encouraged to click on 
"Clone This Bug" (top right of this page) and open it against that 
version of Fedora.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events.  Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

The process we are following is described here: 
http://fedoraproject.org/wiki/BugZappers/HouseKeeping