Getting PHP CURL to Call HTTPS URLs on Windows

So Windows Server is a fantastic environment for PHP, it has only improved and will only continue to improve.  However, CURL no longer bundles the root certificates in any builds and this causes problems when you look to leverage curl to do something like call an API with HTTPS in the URL.  Some will recommend you disable the verifyhost option in CURL by adding these two lines:

//WARNING: this would prevent curl from detecting a ‘man in the middle’ attack
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);

But that actually opens you up a pretty wide security vulnerability called ‘man in the middle attacks’, not cool.   So here’s a better route to go that will resolve it pretty quickly:

1.  Download the root CA certificates from a known good source. The most common is: http://curl.haxx.se/docs/caextract.html  (If you don’t want to download it this way and instead want to build it yourself you can use the perl script on that page or the VBS script here: https://raw.github.com/bagder/curl/master/lib/mk-ca-bundle.vbs

2. Copy this file to a location you know something like c:windowscacert.pem

3. If you’re running PHP version 5.3.7 or later you can edit your PHP.INI file to include: curl.cainfo = “PATH_TO/cacert.pem”   Where PATH_TO is your actual path (c:/windows for example)

4. That’s it problem fixed.  If you’re not running 5.3.7 or don’t have access to the PHP.INI file then you’ll add these two lines to your php script where you set your CURL options in the script:

curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt ($ch, CURLOPT_CAINFO, “pathto/cacert.pem”);

That’s honestly all there is to it.  I know what you’re thinking though, what if I’m using a self signed cert and not actually a 3rd party cert?  Then you just need to add it to your cacert.pem file.

Leave a Reply