tags:

views:

81

answers:

3

Hi,

I would like to be able to read the SSL certificate information with CURL. From the Linux console I get this response header:

GET https://www.google.com/ -ed
Cache-Control: private, max-age=0
Connection: close
Date: Sun, 20 Jun 2010 21:34:12 GMT
Server: gws
Content-Type: text/html; charset=ISO-8859-1
Expires: -1
Client-Date: Sun, 20 Jun 2010 21:34:18 GMT
Client-Peer: 66.102.13.106:443
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
Client-SSL-Cert-Subject: /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com
Client-SSL-Cipher: RC4-SHA
Client-SSL-Warning: Peer certificate not verified
Set-Cookie: PREF=ID=4d56960f6e3ad831:TM=1277069652:LM=1277069652:S=GF-w8Yc-_61NBzzJ; expires=Tue, 19-Jun-2012 21:34:12 GMT; path=/; domain=.google.com
Title: Google
X-XSS-Protection: 1; mode=block

But with CURL the header is much shorter:

HTTP/1.1 200 OK
Date: Sun, 20 Jun 2010 21:39:07 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=2d4fb1c933eebd09:TM=1277069947:LM=1277069947:S=6_TgGKzD0rM4IWms; expires=Tue, 19-Jun-2012 21:39:07 GMT; path=/; domain=.google.com
Server: gws
X-XSS-Protection: 1; mode=block
Transfer-Encoding: chunked

Is there any possibility to get these information, the full header with CURL or with some other PHP function?

A: 

Are you setting "https" from CURL? Also make sure to change the CURLOPT SSL options correctly.

Christian Sciberras
Could you explain please which options do you mean exactly please?I've been playing with CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST and I'm setting the url, CURLOPT_URL to https://www.google.com/ but still no results.Or am I missing something ?
Radek Suski
+1  A: 

No. EDIT: A CURLINFO_CERTINFO option has been added recently. See http://bugs.php.net/49253

Apparently, that information is being given to you by your proxy in the response headers. If you want to rely on that, you can use curl's CURLOPT_HEADER option to trueto include the headers in the output.

However, to retrieve the certificate without relying on some proxy, you must do

<?php
$g = stream_context_create (array("ssl" => array("capture_peer_cert" => true)));
$r = fopen("https://www.google.com/", "rb", false, $g);
$cont = stream_context_get_params($r);
var_dump($cont["options"]["ssl"]["peer_certificate"]);

You can manipulate the value of $cont["options"]["ssl"]["peer_certificate"] with the OpenSSL extension.

EDIT: This option is better since it doesn't actually make the HTTP request and does not require allow_url_fopen:

<?php
$g = stream_context_create (array("ssl" => array("capture_peer_cert" => true)));
$r = stream_socket_client("ssl://www.google.com:443", $errno, $errstr, 30,
    STREAM_CLIENT_CONNECT, $g);
$cont = stream_context_get_params($r);
var_dump($cont["options"]["ssl"]["peer_certificate"]);
Artefacto
So I will need the directive "allow_url_fopen" to get the certificate information?
Radek Suski
BTW: Why do you think that this connection is going through a proxy server? The CURLOPT_HEADER has been set. But the header seems not to be complete
Radek Suski
@Radek Suski Because google does not send such `Client-*` headers.
Artefacto
@Rad I've also included an option that doesn't require `allow_url_fopen`.
Artefacto
I find it hard to believe that CURL can't do this. CURL is the de facto low-level connection library which I found as an answer to problems even in FTP.I'll do my own tests to get this working, if possible.
Christian Sciberras
Artefacto
@Artefacto: Thank you very much. It works great and with openssl_x509_parse I was able to parse the certificate.@Chris: I have tried also to get certificate of my server and it does not work either. Funny thing is that the function curl_getinfo returns also an array called "certinfo" which is always empty.
Radek Suski
@Rad You're right, my bad, there's a certinfo array that's defined in another file. If it's not filled and `LIBCURL_VERSION_NUM > 0x071301`, that's probably a bug.
Artefacto
A: 

To do this in php and curl:

<?php
if($fp = tmpfile())
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,"https://www.digicert.com/");
    curl_setopt($ch, CURLOPT_STDERR, $fp);
    curl_setopt($ch, CURLOPT_CERTINFO, 1);
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_NOBODY, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
    curl_setopt($ch, CURLOPT_SSLVERSION,3);
    $result = curl_exec($ch);
    curl_errno($ch)==0 or die("Error:".curl_errno($ch)." ".curl_error($ch));
    fseek($fp, 0);//rewind
    $str='';
    while(strlen($str.=fread($fp,8192))==8192);
    echo $str;
    fclose($fp);
}
?>
velcrow
Are you sure you read my question and all these answer?
Radek Suski
My example requires php 5.3.2, and the SSL cert information is available in $str, the HTTP headers are available in $result.
velcrow