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
  • Your *.cer file has correct user and group set? Same as your script, that is accessing it? – Paladin Sep 29 '15 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` – Pedro Lobito Sep 29 '15 at 15:47
  • @Helge Hmm, are you sure that your `/tmp/cert.cer` is a CA(Certificate Authority) or a CA bundle, and not just a self signed certificate? if you type this command: `openssl x509 -noout -text -in /tmp/cert.cer` can you see any `CA:TRUE` string in the output? what about the `Issuer` and `Subject` fields, are they the same? – godvsdeity Sep 29 '15 at 17:07
  • Paladin, Yeah, I checked that as well. Owner is same as script execution user. Pedro, For various reasons, I'd like to keep this one bundled and expressively used in this script. @godvsdeity You got something! =D This is the output of your command: 10144:error:0906D06C:PEM routines:PEM_read_bio:no start line:/SourceCache/OpenSSL098/OpenSSL098-52.40.1/src/crypto/pem/pem_lib.c:648:Expecting: TRUSTED CERTIFICATE – Helge Talvik Söderström Sep 29 '15 at 18:15
  • 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`? – godvsdeity Sep 29 '15 at 18:21
  • @godvsdeity Yeah, I understand. It's a binary file. I haven't seen the `.cer`-extension before, but I read online that it should be a compound PEM certificate. – Helge Talvik Söderström Sep 29 '15 at 18:25
  • 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. – godvsdeity Sep 29 '15 at 18:57
  • @godvsdeity You are absolutely right. Seems the `.cer`-file was in `der`-format. The following command properly converted it and made it work: `openssl x509 -inform der -in cert.cer -outform pem -out cert.pem`. Please write an answer so I can mark it as solving the problem and give you the credit =) Thanks for your help! – Helge Talvik Söderström Sep 29 '15 at 19:24
  • 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 – godvsdeity Sep 29 '15 at 19:48

2 Answers2

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

Community
  • 1
  • 1
Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
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.

godvsdeity
  • 969
  • 8
  • 15
  • 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! – Helge Talvik Söderström Sep 29 '15 at 19:48