Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
TLDR
I can't seem to connect to a https endpoint with a SoapClient. As my wget returns a handshake failure, I suspect that is the cause.
How can I do a SOAP request to this server with PHP?
complete
I'm trying to connect to a SOAP server (https). It doesn't have client certificate authentication, so the connection should be pretty straightforward, but sadly it isn't.
The problem is that I keep getting Could not connect to host messages.
The connection method I'm using is working for another server and I've verified that I'm setting the location for this server correctly (changed it to a server I control, and I'm getting response there). I suspect the problem is with the https/ssl connection to the server.
Situation
I'm creating a PHP Soapclient based on a wsdl I have locally.
If I change the endpoint I get Request and Response headers, and everything works as expected.
the machine is reachable from my server, though there is a problem visible when I use wget to connect to it (see below)
Unable to establish SSL connection.
The problem is also visible with openssl connections (see below)
What I tried.
There are a lot of topics about "no connection!", but there is obviously a lot of "my router was bad, I made a typo in the address etc" going on. I did try these settings that were suggested multiple times, but more as a "cut'n'paste" solution to be sure It didn't work" then out of real reasoning. Some comments from me added
Creating a stream_context for the wsdl options. I have tried
$context = stream_context_create(
array(
'ssl' => array(
'verify_peer' => false, //default
'allow_self_signed' => true, //needs verify peer, tried that
'ciphers'=>"SHA1", // quite random.
),
'https' => array(
'curl_verify_ssl_peer' => false,
'curl_verify_ssl_host' => false
)
)
);
$options['stream_context'] = $context;
(first only the ssl options with verify_peer and allow_self_signed. Then I added the https array, then finally I added the ciphers key to ssl.)
I found a reference to this bug, but 1) I'm not getting that warning, 2) it seems to be proxy-related and 3) My version shouldn't have the bug anymore. I'm running php 5.3.10
When I try to wget the url, I get:
wget https://[[servername]]/SOAP
Resolving [[servername]] ([[servername]])... xxx.xxx.xxx.xxx
Connecting to [[servername]]([[servername]])|xxx.xxx.xxx.xxx|:443... connected.
OpenSSL: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
If I try to connect with openssl, I get this:
$ openssl s_client -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
SSL3 alert read:fatal:handshake failure
SSL_connect:error in unknown state
3074463944:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:724:
but if I force ssl3, I get an expected result
$ openssl s_client -ssl3 -connect [[server]]:443 -state
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
**happy certificate stuff. this is good**
Protocol : SSLv3
Cipher : DHE-RSA-AES256-SHA
**more happy certificate stuff. **
I have tried to add the curl-wrapper from this question with ssl_version set to 3 (as this seems to work on the openssl command above). That wrapper does discard some of the parameters, so I'm not sure how complete this would be. Further, I still get a handshake error, unless I explicitly set checking to false. If I do that (see below), I get an empty response.
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
Causes
As said above, I suspect the ssl handshake, but I have no clue how to fix it. I don't suspect issues with the wsdl or the client-creation, as the connection does work with another wsdl, the same wsdl with a different location set etc. It is purely this (https) endpoint that's giving me headaches.
Extra tests.
Just as the test above with the curl wrapper I tried sending a minimal soap envelope as #halfwarr seemed to suggest in the comments. Als returns an empty response.
So with above it seems that I do have a method to squeeze an http 204 out of the server, but that's hardly success. But it could be a second problem? Not sure.
I am supposing that I need to try and force the ssl3, but I have no idea how (and this could be the wrong path as well so I'm trying to not have an XY problem here :)
Interesting. Try adding this:
wget https://[[SERVER]]/soap/ —post-file=request.xml —header=”Content-Type: text/xml” -O response.xml
This will save the result as a file named response.xml.
The latest version PHP 5.5.3 will allow you to set the SSL Version. I've seen others that have been able to use a stream_context but, I was unable to get that work as well.
As a work around and fail safe, I used a catch to grab the soap envelope request (similar to what you tested above):
$xml = $client->__getLastRequest()
and send via curl:
curl_setopt($ch, CURLOPT_SSLVERSION, 3);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
That's allowing me to at least move forward.
Have you enabled php_openssl.dll in your php.ini?
Reference:
PHP SOAP cannot connect to an SSL WSDL source
Related
I'm running the next script from my local host and the production server, and Im getting different outputs. Anyone knows why am I getting that false from my localhost?
<?php
$host = 'ssl://mail.companyname.org';
$port = 993;
$error = 0;
$errorString = "";
var_dump(fsockopen($host, $port, $error, $errorString, 30));
var_dump($errorString);
var_dump($error);
Local host output:
bool(false)
Production server output:
resource(4) of type (stream)
UPDATE: after the comments/answer I have modified the code and now Im getting this output on my local host:
PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL
Error messages: error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify failed in
/tmp/test.php on line 7 PHP Warning: fsockopen(): Failed to enable
crypto in /tmp/test.php on line 7 PHP Warning: fsockopen(): unable to
connect to ssl://mail.twmdata.org:993 (Unknown error) in /tmp/test.php
on line 7 bool(false) string(0) "" int(0)
it seems this is problem with server certificate :
first you can check if your server certificate and its chains are valid by this:
https://www.sslshopper.com/ssl-checker.htm
if somethings were wrong in ssl-checker?
you can try to correct SSL certificate configs in companyname.org
if you succeed and error was persists ?
you have to add Certificate files manually.
if you have a self-signed certificate:
you have to add Certificate files manually.
if you dont have certificate nor you dont care about man-in-the-middle attack,
you can still use SSL without Certificate.
turn off php fsock Certificate check (not recommended)
its recommended to have a certificate at least a self-signed. if you have a self-signed try 1 solution.
I have found the Problem
You have exposed your Domain name in your PHP Warning Log, so i have checked your domain SSL.
after i check your company`s domain certificate using this tool:
https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org
it had 2 errors with your certificates:
This certificate has expired (0 days ago). Renew now.
None of the common names in the certificate match the name that was entered (twmdata.org). You may receive an error when accessing this site in a web browser.
so it seems you have to renew your certificate first
Update:
i have found this answer maybe helpful
https://stackoverflow.com/a/40962061/9287628
it suggested to use
stream_context_create(['ssl' => [
'ciphers' => 'RC4-MD5'
]])
as #ChrisHaas suggested connecting with stream_context_create and stream_socket_client brings you a lot of option if you want to dictate the cert directory or you want to turn off certificate check.
Per the documentation for fsockopen
The function stream_socket_client() is similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.
Basically, fsockopen is very low-level but without many options, or, arguably, "sane defaults".
Instead, you can switch to stream_socket_client which will allow you to specify a context as the last parameter, and that object has many options, including a dedicated one with over a dozen options specific to SSL. The object created from this function is compatible with fwrite and other functions, so it should do everything you are hoping for.
$context = stream_context_create([/*Options here*/]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Now, what options should you use?
The worst option that might work is probably verify_peer. I say "worst" because you are throwing away the verifiability part of SSL/TLS and only using it for encryption, and doing this will make you susceptible to MitM attacks. However, there's a place and time for this, so you could try it if the other options are too complicated.
$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Instead, I'd recommend using either cafile or capath which do the same thing except the former is for a file while the latter is for a directory.
$context = stream_context_create(['ssl' => ['verify_peer' => true, 'cafile' => '/path/to/file']]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
What certs should you use? We use this library to pull in recent CA files on a periodic basis, very convenient. There's a little bit of setup that's per-project but once you get it it goes pretty fast. See this for pulling in a CA file at a well-known location.
One other last option is local_cert which you can use with a PEM file that holds the certificate and private key from the server, if you have access to that.
EDIT
The cert on mail.twmdata.org:993 is different than the web server's cert that other people are talking about, which is generally a best practice. You can inspect that cert using:
openssl s_client -connect mail.twmdata.org:993 -servername mail.twmdata.org
If you do that, you'll see that the server has a self-signed cert which you can get around by setting the verify_peer option to false.
Remove the # symbol. You are hiding error messages that might tell you what the problem is. You should also set a variable in the errorno argument to fsockopen() and echo it for debugging.
My guess would be that you haven't installed PHP with SSL support on your local server. See here.
Companyname.org might also block requests from your local server that are allowed from the production server.
I have read all the internet and tried almost all solutions, nothing works.
If I run curl http://... site, it works but if i run https://... it doesn't.
I' running centos 7 with php 5.6
Nothing happens also if I try the famous answer with
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
The only thing that can help me getting the site is
curl -4svo/dev/null --ciphers ecdhe_ecdsa_aes_128_sha https://.....
however since i need to send my headers, it is not a solution, i need something compatible with the curl_setopt.
UPDATE ERROR
I get this: curl: (35) Cannot communicate securely with peer: no
common encryption algorithm(s).
i think , this problem is caused by the version of cURL not supporting ECC 256 bit SSL certificates and the ECDSA signature algorithm (which is used by CloudFlare). You can test to see if your version of cURL supports this encryption by running:
curl -1IsS --ciphers ecdhe_ecdsa_aes_128_sha https://sslspdy.com
If you get the following, then your cURL is out of date:
curl: (59) Unknown cipher in list: ecdhe_ecdsa_aes_128_sha
This is the magic line!
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'ecdhe_ecdsa_aes_128_sha');
I have an ecommerce website that has been running for several months with no code changes (and for several years with only minimal changes to the card processing path). I now have a problem where when first opening a connection to the credit card processor secure server, the connection fails. On a second (or third, or fourth, etc.) attempt the connection succeeds. After some length of time--perhaps 5 minutes--the initial connection will fail again and subsequent connections will succeed.
Sample code that comes from the credit card processor's PHP API file:
$url = 'https://esplus.moneris.com:443/gateway_us/servlet/MpgRequestArray';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$dataToSend);
curl_setopt($ch,CURLOPT_TIMEOUT,$gArray[CLIENT_TIMEOUT]);
curl_setopt($ch,CURLOPT_USERAGENT,$gArray[API_VERSION]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
$response=curl_exec ($ch);
if(!$response) {
print curl_error($ch);
print "\n";
print curl_errno($ch);
print "\n";
} else {
print "Success\n";
}
Output:
% php tester_curl.php
error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
35
% php tester_curl.php
Success
% php tester_curl.php
Success
% php tester_curl.php
Success
There are some similar questions, but I haven't been able to resolve the problem and I do not see any with the same error message and symptom of subsequent connection attempts succeeding after an initial fail, e.g.:
Unable to establish SSL connection, how do I fix my SSL cert?
curl errno 35 (Unknown SSL protocol error in connection to [secure site]:443) (same error message)
How to fix cURL SSL connection timeout that only happens the first time the script is called (different error msg, but SSL connections fails first attempt, subsequently succeeds)
The server is kind of broken. It does support TLS1.2 and TLS1.0, but not TLS1.1 (replies with TLS1.0 which is ok). This is usually not a problem unless you have client code which tries to enforce specific protocols by excluding others.
The behavior you describe looks like a client which downgrades the connection on failed connection, keeps this downgrade cached for a while but retries with the originally failed version again after some time. To trace the problem down:
check if the problem is also with other servers
check if other clients have the problem with the same server
check the underlying implementation. Curl can use GnuTLS, NSS, OpenSSL and maybe more. From the error message it looks like OpenSSL, but which version?
check for any middlebox (firewall, load balancer...) in the path to the server which might cause problems
do a packet capture and post it here in a form usable with wireshark (e.g. cloudshark)
For more information on how to debug this kind of problems and which additional information would be useful check http://noxxi.de/howto/ssl-debugging.html#aid_external_debugging
I had the exact thing happen with a client using an old VirtualMerchant gateway. It started failing at 5:00 PM on a Monday and magically started working again at 10 AM the next day.
Whether on the command line via openssl, or curl, or through curl in PHP the connection would fail the first time and then if you ran the same command a second latter it would work.
I tried forcing IPv4 (instead of IPv6), setting timeouts, forcing different protocols, downgrading openssl, etc, and none of it work.
The assumption is that this was something DNS and/or server related on the gateway side because nothing we did fixed it and it fixed itself.
We were running an older openssl that only supported up to TLS 1.1, but it was working and then it started working again, so it wasn't only our client. Though, the age of our client must have been part of the issue because other newer clients didn't experience the "first attempt failure" during the same window of time.
Long story short, if this happens it's probably not YOU (besides you have an older OpenSSL) and the other gateway/server you're calling likely will possibly need to fix/tweak something for it to start working again.
Keep in mind, openssl is part of the Linux core packages, so you can't simply upgrade openssl without serious risk of messing up your server. You'll have to upgrade to a newer version of the operating system to get a more modern openssl.
All of a sudden, my PHP cURL implementation that access sites over SSL stopped working. After some digging around in the cURL response headers I discovered that the issue was a result of cURL not liking the sites SSL cert, giving the error:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Now I didn't test it with other sites and I know there are solutions to add Mozilla's certs to cURL. But to get stuff to work I simply added a new cURL option to disable SSL validity checks (CURLOPT_SSL_VERIFYHOS).
But I am still confused as to how this would stop working in just one day. It worked yesterday. The cert on the site didn't change and it is still a valid, unexpired, Verisign-issued cert.
Had this happen to me last month as well, and the only reason was that the SSL certificate in question was expired. So I just renewed it and the curl ssl link worked again. If you happen to deal with self-signed certificates it's the same deal btw, you either import it or switch of the verification.
That's the only thing I can think off but you state you already verified that...weird. Any chance to take a peek at the site's certificate or is it private? If you haven't changed anything it's almost certainly that something happened to the SSL certificate.
Try These two options in curl
CURLOPT_SSL_VERIFYPEER, FALSE
CURLOPT_SSL_VERIFYHOST, 2
I am using the latest Janrain openid library example and the discovery process seems to work well with Yahoo, myopenid.com and others...
But I am stuck with Google endpoint (https semicolon //www.google.com/accounts/o8/id). Consumer.php just returns a 406 apache error, before I am redirected to google's page.
All my installation is available here :
http://www.coplango.com/vendor/openid/examples/
Click on consumer to try the consumer example, but discovery.php fails the same way,proving it happens during discovery...
You can also check detect.php to check my installation - The HTTP fetching test fails with a 503 because it tries to reach an address which returns a 503. Rest is fine.
I supposed it was down to php-yadis specifying Accept: application/xrds+xml header but I checked the code and other types are also accepted such text/html and application/xhtml+xml.
Anyone came accross this?
Any clue?
Thank you very much!
Ok,
I have investigated further and it seems to be down to my provider, who returns a 406 error if any string containing the death word "/id" is passed as GET parameter. Took me days to figure out it was not down to openid !!
For info I am using PlanetHoster, if anyone else ever comes accross this. I have sent them a ticket request and waiting for their answer.
running the consumer example at my machine, i get the following error:
Got no response code when fetching https://www.google.com/accounts/o8/id
CURL error (60): SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
this means curl fails verifying google's https server certificate. you can workaround this by either providing curl with CA certificates to verify google's certificate via CURLOPT_CAINFO/CURLOPT_CAPATH, or - easier - stop validating the cert via CURLOPT_SSL_VERIFYPEER. the following change in Auth/Yadis/ParanoidHTTPFetcher.php accomplishes latter for me:
--- ParanoidHTTPFetcher.php.orig 2009-04-22 02:31:20.000000000 +0800
+++ ParanoidHTTPFetcher.php 2009-09-30 22:35:24.093750000 +0800
## -127,6 +127,9 ##
Auth_OpenID_USER_AGENT.' '.$curl_user_agent);
curl_setopt($c, CURLOPT_TIMEOUT, $off);
curl_setopt($c, CURLOPT_URL, $url);
+
+ // don't verify server cert
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_exec($c);
of course, your curl installation must also support ssl - check your phpinfo(). also, if CURLOPT_SSL_VERIFYPEER is disabled, CURLOPT_SSL_VERIFYHOST may also need to be TRUE or FALSE.
see also http://www.openrest.eu/docs/openid-not-completely-enabled-for-google.php (via the Related Why doesn't Google OpenID provider work with PHP-OpenId on my server?).
SOLUTION:
In the .htaccess file put
SecFilterEngine Off