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.
Related
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.
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.
I create a process that log me in my account of #########.com. It work like a charm when I put it on my FTP.
This is the problem :
I have an apache local server set on my machine (easyPHP) on localhost:8080.
I have also an IIS server set on my machine at the port --> localhost:80.
My cURL request don't work. This is my code:
$lien = 'https://#########.com/login';
$postfields = array(
'username' => 'xxx',
'password' => 'xxx'
);
$path_cookie = 'connexion.txt';
if (!file_exists(realpath($path_cookie))) touch($path_cookie);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $lien);
curl_setopt($curl, CURLOPT_COOKIESESSION, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields);
curl_setopt($curl, CURLOPT_COOKIEJAR, realpath($path_cookie));
$return = curl_exec($curl);
echo($return);
echo 'error:' . curl_error($curl);
curl_close($curl);
}
Firstly: Yes I have cURL install on my server, I did some other cURL request between my apache server and my IIS server and everything work fine.
Secondly: The file "connexion.txt" is well create, BUT empty.
Thirdly: The echo of ($return) response nothing, and on my server the response is "Object moved to here."
Fourthly: Yes i read this topic, but didn't help me a lot..
cURL not working
Finally: When I try to debug the cURL request the error is:
error:SSL certificate problem: unable to get local issuer certificate
Can anyone help me please? I'll stay here to answer comment/test/debug/answer etc.
Thanks !
You're most likely not using a certificate at all so either use http or try using
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
It's not a good practice to set "CURLOPT_SSL_VERIFYHOST" false.
I recommed you to download the CA root certificate bundle and tell PHP where to find it.
You can find it to download here.
Download the .pem and save it where your PHP installation can access
it.
Add to your php.ini the file location: curl.cainfo="C:\Xamp\php\cacert.pem"
Restart your server]
Job is done, safely.
Font: https://snippets.webaware.com.au/howto/stop-turning-off-curlopt_ssl_verifypeer-and-fix-your-php-config/
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.
I'm trying to write a PHP script using cURL that can authorize a user through a page that uses an SSL certificate, in addition to username and password, and I can't seem to get past the SSL cert stage.
In this case, curl_setopt($handle, CURLOPT_VERIFYPEER, 0) unfortunately isn't an option. The certificate is a required part of authentication, otherwise I get the error mentioned in this other similar SO post.
I've tried a few command-line runs with cURL:
> curl --url https://website
This returns the (60) SLL certificate problem error. If I adjust the command to include the --cacert option:
> curl --url https://website --cacert /path/to/servercert.cer
It works just fine; the auth website is returned.
However, I've tried the following PHP code:
$handle = curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => false,
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_SSL_VERIFYHOST => '0',
CURLOPT_SSL_VERIFYPEER => '1',
CURLOPT_CAINFO => '/path/to/servercert.cer',
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
CURLOPT_VERBOSE => true,
CURLOPT_URL => 'https://website'
);
curl_setopt_array($handle, $options);
curl_exec($handle);
if (curl_errno($handle)) {
echo 'Error: ' . curl_error($handle);
}
curl_close($handle);
I would have thought the code was essentially analogous to the shell commands, but instead I'm greeted with the following error message:
Error: error setting certificate verify locations: CAfile: /path/to/servercert.cer CApath: none
I've read all the literature I can find (particularly on php.net and curl.haxx) and can't seem to find anything that fixes this problem. Any suggestions?
I have tried chmod 777 servercert.cer with no success. However, in executing the PHP script with the above code from the command line instead of the browser via php test.php, it works perfectly. Any explanation for why it doesn't work in the browser?
Because things work via the command line but not via php using curl then I would pursue curl being the problem.
According to this URL, http://curl.haxx.se/docs/sslcerts.html, which was reference in an SO post you cited above ( reading SSL page with CURL (php) )...
"Until 7.18.0, curl bundled a severely outdated ca bundle file that was
installed by default. These days, the curl archives include no ca certs at
all. You need to get them elsewhere. See below for example.
If the remote server uses a self-signed certificate, if you don't install a CA
cert bundle, if the server uses a certificate signed by a CA that isn't
included in the bundle you use or if the remote host is an impostor
impersonating your favorite site, and you want to transfer files from this
server, do one of the following:"
It then goes on to list a number of steps that you can try.
Since your 7.16.3 version of curl is prior to 7.18.0, if you haven't already, I would recommend updating your curl and openssl components and then working through the list referenced above.
To elaborate and sum this up:
if you have a PHP file using PHP curl and place the ca certificate for your systems in the same directory, the below code will give you a jumpstart
$url = "https://myserver.mydomain.local/get_somedata.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
//These next lines are for the magic "good cert confirmation"
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_VERBOSE, true);
//for local domains:
//you need to get the pem cert file for the root ca or intermediate CA that you signed all the domain certificates with so that PHP curl can use it...sorry batteries not included
//place the pem or crt ca certificate file in the same directory as the php file for this code to work
curl_setopt($ch, CURLOPT_CAINFO, __DIR__.'/cafile.pem');
curl_setopt($ch, CURLOPT_CAPATH, __DIR__.'/cafile.pem');
//DEBUG: remove slashes on the next line to prove "SSL verify" is the cause
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Error handling and return result
$data = curl_exec($ch);
if ($data === false) {
$result = curl_error($ch);
} else {
$result = $data;
}
// Close handle
curl_close($ch);
return $result;
After 6 years of the question, I meet the same problem on a shared-host, and apparently there is no satisfactory answer. I found for myself a solution, hope it useful for everybody.
You can try this config:
curl_setopt($config,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($config,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($config,CURLOPT_CAINFO,'ca-bundle.crt');
curl_setopt($config,CURLOPT_CAPATH,'ca-bundle.crt');
I met same error with #Magsol: Error: error setting certificate verify locations: CAfile: /path/to/servercert.cer CApath: none; so I added the 4th line to set CAPath.
It's work with me. But note, the CA file must be place in accessable dir (with chmod 755 or 777) and it will better if CA file is in the same dir with PHP file.
Now that this question is vey old, but maybe could be useful for some users looking for an answer currently.
I have a similar problem about an API with SSL, having problems with CURL (not with the browsers) my problem was that I just put the certificate but not the ceritifcates chain/bundle. Then I put that and things started working. So that's important in order to avoid problems.
Hope this can be useful for someone.
You can try this if it works for you:
curl_setopt($ch, CURLOPT_URL, "https://test.example.com/v1/authenticate.json?api_key=123456");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch,CURLOPT_CAINFO,'cert.embedapp.20191004.pem');
curl_setopt($ch,CURLOPT_CAPATH,'./cert.embedapp.20191004.pem');
Comment these lines and add this:
//curl_setopt($ch,CURLOPT_CAINFO,'cert.embedapp.20191004.pem');
//curl_setopt($ch,CURLOPT_CAPATH,'./cert.embedapp.20191004.pem');
curl_setopt($ch, CURLOPT_SSLCERT,'cert.embedapp.20191004.pem');