Related
I'm running PHP Version 5.6.3 as part of XAMPP on Windows 7.
When I try to use the Mandrill API, I'm getting the following error:
Uncaught exception 'Mandrill_HttpError' with message 'API call to messages/send-template failed: SSL certificate problem: unable to get local issuer certificate'
I already tried everything I read on StackOverflow, including adding the following to the php.ini file:
curl.cainfo = "C:\xampp\php\cacert.pem"
And ofcourse downloaded to that location the cacert.pem file from http://curl.haxx.se/docs/caextract.html
but after all that, restarted XAMPP and Apache server but still getting the same error.
I really don't know what else to try.
Can anyone advise on what else can I try?
Finally got this to work!
Download the certificate bundle.
Put it somewhere. In my case, that was c:\wamp\ directory (if you are using Wamp 64 bit then it's c:\wamp64\).
Enable mod_ssl in Apache and php_openssl.dll in php.ini (uncomment them by removing ; at the beginning). But be careful, my problem was that I had two php.ini files and I need to do this in both of them. One is the one you get from your WAMP taskbar icon, and another one is, in my case, in C:\wamp\bin\php\php5.5.12\
Add these lines to your cert in both php.ini files:
curl.cainfo="C:/wamp/cacert.pem"
openssl.cafile="C:/wamp/cacert.pem"
Restart Wamp services.
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
I had the same problem in Mandrill.php file after line number 65 where it says $this->ch = curl_init();
Add following two lines:
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, 0);
This solved my problem and also sent email using localhost but I suggest to NOT use it on live version live. On your live server the code should work without this code.
Thanks #Mladen Janjetovic,
Your suggestion worked for me in mac with ampps installed.
Copied: http://curl.haxx.se/ca/cacert.pem
To: /Applications/AMPPS/extra/etc/openssl/certs/cacert.pem
And updated php.ini with that path and restarted Apache:
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo="/Applications/AMPPS/extra/etc/openssl/certs/cacert.pem"
openssl.cafile="/Applications/AMPPS/extra/etc/openssl/certs/cacert.pem"
And applied same setting in windows AMPPS installation and it worked perfectly in it too.
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo="C:/Ampps/php/extras/ssl/cacert.pem"
openssl.cafile="C:/Ampps/php/extras/ssl/cacert.pem"
:
Same for wamp.
[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo="C:/wamp/bin/php/php5.6.16/extras/ssl/cacert.pem"
openssl.cafile="C:/wamp/bin/php/php5.6.16/extras/ssl/cacert.pem"
If you are looking for generating new SSL certificate using SAN for localhost, steps on this post worked for me on Centos 7 / Vagrant / Chrome Browser.
When you view the http://curl.haxx.se/docs/caextract.html page, you will notice in big letters a section called:
RSA-1024 removed
Read it, then download the version of the certificates that includes the 'RSA-1024' certificates.
https://github.com/bagder/ca-bundle/blob/e9175fec5d0c4d42de24ed6d84a06d504d5e5a09/ca-bundle.crt
Those will work with Mandrill.
Disabling SSL is a bad idea.
The above steps, though helpful, didnt work for me on Windows 8. I don't know the co-relation, but the below steps worked. Basically a change in the cacert.pem file. Hope this helps someone.
Download cacert.pem file from here:
http://curl.haxx.se/docs/caextract.html
Save the file in your PHP installation folder. (eg: If using xampp – save it in c:\Installation_Dir\xampp\php\cacert.pem).
Open your php.ini file and add these lines:
curl.cainfo=”C:\Installation_Dir\xampp\php\cacert.pem”
openssl.cafile=”C:\Installation_Dir\xampp\php\cacert.pem”
Restart your Apache server and that should fix it (Simply stop and start the
services as needed).
Note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
I found new Solution without any required certification to call curl only add two line code.
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
If you don't have access to php.ini, adding this code (after your $ch = curl_init(); line) works for me:
$certificate_location = "C:\Program Files (x86)\EasyPHP-Devserver-16.1\ca-bundle.crt"; // modify this line accordingly (may need to be absolute)
curl_setopt($ch, CURLOPT_CAINFO, $certificate_location);
curl_setopt($ch, CURLOPT_CAPATH, $certificate_location);
Then, you will just need to download ca-bundle.crt and save it to location you specified in $certificate_location.
Editor's note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
I tried this it works
open
vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php
and change this
$conf[CURLOPT_SSL_VERIFYHOST] = 2;
$conf[CURLOPT_SSL_VERIFYPEER] = true;
to this
$conf[CURLOPT_SSL_VERIFYHOST] = 0;
$conf[CURLOPT_SSL_VERIFYPEER] = FALSE;
Note: disabling SSL verification has security implications. Without verification of the authenticity of SSL/HTTPS connections, a malicious attacker can impersonate a trusted endpoint (such as GitHub or some other remote Git host), and you'll be vulnerable to a Man-in-the-Middle Attack.
Be sure you fully understand the security issues before using this as a solution.
elaborating on the above answers for server deployment.
$hostname = gethostname();
if($hostname=="mydevpc")
{
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
}
should do the trick for development environment without compromising the server when deployed.
I was facing a problem like this in my local system but not in the live server. I also mentioned another solution on this page its before, but that was not working in localhost.so find a new solution of this, that is working in the localhost-WAMP Server.
cURL Error #:SSL certificate problem: unable to get local issuer
certificate
sometimes system could not find your cacert.pem in your drive. so you can define this in your code where you are going to use CURL
Note that i am fulfilling all conditions for this like OPEN-SSL library active and other things.
check this code of CURL.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL =>$url,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER=> true,
));
curl_setopt($curl, CURLOPT_CAINFO, "f:/wamp/bin/cacert.pem"); // <------
curl_setopt($curl, CURLOPT_CAPATH, "f:/wamp/bin/cacert.pem"); // <------
$response = json_decode(curl_exec($curl),true);
$err = curl_error($curl);
curl_close($curl);
but this solution may not work in live server. because of absolute path of cacert.pem
On Amazon Linux (CentOS / Red Hat etc) I did the following to fix this issue. First copy the cacert.pem downloaded from http://curl.haxx.se/ca/cacert.pem and put it in the /etc/pki/ca-trust/source/anchors/ directory. Then run the update-ca-trust command.
Here is a one liner taken from https://serverfault.com/questions/394815/how-to-update-curl-ca-bundle-on-redhat
curl https://curl.se/ca/cacert.pem -o /etc/pki/ca-trust/source/anchors/curl-cacert-updated.pem && update-ca-trust
However since curl was broken I actually used this command to download the cacert.pem file.
wget --no-check-certificate http://curl.haxx.se/ca/cacert.pem
After running the update-ca-trust command you can restart the web server service httpd restart for apache or service nginx restart for nginx.
I have Very Simple Solution of this problem. You can do this without any certificate file.
Note that this solution is valid for local system not client server and Production server.
Go on Laravel Root Folder -> Vender -> guzzlehttp -> guzzle -> src
open Client.php
find $defaults Array . that look like this way ..
$defaults = [
'allow_redirects' => RedirectMiddleware::$defaultSettings,
'http_errors' => true,
'decode_content' => true,
'verify' => true,
'cookies' => false
];
Now main Job is to change value of verify key ..
'verify' => false,
So After this it will not check SSL Certificate for CURL Request... This Solution is work for me. I find this solution after many research ...
I had the same issue during building my app in AppVeyor.
Download https://curl.haxx.se/ca/cacert.pem to c:\php
Enable openssl echo extension=php_openssl.dll >> c:\php\php.ini
Locate certificateecho curl.cainfo=c:\php\cacert.pem >> c:\php\php.ini
I have a proper solution of this problem, lets try and understand the root cause of this issue. This issue comes when remote servers ssl cannot be verified using root certificates in your system's certificate store or remote ssl is not installed along with chain certificates. If you have a linux system with root ssh access, then in this case you can try updating your certificate store with below command:
update-ca-certificates
If still, it doesn't work then you need to add root and interim certificate of remote server in your cert store. You can download root and intermediate certs and add them in /usr/local/share/ca-certificates directory and then run command update-ca-certificates. This should do the trick. Similarly for windows you can search how to add root and intermediate cert.
The other way you can solve this problem is by asking remote server team to add ssl certificate as a bundle of domain root cert, intermediate cert and root cert.
Another reason this error can occur is if a CA bundle has been removed from your system (and is no longer available in ca-certificates).
This is currently the situation with the GeoTrust Global CA which (among other things) is used to sign Apple's certificate for APNS used for Push Notifications.
Additional details can be found on the bug report here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=962596
You can manually add the GeoTrust Global CA certificate on your machine as suggested by Carlos Alberto Lopez Perez:
wget --no-check-certificate -c https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.pem \
&& mkdir /usr/local/share/ca-certificates/extra \
&& mv GeoTrust_Global_CA.pem /usr/local/share/ca-certificates/extra/GeoTrust_Global_CA.crt \
&& update-ca-certificates
If none of the solutions above are working for you try updating your XAMPP installation to a newer version.
I was running XAMPP with php 5.5.11, the same exact code didn't work, I upgraded to XAMPP with php 5.6.28 and the solutions above worked.
Additionally only updating PHP didn't work either seems like a combination of apache and php settings on that version of XAMPP.
Hope it helps someone.
I got the error like :
failed loading cafile stream: `C:\xamppPhp\apache\bin\curl-ca-bundle.crt`
I am using windows machine. So I followed the below steps.
1. I have downloaded .pem file from " https://curl.haxx.se/docs/caextract.html "
2. Then I kept the downloaded file inside "C:/xamppPhp/apache/bin/" folder and renamed the same downloaded file to "curl-ca-bundle.crt".
3. I restarted XAMPP and cleared the cache.
4. It's done.
Hope it may help someone
simply put two more line on local to solve the issue and this worked for me fine.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
for guzzle you can try this :
$client = new Client(env('API_HOST'));
$client->setSslVerification(false);
tested on guzzle/guzzle 3.*
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.
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.
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.
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.