0

On Debian Jessie 8.4 GNU/Linux, I am experiencing a certificate validation inconsistency between Iceweasel (Debian's derivative of Firefox) and cURL in relation to the URL https://profile.mensa.org.uk/contact.aspx .

Iceweasel

Visiting https://profile.mensa.org.uk/contact.aspx using Iceweasel results in no errors or warnings. Clicking on the padlock icon at the left of the address bar, and then clicking the "More Information..." button, yields a window saying, among other things:

Web Site Identity
Web site: profile.mensa.org.uk
Owner: This web site does not supply ownership information.
Verified by: GeoTrust Inc.

Clicking the "View Certificate" button yields a window with two tabs, "General" and "Details". The General tab says:

This certificate has been verified for the following uses:
SSL Client Certificate
SSL Server Certificate
Issued To
Common Name (CN) profile.mensa.org.uk
Organisation (O) <Not Part Of Certificate>
Organisational Unit (OU) GT91227394
Serial Number 06:26:4F
Issued By
Common Name (CN) RapidSSL SHA256 CA - G3
Organisation (O) GeoTrust Inc.
Organisational Unit (OU) <Not Part Of Certificate>
Period of Validity
Begins On 05/08/15
Expires On 06/09/16
Fingerprints
SHA-256 Fingerprint 9C:F3:D7:B8:96:D6:A5:BC:98:9E:F0:DE:26:63:BD:17:
C5:29:24:C9:02:A9:90:D3:A5:49:AB:10:5D:E8:C0:3C
SHA1 Fingerprint

Clicking on the Details tab shows a three-level hierarchy in the Certificate Hierarchy field:

GeoTrust Global CA
  RapidSSL SHA256 CA - G3
    profile.mensa.org.uk

Selecting the GeoTrust Global CA item in that field, then clicking the "Export..." button, and then saving as the file ~/Documents/organisations/mensa/geotrust_global_ca.pem works as expected. Here is the fingerprint:

$ openssl x509 -noout -in ~/Documents/organisations/mensa/geotrust_global_ca.pem -fingerprint
SHA1 Fingerprint=DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12

Let's compare this with cURL.

cURL

Visiting https://profile.mensa.org.uk/contact.aspx using cURL results in a certificate error. Here is the verbose output, attempting to fetch only header information:

$ curl -v --head https://profile.mensa.org.uk/contact.aspx
* Hostname was NOT found in DNS cache
*   Trying 93.159.201.114...
* Connected to profile.mensa.org.uk (93.159.201.114) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

cURL works OK for this URL over HTTP, and also for other domains over HTTPS:

$ curl --head http://profile.mensa.org.uk/contact.aspx
HTTP/1.1 302 Found
Date: Sat, 28 May 2016 14:30:56 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 4.0.30319
Location: /login.aspx?target=%2fcontact.aspx
Set-Cookie: ASP.NET_SessionId=axylcyf2cep2lq4e3brkggln; path=/; HttpOnly
Set-Cookie: WebToolsParam= ; path=/; HttpOnly
Cache-Control: no-cache, no-store
Pragma: no-cache
Expires: -1
Content-Type: text/html; charset=utf-8
Content-Length: 151

$ curl --head https://www.mensa.org.uk
HTTP/1.1 200 OK
Date: Sat, 28 May 2016 12:39:56 GMT
Server: Apache
Pragma: no-cache
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: store, no-cache, must-revalidate, post-check=0, pre-check=0
Set-Cookie: SESS4b296932593725667cea89bf7eb4e462=d10lbmrpju03rccsaftdemiai6; path=/; domain=.mensa.org.uk
Last-Modified: Sat, 28 May 2016 12:39:56 GMT
Content-Type: text/html; charset=utf-8

Here is information about the current version of cURL:

$ curl -V
curl 7.38.0 (i586-pc-linux-gnu) libcurl/7.38.0 OpenSSL/1.0.1k zlib/1.2.8 libidn/1.29 libssh2/1.4.3 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp 
Features: AsynchDNS IDN IPv6 Largefile GSS-API SPNEGO NTLM NTLM_WB SSL libz TLS-SRP

I believe that whereas Iceweasel has its own CA store, cURL looks for certificate authority certificates in /etc/ssl/certs, as shown in the verbose output above. So, my first thought was that the error cURL experienced in visiting https://profile.mensa.org.uk/contact.aspx must be due to /etc/ssl/certs being devoid of a certificate for the CA that Iceweasel identified: GeoTrust Global CA. However, I found that /etc/ssl/certs does contain a suitable certificate:

$ openssl x509 -noout -in /etc/ssl/certs/GeoTrust_Global_CA.pem -fingerprint
SHA1 Fingerprint=DE:28:F4:A4:FF:E5:B9:2F:A3:C5:03:D1:A3:49:A7:F9:96:2A:82:12

As you can see, this is the same fingerprint as for ~/Documents/organisations/mensa/geotrust_global_ca.pem above.

So, something else must be going on. I tried forcing cURL to use each of these two certificates, via the --cacert option, but that didn't yield success:

$ curl --cacert ~/Documents/organisations/mensa/geotrust_global_ca.pem --head https://profile.mensa.org.uk/contact.aspx
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

$ curl --cacert /etc/ssl/certs/GeoTrust_Global_CA.pem --head https://profile.mensa.org.uk/contact.aspx
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

My primary question is: what is causing this inconsistency between cURL and Iceweasel?

My secondary question is: does this inconsistency mean that there is a bug in Iceweasel and/or a bug in cURL?

2
  • As i wrote elsewhere, profile.mensa.org.uk has an improperly configured certificate chain. Your Firefox profile has the missing intermediate cached, so it works (for you); curl doesn't have a cache. May 28, 2016 at 19:12
  • @MattNordhoff, thanks. Folks on the curl-users mailing list drew the same conclusion. If you're happy to post this as an answer, I'll mark it as correct; that way, you'll get some "rep". Thanks again :)
    – user6860
    May 28, 2016 at 20:25

1 Answer 1

-1

Apparently, profile.mensa.org.uk has an improperly configured certificate chain. Your Firefox profile has the missing intermediate cached, so it works (for you); curl doesn't have a cache.

Credit to Matt Nordhoff

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.