jlhonora
jlhonora

Reputation: 10709

cURL not respecting TLS v1

I'm having trouble connecting to a TLS-only backend. The configuration is the following:

When using cURL 7.43.0 in OS X the connection works fine, since the client is respecting the server's highest TLS version:

curl -vvv -X GET -o /dev/null https://domain
* Rebuilt URL to: https://domain
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying ip...
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to domain (ip) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: *.domain
* Server certificate: DigiCert SHA2 Secure Server CA
* Server certificate: DigiCert Global Root CA
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0> GET / HTTP/1.1
> Host: domain
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK

But no luck in Android. Since no SSLv3 connections will be accepted, the --tlsv1 option is passed. Still, the client chooses to use SSLv3, thus failing to conclude the handshake:

curl -vvv --tlsv1 -X GET https://domain                                                                                                                                                             
* About to connect() to domain port 443 (#0)
*   Trying ip... connected
* Connected to domain (ip) 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, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0

Same results without specifying TLS 1.0: curl -vvv -X GET https://domain

Is there any way that I can tell the client to use TLS and not SSLv3?

Edit: Check the accepted answer, since it's a good way to really check what cURL is doing in your device. The issue itself was being caused because the cert didn't have the full chain attached to it (intermediate + root certs). Here are a couple of online SSL health checkers that can help you further debug the issue:

https://www.ssllabs.com/ssltest/

https://www.digicert.com/help/

Upvotes: 1

Views: 7099

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123481

  • SSLv3, TLS handshake, Client hello (1):

Although this looks like SSLv3 is used maybe it is not used. OpenSSL implements most of the TLS1.x protocol within SSLv3 functions because TLS1.x is just the better SSLv3 and the protocols don't differ that much.

To test this I've setup a simple server which echos the cipher and protocol version back which gives on the curl side:

$ curl -vvv --tlsv1 -o /dev/null --insecure  https://127.0.0.1:12345
...
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256

But on the server side:

cipher=ECDHE-RSA-AES128-GCM-SHA256 version=TLSv1_2
GET / HTTP/1.1
User-Agent: curl/7.35.0
Host: 127.0.0.1:12345
Accept: */*

Thus even if the debug output says SSLv3 it is actually TLS1.2.

Upvotes: 4

Related Questions