An often heard solution to PHP cURL errors with SSL is to turn off CURLOPT_SSL_VERIFYPEER. Please don’t turn off CURLOPT_SSL_VERIFYPEER, but fix your PHP config instead. This article provides you with two solutions to solve CA certificate validation errors with PHP cURL and OpenSSL. For system administrators and end-users.

Here you’ll learn what you need to do to fix your PHP cURL configuration.

Don’t turn off CURLOPT_SSL_VERIFYPEER in your PHP config; fix cURL errors by updating cURL’s bundle of CA root certificates and your php.ini configuration.

When PHP cURL throws error messages like “routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed“, or “SSL certificate problem, verify that the CA cert is OK“, cURL can’t validate a certificate’s CA. The error is often caused by an outdated or missing bundle of CA root certificates, in your PHP configuration.

This post provides two solutions to fix the CA validation with PHP cURL, and one for OpenSSL. For you, as system administrators and end-users.

Pádraic Brady writes:

[…] The options here are somewhat obvious, configuring PHP to use SSL properly is added complexity that programmers are tempted to ignore. Once you go down that road and once you start throwing user data into those connections, you have inherited a security vulnerability that poses a real risk to users. Perhaps more telling is the following function call using the cURL extension for HTTPS connections in place of PHP built-in feature.

This one is far worse than PHP’s default position since a programmer must deliberately disable peer verification in cURL. That’s blatantly the fault of the programmer and, yes, a lot of programmers do this. To deliberately disable SSL’s protection of user data, assuming it’s not due to ignorance, can only be described as loathsome and the tolerance afforded to such security vulnerabilities, at a time when browsers and Certificate Authorities would be publicly and universally condemned for the same thing, reflects extremely poorly on PHP programmers taking security seriously.

Seriously, do NOT do this. Yes, you’ll get more errors (browsers display big red warnings too). Yes, end programmers may need to define a path to a CA file. Yes, this is all extra work (and examples are scarce on the ground as to how to do it properly). No, it is NOT optional. Keeping user data secure outweighs any programming difficulty. Deal with it.

As you see, there’s a whole lot of misinformation about how to deal with these SSL certificate problem, verify that the CA cert is OK errors with cURL.

Nearly everyone advises you to turn off CURLOPT_SSL_VERIFYPEER, and in fact, countless comments on the PHP manual page for curl_setopt tell you to do this.

This is bad, because it allows your nice, encrypted stream of confidential data to be silently hijacked by a bad guy. So, don’t to that! Instead, fix your PHP php.ini configuration.

And the SSL certificate problem, verify that the CA cert is OK error is caused by not having an up-to-date bundle of CA root certificates, available to cURL, on your system. Not someone else’s.

The bundle of CA root certificates is typically an ordinary text file with cryptographic signatures. CURL uses this to verify a host’s SSL- or TLS certificate. Therefore you need to make sure that your PHP installation has one of these files, and that it’s up to date.

Add CA root certificates bundle in php.ini

As a systems administrator:

To add a Certificate Authority CA root certificates bundle in your php.ini file, you need to download the cacert.pem CA root certificate bundle from curl.haxx.se.

Then configure the path to this file in your php.ini file:

; Windows Server IIS:
curl.cainfo = c:\path\to\php\cacert.pem

This is often only required on Windows Server, not Linux.

End-user, read on to learn how you can easily fix the CA validation in cURL yourself. One of the errors caused by an outdated -or missing- bundle of CA root certificates is a WordPress Jetpack activation error.

What Are CA Certificates?

What exactly are CA certificates?

CA certificates are all about trust. Certification authority (CA) certificates are certificates that are issued by a CA to itself or to a second CA for the purpose of creating a defined relationship between the two CAs. A certificate that is issued by a CA to itself is referred to as a trusted root certificate, because it is intended to establish a point of ultimate trust for a CA hierarchy.

Once the trusted root has been established, it can be used to authorize subordinate CAs to issue certificates on its behalf. Although the relationship between CAs is most commonly hierarchical, CA certificates are also used to establish trust relationships between CAs in two different public key infrastructure (PKI) hierarchies.

In all of these cases, the CA certificate is critical to defining the certificate path and usage restrictions for all end entity certificates issued for use in the PKI.

Jetpack register_http_request_failed

Fix Jetpack register_http_request_failed errors: How to register and activate Jetpack with WordPress properly!

One often reported error message is with activating the Jetpack plugin in WordPress. The error is:

Jetpack could not contact WordPress.com: register_http_request_failed. This usually means something is incorrectly configured on your web host. SSL certificate problem: self signed certificate in certificate chain

As a solution, you often read about turning off CURLOPT_SSL_VERIFYPEER a lot. Well, don’t do that! In fact, don’t do this ever!

You can easily overcome and resolve this error by manually editing a line in /wp-includes/class-http.php, if your web host is unable or unwilling to update the cURL root certificates (cacert.pem file). Point your web host to this blog post for information.

First you need to download an up to date bundle of CA root certificates.

Fix the “register_http_request_failed” error and activate Jetpack properly

Here is how to fix "Jetpack could not contact WordPress.com: register_http_request_failed. This usually means something is incorrectly configured on your web host." in just a few steps, and you are to able to connect the Jetpack plugin activation:

  1. download the cacert.pem file (http://curl.haxx.se/ca/cacert.pem) to your computer
  2. upload cacert.pem to your website, preferably to an unwritable location (but readable for the web server, just to protect the file)
  3. download and open the wp-includes/class-http.php file
  4. somewhere around line 1084, within function request() of class WP_Http_Curl{}, add:
    curl_setopt( $handle, CURLOPT_CAINFO, "/path/to/domain/cacert.pem" );
  5. save and upload the file to the wp-includes/ folder

Jetpack is now able to connect to WordPress!

PHP OpenSSL.cafile, use sslverify = true

Don’t set sslverify = false for wp_remote_get() in WordPress!

The default CA bundle may be overridden on a global basis by setting either the openssl.cafile or openssl.capath configuration setting, or on a per request basis by using the cafile or capath context options.

For OpenSSL, you have to configure an openssl.cafile path in your PHP installation as well:

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile=c:\php70\cacert.pem

As with cURL curl.cainfo, this is only necessary on Windows Server.

This setting fixes WordPress errors you get with the WordPress HTTP API like SSL certificate problem: unable to get local issuer certificate.. See Developers: Stop Using sslverify = false @SkyVerge for more information. My colleague Pieter also runs a post urging developers not to set sslverify to false.

Psstt: Curious how to boost PHP performance with WinCache and OPcache? Learn how to add SSL in WordPress.