TLS 1.2 not working in cURL
Asked Answered
P

6

28

I am having trouble curling an HTTPS url that uses TLS1.2, in my curl operation I post my login data into the website and save it in cookiefile. The error message I am getting is this

 error:14077438:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error

I have tried setting VERIFYPEER and VERIFYHOST to 0 but that does not seem to work, any suggestions?

Here are the versions I am using:

  • OpenSSL version is 0.9.8b
  • CURL version is 7.24.0
  • PHP is 5.3

Here is the code:

$setuplogin = curl_init(); 
curl_setopt ($setuploginurl, CURLOPT_URL, $url); 
curl_setopt ($setuploginurl, CURLOPT_SSL_VERIFYPEER, 1); 
curl_setopt ($setuploginurl, CURLOPT_SSL_VERIFYHOST, 1);
curl_setopt ($setuploginurl, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt ($setuploginurl, CURLOPT_SSLVERSION, 'CURL_SSLVERSION_TLSv1_2');
curl_setopt ($setuploginurl, CURLOPT_POSTFIELDS, 'username=uname&password=pword&act=login&submit=Login');
curl_setopt ($setuploginurl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36"); 
curl_setopt (setuploginurl, CURLOPT_TIMEOUT, 60); 
curl_setopt ($setuploginurl, CURLOPT_COOKIESESSION, TRUE); 
curl_setopt ($setuploginurl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($setuploginurl,  CURLOPT_HEADER, 1);
curl_setopt ($setuploginurl,CURLOPT_ENCODING,"gzip");
curl_setopt ($setuploginurl, CURLOPT_POST, true);
curl_setopt ($setuploginurl, CURLOPT_COOKIEJAR, 'cookies.txt'); 
curl_setopt ($setuploginurl, CURLOPT_FRESH_CONNECT , 1);

$loginp= curl_exec($setuploginurl); 
if ($loginp === FALSE) {
    die(curl_error($setuploginurl));
}

curl_close ($setuploginurl); 
var_dump ($loginp);
Perennial answered 9/5, 2015 at 21:14 Comment(2)
You should use 2 for CURLOPT_SSL_VERIFYHOST, not 1.Artless
I don't know if this is automatic but switching to PHP v 5.6.33 solved my problem.Batangas
C
56

You must use an integer value for the CURLOPT_SSLVERSION value, not a string as listed above

Try this:

curl_setopt ($setuploginurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); // constant NOT string value

http://php.net/manual/en/function.curl-setopt.php

value should be an integer for the following values of the option parameter: CURLOPT_SSLVERSION

One of:

CURL_SSLVERSION_DEFAULT (0)
CURL_SSLVERSION_TLSv1 (1)
CURL_SSLVERSION_SSLv2 (2)
CURL_SSLVERSION_SSLv3 (3)
CURL_SSLVERSION_TLSv1_0 (4)
CURL_SSLVERSION_TLSv1_1 (5)
CURL_SSLVERSION_TLSv1_2 (6)
Circassia answered 3/10, 2015 at 19:50 Comment(4)
you can still use CURL_SSLVERSION_TLSv1_2 - just needs to be a constant, i.e., not in quotes. curl_setopt ($setuploginurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); works for me.Suricate
CURL_SSLVERSION_TLSv1_2 this is available from php 5.5.19, in php 5.3 it is not working.Vladimar
TX SO MUCH for posting this... HELPED ME!Anastos
@KavinD the constant was first added to PHP in versions 5.5.19 and 5.6.3.Guth
O
29

TLS 1.1 and TLS 1.2 are supported since OpenSSL 1.0.1

Forcing TLS 1.1 and 1.2 are only supported since curl 7.34.0

You should consider an upgrade.

Ovoviviparous answered 9/5, 2015 at 21:30 Comment(7)
Curl also only added supported to TLS 1.2 at version 7.34.0Sitsang
Upgrading to OpenSSL 1.0.1 solved a similar problem for me.Serpasil
Had to yum update nss openssl curl to get it working on Centos 6.4.Chronograph
@LPPapillon Thanks a lot! :) That fixed the error for me as well :)Osmometer
@hannele's statement is incorrect. Libcurl with lower version than 7.34.0 support TSL 1.2.Hearten
@Hearten I linked to the documentation -- do you have another source?Sitsang
@hannele the documentation you specified is for forcing tls 1.2. Libcurl supports this protocol in earlier versions.Hearten
A
15

I has similar problem in context of Stripe:

Error: Stripe no longer supports API requests made with TLS 1.0. Please initiate HTTPS connections with TLS 1.2 or later. You can learn more about this at https://stripe.com/blog/upgrading-tls.

Forcing TLS 1.2 using CURL parameter is temporary solution or even it can't be applied because of lack of room to place an update. By default TLS test function https://gist.github.com/olivierbellone/9f93efe9bd68de33e9b3a3afbd3835cf showed following configuration:

SSL version: NSS/3.21 Basic ECC
SSL version number: 0
OPENSSL_VERSION_NUMBER: 1000105f
TLS test (default): TLS 1.0
TLS test (TLS_v1): TLS 1.2
TLS test (TLS_v1_2): TLS 1.2

I updated libraries using following command:

yum update nss curl openssl

and then saw this:

SSL version: NSS/3.21 Basic ECC
SSL version number: 0
OPENSSL_VERSION_NUMBER: 1000105f
TLS test (default): TLS 1.2
TLS test (TLS_v1): TLS 1.2
TLS test (TLS_v1_2): TLS 1.2

Please notice that default TLS version changed to 1.2! That globally solved problem. This will help PayPal users too: https://www.paypal.com/au/webapps/mpp/tls-http-upgrade (update before end of June 2017)

Argumentative answered 8/3, 2017 at 23:9 Comment(1)
Just wanted to add that you need to restart apache after this. ThanksExserviceman
A
2

TLS 1.2 is only supported since OpenSSL 1.0.1 (see the Major version releases section), you have to update your OpenSSL.

It is not necessary to set the CURLOPT_SSLVERSION option. The request involves a handshake which will apply the newest TLS version both server and client support. The server you request is using TLS 1.2, so your php_curl will use TLS 1.2 (by default) as well if your OpenSSL version is (or newer than) 1.0.1.

Abash answered 27/4, 2018 at 9:16 Comment(0)
B
1

To force to specific tls version we need to useCURL_SSLVERSION_MAX_TLSv... not CURL_SSLVERSION_TLSv...

curl_setopt ($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_MAX_TLSv1_2);

modified script from @Tomasz Dobrzyński

<?php

function get_tls_version($tlsVersion)
{
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, "https://www.howsmyssl.com/a/check");
    curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($c, CURLOPT_SSLVERSION, $tlsVersion);
 
    $rbody = curl_exec($c);
    if ($rbody === false) {
        $errno = curl_errno($c);
        $msg = curl_error($c);
        curl_close($c);
        return "Error! errno = " . $errno . ", msg = " . $msg;
    } else {
        $r = json_decode($rbody);
        curl_close($c);
        return $r->tls_version;
    }
}

echo "OS: " . PHP_OS . "\n";
echo "uname: " . php_uname() . "\n";
echo "PHP version: " . phpversion() . "\n";

$curl_version = curl_version();
echo "curl version: " . $curl_version["version"] . "\n";
echo "SSL version: " . $curl_version["ssl_version"] . "\n";
echo "SSL version number: " . $curl_version["ssl_version_number"] . "\n";
echo "OPENSSL_VERSION_NUMBER: " . dechex(OPENSSL_VERSION_NUMBER) . "\n";

echo "\nTesting CURL_SSLVERSION_TLSv... (not forced)\n";
echo "Result TLS_Default: " . get_tls_version(CURL_SSLVERSION_DEFAULT) . "\n";
echo "Result TLS_v1_1: " . get_tls_version(CURL_SSLVERSION_TLSv1_1) . "\n";
echo "Result TLS_v1_2: " . get_tls_version(CURL_SSLVERSION_TLSv1_2) . "\n";
echo "Result TLS_v1_3: " . get_tls_version(CURL_SSLVERSION_TLSv1_3) . "\n";

echo "\nTesting CURL_SSLVERSION_MAX_TLSv...\n";
echo "Result MAX_Default: " . get_tls_version(CURL_SSLVERSION_MAX_DEFAULT) . "\n";
echo "Result MAX_TLS_v1_1: " . get_tls_version(CURL_SSLVERSION_MAX_TLSv1_1) . "\n";
echo "Result MAX_TLS_v1_2: " . get_tls_version(CURL_SSLVERSION_MAX_TLSv1_2) . "\n";
echo "Result MAX_TLS_v1_3: " . get_tls_version(CURL_SSLVERSION_MAX_TLSv1_3) . "\n";

Results

OS: WINNT
uname: Windows NT 10.0 build 19043 (Windows 10) AMD64
PHP version: 7.4.29
curl version: 7.70.0
SSL version: OpenSSL/1.1.1l
SSL version number: 0
OPENSSL_VERSION_NUMBER: 101010cf

Testing CURL_SSLVERSION_TLSv... (not forced)
Result TLS_Default: TLS 1.3
Result TLS_v1_1: TLS 1.3
Result TLS_v1_2: TLS 1.3
Result TLS_v1_3: Error! errno = 35

Testing CURL_SSLVERSION_MAX_TLSv...
Result MAX_Default: TLS 1.3
Result MAX_TLS_v1_1: TLS 1.1
Result MAX_TLS_v1_2: TLS 1.2
Result MAX_TLS_v1_3: TLS 1.3
Bonn answered 6/8, 2022 at 0:23 Comment(0)
M
0

Replace following

curl_setopt ($setuploginurl, CURLOPT_SSLVERSION, 'CURL_SSLVERSION_TLSv1_2');

With

curl_setopt ($ch, CURLOPT_SSLVERSION, 6);

Should work flawlessly.

Morton answered 4/11, 2016 at 11:0 Comment(1)
Don't do this. You're hardcoding an integer that is meaningless to a person reading your code. Instead...just remove the apostrophes and use the constant.Crossbones

© 2022 - 2024 — McMap. All rights reserved.