Send data securely via curl

If you cURL to paypal using https, paypal doesn’t know or care what CURLOPT_SSL_VERIFYPEER is set to.

CURLOPT_SSL_VERIFYPEER is your option.
set to false it will connect to ANY https and do its thing, no one cares.
set to true cURL will check if it is a “signed” certificate and only communicate with a server with a valid signed certificate.

Either way will work fine as far as paypal is concerned.

sorry, what is the difference of signed and un-signed certificate?

“So, if you connect to a web server that provides an SSL certificate, but it is not signed by a trusted third party, in theory this could mean that you are communicating with an imposter that is pretending to be a server belonging to a different organization.”

Lets say that somehow someone intercepted traffic from your web server and acted as a relay to paypal.com.
This is “man in the middle” and he has a self signed SSL (not signed by a trusted third party).
With CURLOPT_SSL_VERIFYPEER set to false, you would have given the man in the middle all of your data.
With CURLOPT_SSL_VERIFYPEER set to true, cURL would know that the man in the middle was not paypal.com and would not send the data.

http://superuser.com/questions/161820/why-is-an-unsigned-ssl-cert-treated-worse-than-no-ssl-cert

see self signed certs, first link is to one of my websites with a self signed cert.
https://wifigator.com/
Notice the warning!

Chrome says,
Your connection is not private
Attackers might be trying to steal your information from wifigator.com (for example, passwords, messages, or credit cards).

Why the error? Chrome wanted to make sure I was who I claimed to be but chrome could not find a certificate of trust.

https://www.globalsign.com/en/ssl-information-center/dangers-self-signed-certificates/

This error is because of domain mismatch, but if it was because of untrusted issuer, how the browser knows that issuer is trusted? Does browser have a list/database of recognized issuers?

Yes they do. Those are what the browser considers to be root authorities. For any others to be trusted there must be a chain of trust back from the current certificate through other certificates to one of the root authorities. If not then the browser will indicate that the certificate is not trusted.

Untrusted certificates can still handle the encryption part but it is then up to the person to decide whether they trust the certificate and override the untrusted message.

  1. So if understood correctly CURLOPT_SSL_VERIFYPEER set to true validates target server SSL and NOT client server ssl, so if on request sender server there is no ssl installed, there is still no problem for curl to do its job with CURLOPT_SSL_VERIFYPEER set to true, but if target server has no valid ssl, then curl denies communication with that server? right?

  2. So if I generate ssl certs myself, and I want browsers to recognize my certs by default without end-user being forced to install my cert in store, I have to be an authorized issuer company that browsers consider to add my info in store by default? right?

  3. If I try to send data with CURLOPT_SSL_VERIFYPEER set to true to a server with no valid ssl, which error message should I get?

  4. If I try to send data with CURLOPT_SSL_VERIFYPEER set to true but with http url e.g. $ch = curl_init(http://…) should I get an error too?

  1. VERIFYPEER says “I’m going to use SSL to communicate with Server X. I want to make sure Server X is using a trusted certificate.” If ServerX’s SSL certification check fails, cURL will throw an error and not send the data.

  2. Yes. Or more specifically, there must be a trust chain that extends back to a trusted root authority.

  3. libcurl should spit out error code 51 - CURLE_PEER_FAILED_VERIFICATION. [FPHP]curl_errno[/FPHP] would give you the number associated with the last attempt.

  4. This… most likely should spit error code 35 - CURLE_SSL_CONNECT_ERROR. Not entirely sure. Why dont you test it and find out?

Thanks,

  1. I did read user comments and I see I should be careful about error constants difference in php and in their website, I am going to test them as you said too, I like to create an array to map CURLE_* constants with English error message, but if you know there is already such array that I can just copy/paste I appreciate it.

  2. So if a user doesn’t have ssl installed and wants to use paypal ipn, he should set CURLOPT_SSL_VERIFYPEER to false to avoid error 35, but still with this set to false he can send data to httpS://paypal to use ipn and get no error from paypal part? right?

  3. No if I understood everything correctly, that .pem file that cURL needs it to be installed is actually a CA store to validate target server’s ssl, just like what browers do? right?

  1. http://curl.haxx.se/libcurl/c/libcurl-errors.html
  2. Let’s be a bit more specific here - when you’re using cURL, the ‘user’ has nothing to do with it. It’s your web SERVER talking to a remote web SERVER. If the user’s webserver doesnt have SSL installed, they will not be able to communicate via SSL at all. The client server would request a SSL url, Paypal’s server would send an SSL handshake, the client server would say “I dont know what this is” and the whole thing would fall apart. That said, find me a web server that doesn’t have SSL installed.
  3. generally, a pem file is a public certificate, only. while it should refer to the issuing authority, that doesn’t mean it itself is the authority. Part of the SSL Handshake is that the Server hands the Client it’s public certificate (along with other data), which the Client can then validate based on the information contained within, by checking it’s own CA store. If the client server can’t validate the certificate using it’s CA store, it will fail the VERIFYPEER check. You can set VERIFYPEER to false (it’s set to 1 by default), which will prevent this failure, but it also opens the possibility of man-in-the-middle attacks, because you’re not actually checking to see if the certificate is valid. (Hint: Paypal’s certificate is issued by Symantec, one of the largest CA in the world. It’s pretty safe to assume every server will have it in their CA store.)

I tested several variants:

  1. It doesn’t care if client server has ssl installed regardless any setting. I did not get error 35 without having ssl installed on client server.
  2. It doesn’t care if openssl extension is installed as a separate extension regardless any setting, but “openssl” was present under curl extension without openssl extension being installed separately.
  3. If .pem file is missing it throws error 60
  4. If target server doesn’t have a valid ssl e.g. that wifiorg.com, it throws error 51.

Something goes wrong with these testings?

PS. how target server send an ssl handshake? how client server recognizes ssl handshake sent from target server?

Also I see these constant difference between official site and php,

errno, official curl site => PHP
22, CURLE_HTTP_RETURNED_ERROR => CURLE_HTTP_NOT_FOUND
25, CURLE_UPLOAD_FAILED => CURLE_FTP_COULDNT_STOR_FILE
28, CURLE_OPERATION_TIMEDOUT => CURLE_OPERATION_TIMEOUTED
45, CURLE_INTERFACE_FAILED => CURLE_HTTP_PORT_FAILED
64, CURLE_USE_SSL_FAILED => CURLE_FTP_SSL_FAILED

following errors have more than one constant:
[CURLE_FTP_PARTIAL_FILE] 18
[CURLE_PARTIAL_FILE] 18
[CURLE_HTTP_NOT_FOUND] 22
[CURLE_HTTP_RETURNED_ERROR] 22
[CURLE_OPERATION_TIMEDOUT] 28
[CURLE_OPERATION_TIMEOUTED] 28
[CURLE_BAD_DOWNLOAD_RESUME] 36
[CURLE_FTP_BAD_DOWNLOAD_RESUME] 36

and constants from 65 to 89 (except 79) according to official site, are missing from php.

As long as I tested it seems curl has nothing to do with separated openssl extension, but I guess it has its own openssl as appears under curl extension in phpinfo.
with extension_exists this is possible to check whether curl is installed, but how can I check with php whether curl has openssl or ssl support?

the output of curl_version(); is an array like below, to check whether this curl installation is able to send data via ssl, other than checking [ssl_version] element, is it good idea to check if https is in array of [protocols] element?

Array
(
    [version_number] => 466432
    [age] => 3
    [features] => 4029
    [ssl_version_number] => 0
    [version] => 7.30.0
    [host] => i386-pc-win32
    [ssl_version] => OpenSSL/1.0.1e
    [libz_version] => 1.2.7
    [protocols] => Array
        (
            [0] => dict
            [1] => file
            [2] => ftp
            [3] => ftps
            [4] => gopher
            [5] => http
            [6] => https
            [7] => imap
            [8] => imaps
            [9] => ldap
            [10] => pop3
            [11] => pop3s
            [12] => rtsp
            [13] => scp
            [14] => sftp
            [15] => smtp
            [16] => smtps
            [17] => telnet
            [18] => tftp
        )
)

Well you’d be looking for https, not http. But that should allways exist. Again, find a webserver package that doesnt include SSL in some form. It may take you some time.

find a webserver package that doesnt include SSL in some form. It may take you some time.

:smile:

This may answer your questions.
http://curl.haxx.se/docs/faq.html#curl_1_SSL_is_disabled_https

“If you get this output when trying to get anything from a https:// server, it means that the instance of curl/libcurl that you’re using was built without (SSL) support for this protocol.”

https requires some sort of support for SSL
http works right out of the box with cURL, no need to check anything.

is it possible to check with php, whether ssl is supported with current curl extension?

is it possible to check with php, whether ssl is supported with current curl extension?

Yes, phpinfo, if it is a one off, parse phpinfo with regex. ( preg_match() )

Too lazy to write it, print_r($out) will tell you what matches ($out may be $matches, depending what you read).

Finally I found the way, and wrote what I discovered here: http://stackoverflow.com/questions/5773516/how-to-check-if-curl-has-support-for-ssl/31712010#31712010

I am not sure if it is good idea to go with curl_version()[‘ssl_version’], (e.g. if (stripos(curl_version()['ssl_version'], "openssl") !== false) { ) as curl says here http://curl.haxx.se/docs/faq.html#Does_curl_work_build_with_other it may use other ssl library than OpenSSL (which does not have anything to do with that separated openssl extension, curl has its own openssl library) so as described here http://curl.haxx.se/libcurl/c/curl_version_info.html it appears better to go with CURL_VERSION_SSL bitmask check rather than curl_version()[‘ssl_version’]. Note that not all of those constants stated on official cURL website are available in php, but only these four constants:
[CURL_VERSION_IPV6] => 1
[CURL_VERSION_KERBEROS4] => 2
[CURL_VERSION_SSL] => 4
[CURL_VERSION_LIBZ] => 8

I tested this on Windows by disabling “openssl” extension in php.ini and noticed curl has nothing to do with that separated openssl extension but it has its own openssl, in other word, disabling openssl extension does not affect on $v[‘ssl_version’];. So if you want to check if curl has support for ssl, you should not rely on existence of that separated openssl extension and above I explained you should not rely on curl_version()[‘ssl_version’] neither. The only reliable way is CURL_VERSION_SSL bitmask checking:

if (!curl_version()['features'] & CURL_VERSION_SSL) {
    echo "SSL is not supported with this cURL installation.";
}

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.