Convert PHP code to curl command where only TLSv1 is allowed - php

How can I convert this php code to curl command? I want to use this code on linux machine by executing single curl command.
$headers = array(
"Content-type: text/xml",
"Content-length: " . strlen($xml)
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = curl_exec($ch);
I tired with this one, but unsuccessful:
curl -X POST -H "Content-type: text/xml" -o output.txt -d "param1=param1&username=username&password=password" https://site.url.com -d #data.xml
Maybe the problem is in the HTTPS because only TLSv1 is allowed on the site.

In php you would use:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
Documentation speaks of more TLS versions:
http://www.php.net/manual/en/function.curl-setopt.php
CURL_SSLVERSION_TLSv1_0
CURL_SSLVERSION_TLSv1_1
CURL_SSLVERSION_TLSv1_2
The TLS versions only work with CURL version 7.34 or newer.

If you want to force curl to use TLSv1, you can use the --tlsv1 option, from the docs:
-1, --tlsv1
(SSL) Forces curl to use TLS version 1.x when negotiating with a remote TLS server. You can use options --tlsv1.0, --tlsv1.1, and --tlsv1.2 to control the TLS version more precisely (if the SSL backend in use supports such a level of control).
-2, --sslv2
(SSL) Forces curl to use SSL version 2 when negotiating with a remote SSL server. Sometimes curl is built without SSLv2 support. SSLv2 is widely considered insecure.
-3, --sslv3
(SSL) Forces curl to use SSL version 3 when negotiating with a remote SSL server. Sometimes curl is built without SSLv3 support.

Problem is not related to TLS/SSL. Client will negotiate TLS automatically.
It seems like you need to make a POST some xml data and specify your credentials as GET parameters.
It can be done by putting your GET parameters to the request URL
Im not sure on syntax, but try this:
curl -X POST -H "Content-type: text/xml" -o output.txt https://site.url.com?param1=param1&username=username&password=password -d #data.xml
Also, (small offtopic for message above, but i cannt comment it) please not force SSL2, SSL3 or TLS1.0 since they have vulnerabilities. Most servers will negotiate best version of TLS automatically.

Related

PHP Curl - Received HTTP/0.9 when not allowed

I stumbled over a weird behavior when I try to send a post HTTP/2.0 request to apples push service:
$http2ch = curl_init();
curl_setopt($http2ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($http2ch, CURLOPT_URL, 'https://api.push.apple.com/3/device/megauniquedevicetokendummy');
curl_setopt($http2ch, CURLOPT_PORT, 443);
curl_setopt($http2ch, CURLOPT_HTTPHEADER, $httpHeader);
curl_setopt($http2ch, CURLOPT_POST, true);
curl_setopt($http2ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($http2ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($http2ch, CURLOPT_TIMEOUT, 30);
curl_setopt($http2ch, CURLOPT_HEADER, 1);
$result = curl_exec($http2ch);
if ($result === false) {
throw new \Exception("Curl failed: " . curl_error($http2ch) . " | " . curl_getinfo($http2ch, CURLINFO_HTTP_CODE));
}
The exception is thrown with the Message:
Curl failed: Received HTTP/0.9 when not allowed | 0
I explicitly told curl to use HTTP/2.0 on the second line of the code snipped above.
Does anyone have any idea what that error message means and why curl uses such an old HTTP version?
I am on PHP 7.2 and curl version 7.66.0.
This can also happen when the server is a grpc server. When curl is run against a grpc server or other non-HTTP server that doesn't respond with a valid HTTP status line that curl expects, curl will print the "Received HTTP/0.9 when not allowed".
It might be better if curl printed something like "unknown protocol" rather than assuming it is 0.9 because hitting something like a grpc server these days is going to be far more common than an actual HTTP 0.9 server.
I figured it out.
Make sure that curl is compiled with nghttp2.
If you are unsure, you can check it on your terminal using curl --version
If you dont find nghttp2/{version} you need to compile curl again with nghttp2.
curl --version example where nghttp2 is missing:
curl 7.66.0 (amd64-portbld-freebsd12.0) libcurl/7.66.0 OpenSSL/1.1.1d zlib/1.2.11
curl --version example where nghttp2 is available:
curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2
I do not believe it requires you to have a version of curl compiled differently, but rather set the option to allow http 0.9 as a response from your older server. PHP has some notes on "CURLOPT_HTTP09_ALLOWED" that may have differed when you posted your question via https://www.php.net/manual/en/function.curl-setopt.php
The option that overcame the error for me was:
curl_setopt($http2ch, CURLOPT_HTTP09_ALLOWED, true);

PHP cURL: enforce low TLS version

Goal is to write PHP code testing for TLS v1.2 connectivity. Getting a successful answer isn't a problem, but I can't produce a failure by using an older TLS version in PHP. Testing failures is obviously needed to prove correctness of code (to some reasonable degree).
On the command line I could come up with this, giving a clear distinction:
$ curl -X POST https://api.paypal.com/v1/oauth2/token
{"name":"AUTHENTICATION_FAILURE", [...]
$ curl --tls-max 1.1 -X POST https://api.paypal.com/v1/oauth2/token
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
In PHP I tried this ...
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.paypal.com/v1/oauth2/token');
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
// $response: '{"name":"AUTHENTICATION_FAILURE", [...]
... which means a succcessful TLS v1.2 connection, as one can see in the CLI example above, despite TLS v1.1 being requested. It's the same result as when requesting CURL_SSLVERSION_TLSv1_2.
This is PHP 7.3.7 with cURL 7.64.0 and I hope I can get away without recompiling PHP just for disabling TLS v1.2 support.
To answer my own question, documentation at https://www.php.net/function.curl-setopt is/was outdated. cURL 7.54 changed behavior of CURL_SSLVERSION_ macros, these set now the minimum acceptable TLS version for the connection. It also introduced CURL_SSLVERSION_MAX_ macros, which set the maximum TLS version tried. Until PHP documentation is updated, see https://curl.haxx.se/libcurl/c/CURLOPT_SSLVERSION.html.
Accordingly, limiting the connection to TLS v1.1 works like this:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.paypal.com/v1/oauth2/token');
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_MAX_TLSv1_1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
Little PHP/CURL test script:
<?php
echo 'PHP version: ' . phpversion() . PHP_EOL;
echo 'cURL version: ' . curl_version()['version'] . PHP_EOL;
$ch = curl_init('https://www.howsmyssl.com/a/check');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_0); // TLS 1.0
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_1); // TLS 1.1
//curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); // TLS 1.2 or 1.3
$data = curl_exec($ch);
curl_close($ch);
$json = json_decode($data);
echo ($data ? $json->tls_version : 'curl request failed') . PHP_EOL;
"TLS v1.1 being requested" is wrong given that TLS v1.1 or later (Added in 7.34.0) is pretty clear as well as "The maximum TLS version can be set by using one of the CURL_SSLVERSION_MAX_ macros"

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 Error : Cannot connect: SSL is disabled. Error number 35

I am working on the paypal ipn script in one of my applications hosted on a Digital Ocean's box with Centos 7.
When i try to connect to the paypal sandbox api i get the error "Cannot connect: SSL is disabled."
I have tried several things like adding the path of the curl.cainfo in my php.ini file like so
curl.cainfo = /etc/pki/tls/certs/ca-bundle.trust.crt
this is what my cURL script looks like
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr'); // change to [...]sandbox.paypal[...] when using sandbox to test
curl_setopt($ch, CURLOPT_SSLVERSION, 4);
curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'ecdhe_rsa_aes_128_gcm_sha_256');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
I have not got much experience with Linux server setup so I am learning as i go along.
Any help or guide is much appreciated
UPDATE : when i run the this command in the command line
curl --version https://sandbox.paypal.com/cgi-bin/webscr
i get this error
curl: (1) Protocol "https" not supported or disabled in libcurl
Also the command curl --version
displays curl 7.42.1 (x86_64-unknown-linux-gnu) libcurl/7.46.0
So i am guessing the new question would be how to enable https in libcurl?
You're setting the wrong SSL version:
curl_setopt($ch, CURLOPT_SSLVERSION, 4);
The Paypal sandbox only supports TLS 1.2 (which is CURLOPT_SSLVERSION == 6). The correct SSL version will be used automatically if you use PHP 5.5.19+ and OpenSSL 1.0.1+, or you can force it yourself with the following (still requires OpenSSL 1.0.1+):
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
I would only expect to see Protocol "https" not supported or disabled in libcurl if this were running a libcurl not installed from rpm - or if whoever configured the machine deliberately broke it for a valid reason, or was very incompetent; the Centos 7 rpm for libcurl has openSSL as a requirement.
Understanding what happened here and remediation will require root access to the target host to install software. You didn't say what access you have on the target system, and you are presumably paying Digital Ocean for support. Unless you broke it yourself, you should be asking Digital Ocean to fix it.
I was able to solve this problem with the help of one my friends with a lot of Linux experience. Apparently this was an issue with the version of cURL installed on my Digital Ocean box.
So the solution was to remove the version of cURL i had installed which was not installed correctly because i had built the binaries my self.
I installed the problematic cURL using these commands
wget -O curl.tar.gz http://curl.haxx.se/download/curl-7.42.0.tar.gz
tar -xvzf curl.tar.gz
cd curl-7.42.0
./configure
make
make install
I removed the problematic cURL that had https issues like this
which curl
(To tell me where the executable was located and it was located in usr/local/bin/curl)
Then i did
sudo rm -f /usr/local/bin/curl
(To remove the cURL giving issues)
Then i used the command
sudo yum install curl php5-curl
This installed cURL correctly for me. The i ran
curl --version
To confirm that https is now supported in the cURL version and it was.
I logged out of my droplet and logged back in. Then tried the
curl --version "https://sandbox.paypal.com/cgi-bin/webscr"
command and everything worked. I was able to connect to Paypal.
Thanks to everyone for their help and comments.
I think you need to enable fopen socket.You can ask hosting provider

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!!!

Categories