Laravel - GuzzleHttp: handshake failure - php

I'm having some difficulties in setting up a simple login test with GuzzleHttp client on a REST call. I've looked around all over the net but unfortunately without success so i'm wondering if someone here could help.
I'm using the latest laravel on Debian 9 server.
Here's my code:
use GuzzleHttp\Client as HttpClient;
$response = Http::withOptions(['debug' => true,])
->withHeaders([
'cert' => Storage::get('dss/mTLS.crt'),
'ssl_key' => Storage::get('dss/privateKey.pem'),
'Content-Type' => 'application/json;charset=utf-8',
'X-CSRF-TOKEN' => session()->token(),
])
->post('https://emea.api.hvca.globalsign.com:8443/v2/login', [
'api_key' => env('DSS_API_KEY'),
'api_secret' => env('DSS_API_SECRET'),
'curl' => array(
'CURLOPT_SSLVERSION' => 'CURL_SSLVERSION_TLSv1',
'CURLOPT_SSL_CIPHER_LIST' => 'SSLv2',
'CURLOPT_CAINFO' => '/etc/ssl/certs/ca-certificates.crt',
),
]);
dd($response);
As you can see it's a simple request, i tried v1, v2 & v3 for SSL version with the same results:
Debug results:
Trying 185.140.80.38... * TCP_NODELAY set * Connected to emea.api.hvca.globalsign.com (185.140.80.38) port 8443 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure * Curl_http_done: called premature == 1 * stopped the pause stream! * Closing connection 0
Exception: Illuminate\Http\Client\ConnectionException cURL error 35: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure (see https://curl.haxx.se/libcurl/c/libcurl-errors.html)
Any help would be much appreciated :-)
Thanks in advance.
Cheers

Related

Curl works 90% of the time, 10% it fails with OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.site.com:443

I have a bug I am hoping someone can shed some insight on. I am fetching data from a client's API, and it works...90% of the time. About 1/10 times (but random frequency), curl_exec returns false with error:
OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.site.com:443
I've checked numerous threads on this error, and in all cases I see the issue is happening 100% of the time for the person. Has anyone dealt with something like this? If it's working sometimes and failing other times, where is the issue likely to be (the site/server or the api)?
I have experimented with different settings and nothing has fixed the issue. I've tried with and without CURLOPT_PINNEDPUBLICKEY, with and without CURLOPT_SSL_VERIFYHOST => 0, CURLOPT_SSL_VERIFYPEER => 0, with and without forcing HTTP and SSL versions. It fails always when I set these incorrectly, so I am pretty sure I have the right versions selected. The code exists in a custom joomla component which has been stable before this API switch. Here is my code:
$headers = array(
'X-apikey: '.$this->apikey,
"Cache-Control: no-cache",
);
$url = $this->url;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2,
CURLOPT_PINNEDPUBLICKEY => '/path/to/api.site.com.pubkey.der',
));
$data = curl_exec($curl);
$result = json_decode($data);
curl_close($curl);
PHP version: 7.3.10
curl version: 7.66.0
openSSL library version: OpenSSL 1.1.1d 10 Sep 2019
Output from hanshenrik comment (removed company info):
Error output:
string(385) "* Trying xxx.xxx.xxx.xxx:443... * TCP_NODELAY set * Connected to api.site.com (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /usr/local/etc/openssl#1.1/cert.pem CApath: /usr/local/etc/openssl#1.1/certs * OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.site.com:443 * Closing connection 0 "
Success Output
string(1324) "* Trying xxx.xxx.xxx.xxx:443... * TCP_NODELAY set * Connected to api.site.com (xxx.xxx.xxx.xxx) port 443 (#0) * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /usr/local/etc/openssl#1.1/cert.pem CApath: /usr/local/etc/openssl#1.1/certs * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server did not agree to a protocol * Server certificate: * subject: C=US; ST=Illinois; L=Chicago; O=Company Name; CN=*.site.com * start date: May 14 15:20:46 2019 GMT * expire date: Aug 8 15:41:00 2020 GMT * issuer: C=US; ST=Arizona; L=Scottsdale; O=GoDaddy.com, Inc.; OU=http://certs.godaddy.com/repository/; CN=Go Daddy Secure Certificate Authority - G2 * SSL certificate verify ok. > GET /endpoint/id?fields=field1,field2,etc HTTP/1.1 Host: api.site.com Accept: / X-apikey: xxxxx Cache-Control: no-cache * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Tue, 08 Oct 2019 21:21:45 GMT < Server: Apache < Content-Length: 614 < Content-Type: application/json < * Connection #0 to host api.site.com left intact "

Php 5.6 unable to get local issuer certificate

I have a valid wildcard CA Certificate for my sites:
myapp.example.com
qamyapp.example.com
I need consume a rest service using php 5.6 curl.
When try to execute php curl calling qamyapp.example.com, show the next error:
* Trying xx.xxx.xxx.xx...
* Connected to qamyapp.example.com (xx.xxx.xxx.xx) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection:
ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
But when curl call myapp.example.com work fine.
How a can update the ca-certificates.crt file.
I have found the solution. In qamyapp.example.com server, is necesary concat to certificate.crt file, the content of bundle.crt file, to NGinx.

CURL issue on new Server

I am trying to curl the below location;
Curl::to('https://serp.webshed.co/')->enableDebug('/uploads/log/logFile.txt')->get();
When I load the URL directly in my browser it works fine, when I try curling it from my local dev it works fine. When I try and curl it from my actual system online it times out, the error I get is;
* Trying 46.101.38.201...
* Connected to serp.webshed.co (46.101.38.201) port 443 (#0)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:#STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* Operation timed out after 0 milliseconds with 0 out of 0 bytes received
* Closing connection 0
Does anyone know what the issue could be?

How to specify public certificate using GuzzleHttp/cURL

I have been fighting this issue for a while and cannot seem to get it right. To preface, this is my first experience having to work with SSL. The server I am working on is using PHP 5.6.30 and Laravel 5.1.46, and I'm trying to use GuzzleHttp 6.2.3 to post JSON to a third party. Up until now, I've been disabling ssl verification by specifying 'verify' => false within the client, and have been able to get successful responses. The third party provided me with a certificate to use, and gave me both .pem and .cer formats. They stated the certificate is not password protected since it is the public key. According to GuzzleHttp's documentation, my request should look like this:
$response = $client->request('POST', $endpoint, [
'cert' => /path/to/new/cert.pem,
'headers' => [
'Content-type' => 'application/json'
],
'body' => $request_body,
'connect_timeout' => 5,
]);
I cannot connect using this method, and unfortunately I can't get the low level error detail due to the design of the server I'm working on (it's a large pre-existing codebase I'm having to update, it will hopefully eventually be completely rewritten).
In order to get more detail, I decided to send the request using cURL. First I sent the request without the certificate:
// REQUEST
curl -v -H "Content-Type: application/json" -X POST -d '{"some_json_request": "value"}' https://sometargeturl.com:8443/dosomething
// OUTPUT
* Trying 204.71.178.10...
* TCP_NODELAY set
* Connected to sometargeturl.com (204.71.178.10) port 8443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* Server certificate:
* subject: CN=sometargeturl.com,OU=OU,O="Some Company Name, Inc",L=Pleasanton,ST=California,C=US
* start date: May 13 00:00:00 2016 GMT
* expire date: May 14 23:59:59 2018 GMT
* common name: sometargeturl.com
* issuer: CN=Symantec Class 3 Secure Server CA - G4,OU=Symantec Trust Network,O=Symantec Corporation,C=US
* NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)
* Peer's Certificate issuer is not recognized.
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (60) Peer's Certificate issuer is not recognized.
Then, with the certificate:
// REQUEST
curl -v --cert /path/to/the/cert.pem -H "Content-Type: application/json" -X POST -d '{"some_json_request": "value"}' https://sometargeturl.com:8443/dosomething
// OUTPUT
* Trying 204.71.178.10...
* TCP_NODELAY set
* Connected to sometargeturl.com (204.71.178.10) port 8443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* unable to load client key: -8178 (SEC_ERROR_BAD_KEY)
* NSS error -8178 (SEC_ERROR_BAD_KEY)
* Peer's public key is invalid.
* Curl_http_done: called premature == 0
* Closing connection 0
curl: (58) unable to load client key: -8178 (SEC_ERROR_BAD_KEY)
I've done a ton of research and have not been able to find a solution. I'm really just unsure of next steps at this point. I ultimately will need to use GuzzleHttp to send the request, but I don't what I'm missing. I have read about adding the new cert to an existing CA bundle, however I'm not sure if that is the right solution/how I would do that if so. Any help would be appreciated, thanks!
what are you exactly trying to do ?
Verifying remote server certificate with 'verify' => true
Authenticating yourself by presenting your certificate to remote ?
That being said, your curl is compiled against NSS and not openssl.
The NSS error -8178 (SEC_ERROR_BAD_KEY) comes from NSS that does not support providing the private key as a file

Error GuzzleHttp cURL error 60: SSL certificate

Im trying to use the Google API, however, when I run it it shows me the following error:
GuzzleHttp\Exception\RequestException: cURL error 60: SSL certificate problem: u
nable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl
-errors.html) in C:\wamp64\www\apigmail\vendor\guzzlehttp\guzzle\src\Handler\Cur
lFactory.php on line 187
Im using WAMP -Server PHP v 7.0.13
Now you can use :
$client = new \GuzzleHttp\Client(['verify' => false ]);
You have to read your error code :)
Its simple you have some SSL errors because your localhost enviroment cant get the data, because you didnt have any SSL certificate.
But here is an solution of your problem in an another thread:
cURL error 60: SSL certificate: unable to get local issuer certificate
you have to add
\GuzzleHttp\RequestOptions::VERIFY => false to the client config:
$this->client = new \GuzzleHttp\Client([
'base_uri' => 'someAccessPoint',
\GuzzleHttp\RequestOptions::HEADERS => [
'User-Agent' => 'some-special-agent',
],
'defaults' => [
\GuzzleHttp\RequestOptions::CONNECT_TIMEOUT => 5,
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => true,
],
\GuzzleHttp\RequestOptions::VERIFY => false,
]);
it will set CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER in the CurlFactory::applyHandlerOptions() method
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
$conf[CURLOPT_SSL_VERIFYPEER] = false;
From the GuzzleHttp documentation
verify
Describes the SSL certificate verification behavior of a request.
Set to true to enable SSL certificate verification and use the default CA bundle > provided by operating system.
Set to false to disable certificate verification (this is insecure!).
Set to a string to provide the path to a CA bundle to enable verification using a custom certificate.

Categories