Downloaded PEM cert but still getting "unable to get local issuer certificate" - php

I'm trying to create a proxy server where I will be requesting a JSON object from an API using curl. I've been able to successfully make this work except for the certification.
<?php
error_reporting(E_ALL);
$url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20csv%20where%20url%3D'http%3A%2F%2Ffinance.yahoo.com%2Fd%2Fquotes.csv%3Fs%3DMSFT%2BFFIV%26f%3Dnab'&format=json&diagnostics=true&callback=";
$ch = curl_init($url);
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "\VeriSignClass3PublicPrimaryCertificationAuthority-G5.crt");
// Perform the request, and save content to $result
$result = curl_exec($ch);
if(curl_errno($ch)){
echo 'Curl error: ' . curl_error($ch);
} else {
echo $result;
}
exit();
?>
I've already downloaded the yahooapis certification PEM file (with and without chain) and placed it in the same folder level as the proxy.php file, but I'm still getting the error "unable to get local issuer certificate".
Any ideas on what might be missing?
Also, please do not suggest to set CURLOPT_SSL_VERIFYPEER to false, as I know this bypasses verification. I need the server to verify before it connects.
Thanks!

curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "\VeriSignClass3PublicPrimaryCertificationAuthority-G5.crt");
I don't think this is the right one. You need the G3 and not the G5 certificate with the fingerprint 74:2C:31:92:E6:07:E4:24:EB:45:49:54:2B:E1:BB:C5:3E:61:74:E2. The G5 certificate will not work with OpenSSL stack with the setup used by query.yahooapis.com because of problems of OpenSSL with alternative trust path. For more details look at http://kriscience.blogspot.de/2013/03/supporting-trusted-but-untrusted.html.

Related

PHP Curl - SSL peer had some unspecified issue with the certificate it received

This is the request I'm sending with my PHP code-
$url = 'https://mywebserviceurl.com';
$method='GET';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_VERBOSE, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 'TRUE');
curl_setopt($ch, CURLOPT_CAINFO, __DIR__.'/print_ca_ca.cer');
curl_setopt($ch, CURLOPT_SSLCERT, __DIR__.'/print_ca_cert.cer');
curl_setopt($ch, CURLOPT_SSLKEY, __DIR__.'/print_ca_key_decr.pem');
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, 'somepassword');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$resp = json_encode($response);
$this->setErrorCodeMessage('401', 'Response-> '.$resp); //get a False here
$error = curl_error($ch);
$this->setErrorCodeMessage('401', 'Error-> '.$error); //get Error here
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code == '200' && !empty($response)) {
$this->setErrorCodeMessage('401', 'Inside 200 OK..');
}
The Error that I see on my Error Logs is-
SSL peer had some unspecified issue with the certificate it received.
When I do php -a and try to run the request as is on the shell, along with the above error line I also get the following-
NSS error -12224 (SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT)
I originally had a p12 file and got a ca chain(.cer file), ssl cert(.cer file) and key files(.pem file) from it using the openssl commands, and I'm using these files with the Curl request.
At this point I've tried everything; using pem,crt,cer files, setting CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER to different values and also tried a POST request, but i keep getting SSL peer had some unspecified issue with the certificate it received.
Is there something that I'm doing wrong? Any suggestions?
PS- I've used the original P12 file and its password on Postman and have been able to send both GET/POST requests without issues.
The error you receive is due to the server not accepting your client certificate (the print_ca_cert.cer). CURLOPT_SSL_VERIFYHOST etc will not help since these option are about verifying the server certificate by the client.
It is unclear what the server does not like with your client certificate since it is unknown what the requirements are for this certificate and what's actually in the files you've received. It might be that the print_ca_ca.cer is not the CA for the server certificate which you configure with CURLOPT_CAINFO but that it is an intermediate CA you need to send together with your client certificate. In this case you need to append your print_ca_ca.cer to your print_ca_cert.cer. But again, these are just speculations since nothing is known about the contents of these files.

PHP / curl - SSL certificate error - unable to get local issuer certificate

I'm attempting to log into a bank's website via PHP/curl (PHP 5.5.3) to download transactions. I'm new to curl, so I'm trying to figure out how to just log in to the site first.
CURRENT CODE:
$postinfo = 'username=' . $username . '&password=' . $password;
$curl = curl_init();
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_NOBODY, false);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_CAINFO, getcwd() . '\certificateCA.cer');
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postinfo);
$content = curl_exec($curl);
if(false == $content){
echo curl_error($curl);
}
curl_close($curl);
print $content;
ISSUE
I'm getting the following error:
"SSL certificate problem: unable to get local issuer certificate"
WHAT I'VE TRIED
So far, I've tried getting the certificate of the remote site per the answer on this SO question. This seems to have helped, because before I was getting a different error ("error setting certificate verify locations"). The certificateCA.cer referenced in my code is the certificate I downloaded from the remote site (the bank), by choosing to export the "Base-64 encoded X.509 (.CER)" option.
As it seems my current issue is related to the local cert not the remote cert, I've tried getting the latest from here: https://curl.haxx.se/ca/cacert.pem per this SO answer.
I added the following lines to my php.ini file and restarted Apache per this SO answer:
curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"
openssl.cafile = "C:\xampp\php\extras\ssl\cacert.pem"
Per this SO response, I also tried changing the file name and the reference to this:
curl.cainfo = "C:\xampp\php\extras\ssl\ssl.txt"
openssl.cafile = "C:\xampp\php\extras\ssl\ssl.txt"
HOW YOU CAN HELP ME
Please help me understand CURLOPT_CAINFO. Is this expecting the certificate of the remote site, or the local machine? It seems that it's looking for the remote site certificate based on the error going away after adding that certificate, but it's not clear from the documentation exactly what it's expecting.
A solution, or even a method by which I can triage this issue and find a resolution myself. It seems like what's worked for others on the linked SO questions isn't working for me, so I'm doing something wrong.

PHP curl error: "Unknown SSL protocol error in connection to..."

I having extreme difficulty with PHP curl. I am attempting to open a site: https://www.novaprostaffing.com/np/index.jsp through PHP curl, but it keeps yielding the following error: "Unknown SSL protocol error in connection to www.novaprostaffing.com"
My function is as follows:
function getUrl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$buffer = curl_exec($ch);
if (!$buffer)
{
echo "cURL error number:" .curl_errno($ch);
echo " and url is $url and cURL error:" . curl_error($ch);
}
curl_close($ch);
return $buffer;
}
I have attempted multiple fixes including:
Forcing curl to version 3
Setting CURLOPT_SSL_VERIFYPEER & CURLOPT_SSL_VERIFYHOST to 0
Checking to see if was on curl 7.34. I was told there was a bug on this version, but I am on curl 7.19.1
None of the above worked. If you have any idea how to fix this, it would be much appreciated!
Try setting the cURL option CURLOPT_SSLVERSION. I had the same problem a while ago, this did the trick for me :)
curl_setopt($ch, CURLOPT_SSLVERSION, 3); // 1, 2 or 3
The server speaks only TLS 1.0 and trying to connect with SSL 2.0 or SSL 3.0 will cause the error you see. This means setting the version to 3 is exactly the wrong thing with this server. Apart from that the certificate chain is incomplete. The server only provides the leaf certificate, not the intermediate certificates until the trusted root. This will cause verification to fail.
Did you try some other https url and see if that worked ?
Here are 3 common causes
Destination Site Does Not Like the Protocol
The Destination Site Does Not Like the Cipher
The SSL Private Key Has Expired

send multiple .crt certificate with curl in php

I want to send two .crt certificates with curl in php.
I am using this code.
$firstcalldata = "csv file data";
$target_url = www.example.com;
$ch = curl_init($target_url);
curl_setopt($ch, CURLOPT_VERBOSE, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_CAINFO,"C:/Users/admin/Desktop/CERT/PSCERT.pem");
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "C:/Users/admin/Desktop/CERT/PSCERT-C.crt");
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $firstcalldata);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/csv'));
$result = curl_exec($ch);
echo $result;
curl_close($ch);`
I am sending also a csv file to $target_url.
But all time I am getting 403 - Forbidden: Access is denied.
You're not really saying what you want to accomplish, you're just asking a very weird question with no answer. You example doesn't send the .crt at all, it uses it to verify the server's certificate. And CAINFO is meant to point to a file holding a full bundle (like one of those you can get at curl's caextract page)
But you disable both VERIFYPEER and VERIFYHOST so you don't actually need any CA cert!?
What exactly do you want to do? Note also how getting a 403 back means that you already communicate fine over the TLS layer.

SSL error with PHP curl

Hello fellow programmers,
I'm making an API with a https connection. I want to secure the API call with a certificate check. Now i've downloaded the cacert.pem from curl and placed this in my folder, but it doesn't work and gives me this error:
SSL certificate problem: unable to get local issuer certificate
Well i'm really sure that the cacert.pem file is located correctly but for you guys some code that i've been writing to get it working:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST ,1);
curl_setopt($ch, CURLOPT_USERPWD, $this->api_key . ":" . $this->api_secret);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . "/cacert.pem");
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_POSTFIELDS ,$post_vars);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION ,0);
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Accept: application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,1); // RETURN THE CONTENTS OF THE CALL
$data = curl_exec($ch);
I hope you some of you guys have an answer for my question because I really don't know much about SSL connections.
Thanks in advance!
After having made sure that your certificate bundle is readable by the script you're running, the next step is to investigate the server itself.
If this is your own server, it's likely that you forgot to install the intermediate certificates, i.e. the ones in between the issued certificate and one of the certificate authorities that comes with the bundle.
If you're working with a self-signed certificate, your cacert.pem should contain the public certificate of the server you're connecting to; this can be generated from the private certificate, outlined here, referred to as the .crt file.

Categories