Authentication failure with curl in PHP ( openssh connexion OK ) - php

I am trying to connect via php curl on an SFTP destination, with key authentication.
I manage to connect outside of curl, with openSSH: ( it work )
sftp -i myPrivateKey sftp://myusername#destination.com
however, I cannot reproduce this connection in curl, I have an authentication failure error. how is that possible?
$dest = 'sftp://myusername#mydestination:22';
$curlHandler = curl_init();
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curlHandler, CURLOPT_URL, $dest);
curl_setopt($curlHandler, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_setopt($curlHandler, CURLOPT_VERBOSE, true);
curl_setopt($curlHandler, CURLOPT_SSH_PUBLIC_KEYFILE, mypublickey);
curl_setopt($curlHandler, CURLOPT_SSH_PRIVATE_KEYFILE,myprivatekey);
$resp = curl_exec($curlHandler);
log:
* SSH public key authentication failed: Callback returned error
* Failure connecting to agent
* Authentication failure
* Closing connection 0
I am sure of the validity of the keys, I checked the fingerprints with the remote server, and I manage to connect outside of php-curl.
I also checked that my keys were in restricted access and accessible

Finally, it turns out that ubuntu LTS 14 uses the libgcrypt utility, which creates SSH keys with private keys starting with" ----BEGIN OPENSSH ---" and in the case of SFTP, we need a .pem starting with "-----BEGIN RSA PRIVATE KEY-----", so I converted my private key, and it worked
ssh-keygen -f id_rsa -m pem -p

Related

php curl connect with ssl cert fails

I am trying to connect to a server using ssl cert verification. on my local machine i run curl in verbose and i get:
* Trying X.X.X.X...
* TCP_NODELAY set
* Connected to server.com (X.X.X.X) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: ./XXX.pem
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
......<<connects correctly and does it's thing>>......
on my other linux box i do the exact same script and get:
* About to connect() to server.com port 443 (#0)
* Trying X.X.X.X...
* Connected to server.com (X.X.X.X) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* Closing connection 0
<< Curl error: 77 >>
I am using the exact same certs on both machines. I have tried a billion different things and cant figure it out.
What do i need to do on the failing machine to get it to connect correctly? What other info do you need to assist me. I am quite far out of my comfort zone on this one...I dont know if its a local cert on the machine thats causing the error....
here is the script I am using:
$path = "./someFile.pem";
$keyFile = "./someFile.key";
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSLCERT, $path);
curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD , $pass);
curl_setopt($ch, CURLOPT_CAPATH, $path);
curl_setopt($ch, CURLOPT_TIMEOUT, 300);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_CERTINFO, true);
$response = curl_exec($ch);
EDIT***
I was given a pfx file and i did the following:
to export the private key: openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes
to export the certificate: openssl pkcs12 -in certname.pfx -nokeys -out cert.pem
to remove the passphrase from the private key: openssl rsa -in key.pem -out server.key
I then put each of those files in the dir that httpd.conf expects. access to the server works fine now over https://.
I did yum install ca-certifcates and got:
Package ca-certificates-2019.2.32-76.el7_7.noarch already installed and latest version
I dont know what else to do next. getting same error as above.

cURL PUT Requests hangs

So here's my problem.
I'm using curl to access my CouchDB by HTTP. I recently updated my WAMP to the WAMP 3 64bit wich comes with PHP 5.6.16 and Apache 2.4.17. Therefore, since this upgrade, I discovered that I couldn't do PUT request anymore.
Env
PHP 5.6.16
Apache 2.4.17
Windows 10 64 bit
Wamp 3 64 bit
Curl --version
curl 7.49.1 (x86_64-pc-win32) libcurl/7.49.1 OpenSSL/1.0.2h nghttp2/1.11.1
Protocols: dict file ftp ftps gopher http https imap imaps ldap pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile NTLM SSL HTTP2
Code executed
So when I execute this :
<?php
$table="testname";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:5984/' . $table);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'validUser:validPass');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-type: application/json',
'Accept: */*'
));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
I get a quick response from the server.
Then, I try to create a database :
<?php
$table = "testname";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost:5984/' . $table);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'validUser:validPass');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-type: application/json',
'Accept: */*'
));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
Problem
So, when I execute this code, the request will hang on curl_exec.
What's weird is that, after the timeout, the request will be received by CouchDB but no response will be given. It seems that my "Put" request are stacked in a buffer and they are waiting to be executed.
Verbose curl output
* Hostname in DNS cache was stale, zapped
* Trying ::1...
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 5984 (#0)
* Server auth using Basic with user 'validUser'
> PUT /customers HTTP/1.1
Host: localhost:5984
Authorization: Basic dGVzdEFkbWluOnRlc3RQYXNzd29yZA==
Content-type: application/json
Accept: */*
* Operation timed out after 10000 milliseconds with 0 bytes received
* Closing connection 0
Hints
-I try to install a SSL certificate but It didn't seem to work. Having this certificate still installed can cause problems?
-I can do PUT request with a REST client on my Atom editor without problems.
-I seems like there is a problem in my network route internally. I'm saying this because It affected the PHP-Curl aswell as the Curl CLI. Also, I'm able to do GET request but the PUT request are like "hanging" for no reason and are "Accepted" by my CouchDB when the timeout occurs. It's like if I was sending long poll request.
What have been tested
Execute the same command on the command line -> Same result
Try a REST Client on my Atom editor with success
A friend of mine try to access to my database remotly with success (So CouchDB doesn't seem the problem)
Even if I tested with my Firewall disabled, uninstalling my antivirus ( Bitdefender Total Security 2016) fixed my issue.

curl vs libcurl command using php-curl

I have a curl command that works perfectly from the command line that goes like so :
curl --cert /path/to/cert.pem \
--cert-type PEM \
--form "files[0]=#/path/to/file.csv" \
https://url.com/whatever
I can also run it successfully from php using
exec("curl --cert /path/to/cert.pem --cert-type PEM --form \"files[0]=#/path/to/file.csv\" https://url.com/whatever");
Translating the command to php-curl I got
$url = "https://url.com/whatever";
$certificate = "/path/to/cert.pem";
$filePath = "/path/to/file.csv";
$postData = array("files[0]" => "#".$filePath);
// Upload request
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSLCERT, $certificate);
curl_setopt($ch, CURLOPT_SSLCERTTYPE, "PEM");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
// I have tried WITH or WITHOUT the following options to no avail
// Note that SSL_VERIFYPEER false is not necessary -- I do not have a self-signed cert in the chain
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$postUploadResponse = curl_exec($ch);
and this does not work. The message I get from the server is that the authentication has failed and that my certificate is not valid (though the exact same certificate works from the cmd line).
An important detail : that function runs perfectly well (with SSL_VERIFYPEER false as I use a self-signed cert locally) from my local XAMPP installation but the same code fails on the server.
The server is on Debian 8.3.
curl --version is
curl 7.38.0 (x86_64-pc-linux-gnu) libcurl/7.38.0 OpenSSL/1.0.1k zlib/1.2.8 libidn/1.29 libssh2/1.4.3 librtmp/2.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS IDN IPv6 Largefile GSS-API SPNEGO NTLM NTLM_WB SSL libz TLS-SRP
What could be causing this ? Is there anything that could be causing my certificate to not be sent properly when using libcurl ?

SL3_GET_SERVER_CERTIFICATE:certificate verify failed

i am using Repo script by command:
curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
but after that i get an error:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
i read some solutions to fix this problem and i got that adding the following line:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
but i want to know that which is the file can i add this line? Please help me! Thanks in advance!
You would add VERIFYPEER in a PHP file when making the cURL call e.g.
<?php
// create curl resource
$ch = curl_init();
// set url
curl_setopt($ch, CURLOPT_URL, "example.com");
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// set verifypeer to false
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// $output contains the output string
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
?>
As you are running curl from command line verifypeer will not work, you would need to use --insecure
curl --insecure https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
A better solution would be to try and make sure you have SSL certificate bundles installed. E.g. on CentOS:
yum install ca-certificates
If that doesn't work you can download and include the bundle manually from http://curl.haxx.se/ca/cacert.pem or https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt
curl_setopt($ch, CURLOPT_CAPATH, 'ca-bundle.crt');
or via command line
curl --cacert /path/to/ca-bundle.crt https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
You can use the curl shell command with the --insecure option:
curl --insecure https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
From the curl man page:
-k/--insecure
(SSL) This option explicitly allows curl to perform "insecure"
SSL connections and transfers. [...]
Maybe your network connenction to git server was blocked!!!

cURL with SSL certificates fails: error 58 unable to set private key file

I'm trying to connect to a remote host using cURL. The connection requires the use of a certificate and a private key which is password protected. So far I'm unsuccessful with this code below:
<?php
$wsdl = 'https://domain.com/?wsdl';
$certFile = getcwd() . '/auth/cert.pem';
$keyFile = getcwd() . '/auth/key.pem';
$password = 'pwd';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $wsdl);
curl_setopt($ch, CURLOPT_SSLCERT, $certFile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $password);
curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);
#curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
#curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
#curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$output = curl_exec($ch);
var_dump(curl_errno($ch));
var_dump(curl_error($ch));
The result I keep getting is error 58: unable to set private key file: '/home/.../domains/.../public_html/auth/key.pem' type PEM.
Things I've tried so far:
Check if the key-file is readable as suggested here: Unable to use libcurl to access a site requiring client authentication. Trying to pass the file through openssl_private_key() gives me a resource, and not a boolean. So this seems good.
Switch the order of the content in the key.pem file as suggested here: Unable to use libcurl to access a site requiring client authentication. No luck so far.
Played around with some other options like SLL_VERIFY_PEER, SSL_VERIFY_HOST, SSL_CERTTYPE and other options which seemed trivial regarding the official PHP-docs. No luck so far.
I'm pretty sure the problem lies somehwere in my configuration, but I'm not sure where to look.
I've fixed this problem. I think, due to the number of questions regarding this issue and number of different solutions, others will benefit from the solution. Here goes:
I used the openssl CLI program to convert the .p12 key-file to a .pem key-file. The trick is the way the conversion takes place.
First I converted it with this command and I had the issue as described in the question:
openssl pkcs12 -in key.p12 -out key.pem -nodes -clcerts
While the command below did the actual trick:
openssl pkcs12 -in key.p12 -out key.pem -clcerts
For more info please see the source I used: https://community.qualys.com/docs/DOC-3273
Just in case this is useful to others searching for this problem, I ended up discovering that CURLOPT_SSLCERT and CURLOPT_SSLKEY don't seem to work with relative paths.
This is with WAMP, php version 5.5 on Windows.
I got the same error when using the curl and when searching found this question. I was using the command curl --key my.pem https://example.com/
The solution that worked for me was to add the --key option and point to the same PEM file. Apparently, the PEM file (in my case) had the key as well as the certificate.
I tested it with the curl command:
curl --cert my.pem --key my.pem https://example.com/my/url

Categories