1

I'm attempting to add a custom cer-certificate to my PHP cURL request, but I keep getting this error:

error setting certificate verify locations:
  CAfile: /path/to/my/cert.cer
  CApath: none

All I've found about this error is that:

  1. The path is relative.
    As you can see, I've supplied an absolute path.

  2. The path is erroneous.
    I've tried to var_dump(file_exists($certLocation));, which gives me true, so this is not the case.

  3. The permissions on the file are incorrect.
    I've set the permissions to 777 for debugging purposes. Error remains.

  4. The path to the file doesn't have +x-permissions somewhere in the chain.
    I've set this as well, ensuring that the entire path from root has +x-permissions, and still no luck.

I'm at a loss here, having tried everything I can find, and fact is, I don't even understand what the error actually means. What is a verify location? All I can understand is that there's an error with loading the file.

Any light shed on this is greatly appreciated. See code example below.

Thanks.

Code I use:

<?php

$oCurl = curl_init($this->baseUrl);
curl_setopt($oCurl, CURLOPT_FAILONERROR, 1);
curl_setopt($oCurl, CURLOPT_TIMEOUT, $this->timeout);
curl_setopt($oCurl, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($oCurl, CURLOPT_POST, 1);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($oCurl, CURLOPT_CAINFO, "/tmp/cert.cer");

Error:

error setting certificate verify locations:
  CAfile: /tmp/cert.cer
  CApath: none
9
  • Your *.cer file has correct user and group set? Same as your script, that is accessing it? Commented Sep 29, 2015 at 15:02
  • Check the curl.cainfo value on your php.ini, if you're able to modify it change to curl.cainfo=/tmp/cert.cer Commented Sep 29, 2015 at 15:47
  • 1
    @HelgeTalvikSöderström that's an unexpected output. Isn't your /tmp/cert.cer a PEM formatted certificate? what's the output of file /tmp/cert.cer? Commented Sep 29, 2015 at 18:21
  • 1
    @HelgeTalvikSöderström oh, I think that I understand what kind of file you have; this command should read it properly now: openssl x509 -in /tmp/cert.cer -inform der -text -noout, check if it is a CA certificate; my guess is that the cer you are trying to use is not a CA or CA-bundle, or if it is, then it is not the CA which signed the certificate used on the url you try to connect to. Commented Sep 29, 2015 at 18:57
  • 1
    @HelgeTalvikSöderström oh, i was busy writing the answer, didn't notice that you commented here :) ignore my last line from answer, you have a proper CA after all xD Commented Sep 29, 2015 at 19:48

2 Answers 2

3

If your PHP installation doesn't have an up-to-date CA root certificate bundle, download the one at the curl website and save it on your server:

http://curl.haxx.se/docs/caextract.html

Then set a path to it in your php.ini file, e.g. on Windows:

curl.cainfo=c:\php\cacert.pem

NOTE:
Turning off CURLOPT_SSL_VERIFYPEER allows man in the middle (MITM) attacks, which you don't want!


SRC1 - https://stackoverflow.com/a/14064903/797495
SRC2 - http://php.net/manual/en/function.curl-setopt.php#110457

Sign up to request clarification or add additional context in comments.

Comments

2

CURLOPT_CAINFO is used in conjunction with CURLOPT_SSL_VERIFYPEER

CURLOPT_CAINFO should be set to a CA or CA-bundle in PEM format. I managed to track the curl code which triggers this error and this is what I found:

in curl/openssl.c:

if(!SSL_CTX_load_verify_locations(connssl->ctx,
                                   data->set.str[STRING_SSL_CAFILE],
                                   data->set.str[STRING_SSL_CAPATH])) {
  if(data->set.ssl.verifypeer) {
    /* Fail if we insist on successfully verifying the server. */
    failf(data, "error setting certificate verify locations:\n"
          "  CAfile: %s\n  CApath: %s",
          data->set.str[STRING_SSL_CAFILE]?
          data->set.str[STRING_SSL_CAFILE]: "none",
          data->set.str[STRING_SSL_CAPATH]?
          data->set.str[STRING_SSL_CAPATH] : "none");
    return CURLE_SSL_CACERT_BADFILE;
  }
  ...

Apparently the call on SSL_CTX_load_verify_locations returns 0 and combined with the fact of having CURLOPT_SSL_VERIFYPEER set to 1 it triggers the error.

SSL_CTX_load_verify_locations is a function from openssl library, and according to the documentation(SSL_CTX_load_verify_locations documentation), the following statements should be taken into consideration:

"If CAfile is not NULL, it points to a file of CA certificates in PEM format."

"The CAfile is processed on execution of the SSL_CTX_load_verify_locations() function."

"0 - The operation failed because CAfile and CApath are NULL or the processing at one of the locations specified failed." under RETURN VALUES section


You could try to convert your cer to a pem using the following command:

openssl x509 -in /tmp/cert.cer -inform der -outform pem -out /tmp/cert.pem

but I can't guarantee that this will work, because I'm not sure if you even have a proper CA or CA bundle file.

1 Comment

Yup, problem was that the .cer-file was in der-format. Running the command supplied to convert it from der to pem made everything work properly. Many thanks for your time and help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.