PHP, SSL, and cURL SSL3_GET_SERVER_CERTIFICATE Errors

By  on  

I recently developed a complex system for a customer that involved PHP, cURL, and a SSL connection to a third party vendor. The third party vendor would validate the security certificate of the source (the system I created) and either allow or reject access. My code looked like this:

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,'https://thirdparty.com/token.php'); //not the actual site
curl_setopt($ch,CURLOPT_TIMEOUT,60);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,'customer_id='.$cid.'&password='.$pass);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,true); 
curl_setopt($ch,CURLOPT_CAINFO,'ca-bundle.crt'); /* problem here! */
$result = curl_exec($ch);
if(empty($result)) { /* error: nothing returned */ } else { /* success! */ }
curl_close($ch);

Unfortunately I was persistently receiving the following error message:

error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

It turns out that the SSL bundle file I was using was old, as was the default bundle that came with the old version of cURL the shared hosting server. Essentially the third party didn't trust that the system's SSL certificate was valid. I downloaded Mozilla's bundle file, named it mozilla.pem and changed my PHP code to:

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,'https://thirdparty.com/token.php'); //not the actual site
curl_setopt($ch,CURLOPT_TIMEOUT,60);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_POSTFIELDS,'customer_id='.$cid.'&password='.$pass);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,true); 
curl_setopt($ch,CURLOPT_CAINFO,'mozilla.pem'); /* fixed! */
$result = curl_exec($ch);
if(empty($result)) { /* error: nothing returned */ } else { /* success! */ }
curl_close($ch);

I share this with you because it cost me over three hours. Hopefully this will save someone time and frustration in the future.

Recent Features

  • By
    CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

  • By
    5 Awesome New Mozilla Technologies You’ve Never Heard Of

    My trip to Mozilla Summit 2013 was incredible.  I've spent so much time focusing on my project that I had lost sight of all of the great work Mozillians were putting out.  MozSummit provided the perfect reminder of how brilliant my colleagues are and how much...

Incredible Demos

  • By
    dwProgressBar v2:  Stepping and Events

    dwProgressBar was a huge hit when it debuted. For those of you who didn't catch my first post, dwProgressBar is a MooTools 1.2-based progress bar which allows for as much flexibility as possible. Every piece of dwProgressBar can be controlled by CSS...

  • By
    Generate Dojo GFX Drawings from SVG Files

    One of the most awesome parts of the Dojo / Dijit / DojoX family is the amazing GFX library.  GFX lives within the dojox.gfx namespace and provides the foundation of Dojo's charting, drawing, and sketch libraries.  GFX allows you to create vector graphics (SVG, VML...

Discussion

  1. Thanks for sharing. That’s going to same someone a great deal of time.

  2. Great post. Thanks…

  3. “Hopefully this will save someone time and frustration in the future.”

    Yes, it has saved many time to me. There is, however, a point that you don’t explain in your article: where to put the Mozilla’s bundle file? I develop using WAMP, and this is the code I use:

    curl_setopt($rRequest, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($rRequest, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($rRequest, CURLOPT_CAINFO, "C:\path\sub-path\wamp\www\php\mozilla.pem");
    

    The CURLOPT_SSL_VERIFYHOST option verify that the name field matches the host name of the server.

    More information:
    Using cURL in PHP to access HTTPS (SSL/TLS) protected sites

  4. SomeDude

    I still can’t get mine to work. I’m getting this problem with my Facebook app.

    • Koen

      Dear somedude, did you fix your SSL CURL error that you were experiencing with your Facebook app? I’m experiencing the same thing and cannot get it fixed!

  5. Dude, you saved my life! ;o)

  6. az

    Very helpful. Thank you!

  7. i am getting this now.
    error setting certificate verify locations:

  8. Neelesh

    Thanks david… But I don’t understand How its working for common cert file ,that I downloaded from above link..

  9. Weston

    THANKS YOU SOOOOO MUCH.

    This _did_ save me hours of time!

  10. Alfredo

    David, thank you for saving me three invaluable hours!

  11. mozilla rocks

    thanks dave

  12. yuvraj jain

    Thanks David, it saved my important hours:). I have faced the same problem and this article solved all the things.

    Keep posting man Thanks again.

  13. Lech

    Thank you for the info and link, but I think what you mean is that *your* system did not trust the third party’s certificate.

  14. Mohamed

    Or you could just turn ssl verification off

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
    
  15. Ferg

    Thank you so much! I only wish I had found this post sooner.

  16. mark

    you can check if both ends use the same ssl version: http://newexception.com/php-curl-https

  17. Abhay

    Hi David,

    Even after updating the certs, I get same error

    I have also set absolute path for the latest crt file

        curl_setopt($ch, CURLOPT_CAPATH, "/path/to/certfile");
        curl_setopt($ch, CURLOPT_CAINFO, "cacert.pem"); 
    

    —————-
    successfully set certificate verify locations:
    * CAfile: none
    CApath: /etc/ssl/certs
    * SSL certificate problem, verify that the CA cert is OK. Details:
    error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
    * Closing connection #0
    —————-

  18. Chintan

    Thanks a lot !! It helped me ..

  19. Evan

    Saved me a bunch of time too. Thanks.

  20. sdiver

    Hello, is it secure to put the “cacert.pem” file under the public site directory? Or it’s better to put it out of the web directory?

    Thank you

  21. Ptrol

    Thx! Dude! you save my time!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!