A problem occurred somewhere in the SSL/TLS handshake
Asked Answered
A

4

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.

Augustusaugy answered 19/3, 2012 at 16:53 Comment(4)
Are you accessing the same URL? You've hit most of the same research that I did when I ran into this issue.Isometric
I used both http:// www.google.com, which worked; and https:// www.google.com, which didn't.Augustusaugy
@Spezied, if the supplied answer answers your question, could you please choose it as your answer so the question can be closed? Thx.Litigant
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.Augustusaugy
M
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

Marita answered 1/7, 2013 at 16:36 Comment(5)
Why not just use the equivalent of the --insecure flag? Is there one?Illuminating
@Illuminating 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 serverMarita
it didn't work. While CURLOPT_SSL_VERIFYPEER to false does.Shavon
@Shavon 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.Marita
not working,results empty with your above code.please suggest any otherVauntcourier
L
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
?>
Litigant answered 21/3, 2012 at 1:35 Comment(6)
See my answer above, ignoring cert's isn't the best option.Marita
THIS IS INSECURE. Do not do this. Always verify the peer and the host. See other answer.Gaul
@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.Litigant
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.Sisterly
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.Shavon
This example is not POSTing anything.Granduncle
G
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);
Gaul answered 5/6, 2017 at 15:23 Comment(0)
B
0
var_dump( curl_error($ch) );

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

Bucko answered 2/12, 2019 at 22:3 Comment(2)
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.Gizela
It was useful information for me though - so there's a little dilemma but nothing impossible to not get along with, I suppose :)Sufi

© 2022 - 2024 — McMap. All rights reserved.