PayPal: Peer certificate cannot be authenticated with known CA certificates - ssl

Hi suddely I start to get this error curl_error: Peer certificate cannot be authenticated with known CA certificates on paypal transactions on my site. The certificate name is VeriSignClass3PublicPrimaryCertificationAuthority-G5.crt and seem to be valid and seem to be an Intermediate Certificate. The code is the following but it workd for years.
curl_setopt($conn, CURLOPT_HEADER, 0);
curl_setopt($conn, CURLOPT_NOBODY, 0);
curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($conn, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($conn, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($conn, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($conn, CURLOPT_CAINFO, getcwd() . "/CAcerts/VeriSignClass3PublicPrimaryCertificationAuthority-G5.crt");
curl_setopt($conn, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($conn, CURLOPT_PROXYTYPE, "CURLPROXY_HTTP");
curl_setopt($conn, CURLOPT_PROXYAUTH, "CURLAUTH_BASIC");
curl_setopt($conn, CURLOPT_POST, 1);
curl_setopt($conn, CURLOPT_POSTFIELDS, $postString);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
The site is on a simple hosting and there is no ssh. What should I do? Should I insltall a new certificate? If so what certificate and what is the correct procedure?

The file /CAcerts/VeriSignClass3PublicPrimaryCertificationAuthority-G5.crt is out of date.
Update to one that is able to verify the issuer of the certificate of the PayPal server you are connecting to.
You can download an updated bundle of Certificate Authorities here: https://curl.haxx.se/docs/caextract.html
Put that .pem file somewhere like /CAcerts/, and change your path to point to it.

Related

Docusign Connect: Error - The request was aborted: Could not create SSL/TLS secure channel

After 4 years of reliable operation, my PHP listener script started to fail from October 8th, 2019 onwards with the
Error - The request was aborted: Could not create SSL/TLS secure channel.
I have not changed anything on my server. The SSL certificate is a valid v3 from Lets Encrypt. TLS is 1.2.
I have been on support calls for hours with no resolution, other than them telling me that I need to install their certificates here: https://www.docusign.com/trust/compliance/public-certificates
The problem is that I don't know how I would integrate that with my server, and my web host doesn't know either. When asked, they are not able to explain it either.
The listener script on my server is fairly simple:
function guid() {
$uuid = '';
if (function_exists('com_create_guid')){
$uuid = com_create_guid();
// somehow the function com_create_guid includes {}, while our webservice
// doesn't. Here we are changing the format by taking those curly braces out.
$uuid = str_ireplace("{", "", $uuid );
$uuid = str_ireplace("}", "", $uuid );
} else {
mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
$charid = strtoupper(md5(uniqid(rand(), true)));
$hyphen = chr(45);// "-"
$uuid = substr($charid, 0, 8).$hyphen
.substr($charid, 8, 4).$hyphen
.substr($charid,12, 4).$hyphen
.substr($charid,16, 4).$hyphen
.substr($charid,20,12);
}
return $uuid;
}
// Figure out the URL of this server
// NOTE: DocuSign only pushes status to HTTPS!
$postBackPath = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
$postBackPath .= ($_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'] );
$postedXml = #file_get_contents('php://input');
if (!empty($_POST['post'])) {
// if this is a sample load
$xml = simplexml_load_file("post.sample") or die("Unable to load sample XML file!");
$xml->EnvelopeStatus->EnvelopeID = guid(); // here we replace the GUID so we have unique files
// using the curl library to get the post
$curl = curl_init();
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT ,30);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_URL, $postBackPath);
curl_setopt($curl, CURLOPT_HEADER, array("Content-Type: application/xml"));
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml->asXML());
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_exec ( $curl );
curl_close ($curl);
}
else if(!empty($postedXml)) {
// see if this is a post to this page if it is then we have to save it.
$xml = simplexml_load_string($postedXml);
$post = $xml;
print 'Got Envelope ID: ' . $xml->EnvelopeStatus->EnvelopeID . '<br />';
}
After that code, it just parses data from the xml that I pass into my CRM.
On the Docusign Connect setup, I have the log enabled and require acknowledgement. All of the integration and security settings are unchecked (HMAC signature, Include basic authentication header, require mutual TLS, use SOAP interface, enable mutual TLS are all unchecked).
UPDATE: A response from my webhost assisting in this issue:
Hello again.
I took a look at the SSL you presently have installed for
sub.domain.com (you can see the info from Chrome browser) If you
click on the lock in the url bar and then click on Certificate >
Details > Version you (or docusign) can see that that cert is version
3 as they specified that you need.
I'm not clear on where they think that you should install their
certificate though. The cert at the link provided is to cover
na2.docusign.net which is not hosted on your server so there's no
place to install that that I'm aware of. You can verify that by
downloading the NA2 certificate from the link they provided:
https://www.docusign.com/trust/compliance/public-certificates
Open the .cer file in the simplest text editor you have available and
paste the contents in here:
https://www.sslshopper.com/certificate-decoder.html
That will give you all the information about the certificate. Under
"Subject:" you'll see CN = na2.docusign.net which means that it covers
their domain not yours.
I'm afraid we'll need more information from DocuSign to be able to
assist you. If this SSL were installed on your domain, it would fail
authenticity checks run by any browser connecting to your site which
isn't going to instill any confidence for your visitors.
This was my impression as well, so I feel like we are misunderstanding how this certificate from Docusign would work in conjunction with the certificate we already have from Lets Encrypt.
Is this a coding issue?
I am using a very simple Docusign connect integration, which is just a php listener catching the XML from a completed envelope and parsing it so I can pass that to my CRM.
I had the same issue today. after 5 hours digging into the internet, Here my change which resolved my issue:
+=+ all the update is related to the Haproxy certification setting, I added these three lines to the haproxy.conf file:
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
I was able to find this article: https://developers.docusign.com/esign-rest-api/guides/mutual-tls-apache2 and pass this to my server administrator. This was apparently had the missing info they needed to get it working. Not really an answer, but if you are struggling like I was, this will help steer you in the right direction.
see information on this page:
https://www.docusign.com/trust/compliance/public-certificates
"The renewed Connect certificates listed below are slated to be introduced into the DocuSign Service in the September 2019 - November 2019 timeframe. The ‘offer’ date specified below is the date the renewed certificate will be available for consumption and the ‘enforce’ date is when the renewed certificate will be the only option i.e. the current certificate will no longer be available for consumption."
You would have to update the certificate from that page on your server to fix this.

CURLOPT_SSLVERSION on my webserver

i have a site with paypal payment method, when user try to pay the following error is displayed :
curl_error: 35
SSL connect error
I use curl to make paypal call :
ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $endpoint);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
//curl_setopt($ch, CURLOPT_SSLVERSION, 4);
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
//turning off the server and peer verification(TrustManager Concept)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/Certs/api_cert_chain.crt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
$headers_array = paypal_adaptive_setupHeaders();
if (!empty($sandboxEmailAddress)) {
$headers_array[] = "X-PAYPAL-SANDBOX-EMAIL-ADDRESS: " . $sandboxEmailAddress;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers_array);
curl_setopt($ch, CURLOPT_HEADER, false);
So i have two questions
1- how can i solve this issue ?
adding : PPHttpConfig::$DEFAULT_CURL_OPTS[CURLOPT_SSLVERSION] = 4; cause 500 server error
2- Is there a way to know the CURLOPT_SSLVERSION used on my webserver? (dedicated server and i can access all privileges to install update things ...)
3- updating OPEN SSL can solve this?
Thanks everybody.
cURL error 35 is CURLE_SSL_CONNECT_ERROR which states:
A problem occurred somewhere in the SSL/TLS handshake. You really want
the error buffer and read the message there as it pinpoints the
problem slightly more. Could be certificates (file formats, paths,
permissions), passwords, and others.
This is probably 1 of 2 things given recent changes PayPal made.
Your version of cURL/OpenSSL do not support TLS (several months ago PayPal stopped supporting SSLv3 and below which broke a lot of clients). Since you've disabled peer verification, this might be the issue.
The api_cert_chain.crt no longer contains the correct certificate authority certificate PayPal is using.
There is a leaflet of information on paypal about the security upgrade and the protocols your server has to support to communicate with PayPal.
Here is the link of the information page : https://www.paypal-knowledge.com/infocenter/index?page=content&widgetview=true&id=FAQ1913&viewlocale=en_US#TLS
You have to make sure that openssl and Curl have the correct version on your server to be enable to establish the connection.
Apparently you should have the following requirements :
- openssl version >= 1.0.1
- curl version >= 7.34.0.

Server always responds 200 with curl, but gives error messages when accessed in browser

I'm trying to communicate with a third party server using curl.
The authentication system is as follows:
Use credentials to ask for cookie
Set cookie
Make requests
This in itself has not been a problem and I am able to make requests etc, but whatever I send the server always responds 200 even if i send an invalid data format. If i put the same url in the browser it returns error messages about the invalid format.
Does anyone know why this might be? Thanks in advance,
function go($url,$postvars=null)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookie_.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookie_.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POST,count($postvars));
$postfields = http_build_query($postvars);
curl_setopt($ch, CURLOPT_POSTFIELDS,$postfields);
curl_exec($ch);
curl_close($ch);
}
go($url,$login_array); //login=>'',pass=>''
go($url,$some_request_array);
One very likely possibility is a bug in the server code that means it sends 200 statuses with its error messages. Hence while in the browser it'll be an error message, because that's what is in the body, it'll still be "successful". Put an intercept (firebug network, fiddler, etc) on the browser access and see what the status is.
If this is the case you've two options:
Get the party responsible for the server to fix it.
Parse for the error message yourself, and then treat it as an error condition.

Client Certificates with LibCUrl

I am using libCurl to download a file from a remote server. That remote server requires client certificates. Here are the options that i have tried:
curl_easy_setopt(pCurl, CURLOPT_URL, url);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(pCurl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(pCurl, CURLOPT_CERTINFO, 1L);
curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 1);
//the following two lines specify the path to my valid client certificate
curl_easy_setopt(pCurl, CURLOPT_CAINFO, "c:\\Delta.p12");
curl_easy_setopt(pCurl, CURLOPT_CAPATH, "c:\\Delta.p12");
When I make the Https request, I get a 403: Forbidden error that says I have not specified the needed credentials. This certificate works via a browser, so I know that the cert is valid.
Any help to get this work is appreciated. Thanks!
If you get a 403, you already got passed the SSL layer so it would indicate that the certificate was good enough but that the server is there talking about something else.
But note that the CURLOPT_CA* options are used to specify your CA cert bundle (or path), so the above lines don't set any client certificate at all!
For a small example that shows how to use a client certificate with libcurl, see this:
http://curl.haxx.se/libcurl/c/simplessl.html

Curl command to test the API

I need to test an API of following spec
URL: http://myapp.com/api/upload/
Method: POST
Parameters:
image: (binary data of image)
returns
a JSON Object
sample php implementation to test the api
<?php
$ch = curl_init();
$url = 'http://myapp.com/api/upload/';
$fields = array('image'=>file_get_contents('profile-pic.jpg'));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_URL, $url);
$json = curl_exec($ch);
echo "\n".$json."\n";
?>
I use RESTClient and Poster extensions to test other api, I'm not sure how to send binary data for a parameter named image with those tools.
How do I test the above api using Curl command?
No luck with this one
curl -X POST --data-binary "image=#test.jpg" "http://myapp.com/api/upload/"
test.jpg is in current directory. I can't change the 3rd party API, to be able to test with other encoding formats.
curl -X POST --data-urlencode 'image#test.jpg' 'http://myapp.com/api/upload'
It’s image#, not image=#.
This is assuming that the image data is urlencoded before sending, which is what I figure the PHP code does.
CURLOPT_POSTFIELDS with a hash array in PHP corresponds to the command line -F option. Thus, it should be something similar to:
curl -F image=#profile-pic.jpg http://myapp.com/api/upload/
If that isn't the exact thing, add '--trace-ascii dump.txt' to get a full trace logged and check that out closely to see what's wrong.