118

I'm working on setting up credit card processing and needed to use a workaround for CURL. The following code worked fine when I was using the test server (which wasn't calling an SSL URL), but now when I am testing it on the working server with HTTPS, it's failing with the error message "failed to open stream".

function send($packet, $url) {
  $ctx = stream_context_create(
    array(
      'http'=>array(
        'header'=>"Content-type: application/x-www-form-urlencoded",
        'method'=>'POST',
        'content'=>$packet
      )
    )
  );
  return file_get_contents($url, 0, $ctx);
}
DRosenfeld
  • 115
  • 1
  • 9
James Simpson
  • 13,488
  • 26
  • 83
  • 108

11 Answers11

120

To allow https wrapper:

  • the php_openssl extension must exist and be enabled
  • allow_url_fopen must be set to on

In the php.ini file you should add this lines if not exists:

extension=php_openssl.dll

allow_url_fopen = On
hassan
  • 1,209
  • 1
  • 8
  • 2
  • Both are set to On in my installation but I still get the SSL error "Warning: file_get_contents(): SSL: Handshake timed out in" – Adamantus Jan 14 '19 at 14:16
96

Try the following script to see if there is an https wrapper available for your php scripts.

$w = stream_get_wrappers();
echo 'openssl: ',  extension_loaded  ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_export($w);

the output should be something like

openssl: yes
http wrapper: yes
https wrapper: yes
wrappers: array(11) {
  [...]
}
MagicSux
  • 382
  • 3
  • 11
VolkerK
  • 95,432
  • 20
  • 163
  • 226
67

If you want to be vulnerable to a man-in-the middle attack, try this code:

$url= 'https://example.com';

$arrContextOptions=array(
      "ssl"=>array(
            "verify_peer"=>false,
            "verify_peer_name"=>false,
        ),
    );  

$response = file_get_contents($url, false, stream_context_create($arrContextOptions));

This will allow you to get the content from the url no matter what certificate it presents

miken32
  • 42,008
  • 16
  • 111
  • 154
Dushyant Dagar
  • 1,019
  • 10
  • 17
  • 2
    Thanks! This worked on my end. Been trying to call FB Open Graph API :) – decodingpanda Sep 20 '16 at 12:50
  • I was trying to access a domain of mine with invalid certificate just for test purposes and even though this disables SSL validation, it was what I needed. – carla May 30 '17 at 17:35
  • 1
    Great! I have been trying for 5 days to download an airbnb calendar on my XAMPP test site using file_get_contents, this solved the problem, thanks. – JohnnyBeGood Feb 16 '19 at 13:08
  • Worked for me trying to connect to Vagrant test box without a valid HTTP certificate over https. Link to PHP SSL Context options being set here: http://php.net/manual/en/context.ssl.php ; verify peer = Require verification of SSL certificate used; verify_peer_name=Require verification of peer name. – Anthony Mar 14 '19 at 16:53
  • 3
    isn't this breaking SSL certification and is a security hole? – webchun Jun 29 '19 at 06:06
  • 1
    This is a bad Solution, youre basically disabling the SSL certification verification which allows for MITM attacks. [read more MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) – Zyfella Apr 06 '23 at 14:37
58

Try the following.

function getSslPage($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);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

Note: This disables SSL verification, meaning the security offered by HTTPS is lost. Only use this code for testing / local development, never on the internet or other public-facing networks. If this code works, it means the SSL certificate isn't trusted or can't be verified, which you should look into fixing as a separate issue.

David Gourde
  • 3,709
  • 2
  • 31
  • 65
Benjamin Crouzier
  • 40,265
  • 44
  • 171
  • 236
6

Just add two lines in your php.ini file.

extension=php_openssl.dll

allow_url_include = On

its working for me.

Ritesh Chandora
  • 8,382
  • 5
  • 21
  • 38
5

HTTPS is supported starting from PHP 4.3.0, if you have compiled in support for OpenSSL. Also, make sure the target server has a valid certificate, the firewall allows outbound connections and allow_url_fopen in php.ini is set to true.

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • I have PHP 5.2.8 with OpenSSL support. I am getting the same error with this, and the target server has a valid certificate. – James Simpson Dec 29 '09 at 16:46
  • 2
    is the firewall configured to allow outbound https connections? Usually, webserver running https do not run on port 80. is there anything else in the error apart from 'failed to open stream'? – Gordon Dec 29 '09 at 16:51
  • 1
    As far as I know it does, this is the entire error: Warning: fopen(https://...) [function.fopen]: failed to open stream: No such file or directory in /home/user/public_html/test.php on line 993 – James Simpson Dec 29 '09 at 17:29
  • and allow_url_fopen in php.ini is set to what? – Gordon Dec 29 '09 at 17:31
  • That's odd. Can you do a GET on an HTTP and an HTTPS url to see if that works? without the stream context? – Gordon Dec 29 '09 at 17:59
  • GET gives the same error as POST (going to the URL in the browser works fine). – James Simpson Dec 29 '09 at 18:33
5

I had the same error. Setting allow_url_include = On in php.ini fixed it for me.

sth
  • 222,467
  • 53
  • 283
  • 367
Jim Jones
  • 51
  • 1
  • 1
4

use the following code:

$homepage = file_get_contents("https://www.google.com",false,
                             stream_context_create([
                                'ssl'  => [
                                    'verify_peer'      => false,
                                    'verify_peer_name' => false,
                                ]
                            ])
            );
    
 echo $homepage;
Hojjat
  • 158
  • 2
  • 4
3

In my case, the issue was due to WAMP using a different php.ini for CLI than Apache, so your settings made through the WAMP menu don't apply to CLI. Just modify the CLI php.ini and it works.

dtbarne
  • 8,110
  • 5
  • 43
  • 49
1

Sometimes a server will choose not to respond based on what it sees or doesn't see in the http request headers (such as an appropriate user agent). If you can connect with a browser, grab the headers it sends and mimic them in your stream context.

GZipp
  • 5,386
  • 1
  • 22
  • 18
0

I was stuck with non functional https on IIS. Solved with:

file_get_contents('https.. ) wouldn't load.

  • download https://curl.haxx.se/docs/caextract.html
  • install under ..phpN.N/extras/ssl
  • edit php.ini with:

    curl.cainfo = "C:\Program Files\PHP\v7.3\extras\ssl\cacert.pem" openssl.cafile="C:\Program Files\PHP\v7.3\extras\ssl\cacert.pem"

finally!

Teson
  • 6,644
  • 8
  • 46
  • 69