2010-06-20 36 views
20

Me gustaría poder leer la información del certificado SSL con CURL. Desde la consola Linux obtengo esta cabecera de respuesta:¿Cómo obtener información del certificado SSL con CURL en PHP?

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 

Pero con el enrollamiento de la cabecera es mucho más corto:

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 

¿Hay alguna posibilidad de obtener esta información, la cabecera completa con rizo o con alguna otra función de PHP?

Respuesta

17

EDIT: Se ha agregado una opción CURLINFO_CERTINFO a PHP 5.3.2. Ver http://bugs.php.net/49253

Aparentemente, esa información la está dando su proxy en los encabezados de respuesta. Si desea confiar en eso, puede usar curl CURLOPT_HEADER option a true para incluir los encabezados en la salida.

Sin embargo, para recuperar el certificado sin depender de algún proxy, debe hacer

<?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"]); 

Se puede manipular el valor de $cont["options"]["ssl"]["peer_certificate"] con la extensión de OpenSSL.

EDITAR: Esta opción es mejor, ya que en realidad no hacen la petición HTTP y no requiere 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"]); 
+0

¿Necesitaré la directiva "allow_url_fopen" para obtener la información del certificado? –

+0

BTW: ¿Por qué crees que esta conexión pasa por un servidor proxy? Se ha configurado CURLOPT_HEADER. Pero el encabezado parece no estar completo –

+0

@Radek Suski Porque Google no envía tales encabezados 'Client- *'. – Artefacto

13

Para hacer esto en php y rizo:

 
<?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); 
    $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); 
} 
?> 
+0

¿Estás seguro de que has leído mi pregunta y todas estas respuestas? –

+2

Mi ejemplo requiere php 5.3.2, y la información del certificado SSL está disponible en $ str, los encabezados HTTP están disponibles en $ result. – velcrow

+0

Esta es la solución que necesitaba para verificar no solo si el certificado SSL existe, sino también si tiene algún error o no. ¡Gracias! – armandbertea

17

Obtendrá el certificado como recurso usando stream_context_get_params. Conecte ese recurso al $certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']); para obtener más información del certificado.

$url = "http://www.google.com"; 
$orignal_parse = parse_url($url, PHP_URL_HOST); 
$get = stream_context_create(array("ssl" => array("capture_peer_cert" => TRUE))); 
$read = stream_socket_client("ssl://".$orignal_parse.":443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get); 
$cert = stream_context_get_params($read); 
$certinfo = openssl_x509_parse($cert['options']['ssl']['peer_certificate']); 
print_r($certinfo); 

Ejemplo resultar

Array 
(
    [name] => /C=US/ST=California/L=Mountain View/O=Google Inc/CN=www.google.com 
    [subject] => Array 
     (
      [C] => US 
      [ST] => California 
      [L] => Mountain View 
      [O] => Google Inc 
      [CN] => www.google.com 
     ) 

    [hash] => dcdd9741 
    [issuer] => Array 
     (
      [C] => US 
      [O] => Google Inc 
      [CN] => Google Internet Authority G2 
     ) 

    [version] => 2 
    [serialNumber] => 3007864570594926146 
    [validFrom] => 150408141631Z 
    [validTo] => 150707000000Z 
    [validFrom_time_t] => 1428498991 
    [validTo_time_t] => 1436223600 
    [purposes] => Array 
     (
      [1] => Array 
       (
        [0] => 1 
        [1] => 
        [2] => sslclient 
       ) 

      [2] => Array 
       (
        [0] => 1 
        [1] => 
        [2] => sslserver 
       ) 

      [3] => Array 
       (
        [0] => 1 
        [1] => 
        [2] => nssslserver 
       ) 

      [4] => Array 
       (
        [0] => 
        [1] => 
        [2] => smimesign 
       ) 

      [5] => Array 
       (
        [0] => 
        [1] => 
        [2] => smimeencrypt 
       ) 

      [6] => Array 
       (
        [0] => 1 
        [1] => 
        [2] => crlsign 
       ) 

      [7] => Array 
       (
        [0] => 1 
        [1] => 1 
        [2] => any 
       ) 

      [8] => Array 
       (
        [0] => 1 
        [1] => 
        [2] => ocsphelper 
       ) 

     ) 

    [extensions] => Array 
     (
      [extendedKeyUsage] => TLS Web Server Authentication, TLS Web Client Authentication 
      [subjectAltName] => DNS:www.google.com 
      [authorityInfoAccess] => CA Issuers - URI:http://pki.google.com/GIAG2.crt 
OCSP - URI:http://clients1.google.com/ocsp 

      [subjectKeyIdentifier] => FD:1B:28:50:FD:58:F2:8C:12:26:D7:80:E4:94:E7:CD:BA:A2:6A:45 
      [basicConstraints] => CA:FALSE 
      [authorityKeyIdentifier] => keyid:4A:DD:06:16:1B:BC:F6:68:B5:76:F5:81:B6:BB:62:1A:BA:5A:81:2F 

      [certificatePolicies] => Policy: 1.3.6.1.4.1.11129.2.5.1 

      [crlDistributionPoints] => URI:http://pki.google.com/GIAG2.crl 

     ) 

) 
+2

Esta es una respuesta mejor que la respuesta aceptada. Falta la línea clave '$ certinfo = openssl_x509_parse ($ cert ['options'] ['ssl'] ['peer_certificate']);' que necesitaba para verificar diferentes detalles sobre mi cert –

+0

Esta es la solución que necesitaba, pero con un pequeño cambio. Voy a utilizar esto para verificar el período de validez de cert en localhost (por lo que el certificado no es válido para este "dominio"), así que tuve que cambiar: '$ get = stream_context_create (array (" ssl "=> array (" capture_peer_cert "=> TRUE)));' a '$ get = stream_context_create (array (" ssl "=> array (" capture_peer_cert "=> TRUE," verify_peer_name "=> FALSE)));' – Whatts

0

Este fragmento de código no está utilizando rizo específicamente, pero que recupera e imprime el texto del certificado remoto (puede ser manipulado para devolver cualquier detalle que se desea utilizar las diversas funciones openssl_)

$g = stream_context_create (array("ssl" => array("capture_peer_cert" => true))); 
$r = fopen("https://somesite/my/path/", "rb", false, $g); 
$cont = stream_context_get_params($r); 
openssl_x509_export($cont["options"]["ssl"]["peer_certificate"],$cert); 
print $cert; 

salidas:

-----BEGIN CERTIFICATE----- 
...certificate content... 
-----END CERTIFICATE----- 
Cuestiones relacionadas