49

In my PHP app I use PHP's CURL and openssl, to connect and talk using SOAP. Until now, remote server supported SSL and TLS but because of "poodle" bug, admin decided to disable SSL and use TLS only. SSL is supported until the end of January.

I changed my code by adding:

curl_setopt($objCurl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);

That in theory should force curl to use TLSv1.2.

But that's theory - I need to verify that it actually uses TLS - is there any method for that? There is a method called curl_getinfo(), but info it returns is not useful for me:

[url] => https://www.example.com/soap/MessagingPort
[content_type] => text/xml;charset=utf-8
[http_code] => 200
[header_size] => 293
[request_size] => 882
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.164487
[namelookup_time] => 3.4E-5
[connect_time] => 3.4E-5
[pretransfer_time] => 0.000122
[size_upload] => 604
[size_download] => 178
[speed_download] => 1082
[speed_upload] => 3672
[download_content_length] => 178
[upload_content_length] => 604
[starttransfer_time] => 0.164477
[redirect_time] => 0
starball
  • 20,030
  • 7
  • 43
  • 238
kayo
  • 642
  • 1
  • 6
  • 10
  • You can examine the handshake with some sort of network sniffer, or if you can, disable SSL and TLS 1.0 and 1.1 on the server so it *has* to connect with TLS 1.2. – vcsjones Jan 12 '15 at 15:00
  • 1
    Script works on a shared hosting so there is no way to sniff it. I already forced Apache on my dev server to use TLS and it works but I have no way to check it in production. After a few years of using php you start not to take everything for granted. I still need a way to to get "you are using TLS" on screen. I also had a problem on my Debian with CURL_SSLVERSION_TLSv1_2 not being defined and had to change the line to: curl_setopt($objCurl, CURLOPT_SSLVERSION, 6); – kayo Jan 13 '15 at 08:43

3 Answers3

107

Short Answer

Make a request with curl to https://www.howsmyssl.com/

<?php 
$ch = curl_init('https://www.howsmyssl.com/a/check');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);

$json = json_decode($data);
echo $json->tls_version;

that should output what TLS version was used to connect.

Digging Deeper

Curl relies on the underlying OpenSSL (or NSS) library to do the negotiation of the secure connection. So I believe the right question to ask here is what is the OpenSSL library capable of. If it can handle a TLS connection, then curl can handle a TLS connection.

So how to figure out what the openssl (or NSS) library is capable of?

<?php    
$curl_info = curl_version();
echo $curl_info['ssl_version'];

which is going to dump out something like

OpenSSL/1.0.1k

Then you can go and have a look at the release notes for that version and see if it includes TLS support.

OpenSSL Release notes - https://www.openssl.org/news/changelog.html

NSS Release notes - https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/NSS_Releases

Spoiler Alert

  • openssl includes support for TLS v1.1 and TLS v1.2 in OpenSSL 1.0.1 [14 Mar 2012]
  • NSS included support for TLS v1.1 in 3.14
  • NSS included support for TLS v1.2 in 3.15
Ricardo Martins
  • 5,702
  • 3
  • 40
  • 59
Jeff Richards
  • 2,032
  • 2
  • 18
  • 23
  • I did the curl to howsmyssl and it returns `error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version`. It's rejecting ssl v2/3? https://twitter.com/jmhodges/status/420614636606468096. What do I do in this case? – meder omuraliev Apr 29 '16 at 18:13
  • With the second php logic, my server indicates "NSS/3.19.1 Basic ECC" which implies support for TLS v1.2, however the first php logic returned "TLS 1.0"? What do I need to do to support TLS 1.2? – panofish Jun 01 '16 at 19:45
  • Nevermind to my previous comment... I simply added the following code in php logic #1 and now I get TLS 1.2 `curl_setopt($ch, CURLOPT_SSLVERSION, 6);` – panofish Jun 01 '16 at 19:53
  • It may be require to add `curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');` ref http://stackoverflow.com/questions/9774349/php-curl-not-working-with-https – Amit Garg Feb 17 '17 at 09:01
  • I received such error: `SSL certificate problem: unable to get local issuer certificate`. This was fixed (temporary) by `curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);` – Andron Jun 13 '17 at 08:45
  • This answer is waaaaay overrated firstly because the code solution only tells you what tsl version is used to connect to howsmyssl.com -- and it relies on that remote server to report the protocol. This 'answer' it totally unhelpful if you are trying to evaluate your application's connection method when connecting to a payment gateway, for instance. – S. Imp Feb 14 '18 at 20:47
  • Hi, I add a line on the code, to check TLS version response: `curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);` – Gustavo Emmel Jan 10 '20 at 18:13
5

Use https://tlstest.paypal.com:

For example:

$ curl https://tlstest.paypal.com/
ERROR! Connection is using TLS version lesser than 1.2. Please use TLS1.2

$ ./src/curl https://tlstest.paypal.com/
PayPal_Connection_OK
kbulgrien
  • 4,384
  • 2
  • 26
  • 43
3

If you want to test which protocol is being used for a specific url (like a payment api endpoint) you can log curl's verbose output and see it there. Here's a quick example:

$url = 'https://example.com/';
$ch  = curl_init($url);
$out = fopen('php://temp', 'w+');

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $out);
curl_exec($ch);
curl_close($ch);
rewind($out);

$debug = stream_get_contents($out);

if (preg_match('/SSL connection.*/', $debug, $match)) {
    echo '<pre>' . $url . PHP_EOL . $match[0];
}

For me that gives output like:

https://example.com/
SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384