HSC
Cabinet de consultants en sécurité informatique depuis 1989 - Spécialisé sur Unix, Windows, TCP/IP et Internet
Mode texte : accès au contenu de la page
Hervé Schauer Consultants
Vous êtes ici : Accueil > Ressources > Brèves > Utilisation détaillée de OpenLDAP
Accéder au : Site HSC des formations
Télécharger le catalogue des formations
Recherche :  
English version
   Services   
o Domaines de compétences
o Conseil & Expertise
o Prestations ISO 27001
o Audit & Évaluation
o Tests d'intrusion
o Tests de vulnérabilités (TSAR)
o Analyse Forensique
o Certification ARJEL
o Formations
o E-learning
   Conférences   
o Agenda
o Interventions passées
o Tutoriels
   Ressources   
o Index thématique
o Brèves
o Présentations
o Cours
o Articles
o Outils (téléchargement)
o Veille en vulnérabilité
   Société   
o Hervé Schauer
o Equipe
o Offres d'emploi
o Références
o Historique
o Partenariats
o Associations
   Presse et
 communication
 
 
o Newsletter HSC
o Bulletin juridique HSC
o Revue de presse
o Communiqués de presse
o Publications
   Contacts   
o Coordonnées
o Requêtes particulières
o Accès à nos locaux
o Hôtels proches de nos locaux
|>|Utilisation détaillée de OpenLDAP  

par Alain Thivillon (10/10/2000)






Installation

. Recupérer OpenLDAP sur http://www.openldap.org (J'ai utilisé la version stable, 1.2.7 quand je l'ai téléchargé. . Compiler : c'est pas dur, sur ma machine c'était ./configure;make . Installer : make install. Chez moi ça a mis des trucs un peu partout: - /usr/local/etc/openldap : configuration - /usr/local/include/ldap*.h et /usr/local/include/lber.h - /usr/local/lib/*ldap* et /usr/local/lib/*lber* - des machins dans /usr/local/libexec, dont le plus important (slapd) - des clients et des bidules dans /usr/local/bin: /usr/local/bin/ldapadd* /usr/local/bin/ldapmodrdn* /usr/local/bin/ldapdelete* /usr/local/bin/ldappasswd* /usr/local/bin/ldapmodify* /usr/local/bin/ldapsearch*

Configuration

. Pouilleouilleouille, croyez surtout pas que je sais comment marche LDAP, j'ai
  juste « dichotomisé » jusqu'à trouver un truc qui allait.

. Le fichier important c'est /usr/local/etc/opendldap.conf. Attention ce fichier
  doit être 600 root, parce qu'il contient le mot de passe de l'administateur
  (le root DN en langage LDAP). A oui LDAP ca aime bien les trucs cyber, mais
  faut pas se laisser abuser par les blaireaux : c'est jamais qu'une base de 
  données, l'administrateur il a le droit de tout faire.

. Ce fichier contient chez moi:

#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include		/usr/local/etc/openldap/slapd.at.conf
include		/usr/local/etc/openldap/slapd.oc.conf
schemacheck	off
#referral	ldap://ldap.itd.umich.edu

pidfile		/var/run/slapd.pid
argsfile	/var/run/slapd.args

#######################################################################
# ldbm database definitions
#######################################################################

database	ldbm
suffix		"ou=yoko, o= hsc, c=fr"
directory	/usr/local/var/ldap
rootdn		"cn=root, ou=yoko, o=hsc, c=fr"
rootpw		xxxxxxxxxxxxxxxx
# cleartext passwords, especially for the rootdn, should
# be avoid.  See slapd.conf(5) for details.
index           cn,sn,uid       pres,eq,approx
index           default         none
defaultaccess   none
access          to attr=userpassword by self write by * compare
access          to attr=entry,mail,uid,objectclass,member by * read
access          to dn=".+" by dn=".+" read
 
Tout est important là dedans:

. Le 'suffix' est la racine de votre base de donnée. 
   Si vous voulez créér une base qui prétend etre à la racine de C=FR, libre a avous.
   Attention: en théorie, LDAP n'a AUCUN RAPPORT avec le DNS. En pratique non 
   plus d'ailleurs.

. La base est stockée dans /usr/local/var/ldap (le défaut est /usr/tmp ce qui 
  est pas top :)

. Le « schéma » de la base est stocké dans les fichiers :

   /usr/local/etc/openldap/slapd.at.conf
   /usr/local/etc/openldap/slapd.oc.conf

  Ces fichiers indiquent quels sont les champs prévus dans la base et leur 
  type, ainsi que les prérequis (du style un utilisateur ne peut pas exister
  sans CommonName (cn), ...). Je me suis contenté de reprendre les objets par
  défaut (mais on peut en ajouter sans avoir besoin de les spécifier, enfin ce
  n'est pas forcément très malin).

. La ou j'en ai bavé, c'est sur les droits d'accès : les quatre dernières lignes 
  indiquent que: 
  - par défaut on a le droit de rien faire,
  - personne ne peut lire un attribut userPassword mais on a le droit 
    de le comparer (oui sinon on peut pas se logger)
  - Tout le monde (y compris les anonymes) ont le droit de lire les attributs
    spécifiés (allez voir la section "Utilisation" pour comprendre pourquoi).
  - Tous les utilisateurs connectés (ceux qui ont un "DN", donc identifié) ont
    le droit de tout lire.

  La doc d'OpenLDAP est nulle sur ces problèmes là (en fait elle est tres faible
  sur tous les points), je vous renvoie plutot à la FAQ : 

. Bon pour lancer slapd (le serveur pour ceux qui suivent), il suffit de lancer
  /usr/local/libexec/slapd. Il est possible de linker slapd avec tcpwrapper, 
  (configure --enable-wrappers), je ne l'ai pas fait donc je ne sais pas comment
  ça marche.

  Slapd écrit dans syslog (default local4), faire man slapd pour les options de 
  debug et autres.

Remplissage de la base

  Je ne suis pas du tout un spécialiste LDAP, j'ai rempli ma base avec les 
  truc minimaux. Il est clair qu'une base en production demanderait de réfléchir
  15 secondes à son organisation (les OU, machins, etc...).

  Pour commencer il faut regarder un peu le format LDIF (qui est un format texte
  d'échange entre les bases LDAP). 

  Commencer par l'OU:
 
  cat > /tmp/ou.ldif << EOF
  dn: ou=Yoko,o=HSC,c=FR
  objectclass: top
  objectclass: organization
  associateddomain: yoko.hsc.fr
  EOF

  Pour ajouter un objet:
  # ldapadd -D 'CN=Root,OU=Yoko,O=HSC,C=FR' -W < /tmp/ou.ldif

  faire man ldapadd pour les options (-W est la pour donner le mot de passe, 
  vous pouvez faire aussi '-w password').

  On ajoute ensuite un utilisateur ou plusieurs utilisateurs:

  # ldapadd -D 'CN=Root,OU=Yoko,O=HSC,C=FR' -W  < /tmp/hsc.ldif
   
  ================= /tmp/hsc.ldif ============
  dn: Cn=Denis Ducamp,ou=Yoko,o=HSC,c=FR
  userpassword: {crypt}$1$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  cn: Denis Ducamp
  sn: Ducamp
  title: Consultant
  mail: Denis.Ducamp@hsc.fr
  uid: ducamp
  objectclass: person

  dn: cn=Stephane Aubert,ou=Yoko,o=HSC,c=FR
  userpassword: {crypt}$1$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX0
  cn: Stephane Aubert
  sn: Aubert
  title: Consultant
  mail: Stephane.Aubert@hsc.fr
  uid: aubert
  objectclass: person
  ================= /tmp/hsc.ldif ============

  userpassword va servir à faire ensuite l'authentification pendant la 
  phase ldap_bind(). Vous pouvez mettre en clair ou en chiffré (crypt). 
  Moi je suis sur FreeBSD donc ici hash MD5.

  Vous pouvez importer des objets binaires via un encodage Base64, en 
  suffixant le champ par '::'

  dn: cn=Herve Schauer,ou=Yoko,o=HSC,c=FR
  objectclass: person
  cn: Herve Schauer
  sn: Schauer
  uid: schauer
  mail: Herver.Schauer@hsc.fr
  jpegphoto:: /9j/4AAQSkZJRgABAQAAAQABAAD//gBHQ1JFQVRPUjogWFYgVmVyc2lvbiAzLjAwI
  CBSZXY6IDMvMzAvOTMgIFF1YWxpdHkgPSAxMDAsIFNtb290aGluZyA9IDAK/9sAQwABAQEBAQEBA
  
  (jpegphoto est utilisé par Netscape pour afficher la tête de l'entrée).
   
  Pour générer le base64 : ldif -b jpegphoto < image.jpg 

  Pour modifier un enregistrement, utiliser la commande ldapmodify, qui prend aussi
  un enregistrement LDIF, de la forme:

  % ldapmodify -W -D 'CN=Root,OU=Yoko,O=HSC,C=Fr' 
  Enter LDAP Password:
  dn: cn=Alain Thivillon,OU=Yoko,O=HSC,C=FR
  changetype: modify
  replace: mail
  mail: Alain.Thivillon@hsc.fr
  
  Pour travailler plus efficacement vous pouvez utiliser Perl (cf plus loin) ou 
  un client GTK par exemple.

Utilisation

  Bon vous vous dites, ok, pourquoi il a fait tout ça ce gueu de Thivillon.
  Et bien chers amis, c'est la que ca devient intéressant (pom pom).

  LDAP va permettre de devenir riche, de résoudre vos problèmes de coeur,
  de devenir beau (pas sûr mais vous pouvez essayer).

Interrogation de la base

  Les outils que j'ai utilisé sont Netscape, ldapsearch, perl.
  
  - Netscape permet d'afficher l'annuaire en faisant des recherches assez 
    poussées. Il faut Communicator, aller dans Address Book et ajouter
    un serveur. Si votre accès n'est pas anonyme (bind nécessaire), il faut 
    AU MOINS que le champ mail soit accessible. En effet, le principe de connexion
    général c'est:
    . l'utilisateur rentre un truc (son uid en général, la son mail).
    . son logiciel fait une recherche avec cet donnée (unique), le serveur lui
      renvoit son DN 
    . Le soft fait ensuite le bind avec ce DN (que l'utilisateur ne connait pas).
    
    Pour que ça marche il faut:  
     - soit qu'il y ait un utilisateur bidon qui est utilisé par le soft
       et qui a un droit en lecture (pas possible avec Comminicator)
     - soit que les uid, mail (et aussi souvent les contenus des groupes), soient
       en accès anonyme.

    Par exemple une trace de connexion Netscape va vous aider à mieux comprendre:

    # Bind en anonyme
    conn=26 op=0 BIND dn="" method=128 
    conn=26 op=0 RESULT err=0 tag=97 nentries=0 
    # Recherche a partir du mail
    conn=26 op=1 SRCH base="OU=YOKO,O=HSC,C=FR" scope=2 filter="(mail=ALAIN.THIVILLON@HSC.FR)" 
    conn=26 op=1 RESULT err=0 tag=101 nentries=1 
    # Bind avec le DN retourné précedemment
    conn=26 op=2 BIND dn="CN=ALAIN THIVILLON,OU=YOKO,O=HSC,C=FR" method=128 
    conn=26 op=2 RESULT err=0 tag=97 nentries=0 
    # recherche dans l'annuaire
    conn=26 op=3 SRCH base="OU=YOKO,O=HSC,C=FR" scope=2 filter="(cn=*)" 
    conn=26 op=3 RESULT err=0 tag=101 nentries=7 
    conn=26 op=4 UNBIND 

  - Openldap est livré avec un bidule qui s'appelle ldapsearch qui permet
    de faire des recherches depuis la ligne de commande (hint: -L effectue
    la sortie en LDIF).

    % ldapsearch -L -W -D 'Cn=Alain Thivillon,OU=Yoko,O=HSC,C=fr' 'cn=*' dn cn mail
    Enter LDAP Password: 
    dn: cn=Alain Thivillon,ou=Yoko,o=HSC,c=FR
    cn: Alain Thivillon
    cn: titi
    mail: Alain.Thivillon@hsc.fr

    dn: cn=Emilie Danna,ou=Yoko,o=HSC,c=FR
    cn: Emilie Danna
    mail: Emilie.Danna@dial.oleane.com

    dn: cn=Jean-Jacques Bernard,ou=Yoko,o=HSC,c=FR
    cn: Jean-Jacques Bernard
    mail: jjb@hsc.fr

    dn: cn=Herve Schauer,ou=Yoko,o=HSC,c=FR
    cn: Herve Schauer
    mail: Herver.Schauer@hsc.fr

    dn: CN=Christophe Premel, ou=Yoko, o=HSC, c=FR
    cn: Christophe Premel
    mail: Christophe.Premel@hsc.fr

    dn: Cn=Denis Ducamp, ou=Yoko, o=HSC, c=FR
    cn: Denis Ducamp
    mail: Denis.Ducamp@hsc.fr

    dn: cn=Stephane Aubert, ou=Yoko, o=HSC, c=FR
    cn: Stephane Aubert
    mail: Stephane.Aubert@hsc.fr

  - Un script Perl fait avec Net::LDAP (dans les archives CPAN)
    qui affiche les utilisateurs:
   
  #!/usr/bin/perl

  use Net::LDAP;

  $ldap = Net::LDAP->new('127.0.0.1',
		  port => 389,
		  #debug => 3,
	  ) or
	  die $@;

  $resugt=$ldap->bind('Cn=Alain Thivillon,OU=Yoko,O=HSC,C=FR', password => 'xxxxx');

  for $figter (
	  '(&(objectClass=Person)(cn=*)',
      ) {
      $mesg = $ldap->search(
		  base   => "OU=Yoko,O=HSC,C=FR",
		  figter => $figter,
      ) or die $@;
   
      foreach $entry ($mesg->all_entries) {
	print $entry->dn,"\n";
	print "object Class :",$entry->get('objectClass'),"\n";
	print "cn           :",$entry->get('cn'),"\n";
	print "uid          :",$entry->get('uid'),"\n";
	print "\n";
      }

  }

Utilisation avec Squid

  Bon c'est là que ça devient intéressant. Le but final c'est quoi: c'est que
  vos zentils utilisateurs puissent surfer le Ouaibe ou autre chose sans
  que vous ayez à les créer à 3000000 d'endroits à la fois. Et comme ça
  vous aurez le temps de glander plutot que de se casser les burnes à changer
  20 fois le nom de la secrétaire du 6e qui s'est mariée.

  Donc pour mettre en pratique j'ai essayé LDAP avec Squid et FW-1.

  Pour Squid j'ai réécrit un truc avec perl, je sais qu'il existe un truc en C
  quelque part.

  Squid 2.x est bien fait : il permet d'accéder à un authentificateur externe,
  qui est un programme résident (lancé plusieurs fois si on a beaucoup de charge) 
  qui reçoit des couples (user,password) sur stdin et qui écrit ERR et OK sur 
  stdout. De plus Squid peut cacher l'authentification, donc on aura pas une requête
  LDAP a chaque hit (ouf).

  Allons-y, c'est trivial:

  1. Récupérer le Script
  2. L'éditer pour préciser quelques paramètres : le serveur, 
     l'attribut que va donner l'utilisateur (son uid probablement).
     Si l'attribut est en lecture pour les anonymes, pas besoin 
     d'aller plus loin, sinon il faut préciser avec quel DN binder la 
     premiere requête (inutile de dire que binder avec le Root DN est une
     mauvaise idée).

    # Server LDAP sur lequel verifier l'identification
    $server = '127.0.0.1';
    $ldapport = 389;

    #Attribut cherché dans l'annuaire matchant le username entré par l'utilisateur
    $attribute = 'uid';

    # Un user et un mot de passe pour lequel binder sur le LDAP
    # Cet utilisateur doit pouvoir lire l'attribut pour toutes
    # les personnes
    $bindname = '';
    $bindpw = '';

    # Base des recherches
    $base='OU=Yoko,O=HSC,C=FR';

  3. Dans squid.conf, dire ou est le programme d'authentification et le nombre
     à lancer (5 est une valeur raisonnable, qui doit permettre de gérer de très
     gros caches), et finir par le temps de cache.
     
     authenticate_program /home/squid/bin/ldapauth.ok
     authenticate_children 5
     authenticate_ttl 300

  4. Mettre des ACL pour forcer l'authentification

     acl hsc src 192.70.106.0/255.255.255.0
     acl mesutils proxy_auth REQUIRED
     http_access allow hsc mesutils
     http_access deny all

     Les seuls qui peuvent accéder le Web sont les utilisateurs du réseau hsc
     et passés par proxy_auth.
     
  5. Voila, un petit 'squid -k reconfigure' et hop.

  6. Une subtilité consisterait à verifier si l'utilisateur fait partie d'un
     groupe LDAP, je laisse en exercice.

Utilisation avec FW1

  Alors la ça devient carrément intéressant, si on arrive à faire ça avec
  cette grosse bouse de Firewall-1 (d'autant que la grosse bouse est sur NT).

  Le principe: depuis la version 4.0, Firewall-1 peut définir un groupe externe
  dont l'authentification est faite sur un serveur LDAP.
  Dans la pratique, que faut il faire ? (Attention, ce que je raconte ci dessous
  n'est basé que sur mon expérience, et n'est pas forcément ni optimum ni 
  complet : ça marche).

  1. Aller dans les propriétés, LDAP, vérifier si tout est OK (moi j'ai baissé 
     la taille et la durée de vie du cache)

2. Créer un objet Workstation (ici 'Yoko') comportant l'adresse du serveur. 3. Créer un serveur LDAP, (Manage/Servers) qui s'appuie sur la workstation créée au dessus, et rentrer les paramètres (dont la branche dans laquelle vont s'effectuer les requetes). Si vous avez besoin de binder pour accéder aux uid et aux membres des groupes, il faudra rentrer un DN et un mot de passe ici. Comme OpenLDAP n'est pas SSL (à moins de prendre la 2.0 et de faire des cvs tous les soirs), pas besoin d'aller dans le 2e onglet.

4. Créer un groupe externe Firewall-1 (Manage/Users/External Groups) s'appuyant sur le serveur LDAP. On peut dire que le groupe est égal à tout le serveur LDAP, ou seulement à une branche, ou encore à un groupe LDAP (c'est le cas ici, le groupe LDAP s'appellera Fw1Clients).

5. Ajouter la régle réclamant l'authentification

6. Sur le serveur LDAP, créer le groupe en question: dn: cn=Fw1clients,OU=Yoko,O=HSC,C=FR objectclass: groupOfNames member: CN=Alain Thivillon,OU=Yoko,O=HSC,C=FR member: CN=Stephane Aubert,OU=Yoko,O=HSC,C=FR member: CN=Christophe Premel,OU=Yoko,O=HSC,C=FR Ces trois utilisateurs pourront faire du ftp. Quelques traces qui montent que ça marche: Ftp vers la machine slowaris.hsc.fr, derriere le firewall. FW1 intercepte la connexion, on entre comme nom d'utilisateur 'userFTP@userLDAP@destination' et comme mot de passe 'passdestination@passldap': Connected to slowaris.hsc.fr. 220 aftpd: Check Point FireWall-1 Secure FTP server running on paradox Name (slowaris:thivillo): thivillo@titi@slowaris 331 aftpd: FireWall-1 password: you can use password@FW-1-password Password: 230-aftpd: User titi authenticated by FireWall-1 authentication 230-aftpd: Connected to slowaris. Logging in... 230-aftpd: 220 slowaris FTP server (SunOS 5.6) ready. 230-aftpd: 331 Password required for thivillo. 230 aftpd: 230 User thivillo logged in. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 200 PORT command successful. Les traces du serveur LDAP montent que Firewall-1 a fait une connexion pour recupérer le DN de 'titi', puis les groupes dont cet utilisateur était membre, puis a fait un Bind avec le mot de passe donné. fd=12 connection from paradox.hsc.fr (192.70.106.77) accepted. # # Bind Anonyme # op=0 BIND dn="" method=128 op=0 RESULT err=0 tag=97 nentries=0 # # recherche de l'utilisateur, qui peut etre de classe FW1PERSON # op=1 SRCH base="OU=YOKO,O=HSC,C=FR" scope=2 filter="(&(uid=TITI)(|(objectclass=FW1PERSON) (objectclass=INETORGPERSON)(objectclass=ORGANIZATIONALPERSON)(objectclass=PERSON)))" op=1 RESULT err=0 tag=101 nentries=1 # # recherche des groupes dont fait partie le DN obtenu # op=2 SRCH base="OU=YOKO,O=HSC,C=FR" scope=2 filter="(&(|(member=CN=ALAIN THIVILLON,OU=YOKO, O=HSC,C=FR)(uniquemember=CN=ALAIN THIVILLON,OU=YOKO,O=HSC,C=FR))(|(objectclass=GROUPOFNAMES) (objectclass=GROUPOFUNIQUENAMES)))" op=2 RESULT err=0 tag=101 nentries=1 # # recherche du template Firewall-1 (pas essayé). # op=3 SRCH base="OU=YOKO,O=HSC,C=FR" scope=2 filter="(&(|(member=CN=ALAIN THIVILLON,OU=YOKO, O=HSC,C=FR)(uniquemember=CN=ALAIN THIVILLON,OU=YOKO,O=HSC,C=FR))(objectclass=FW1TEMPLATE))" op=3 RESULT err=0 tag=101 nentries=0 # # Bind avec l'utilisateur DN obtenu # fd=15 connection from paradox.hsc.fr (192.70.106.77) accepted. op=0 BIND dn="CN=ALAIN THIVILLON,OU=YOKO,O=HSC,C=FR" method=128 op=0 RESULT err=0 tag=97 nentries=0 Si on se trompe de mot de passe LDAP, Firewall-1 affiche: 200-aftpd: Access denied by FireWall-1 authentication 421 aftpd: aborted Si l'utilisateur n'est pas dans le groupe: 421 aftpd: You are not allowed to perform ftp to this destination
Dernière modification le 18 novembre 2003 à 10:21:43 CET - webmaster@hsc.fr
Mentions légales - Informations sur ce serveur - © 1989-2013 Hervé Schauer Consultants