PHP7 cURL and SOAP request SSL failing - php

I'm using PHP 7.0.25 in a vagrant VM with ubuntu 16.04
I need to make a request to this SOAP API:
https://ws.ocasa.com/testecommerce/service.asmx?wsdl
Both php curl and SoapClient are failing
With SoapClient I'm doing this (also tried with no options at all, and just the cache_wsdl part):
$options = array(
'cache_wsdl' => 0,
'trace' => 1,
'stream_context' => stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
))
);
$wsdl = 'https://ws.ocasa.com/testecommerce/service.asmx?wsdl';
$client = new \SoapClient( $wsdl, $options);
Giving me this error:
[SoapFault]
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"
With php curl I endend getting this error:
Unknown SSL protocol error in connection to ws.ocasa.com:443
I cant get the page from the linux curl command line without a problem (from inside the VM, of course)
curl -I https://ws.ocasa.com/testecommerce/service.asmx?wsdl -v
The SSL connection is using TLS1.0 / RSA_3DES_EDE_CBC_SHA1
I tested adding
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
and also tried adding the CA certs: (also tried adding them in the php.ini)
curl_setopt($ch, CURLOPT_CAINFO, '/vagrant/cacert.pem');
Something very strange is that I can curl some other https sites without problem like secure.php.net usgin php curl.
Also, there is no "http" version available to get rid of the whole SSL problem.
Any ideas? I'm missing some dependency maybe? openssl is installed.
Thanks for your time.

Well, I kinda found a solution...
With curl (the CURLOPT_SSLVERSION makes the difference)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $wsdl);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); // $xml is the envelope (string)
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0);
I couldn't make SoapClient work, even with the SOAP_SSL_METHOD_TLS option.
I'll mark it as resolved, but if some finds how to make it work with SoapClient, that would be the real answer.
This helped me out with making the request (not the ssl part)

Related

What is the correct method of installing Private IP With SSL Certificate Signed by broker from DigiCert

I am connected to a vendor (for accessing their API) through a NAT. I can easily access the APIs through http, now for production, https is required. However, when I make the API request to the vendor's endpoint with https enabled, below is the errors:
When SSL Verification is enabled:
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://xyz.xyz.xyz.xyz:18423/interface//request
When SSL Verification is disabled:
cURL Error #:OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
I have taken the following steps to set up the SSL.
Step 1: I have first generated the SSL Certificate request and private key with openssl as below:-
-
openssl req -new -newkey rsa:2048 -nodes -keyout mycompany.key -out mycompany.csr
NOTE: The FQDN used api.mycompany.com does not exist. My server is accessed through my private IP address within the network only. (The vendor can reach me for a callback through the NAT)
Step 2: I have sent the CSR only to the vendor to sign
Step 3: Vendor signed the request and sent back the following files:
1.mydomain.cer
2.mydomain.p7b
3.broker_vendor_com.crt
4.DigiCertCA.crt
Step 4: I have decoded the mydomain.cer
I Followed Nginx: Create CSR & Install SSL Certificate (OpenSSL)
Step 5: I combined the mydomain.cer and DigitCert.cer into new file bundle.crt
Step 6: I added the bundle.crt and mycompany.key into my nginx server as below
ssl_certificate /etc/ssl/bundle.crt;
ssl_certificate_key /etc/ssl/salaammfbank.key;
I tried disabling the verification and I get the errors stated above. When I make normal curl request on the terminal using
curl -kv https://xyz.xyz.xyz.xyz:18423/interface//request
I can reach the endpoint with valid response status 200.
Below is the php curl request that returns
cURL Error #:OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0
and when verification is enabled
cURL Error #:SSL certificate problem: unable to get local issuer certificate
$url = 'https://xyz.xyz.xyz.xyz:18423/interface//request';
$body = '';
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 40,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => ["Accept: application/json", "Content-Type: application/xml"]
]);
#curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
#curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
What am I missing to be able to reach the vendor endpoints through https from my server?
After a long weekend of trying to figure this out, I was able to hit the vendor endpoint through laravel Http facade to make the request and disabled the verification.
$response = Http::withOptions([
'verify' => false,
])->withBody($this->ParseCreateTransactionXml($data),'text/xml')->post($url);
I have also tested with, and returned expected response using below curl:-
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->ParseCreateTransactionXml($data));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 2);
$response = curl_exec($ch);
I have not made any other changes in the rest of the code. I am not so sure why the code in the question was not working.

PHP Laravel cURL SSL certificate problem: unable to get local issuer certificate

I my project written in Laravel I have method that get number value from server:
public static function getAddressApiBalance()
{
try {
$uri = "https://btczexplorer.blockhub.info/ext/getbalance/t1ZYiG4R4n5gTgUKZRgVpKPzG5FYQXpEqga";
$response = Http::get($uri);
return $response;
...
And when I call this code I get error in my browser:
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)
You can disable ssl verification (not recommended!, but quick and easy for dev) :
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
or with guzzle :
$client = new Client(['verify' => false]);
or you can download a cacert.pem file :
https://curl.haxx.se/ca/cacert.pem
and edit your php ini with the path of cacert :
openssl.cafile=/etc/ssl/cacert.pem
\Illuminate\Support\Facades\Http::withOptions([]) accept guzzlet http options
https://docs.guzzlephp.org/en/stable/request-options.html#verify
In Laravel 8 you can use Http API which is easier but still use Guzzle HTTP client behind the scenes. In that case you can disable certificate validation like this:
$client = Http::withOptions([
'debug' => true,
'verify' => false,
])
->get('https://btczexplorer.blockhub.info/ext/getbalance/t1ZYiG4R4n5gTgUKZRgVpKPzG5FYQXpEqga', [
'parameter1' => '1234567',
'parameter2' =>'890',
]);
Of course debug option is not required to disable ssl checking but it helps with testing. Also parameters are just to show how to add them to the request.
You have 3 options to solve that problem (3 way I know) :
1 -> Download certificate file (https://curl.haxx.se/ca/cacert.pem) and move it to your php file. Edit your php.ini after it for the cerfificate file.
2 -> Use verify option in your Request to disable ssl verification
Http::withOptions([
'verify' => false,
])...
3 -> Find Guzzle Client folder to disable ssl for all request
File Locate : \vendor\guzzlehttp\guzzle\src\Client.php
Function : configureDefaults
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
'http_errors' => true,
'decode_content' => true,
'verify' => app()->env == "local" ? false : true,
'cookies' => false,
'idn_conversion' => true,
];
Normally verify => true as default. If you edit it only for your local, use it as me or you want to disable it for everything you can use as below.
$defaults = [
...
'verify' => false,
...
]

phpbrew php7 throws gnutls_handshake() failed: Illegal parameter

I've compiled php7.1.30 on ubuntu 14.04 successfully.
When I test that peace of code
/ Get cURL resource
$curl = curl_init();
// Set some options - we are passing in a useragent too here
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'https://buy.itunes.apple.com',
CURLOPT_USERAGENT => 'Codular Sample cURL Request',
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => [
'item1' => 'value',
'item2' => 'value2'
]
]);
curl_setopt($curl, CURLOPT_VERBOSE, true);
// Send the request & save response to $resp
$resp = curl_exec($curl);
// Close request to clear up some resources
if (!$resp) {
echo('Error: "' . curl_error($curl) . '" - Code: ' . curl_errno($curl));
echo "\n";
}
curl_close($curl);
I got error Error: "gnutls_handshake() failed: Illegal parameter" - Code: 35
The verbose output is that:
Rebuilt URL to: https://buy.itunes.apple.com/
* Hostname was NOT found in DNS cache
* Trying 17.173.66.180...
* Connected to buy.itunes.apple.com (17.173.66.180) port 443 (#0)
* found 148 certificates in /etc/ssl/certs/ca-certificates.crt
* gnutls_handshake() failed: Illegal parameter
* Closing connection 0
From time to time this works successfully it seems that apple TLS support is not consistent.
However if I build the same code on Ubuntu 18.04 it works 100% and if I run the same code with php 5.5.9 (dist version) again 100% working.
So far I plan to upgrade to ubuntu 18.04 in order to get the working because I fail to overcome above issue. I've tried different /etc/ssl/cert ca files but unsuccessfully.
Help is appreciated.
Unfortunately the only way to get that working in the change openssl-dev lib on ubuntu with the newer one and recompile again.
However I decide to get rid of ubuntu 14.04 in your infrastructure - speed the planned discount of Ubuntu 14 and replace with amazon linux 2.

unable to Curl or SoapClient Any remote_server:8080 port on Directadmin Centos

I am Trying To Connect a Soap Api by php
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA', 'verify_peer'=>false, 'verify_peer_name'=>false)
);
$params = array ('encoding' => 'UTF-8', 'verifypeer' => false, 'verifyhost' => false, 'soap_version' => SOAP_1_1, 'trace' => 1, 'exceptions' => 1, "connection_timeout" => 5, 'stream_context' => stream_context_create($opts) );
$url = "http://x.x.x.x:8080/ws-relay/MessageRelayService?wsdl";
$client =new SoapClient($url,$params);
$result = $client->sendMessageOneToMany(array(
"username" => 'xxxxx',
"password" => 'xxxxx',
"originator" => "50004132311446",
"destination" => $numbers,
"content" => $massage,
));
but it allways got an
SOAP-ERROR: Parsing WSDL: Couldn't load from 'x.x.x.x:8080/ws-relay/MessageRelayService?wsdl";' : failed to load external entity "x.x.x.x:8080/ws-relay/MessageRelayService?wsdl";")
error !
I also Tried to Curl This WSDL but I got
[root#myhost ~]# curl http://x.x.x.x:8080/ws-relay/MessageRelayService?wsdl
curl: (7) Failed to connect to x.x.x.x port 8080: Connection timed out
Error !
so i also tried to curl portquiz.net:8080/ for test and i got timeout again !
is there some rule in firewall that block me to send request to 8080 ports !
how can i unblock it in centos directadmin vps ?
often this happens because that your ip address has been blocked , or there are an issues with the server it self .
for more info about that , libcurl error codes
CURLE_COULDNT_CONNECT (7)
Failed to connect() to host or proxy.
for your command :
curl http://xx.xx.xx.xx:xxxxws-relay/MessageRelayService?wsdl
when executing it in my own pc i got the response normally .
so you will need to use proxy in your SoapClient class
For making an HTTP connection through a proxy server, the options
proxy_host, proxy_port, proxy_login and proxy_password are also
available.
so you will need to add some params to your $params array ass follows :
$params['proxy_host'] = "proxy_ip";
$params['proxy_port'] = "proxy_port";
it's also possible (personally i recommend this) to use procedures libcurl functions or packages built on it.
if you want to use the cli way , so your command may be some thing like this :
curl http://xx.xx.xx.xx:xxxx/ws-relay/MessageRelayService?wsdl -x "ip_address:ip_port"
for socks5 ips
curl http://xx.xx.xx.xx:xxxx/ws-relay/MessageRelayService?wsdl -x "ip_address:ip_port" --socks5

cURL error 35 - Unknown SSL protocol error in connection to api.rkd.reuters.com:443

From development machine (mac) there is no problem connecting via cURL in PHP to this, but in Ubuntu, I get this error. I've tried on a local machine and on an Amazon AWS instance. I've googled and googled and keep coming up to brick walls. There's no firewall restrictions in place, its a complete mystery. php5-curl IS installed in ubuntu, I just don't have any ideas. I ran this command:
curl -v https://api.rkd.reuters.com/api/2006/05/01/TokenManagement_1.svc/Anonymous
and got this output, no clues whatsoever to a solution. OpenSSL is also installed.
* About to connect() to api.rkd.reuters.com port 443 (#0)
* Trying 159.220.40.240... connected
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* Unknown SSL protocol error in connection to api.rkd.reuters.com:443
* Closing connection #0
curl: (35) Unknown SSL protocol error in connection to api.rkd.reuters.com:443
Any ideas welcomed on this
I had this problem, and I fixed it by setting the curl SSL version to version 3
curl_setopt($ch, CURLOPT_SSLVERSION,3);
Apparently the server started requiring SSL version 3, and this setting caused cURL with SSL to start working again.
I had the same problem, unfortunately with a host unwilling to upgrade to php 5.5.
I solved it by creating a new class extending php's SoapClient to use cURL:
/**
* New SoapClient class.
* This extends php's SoapClient,
* overriding __doRequest to use cURL to send the SOAP request.
*/
class SoapClientCurl extends SoapClient {
public function __doRequest($request, $location, $action, $version, $one_way = NULL) {
$soap_request = $request;
$header = array(
'Content-type: application/soap+xml; charset=utf-8',
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: \"$action\"",
"Content-length: " . strlen($soap_request),
);
$soap_do = curl_init();
$url = $location;
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => FALSE,
//CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
//CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
CURLOPT_VERBOSE => true,
CURLOPT_POST => TRUE,
CURLOPT_URL => $url,
CURLOPT_POSTFIELDS => $soap_request,
CURLOPT_HTTPHEADER => $header,
CURLOPT_FAILONERROR => TRUE,
CURLOPT_SSLVERSION => 3,
);
curl_setopt_array($soap_do, $options);
$output = curl_exec($soap_do);
if ($output === FALSE) {
$err = 'Curl error: ' . curl_error($soap_do);
}
else {
///Operation completed successfully
}
curl_close($soap_do);
// Uncomment the following line to let the parent handle the request.
//return parent::__doRequest($request, $location, $action, $version);
return $output;
}
}
Fixed it! It's a known problem with Ubuntu 12.04
These instructions
http://willbradley.name/2012/10/workaround-for-php-error-in-ubuntu-12-04-soapclient-ssl-crypto-enabling-timeout/
-- Cancel that, it just disabled exceptions, this is still not working! HELP!
-- EDIT - HERES HOW I FIXED IT IN THE END!
I upgraded to PHP 5.5 from 5.4.3 and set the following options in my call, which fixed it:
$options = array('ssl_method' => SOAP_SSL_METHOD_SSLv3,'soap_version' => SOAP_1_2);
$sc = new SoapClient('https://my-url.com/call/', $options);
The upgrade was necessary because the constant SOAP_SSL_METHOD_SSLv3 isn't present in PHP versions < 5.5, and unfortunately Ubuntu Server at the time would only allow an upgrade to 5.4.3 through apt-get update php5. I manually installed the later version, and it works fine now.
Error : CURL Error: 35 - OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to httpapi.com:443 (IP: 162.x.x.x & 204.x.x.x)
Incase of WHMCS:
You can contact your host to whitelist the IP address at their end to use their API.
Fixed by adding curl-ca-bundle.crt to the folder next to curl.exe
I'm using Fefora 33 and solutions proposed by other users have not worked for me. In my case the problem is given by changes on Fedora 33, that have disabled SHA-1 signatures by default (https://fedoraproject.org/wiki/Changes/StrongCryptoSettings2).
I solved it changing crypto policies:
update-crypto-policies --set DEFAULT:FEDORA32

Categories