Queremos autenticar una Web utilizando el DNI Electrónico, para ello vamos a utilizar:
Para ello, instalamos Apache2 y php5:
apt-get install apache2 libapache2-mod-php5 php5
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
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
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.net ⇒ https://dnie.locolandia.net:8443