HTTPS and SSL3_GET_SERVER_CERTIFICATE:certificate verify failed, CA is OK

PhpSslCurlOpensslCa

Php Problem Overview


I am using XAMPP for development. Recently I upgraded my installation of xampp from an old version to 1.7.3.

Now when I curl HTTPS enabled sites I get the following exception

> Fatal error: Uncaught exception 'RequestCore_Exception' with message > 'cURL resource: Resource > id #55; cURL error: SSL certificate problem, verify that the CA cert is OK. Details: > error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (60)'

Everyone suggest using some specific curl options from PHP code to fix this problem. I think this shouldn't be the way. Because I didn't have any problem with my old version of XAMPP and happened only after installing the new version.

I need help to figure out what settings change in my PHP installation, Apache etc can fix this problem.

Php Solutions


Solution 1 - Php

It's a pretty common problem in Windows. You need just to set cacert.pem to curl.cainfo.

Since PHP 5.3.7 you could do:

  1. download https://curl.se/ca/cacert.pem and save it somewhere.
  2. update php.ini -- add curl.cainfo = "PATH_TO/cacert.pem"

Otherwise you will need to do the following for every cURL resource:

curl_setopt ($ch, CURLOPT_CAINFO, "PATH_TO/cacert.pem");

Solution 2 - Php

curl used to include a list of accepted certificate authorities (CAs) but no longer bundles ANY CA certs since 7.18.1 and onwards. So by default it'll reject all TLS/SSL certificates as unverifiable.

You'll have to get your CA's root certificate and point curl at it. More details at curl's details on TLS/SSL certificates verification.

Solution 3 - Php

Warning: this can introduce security issues that SSL is designed to protect against, rendering your entire codebase insecure. It goes against every recommended practice.

But a really simple fix that worked for me was to call:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

before calling:

curl_exec():

in the php file.

I believe that this disables all verification of SSL certificates.

Solution 4 - Php

Source: http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

> #Curl: SSL certificate problem, verify that the CA cert is OK# > ###07 April 2006### > > When opening a secure url with Curl you may get the following error: > > SSL certificate problem, verify that the CA cert is OK > > I will explain why the error and what you should do about it. > > The easiest way of getting rid of the error would be adding the > following two lines to your script . This solution poses a security > risk tho. > > > //WARNING: this would prevent curl from detecting a 'man in the middle' attack > curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); > curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0); > > Let see what this two parameters do. Quoting the manual. > > CURLOPT_SSL_VERIFYHOST: 1 to check the existence of a common name in the SSL peer certificate. 2 to check the existence of a common name > and also verify that it matches the hostname provided. > > CURLOPT_SSL_VERIFYPEER: FALSE to stop CURL from verifying the peer's certificate. Alternate certificates to verify against can be > specified with the CURLOPT_CAINFO option or a certificate directory > can be specified with the CURLOPT_CAPATH option. > CURLOPT_SSL_VERIFYHOST may also need to be TRUE or FALSE if > CURLOPT_SSL_VERIFYPEER is disabled (it defaults to 2). Setting > CURLOPT_SSL_VERIFYHOST to 2 (This is the default value) will garantee > that the certificate being presented to you have a 'common name' > matching the URN you are using to access the remote resource. This is > a healthy check but it doesn't guarantee your program is not being > decieved. > > ###Enter the 'man in the middle'### > > Your program could be misleaded into talking to another server > instead. This can be achieved through several mechanisms, like dns or > arp poisoning ( This is a story for another day). The intruder can > also self-sign a certificate with the same 'comon name' your program > is expecting. The communication would still be encrypted but you would > be giving away your secrets to an impostor. This kind of attack is > called 'man in the middle' > > ###Defeating the 'man in the middle'### > > Well, we need to to verify the certificate being presented to us is > good for real. We do this by comparing it against a certificate we > reasonable* trust. > > If the remote resource is protected by a certificate issued by one of > the main CA's like Verisign, GeoTrust et al, you can safely compare > against Mozilla's CA certificate bundle which you can get from > http://curl.se/docs/caextract.html > > Save the file cacert.pem somewhere in your server and set the > following options in your script. > > > curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE); > curl_setopt ($ch, CURLOPT_CAINFO, "pathto/cacert.pem");

for All above Info Credit Goes to : http://ademar.name/blog/2006/04/curl-ssl-certificate-problem-v.html

Solution 5 - Php

The above solutions are great, but if you're using WampServer you might find setting the curl.cainfo variable in php.ini doesn't work.

I eventually found WampServer has two php.ini files:

C:\wamp\bin\apache\Apachex.x.x\bin
C:\wamp\bin\php\phpx.x.xx

The first is apparently used for when PHP files are invoked through a web browser, while the second is used when a command is invoked through the command line or shell_exec().

TL;DR

If using WampServer, you must add the curl.cainfo line to both php.ini files.

Solution 6 - Php

For the love of all that is holy...

In my case, I had to set the openssl.cafile PHP config variable to the PEM file path.

I trust it is very true that there are many systems where setting curl.cainfo in PHP's config is exactly what is needed, but in the environment I'm working with, which is the eboraas/laravel docker container, which uses Debian 8 (jessie) and PHP 5.6, setting that variable did not do the trick.

I noticed that the output of php -i did not mention anything about that particular config setting, but it did have a few lines about openssl. There is both an openssl.capath and openssl.cafile option, but just setting the second one allowed curl via PHP to finally be okay with HTTPS URLs.

Solution 7 - Php

Sometimes if the application you try to contact has self signed certificates, the normal cacert.pem from http://curl.haxx.se/ca/cacert.pem does not solve the problem.

If you are sure about the service endpoint url, hit it through browser, save the certificate manually in "X 509 certificate with chain (PEM)" format. Point this certificate file with the

curl_setopt ($ch, CURLOPT_CAINFO, "pathto/{downloaded certificate chain file}");   

Solution 8 - Php

I have the same error on amazon AMI linux.

I Solved by setting curl.cainfo on /etc/php.d/curl.ini

https://gist.github.com/reinaldomendes/97fb2ce8a606ec813c4b

Addition October 2018

On Amazon Linux v1 edit this file

vi /etc/php.d/20-curl.ini

To add this line

curl.cainfo="/etc/ssl/certs/ca-bundle.crt"

Solution 9 - Php

When setting the curl options for CURLOPT_CAINFO please remember to use single quotes, using double quotes will only cause another error. So your option should look like:

curl_setopt ($ch, CURLOPT_CAINFO, 'c:\wamp\www\mywebfolder\cacert.pem');

Additionally, in your php.ini file setting should be written as:(notice my double quotes)

curl.cainfo = "C:\wamp\www\mywebfolder"

I put it directly below the line that says this: extension=php_curl.dll

(For organizing purposes only, you could put it anywhere within your php.ini, i just put it close to another curl reference so when I search using keyword curl I caan find both curl references in one area.)

Solution 10 - Php

I ended up here when trying to get GuzzleHttp (php+apache on Mac) to get a page from www.googleapis.com.

Here was my final solution in case it helps anyone.

Look at the certificate chain for whatever domain is giving you this error. For me it was googleapis.com

openssl s_client -host www.googleapis.com -port 443

You'll get back something like this:

Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.googleapis.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority

Note: I captured this after I fixed the issue, to your chain output may look different.

Then you need to look at the certificates allowed in php. Run phpinfo() in a page.

<?php echo phpinfo();

Then look for the certificate file that's loaded from the page output:

openssl.cafile	/usr/local/php5/ssl/certs/cacert.pem

This is the file you'll need to fix by adding the correct certificate(s) to it.

sudo nano /usr/local/php5/ssl/certs/cacert.pem

You basically need to append the correct certificate "signatures" to the end of this file.

You can find some of them here: You may need to google/search for others in the chain if you need them.

They look like this:

example certificate image

(Note: This is an image so people will not simply copy/paste certificates from stackoverflow)

Once the right certificates are in this file, restart apache and test.

Solution 11 - Php

You could try to reinstall the ca-certificates package, or explicitly allow the certificate in question as described here.

Solution 12 - Php

The solution is very simple! Put this line before curl_exec:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

For me it works.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJosnidhinView Question on Stackoverflow
Solution 1 - PhpАртур КурицынView Answer on Stackoverflow
Solution 2 - PhpMarc BView Answer on Stackoverflow
Solution 3 - PhpChris DutrowView Answer on Stackoverflow
Solution 4 - PhpDeepak OberoiView Answer on Stackoverflow
Solution 5 - PhpNateView Answer on Stackoverflow
Solution 6 - PhpSpencer WilliamsView Answer on Stackoverflow
Solution 7 - PhpmadRaiView Answer on Stackoverflow
Solution 8 - PhpReinaldo MendesView Answer on Stackoverflow
Solution 9 - PhpLOwens1931View Answer on Stackoverflow
Solution 10 - PhpTrophyGeekView Answer on Stackoverflow
Solution 11 - PhpsiteView Answer on Stackoverflow
Solution 12 - PhpZsolt BoszormenyiView Answer on Stackoverflow