Cet article est une “loose translation” de l'excellentissime document de Tonton Tonio, repéré par sa Saignerie iMil.

Comme le titre l'indique, il s'agit de faire de l'authentification user/password sur une machine OpenBSD alors que les dits users/passwords sont dans un serveur LDAP. L'article se base sur OpenBSD 3.8 qui utilise login_ldap, et un annuaire OpenLDAP.

Introduction

LDAP (Lightweight Directory Access Protocol) est un protocole hachement sympa que si tu connais pas, tu files voir Wikipedia : http://fr.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol

Un usage typique d'un annuaire LDAP est d'y maintenir les comptes utilisateurs d'une entreprise, histoire de servir à l'identification (qui t'es toi ?) et l'authentification (prouve le moi, du con !) de ces derniers pour différents applicatifs (genre les serveurs de mails, les web-eries, mais pas seulement : la majorité des gros bloatwares commerciaux bien chers savent faire du LDAP…) et systèmes (login d'OpenBSD par exemple, objet de ce papier. Mais bon, tout bon Linux aimera la chose aussi..).

Du coup, avec OpenLDAP, une implémentation open source d'un annuaire LDAPv3, qui dispose d'un joli port kikoulos officiel pour OpenBSD 3.8, on peut commencer à faire dresser son kiki. Pour y parvenir, il est nécessaire d'utiliser un autre port kikoulos tout aussi officiel nommé login_ldap qui permet… ben justement d'identifier et authentifier les gens à la porte du notre puffyware adoré.

Si on veut faire simple, on va y mettre donc un gros serveur OpenLDAP sur notre OpenBSD, et le système devra y consulter les données relatives aux utilisateurs… Pourquoi faire ça ? Bah… chacun ses problèmes… Mais faut savoir que ça peux devenir sympa car le serveur LDAP n'est peut être pas forcé d'être sur notre puffybox, voir il peux être mis à jour par un autre serveur LDAP distant… bref, des LDAP-eries habituelles (pour les aficionados du LDAP biensur).

Bon, commençons par tout y coller sur notre belle puffybox…

Installation et Configuration

Dans un premier temps, faut installer quelques petits paquetages bien sympa (ou install à partir des ports pour les gars du Bien) :

# pkg_add $PKG_PATH/openldap-client-2.2.27p0.tgz
# pkg_add $PKG_PATH/openldap-server-2.2.27p0.tgz
# pkg_add $PKG_PATH/login_ldap-3.3.tgz

Par ailleurs, pour notre serveur OpenLDAP tout beau, il nous faut récupérer un schéma LDAP : le authldap.schema, qui est inclus dans le port courier-authlib-ldap (disponible pour OpenBSD 4.1) ou directement disponible sur Inet : http://cvs.sourceforge.net/viewcvs.py/*checkout*/courier/libs/authlib/authldap.schema .

Bon, c'est fait ? Ben reste à configurer le gourbi maintenant.

OpenLDAP

Pour configurer le serveur OpenLDAP, il faut commencer par lui créer un utilisateur (_openldap) et un groupe (_openldap), les deux locaux, bien en dur dans nos chers /etc/{passwd,group}.

# groupadd -g 544 _openldap
# useradd -s /sbin/nologin -c "Servidor LDAP" -g _openldap -m \
  -d /var/openldap-data/ -u 544 _openldap

Puis copier les exemples de configuration du serveur à leur bonne place :

# mkdir /etc/openldap
# cp /usr/local/share/examples/openldap/slapd.conf /etc/openldap/
# cp -rf /usr/local/share/examples/openldap/schema /etc/openldap/

Ne pas oublier de copier également le fâmeux authldap.schema à sa bonne place. Par exemple, si vous l'avez récupéré de l'installation de courier-authlib-ldap :

# cp /usr/local/share/examples/courier-authlib/authldap.schema /etc/openldap/schema

Maintenant que tout est en place, jouez du vi pour y indiquez vos sales besoins dans le /etc/openldap/slapd.conf (fichier de configuration principal d'OpenLDAP) pour y placer les lignes suivantes :

include               /etc/openldap/schema/core.schema
include               /etc/openldap/schema/cosine.schema
include               /etc/openldap/schema/nis.schema
include               /etc/openldap/schema/inetorgperson.schema
include               /etc/openldap/schema/openldap.schema
include               /etc/openldap/schema/authldap.schema
 
allow bind_v2

Et puis, modifiez les lignes dtabase, suffix, rootdn et rootpw pour s'adapter à votre petite entreprise :

database      ldbm
suffix        "dc=correo,dc=pasosdeJesus,dc=org"
rootdn        "cn=Manager,dc=correo,dc=pasosdeJesus,dc=org"
rootpw        secret

Remarque que : *on authorise le LDAPv2 pour login_ldap *on utilise la base Berkeley DB pour y stocker les données de l'annuaire *on utilise un mot de passe hachement sécure pour accéder avec tous les privilèges à toutes les données de cette base. Mais faut également l'indiquer à la base au moyen de la commande :

#  slappasswd -v -u -h {CRYPT} -s secret

qui dans les cas du mot de passe 'secret' est '{CRYPT}uPUCy906TIu/k'

La configuration par défaut de slapd.conf utilise le répertoire /var/openldap-data pour y stocker la base de donnée. C'est bien beau, mais faut l'initialiser à la mano :

# mkdir /var/openldap-data
# chown _openldap:_openldap /var/openldap-data
# chmod 700 /var/openldap-data

Chaque fois que vous modifiez le fichier de configuration du serveur, vous pouvez en vérifier sa syntaxe avec :

# slaptest

Et pour lancer le serveur LDAP en mode debug pour y voir les possibles erreurs

# /usr/local/libexec/slapd -d 1

Du coup, une fois que vous êtes sûr de votre conf, pour démarrer le serveur OpenLDAP de façon automatique au boot, rajoutez les lignes suivantes dans votre /etc/rc.local :

#LDAP
if [ -x /usr/local/libexec/slapd ]; then
        echo -n " slapd"; /usr/local/libexec/slapd
fi

Si vous vouliez lui faire la peau, il vous suffira d'un :

# pkill slapd

Et si vous voulez vérifier que le serveur est prêt à fonctionner correctement avec votre conf kikoulos :

ldapsearch -x -b 'dc=correo,dc=pasosdeJesus,dc=org' '(objectclass=*)'

Bon, c'est beau, c'est neuf… il est temps de passer à la suite.

login_ldap

Il faut configurer /etc/login.conf pour tirer partie de l'utilisation de login_ldap. Bon, ne pas jouer pas du copier/coller car le fichier /etc/login.conf est plutôt du genre casse-couille. Vazy avec les doigts et ajoute les lignes suivantes :

ldap:\
        :auth=-ldap:\
        :x-ldap-server=localhost:\
        :x-ldap-port=389:\
        :x-ldap-noreferrals:\
        :x-ldap-uscope=subtree:\
        :x-ldap-basedn=ou=gente,dc=correo,dc=pasosdeJesus,dc=org:\
        :x-ldap-binddn=cn=Manager,dc=correo,dc=pasosdeJesus,dc=org:\
        :x-ldap-bindpw=secret:\
        :x-ldap-filter=(&(objectclass=posixAccount)(uid=%u)):\

Si login.conf est utilisé avec cap_mkdb, il semble que cette classe doit être construite par ordre alphabétique

FIXME : quoi cap_mkdb ? relire l'original et comprendre…

Ajout des données et autres utilisateurs

Bon, ben maintenant il est temps d'injecter dans l'annuaire LDAP les quelques données initiales pour permettre d'y coller des users par la suite. Le plus simple est d'utiliser un fichier texte au format LDIF, d'y coller les infos qu'on veut injecter dedans, et de balancer la purée (le fichier ldif) grace à ce bon ldapadd.

Voici un bon fichier ldif, que l'on nommera org.ldif, d'exemple pour les données initiales de notre petite entreprise :

dn:     dc=correo,dc=pasosdeJesus,dc=org
objectClass:    dcObject
objectClass:    organization
o:      Pasos de Jesús
dc:     correo
 
dn: cn=Manager,dc=correo,dc=pasosdeJesus,dc=org
objectClass: organizationalRole
cn: Manager
 
dn:ou=gente, dc=correo,dc=pasosdeJesus,dc=org
objectClass:    top
objectClass:    organizationalUnit
ou:     gente
 
dn:ou=grupos,dc=correo,dc=pasosdeJesus,dc=org
objectClass:    top
objectClass:    organizationalUnit
ou:     grupos

dn:ou=sendmail,dc=correo,dc=pasosdeJesus,dc=org
ou: sendmail
objectClass: top
objectClass: organizationalUnit
userPassword: sendmail
 

Notez bien de ne pas laisser des espaces (blancs) en fin de chaque ligne… Encore une fois, un ldif, c'est un ldif… Puis, injectez le brave org.ldif dans l'annuaire LDAP:

ldapadd -x -D "cn=Manager,dc=correo,dc=pasosdeJesus,dc=org" -W -h correo.pasosdeJesus.org -f org.ldif

Notez que notre brave org.ldif utilise des “champs” des schémas LDAP /etc/openldap/{cosine.schema,nis.schema,authldap.schema}.

En plus de pouvoir contrôler les messages générées par slapd lors de son exécution en mode debug, on peut consulter les données intégrées à l'annuaire avec :

# ldapsearch -x -b 'dc=correo,dc=pasosdeJesus,dc=org' '(objectclass=*)'

Avec l'actuel schéma d'autentification d'OpenBSD, chaque utilisateur accédant au système doit avoir un enregistrement dans le fichier /etc/passwd, c'est la raison pour laquelle avant d'ajouter un utilisateur dans la base LDAP, on doit d'abord exécuter une commande comme :

# useradd -m -d /home/pablo -s /bin/sh -L ldap pablo

qui ajoutera pablo au groupe usuario avec la classe de login ldap et au début sans mot de passe (le mot de passe et d'autres données seront directement ajoutées à l'enregistrement LDAP). Récupérez le uid et gid de l'utilisateur; avec 'vipw' ou 'id pablo'.

Une fois obtenus l'uid et le gid de l'utilisateur on peut créer l'enregistrement ldif :

dn:uid=pablo,ou=gente,dc=correo,dc=pasosdeJesus,dc=org
uid: pablo
cn: Pablo
sn: Ramirez
userPassword: MiClave
loginShell: /bin/ksh
uidNumber: 1003
gidNumber: 10
homeDirectory: /home/pablo/
shadowMin: -1
shadowMax: 999999
shadowWarning: 7
shadowInactive: -1
shadowExpire: -1
shadowFlag: 0
objectClass: top
objectClass: person
objectClass: posixAccount
objectClass: shadowAccount
objectClass: CourierMailAccount
mail: pablo\@correo.pasosdeJesus.org
mailbox: maildir/
quota: 0

Pour permettre l'authentification avec Courier-POP, il faut vérifier que la ligne 'mail:pablo\@correo.pasosdeJesus.org' ait le nom complet du serveur de mail de l'utilisateur (et pas seulement 'pablo\@pasosdeJesus').

De même que le mot de passe du LDAP peut être la valeur retournée par 'slpasswd' au lieu du mot de passe en clair.

Si vous utilisez des accents ou autres caractères spéciaux, l'enregistrement ldiff doit être en Unicode (UTF-8 à été testé avec succès). ceci peut être réalisé avec un éditeur supportant UTF-8 ou en changeant le codage de l'archive. P. ex on peut changer le codage d'un texte (p.ldif) de ASCII à UTF-8 avec :

#recode txt..UTF-8 p.ldif

Après avoir ajouté l'utilisateur à l'annuaire (avec 'ldpadd' comme expliqué précédemment) on peut tenter une recherches. En premier une recherche générale :

ldapsearch -P 2 -H ldap://localhost:389 -w secret \
-D "cn=Manager,dc=correo,dc=pasosdeJesus,dc=org" -x \
-b 'dc=correo,dc=pasosdeJesus,dc=org'

après une recherche d'un utilisateur en particulier (le dernier ajout)

ldapsearch -P 2 -H ldap://localhost:389 -w secret \
-D "cn=Manager,dc=correo,dc=pasosdeJesus,dc=org" \
-x -b "ou=gente,dc=correo,dc=pasosdejesus,dc=org" \
"(&(objectClass=posixGroup)(memberUid=pablo))"

Si les recherches ont bien marché, on doit pouvoir aussi faire :

/usr/libexec/auth/login_-ldap -d -s login pablo ldap; echo $?

ainsi que

$ login
login: pablo
...

Détruire des données

Pour supprimer un utilisateur on peut utiliser

ldapdelete -v -P 2 -H ldap://localhost:389 -w secret \
-D "cn=Manager,dc=correo,dc=pasosdeJesus,dc=org" \
-x  'uid=pablo,ou=gente,dc=correo,dc=pasosdeJesus,dc=org'

Si vous devez effacer l'ensemble de l'annuaire : (je me demmande si la traduction était nécessaires là !)

# pkill slapd
# rm /var/openldap-data/*

Optimisations

Performances

Pour améliorer la vitesse des recherches, il faut créer des indexes sur les champs sur lesquels porte la recherche et configurer les cache. Chacun de ces indices se configure dans /etc/openldap/slapd.conf comme dans l'exemple ci dessous :

index   objectClass     eq
index   mail            eq
index   uid             eq
cachesize 1000000
dbcachesize 10000000

les paramètres de cache s'appliquent aux champs objectClass,mail et uid. Les indices crées son adaptés pour la comparaison entre une chaîne recherchée et le contenu d'un registre.

Après cette configuration, on doit régénérer les indices avec :

# pkill slapd
# slapindex

puis relancer slapd

Sécurité

Il est recommandé d'utiliser SSL pour l'encryptage des connections qui accèdent à slapd. Pour cela il est indispensable de disposer d'un certificat serveur signé par une authorité de certification (CA), vous disposez de trois moyens d'obtenir ce type de certificats :

  • S'adresser à une autorité de certification officielle/commerciale
  • S'adresser à une autorité de certification non officielle où non commerciale

* Créer son certificat en l'auto-signant.

Dans tous les cas vous devrez créer un certificat pour votre serveur et une requête pour qu'elle soit signée par une autorité de certification, confère http://structio.sourceforge.net/guias/servidor_OpenBSD/apache.html#ss

En plus de votre certificat signé (p.ex /etc/ssl/server.crt), la clé de ce dernier (p.ex /etc/ssl/private/server.key), il faut la clé publique de l'autorité de certification (p.ex /etc/ssl/cacert.pem)

Ajoutez alors dans /etc/openldap/slapd.conf

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /etc/ssl/cacert.pem
TLSCertificateFile /etc/ssl/server.crt
TLSCertificateKeyFile /etc/ssl/private/server.key
TLSVerifyClient allow

Modifiez votre script de démarrage /etc/rc.local pour que slapd soit démarré en acceptant les connections depuis deux ports : 389 (ldap) pour les connections en clair et 636 (ldaps) pour les connections sécurisées.

#LDAP
if [ -x /usr/local/libexec/slapd ]; then
      echo -n " slapd"; /usr/local/libexec/slapd -h "ldap:/// ldaps:///"
fi

Arrêtez et redémarrez slapd avec la nouvelle option et essayez avec les deux modes de connexion :

$ telnet localhost 389

et

# openssl s_client -connect localhost:636 -showcerts -state \
-CAfile /etc/ssl/cacert.pem

ce dernier, en plus d'initialiser une connexion avec le serveur, doit retourner :

  Verify return code: 0 (ok)

Notez que la clé publique de l'autorité de certification est indispensable pour réussir les connexions au port 636.

Il est recommandé d'utiliser pf pour bloquer les ports sur lesquels vous n'offrez aucun service et accessoirement pour ouvrir le port 636.

Automatisations

  • Configuration générale: DN.sh
  • Ajoutes des données LDIF (nécessite DN.sh): agldif.sh
  • Rechercher une information (nécessite DN.sh): busca.sh
  • Ajouter un utilisateur (nécessite DN.sh y agldif.sh. Nécessite aussi le paquet courier-utils): agusuario.sh
  • Supprimer un utilisateur (nécessite DN.sh): elimusuario.sh
  • Changer le mot de passe d'un utilisateur (nécessite DN.sh): camclave.sh

FIXME : il faut définir, si on pointe sur les fichiers de conf de l'article ou si on les recopier sur le wiki

Conclusions

Bien que le schéma d'authentification OpenBSD nécessite la création de comptes systèmes pour chaque utilisateur LDAP, cette configuration semble propice pour :

  • Administrer de manière uniforme, un grand nombre d'information relatives à un utilisateur, impossibles à gérer dans le fichier /etc/passwd .
  • Faciliter l'accès à cette information par les utilisateurs
  • Rendre publiques certaines de ces informations en utilisant OpenLDAP LDAP Root Service (cf http://www.openldap.org/faq/data/cache/393.html)
  • Permettre l'authentification des utilisateurs tant avec le mécanisme standard d'OpenBSD qu'au travers d'un serveur LDAP (p.ex Courier-POP3D peut authentifier les utilisateurs directement avec le serveur LDAP)

Bibliographie

Inconvénients avec /etc/login.conf

La nécessités d'autoriser LDAPv2 à été vue dans un courrier, disponible jusqu'à il n'y a si longtemps sur le cache de google.

Sécurité et autorités de certification :

openbsd/login_ldap.txt · Last modified: 2010/01/12 13:29 (external edit)