curl SSL certificate error: verifcation failed

18,681

Solution 1

You've run into a problem caused by a long standing issue where OpenSSL is not properly handling situations with multiple trust path. If you look into the report from SSLLabs you'll see, that the server provides the following chain:

[0] /O=www.onevanilla.com/OU=Domain Control Validated/CN=www.onevanilla.com SAN=DNS:www.onevanilla.com,DNS:onevanilla.com
[1] /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07969287
[2] /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
[3] /L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//[email protected]

Browsers have included a root certificate for Go Daddy Class 2 Certification Authority and thus can build a trust path with [0],[1] and the root certificate and thus they will ignore the certificates [2] and [3]. OpenSSL instead will ignore only certificate [3] because it is self-signed and therefore should not have been included in the chain at all. It will then attempt to verify the chain [0],[1],[2] and will fail because it does not find a root certificate signing [2]. It will not attempt to verify the shorter chain [0],[1] instead.

For more details about this problem see Python Urllib2 SSL error and http://kriscience.blogspot.de/2013/03/supporting-trusted-but-untrusted.html and the OpenSSL bug report.

What you can do: get the missing certificate from https://certs.godaddy.com/repository/valicert_class2_root.crt and use it in the --cacert parameter.

Solution 2

The curl --cacert <cert> option is used to specify a certificate authority to use to verify the server certificate. The certificate you copied from the s_client output is the server certificate, and using it as as the --cacert argument fails because the server certifiate is not self-signed, but signed by a different certificate authority (in your case, Go Daddy).

Invoke curl with the --capath option to specify the trusted root CA(s). This is analogous to the s_client -CApath <dir> option.

$ curl -v --capath /etc/ssl/certs https://www.onevanilla.com
Share:
18,681
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    Please help me understand why I cannot successfully curl this url via https:

    I am using Ubuntu 12.04.5 with curl 7.22.0, libcurl 7.22.0 and OpenSSL 1.0.1-4ubuntu5.25

    $ curl -v https://www.onevanilla.com/
    * About to connect() to www.onevanilla.com port 443 (#0)
    *   Trying 199.83.128.4... connected
    * 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, verify that the CA cert is OK. Details:
    error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
    * Closing connection #0
    curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
    error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
    

    So I try to manually get the cert:

    $ openssl s_client -connect www.onevanilla.com:443 </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/www.onevanilla.com.pem
    

    and then:

    $ curl -v --cacert /tmp/www.onevanilla.com.pem https://www.onevanilla.com
    

    but I get the same result:

    * About to connect() to www.onevanilla.com port 443 (#0)
    *   Trying 199.83.128.4... connected
    * successfully set certificate verify locations:
    *   CAfile: /tmp/www.onevanilla.com.pem
      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, verify that the CA cert is OK. Details:
    error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
    * Closing connection #0
    curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
    error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
    

    I can verify the certificate with openssl:

    $ openssl s_client -host www.onevanilla.com -port 443 -CApath /etc/ssl/certs
    

    and this returns Verify return code: 0 (ok)

    I've also run sudo update-ca-certificates --fresh just to be sure, but no luck.

    So it seems to me like the cert is valid (not expired, hostname matches CN), but I can never get a successful response using curl (unless of course I use -k or --insecure options). Can someone please explain?