I having extreme difficulty with PHP curl. I am attempting to open a site: https://www.novaprostaffing.com/np/index.jsp through PHP curl, but it keeps yielding the following error: "Unknown SSL protocol error in connection to www.novaprostaffing.com"
My function is as follows:
function getUrl($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$buffer = curl_exec($ch);
if (!$buffer)
{
echo "cURL error number:" .curl_errno($ch);
echo " and url is $url and cURL error:" . curl_error($ch);
}
curl_close($ch);
return $buffer;
}
I have attempted multiple fixes including:
Forcing curl to version 3
Setting CURLOPT_SSL_VERIFYPEER & CURLOPT_SSL_VERIFYHOST to 0
Checking to see if was on curl 7.34. I was told there was a bug on this version, but I am on curl 7.19.1
None of the above worked. If you have any idea how to fix this, it would be much appreciated!
Try setting the cURL option CURLOPT_SSLVERSION. I had the same problem a while ago, this did the trick for me :)
curl_setopt($ch, CURLOPT_SSLVERSION, 3); // 1, 2 or 3
The server speaks only TLS 1.0 and trying to connect with SSL 2.0 or SSL 3.0 will cause the error you see. This means setting the version to 3 is exactly the wrong thing with this server. Apart from that the certificate chain is incomplete. The server only provides the leaf certificate, not the intermediate certificates until the trusted root. This will cause verification to fail.
Did you try some other https url and see if that worked ?
Here are 3 common causes
Destination Site Does Not Like the Protocol
The Destination Site Does Not Like the Cipher
The SSL Private Key Has Expired
Related
This is the request I'm sending with my PHP code-
$url = 'https://mywebserviceurl.com';
$method='GET';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_VERBOSE, '1');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, '2');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 'TRUE');
curl_setopt($ch, CURLOPT_CAINFO, __DIR__.'/print_ca_ca.cer');
curl_setopt($ch, CURLOPT_SSLCERT, __DIR__.'/print_ca_cert.cer');
curl_setopt($ch, CURLOPT_SSLKEY, __DIR__.'/print_ca_key_decr.pem');
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, 'somepassword');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$resp = json_encode($response);
$this->setErrorCodeMessage('401', 'Response-> '.$resp); //get a False here
$error = curl_error($ch);
$this->setErrorCodeMessage('401', 'Error-> '.$error); //get Error here
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($status_code == '200' && !empty($response)) {
$this->setErrorCodeMessage('401', 'Inside 200 OK..');
}
The Error that I see on my Error Logs is-
SSL peer had some unspecified issue with the certificate it received.
When I do php -a and try to run the request as is on the shell, along with the above error line I also get the following-
NSS error -12224 (SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT)
I originally had a p12 file and got a ca chain(.cer file), ssl cert(.cer file) and key files(.pem file) from it using the openssl commands, and I'm using these files with the Curl request.
At this point I've tried everything; using pem,crt,cer files, setting CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER to different values and also tried a POST request, but i keep getting SSL peer had some unspecified issue with the certificate it received.
Is there something that I'm doing wrong? Any suggestions?
PS- I've used the original P12 file and its password on Postman and have been able to send both GET/POST requests without issues.
The error you receive is due to the server not accepting your client certificate (the print_ca_cert.cer). CURLOPT_SSL_VERIFYHOST etc will not help since these option are about verifying the server certificate by the client.
It is unclear what the server does not like with your client certificate since it is unknown what the requirements are for this certificate and what's actually in the files you've received. It might be that the print_ca_ca.cer is not the CA for the server certificate which you configure with CURLOPT_CAINFO but that it is an intermediate CA you need to send together with your client certificate. In this case you need to append your print_ca_ca.cer to your print_ca_cert.cer. But again, these are just speculations since nothing is known about the contents of these files.
I use curl in PHP to request some https site such as https://github.com, and I use just code like this:
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://github.com/search?q=react");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
echo $output;
curl_close($ch);
?>
Then, I can get the page.
But, I searched before and found that if requesting a https resource, it needs adding these codes:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
So why I can request https resource without these two lines of codes to avoid SSL check?
Thanks.
The two Curl options are defined as:
CURLOPT_SSL_VERIFYPEER - verify the peer's SSL certificate
and
CURLOPT_SSL_VERIFYHOST - verify the certificate's name against host
They both default to true in Curl, and shouldn't be disabled unless you've got a good reason. Disabling them is generally only needed if you're sending requests to servers with invalid or self-signed certificates, which is only usually an issue in development. Any publicly-facing site should be presenting a valid certificate, and by disabling these options you're potentially opening yourself up to security issues.
I have been using the following code block to collect data from a HTTPS website using cURL.
$q = 'https://www.example.org/'; // for example
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $q);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$json = curl_exec($ch);
cURL shows the following error
error:14077458:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 unrecognized name
This might be related to older OpenSSL version, but as the website is in a Shared hosting, server side settings cannot be changed at the moment. All I can do is to change cURL parameters.
I have checked here https://www.ssllabs.com/ssltest/analyze.html to see the available protocols for that server, found SSL3 and SSL2 is not available, but TLS 1.2, TLS 1.1 and TLS 1.0 are available. Searching over Google, I found its best not specifying SSL version which actually auto-negotiate the best level to use. Although, I tried with setting TLS version in CURLOPT_SSLVERSION (as follows), but same error occurs.
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
I have been trying a lot for last few days, but all attempts went in vain.
I have tried to explain all the things I did, but anyone please ask if more info needed. Any help would be greatly appreciated.
Thanks a lot
This might be cURL #1037 Bug http://sourceforge.net/p/curl/bugs/1037/
It seems to happen when you connect with an outdated openssl 0.9.8 cURL against some server with openssl 1.0.x and use SNI.
This has been driving me crazy for 2 days - I have 2 PHP functions as detailed below both using curl. They point at exactly the same 'XML gateway' the only difference is one is trying to do it over SSL and the other over unencrypted HTTP.
The HTTP connector operator works exactly as expected, posting the XML file and returning the server response.
The SSL connector returns the ever so vague 'An internal server error occurred. Please try again later'. Nothing shows up in my lighttpd error log, has anyone got any bright ideas?
I'm wondering if it's my web server config/openSSL config. They are both Debian Wheezy standard packages. I appreciate SSL_VERIFYPEER & HOST being set to sale is insecure, however I've been trying to exhaust the options.
openssl s_client -connect xmlgw.companieshouse.gov.uk:443 -ssl3
and the command line function
curl https://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway
also works as expected on the web server.
PHP functions:
//SSL post function
public function getSSLCurlResponse($xml) {
$url = "https://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSLVERSION,3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
//HTTP non SSL function
public function getCurlResponse($xml) {
$url = "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
any help would be really appreciated!
Thanks
I have concluded this was an error in the overall connection to the server - though i could not find any way of proving that. I have managed to find an alternative solution without using an SSL socket.
I just installed the curl library for codeigniter written by Phil Sturgeon.
I keep getting this error
"Error: 60: SSL certificate problem, verify that the CA cert is OK.
Details:\nerror:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed"
I've checked across the internet and the general solution was to set the following values to FALSE and 0 respectively
CURLOPT_SSL_VERIFYPEER, FALSE;
CURLOPT_SSL_VERIFYHOST, 0;
you can use
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$curlReturned = curl_exec($ch);
if(!$curlReturned)
{
trigger_error(curl_error($ch));
}
Download the CA that curl dosn't have, and load it with:
curl_setopt ($ch, CURLOPT_CAINFO, “pathto/cacert.pem”);
or if you don't want the safty of SSL, just turn of it,
Boras link describes this more deeply