[spip-dev] Authentification SSL Client et SPIP

Bonjour,

Pour un usage dans un Intranet, je souhaitais effectuer le contrôle d'accès au
serveur par de l'authentification SSL Client (serveur Apache).

J'ai donc apporté quelques modifications au code SPIP (j'ai travaillé sur la
version 1.5a5, sous Windows pour faire mes tests) que je vous livre (désolé,
par de diff).

Fonctionnement: si tu arrives en authentification SSL client dans la page de
login, et que Apache t'as authentifié (SSL_CLIENT_VERIFY == SUCCESS), et que
Spip trouve ton CN dans sa table des auteurs, dans le champ 'login' (le champ
pass est ignoré), alors tu est authentifié directement, sans taper de mot de
passe. Voir en fin de mail la configuration d'Apache.

Si tu n'es pas trouvé dans la table des auteurs, SPIP sort une page d'erreur et
tu as la possibilité de te connecter avec un login/mot de passe classique
(lien "reconnecter").

Note: il est important de placer un mot de passe sur les auteurs créés ou il
devient possible de se connecter à leur place, sans mot de passe.

Les modifications à apporter sont les suivantes:
-dans ecrire/inc_session.php3, rajouter une fonction verifier_x509_auth():

//
// reconnaitre un utilisateur authentifie en php_auth (Nicolas STAMPF
<stampf.lutin@free.fr> 2003/11/20)
//
function verifier_x509_auth() {
  global $_SERVER;
  if ($_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" && $_SERVER
["SSL_CLIENT_S_DN_CN"]) {
    $login = addslashes($_SERVER["SSL_CLIENT_S_DN_CN"]);
    $result = spip_query("SELECT * FROM spip_auteurs WHERE
login='$login'"); // le login doit valoir le CN du certificat
    $row = spip_fetch_array($result);
    $GLOBALS['auteur_session']['id_auteur'] = $row['id_auteur'];
    $GLOBALS['auteur_session']['nom'] = $row['nom'];
    $GLOBALS['auteur_session']['login'] = $row['login'];
    $GLOBALS['auteur_session']['email'] = $row['email'];
    $GLOBALS['auteur_session']['statut'] = $row['statut'];
    $GLOBALS['auteur_session']['hash_env'] = '';
    return true;
  } else {
    return false;
  }
}

-dans ecrire/inc_auth.php3, rajouter le code suivant dans la fonction auth(),
juste avant if(!$auth_login)

  // Peut-être sommes-nous authentifiés avec un certificat client x509?
Nicolas STAMPF <stampf.lutin@free.fr> 2003/11/20
  else if ($_SERVER["SSL_CLIENT_VERIFY"] && $_SERVER
["SSL_CLIENT_S_DN_CN"]) {
    if (verifier_x509_auth()) {
      $auth_login = $_SERVER["SSL_CLIENT_S_DN_CN"];
      $auth_pass_ok = true;
      $auth_can_disconnect = true;
    } else {
      // Normalement on n'arrive pas là car une
authentification x509 echouée doit être rejetée par le serveur
      // c'est à dire qu'il faut placer "SSLVerifyClient
require" et non "optional" dans Apache, par exemple
      $auth_login = '';
      echo "<p><b>Connexion refus&eacute;e</b></p>";
      echo "[<a href='../spip_cookie.php3?
essai_auth_http=oui'>r&eacute;essayer</a>]";
      exit;
    }
  }

C'est tout. Ensuite, il faut configurer le serveur Apache. Voici ce que j'ai
fait:

-créé un répertoire conf/ssl dans lequel j'ai mis:
-ca.crt qui est le certificat de la CA qui signe les utilisateurs que l'on
accepte.
-créé un certificat serveur et placé dans conf/ssl les fichiers server.crt et
server.key: sert à identifier le serveur.

Ensuite, configurer Apache dans conf/httpd.conf:
LoadModule ssl_modules modules/mod_ssl.so # (mettre ce qui va bien, c'est ma
conf Windows, ca)
AddModule mod_ssl.c

et plus loin:

<IfModule mod_ssl.c>
  # see http://www.modssl.org/docs/2.8/ssl_reference.html for more info
  SSLMutex sem
  SSLRandomSeed startup builtin
  SSLSessionCache none

  SSLLog logs/SSL.log
  SSLLogLevel info
  # You can later change "info" to "warn" if everything is OK

  <VirtualHost parw031096:443>
    SSLEngine On
    SSLCertificateFile conf/ssl/server.crt
    SSLCertificateKeyFile conf/ssl/server.key
    SSLCACertificateFile conf/ssl/ca.crt
    SSLOptions StdEnvVars # pour avoir les variables dont se sert
PHP!

<Location /spip>
  SSLVerifyClient require
  SSLVerifyDepth 1
</Location>

</VirtualHost>
</IfModule>

Note: on pourra améliorer le contrôle des certificats dans Apache à l'aide de
la directive SSLRequire pour effectuer des contrôles sur les champs du
certificat.

Ces modifications sont sans garanties: elles ont fonctionné pour moi, peut-être
pour vous, mais ne vous plaignez pas si cela casse tout! Pensez à effectuer une
sauvegarde avant.