SSL error with file_get_contents

2

When I try to open a url through file_get_contents , I'm having problems when the page is https . I do not speak of external pages, but in some libraries where the images of the application itself is opened by file_get_contents , if it has https , it generates the following error:

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 /caminho/public/test.php on line 4

Warning: file_get_contents():
Failed to enable crypto in /caminho/public/test.php on line 4

Warning: file_get_contents(http://meusite.com.br): 
failed to open stream: operation failed in /caminho/public/test.php on line 4

Of course, I know it's possible to resolve this using stream_context_create , but I do not want this solution. I use library in my application that uses file_get_contents (DOMPDF) 'and it's absurd to think about editing the source code, since if I have to do an update in the library, I would have to do the whole patch hour.

I would like to understand what is causing this error. This problem has started since we migrated from the old hosting. Currently Amazon today and the configuration was made by us. We asked for the certificate keys for each of the domains and configured it.

I would like to know if the error indicates some type of error in the configuration of our SSL, because when I make a file_get_contents to urls of Google , for example, everything works normally. >

Another important point is that SSL works normally in the browser, but is only giving file_get_contents .

You can check in this url.

Note : Please do not answer anything about "disabling" SSL verification on requests, as I do not want to create another problem (no "final temporary solutions"). I want to understand what's going on and solve.

    
asked by anonymous 24.06.2016 / 20:10

2 answers

3

Thanks to my friend @GuilhermeNascimento for the response and @Bacco to have helped in the chat to solve the problem.

I finally got it resolved!

Let's take the necessary steps. I'm using PHP version 5.6.

Once you have made all the necessary settings in apache, you need to do a configuration for PHP.

First, we need to find the location of the certificate file PHP is reading. It can be seen through the openssl_get_cert_locations function.

In my case, it returned the following:

[
 "default_cert_file" => "/usr/lib/ssl/cert.pem",
 "default_cert_file_env" => "SSL_CERT_FILE",
 "default_cert_dir" => "/usr/lib/ssl/certs",
 "default_cert_dir_env" => "SSL_CERT_DIR",
 "default_private_dir" => "/usr/lib/ssl/private",
 "default_default_cert_area" => "/usr/lib/ssl",
 "ini_cafile" => "/usr/lib/ssl/cert.pem",
 "ini_capath" => "",
]

Looking at the value of default_cert_file , you now know where PHP reads the Certified Intermediates .

Explaining very quickly, the cert.pem file contains a list of trusted certificates from each Certification Authority. It is called CA Bundle .

You should download it at this link and move it to the location returned in default_cert_file . Or you can download it to a different location and set the location of your file through php.ini through openssl.cafile .

openssl.cafile = /caminho/do/cacert.pem

Every time you make a request by PHP via curl or any other function using the wrapper https , using the verify_peer option, PHP will read this file to find out which are the valid Certificate Authority.

After these operations, if the error shown in the question still remains, you must manually add the intermediate code of your SSL certificate at the end of the file.

The @Bacco user recommended me to access the browser itself and download this code.

See the image:

Inmycase,IchosetheRapidSSLSHA256CAoptionandexportedthedata.Youcandothisinanybrowser.ThenamewillchangeaccordingtoyourCertificationAuthority.

  

Important

    

FromthemomentyouareaddinganewCAtoyoursystem,  youaresayingyoutrust"blindly" in that entity, so just do   this is really if it is a certificate that you are sure   absolute of the origin and suitability.

Note : You can also find the code on the SSL Service Provider website, but in my case it worked better by downloading from the browser.

The code that you will download from the certificate will look something like this:

-----BEGIN CERTIFICATE-----
MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
-----END CERTIFICATE-----

After that, edit the file marked as default_cert_file in your PHP. In my case, I renamed cert.pem after download. Now add the code of the certificate you downloaded from the browser (or the CA certificate you are using) and add it to the previously cited file. It is recommended that you put in the end of your.

After this you may have to restart Apache, but in my case, you did not need to.

CA Bundle Link:

link

    
27.06.2016 / 19:54
2

I may be wrong, but depending on the answers here link you should download the #

$url = 'https://site';

$streamSSL = stream_context_create(array(
    "ssl"=>array(
        "cafile" => "/path/cacert.pem",
        "verify_peer"=> true,
        "verify_peer_name"=> true
    )
));

$response = file_get_contents($url, false, $streamSSL);

PHP 5.6

In php5.6 it is possible to configure openssl via php.ini ( link ):

p>
  

openssl.cafile "" PHP_INI_PERDIR Available since PHP 5.6.0

     

openssl.capath "" PHP_INI_PERDIR Available since PHP 5.6.0

Example:

openssl.cafile=/path/cacert.pem

So I believe you can set the path. As for capath if not specified it will look for a suitable one, so I think it might be possible to directly use file_get_contents:

$url = 'https://site';

$response = file_get_contents($url, false);

CURL

As I mentioned, I believe that if SSL (openssl) is installed it should work without any configuration, curl is also this way, but it is available since Available since PHP 5.3.7 in php.ini using curl.cainfo = /path/cacert.pem :

$url = 'https://site';

$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);
  

Note: The certificate path must be absolute

Installing ssl

I think the only thing that needs to be set up is openssl enabling extension for it, if it is Windows and debian-based distros (repository), just remove comment ( ;extension= ) in the following line:

extension=openssl.so

or (windows):

extension=php_openssl.dll

However if you compiled PHP yourself (using make for example, you will need to recompile) using the --with-openssl[=DIR] parameter ( link )

If Debian / ubuntu / etc install libssl (if not installed):

  • Debian:

    su
    apt-get install libssl1.0.0
    
  • Ubuntu:

    sudo apt-get install libssl1.0.0
    
24.06.2016 / 20:43