Squid : Authentification par groupes avec un annuaire LDAP

Christophe ILKIEWICZ - christophe.ilkiewicz@wanadoo.fr

Version 1.0 - Dernière mise à jour le 2 mars 2004

Version originale 1 page : http://www.espace-groupware.com/squid/authentification-ldap/doc.html
Version originale multi-pages : http://www.espace-groupware.com/squid/authentification-ldap/index.html

1  Introduction

Pour réglementer l'usage d'un proxy, il existe plusieurs moyens d'authentification, souvent par individus, ce qui implique que lorsque l'on veut modifier des restrictions qui s'appliquent à un groupe d'individus, il faut les modifier pour chacun des individus, ce qui est assez fastidieux. Or, le proxy Squid permet d'utiliser une authentification par groupes, les informations sur les groupes et les individus se trouvant dans un annuaire LDAP. Ainsi, on n'applique plus les restrictions à des individus, mais à des groupes, et pour changer un individu de groupe il suffit d'intervenir sur l'annuaire LDAP, on n'a pas besoin de modifier la configuration du proxy, les restrictions s'appliquant à cet individu étant automatiquement celles de son nouveau groupe.

Nous verrons ici comment installer et configurer un annuaire OpenLDAP et un proxy Squid 2.5 afin d'avoir une telle méthode d'authentification, puis comment adapter la configuration de Squid pour utiliser Active Directory à la place d'OpenLDAP pour cette authentification.

2  OpenLDAP

OpenLDAP est un annuaire open-source qui implémente le protocole LDAP. Pour récupérer les sources d'OpenLDAP ainsi que la documentation officielle, une seule adresse : http://www.openldap.org .

2.1  Installation

OpenLDAP nécessite que BerkeleyDB (http://www.sleepycat.com ) soit installé, ce qui ne pose pas de problème particulier, que ce soit une installation à partir d'un binaire ou de sources.

En revanche, pour installer OpenLDAP à partir des sources (afin d'avoir la dernière version disponible, la 2.2.5, qui nécessite d'ailleurs d'avoir la version 4.2 de BerkeleyDB ), il faut procéder ainsi, une fois que l'on a décompressé les sources et que l'on s'est placé dans le répertoire principal des sources :
$ export CPPFLAGS='-I/usr/local/BerkeleyDB.4.2/include'
       # adapter le chemin si celui-ci est incorrect : c'est le chemin d'installation de BerkeleyDB
$ export LDFLAGS='-L/usr/local/BerkeleyDB.4.2/lib'
$ ./configure --with-tls=no --with-cyrus-sasl=no
       # les 2 paramètres permettent de désactiver le support tls et cyrus sasl 
$ make depend
$ make
$ make test
$ su root -c "make install"
(consulter le fichier INSTALL dans le répertoire principal des sources d'OpenLDAP , ainsi que le guide d'installation sur http://www.openldap.org pour plus d'informations, et la section 5.1 pour voir comment utiliser OpenLDAP avec TLS)

2.2  Configuration

Pour configurer OpenLDAP , il faut modifier le fichier slapd.conf (situé par défaut, si on a installé depuis les sources, dans le répertoire /usr/local/etc/openldap).

Vers la fin de ce fichier, il faut avoir les lignes suivantes :
allow bind_v2
pour autoriser les clients qui utilisent le protocole LDAPv2 (par défaut seuls ceux utilisant LDAPv3 sont autorisés). En effet, squid_ldap_auth peut utiliser LDAPv2, donc dans ce cas cette ligne devient indispensable (la version de squid_ldap_auth fournie avec Squid à partir de la version 2.5.STABLE3 permet d'indiquer la version de LDAP à utiliser à l'aide du paramètre -v ; la version la plus récente de Squid existant en package RedHat au moment de la rédaction de ce document est la 2.5.STABLE1).
database bdb
suffix "dc=example,dc=com"
à remplacer par le bon suffixe
rootdn "cn=Manager,dc=example,dc=com"
à adapter également
rootpw secret
mettre un vrai mot de passe, en clair (déconseillé), ou crypté (par exemple le mot de passe crypté correspondant à "secret" est {SSHA}qmWiSnPhgOfkfmU0JS1XGVgvfA/0GFKu). On peut crypter un mot de passe par exemple avec /usr/local/sbin/slappasswd.

Une fois que le fichier de configuration a été correctement écrit, l'annuaire est prêt à être utilisé.

2.3  Utilisation

Pour utiliser l'annuaire OpenLDAP , il faut tout d'abord exécuter slapd (situé par défaut dans /usr/local/libexec/).

Ensuite, on peut consulter l'annuaire, ajouter, modifier, ou retirer des entrées au moyen de ldapsearch, ldapadd, ldapmodify, ldapdelete (fournis avec OpenLDAP ) et de fichiers LDIF (LDAP Data Interchange Format)... ou bien à l'aide d'outils graphiques comme l'interface php phpLDAPadmin (http://phpldapadmin.sourceforge.net ) ou l'outil java LDAP Browser/Editor (http://www.iit.edu/~gawojar/ldap )...

2.4  Exemple

J'ai défini un annuaire d'exemple correspondant à l'arbre suivant :


Figure 1 : Arbre d'exemple


On a ainsi 4 utilisateurs situés dans l'Organizational Unit (ou) Users, et 2 groupes situés dans l'ou Groups, 2 utilisateurs étant membres du premier groupe, les 2 autres utilisateurs étant membres du deuxième groupe.

Le fichier LDIF correspondant est le suivant :
version: 1

# LDIF Export for: dc=example,dc=com
# Generated by phpLDAPadmin on February 17, 2004 2:52 pm
# Server: Serveur test (localhost)
# Search Scope: sub
# Total entries: 10

# Entry 1: dc=example,dc=com
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
o: my organization
dc: example

# Entry 2: cn=Manager,dc=example,dc=com
dn: cn=Manager,dc=example,dc=com
objectClass: organizationalRole
cn: Manager

# Entry 3: ou=Groups,dc=example,dc=com
dn: ou=Groups,dc=example,dc=com
ou: Groups
objectClass: top
objectClass: organizationalUnit

# Entry 4: ou=Users,dc=example,dc=com
dn: ou=Users,dc=example,dc=com
ou: Users
objectClass: top
objectClass: organizationalUnit

# Entry 5: cn=bart,ou=Users,dc=example,dc=com
dn: cn=bart,ou=Users,dc=example,dc=com
cn: bart
sn: Bart Simpson
userPassword: azerty
objectClass: person
objectClass: top

# Entry 6: cn=homer,ou=Users,dc=example,dc=com
dn: cn=homer,ou=Users,dc=example,dc=com
cn: homer
objectClass: person
objectClass: top
userPassword: azerty
sn: Homer Simpson

# Entry 7: cn=lisa,ou=Users,dc=example,dc=com
dn: cn=lisa,ou=Users,dc=example,dc=com
cn: lisa
objectClass: person
objectClass: top
userPassword: azerty
sn: Lisa Simpson

# Entry 8: cn=marge,ou=Users,dc=example,dc=com
dn: cn=marge,ou=Users,dc=example,dc=com
cn: marge
objectClass: person
objectClass: top
userPassword: azerty
sn: Marge Simpson

# Entry 9: cn=Parents,ou=Groups,dc=example,dc=com
dn: cn=Parents,ou=Groups,dc=example,dc=com
cn: Parents
objectClass: groupOfNames
objectClass: top
description: groupe des parents
member: cn=homer,ou=Users,dc=example,dc=com
member: cn=marge,ou=Users,dc=example,dc=com

# Entry 10: cn=Enfants,ou=Groups,dc=example,dc=com
dn: cn=Enfants,ou=Groups,dc=example,dc=com
cn: Enfants
objectClass: groupOfNames
objectClass: top
description: groupe des enfants
member: cn=bart,ou=Users,dc=example,dc=com
member: cn=lisa,ou=Users,dc=example,dc=com
Cet annuaire d'exemple servira plus loin dans l'exemple d'authentification par groupes de Squid .

3  Squid

On ne verra ici qu'une utilisation de Squid dans le cadre d'une authentification par groupes simple, pour une configuration plus avancée il faudra voir par exemple les documentations officielles.

3.1  Installation

L'installation de Squid à partir des binaires ne pose pas de problème particulier. Pour une installation à partir des sources, se référer à la documentation accessible depuis le site de Squid (http://www.squid-cache.org ).

3.2  Configuration

On configure Squid en modifiant le fichier /etc/squid/squid.conf.

On passe sur tous les paramètres classiques (http_port, cache_effective_user...).

Pour configurer l'authentification, on utilise squid_ldap_auth et squid_ldap_group .

3.2.1  squid_ldap_auth

squid_ldap_auth est ce qu'on appelle un authentication helper, c'est-à-dire un petit programme qui détermine si un couple login/pass est correct : dans ce cas-ci, il communique avec un annuaire LDAP afin de voir s'il existe une entrée dans l'annuaire ayant le login indiqué dans un champ uid (ou cn ou autre si on le précise), et le pass correspondant dans un champ userPassword, mais un autre authentication helper pourrait tout aussi bien regarder si le couple login/pass se trouve dans un fichier contenant une liste de login/pass, voire même renvoyer toujours OK... Ce programme doit renvoyer la chaîne de caractères "OK" en cas de succès et "ERR" en cas d'échec.

Pour utiliser squid_ldap_auth , on ajoute dans squid.conf les lignes suivantes :
auth_param basic program /usr/lib/squid/squid_ldap_auth -b ou=Users,dc=example,dc=com -u cn localhost
auth_param basic children 5
auth_param basic realm Identification proxy
auth_param basic credentialsttl 2 hours
Les paramètres ici utilisés pour squid_ldap_auth sont : On peut se demander à quoi servent les 3 lignes suivantes. Dans le cas d'une authentification par individus, il ne reste qu'à ajouter une règle ACL (Access Control List) qui indique l'utilisation du mécanisme d'authentification. Cette règle a la forme suivante :
acl password proxy_auth REQUIRED

Explications : Une fois cette règle ACL définie, on peut l'utiliser dans des règles d'accès, comme par exemple :
http_access allow password

Cette règle indique que tous les utilisateurs authentifiés auront un accès http (suivant sa position par rapport à d'autres règles d'accès, cet accès sera peut-être restreint).

On notera que la règle ACL d'authentification acl password proxy_auth REQUIRED devient inutile dès qu'on utilise l'authentification par groupes.

3.2.2  squid_ldap_group

squid_ldap_group est aussi un helper, mais il interroge un annuaire LDAP pour savoir si un utilisateur donné appartient bien à un groupe donné, indépendamment d'un quelconque mot de passe. C'est un complément à squid_ldap_auth qui permet d'établir des règles d'accès au proxy selon des groupes définis dans l'annuaire.

Pour l'utiliser, on ajoute dans squid.conf la ligne :
external_acl_type ldap_group ttl=3600 %LOGIN /usr/lib/squid/squid_ldap_group
    -b ou=Groups,dc=example,dc=com
    -B ou=Users,dc=example,dc=com
    -f "(&(cn=%g)(objectClass=groupOfNames)(member=%u))"
    -F "(&(cn=%s)(objectClass=person))"
    localhost
Attention, cette ligne a été découpée pour une lecture plus commode, mais dans le fichier de configuration, il ne faut pas la couper par des retours à la ligne.

Explications : Pour mieux comprendre le sens de ces paramètres, lire la section suivante.

Pour utiliser l'authentification par groupes, il faut également définir une règle ACL par groupe, du type :
acl group_Parents external ldap_group Parents

où : puis il faut définir des règles d'accès, comme par exemple :
http_access allow group_Parents

qui autorise l'accès http à tous les utilisateurs vérifiant l'ACL group_Parents, c'est-à-dire les utilisateurs authentifiés appartenant au groupe Parents dans l'annuaire LDAP.

3.3  Utilisation

Une fois que le proxy est configuré, on peut le lancer, ce qui se fait dans le cas d'une installation à partir des binaires Redhat 9 par la commande :
/etc/init.d/squid start

Si on doit le relancer (suite à une modification de squid.conf), on tape :
/etc/init.d/squid restart

On peut maintenant tester le proxy.

3.4  Exemple

On retourne sur son poste client, et on indique à son navigateur préféré que l'on utilise ce proxy, en lui donnant l'ip de l'ordinateur faisant office de serveur proxy, ainsi que le port utilisé (défini dans squid.conf par http_port).

Ensuite, lorsqu'on essaie d'accéder à une page nécessitant une authentification, une fenêtre devrait s'ouvrir, demandant un nom d'utilisateur et un mot de passe.


Figure 2 : Dialogue d'authentification


On notera qu'on retrouve bien la chaîne de caractères passée en argument à auth_param basic realm dans squid.conf.

Rentrons par exemple l'utilisateur homer et le mot de passe azerty. On accède bien à la page demandée, et on n'a plus besoin de rentrer son login/pass à nouveau (comportement de la plupart des navigateurs, indépendant de Squid ).

Si maintenant on relance le navigateur et si on réessaie d'accéder à la même page, la plupart des navigateurs vont redemander le login/pass. Rentrons cette fois-ci le couple bart/azerty, et on arrive à une page nous indiquant que l'accès est interdit. Pour accéder à la page, il faut donc relancer le navigateur et entrer un couple login/pass ayant les droits d'accès suffisants (en théorie chaque utilisateur ne connaît qu'un seul login/pass bien évidemment).

Pour bien comprendre le fonctionnement de l'authentification, on peut analyser les transmissions de paquets avec un outil comme Ethereal.

3.5  Fonctionnement

Ethereal est un outil d'analyse de protocoles réseau (http://www.ethereal.com ). Il permet d'observer les paquets échangés sur un réseau, de les classer par protocole... On ne s'intéresse ici qu'aux paquets LDAP échangés, entre le moment où on rentre un couple login/pass et le moment où une page s'affiche.

3.5.1  Identifiant incorrect

Dans le cas d'un utilisateur rentrant un mauvais login ou mot de passe, on observe la succession des paquets suivants :

3.5.2  Identifiant correct - Personne autorisée

Dans le cas d'un utilisateur autorisé rentrant correctement ses identifiants, on a d'abord les 3 mêmes paquets que précédemment, avec la nuance que le champ Result Code du paquet Bind Result indique Success, puis les paquets suivants :

3.5.3  Identifiant correct - Personne non autorisée

Enfin, dans le cas d'un utilisateur non autorisé rentrant correctement ses identifiants, on a exactement le même type de paquets échangés jusqu'au deuxième Search Request, qui, ayant un filtre ne correspondant à aucune entrée de l'annuaire, n'entraîne pas d'émission de paquet Search Entry.


Figure 7 : Search Request de groupe inexistant


Le deuxième paquet Search Request est donc immédiatement suivi en réponse d'un paquet Search Result indiquant que la recherche s'est effectuée sans problème (en effet le fait de ne pas avoir de réponse n'est pas une erreur), puis d'un paquet Unbind Request.

3.5.4  Remarques

ttl de squid_ldap_auth
Dans squid.conf, nous avons mis la ligne suivante :
auth_param basic credentialsttl 2 hours

Lorsqu'on s'est identifié correctement auprès du proxy (que l'on soit autorisé ou non), si on s'identifie une nouvelle fois avant la fin de la durée associée à credentialsttl, Squid ne fera pas d'échange avec le serveur LDAP. Squid possède en quelque sorte un cache d'identifiants, ce qui évite de solliciter le serveur LDAP trop souvent (en effet si on réduit cette durée à une seconde, on se rend compte en utilisant Ethereal que Squid effectue un Bind Request/Result/Unbind à chaque nouvelle page demandée par l'utilisateur). En contrepartie, si on modifie le mot de passe dans l'annuaire, le changement ne sera pas perçu avant la fin de la durée choisie ici, l'utilisateur n'aura donc pas besoin de se ré-authentifier avant la fin de cette durée (que ce soit l'utilisateur lui-même ou quelqu'un qui lui a volé son mot de passe et qui se sert de son compte), par contre une fois que la durée sera écoulée, Squid saura que le mot de passe n'est plus valide, et donc l'utilisateur devra s'authentifier à nouveau.

ttl de squid_ldap_group
De même, dans la ligne appelant squid_ldap_group de squid.conf, nous avons mis le paramètre
ttl=3600

Ce paramètre a le même rôle concernant squid_ldap_group que credentialsttl avec squid_ldap_auth . Ainsi, si on modifie l'annuaire LDAP de sorte à rajouter un utilisateur non autorisé dans un groupe autorisé, le changement ne sera pas perçu avant la fin de cette durée, et l'utilisateur ne sera donc pas autorisé selon Squid avant qu'il ne refasse sa requête au serveur LDAP.

(Remarque : ttl signifie time to live, c'est-à-dire le temps, la durée qu'il reste à vivre...)

4  Active Directory

Active Directory est l'annuaire utilisé par MS Windows 2000 Server et MS Windows Server 2003.

Une fois qu'on a réussi à interfacer Squid avec OpenLDAP , le passage à Active Directory n'est pas très compliqué. Il vaut donc mieux lire la section précédente avant de passer à celle-ci.

4.1  Description rapide des données utilisées dans Active Directory

Dans Active Directory , les utilisateurs sont en général répertoriés dans CN=Users, mais rien n'empêche de créer une zone plus adaptée, pour différencier toutes les personnes que l'on va ajouter de toutes les entrées qui se trouvent déjà par défaut dans CN=Users.

Par exemple, on peut créer une OU=Personnes (OU=Organizational Unit, c'est-à-dire Unité d'Organisation), ou tout autre chose selon ses souhaits. On peut alors ajouter des utilisateurs à l'emplacement de son choix.

Pour faire cela, la méthode classique est d'utiliser la console Utilisateurs et ordinateurs Active Directory, qui est accessible dans les Outils d'Administration, ou qu'on peut rajouter dans une console personnalisée au moyen de la Microsoft Management Console (qu'on peut lancer par la commande mmc). On crée ainsi des utilisateurs, par exemple Jean MARTIN, Pierre DUPONT et Jacques DURAND.

On peut aussi créer ces utilisateurs sans passer par la console Microsoft, mais en utilisant des programmes permettant de modifier les données d'un annuaire LDAP (les mêmes programmes qui permettent de remplir un annuaire OpenLDAP). Cependant, c'est un peu plus délicat au niveau des mots de passe (voir 4.4.1).

Maintenant que des utilisateurs existent, on peut créer un groupe qui regoupera les personnes ayant accès à Internet par exemple. Cela se fait aussi aisément avec les mêmes outils que pour les utilisateurs. On ajoute alors dans ce groupe les utilisateurs à qui on veut donner accès à Internet.

On peut alors passer à la configuration de Squid .

4.2  Configuration de Squid

Pour passer d'OpenLDAP à Active Directory , il suffit de modifier les 2 lignes d'appel de squid_ldap_auth et squid_ldap_group .

4.2.1  squid_ldap_auth

Voici la ligne que j'obtiens :
auth_param basic program /usr/lib/squid/squid_ldap_auth 
      -R -D "CN=Administrateur,CN=Users,DC=demo-cg77,DC=org" -w azerty 
      -b dc=demo-cg77,dc=org -f sAMAccountName=%s 101.0.50.41
Explications : A ce niveau, on peut déjà procéder à une authentification par individus.

4.2.2  squid_ldap_group

Pour l'authentification par groupes, on modifie la ligne d'appel de squid_ldap_group ainsi :
external_acl_type ldap_group ttl=3600 %LOGIN /usr/lib/squid/squid_ldap_group 
      -R -D "CN=Administrateur,CN=Users,DC=demo-cg77,DC=org" -w azerty 
      -b "cn=Users,dc=demo-cg77,dc=org" 
      -B "ou=Personnes,dc=demo-cg77,dc=org" 
      -f "(&(cn=%g)(objectClass=group)(member=%u))" 
      -F "(&(sAMAccountName=%s)(objectClass=person))" 
      101.0.50.41
De même que pour squid_ldap_auth , on a rajouté -R, -D ... et -w ..., on a adapté la base de recherche des utilisateurs et des groupes, on a mis l'adresse du serveur Active Directory , et on a changé, pour le filtre des utilisateurs, l'attribut déterminant le login.

Il faut remarquer, concernant le filtre des groupes, que l'on a changé la classe du groupe : en effet, dans Active Directory , les groupes ne sont pas de la classe groupOfNames, mais group.

Une fois ces modifications effectuées, on peut relancer Squid , et l'authentification doit fonctionner par l'intermédiaire d'Active Directory .

4.3  Petite remarque en passant

On observe avec Ethereal qu'Active Directory , contrairement à OpenLDAP , renvoie le Search Entry et le Search Result concaténés au sein du même paquet.

4.4  Utilisateurs

4.4.1  Attribution d'un mot de passe

Un mot de passe doit avoir une forme particulière pour pouvoir être attribué : On peut automatiser ceci par le petit script perl suivant :
use MIME::Base64; print encode_base64(join("\0",split(//,"\"password\"")) . "\0");

ou de manière plus interactive :
use MIME::Base64; chomp($p=<STDIN>); print encode_base64(join("\0",split(//,"\"$p\"")) . "\0");

(ce script lit l'entrée standard, rajoute les double quotes, sépare la chaîne de caractères obtenue en caractères distincts, rassemble ces caractères en intercalant des "\0", rajoute le dernier "\0", puis encode en base64 et renvoie la chaîne obtenue)

Il faut ensuite modifier l'utilisateur avec ldapmodify par exemple, mais en utilisant le port sécurisé (ldaps://). A priori, ce n'est que pour modifier le mot de passe que l'on est obligé d'utiliser le SSL (mais il est recommandé de toujours l'utiliser pour plus de sécurité).

Voir la section 5 pour plus d'informations sur le SSL, et plus particulièrement 5.2 pour savoir comment utiliser SSL avec Active Directory .

On peut très simplement automatiser toute l'opération de changement de mot de passe, par exemple avec le script perl suivant :
#!/usr/bin/perl use MIME::Base64; $l=6; $host="101.0.50.41"; $tmpfile="__chpass__tmp__ldif__file__"; print "DN de l'utilisateur Active Directory : "; chomp($u=<STDIN>); $msg = "Entrez un mot de passe ($l car. minimum) : "; do {   do {     system "stty -echo";     print $msg;     chomp($p=<STDIN>);     print "\n";     system "stty echo";     $msg = "Erreur - mot de passe trop court : "           ."il faut au moins $l caracteres\n"           ."Entrez un mot de passe ($l car. minimum) : ";   } while (length($p)<$l);   system "stty -echo";   print "Retapez le mot de passe (verification) : ";   chomp($p2=<STDIN>);   print "\n";   system "stty echo";   $msg = "Echec de la verification\n"         ."Entrez un mot de passe ($l car. minimum) : "; while (not ($p eq $p2)); open (OUTFILE, ">$tmpfile"); $crypt = encode_base64(join("\0",split(//,"\"".$p."\"")) . "\0"); print OUTFILE "dn: $u\n"."unicodePwd:: $crypt"; close (OUTFILE); print "\nMot de passe Administrateur Active Directory - "; $res=system "ldapmodify -D cn=Administrateur,cn=Users,dc=demo-cg77,dc=org -W -H ldaps://$host -f $tmpfile"; system "rm -f $tmpfile"; if ($res) {   print "Erreur : le mot de passe n'a donc pas ete change\n"; else {   print "Le mot de passe a bien ete change\n"; }

4.4.2  Activation de l'utilisateur : userAccountControl

Le champ userAccountControl regroupe plusieurs propriétés sur le compte utilisateur. C'est un champ de bits d'une taille de 4 octets, soit 32 bits, c'est-à-dire 32 drapeaux (flags), pouvant indiquer autant de propriétes.

En pratique, dans la documentation officielle de Microsoft, il n'y a pas d'explications pour tous ces bits, et les celles fournies sont très sommaires, j'ai donc tatonné pour comprendre à quoi correspondent certains de ces bits.

En voici la description (le bit 0 est celui de poids faible, c'est-à-dire le plus à droite) :
Bit n° Signification Valeur Accepté
0 Script 1 non
1 Compte désactivé 2 oui
3 Homedir required 8 oui
4 Lockout (verrouillage) 16 non
5 Password not required 32 oui
6 Password can't change 64 non
7 Enregistrer le mot de passe en utilisant un cryptage réversible 128 oui
8 Temp duplicate account 256 non
9 Normal account 512 oui
11 Interdomain trust account 2048 non
12 Workstation trust account 4096 oui
13 Server trust account 8192 non
16 Le mot de passe n'expire jamais 65536 oui
17 MNS logon account 131072 oui
18 Une carte à puce est nécessaire pour ouvrir une session interactive 262144 oui
19 Le compte est approuvé pour la délégation 524288 oui
20 Le compte est sensible et ne peut pas être délégué 1048576 oui
21 Utiliser les types de cryptage DES pour ce compte 2097152 oui
22 La pré-authentification Kerberos n'est pas nécessaire 4194304 oui

La valeur que l'on donne à userAccountControl est la somme des valeurs associées aux propriétés que l'on veut activer pour le compte (ces valeurs sont en fait 2 à la puissance le numéro du bit).

Ainsi, si on veut par exemple un compte normal désactivé, on met la valeur 514 (512 + 2), alors que si on veut qu'il soit activé, on met juste 512.

Si on veut que le mot de passe n'expire jamais, il suffit de rajouter 65536.

Si on veut activer l'utilisateur sans avoir défini de mot de passe, on met 512 + 32 = 544 ...

Attention, on ne peut pas (Active Directory l'empêche) cumuler "normal account" et "workstation trust account" par exemple, vu qu'un compte ne peut être que dans l'une de ces 2 catégories à la fois. En pratique, pour un normal account, l'utilisateur sera automatiquement membre du groupe Utilisa. du domaine, alors que pour un workstation trust account, il sera membre du groupe Ordinateurs du domaine.

Une fois que l'on a créé l'utilisateur, défini son mot de passe, et activé son compte, on peut enfin l'utiliser pour se connecter...

5  SSL

Afin de sécuriser les échanges d'informations avec les différents serveurs LDAP, on peut utiliser SSL (Secure Sockets Layer), qui est en fait une couche se rajoutant dans les paquets transmis, et permettant de crypter les données transmises.

J'ai tenté d'utiliser SSL avec OpenLDAP et Active Directory .

5.1  SSL avec OpenLDAP

Pour pouvoir utiliser SSL avec OpenLDAP , il faut l'avoir compilé avec le support SSL/TLS (TLS : Transport Layer Security). Il faut avoir au préalable installé OpenSSL .

(On peut aussi installer un package rpm, mais au moment de la rédaction de ce document, la dernière version que j'ai trouvée est OpenLDAP 2.1.25 (pas en paquet officiel, mais sur http://www.int-evry.fr/mci/user/procacci/SRPMS/9/ ). Cette version possède le support SSL, on peut donc l'utiliser)

Pour compiler OpenLDAP avec le support SSL/TLS, j'ai dû taper les commandes suivantes depuis le répertoire des sources :
$ export CPPFLAGS='-I/usr/local/BerkeleyDB.4.2/include -I/usr/kerberos/include'
      # configure ne trouvant pas les headers kerberos, il a fallu lui indiquer
      # où ils se trouvent
$ export LDFLAGS='-L/usr/local/BerkeleyDB.4.2/lib'
$ ./configure --with-tls=yes --with-cyrus-sasl=no
      # l'utilisation de tls et de cyrus sasl est choisie automatiquement par défaut,
      # ici on force l'utilisation de tls, et on interdit celle de cyrus sasl
      # (en effet, il y a déjà une version trop ancienne de cyrus sasl installée,
      # que je ne peux pas supprimer car c'est une dépendance de sendmail, mutt
      # et squid, et en compilant la dernière version, j'ai un problème de conflit de 
      # versions que je n'ai pas réussi à résoudre)
$ make depend
$ make
$ make test
$ su -c "make install"
Pour pouvoir utiliser SSL, il faut créer un certificat, reconfigurer le serveur, et le relancer en lui indiquant d'utiliser ssl.

5.1.1  Création d'un certificat

(cf http://www.openldap.org/pub/ksoper/OpenLDAP_TLS_howto.html (en anglais))

On peut assez aisément créer un certificat à l'aide d'OpenSSL .

En fait, on a besoin de : Pour les obtenir, on procède ainsi : Maintenant qu'on a les certificats nécessaires, on peut passer à la configuration du serveur OpenLDAP .

5.1.2  Configuration

On commence par copier les fichiers que l'on vient de générer à un endroit accessible par OpenLDAP , par exemple /usr/local/etc/openldap :
$ su
Password: <pass root>
# cp ./demoCA/cacert.pem /usr/local/etc/openldap/
# cp ./newcert.pem /usr/local/etc/openldap/ldap_crt.pem
# cp ./newreq.pem /usr/local/etc/openldap/ldap_key.pem
Puis on modifie le fichier slapd.conf, en ajoutant à la fin les lignes suivantes :
TLSCertificateFile     /usr/local/etc/openldap/ldap_crt.pem
TLSCertificateKeyFile  /usr/local/etc/openldap/ldap_key.pem
TLSCACertificateFile   /usr/local/etc/openldap/cacert.pem
Ca y est, le serveur OpenLDAP est correctement configuré pour gérer le SSL!

On configure aussi les clients afin de ne pas avoir à demander de certificat client (dans le cas contraire il faudrait créer des certificats pour les clients). Pour cela on rajoute dans ldap.conf la ligne :
TLS_REQCERT never

5.1.3  Utilisation

Si un serveur OpenLDAP tournait déjà en tâche de fond, on l'arrête proprement avec la commande :
kill -2 `cat /usr/local/var/run/slapd.pid`
(faire attention aux backquotes (`) (AltGr-7) qui ne sont pas des quotes (') ...)

Pour lancer le serveur OpenLDAP avec accès au port sécurisé uniquement, on tape la commande :
/usr/local/libexec/slapd -h "ldaps:///"
Pour le lancer avec à la fois accès au port sécurisé et au port classique, on tape :
/usr/local/libexec/slapd -h "ldap:/// ldaps:///"
On peut alors tester que tout fonctionne bien avec :
ldapsearch -b dc=example,dc=com -H ldaps://localhost
Dorénavant, lorsqu'on s'authentifie auprès du serveur LDAP (si on utilise bien le port ldaps), le mot de passe ne circule plus en clair sur le réseau, et on ne peut plus l'intercepter à l'aide d'un sniffer...

5.2  SSL avec Active Directory

Pour utiliser le SSL avec Active Directory , il faut aussi créer un certificat.

On procède ainsi :
Remarque
Apparemment, dans Windows 2000 Server (pas vérifié dans le 2003), s'il y a plusieurs certificats valides dans le magasin de l'ordinateur local,ce sera toujours le 1er trouvé qui sera sélectionné, donc pas forcément le bon, alors qu'avec OpenLDAP on indique tout simplement quel certificat on veut utiliser...




On peut maintenant tester la connexion SSL :
$ openssl s_client -connect 101.0.50.41:636 -showcerts -state -CAfile demoCA/cacert.pem
(on remplace bien sûr l'ip après "-connect" par l'adresse du serveur Active Directory ...)

Si tout se passe bien, on devrait avoir un certain nombre d'informations qui devraient s'afficher, comme sur l'exemple suivant :
$ openssl s_client -connect 101.0.50.41:636 -showcerts -state -CAfile demoCA/cacert.pem
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=1 /C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
verify return:1
depth=0 /C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
---
Certificate chain
 0 s:/C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
   i:/C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
-----BEGIN CERTIFICATE-----
MIIDCDCCAnGgAwIBAgIBATANBgkqhkiG9w0BAQQFADBZMQswCQYDVQQGEwJGUjEL
MAkGA1UECBMCNzcxDjAMBgNVBAcTBU1lbHVuMQ0wCwYDVQQKEwRDRzc3MR4wHAYD
VQQDExVhY3QyMDAwLmRlbW8tY2c3Ny5vcmcwHhcNMDQwMjI2MTQxNzI0WhcNMDUw
MjI1MTQxNzI0WjBZMQswCQYDVQQGEwJGUjELMAkGA1UECBMCNzcxDjAMBgNVBAcT
BU1lbHVuMQ0wCwYDVQQKEwRDRzc3MR4wHAYDVQQDExVhY3QyMDAwLmRlbW8tY2c3
Ny5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK78N9OZ58meYVWABeKN
E4gNT8Nl7t1FftOpp4qWQm63XVoMhOvioPJfrXwpjIeVlHHluFX3bmd7+QcrgLhe
gxEuffBv+FTS1VSqWr3EZArpk5d70l5ueUjLJGihG9gAZw/e23QJQcyT5kDr8aaZ
ZzdzPUd+97URBKKIXBDuhcUtAgMBAAGjgd8wgdwwCQYDVR0TBAIwADAsBglghkgB
hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
FLHG6t5N4zDcaUlo1fmUYOuHbEarMIGBBgNVHSMEejB4gBTAAn0nbntcY51kBaAg
oDpdptYzUqFdpFswWTELMAkGA1UEBhMCRlIxCzAJBgNVBAgTAjc3MQ4wDAYDVQQH
EwVNZWx1bjENMAsGA1UEChMEQ0c3NzEeMBwGA1UEAxMVYWN0MjAwMC5kZW1vLWNn
Nzcub3JnggEAMA0GCSqGSIb3DQEBBAUAA4GBAAOdM1OPLCEVpGLJjz8czhPVg42y
QNUiQYvTmSmG8868GjvKl2iPBmSp9ZEVNv2xVyUHb6E0VTwwWih1cujYLbWw9ixM
MhgENCSyrVHT59Y7m0P7vH1FRZMhfko04FiVHP7HWtDGL3B9wxK/M4SIPyRzE0Cr
i83N1Dd5i1Ecew9a
-----END CERTIFICATE-----
---
Server certificate
subject=/C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
issuer=/C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
---
Acceptable client certificate CA names
/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
/C=US/O=VeriSign, Inc./OU=Class 4 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting/OU=Certification Services
Division/CN=Thawte Personal Freemail CA/emailAddress=personal-freemail@thawte.com
/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting/OU=Certification Services
Division/CN=Thawte Personal Premium CA/emailAddress=personal-premium@thawte.com
/C=US/O=First Data Digital Certificates Inc./CN=First Data Digital Certificates
Inc. Certification Authority
/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting/OU=Certification Services
Division/CN=Thawte Personal Basic CA/emailAddress=personal-basic@thawte.com
/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
/C=US/O=VeriSign, Inc./OU=Class 2 Public Primary Certification Authority
/C=US/O=VeriSign, Inc./OU=Class 1 Public Primary Certification Authority
/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
/C=HU/L=Budapest/O=NetLock Halozatbiztonsagi Kft./OU=Tanusitvanykiadok/CN=NetLock Uzleti (Class B) Tanusitvanykiado
/C=US/O=GTE Corporation/CN=GTE CyberTrust Root
/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Global Root
/C=US/O=Entrust.net/OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Secure Server Certification Authority
/C=HU/ST=Hungary/L=Budapest/O=NetLock Halozatbiztonsagi Kft./OU=Tanusitvanykiadok/CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado
/C=US/O=VeriSign, Inc./OU=Class 2 Public Primary Certification Authority - G2/OU=(c) 1998 VeriSign, Inc. - For authorized use only/OU=VeriSign Trust Network
/C=US/O=GTE Corporation/OU=GTE CyberTrust Solutions, Inc./CN=GTE CyberTrust Root/C=HU/L=Budapest/O=NetLock Halozatbiztonsagi Kft./OU=Tanusitvanykiadok/CN=NetLock Expressz (Class C) Tanusitvanykiado
/OU=Copyright (c) 1997 Microsoft Corp./OU=Microsoft Corporation/CN=Microsoft Root Authority
/DC=com/DC=microsoft/CN=Microsoft Root Certificate Authority
/C=FR/ST=77/L=Melun/O=CG77/CN=act2000.demo-cg77.org
---
SSL handshake has read 4098 bytes and written 336 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 1024 bit
SSL-Session:
    Protocol  : TLSv1
    Cipher    : RC4-MD5
    Session-ID: DB17000043304AC576E0586E82B6139839D1D812DA0C3C707CD1CABF390A1965    Session-ID-ctx:
    Master-Key: 149A4A63893D34003E4D5AC2C9223040D68CAA2714AE7709193C64E7C2BE4B49AB7EA0B619DD8146F147FD0EE76DE1C3
    Key-Arg   : None
    Krb5 Principal: None
    Start Time: 1077894853
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
(le programme ne rend pas la main, il faut l'interrompre par Ctrl-c)

Si par contre il y a un problème, le programme rendra la main après avoir affiché la cause de l'erreur, et il faudra essayer de comprendre pourquoi ça ne marche pas...

Une fois que tout ceci fonctionne, on peut enfin accéder à Active Directory au moyen d'une connexion LDAP sécurisée par SSL/TLS, ce qui permet entre autres de changer le mot de passe d'un utilisateur (voir 4.4.1).

5.3  SSL avec Squid

Maintenant que les annuaires fonctionnent correctement avec SSL, on peut passer à la configuration de Squid .

A priori, la seule chose à faire pour que Squid utilise SSL pour communiquer avec les serveurs LDAP est de rajouter ldaps:// en tête de l'adresse du serveur dans les appels de squid_ldap_auth et squid_ldap_group .

Cependant, il y avait un bug dans le code source de ces 2 helpers (le bug #887 de Squid , cf http://www.squid-cache.org/bugs/show_bug.cgi?id=887 ), qui empêchait d'utiliser correctement SSL/TLS, mais ce bug a été corrigé le 05/01/2004.

Il faut donc patcher les sources de la version utilisée de Squid , ou récupérer la dernière version de Squid (la version 2.5STABLE5 est sortie le 01/03/2004), et la recompiler avec support SSL (paramètre --enable-ssl de configure).

Si on veut utiliser cette dernière version de Squid , il faut la compiler avec toutes les options adaptées, par exemple :
$ ./configure --prefix=/usr/local/squid 
            --enable-default-err-language=French
            --enable-err-languages="English French"
            --enable-basic-auth-helpers="LDAP NCSA"
            --enable-external-acl-helpers="ldap_group"
            --enable-ssl
$ make
$ su -c "make install"
Par contre, on peut ne récupérer que les dernières versions de squid_ldap_auth et squid_ldap_group , dans ce cas on ne fait pas de make install, mais après le make on récupère les fichiers helpers/basic_auth/LDAP/squid_ldap_auth et helpers/external_acl/ldap_group/squid_ldap_group, et on les place par exemple à l'endroit où se trouvaient les vieilles versions de ces fichiers (qu'on aura sauvegardés avant au cas où).


Remarque

Lors de la compilation de Squid , en fait lors de la compilation de squid_ldap_auth et squid_ldap_group , j'ai été confronté à une erreur, et il a fallu que je rajoute -L/usr/local/lib à la ligne LDADD=... des Makefile correspondants.




Ensuite, il suffit effectivement de modifier les 2 lignes de squid.conf qui appellent squid_ldap_auth et squid_ldap_group , afin d'indiquer le nouveau chemin de ces 2 programmes si celui-ci a changé, et de rajouter ldaps:// en tête de l'adresse du serveur LDAP.

Il ne reste plus qu'à relancer le serveur Squid , et maintenant l'authentification par groupes s'effectue de manière cryptée par SSL/TLS. (On peut le vérifier avec Ethereal : aucun mot de passe ne circule plus en clair)


Ce document a été traduit de LATEX par HEVEA.