Le module ntlm2 (SSO - Single Sign On) avec Apache 2.2 sous Solaris

Introduction

Dans les articles précédents, l'étude de la compilation d'un serveur Apache 2.0 incluant les modules LDAP pour l'authentification a été réalisée (Compilation et configuration d'un serveur Apache 2.0 avec LDAP sous Solaris). Le module LDAP est puissant pour l'authentification mais il présente un inconvénient majeur : la fenêtre de login/mot de passe est systématique.

Il est plus avantageux de pouvoir mettre en œuvre ce que l'on appelle du SSO (Single Sign On) : l'utilisateur n'a pas besoin de re-taper son login et son mot de passe pour accéder à une zone sécurisée par Apache. De plus la plupart des applications ont besoin de la variable Apache REMOTE_USER et cette variable est automatiquement renseignée avec l'utilisateur dans un contexte Single Sign On.

Le module Apache mod_ntlm2 permet de mettre en œuvre cette fonctionnalité : NTLM, acronyme pour "NT Lan Manager" est un protocole d'identification Microsoft combiné au protocole SMB (Samba). Cet article décrit la mise en place du module NTLM (compilation, configuration etc...) au sein d'un serveur Apache 2.2 sous Solaris.

Compilation d'un serveur Apache 2.2 sous Solaris

Dans le contexte de cet article, la distribution Apache 2.2 a été compilée et installée avec la ligne de configuration ci-dessous.


root% ./configure --prefix=/Software/apache/apache-2.2
        --with-ldap --with-ldap-lib=/Software/openldap/lib
        --with-ldap-include=/Software/openldap/include
        --enable-ldap
        --enable-authnz-ldap

L'objectif de cet article n'est pas de décrire à nouveau la compilation d'un serveur Apache 2.2 qui est guère différente de la compilation d'un serveur Apache 2.0 : pour plus d'informations Compilation et configuration d'un serveur Apache 2.0 avec LDAP sous Solaris

Juste une petite note d'informations : c'est la version 2.2.8 qui a été compilée, la commande configure présentant quelques bugs avec la version 2.2.9 (configure: WARNING: Unrecognized options: --with-ldap....). Ce ne sont en fait que des avertissements sans gravité, toutefois pour la mise en œuvre du module mod_ntlm sans problèmes, c'est la version 2.2.8 qui a été choisie.

Compilation du module mod_ntlm2 avec apxs

Pré-requis de l'environnement de compilation

Le binaire ar est indispensable pour la compilation du module ntlm 2 avec Apache 2.2. Le binaire ar compile les librairies .a nécessaires et sans précautions, la compilation est en échec car le binaire ar n'est pas installé dans des répertoires standards comme /usr/local/bin etc..., il est installé dans le répertoire /usr/ccs/bin.

Après vérification de la présence du binaire ar dans le répertoire /usr/ccs/bin, il faut modifier la variable d'environnement PATH ou AR afin de référencer le répertoire /usr/ccs/bin pour l'utilisateur root qui réalise la compilation : dans le contexte de cet article, c'est la variable PATH qui est modifiée en passant en K-Shell. Par précaution également, pour retrouver les packages nécessaires lors de la compilation, les répertoires /usr/local/bin et /usr/local/lib sont respectivement référencés dans les variables PATH et LD_LIBRARY_PATH :

root% ksh
root% export PATH=/usr/ccs/bin:/usr/local/bin:$PATH
root% export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

Préparation de la compilation

Le module mod_ntlm2 est disponible dans une archive compressée (mod_ntlm2-0.1.tgz) sur le site SourceForge : Module ntlm2.

L'archive est installée et décompressée dans le répertoire /export/home/compilation/apache en tant que root :

root% cd /export/home/compilation/apache
root% gunzip mod_ntlm2-0.1.tgz

Puis les fichiers sont extraits de l'archive mod_ntlm2-0.1.tar avec la commande tar :

root% tar xvf mod_ntlm2-0.1.tar

Les fichiers sources sont extraits par la commande tar dans le répertoire /export/home/compilation/apache/mod_ntlm2-0.1.tar.

Compilation du module ntlm2 avec apxs (APache eXtenSion tool)

Le binaire apxs d'Apache 2.2

Le module mod_ntlm2 est compilée avec le binaire apxs de la distribution Apache 2.2. apxs (APache eXtenSion tool) est un nouveau binaire permettant de compiler des modules à la volée sans avoir besoin des sources Apache et de recompiler une distribution Apache.

Pour pouvoir utiliser le binaire apxs, les répertoires bin et lib de la distribution Apache 2.2 doivent être respectivement inclus dans les variables d'environnement PATH et LD_LIBRARY_PATH.

root% ksh
root% export PATH=/Software/apache/apache-2.2/bin:$PATH
root% export LD_LIBRARY_PATH=/Software/apache/apache-2.2/lib:$LD_LIBRARY_PATH

Ce sont les options -i, -a et -c qui sont utilisées dans l'appel d'apxs pour compiler le module ntlm2.

root% apxs -i -a -c mod_ntlm.c

Description des parametres :



-i L'option -i spécifie d'installer le ou les modules dans le répertoire des modules d'Apache (/Software/apache/apache-2.2/modules)
-a L'option -a ajoute automatiquement la directive LoadModule dans le fichier httpd.conf d'Apache
-c <fichier C> L'option -c indique qu'il s'agit d'une opération de compilation. Les fichiers sources *.c sont compilés en fichiers objets *.o, puis construits en objet partagé dynamique (fichier *.so pour Solaris).

Quelques retouches dans le fichier mod_ntlm.c avant la compilation

Fonction apr_pool_sub_make devenu obsolète
Avant de lancer la compilation du module mod_ntlm, une modification doit être apportée dans le ficher source mod_ntlm.c, en effet la fonction apr_pool_sub_make est devenue obsolète et a été remplacée par la fonction apr_pool_create_ex

Sans cette modification, l'erreur ci-dessous apparaît au démarrage d'Apache (la compilation ne bloque pas) :

apache>./apachectl start

httpd: Syntax error on line 53 of /Software/apache/apache-2.2/conf/httpd.conf:
Cannot load /Software/apache/apache-2.2/modules/mod_ntlm.so into server: ld.so.1: httpd: fatal:
relocation error: file /Software/apache/apache-2.2/modules/mod_ntlm.so:
symbol apr_pool_sub_make: referenced symbol not found

Il faut remplacer dans le fichier mod_ntlm.c :

apr_pool_sub_make(&sp,p,NULL);

par

apr_pool_create_ex(&sp,p,NULL,NULL);
Réduction de la verbosité

Il est également judicieux de mettre en commentaire dans le fichier mod_ntlm.c quelques commandes log et DEBUG, car par défaut, le module mod_ntlm.c est très verbeux dans le fichier error_log du serveur Apache 2.2, ainsi certaines lignes de code qui écrivent dans le fichier error_log sont mises en commentaire :

/**
#ifdef LOG
    log(r, "got header with host \"%s\", domain \"%s\"",
        ntlmssp->host, ntlmssp->domain);
#endif
*/
Délocalisation du fichier mod_ntlm.log

Par défaut en consultant le code source mod_ntlm.c, quelques informations sont écrites dans le fichier de log /tmp/mod_ntlm.log. En fonction de l'environnement, il est peut être souhaitable que ce fichier de log soit créé dans un répertoire autre que /tmp. C'est dans cette portion de code ci-dessous qu'il est possible de spécifier le nouveau chemin pour le fichier de log mod_ntlm.log :

    if ((f = fopen("/tmp/mod_ntlm.log", "a")) != NULL) {
        fputs(s, f);
        fputs("\n", f);
        fclose(f);
    }

Dans le cas pratique de cette documentation, le fichier de log mod_ntlm.log est délocalisé dans le répertoire /Software/apache/apache-2.2/logs

    if ((f = fopen("/Software/apache/apache-2.2/logs/mod_ntlm.log", "a")) != NULL) {
        fputs(s, f);
        fputs("\n", f);
        fclose(f);
    }

Compilation du module avec apxs

Voici ci-dessous le résultat de la compilation du module mod_ntlm.c dans la distribution Apache 2.2.

SRVUNXFR1# apxs -i -a -c mod_ntlm.c

/Software/apache/apache-2.2/build/libtool --silent
        --mode=compile gcc -prefer-pic
        -DSOLARIS2=9 -D_POSIX_PTHREAD_SEMANTICS
        -D_REENTRANT -D_LARGEFILE64_SOURCE -g -O2 -pthreads
        -I/Software/apache/apache-2.2/include -I/Software/apache/apache-2.2/include
        -I/Software/apache/apache-2.2/include -I/Software/openldap/include
        -c -o mod_ntlm.lo mod_ntlm.c && touch mod_ntlm.slo
mod_ntlm.c:44: warning: conflicting types for built-in function 'log'
/Software/apache/apache-2.2/build/libtool --silent
        --mode=link gcc -o mod_ntlm.la
        -rpath /Software/apache/apache-2.2/modules -module
        -avoid-version    mod_ntlm.lo
/Software/apache/apache-2.2/build/instdso.sh
        SH_LIBTOOL='/Software/apache/apache-2.2/build/libtool'
        mod_ntlm.la /Software/apache/apache-2.2/modules
/Software/apache/apache-2.2/build/libtool
        --mode=install cp mod_ntlm.la /Software/apache/apache-2.2/modules/
cp .libs/mod_ntlm.so /Software/apache/apache-2.2/modules/mod_ntlm.so
chmod +x /Software/apache/apache-2.2/modules/mod_ntlm.so
cp .libs/mod_ntlm.lai /Software/apache/apache-2.2/modules/mod_ntlm.la
cp .libs/mod_ntlm.a /Software/apache/apache-2.2/modules/mod_ntlm.a
chmod 644 /Software/apache/apache-2.2/modules/mod_ntlm.a
ranlib /Software/apache/apache-2.2/modules/mod_ntlm.a
----------------------------------------------------------------------
Libraries have been installed in:
   /Software/apache/apache-2.2/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - use the `-RLIBDIR' linker flag

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
chmod 755 /Software/apache/apache-2.2/modules/mod_ntlm.so
[activating module `ntlm' in /Software/apache/apache-2.2/conf/httpd.conf]

A l'issue de la compilation un fichier dso mod_ntlm.so est compilé et installé dans le répertoire /Software/apache/apache-2.2/modules, répertoires des modules.

Le fichier httpd.conf est modifié pour ajouter la directive LoadModule :

# LoadModule foo_module modules/mod_foo.so
LoadModule ntlm_module modules/mod_ntlm.so
#

Le module ntlm est alors prêt à l'emploi avec un simple redémarrage d'Apache.

Directives dans le fichier httpd.conf avec la module ntlm

Les directives d'authentification par le module NTLM sont données dans une section <Directory> </Directory> ou <location> </location> dans le ficher httpd.conf du serveur Apache. Dans l'exemple ci-dessous, l'accès au répertoire /dba/docroot/secure est sécurisé par une authentification NTLM :

<Directory "/dba/docroot/secure">
    AuthType NTLM
    NTLMAuth on
    NTLMAuthoritative off
    NTLMDomain <name of domain here>
    NTLMServer <hostname>
    NTLMBackup <hostname>
    Require valid-user
</Directory>
  • La directive AuthType NTLM permet d'indiquer que le répertoire est protégé par défaut par une authentification NTLM.
  • La directive NTLMAuth (on | off) active ou désactive l'authentification NTLM pour le répertoire.
  • La directive NTLMAuthoritative (on | off) permet d'empêcher ou non les autres modules d'authentification de prendre la main si l'authentifcation NTLM est en échec.
  • La directive NTLMDomain indique le domaine.
  • La directive NTLMServer indique le serveur jouant le rôle de contrôleur de domaines.
  • La directive NTLMBackup indique le serveur de secours jouant le rôle de contrôleur de domaines si le serveur primaire est défaillant.

Ensuite viennent les directives require pour attribuer les droits d'accès :

Pour autoriser tous les membres du domaine :

require valid-user

Pour autoriser un ou des utilisateurs d'un domaine:

require user bjenson fuser jmanager

Pour les groupes, la fonctionnalité est un peu plus particulière et peu intéressante: il ne s'agit pas en effet des groupes au sens LDAP comme on pourrait le penser, mais de groupes définis dans un fichier personnalisé défini par la directive AuthNTGroups :

<Directory "/dba/docroot/secure">
    AuthType NTLM
    AuthNTGroups /usr/local/apache/conf/ntgroup
    NTLMAuth on
    NTLMAuthoritative off
    NTLMDomain <name of domain here>
    NTLMServer <hostname>
    NTLMBackup <hostname>
    Require group admin
</Directory>

Les utilisateurs sont alors définis dans le fichier donné par la directive AuthNTGroups :

admin: joe jane
office: jim jeff
L'utilisation des groupes est exclusive, il n'est pas possible de combiner des directives "require group" et "require user". De plus avec la notion de groupes, l'utilisateur n'apparaît plus dans le fichier de log d'Apache.

Variables d'environnement REMOTE_USER et REDIRECT_REMOTE_USER

Au sein du serveur Apache, l'utilisateur est bien reconnu avec la variable REMOTE_USER, variable utilisable dans tout script cgi, en revanche dans un script PHP, si le mode FastCGI est mis en œuvre, ce n'est pas la variable REMOTE_USER qui est initialisée mais la variable REDIRECT_REMOTE_USER.

En version FastCGI pour PHP : c'est la variable PHP $_SERVER["REDIRECT_REMOTE_USER"] qui contient le nom de l'utilisateur authentifié.

Un simple appel de la fonction PHP phpinfo() permet de voir rapidement si c'est la variable $_SERVER["REMOTE_USER"] ou la variable $_SERVER["REDIRECT_REMOTE_USER"] qui est renseignée.

Activation de l'authentification NTLM avec FireFox (préférence network.automatic-ntlm-auth.trusted-uris)

L'authentification NTLM est automatique avec Internet Explorer, en revanche avec FireFox, une boîte de dialogue d'authentification apparaît. FireFox est beaucoup moins permissif qu'Internet Explorer.

Pour autoriser l'envoi des informations REMOTE_USER via FireFox, la préférence network.automatic-ntlm-auth.trusted-uris doit être modifiée.

Pour ajouter les sites de confiance pour lesquels les informations d'authentification NTLM peuvent être envoyées :

  • Ouvrir une fenêtre FireFox et taper dans la barre d'adresse "about:config" (sans le mot clé http://)
  • Dans le champ filtre, taper la préférence "network.automatic-ntlm-auth.trusted-uris"
  • Double-cliquer sur la préférence "network.automatic-ntlm-auth.trusted-uris" dans la liste, une boîte de dialogues s'affiche, boîte de dialogues dans laquelle les sites de confiance pouvant recevoir les informations d'authentification NTLM peuvent être saisis : les adresses URL doivent être saisies sous la forme http://intranet.company.com,http://email.company.lan.
  • Il faut que toutes les instances FireFox soient redémarrées pour que le paramétrage soit pris en compte.