Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force a certain TLS version in a PHP stream context for the ssl:// transport?

Tags:

php

ssl

How can I force TLSv1.0 in a PHP stream context when trying to access an https URL?

I’m looking for something along the lines of this:

$context = stream_context_create(
  array(
    'ssl' => array(
      'protocol_version' => 'tls1',
    ),
  ));
file_get_contents('https://example.com/test', false, $context);

Background

Actually I’m facing an issue in Ubuntu 12.04 when working with PHP’s SoapClient. Unfortunately, the server I’m trying to connect to does only support SSLv3.0/TLSv1.0 and fails on the default TLSv1.1 negotiation. Therefore I’d like to explicitly set the protocol of the ssl:// transport to TLSv1.0.

like image 340
Chriki Avatar asked May 14 '13 15:05

Chriki


1 Answers

PHP 5.6+ Users

This is a new feature as documented on the PHP 5.6 OpenSSL Changes page.

At time of writing this, PHP5.6 is in Beta1 and thus this isn't overly useful. People of the future - lucky you!

The future is upon us. PHP 5.6 is a thing and its use should be encouraged. Be aware that it deprecates some fairly widely used things like mysql_* functions so care should be taken when upgrading.

Everyone else

@toubsen is correct in his answer - this isn't directly possible. To elaborate on his suggested workarounds... when working around a problem where a supplier's API server wasn't correctly negotiating TLSv1.2 down to its supported TLSv1.0, sending a small subset of ciphers seemed to allow negotiation to complete correctly. Stream context code is:

$context = stream_context_create(
    [
        'ssl' => [
            'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
        ],
    ]
);

SOAP Users

PHP's SOAP client doesn't use curl, nor does it seem to use the default context set with stream_context_set_default. As such, the created context needs to be passed to the SOAPClient constructor in the 2nd parameter as such:

$soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context));

Why those Ciphers?

Running the command openssl ciphers on the server gives you a list of supported ciphers in the above format. Running openssl ciphers -v tells you those that are TLSv1.2 specific. The above list was compiled from all of the non-TLSv1.2 ciphers reported by OpenSSL.

openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'

like image 85
phil-lavin Avatar answered Sep 21 '22 14:09

phil-lavin