Until literally a couple of days ago, everything was going well, but now, Curl has stopped working for addresses with HTTPS.
This is the code:
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => array($registation_ids),
'data' => array( "message" => $message,
"title" => $title,
"params" => $params,
"code" =>$code),
);
$headers = array(
'Authorization: key=' . GOOGLE_API_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
$result = curl_exec($ch);
This code had been running smoothly for over a year. But now it returns this:
Proxy Error
The proxy server received an invalid response from an upstream server.
The proxy server could not handle the request GET
/app/test_notifications.
Reason: Error reading from remote server
Apache/2.2.15 (Red Hat) Server at app-servername.rhcloud.com Port 80
However, if in the previous code I remove the s from https:// ... like this http://android.googleapis.com/gcm/send the request is sent without problems, but I can not allow that modification, since I also need access to other addresses that require SSL.
I have also tested with other https addresses, but it is the same result
Searching on the internet I found the solution to update curl, but I'm not sure if that is my solution, since the code executed correctly https requests last week. Anyway I leave here the curl --version response on my server:
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz
Is there a way to test that, in effect, is a Curl problem? That would help me to know how to find the solution.
I think it's a Google upgrade not a Curl problem.
Firebase Cloud Messaging (FCM) is the new version of GCM. It inherits the reliable and scalable GCM infrastructure, plus new features! See the FAQ to learn more. If you are integrating messaging in a new app, start with FCM. GCM users are strongly recommended to upgrade to FCM, in order to benefit from new FCM features today and in the future.
GCM Connection Server Reference
HTTP Protocol
XMPP Protocol
Android API Reference
iOS API Reference
Chrome API Reference
Contents
Downstream message syntax
Downstream HTTP messages (JSON)
Notification payload support
Downstream HTTP messages (Plain Text)
Interpreting a downstream message response
Downstream message error response codes
Check https://developers.google.com/cloud-messaging/http-server-ref
Reviewing the problem and comparing my different applications in Openshift I realized that curl in https addresses worked in one of them. I checked the differences using phpinfo() and discovered that, contrary to what the server indicated, in the application that presented the problem, SSL Version was 3.18.1 and not 3.27.1.
Solution: restart the application in openshift and if that does not work, manually update curl. (Restart work for me)
Related
I'm not an SSL wizard, so I'm hoping that someone who is can help with this. I am developing an app demo that was able to send FCM messages successfully a while back. The mobile app calls a PHP script on the CentOS 7 server that uses the following code to send the request. This worked just fine.
$notification = array('title' =>$this->title , 'body' => $this->body, 'sound' => 'default', 'badge' => '1');
// $arrayToSend = array('to' => $token, 'notification' => $notification,'priority'=>'high');
$params_android = array('ttl'=>'0s','priority'=>'high');
$headers_apns = array('apns-expiration'=>'400','apns-priority'=>'10');
$params_apns = array('headers'=>$headers_apns);
// if only one recipient, must use the 'to' field instead of registration_ids
if (1 == sizeof($this->recipients)) {
$arrayToSend = array('to' => $this->recipients[0], 'notification' => $notification, 'android'=>$params_and$
} else {
$arrayToSend = array('registration_ids' => $this->recipients, 'notification' => $notification, 'android'=>$
}
$json = json_encode($arrayToSend);
$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = 'Authorization: key='. self::$SERVER_KEY_COMMTEST;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, self::$FCM_URL);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch, CURLOPT_FAILONERROR,true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
//Send the request
$response = curl_exec($ch);
//Close request
if ($response === FALSE) {
$this->errorstring .= curl_error($ch) . "\n";
return false;
}
curl_close($ch);
$this->fcm_response = $response;
The URL to which I send the request is provided by Google: https://fcm.googleapis.com/fcm/send
About six months ago, I paused work on this project. Now, I'm trying to resume it but the FCM calls return an error: "Issuer Certificate Is Invalid"
FCM support has been useless on this.
I can issue a manual CURL call from the command line to get a more detailed response. It is:
curl: (60) Issuer certificate is invalid.
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
I see a link to more details in the detailed response. It suggests I need to obtain certificates and go through an installation process. Where do I get said certificates?
Is this a certificate error on my server or theirs? And, how do I fix it?
This problem is resolved. For information's sake, here it is.
The DNS servers configured on my Linux server were not providing the DNS information it needed. Therefore, outgoing requests were being intercepted along the way by the ISP. Naturally, that meant calls supposedly going out to FCM were really hitting the ISP's server and there was an SSL certificate mismatch situation.
This was resolved by contacting the ISP that provided new DNS server addresses. Now, outgoing requests are reaching their correct destinations.
I'm trying to send a basic HTTP request to an Odata web service in Microsoft Dynamics NAV 2016, using the following PHP code :
$url = 'https://<Server>:<WebServicePort>/<ServerInstance>/OData/Company(\'<CompanyName>\')/customer(\'1\')';
$credentials = 'user:password';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, $credentials);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Accept: application/json',
'Content-Type: application/json'
]);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
This code returns the expected result when I execute it on localhost.
However, when I execute this same code on my server, the browser keeps waiting for a response until a timeout.
I also tried using the HTTPful library :
$url = 'https://<Server>:<WebServicePort>/<ServerInstance>/OData/Company(\'<CompanyName>\')/customer(\'1\')';
$response = \Httpful\Request::get($url)
->sendsJson()
->authenticateWith('user', 'password')
->addHeaders([
'Accept' => 'application/json',
'Content-Type' => 'application/json'
])->send();
echo json_encode($response->body, JSON_PRETTY_PRINT);
Results were the same.
Both localhost and server use PHP5.5 and have cURL enabled, and sending a GET request to eg. http://en.gravatar.com/johnslegers.json works just fine on the server.
Any idea what might cause this and/or how to fix it?
I have detected the cause of the problem :
The Odata web service in Microsoft Dynamics NAV 2016 uses port 1103
Port 80, 443, 25 and 110 are the only ports open on the server from which I'm trying to call the service
It is not an option for our Microsoft Dynamics provider to change the port they're using, nor an option for our web hosting provider to open this port for us.
After a discussion with my boss, we've agreed to move our web hosting to another provider that gives us more flexibility and does not block port 1103.
On an Ubuntu 14.04.3 this code works fine:
$url_login = "https://test.example.com/login.do";
$cert_file = '/var/www/html/test/cert.pem';
$ssl_key = '/var/www/html/test/cert_private.pem';
$post_fields = 'userAction=1&cancelReason=&cancelType=&account=&memoType=&userText=&userid=99999999&password=xxxxxxxxxxxxxxxx';
$ch = curl_init();
$options = array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HEADER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
CURLOPT_VERBOSE => 0,
CURLOPT_URL => $url_login ,
CURLOPT_SSLCERT => $cert_file ,
CURLOPT_SSLCERTTYPE, 'PEM',
CURLOPT_SSLKEY => $ssl_key,
CURLOPT_COOKIESESSION => 1,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_fields
);
curl_setopt_array($ch , $options);
$output = curl_exec($ch);
The php on Ubuntu is using curl with openssl.
On a Centos 7 if fails with:
Curl Error : SSL peer was unable to negotiate an acceptable set of security parameters.
curl is here with nss.
The "cert.pem" contains only the client certificate with the cert-chain, and the "cert_private.pem" contains the private key not password protected. (-----BEGIN RSA PRIVATE KEY-----).
How can i get the above PHP code work with both? openssl and nss implementations of curl?
How about correcting:
CURLOPT_SSLCERTTYPE, 'PEM',
to
CURLOPT_SSLCERTTYPE => 'PEM',
?
I've also come across this problem using client certificate authentication with nss, while openssl works fine.
After much testing, this is what I've established with the server we're trying to contact:
curl using TLS v1.2 (default in some cases) with client certificate fails
curl using TLS v1.2 with client cert required by server, but not used by client, connects successfully. However client is not authenticated.
curl using TLS v1.0 with client certificate is successful
The above happens regardless of cipher suite, generally we're using rsa_aes_256_cbc_sha_256.
The quick workaround is to force TLS v1.0:
CURLOPT_SSLVERSION => 4,
Clearly this isn't ideal, and your server may not support it.
Another option is to compile curl with openssl or even GnuTLS (although I haven't tested the latter) instead of nss. Again, this may not be an option.
So far this points to a problem with NSS. I'll update this answer if further debugging generates any useful information.
Just for reference, this is the full error message using curl on the command line:
* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* SSL peer was unable to negotiate an acceptable set of security parameters.
* Closing connection 0
curl: (35) SSL peer was unable to negotiate an acceptable set of security parameters.
Update 2015-11-24: Further testing with Wireshark and ssltap shows the initial handshake is succeeding and the connection gets as far as the client sending ChangeCipherSpec, followed by its encrypted "Finished" message.
The server should then decrypt the client's "Finished" message, verify the hash and MAC and respond with its own encrypted "Finished" message. Instead, the server is responding with "handshake_failure" at this point.
This should provide a clue as to where NSS is failing.
Chrome, Openssl and Charles Proxy can all authenticate using the client certificate. Firefox (using NSS) and curl (with NSS) both fail at this point.
Update 2015-11-27: Additional information provided by the server's operations team suggests this may be an issue with a non-compliant server. The problem only arises when using TLS 1.2 under certain circumstances. This would explain why some SSL libraries, such as OpenSSL, are flexible enough to work around it.
NSS may be more strict in its compliance with RFCs. I'll update the answer if/when we hear more from the operations team managing the server.
Update 2017-01-25: The webserver software and load balancers are custom built for a specific bank's payment gateway. We've recently tried again with a new client and the server now appears to work with both Curl built with either NSS or OpenSSL and are no longer seeing the error. In summary: the workaround was to use a different SSL library and wait for the developers to fix the server software.
I'm trying to send an Ajax request using cURL PHP but it gives the error
Unknown SSL protocol error in connection
while I'm able to login to same server.
I've tried this
curl_setopt( $ch, CURLOPT_SSLVERSION, 1 );
and Ajax request is something like that
$header = array('Accept' => '*/*',
"X-Requested-With" => "XMLHttpRequest",
"Content-Type" => "application/x-www-form-urlencoded");
$data = array('ClientNumber=999999&OrderClass=ContractOrders&ShowAll=ContractOrders&ShowPerPage=500');
echo $page = Spider::spider($header, 'https://wfs.nursefinders.com/MasterConsole/displayorders.cfm?ShowAll=ContractOrders', 'https://wfs.nursefinders.com/MasterConsole/BuildOrderDisplaySection.cfm', FALSE, $data[0]);
Note in spider function, first argument is header, second is referrer third is url to access, fourth doesn't matter it's for cookie file and fifth is data o post
I'm using UBUNTU 14.10 and cURL Version is curl 7.37.1 according to this command /usr/bin/curl -V
and same as printing by php phpinfo()
Please help
I believe the reason for your problem is that the server you are communicating with does not support your SSL protocol.
There is a page here with information on that: http://blog.techstacks.com/2010/03/3-common-causes-of-unknown-ssl-protocol-errors-with-curl.html
For more direct information, try looking into the API Documentation for the required connection protocol for their server. They may have provided a sample that will connect.
This server is terrible broken. It does not support the most compatible SSLv23 handshake and will just hang if one tries it. It only supports explicit SSL 3.0 or TLS 1.0 handshakes. From looking at the source code of cURL it seems to me, that all variations of enforcing TLS1.0+ will do a SSLv23 handshake, which the server can not do:
-- curl-7.41.0/lib/vtls/openssl.c
1719 default:
1720 case CURL_SSLVERSION_DEFAULT:
1721 case CURL_SSLVERSION_TLSv1:
1722 case CURL_SSLVERSION_TLSv1_0:
1723 case CURL_SSLVERSION_TLSv1_1:
1724 case CURL_SSLVERSION_TLSv1_2:
1725 /* it will be handled later with the context options */
1726 req_method = SSLv23_client_method();
This leaves only the option of using the insecure SSL 3.0, that is
curl_setopt( $ch, CURLOPT_SSLVERSION, 3 );
While I have no PHP to test with, a short test with curl -1 vs. curl -3 on the command line confirms that CURLOPT_SSLVERSION of 1 will not work while 3 should work.
I'm having troubles debugging a POST request I'm making from my web server to another web server.
I'm trying to communicate with a SOAP web service but from some reason a code that worked well from local machine fails when executing on my server
Looking for a way to see the post request my server make to the web service server
web server OS - CentOs
using PHP curl to make the request
Ideas anyone?
Wireshark? If you've got to connect to the remote end using SSL, then run a stunnel client on the soap client and route requests through that tapping in between.
I had the same problem, and using CURLINFO_HEADER_OUT made outgoing request headers show up in debug info.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
$data = curl_exec($ch);
var_dump($data);
$details = curl_getinfo($ch);
var_dump($details);
To see the POST on the server
$h=fopen('out.txt','w');
fwrite($h,var_export($_POST,true));
Maybe the curl is disabled on your server
Or point your client at:
<?php print_r($_POST); ?>
C.
Redirect the post request to a server you control. You can then read the posted data using echo file_get_contents('php://input');