USing TLS v1.2 for Curl On Amazon AWS - php

I use this PHP function below to use curl to contact an outside API
function api_post($url, $data = array()) {
global $api_key;
global $password;
$data = json_encode($data);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Accept: application/json'
));
curl_setopt($ch, CURLOPT_USERPWD, $api_key . ':' . $password);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
return $response;
}
The api that I m communicating with is about to insist on using tls v1.2 which is a good thing except for some reason my code is using version 1.0.
It is fine if I do it from my local server but on the production server (An Amazon Web Services EC2 instance on AWS Elastic Beanstalk) it is not. I guess it has something to do with my server setup but I have no idea what or how to fix it.
Here is the curl section from my PHPinfo. Maybe I need to upgrade it or something? But how would I do this?

To enforce a TLS version on curl, you may need to use
bool curl_setopt ( resource $ch , int $option , mixed $value )
as documented here: http://php.net/manual/en/function.curl-setopt.php
example for TLS v1.2
curl_setopt ($setuploginurl, CURLOPT_SSLVERSION, 6);
CURLOPT_SSLVERSION: One of CURL_SSLVERSION_DEFAULT (0), CURL_SSLVERSION_TLSv1 (1), CURL_SSLVERSION_SSLv2 (2), CURL_SSLVERSION_SSLv3 (3), CURL_SSLVERSION_TLSv1_0 (4), CURL_SSLVERSION_TLSv1_1 (5) or CURL_SSLVERSION_TLSv1_2 (6).

OK, so I figured it out and thought I'd put the answer up here in case it is useful to anyone else.
As I suspected the problem was the curl version. In order for the line which tells curl which version to use to take affect I needed to be on curl version 7.34 or higher.
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
So how do you upgrade the curl version? Well there was a big upgrade button on the environment's main page to upgrade the version of Linux running on my instances so I clicked on that it upgraded curl at the same time. I now have curl version 7.38 and its using TLS v1.2 as I wanted.

Related

Facebook Graph API to Post to Page not working on new server

So I have been using the below code on my shared hosting server and it has been working fine but now we have moved to a dedicated server but this script is not working?
The dedicated server has CentOS 6.8, Apache 2.2, PHP 7.0.14, MySQL 5.6 and does have curl installed.
I am using a permanent access token also.
$data['access_token'] = '{my permanent access token}';
$post_url = 'https://graph.facebook.com/{my feed ID}/feed';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);
$dec = (Array)json_decode($return);
$link = "https://www.facebook.com/".$dec["id"];
I cannot find any errors in the console, is there any way for me to debug this?
Figured it out. I didn't force SSL on the old server but do on the new server so the below line needed to be added after curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

How can I access the Puppet API using PHP

I am trying to get a PHP script to access the Puppet API. I have spent 2 days searching and cannot believe that I cant find any info whatsoever (only puppet modules for installing PHP).
I am just trying to use PHP and curl but I am not able to get any kind of response, error or anything. Here is my (very basic) attempt to get the cert from the puppet master:
function get_data($url) {
$request_headers = array();
$request_headers[] = 'Accept: s';
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
$response = get_data('https://<puppet master>:8140/production/certificate/ca');
All I am trying to replicate is a curl call that works from my server:
curl -k -H "Accept: s" https://<puppet master>:8140/production/certificate/ca
I have a feeling that there is probably something obvious I am missing but, I cannot figure it out.
Thank to Wrikken and Glen for getting me on track. Once I set the curl_setopt options correctly, it works as expected.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_CAINFO, "/path/to/cacert.pem");

cURL file uploads not working anymore after upgrade from PHP 5.5 to 5.6

I've got a cURL upload that fails after upgrading from PHP 5.5 to 5.6:
$aPost = array(
'file' => "#".$localFile,
'default_file' => 'html_version.html',
'expiration' => (2*31*24*60*60)
)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);
The file seems to be empty on the target system.
Actually I found the answer while starting the question. There is a new Variable included with curl in PHP 5.5: CURLOPT_SAFE_UPLOAD this is set to false by default in PHP 5.5 and is switched to a default of true in PHP 5.6.
This will prevent the '#' upload modifier from working for security reasons - user input could contain malicious upload requests. You can use the CURLFile class to upload files while CURLOPT_SAFE_UPLOAD is set to true or (if you're sure your variables are safe you can switch the CURLOPT_SAFE_UPLOAD to false manually):
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
Here's a source for the information that got me searching in the right direction: http://comments.gmane.org/gmane.comp.php.devel/87521
It's mentioned in the changed functions too: http://php.net/manual/en/migration56.changed-functions.php
But not in the backward incompatible changes, really tripped me off...
Just do following changes for PHP 5.5 or greater
Instead of "#" . $localFile just use new CurlFile($localFile)
And set
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
Include a runtime check to make your code compatible with lower versions too like below
$aPost = array(
'default_file' => 'html_version.html',
'expiration' => (2*31*24*60*60)
)
if ((version_compare(PHP_VERSION, '5.5') >= 0)) {
$aPost['file'] = new CURLFile($localFile);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
} else {
$aPost['file'] = "#".$localFile;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $apiurl);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128);
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPost);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$sResponse = curl_exec ($ch);

Codeigniter REST API headers & authentication

I am using Phil Sturgeon's REST Controller to build an API. API authentication is performed using API keys. Presently there is only one key defined in the api_keys table on the database and I have set-up my client to access the API using this key via the following cURL request:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $uri);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
//curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_MAXREDIRS, 1);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 45);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/html; charset=utf-8',
'Accept: application/html',
'X_API_PREFIX: ' . $this->apiPrefix(),
'X_API_KEY: ' . $this->apiKey(),
"User-Agent: ShowHouse/" . ShowhouseClient::API_CLIENT_VERSION . '; PHP ' . phpversion() . ' [' . php_uname('s') . ']';
'Accept-Language: ' . $this->_acceptLanguage
));
curl_setopt($ch, CURLOPT_USERPWD, $this->apiKey());
if ('POST' == $method)
{
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
else if ('PUT' == $method)
{
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
else if('GET' != $method)
{
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
}
$response = curl_exec($ch);
However I keep getting an invalid API key response back from the API server. The issue appears to be that on the following line in the REST_Controller.php:
if (($key = isset($this->_args[$api_key_variable]) ? $this->_args[$api_key_variable] : $this->input->server($key_name)))
both
$this->_args[$api_key_variable]
and
$this->input->server($key_name)
are not actually set. 3 of us in the office have exactly the same code based checked out from the source control repository, the only difference being two of us are running Apache 2.4.4 and the other is running Apache 2.2.24. Both of us running 2.4.4 keep getting an invalid API key error but it all works fine for the guy running 2.2.24 which would suggest it's an Apache issue but we just can't get to the bottom of it.
Anyone any ideas why this would be happening like this?
Thanks in advance.
Found the issue for anyone else who may have the same problem. Apache 2.4.x now enforces stricter translation of header to environment variables to mitigate against some cross-site scripting attacks via header injection. See:
http://httpd.apache.org/docs/trunk/new_features_2_4.html
"Headers containing invalid characters (including underscores) are now silently dropped."

PHP cURL returns FALSE on HTTPS

I'm trying to make a bot for: https://coinroll.it/api
From the site:
The Coinroll API is a stateless interface which works over HTTPS. Requests are made using POST variables (application/x-www-form-urlencoded) while responses are encoded in JSON (application/json). A HTTPS connection is required for accessing the API.
I have the following code:
$ch = curl_init();
$data = array('user' => 'xxx', 'password' => 'yyy');
curl_setopt($ch, CURLOPT_URL, 'https://coinroll.it');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
echo $result;
When I run this code, it returns a blank page, what am I doing wrong?
EDIT
I don't actually need to use cURl, if there is a better solution, please tell me.
You can prevent cURL from trying to verify the SSL certificate by using CURLOPT_VERIFYPEER.
Also set the action in the URL:
$ch = curl_init();
$data = array('user' => 'xxx', 'password' => 'yyy');
curl_setopt($ch, CURLOPT_URL, 'https://coinroll.it/getbalance');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
echo $result;
You can use the following cURL option in order to see what happens with the HTTP connection:
curl_setopt($ch, CURLOPT_VERBOSE, true);
When TRUE it outputs verbose information.
Today I had the case where "It had been working fine until now.", but it stopped working when the FQDN changed, and I had to self-sign another certificate, with a different DN.
After a few experiments, it turned out to be that the Subject Alternate Name (aka SAN) was not matching the certificate name, and the curl call had not been set with CURLOPT_SSL_VERIFYHOST, 2.
Conclusion: by default, CURLOPT_SSL_VERIFYHOST is set to 2, but, if your cert SAN is wrong, it will fail, unless you deactivate CURLOPT_SSL_VERIFYHOST, and, with it, CURLOPT_SSL_VERIFYPEER.
It is obviously the best practice to set both, and have a SAN that matches the subject.
Reminder: this is how to quickly check the SAN using OpenSSH on command line:
openssl x509 -in /etc/ssl/certs/recette.pharmags.fr.crt -noout -text | grep -A1 "Subject Alternative Name"

Categories