file_get_contents(): SSL operation failed with code 1 - php

I use PHP wamp with php_open_ssl.dll (version: OpenSSL 1.0.1d 5 Feb 2013).
When I tried to access https URL like this:
$result = file_get_contents($url, null, stream_context_create(array(
'http' => array(
'protocol_version' => 1.1,
'user_agent' => 'PHP-MCAPI/2.0',
'method' => 'POST',
'header' => "Content-type: application/json\r\n".
"Connection: close\r\n" .
"Content-length: " . strlen($json_data) . "\r\n",
'content' => $json_data,
),
)));
I get the following warning:
file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac
Some say that this is caused because of bad version of SSL dll. Do you guys have any tips of how to resolve this?
Thanks in advance!

Related

How to pass two arrays to $options parameter of stream_context_create($options)?

Now i pass an array inside $options to stream_context_create which is the next one:
$options = array('http' => array(
'method'=>'POST',
'header'=>
"Accept-language: en\r\n".
"Content-type: application/x-www-form-urlencoded\r\n", 'content'=>http_build_query(array('partida'=>$partida,'dataInici'=>$dataInici,'dataFi'=>$dataFi,'usuari'=>$_SESSION["usuari"]))));
And the php gaves me an error of "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"
And i found a possible solution to this which is pass to stream_context_create($options) inside $options an array like this:
$arrContextOptions=array(
"ssl"=>array(
"cafile" => "/cacert.pem",
"verify_peer"=> true,
"verify_peer_name"=> true,
),);
But i don't know how to pass both arrays inside $options.

PHP: PATCH method fails when others succeed

I have a an API I'm using a variety of methods on. GET works fine as do the others I am testing. When using PATCH, it gives errors despite the documentation showing it's enabled.
The errors are:
Warning: file_get_contents(): SSL: Connection reset by peer in upload.php on line 20
Warning: file_get_contents(https://api-domain/answers/331): failed to open stream: HTTP request failed! in oracle_upload.php on line 20
Error
Line 20 is
$response = file_get_contents('https://api-domain/answers/331', FALSE, $content)
As for the $content variable:
$postData = array(
'solution' => 'Testing 123'
);
$context = stream_context_create(array(
'http' => array(
'method' => 'PATCH',
'header' => "Authorization: Basic dXNlcjpwYXNz\r\nContent-Type: application/json\r\n",
'content' => json_encode($postData)
),
"ssl"=>array(
"allow_self_signed"=>true,
"verify_peer"=>false,
"verify_peer_name"=>false
)
));
Please note, https://api-domain is a fake addy
Thanks
In your php.ini file change this line or add.
extension=php_openssl.dll
allow_url_fopen = On

How to send a facebook notification to a user without using the SDK with only PHP

I don't know if this is possible, i'm having a problem getting the PHP SDK to work and i don't want to send App Access Token to browser.
So i tried the following.
$contextData = array (
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
/* 'header' => "Connection: close\r\n".
"Content-Length: ".strlen($query)."\r\n",
'content'=> $query*/ );
$context = stream_context_create (array('https' =>$contextData));
$url = 'https://graph.facebook.com/userAppId/notifications?access_token=********&href=index.php&template=test';
$result = file_get_contents ($url,false,$context);
echo $result;
Problem: I get this error.
Warning: file_get_contents(https://graph.facebook.com/userAppId/notifications?
access_token=********&href=index.php&template=test):
failed to open stream:HTTP request failed! HTTP/1.1 400 Bad Request in
C:\wamp\app\fb\fb_notificationsphp.php on line 19

PHP set protocol_version for stream_context_create

I want to access an oauth server with a php script, the remote server requires the following request:
POST /oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 81
Authorization: Basic CHAINE_ENCODEE
grant_type=password&username=USERNAME&password=PASSWORD&scope=all
So I wrote the following code:
$params = array ('grant_type' => 'password',
'username' => 'USERNAME',
'password' => hash('sha256', 'PASSWORD'),
'scope' => 'all',
);
$query = http_build_query ($params);
$contextData = array (
'protocol_version'=> '1.1',
'method' => 'POST',
'header' => "Connection: close\r\n".
"Content-Type: application/x-www-form-urlencoded\r\n".
"Content-Length: 81\r\n".
"Authorization: Basic ".base64_encode('APPIDENTIFIER:SECRET'),
'content' => $query );
$context = stream_context_create (array ( 'http' => $contextData ));
$result = file_get_contents (
'https://rest2.some-url.net/oauth/token', // page url
false,
$context);
return $result;
But this gives me the following error:
Warning: file_get_contents(https://rest2.some-url.net/oauth/token): failed to open stream:
HTTP request failed! HTTP/1.0 500 Internal Server Error
My guess is that the problem comes from the protocol_version which I set to 1.1 as required by the api. But the error apparently uses HTTP/1.0
I have tried every possible way, i have seen no one saying it was not working for them so I guess I am missing something. Why is not the HTTP set to HTTP/1.1?

OPENSSL file_get_contents(): Failed to enable crypto

I'm building a personal stock platform (not distributed). A component I would like to have is the EPS graph on this page:
https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes
As you can see, the page is https, so after days of hammering things out, I enabled openssl and now it seems to work for all https pages such as the homepages of facebook and twitter, however it is still not working for the one I need.
file_get_contents('https://facebook.com'); /* works */
file_get_contents('https://twittercom'); /* works */
file_get_contents('https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes');
I'm getting the warning:
Warning: file_get_contents(): SSL: crypto enabling timeout in C:\xampp\htdocs\index.php on line 3
Warning: file_get_contents(): Failed to enable crypto in C:\xampp\htdocs\index.php on line 3
Warning: file_get_contents(https://eresearch.fidelity.com/eresearch/evaluate/fundamentals/earnings.jhtml?stockspage=earnings&symbols=AAPL&showPriceLine=yes): failed to open stream: operation failed in C:\xampp\htdocs\index.php on line 3
Fatal error: Maximum execution time of 30 seconds exceeded in C:\xampp\htdocs\index.php on line 3
The only difference I can see is that the fidelity page has a triangle near the https label.
Ok I have found a solution. The problem is that the site uses SSLv3. And I know that there are some problems in the openssl module. Some time ago I had the same problem with the SSL versions.
<?php
function getSSLPage($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSLVERSION,3);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
var_dump(getSSLPage("https://eresearch.fidelity.com/eresearch/evaluate/analystsOpinionsReport.jhtml?symbols=api"));
?>
When you set the SSL Version with curl to v3 then it works.
Edit:
Another problem under Windows is that you don't have access to the certificates. So put the root certificates directly to curl.
http://curl.haxx.se/docs/caextract.html
here you can download the root certificates.
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/certs/cacert.pem");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
Then you can use the CURLOPT_SSL_VERIFYPEER option with true otherwise you get an error.
Had same problem - it was somewhere in the ca certificate, so I used the ca bundle used for curl, and it worked. You can download the curl ca bundle here: https://curl.haxx.se/docs/caextract.html
For encryption and security issues see this helpful article:
https://www.venditan.com/labs/2014/06/26/ssl-and-php-streams-part-1-you-are-doing-it-wrongtm/432
Here is the example:
$url = 'https://www.example.com/api/list';
$cn_match = 'www.example.com';
$data = array (
'apikey' => '[example api key here]',
'limit' => intval($limit),
'offset' => intval($offset)
);
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data)
)
, 'ssl' => array(
'verify_peer' => true,
'cafile' => [path to file] . "cacert.pem",
'ciphers' => 'HIGH:TLSv1.2:TLSv1.1:TLSv1.0:!SSLv3:!SSLv2',
'CN_match' => $cn_match,
'disable_compression' => true,
)
);
$context = stream_context_create($options);
$response = file_get_contents($url, false, $context);
Hope that helps
A workaround that works for me is to disable peer verification. Be careful when you use it because it shouldn't be use in production.
$arrContextOptions = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
)
);
$context = stream_context_create($arrContextOptions);
$contents = file_get_contents($url,false,$context);

Categories