SoapClient "Could not connect to host" exception with one WSDL API - php

I have a problem with one WSDL connection with API, after moving to a new OVH VPS machine, so it's maybe some kind of strange misconfiguration.
Other WSDL that I use with SoapClient, work fine, without problems. I'm able to use file_get_contents on the address, but when I use SoapClient I gives a exception "Could not connect to host", when trying to use a procedure from that API.
Any ideas? I've tried some stream_context with some SSL options. What's the funniest, on the other OVH VPS is working fine.
System is Debian 8 with PHP 5.6.19 onboard.
Addresss of the WSDL is here: https://api-test.paczkawruchu.pl/WebServicePwR/WebServicePwRTest.asmx?WSDL

After consultation with WSDL provider, and checking logs on both sides, we found the anwser. It looks like PHP 5.6 have some problems, and you have to change parameters to SOAP 1.2. This resolved finally the problem. Resolution could be found here, in first comment:
SOAP PHP fault parsing WSDL: failed to load external entity?
// options for ssl in php 5.6.5
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA', 'verify_peer'=>false, 'verify_peer_name'=>false)
);
// SOAP 1.2 client
$params = array ('encoding' => 'UTF-8', 'verifypeer' => false, 'verifyhost' => false, 'soap_version' => SOAP_1_2, 'trace' => 1, 'exceptions' => 1, "connection_timeout" => 180, 'stream_context' => stream_context_create($opts) );
$oSoapClient = new SoapClient ( $url . "?WSDL", $params );

Related

php SoapClient fails to connect, but command line curl call works

I have a LAMP server (#1) that is communicating via soap with another server (#2) via WSDL. If I issue a curl call on the command line of server 1 to the URL of server 2, it works fine and get the appropriate WSDL response, but a php soapclient to the same URL is getting a "failed to load external entity" error. This was working before when we had a self signed certificate on server 2, but quit working about the same time we upgraded to a CA certificate.
Funny thing is this server is load balanced with another server at a different location (different OS, but same php code/database) and the second server isn't having any issues at all.
Here is the code I am using for the soap client:
function getSoapClient(){
ini_set("soap.wsdl_cache_enabled", 0);
// standard soap client for application service
$post_url = lum_getString("[CAMPAIGN_POST_URL]").
"?enterprise=".lum_getString("[CAMPAIGN_ENTERPRISE]").
"&company=".lum_getString("[CAMPAIGN_COMPANY]");
$options = array(
'trace' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => 1,
'verifypeer' => false,
'verifyhost' => false,
'allow_self_signed' => true,
'login' => lum_getString("[CAMPAIGN_POST_ID]"),
'password' => lum_getString("[CAMPAIGN_POST_LC]"),
);
$context = stream_context_create(
array(
'user_agent' => 'PHPSoapClient',
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
),
'https' => array(
'curl_verify_ssl_peer' => false,
'curl_verify_ssl_host' => false,
)
)
);
$options['stream_context'] = $context;
$client = new SoapClient($post_url."&wsdl",$options);
return $client;
}
The curl and soapclient are using the same ports so it shouldn't be a firewall issue.
Any help in identifying the issue or helping me figure what is wrong is greatly appreciated.
Turns out it appears to be a firewall issue. I opened up all access from server 1 to server 2 and things started working. Not too sure what the issue was. I reduced the options to just the login and password, it's still working. Firewalls are often the answer.
Any ideas regarding the firewall, the correct ports, and why it wasn't working is much appreciated.
Why was cURL working and SOAP not?

Error PHP 7.0 and SSL TLS 1.0

Im having a problem with SoapClient and PHP 7.0 to parse wsdl.
Im getting this error:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://ws.ocasa.com/testecommerce/service.asmx?wsdl' : failed to load external entity "https://ws.ocasa.com/testecommerce/service.asmx?wsdl"
If you put this URL in a browser you can see the SOAP, and also in SoapUI it works OK.
I'm using laravel 5.4, and my code is:
$client = new \SoapClient('https://ws.ocasa.com/testecommerce/service.asmx?wsdl',
['soap_version'=>SOAP_1_2]);
I noticed that that website is under SSL TLS 1.0. If I change PHP to 5.6, it works perfect, but with PHP 7.0 it does not work.
If I change to this other WSDL:
https://id3check.gb.co.uk/gbportalinternational/aspx/id3check_1b.asmx?WSDL
Everything works fine.
Thank you
you could choose to ignore a bad cert:
$endpoint = new SOAPClient($url,
array(
'soap_version'=>SOAP_1_2,
'stream_context' => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false
)
)
)
)
);
This would be a solution, should you not have access to the soap server to correct the certificate, or be able to elsewise make your server accept the certificate.
This should be the last solution as indeed you ignore all warnings something is wrong

SOAPClient Error: Could not connect to host on PHP 7.0 and Laravel

I am having issues connecting to a WSDL via SOAPClient on my Laravel application in a server with PHP 7.0. I have tested the following code on my local server using PHP 5.6 and it works. Both are running Linux; my local server is running Kubuntu and the other server is running CentOS 7.
var $client;
function __construct(){
ini_set('soap.wsdl_cache_enabled',WSDL_CACHE_NONE);
ini_set('soap.wsdl_cache_ttl', 0);
$this->client = new SoapClient(env('WSDL_SOLMAN02_TEST'),
['login'=>env('SOLMAN_US_TEST'),
'password'=>env('SOLMAN_PSSWD_TEST'),
'cache_wsdl' => WSDL_CACHE_NONE,
'soap_version' => SOAP_1_1,
'ssl_method' => 'SOAP_SSL_METHOD_SSLv3',
'trace' => true,
'exception' => false,
'stream_context'=> stream_context_create(array(
'ssl'=> array(
'verify_peer'=>false,
'verify_peer_name'=>false
)
))
]
);
}
public function updateTicket(Ticket $ticket){
$incident = $this->createTicketObject($ticket);
$params = get_object_vars($incident);
return $this->client->wsdlFunc($params);
}
The funny thing is that when I print dd($this->client->__getFunctions()); the WSDL responds with an array of all the functions that you can call, but when I actually call upon any function, the error is displayed.
I have tried just about everything, from changing every parameter in the connection to changing the php.ini, but nothing has worked. I have downgraded the server to PHP 5.6 and it still doesn't work.
I have also tested WSDL on SOAPUI and it works.
The only difference I find between both environments is that the server with PHP 7.0 has https.
My code was fine, I just had to add the WSDL ip address to /etc/hosts.
I faced the same problem when I upgraded from php v7.2 to v7.3 (docker):
SOAPClient Error: Could not connect to host
I tried the solution proposed by #suecamol but it did not work. Looks like php v7.3 changed something with the ssl security.
The solution, that one of my co-worker found, was to add a proper ssl ciphers encryption:
$arrContextOptions= [
'ssl' => [
'ciphers' => 'AES256-SHA',
]
];
$options = [
...
'stream_context' => stream_context_create($arrContextOptions),
];
$client = new SoapClient('some wsdl url', $options);
Hopefully this can help someone facing this issue.

Disable certificate verification in PHP SoapClient

Summary:
Is there a way to force the built in SoapClient-class in PHP to connect over HTTPS to a server with an invalid certificate?
Why would I want to do that?
I have deployed a new application on a server that has no DNS entry or certificate yet. I want to try connecting to it with a SoapClient before setting up the DNS entry and fixing the certificate, and the most reasonable way to do this seems to be to just make the client ignore the certificate during testing.
Don't I realise that this is a huge security risk?
This is only for testing. When the service goes into production, there will be a valid certificate in place, and the client will be forced to validate it.
SoapClient takes a stream context in its parameters, which you can create yourself. That way you can control almost every aspect of the transport layer:
$context = stream_context_create([
'ssl' => [
// set some SSL/TLS specific options
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
$client = new SoapClient(null, [
'location' => 'https://...',
'uri' => '...',
'stream_context' => $context
]);
Documentation:
stream_context_create() Docs
HTTP context options Docs
SSL context options Docs
The accepted answer works but only in the non-WSDL mode. If you try to use this in the WSDL mode (i. e. you pass a WSDL file url as the first argument) you will face the fact that the stream context is ignored when downloading WSDL files. So if the WSDL file is also located on a server with broken certificate, it will fail, most likely throwing the message failed to load external entity. See more here and here.
As suggested, the simplest way around is to download the WSDL file manually and pass the local copy to the SoapClient. You can download it for example with file_get_contents using the very same stream context from the accepted answer.
Note that you will also have to do this when creating a SoapServer.
The correct list for PHP 5.6.8 is
'ssl' => array('verify_peer_name'=>false, 'allow_self_signed' => true),
"verify_peer"=>false,
"verify_peer_name"=>false,
This is working on php 5.6.x;
$arrContextOptions=stream_context_create(array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
)));
$this->client = new \SoapClient("https://tests.com?WSDL",
array(
//"soap_version" => SOAP_1_2,
"trace" => 1, // enable trace to view what is happening
"exceptions" => 0, // disable exceptions
"cache_wsdl" => 0, // disable any caching on the wsdl, encase you alter the wsdl
"stream_context" => $arrContextOptions
)
);
or if you want you can add to cyrpto method
$arrContextOptions=stream_context_create(array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
));

How to get SSL connection with PHP SOAP extension?

When trying to connect to an SSL endpoint with PHP SOAP extension on Windows I am getting the SoapFault "Could not connect to host". Client certificate is not a requirement of the service.
$sslOptions = array(
'ssl' => array(
'cafile' => "c:/inetpub/wwwroot/eServices/Server_DSA_Public_Certificate.pem",
'allow_self_signed' => true,
'verify_peer' => false,
),
);
$sslContext = stream_context_create($sslOptions);
$clientArguments = array(
'stream_context' => $sslContext,
'trace' => true,
'exceptions' => true,
'encoding' => 'UTF-8',
'soap_version' => SOAP_1_1,
);
$oClient = new WSSoapClient("c:/inetpub/wwwroot/eServices/svc.wsdl", $clientArguments);
// WSSoapClient extends SoapClient to add a WS-Security UsernameToken header
$oClient->__setUsernameToken("myusername", "mypassword");
return $oClient->__soapCall($operation, $request);
I converted to .pem format a self-signed server certificate (.cer) that I was given and am passing that in as 'cacert'.
Am able to access the service perfectly using soapUI with the same wsdl.
Question: Do I need to put the server certificate into some trust store? I did already use Internet Explorer to add it into 'Trusted Root Certification Authorities'.
Question: By passing in 'cacert', is it enough for PHP to know it can trust the server?
Any help or suggestions would be much appreciated.
When I ran the code under Apache (using XAMPP) it worked first time. My problem must have been somewhere in the configuration of IIS or PHP.
Setting cacert was superfluous.

Categories