How to fix Curl error 60 without downloading cert - php

I'm using Rackspace API in PHP, and it just stopped working (everything worked fine 3 days ago). It uses guzzle, who uses curl. And curl just stopped working.
[Thu Jun 21 14:55:36 2018] [error] [client xxx.xx.xxx.xx] PHP Fatal error: Uncaught exception 'Guzzle\\Http\\Exception\\CurlException' with message '[curl] 60: [url] https://identity.api.rackspacecloud.com/v2.0/tokens' in
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php:359\nStack trace:\n#0
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php(292): Guzzle\\Http\\Curl\\CurlMulti->isCurlException(Object(Guzzle\\Http\\Message\\EntityEnclosingRequest), Object(Guzzle\\Http\\Curl\\CurlHandle), Array)\n#1
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php(257): Guzzle\\Http\\Curl\\CurlMulti->processResponse(Object(Guzzle\\Http\\Message\\EntityEnclosingRequest),
Object(Guzzle\\Http\\Curl\\CurlHandle), Array)\n#2
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php(240): Guzzle\\Http\\Curl\\CurlMulti->processMessages()\n#3
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php(224): Guzzle\\Http\\Curl\\CurlMulti->executeHandles()\n#4
/var/www/passline.com/vendor/guzzle/http/Guzzle/Http/Curl/CurlMulti.php(111)
The important part from the error is the following:
[curl] 60: [url] https://identity.api.rackspacecloud.com/v2.0/tokens
I get an error 60 from Curl, who means is an SSL cert error. Most answer say's the solution to this problem is: deactivate ssl or download a new cert.
curl: (60) SSL certificate : unable to get local issuer certificate
https://es.stackoverflow.com/questions/174276/curl-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate-url-h
I won't deactivate SSL, I can't use http instead of https and I want to avoid having to get into the machine and downloading a new cert.
If someday I have an old cert again, my site is going to stop working. What is the correct way to fix this?
This server has CenOs 6, We're using PHP 5.3.3 and curl 7.19.7
---- Edit ----
So, my problem is because of the change in the certificates of curl. From https://curl.haxx.se/docs/caextract.html
This bundle was generated at Wed Jun 20 03:12:06 2018 GMT .
There is a tool on linux called update-ca-certificates who solves this problem, also, the curl site say's you can run
curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
But, I don't know, someday I'll see the system stop working properly, I gonna get into the machine an run this command, and, that's all?, What doest the other people do?, set a cron with this command? or what?

Older versions of Guzzle made use of their own CA file that was bundled with the Guzzle library. It would use that file instead of system's (/etc/pki/tls/certs).
If you can get things working with cURL from the command line but get this error in Guzzle that is likely the culprit.
Things were changed to use the system CA bundle by default in late 2014.
https://github.com/guzzle/guzzle/issues/623
https://github.com/guzzle/guzzle/pull/800
The behaviour of newer (> 3.0 ?) versions is described here (see verify configuration flag):
Check if openssl.cafile is set in your php.ini file.
Check if curl.cainfo is set in your php.ini file.
Check if /etc/pki/tls/certs/ca-bundle.crt exists (Red Hat, CentOS, Fedora; provided by the ca-certificates package)
Check if /etc/ssl/certs/ca-certificates.crt exists (Ubuntu, Debian; provided by the ca-certificates package)
Check if /usr/local/share/certs/ca-root-nss.crt exists (FreeBSD; provided by the ca_root_nss package)
Check if /usr/local/etc/openssl/cert.pem (OS X; provided by homebrew)
Check if C:\windows\system32\curl-ca-bundle.crt exists (Windows)
Check if C:\windows\curl-ca-bundle.crt exists (Windows)

If someday I have an old cert again, my site is going to stop working. Curl should download a new cert by himself? isn't it?.
The concept of TLS is that the server sends its certificate to the client, shows a prove that it actually owns the private key belonging to the certificate and then the client checks if the certificate is considered trusted. Trusted means among others that the certificate was issued by a locally trusted CA (certificate authority).
Typically the client has a set of CA it trusts, i.e. CA like Let's Encrypt. If the certificate was issued by such an already trusted CA no changes to the client are needed whenever the certificate is changed as long as the issuer CA is still trusted and the server is configured properly to provide all intermediate CA certificates which are needed to build the trust path.
If instead you have a self-signed certificate or a certificate signed by some private CA the client has no kind of trust anchor it can use to verify the certificate. In this you need to provide the necessary trust anchor to the client. In case of a private CA it is sufficient to setup the client once with this private CA and it will accept also later certificates issued by this CA. But in case of a self-signed certificate this means that you need to update the expected certificate at the client whenever you update the certificate at the server. There is no automatic way to do it - because how should the client verify that it gets the correct new certificate without having an established trust to the party providing the new certificate?

This issue was caused by the change in the certificates of curl. From https://curl.haxx.se/docs/caextract.html
This bundle was generated at Wed Jun 20 03:12:06 2018 GMT .
There is a tool on linux called update-ca-certificates who solves this problem, also, the curl site say's you can run
curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
Just consider any of these commands may be needed to run again in the future if the certificates are renovated again.

Related

PHPmyAdmin, enable SSL in local net

I have a PHP application on Apache 2.4 server with installed mySql server and PHPmyAdmin.
To do some tests for educational purposes I need to enable SSL / TLS both on the PHP WEB application and on PHPmyAdmin.
all tests are performed on a local network between two computers, so there is the problem of generating certificates, but I followed this guide:
https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/
I generated the certificate of the certification authority that I installed on both machines of the local network (the server and the client), and the 3 files needed by Apache:
server.crt (server signed certificate)
server.csr (certificate signing request)
server.key (private key)
following the guide I then enabled TLS 1.3 on the PHP application successfully.
Now I should repeat the thing on phpMyAdmin and enable SSL. I've read that I need to add these directives to the config.inc.php file:
$cfg['Servers'][$i]['ssl'] = true
$cfg['Servers'][$i]['ssl_cert']
$cfg['Servers'][$i]['ssl_key']
$cfg['Servers'][$i]['ssl_ca']
The first must be set TRUE, while the others require the path of the certificates. Can I use the same certificates I use for the app?
I tried to do it: for the certificate of the CA, I exported it, converted it to .pem, put it in a folder in c: and entered the path in ssl_ca, for the signed certificate of the server, I simply converted it to .pem and entered the path, while the keys I left it like this and entered the path.
However, phpmyAdmin gives me an error:
mysqli::real_connect(): SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificat e verify failed
Happens because I don't use the csr file?
Thanks!

What exactly goes into CURLOPT_CAINFO/CAPATH?

Trying to make CURL in PHP work with a self signed certificate. I've made a copy of the cert file available to the client code, and I specify the path to the cert file both in CURLOPT_CAINFO and CURLOPT_CAPATH. Still, I'm getting error 60: SSL certificate problem: unable to get local issuer certificate.
Here are the repro steps. All on Linux (Debian Stretch in my case). Replace example.com with a relevant hostname.
First, I'd generate a private key:
openssl genrsa -out key.pem 2048
Compose a config file:
[req]
prompt=no
distinguished_name=dn
req_extensions=ext
x509_extensions=ext
[dn]
emailAddress=seva#example.com
CN=example.com
O=Seva Alekseyev
L=Chicago
ST=IL
C=US
[ext]
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=#alt
[alt]
DNS=example.com
Save as req.txt, generate a self signed cert:
openssl req -x509 -new -config req.txt -days 3650 -key key.pem -out example.cer
Install example.cer and key.pem in Apache under hostname example.com. Browse to make sure the basic setup works (modulo the scary security message).
Now, the client. Placed a copy of example.cer under $path. The PHP code goes:
$cu = curl_init("https://example.com/");
curl_setopt_array($cu, array(
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CAINFO => "$path/example.cer",
CURLOPT_CAPATH => "$path/example.cer"
));
$r = curl_exec($cu);
$c = curl_errno($cu);
$s = curl_error($cu);
curl_close($cu);
echo "$c $s";
Then the error message.
What am I missing here? Some guides suggest the value of CURLOPT_CAINFO/CAPATH should a folder instead, with serial-based symlinks pointing to cert files. Tried that too, same error. The document at https://curl.haxx.se/docs/sslcerts.html says:
Get a CA certificate that can verify the remote server and use the proper option to point out this CA cert for verification when connecting.
But there's no CA there, no cert chain. The signing cert is itself. Should I somehow transform the cert so that CURL sees it as a CA one? Should I generate a fake CA cert first, and sign the SSL cert with that one?
Command line curl, as in curl --cacert example.cer https://example.com/, pops the same message.
Related question here, but I'd rather not mess with systemwide settings.
The certificates pointed to by CURLOPT_CAINFO/CAPATH are expected to be CA certificates - at least when OpenSSL is used. This means that your self-signed certificate need also to be a CA certificate, i.e. it should not only be for serverAuth but also have basic constraints CA:true.
The keyUsage line under [ext] must include keyCertSign, like this:
keyUsage=digitalSignature,keyEncipherment,keyCertSign
Otherwise, it's not a CA cert as far as OpenSSL is concerned.
OBTW, the basicConstraints=CA:true line under [ext], suggested by Steffen, is not necessary, I've checked. At least with CURL 7.52.1 and OpenSSL 1.0.2r it's not.
In the client code, CURLOPT_CAPATH is not necessary, either. CURL supports two alternative ways of specifying the root CA cert bundle. CURLOPT_CAINFO makes CURL read and parse a single file, potentially with multiple certificates in it. CURLOPT_CAPATH makes CURL scan a directory with certificate files identified by their serial numbers - or symlinks to those, as generated by c_rehash. Since in my scenario the effective root CA cert bundle has exactly one cert, the one file approach is sufficient.
Doesn't work under Windows, at least with command line CURL 7.55.1. The Windows version of CURL uses the built-in Schannel library for its SSL implementation, and ignores the --cacert option, instead relying on Windows' built-in trusted CA store. See here.
It might be possible to rebuild CURL for Windows against a different SSL implementation, but the trouble is hardly worth it. Windows comes with its own fleet of HTTP(S) clients.

magento SSL certificate issue: unable to get local issuer certificate commercial certificate

I am using magento community edition 2.2 on wamp on windows server 2016. Whenever I am trying to Sign in to sync your Magento Marketplace purchases through System > Web Setup Wizard > System Config using the private and public keys taken from magento market place, I am getting the error:
"SSL certificate problem: unable to get local issuer certificate"
I tried solutions provided in some of the other threads in this forum to download cacert.pem and do the following settings in the php.ini
curl.cainfo = "C:\wamp64\bin\php\php7.1.9\cacert.pem" (this is where I put the cacert.pem file). It did not work!!
Other threads advice to put the self certified certificate in a convenient directory and specify the name with path for "curl.cainfo" and "openssl.cafile".
The issue is that I am not using self certified certificate. I have bought a commercial certificate, where they have given two files a certificate and a certificate chain file. Along with the key file I used to create the request, I have successfully installed configured apache to get https for the website.
The question is, how to get rid of the above error ""SSL certificate problem: unable to get local issuer certificate". The answers in the threads are all for the self signed certificates, where I am having a commercially purchased certificate (with multiple files)
I am using php 7.1.9 on wamp 3.1.0 magento CE 2.2.0
Please Advice....
You must have received the root and the intermediate certificate along with the main certificate.
The error states that its unable to verify the certificate uptil the root certificate. Rename the CACert.pem file with .crt extension . Also change the extension of the public key to .crt. Now, verify Whether the ISSUES BY of public key is the ISSUED TO of cartcert.pem is same. if its not the same then the intermediate in the cacert.pem is incorrect.

Transfer file from local machine to server using cURL [duplicate]

I'm working with cUrl and PHP to make a request to a server (for paypal access)
Paypal developer website does never mention that an SSL certificate is required to use PayPal access API, however the code that I use to request the token is the following:
$options = array(
CURLOPT_URL => $url,
CURLOPT_POST => 1,
CURLOPT_VERBOSE => 1,
CURLOPT_POSTFIELDS => $postvals,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSLVERSION => 3
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
echo curl_error($ch);
This echo outputs the following error:
SSL certificate problem: unable to get local issuer certificate
My questions are:
1) do I need SSL to use paypal access if I need only to get the user email?
2) if I do not need SSL why this error occours?
PS: the endpoint is the following: https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/tokenservice
The correct solution is to fix your PHP setup.. setting CURLOPT_SSL_VERIFYPEER to false is a quick hack, but it's wrong as you disable the certificate validation by it's certificate authority. This exposes you to a man-in-the-middle attack.
It's easy to fix (php 5.3.7 or higher) -
Download a list file with an up-to-date certificate authorities, and add this setting to your php.ini
curl.cainfo=<path-to>cacert.pem
Restart your web server, and it'll work !
You may disable SSL verification (which is enabled by default as of cURL 7.10), by adding this:
CURLOPT_SSL_VERIFYPEER, false
to your $options, however the proper way is to keep validation enabled.
SECURITY NOTICE
If remote site uses certificate issued by known CA but validation still fails, then most likely certificate is incorrectly set up on the remote server (lack of intermediate certificates etc.). Alternatively your system got no idea about used Certificate Authority that signed target's certificate. In such case yo should use php.ini's curl.cainfo (documentation) to point to valid PEM file with all supported CAs - that would make your setup properly validate issuer chain.
Please be aware that by setting CURLOPT_SSL_VERIFYPEER to false you are NOT solving the issue! You are working it around. This is all about security so it's fine to do that for a while, but deploying that on production is not wise, politely speaking, as you will become open to Man In The Middle Attack. You have been warned.
I had the same exact problem
Can't connect to PayPal to validate IPN message: SSL certificate: unable to get local issuer certificate
I used the code samples generated on paypal's github found here (I used PHP): https://github.com/paypal/ipn-code-samples
I downloaded both certs and tried testing both from curl: http://curl.haxx.se/docs/caextract.html
After about 2 hours of testing (using paypal's ipn simulator) and googling, found that paypal ipn cannot be tested on localhost, so i pushed the code live and tried testing, but still got the same error (even with permissions set to 777).
When I set CURLOPT_SSL_VERIFYPEER, false, it worked but this would defeat the purpose of having an ssl certificate.
After snooping around on my server's files, I found a curl-ca-bundle.crt file in my PHP folder. I decided to hardcode the CURLOPT_CAINFO in my paypal ipn script to that path. It finally worked!
I noticed this older .crt file included some certificates that weren't on the latest .crt file from the curl website. It was a bunch of certificates from verisign class 1, verisign class 2, verisign class 3 and verisign class 4.
Here's the complete list of the certificate names I added to curl's .crt file:
Verisign Class 1 Public Primary Certification Authority
Verisign Class 1 Public Primary Certification Authority - G2
Verisign Class 1 Public Primary Certification Authority - G3
Verisign Class 2 Public Primary Certification Authority - G2
Verisign Class 2 Public Primary Certification Authority - G3
Verisign Class 3 Public Primary Certification Authority
Verisign Class 4 Public Primary Certification Authority - G2
This may have something to do with what #Andomar was saying - paypal's verisign certificate is not included in the default (by default I mean curl's default) list of safe certificates.
I didn't have the time to debug and figure out exactly which certificate is needed so I just included all of them.
For anyone who experiences this problem in the future, I would suggest to get the latest certs from curl and add one by one the certificates in the list above until the error is gone.
Here's a link for some of those verisign certificates (you may need to google for the others not listed): www.symantec.com/page.jsp?id=roots
Note*: To view paypal's current certificates you can run this command in terminal:
openssl s_client -connect paypal.com:443 -showcerts
If anyone has further insight to this issue, please comment as I spent hours to figure all of the above out.
SSL certificate problem: unable to get local issuer certificate
Means that cUrl doesn't trust Verisign, the certificate authority that vouches for PayPal. As Marc B comments, cUrl no longer ships with trust for any certificate authority.
You can bypass the certificate chain validation with the option:
CURLOPT_SSL_VERIFYPEER => 0
To read how to configure cUrl so that it trusts Verisign, read the cUrl documentation.

curl SSL certificate error

I'm trying to install Vaprobash via CURL but I get this message everytime I try to download something through CURL. I'm using a Mac.
curl -L http://bit.ly/vaprobash > Vagrantfile
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
Append option in curl call:
-k/--insecure
The curl will be not trying to verify SSL cert.
The link is redirecting to a secure HTTP (SSL) server, and curl doesn't have access to the proper chain of trusted certificates to confirm that the site says it is who it is.
If you're sure the site is legitimate, and this is a once-off effort, you can use the --insecure option (it will ignore any certificate errors). Opening the link in a browser directs to GitHub with no issues, and curl fetches it fine on my Ubuntu 12.04 box.
It's likely a missing certificate in your SSL installation. Run with the -v option to get a detailed output if you need to confirm this.

Categories