Home > Mobile >  CURLOPT_SSL_VERIFYHOST returns SSL certificate problem: certificate has expired when certificate is
CURLOPT_SSL_VERIFYHOST returns SSL certificate problem: certificate has expired when certificate is

Time:12-20

Initial problem - Ignore and scroll to UPDATE section

I am performing a cURL to a remote URL. When I set CURLOPT_SSL_VERIFYHOST second argument to 2 as it is suggested, it returns SSL certificate problem: certificate has expired

Clearly however, my remote domain has a valid cert. Tested with https://whatsmychaincert.com/.

The problem seems to go away if I perform the cURL directly to the https://www.sub.domain.com/, and appears when I perform the cURL to the folder/params address where I need to get data from (i.e. https://www.sub.domain.com/index.php?param=one)

However, I also tested that URL with https://whatsmychaincert.com/ and of course, the certificate chain is valid.

This is my code:

$url = 'https://www.sub.domain.com/folder/index.php';
$ch = curl_init( $url . '?param=test' );
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 2 );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 2 );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$content  = @curl_exec( $ch );

if( curl_errno( $ch ) ) {
   $content = curl_error( $ch );
}

$code = curl_getinfo( $ch, CURLINFO_RESPONSE_CODE );
curl_close( $ch );
error_log( print_r( $content, true ), 0 );

The logs will say SSL certificate problem: certificate has expired in this case. If $url = 'https://www.sub.domain.com/folder/index.php'; is $url = 'www.sub.domain.com';, then it does not throw that error. But this makes no sense. The chain is intact, there should be no need (and is not possible anyway by my knowledge) to generate a certificate for https://www.sub.domain.com/folder/index.php, as long sub.domain.com has a valid certificate.

UPDATE

Suspect Lets Encrypt to be the issue cause This problem happens on ALL domains I tried with unless the ones using certificates issued by CloudFlare or Amazon. The others, where the issue happens, all use Lets Encrypt certificates. Valid, non-expired certificates, but the issuing authority is not CF or Amazon in this case, rather Lets Encrypt. Very easily replicable, just use this code:

$ch = curl_init();

// set url 
curl_setopt($ch, CURLOPT_URL, "https://example.com/");

//return the transfer as a string 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$errorFile = dirname(__FILE__) . '/curl_error.txt';
$out       = fopen($errorFile, "w");
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_STDERR, $out);

// $output contains the output string 
$output = curl_exec($ch);

curl_close($ch);
fclose($out);

On LE certificates you will get SSL certificate problem: certificate has expired On (example) netflix.com or similar Amazon/CF issued certs, you will get no error.

Happens with the very letsencrypt.org domain too!

Something is wrong with Lets Encrypt. Any other issuer does not present this issue.

CodePudding user response:

The problem is an outdated local certificate.

In my case, I was using MAMP. MAMP does not update the certificates seemingly and you need to do that manually. Since LE's main certificate expired late September 2021, and MAMP did not update it - the cURL of course failed.

The easiest is to install a fresh version of MAMP freshly downloaded from their site, since they are not able to do that when MAMP (the app) performs updates.

  • Related