If you are using PHP’s cURL functions to connect to a HTTPS URL, you might come across the following error:
SSL certificate problem: unable to get local issuer certificate. (cURL error code 60)
This is a common error that occurs whenever you attempt to use PHP’s cURL functions to connect to a HTTPS website. Essentially, your cURL client has not been configured to connect to SSL-enabled websites.
The Quick Fix.
If you do not care about security and you are looking for a quick fix, then you can simply disable the following cURL options:
- CURLOPT_SSL_VERIFYHOST: This option tells cURL that it must verify the host name in the server cert.
- CURLOPT_SSL_VERIFYPEER: This option tells cURL to verify the authenticity of the SSL cert on the server.
Disabling these two options disables SSL verification.
To disable these two options, you can use the curl_setopt function like so:
//The URL we are connecting to.
$url = 'https://google.com';
$ch = curl_init($url);
//Disable CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER by
//setting them to false.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//Execute the request.
//Check for errors.
throw new Exception(curl_error($ch));
The code above essentially tells cURL that we don’t care if the server has a valid SSL cert or not. We want to connect to it anyway.
The problem with this method is that it is insecure and it leaves you open to man-in-the-middle attacks. Simply put, this means that an attacker could potentially intercept the data that you are sending in your cURL requests.
Using a cert with PHP’s cURL functions.
To use a certificate with PHP’s cURL functions, you can download the cacert.pem certificate bundle from the official cURL website. Once you have downloaded the cacert.pem file, you should move it to whatever directory makes the most sense for you and your setup. On Windows, I moved my bundle to C:\wamp\cacert.pem
Then, you can simply tell cURL where your certificate bundle is located by using the curl_setopt function:
//Tell cURL where our certificate bundle is located.
$certificate = "C:\wamp\cacert.pem";
curl_setopt($ch, CURLOPT_CAINFO, $certificate);
curl_setopt($ch, CURLOPT_CAPATH, $certificate);
This allows us to make a secure request to the server and prevent any man-in-the-middle attacks.
Adding the cert to your php.ini file.
If you don’t like the thought of having to specify the location of the certificate bundle in your PHP code, then you can add it’s path information to your php.ini file like so:
Once you add the above lines to your php.ini file, make sure that you reload the web server / PHP process so that the changes take effect.
Enabling mod_ssl and php_openssl.dll.
If you’re using Apache and PHP on Windows, you might need to enable both mod_ssl and php_openssl.dll.
To enable mod_ssl, you can add the following to your Apache configuration file:
LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so
Note that the above configuration line assumes that a file called mod_ssl.so exists in a Linux directory called “/usr/lib/httpd/modules/”. On Windows, this directory might be something like “C:\wamp\bin\apache\apache2.4.9\modules\“. You will need to change this line to match your own Apache setup.
To enable php_openssl.dll, you will need to uncomment the following line in your php.ini file:
When you find the line above, make sure that there isn’t a semi-colon at the start of it.
As always, you should test your configurations and then reload them for any changes to take effect.