Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cURL: CURLOPT_CAPATH contains correct cert but doesn't work

Tags:

php

curl

ssl

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?

like image 401
BeetleJuice Avatar asked Aug 26 '16 21:08

BeetleJuice


1 Answers

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.

like image 165
Steffen Ullrich Avatar answered Sep 22 '22 14:09

Steffen Ullrich