0

I know there are several posts about this topic but I've tried a lot and nothing has worked.

    curl_setopt($ch, CURLOPT_URL, "https://127.0.0.1:2288");
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
    curl_setopt($ch, CURLOPT_USERPWD, $this->username . ":" . $this->password);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $pRequest);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
    curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($ch, CURLOPT_CAINFO, "/etc/ssl/certs/cacert.pem");
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

When I execute it on Ubuntu 20.04 machine, i get this error:

Fatal error: Uncaught RuntimeException: Unable to connect to https://127.0.0.1:2288/ Error: SSL certificate problem: self signed certificate

The certificate is the current version from curl.se/docs/caextract.html

php.ini:

extension=curl
extension=php_curl.dll
curl.cainfo="/etc/ssl/certs/cacert.pem"

What else can I do without prohibiting curl ssl connections?

serbe204
  • 1
  • 2

2 Answers2

0

If you are using self-signed certificates you either have to add it to your trusted certificates or you have to turn validation off. For the second case just switch the CURLOPT_SSL_VERIFYPEER to false.

Spocklw
  • 9
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 16 '21 at 19:22
0

You are connecting securely to localhost on Ubuntu and, as your error indicates, your server is responding with a self-signed certificate. Your code specifies that curl should attempt to verify the host it's connecting to (localhost, in your case):

curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);

According to the docs, that value of 2 in your code for CURLOPT_SSL_VERIFYHOST is documented thusly:

2 to verify that a Common Name field or a Subject Alternate Name field in the SSL peer certificate matches the provided hostname. 0 to not check the names. 1 should not be used. In production environments the value of this option should be kept at 2 (default value).

If you want to strictly follow the documentation's recommendation, you'd have to map some domain onto localhost and install a cert for that domain on your server. AFAIK, you cannot get a cert for 127.0.0.1 because that special IP address always refers to localhost...sort of a long story but it makes no sense for anyone to sign such a cert.

Your other option is to tell curl not to verify the ssl connection CURLOPT_SSL_VERIFYHOST to zero:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// you may also need to set this?
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

That tells curl not to bother validating the certificate. This should be fairly safe if your are in control of your own server and if your server hasn't been compromised somehow.

EDIT I would add that downloading the cert extract from curl.se just grabs a bundle of widely trusted signatures/certificates that happens to be the bundle used by Firefox. This cert bundle is used to check any domain that you might visit by comparing the signature on that domain's certificate to some big/important certificates that have been signed by supposedly trustworthy organizations. It will never be helpful in validating a self-signed certificate. For more information about this elaborate concept, try reading about Web of Trust.

I should also mention that you might be able to use a few commands to grab the certificate that your local machine coughs up and configure your curl code to use that certificate, HOWEVER, the CURLOPT_SSL_VERIFYHOST setting of 2 instructs curl to check the Common Name field of this certificate against the IP address or domain to which you are connecting. On my ubuntu workstation, the certificate's Common Name is 'Ubuntu' -- and that won't match either localhost or 127.0.0.1. For this approach to work, you'll either have to generate a new cert for your machine with a Common Name that matches the address to which you connect (localhost or 127.0.0.1) OR you'll need to set up something to name your machine 'ubuntu' on your local network.

S. Imp
  • 2,833
  • 11
  • 24
  • If I set `CURLOPT_SSL_VERIFYHOST` to zero, same error occurs – serbe204 Oct 16 '21 at 18:58
  • Hmmm...it was working on my machine. I edited my post so that the code also sets CURLOPT_SSL_VERIFYPEER to false. Hopefully that will help. – S. Imp Oct 17 '21 at 00:00
  • Please... do not set CURLOPT_SSL_VERIFYPEER to false: https://stackoverflow.com/a/23585500/2657515 – JonathanDavidArndt Dec 14 '22 at 20:26
  • @JonathanDavidArndt that other post is never going to fix a situation where someone is using a **self-signed* certificate. No matter which bundle of CA root certificates you use, no matter how up to date, it will not verify a self-signed cert. – S. Imp Dec 15 '22 at 06:31