22

I've been having problems on my development server where cURL, while working perfectly with anything HTTP, does not function properly with anything HTTPS—even the exact same resource with different protocols (for testing I've been requesting google.com using both HTTP and HTTPS).

The cURL error returned is 35:

A problem occurred somewhere in the SSL/TLS handshake.

I have combed the web and SO for solutions, and all of them have been to either set CURLOPT_SSL_VERIFYPEER to false, which changes nothing, or to download the certificate file and set CURLOPT_CAINFO to its path, which also changes nothing.

When setting a certificate, I followed the instructions of this tutorial and this tutorial, trying to both download the certificate for the resource I'm requesting, and downloading a cert bundle.

I've also tried explicitly setting CURLOP_PORT to 443. For thoroughness of my question, other options I set are CURLOPT_VERBOSE=true, CURLOPT_RETURNTRANSFER=true, and CURLOPT_SSL_VERIFYHOST=2 (I've tried every combination of 1, and 2 with VERIFYPEER both true and false). I also have made sure in phpinfo() that I have OpenSSL and it is enabled.

I'm using a lot of old code that worked perfectly on my last production server, so this code has worked before. But that hosting was shared hosting and I don't know most of the configuration there.

Dharman
  • 30,962
  • 25
  • 85
  • 135
spezied
  • 221
  • 1
  • 2
  • 3
  • Are you accessing the same URL? You've hit most of the same research that I did when I ran into this issue. – Jason Mar 19 '12 at 17:01
  • I used both http:// www.google.com, which worked; and https:// www.google.com, which didn't. – spezied Mar 19 '12 at 19:08
  • @Spezied, if the supplied answer answers your question, could you please choose it as your answer so the question can be closed? Thx. – Joseph Lust Mar 24 '12 at 21:33
  • It doesn't answer the question since I clearly stated in the question that that was exactly the unsatisfactory answer I've found elsewhere in SO and on the Internet. I've since concluded that it must not be fixable in PHP; there's something wrong with PHP or my extensions or something. Though I still don't know quite how to fix that. I'll poke around and see. Thank you anyway. – spezied Apr 05 '12 at 17:29

4 Answers4

25

Curl doesn't have built-in root certificates (like most modern browser do). You need to explicitly point it to a cacert.pem file:

  curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cert/file/cacert.pem');

Without this, curl cannot verify the certificate sent back via ssl. This same root certificate file can be used every time you use SSL in curl.

You can get the cacert.pem file here: http://curl.haxx.se/docs/caextract.html

Ray
  • 40,256
  • 21
  • 101
  • 138
  • Why not just use the equivalent of the `--insecure` flag? Is there one? – Pacerier Jan 17 '16 at 21:25
  • 3
    @Pacerier setting `CURLOPT_SSL_VERIFYPEER` to false is exactly `--insecure` flag does on the command line. You don't want to do either if you care about the authenticity of your destination server – Ray Jan 18 '16 at 16:57
  • 1
    it didn't work. While `CURLOPT_SSL_VERIFYPEER` to `false` does. – n8bar May 18 '17 at 16:34
  • @n8bar then you're doing something wrong. es, disabling SSL verification always works, but once again only if you don't care about the authenticity of your destination server--not a wise security choice. – Ray May 21 '17 at 20:25
  • not working,results empty with your above code.please suggest any other – Dhanu K Nov 25 '17 at 14:55
12

How about this. It fetches what might be the HTTPS Google homepage. (Since I've disabled certificate verification, I have no way to actually know that it's the real Google homepage.) It should do the trick for you.

<?PHP

// connect via SSL, but don't check cert
$handle=curl_init('https://www.google.com');
curl_setopt($handle, CURLOPT_VERBOSE, true);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
$content = curl_exec($handle);

echo $content; // show target page
?>
miken32
  • 42,008
  • 16
  • 111
  • 154
Joseph Lust
  • 19,340
  • 7
  • 85
  • 83
  • 2
    See my answer above, ignoring cert's isn't the best option. – Ray Jul 01 '13 at 16:36
  • 5
    THIS IS INSECURE. Do not do this. Always verify the peer and the host. See other answer. – Matt S Sep 18 '13 at 15:19
  • 9
    @Matt. Depends what you're doing. Moving important stuff for finance, certainly validate HTTPS. Scraping shoe brands from a retailer site... MITM should not be a problem. Obviously consider the problem context. – Joseph Lust Sep 18 '13 at 17:37
  • 1
    The right answer is stated above. Why use this when you can just copy the cacert.pem file to your project and make your connections secure. It literally takes a second. – Jochem Kuijpers Nov 24 '15 at 23:29
  • 1
    It's true that this is insecure, however, it is fine for testing purposes where sensitive data isn't actually transmitted. Just don't use it in production. – n8bar May 18 '17 at 16:28
  • This example is not POSTing anything. – DJ Far Aug 18 '17 at 22:17
6

Find if your OS includes a directory of certificates. If so then the required CA certs will often already be included. On Ubuntu, for example, it's usually /etc/ssl/certs. If this directory exists, set the CA path parameter:

curl_setopt($ch, CURLOPT_CAPATH, '/etc/ssl/certs');

Alternatively you can reference a single CA certificate file. Include a cacert.pem file in your project or install it on your server. Download from a trusted source, e.g. cacert.org. For a single file do not set the CAPATH and instead only set CAINFO:

curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem');

Turning off peer and host verification is a quick but insecure workaround to the real problem. These features exist for good reason: so you can trust, via 3rd party, that the system you're connecting to is the one you expect.

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
Matt S
  • 14,976
  • 6
  • 57
  • 76
0
var_dump( curl_error($ch) );

will tell you the error. It might be different cause.

T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • I am not sure how does this answer the question. It might be a good advice, but OP already knew the error message. This adds nothing to this thread. – Dharman Dec 30 '19 at 13:12
  • It was useful information for me though - so there's a little dilemma but nothing impossible to not get along with, I suppose :) – Herbert Van-Vliet Jan 14 '21 at 20:48