So I spent ~20 hours of time isolating and working around an old, as-yet-unfixed openssl bug in Ubuntu 12.04. When using this code to connect to an HTTPS/SSL/TLS1.0 SOAP server:
ini_set( "soap.wsdl_cache_enabled", "0" );
$objSoapClient = new SoapClient(
'https://EXAMPLE.COM/EXAMPLEWSDLPATH',
array ( "encoding"=>"ISO-8859-1",
"trace"=>1,
"exceptions"=>0,
"connection_timeout"=>2000 ));
You get the following errors:
me@my-desktop:~$ php prop-soaptest.php
PHP Warning: SoapClient::SoapClient(): SSL: crypto enabling timeout in /home/me/prop-soaptest.php on line 9
PHP Warning: SoapClient::SoapClient(): Failed to enable crypto in /home/me/prop-soaptest.php on line 9
PHP Warning: SoapClient::SoapClient(https://EXAMPLE.COM/EXAMPLEWSDLPATH): failed to open stream: operation failed in /home/me/prop-soaptest.php on line 9
PHP Warning: SoapClient::SoapClient(): I/O warning : failed to load external entity "https://EXAMPLE.COM/EXAMPLEWSDLPATH" in /home/me/prop-soaptest.php on line 9
PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://EXAMPLE.COM/EXAMPLEWSDLPATH' : failed to load external entity "https://EXAMPLE.COM/EXAMPLEWSDLPATH" in /home/me/prop-soaptest.php on line 9
If you try using Curl, you get an error like this:
curl: (35) Unknown SSL protocol error in connection to https://EXAMPLE.COM/EXAMPLEWSDLPATH:443
The only workaround I found for trying to use PHP’s SoapClient with an HTTPS server that only supports TLS 1.0, is below. Other fixes like using curl on the command line with -ssl3 or –cipher RC4-SHA arguments do work for me, but they don’t fix SoapClient, and it was quite a journey figuring out how to get it working for SoapClient.
Thanks to someone saving my butt in IRC, I finally got the below PHP code to work for my use case, which is communicating with remote SSL SOAP services that only support SSLv2, SSLv3, or TLS1.0 (and not TLS 1.1, TLS 1.2) especially using RC4-SHA ciphers. The ciphers option in a new stream_context is the important bit to make the code work on Ubuntu 12.04 or libssl1.0.0_1.0.1 / openssl 1.0.1:
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA')
);
ini_set( "soap.wsdl_cache_enabled", "0" );
$objSoapClient = new SoapClient(
'https://EXAMPLE.COM/EXAMPLEWSDLPATH',
array ( "encoding"=>"ISO-8859-1",
'stream_context' => stream_context_create($opts),
"trace"=>1,
"exceptions"=>0,
"connection_timeout"=>2000 ));
The trick is to substitute SoapClient’s normal context with your own context + SSL options:
http://www.php.net/manual/en/soapclient.soapclient.php
http://www.php.net/manual/en/context.php
http://www.php.net/manual/en/function.stream-context-create.php
This site was invaluable in testing what exact ciphers/technologies are actually supported by the remote server: https://www.ssllabs.com/ssltest/index.html
Good luck!
dude, thank you so much for this blog entry, you saved us 20+ hours of time 🙂 letz drink a beer
Dude you are a true life saver!
you saved my ass
I also had this problem, thanks to you I didn’t have to pull my hair out or jump off a high building.
THANK YOU SIR!!!
Thanks!
Thanks Thanks Thanks!!! Saved me loadz of time 🙂
WHOA, thank you very much! This solved my issue!
Thanks!
Absolute legend!
Great job! i had the same problem. You saved my time brother!
YEAAAH!!! IT WORKS! TKS A LOT MAN!
You just saved my night!!
Awesome! Thank you very much!
Worked perfectly!
Excellent, that did it!
8 hours of round and round until I found this. This was a massive life saver!
thanks m8
i have this problem on cent os. how can i me fix the problem on guzzle packegae
I’m unsure how to fix this in Guzzle but look around for the ability to customize Guzzle’s SSL settings because that’s basically what I was doing here.