phpbrew php7 throws gnutls_handshake() failed: Illegal parameter - php

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.

Related

file_get_contents(): SSL operation failed with code 1 - Server solving [duplicate]

I’ve been trying to access this particular REST service from a PHP page I’ve created on our server. I narrowed the problem down to these two lines. So my PHP page looks like this:
<?php
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json");
echo $response; ?>
The page dies on line 2 with the following errors:
Warning: file_get_contents(): SSL operation failed with code 1.
OpenSSL Error messages: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in
...php on line 2
Warning: file_get_contents(): Failed to enable crypto in ...php on
line 2
Warning:
file_get_contents(https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json):
failed to open stream: operation failed in ...php on line 2
We’re using a Gentoo server. We recently upgraded to PHP version 5.6. It was after the upgrade when this problem appeared.
I found when I replace the REST service with an address like https://www.google.com; my page works just fine.
In an earlier attempt I set “verify_peer”=>false, and passed that in as an argument to file_get_contents, as described here: file_get_contents ignoring verify_peer=>false? But like the writer noted; it made no difference.
I’ve asked one of our server administrators if these lines in our php.ini file exist:
extension=php_openssl.dll
allow_url_fopen = On
He told me that since we’re on Gentoo, openssl is compiled when we build; and it’s not set in the php.ini file.
I also confirmed that allow_url_fopen is working. Due to the specialized nature of this problem; I’m not finding a lot of information for help. Have any of you come across something like this? Thanks.
This was an enormously helpful link to find:
http://php.net/manual/en/migration56.openssl.php
An official document describing the changes made to open ssl in PHP 5.6
From here I learned of one more parameter I should have set to false: "verify_peer_name"=>false
Note: This has very significant security implications. Disabling verification potentially permits a MITM attacker to use an invalid certificate to eavesdrop on the requests. While it may be useful to do this in local development, other approaches should be used in production.
So my working code looks like this:
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));
echo $response; ?>
You shouldn't just turn off verification. Rather you should download a certificate bundle, perhaps the curl bundle will do?
Then you just need to put it on your web server, giving the user that runs php permission to read the file. Then this code should work for you:
$arrContextOptions= [
'ssl' => [
'cafile' => '/path/to/bundle/cacert.pem',
'verify_peer'=> true,
'verify_peer_name'=> true,
],
];
$response = file_get_contents(
'https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json',
false,
stream_context_create($arrContextOptions)
);
Hopefully, the root certificate of the site you are trying to access is in the curl bundle. If it isn't, this still won't work until you get the root certificate of the site and put it into your certificate file.
I fixed this by making sure that that OpenSSL was installed on my machine and then adding this to my php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
You can get around this problem by writing a custom function that uses curl, as in:
function file_get_contents_curl( $url ) {
$ch = curl_init();
curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE );
$data = curl_exec( $ch );
curl_close( $ch );
return $data;
}
Then just use file_get_contents_curl instead of file_get_contents whenever you're calling a url that begins with https.
Working for me, I am using PHP 5.6. openssl extension should be enabled and while calling google map api verify_peer make false
Below code is working for me.
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$url = "https://maps.googleapis.com/maps/api/geocode/json?latlng="
. $latitude
. ","
. $longitude
. "&sensor=false&key="
. Yii::$app->params['GOOGLE_API_KEY'];
$data = file_get_contents($url, false, stream_context_create($arrContextOptions));
echo $data;
?>
At first you need to have enabled curl extension in PHP. Then you can use this function:
function file_get_contents_ssl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3000); // 3 sec.
curl_setopt($ch, CURLOPT_TIMEOUT, 10000); // 10 sec.
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
It works similar to function file_get_contents(..).
Example:
echo file_get_contents_ssl("https://www.example.com/");
Output:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
...
After falling victim to this problem on centOS after updating php to php5.6 I found a solution that worked for me.
Get the correct directory for your certs to be placed by default with this
php -r "print_r(openssl_get_cert_locations()['default_cert_file']);"
Then use this to get the cert and put it in the default location found from the code above
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
You basically have to set the environment variable SSL_CERT_FILE to the path of the PEM file of the ssl-certificate downloaded from the following link : http://curl.haxx.se/ca/cacert.pem.
It took me a lot of time to figure this out.
If your PHP version is 5, try installing cURL by typing the following command in the terminal:
sudo apt-get install php5-curl
following below steps will fix this issue,
Download the CA Certificate from this link: https://curl.haxx.se/ca/cacert.pem
Find and open php.ini
Look for curl.cainfo and paste the absolute path where you have download the Certificate. curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
Restart WAMP/XAMPP (apache server).
It works!
hope that helps !!
Just wanted to add to this since I ran into the same problem and nothing I could find anywhere would work (e.g downloading the cacert.pem file, setting cafile in php.ini etc.)
If you are using NGINX and your SSL certificate comes with an "intermediate certificate", you need to combine the intermediate cert file with your main "mydomain.com.crt" file and it should work. Apache has a setting specific for intermediate certs, but NGINX does not so it must be within same file as your regular cert.
Reason for this error is that PHP does not have a list of trusted certificate authorities.
PHP 5.6 and later try to load the CAs trusted by the system automatically. Issues with that can be fixed. See http://php.net/manual/en/migration56.openssl.php for more information.
PHP 5.5 and earlier are really hard to setup correctly since you manually have to specify the CA bundle in each request context, a thing you do not want to sprinkle around your code.
So I decided for my code that for PHP versions < 5.6, SSL verification simply gets disabled:
$req = new HTTP_Request2($url);
if (version_compare(PHP_VERSION, '5.6.0', '<')) {
//correct ssl validation on php 5.5 is a pain, so disable
$req->setConfig('ssl_verify_host', false);
$req->setConfig('ssl_verify_peer', false);
}
Had the same error with PHP 7 on XAMPP and OSX.
The above mentioned answer in https://stackoverflow.com/ is good, but it did not completely solve the problem for me. I had to provide the complete certificate chain to make file_get_contents() work again. That's how I did it:
Get root / intermediate certificate
First of all I had to figure out what's the root and the intermediate certificate.
The most convenient way is maybe an online cert-tool like the ssl-shopper
There I found three certificates, one server-certificate and two chain-certificates (one is the root, the other one apparantly the intermediate).
All I need to do is just search the internet for both of them. In my case, this is the root:
thawte DV SSL SHA256 CA
And it leads to his url thawte.com. So I just put this cert into a textfile and did the same for the intermediate. Done.
Get the host certificate
Next thing I had to to is to download my server cert. On Linux or OS X it can be done with openssl:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
Now bring them all together
Now just merge all of them into one file. (Maybe it's good to just put them into one folder, I just merged them into one file). You can do it like this:
cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
tell PHP where to find the chain
There is this handy function openssl_get_cert_locations() that'll tell you, where PHP is looking for cert files. And there is this parameter, that will tell file_get_contents() where to look for cert files. Maybe both ways will work. I preferred the parameter way. (Compared to the solution mentioned above).
So this is now my PHP-Code
$arrContextOptions=array(
"ssl"=>array(
"cafile" => "/Applications/XAMPP/xamppfiles/share/openssl/certs/chain.pem",
"verify_peer"=> true,
"verify_peer_name"=> true,
),
);
$response = file_get_contents($myHttpsURL, 0, stream_context_create($arrContextOptions));
That's all. file_get_contents() is working again. Without CURL and hopefully without security flaws.
<?php
$stream_context = stream_context_create([
"ssl" => [
"verify_peer" => false,
"verify_peer_name" => false
]
]);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, $stream_context);
echo $response;
?>
Just tested of PHP 7.2, it's working well.
EDIT: Also tested and working on PHP 7.1
Had the same ssl-problem on my developer machine (php 7, xampp on windows) with a self signed certificate trying to fopen a "https://localhost/..."-file. Obviously the root-certificate-assembly (cacert.pem) didn't work.
I just copied manually the code from the apache server.crt-File in the downloaded cacert.pem and did the openssl.cafile=path/to/cacert.pem entry in php.ini
Another thing to try is to re-install ca-certificates as detailed here.
# yum reinstall ca-certificates
...
# update-ca-trust force-enable
# update-ca-trust extract
And another thing to try is to explicitly allow the one site's certificate in question as described here (especially if the one site is your own server and you already have the .pem in reach).
# cp /your/site.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust extract
I was running into this exact SO error after upgrading to PHP 5.6 on CentOS 6 trying to access the server itself which has a cheapsslsecurity certificate which maybe it needed to be updated, but instead I installed a letsencrypt certificate and with these two steps above it did the trick. I don't know why the second step was necessary.
Useful Commands
View openssl version:
# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
View PHP cli ssl current settings:
# php -i | grep ssl
openssl
Openssl default config => /etc/pki/tls/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Regarding errors similar to
[11-May-2017 19:19:13 America/Chicago] PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
Have you checked the permissions of the cert and directories referenced by openssl?
You can do this
var_dump(openssl_get_cert_locations());
To get something similar to this
array(8) {
["default_cert_file"]=>
string(21) "/usr/lib/ssl/cert.pem"
["default_cert_file_env"]=>
string(13) "SSL_CERT_FILE"
["default_cert_dir"]=>
string(18) "/usr/lib/ssl/certs"
["default_cert_dir_env"]=>
string(12) "SSL_CERT_DIR"
["default_private_dir"]=>
string(20) "/usr/lib/ssl/private"
["default_default_cert_area"]=>
string(12) "/usr/lib/ssl"
["ini_cafile"]=>
string(0) ""
["ini_capath"]=>
string(0) ""
}
This issue frustrated me for a while, until I realized that my "certs" folder had 700 permissions, when it should have had 755 permissions. Remember, this is not the folder for keys but certificates. I recommend reading this this link on ssl permissions.
Once I did
chmod 755 certs
The problem was fixed, at least for me anyway.
Fix for macos 12.4 / Mamp 6.6 / Homebrew 3.5.2 / Openssl#3
Terminal
Check version
openssl version -a
Mine was pointing to:
...
OPENSSLDIR: "/opt/homebrew/etc/openssl#3"
...
So I looked through homebrew's dir /opt/homebrew/etc/openssl#3 and found the cert.pem and made sure my Mamp's current version of php's php.ini file was pointing to homebrew's correct openssl version's cert.pem
add to php.ini
openssl.cafile=/opt/homebrew/etc/openssl#3/cert.pem
I had the same issue for another secure page when using wget or file_get_contents. A lot of research (including some of the responses on this question) resulted in a simple solution - installing Curl and PHP-Curl - If I've understood correctly, Curl has the Root CA for Comodo which resolved the issue
Install Curl and PHP-Curl addon, then restart Apache
sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload
All now working.
For me, I was running XAMPP on a Windows 10 machine (localhost) and recently upgraded to PHP 8. I was trying to open a localhost HTTPS link via file_get_contents().
In my php.ini file, there was a line that read:
openssl.cafile="C:\Users\[USER]\xampp\apache\bin\curl-ca-bundle.crt"
This was the certificate bundle being used to validate "outside" URLs, and was a package from Mozilla as some people have discussed. I don't know if XAMPP came that way or if I set it up in the past.
At some point I had set up HTTPS on my localhost, resulting in another certificate bundle. This bundle needed to be used to validate "localhost" URLs. To remind myself where that bundle was, I opened httpd-ssl.conf and found the line that read:
SSLCertificateFile "conf/ssl.crt/server.crt"
(The complete path was C:\Users[USER]\xampp\apache\conf\ssl.crt\server.crt)
To make both localhost and outside URLs work simultaneously, I copied the contents of my localhost "server.crt" file into Mozilla's bundle "curl-ca-bundle.crt".
.
.
.
m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
-----END CERTIFICATE-----
Localhost--I manually added this
================================
-----BEGIN CERTIFICATE-----
MIIDGDCCAgCgAwIBAgIQIH+mTLNOSKlD8KMZwr5P3TANBgkqhkiG9w0BAQsFADAU
...
At that point I could use file_get_contents() with both localhost URLs and outside URLs with no additional configuration.
file_get_contents("https://localhost/...");
file_get_contents("https://google.com");
$csm = stream_context_create(['ssl' => ['capture_session_meta' => TRUE]]);
$sourceCountry = file_get_contents("https://api.wipmania.com/{$ip}?website.com", FALSE, $csm);
echo $sourceCountry;

PHP7 cURL and SOAP request SSL failing

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)

How to use php cURL on local vagrant?

I have the following piece of code which works on my remote server
$myCurl = curl_init();
curl_setopt_array($myCurl, array(
CURLOPT_URL => "http://{$_SERVER['HTTP_HOST']}/social/api/auth/login_or_register",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($credentials)
));
$exec = curl_exec($myCurl);
I decided to port the project to local for further development so I have set up a vagrant virtual machine with everything needs, everything seems to work normally except the piece of code above which gives me the following error:
Curl failed with error #7: Failed to connect to project.dev port 8000: Connection refused
Any hints on how I can work around this problem so that I can develop normally on local ?
add in /etc/hosts
127.0.0.1 project.dev

file_get_contents(): SSL operation failed with code 1, Failed to enable crypto

I’ve been trying to access this particular REST service from a PHP page I’ve created on our server. I narrowed the problem down to these two lines. So my PHP page looks like this:
<?php
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json");
echo $response; ?>
The page dies on line 2 with the following errors:
Warning: file_get_contents(): SSL operation failed with code 1.
OpenSSL Error messages: error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed in
...php on line 2
Warning: file_get_contents(): Failed to enable crypto in ...php on
line 2
Warning:
file_get_contents(https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json):
failed to open stream: operation failed in ...php on line 2
We’re using a Gentoo server. We recently upgraded to PHP version 5.6. It was after the upgrade when this problem appeared.
I found when I replace the REST service with an address like https://www.google.com; my page works just fine.
In an earlier attempt I set “verify_peer”=>false, and passed that in as an argument to file_get_contents, as described here: file_get_contents ignoring verify_peer=>false? But like the writer noted; it made no difference.
I’ve asked one of our server administrators if these lines in our php.ini file exist:
extension=php_openssl.dll
allow_url_fopen = On
He told me that since we’re on Gentoo, openssl is compiled when we build; and it’s not set in the php.ini file.
I also confirmed that allow_url_fopen is working. Due to the specialized nature of this problem; I’m not finding a lot of information for help. Have any of you come across something like this? Thanks.
This was an enormously helpful link to find:
http://php.net/manual/en/migration56.openssl.php
An official document describing the changes made to open ssl in PHP 5.6
From here I learned of one more parameter I should have set to false: "verify_peer_name"=>false
Note: This has very significant security implications. Disabling verification potentially permits a MITM attacker to use an invalid certificate to eavesdrop on the requests. While it may be useful to do this in local development, other approaches should be used in production.
So my working code looks like this:
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, stream_context_create($arrContextOptions));
echo $response; ?>
You shouldn't just turn off verification. Rather you should download a certificate bundle, perhaps the curl bundle will do?
Then you just need to put it on your web server, giving the user that runs php permission to read the file. Then this code should work for you:
$arrContextOptions= [
'ssl' => [
'cafile' => '/path/to/bundle/cacert.pem',
'verify_peer'=> true,
'verify_peer_name'=> true,
],
];
$response = file_get_contents(
'https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json',
false,
stream_context_create($arrContextOptions)
);
Hopefully, the root certificate of the site you are trying to access is in the curl bundle. If it isn't, this still won't work until you get the root certificate of the site and put it into your certificate file.
I fixed this by making sure that that OpenSSL was installed on my machine and then adding this to my php.ini:
openssl.cafile=/usr/local/etc/openssl/cert.pem
You can get around this problem by writing a custom function that uses curl, as in:
function file_get_contents_curl( $url ) {
$ch = curl_init();
curl_setopt( $ch, CURLOPT_AUTOREFERER, TRUE );
curl_setopt( $ch, CURLOPT_HEADER, 0 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, TRUE );
$data = curl_exec( $ch );
curl_close( $ch );
return $data;
}
Then just use file_get_contents_curl instead of file_get_contents whenever you're calling a url that begins with https.
Working for me, I am using PHP 5.6. openssl extension should be enabled and while calling google map api verify_peer make false
Below code is working for me.
<?php
$arrContextOptions=array(
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
),
);
$url = "https://maps.googleapis.com/maps/api/geocode/json?latlng="
. $latitude
. ","
. $longitude
. "&sensor=false&key="
. Yii::$app->params['GOOGLE_API_KEY'];
$data = file_get_contents($url, false, stream_context_create($arrContextOptions));
echo $data;
?>
After falling victim to this problem on centOS after updating php to php5.6 I found a solution that worked for me.
Get the correct directory for your certs to be placed by default with this
php -r "print_r(openssl_get_cert_locations()['default_cert_file']);"
Then use this to get the cert and put it in the default location found from the code above
wget http://curl.haxx.se/ca/cacert.pem -O <default location>
At first you need to have enabled curl extension in PHP. Then you can use this function:
function file_get_contents_ssl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3000); // 3 sec.
curl_setopt($ch, CURLOPT_TIMEOUT, 10000); // 10 sec.
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
It works similar to function file_get_contents(..).
Example:
echo file_get_contents_ssl("https://www.example.com/");
Output:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
...
You basically have to set the environment variable SSL_CERT_FILE to the path of the PEM file of the ssl-certificate downloaded from the following link : http://curl.haxx.se/ca/cacert.pem.
It took me a lot of time to figure this out.
If your PHP version is 5, try installing cURL by typing the following command in the terminal:
sudo apt-get install php5-curl
following below steps will fix this issue,
Download the CA Certificate from this link: https://curl.haxx.se/ca/cacert.pem
Find and open php.ini
Look for curl.cainfo and paste the absolute path where you have download the Certificate. curl.cainfo ="C:\wamp\htdocs\cert\cacert.pem"
Restart WAMP/XAMPP (apache server).
It works!
hope that helps !!
Just wanted to add to this since I ran into the same problem and nothing I could find anywhere would work (e.g downloading the cacert.pem file, setting cafile in php.ini etc.)
If you are using NGINX and your SSL certificate comes with an "intermediate certificate", you need to combine the intermediate cert file with your main "mydomain.com.crt" file and it should work. Apache has a setting specific for intermediate certs, but NGINX does not so it must be within same file as your regular cert.
Reason for this error is that PHP does not have a list of trusted certificate authorities.
PHP 5.6 and later try to load the CAs trusted by the system automatically. Issues with that can be fixed. See http://php.net/manual/en/migration56.openssl.php for more information.
PHP 5.5 and earlier are really hard to setup correctly since you manually have to specify the CA bundle in each request context, a thing you do not want to sprinkle around your code.
So I decided for my code that for PHP versions < 5.6, SSL verification simply gets disabled:
$req = new HTTP_Request2($url);
if (version_compare(PHP_VERSION, '5.6.0', '<')) {
//correct ssl validation on php 5.5 is a pain, so disable
$req->setConfig('ssl_verify_host', false);
$req->setConfig('ssl_verify_peer', false);
}
Had the same error with PHP 7 on XAMPP and OSX.
The above mentioned answer in https://stackoverflow.com/ is good, but it did not completely solve the problem for me. I had to provide the complete certificate chain to make file_get_contents() work again. That's how I did it:
Get root / intermediate certificate
First of all I had to figure out what's the root and the intermediate certificate.
The most convenient way is maybe an online cert-tool like the ssl-shopper
There I found three certificates, one server-certificate and two chain-certificates (one is the root, the other one apparantly the intermediate).
All I need to do is just search the internet for both of them. In my case, this is the root:
thawte DV SSL SHA256 CA
And it leads to his url thawte.com. So I just put this cert into a textfile and did the same for the intermediate. Done.
Get the host certificate
Next thing I had to to is to download my server cert. On Linux or OS X it can be done with openssl:
openssl s_client -showcerts -connect whatsyoururl.de:443 </dev/null 2>/dev/null|openssl x509 -outform PEM > /tmp/whatsyoururl.de.cert
Now bring them all together
Now just merge all of them into one file. (Maybe it's good to just put them into one folder, I just merged them into one file). You can do it like this:
cat /tmp/thawteRoot.crt > /tmp/chain.crt
cat /tmp/thawteIntermediate.crt >> /tmp/chain.crt
cat /tmp/tmp/whatsyoururl.de.cert >> /tmp/chain.crt
tell PHP where to find the chain
There is this handy function openssl_get_cert_locations() that'll tell you, where PHP is looking for cert files. And there is this parameter, that will tell file_get_contents() where to look for cert files. Maybe both ways will work. I preferred the parameter way. (Compared to the solution mentioned above).
So this is now my PHP-Code
$arrContextOptions=array(
"ssl"=>array(
"cafile" => "/Applications/XAMPP/xamppfiles/share/openssl/certs/chain.pem",
"verify_peer"=> true,
"verify_peer_name"=> true,
),
);
$response = file_get_contents($myHttpsURL, 0, stream_context_create($arrContextOptions));
That's all. file_get_contents() is working again. Without CURL and hopefully without security flaws.
<?php
$stream_context = stream_context_create([
"ssl" => [
"verify_peer" => false,
"verify_peer_name" => false
]
]);
$response = file_get_contents("https://maps.co.weber.ut.us/arcgis/rest/services/SDE_composite_locator/GeocodeServer/findAddressCandidates?Street=&SingleLine=3042+N+1050+W&outFields=*&outSR=102100&searchExtent=&f=json", false, $stream_context);
echo $response;
?>
Just tested of PHP 7.2, it's working well.
EDIT: Also tested and working on PHP 7.1
Had the same ssl-problem on my developer machine (php 7, xampp on windows) with a self signed certificate trying to fopen a "https://localhost/..."-file. Obviously the root-certificate-assembly (cacert.pem) didn't work.
I just copied manually the code from the apache server.crt-File in the downloaded cacert.pem and did the openssl.cafile=path/to/cacert.pem entry in php.ini
Another thing to try is to re-install ca-certificates as detailed here.
# yum reinstall ca-certificates
...
# update-ca-trust force-enable
# update-ca-trust extract
And another thing to try is to explicitly allow the one site's certificate in question as described here (especially if the one site is your own server and you already have the .pem in reach).
# cp /your/site.pem /etc/pki/ca-trust/source/anchors/
# update-ca-trust extract
I was running into this exact SO error after upgrading to PHP 5.6 on CentOS 6 trying to access the server itself which has a cheapsslsecurity certificate which maybe it needed to be updated, but instead I installed a letsencrypt certificate and with these two steps above it did the trick. I don't know why the second step was necessary.
Useful Commands
View openssl version:
# openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
View PHP cli ssl current settings:
# php -i | grep ssl
openssl
Openssl default config => /etc/pki/tls/openssl.cnf
openssl.cafile => no value => no value
openssl.capath => no value => no value
Regarding errors similar to
[11-May-2017 19:19:13 America/Chicago] PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed
Have you checked the permissions of the cert and directories referenced by openssl?
You can do this
var_dump(openssl_get_cert_locations());
To get something similar to this
array(8) {
["default_cert_file"]=>
string(21) "/usr/lib/ssl/cert.pem"
["default_cert_file_env"]=>
string(13) "SSL_CERT_FILE"
["default_cert_dir"]=>
string(18) "/usr/lib/ssl/certs"
["default_cert_dir_env"]=>
string(12) "SSL_CERT_DIR"
["default_private_dir"]=>
string(20) "/usr/lib/ssl/private"
["default_default_cert_area"]=>
string(12) "/usr/lib/ssl"
["ini_cafile"]=>
string(0) ""
["ini_capath"]=>
string(0) ""
}
This issue frustrated me for a while, until I realized that my "certs" folder had 700 permissions, when it should have had 755 permissions. Remember, this is not the folder for keys but certificates. I recommend reading this this link on ssl permissions.
Once I did
chmod 755 certs
The problem was fixed, at least for me anyway.
Fix for macos 12.4 / Mamp 6.6 / Homebrew 3.5.2 / Openssl#3
Terminal
Check version
openssl version -a
Mine was pointing to:
...
OPENSSLDIR: "/opt/homebrew/etc/openssl#3"
...
So I looked through homebrew's dir /opt/homebrew/etc/openssl#3 and found the cert.pem and made sure my Mamp's current version of php's php.ini file was pointing to homebrew's correct openssl version's cert.pem
add to php.ini
openssl.cafile=/opt/homebrew/etc/openssl#3/cert.pem
I had the same issue for another secure page when using wget or file_get_contents. A lot of research (including some of the responses on this question) resulted in a simple solution - installing Curl and PHP-Curl - If I've understood correctly, Curl has the Root CA for Comodo which resolved the issue
Install Curl and PHP-Curl addon, then restart Apache
sudo apt-get install curl
sudo apt-get install php-curl
sudo /etc/init.d/apache2 reload
All now working.
For me, I was running XAMPP on a Windows 10 machine (localhost) and recently upgraded to PHP 8. I was trying to open a localhost HTTPS link via file_get_contents().
In my php.ini file, there was a line that read:
openssl.cafile="C:\Users\[USER]\xampp\apache\bin\curl-ca-bundle.crt"
This was the certificate bundle being used to validate "outside" URLs, and was a package from Mozilla as some people have discussed. I don't know if XAMPP came that way or if I set it up in the past.
At some point I had set up HTTPS on my localhost, resulting in another certificate bundle. This bundle needed to be used to validate "localhost" URLs. To remind myself where that bundle was, I opened httpd-ssl.conf and found the line that read:
SSLCertificateFile "conf/ssl.crt/server.crt"
(The complete path was C:\Users[USER]\xampp\apache\conf\ssl.crt\server.crt)
To make both localhost and outside URLs work simultaneously, I copied the contents of my localhost "server.crt" file into Mozilla's bundle "curl-ca-bundle.crt".
.
.
.
m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
-----END CERTIFICATE-----
Localhost--I manually added this
================================
-----BEGIN CERTIFICATE-----
MIIDGDCCAgCgAwIBAgIQIH+mTLNOSKlD8KMZwr5P3TANBgkqhkiG9w0BAQsFADAU
...
At that point I could use file_get_contents() with both localhost URLs and outside URLs with no additional configuration.
file_get_contents("https://localhost/...");
file_get_contents("https://google.com");
$csm = stream_context_create(['ssl' => ['capture_session_meta' => TRUE]]);
$sourceCountry = file_get_contents("https://api.wipmania.com/{$ip}?website.com", FALSE, $csm);
echo $sourceCountry;

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