cURL: CURLOPT_CAPATH contains correct cert but doesn't work
Asked Answered
L

1

5

The following script works on PHP 5.6.23:

$options = [
    CURLOPT_POST => 1,
    CURLOPT_URL => 'https://uat.dwolla.com/oauth/rest/offsitegateway/checkouts',
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_POSTFIELDS => json_encode(['name'=>'value']),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_CAINFO => '/path/to/certs/GoDaddyRootCertificateAuthority-G2.crt',
];
$ch = curl_init();

curl_setopt_array($ch, $options);
if( ! $result = curl_exec($ch)) $err = curl_error($ch);
else $err = null;

curl_close($ch);

if($err) echo $err;
else print_r(json_decode($result,true));

I get the expected response from Dwolla's payment API. To make my script more dynamic, I tried to change it to refer to the directory that hosts the certs I want cURL to trust. So I changed the last option (CURLOPT_CAINFO) to:

CURLOPT_CAPATH => '/path/to/certs'

This breaks the script however and no connection is made; the error is:

SSL certificate problem: unable to get local issuer certificate

I know the directory is correct and the cert file is valid since the original script refers to the cert in that same directory. I expected cURL to scan the files in the directory and find the cert it needs but this isn't happening. Why is this?

Leonidaleonidas answered 26/8, 2016 at 21:0 Comment(5)
Rename the crt to test.crt and try again.Latoyia
@Latoyia made no difference; it works the first way (with CURLOPT_CAINFO). Same error the 2nd way (with CURLOPT_CAPATH).Leonidaleonidas
Try with this one: certs.godaddy.com/repository/gdroot-g2.crtLatoyia
@Latoyia I think if the cert was the problem, the original script in the OP wouldn't work (since it verifies the remote server against the cert I was already using). Still I tried the cert you sent, and the results are the same. Original script works; modified script yields the same errorLeonidaleonidas
Just tried (with php.ini configuration) using curl.capath (as well as openssl.capath) - both have no effect. But with openssl.cainfo it works. I'm not sure why capath doesn't work.Straightout
N
7

It does not work if you just point CApath to some directory and put the certificates into this directory. To make the finding of the correct CA certificate efficient the files in this directory need to have names derived from the subject of the certificate. For example you'll might find the following in /etc/ssl/certs:

   ff783690.0 -> UTN_USERFirst_Hardware_Root_CA.pem
   ff588423.0 -> ComSign_CA.pem
   ...

Here the filenames are based on the hashes of the certificate's subject and point to the real certificate. For information on how to create the necessary filename see How to calculate the hash value used by CA file names .

See also the man page for openssl verify:

-CApath directory
A directory of trusted certificates. The certificates should have names of the form: hash.0 or have symbolic links to them of this form ("hash" is the hashed certificate subject name: see the -hash option of the x509 utility). Under Unix the c_rehash script will automatically create symbolic links to a directory of certificates.

Neoma answered 27/8, 2016 at 5:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.