Autenticación DNIe con Apache2 y PHP

Situación

Queremos autenticar una Web utilizando el DNI Electrónico, para ello vamos a utilizar:

Instalación

Para ello, instalamos Apache2 y php5:

apt-get install apache2 libapache2-mod-php5 php5

Certificados

Nos harán falta un par de claves SSL (privada y pública para nuestro servidor apache) las cuales colocaremos en formato de PEM en el fichero: /etc/apache2/ssl/apache.pem. Un buen documento de como generar nuestra propia clave es: http://www.tc.umn.edu/~brams006/selfsign.html

Y la clave pública de la CA de la policía, la cual se puede obtener de: Autoridades de Certificación del DNIe Dicha clave la situaremos en formato PEM en: /etc/ssl/certs/acraiz-dnie.cer

$ openssl x509 -in ACRAIZ-SHA1.crt -inform DER -out ACRAIZ-SHA1.crt -outform PEM
$ sudo cp ACRAIZ-SHA1.crt /etc/ssl/certs/acraiz-dnie.cer

Configuración

Configuramos apache2 para que soporte SSL en el puerto 443 (https):

# echo "Listen 8443" >> /etc/apache2/ports.conf

Y el servicio virtual para que soporte https en el fichero: /etc/apache2/sites-available/default-ssl

NameVirtualHost *:443
<VirtualHost *:443>

        SSLEngine On
        SSLCertificateFile /etc/apache2/ssl/apache.pem


        SSLCACertificateFile /etc/ssl/certs/acraiz-dnie.cer
        SSLVerifyClient require
        SSLVerifyDepth 2
        SSLOptions +StdEnvVars +ExportCertData

        DocumentRoot /var/www/

        ErrorLog /var/log/apache2/error.log

        LogLevel warn
        CustomLog /var/log/apache2/access.log combined

</VirtualHost>

Luego habilitamos la configuración de apache:

# a2ensite default-ssl
# /etc/init.d/apache2 restart

PHP y los datos del DNIe + Comprobación OCSP

Apache envía los datos de la autenticación mediante variables de entorno globales. La comprobación OCSP se realiza utilizando PHP + OpenSSL, debido a que mod_ssl para apache, no soporta OCSP.

Ejemplo de aplicación en PHP para obtener dichas variables es:

 
<html>
<head>
<title>Session and more ...</title>
</head>
<body>
 
<? if ($_SERVER['SSL_CLIENT_S_DN'])
    print "Autenticado con DNIe";
   else
    print "Autenticar con Login y Pass";
?>
 
<h1>Datos de variables globales</h1>
 
<h2>ENV</h2>
<table>
<tr><td><b>Clave</b></td><td><b>Valor</b></td></tr>
<? foreach (array_keys($_ENV) as $key)
    print "<tr><td>" . $key . "</td><td>" . $_ENV[$key] . "</td></tr>\n"; ?>
</table>
 
<h2>SERVER</h2>
<table>
<tr><td><b>Clave</b></td><td><b>Valor</b></td></tr>
<? foreach (array_keys($_SERVER) as $key)
    print "<tr><td>" . $key . "</td><td>" . $_SERVER[$key] . "</td></tr>\n"; ?>
</table>
 
<h2>SESSION</h2>
<table>
<tr><td><b>Clave</b></td><td><b>Valor</b></td></tr>
<? foreach (array_keys($_SESSION) as $key)
    print "<tr><td>" . $key . "</td><td>" . $_SESSION[$key] . "</td></tr>\n"; ?>
</table>
 
<h2>COOKIE</h2>
<table>
<tr><td><b>Clave</b></td><td><b>Valor</b></td></tr>
<? foreach (array_keys($_COOKIE) as $key)
    print "<tr><td>" . $key . "</td><td>" . $_COOKIE[$key] . "</td></tr>\n"; ?>
</table>
<h2>GLOBALS</h2>
<table>
<tr><td><b>Clave</b></td><td><b>Valor</b></td></tr>
<? foreach (array_keys($GLOBALS) as $key)
    print "<tr><td>" . $key . "</td><td>" . $GLOBALS[$key] . "</td></tr>\n"; ?>
</table>
 
<h2>OCSP Check</h2>
<?php
// User variables:
$dir = '/tmp/'; // Directory where apache has access to (chmod 777).
$RootCA = '/etc/ssl/certs/acraiz-dnie.cer'; // Points to the Root CA in PEM format.
$OCSPUrl = 'http://ocsp.dnie.es/'; //Points to the OCSP URL
// Script:
$a = rand(1000,99999); // Needed if you expect more page clicks in one second!
file_put_contents($dir.$a.'cert_i.pem', $_SERVER['SSL_CLIENT_CERT_CHAIN_0']); // Issuer certificate.
file_put_contents($dir.$a.'cert_c.pem', $_SERVER['SSL_CLIENT_CERT']); // Client (authentication) certificate.
$output = shell_exec('openssl ocsp -CAfile '.$RootCA.' -issuer '.$dir.$a.'cert_i.pem -cert '.$dir.$a.'cert_c.pem -url '.$OCSPUrl);
$output2 = preg_split('/[\r\n]/', $output);
$output3 = preg_split('/: /', $output2[0]);
$ocsp = $output3[1];
echo "OCSP status: ".$ocsp; // will be "good", "revoked", or "unknown"
unlink($dir.$a.'cert_i.pem');
unlink($dir.$a.'cert_c.pem');
?>
 
 
</body>
</html>

Para probar un poco: http://dnie.locolandia.nethttps://dnie.locolandia.net:8443

 
Subir
howto/apache-dnie-auth.txt · Última modificación: 02/12/2009 00:29 por xkill