Par défaut dans OpenLDAP le mot de passe utilisateur (attribut usepassword) est stocké sans cryptage.
Si on modifie le mot de passe via un fichier LDIF, on aura donc le mot de passe en clair dans l'annuaire, ce qui n'est pas sécurisé.
On peut également appliquer un algorithme de cryptage en amont (dans l'application cliente) et le transmettre à OpenLDA, qui va le stocker tel quel.
Il est possible de déclarer, via l'attribut olcPasswordHash, un ou plusieurs types de hash acceptables, utilisés dans la génération des mots de passe stockés dans l'attribut userPassword. Le défaut est {SSHA} (Salted SHA1). (cf . http://linux.die.net/man/5/slapd-config).
La modification de l'attribut s'effectue dans la "frontend" database, et héritée par les autres databases, via un fichier LDIF :
dn: olcDatabase={-1}frontend,cn=config
changetype: modify
add: olcPasswordHash
olcPasswordHash: {SHA}
Note: ceci ne veut pas dire que le mot de passe sera stocké crypté dans l'annuaire. Cela indique uniquement à OpenLDAP qu'il peut accepter tel ou tel cryptage en provenance d'un client.
On modifie le mot de passe de l'utilisateur via un fichier LDIF :
dn: uid=USER123,ou=users,dc=example,dc=com
changetype: modify
replace: userpassword
userpassword: UnMotDePa55e
Si on recherche via la commande ldapsearch l'entrée de l'annuaire, elle va renvoyer le mot de passe (codé en base64), que l'on peut décoder via la commandebase64 -d :
dn: uid=USER123,ou=users,dc=example,dc=com
objectClass: inetOrgPerson
uid: USER123
cn: USER123 User
displayName: USER123 User
employeeNumber: USER123
givenName: Test
userPassword:: VW5Nb3REZVBhNTVl
# search result
# numResponses: 2
# numEntries: 1
On décode le mot de passe donné en base64 :
# echo VW5Nb3REZVBhNTVl | base64 -d
UnMotDePa55e
#
Si on modifie l'entrée via LDAPBrowser (mot de passe = Password) et qu'on fait la même recherche ldapsearch, le résultat est quelque peu différent :
dn: uid=USER123,ou=users,dc=example,dc=com
objectClass: inetOrgPerson
uid: USER123
cn: USER123 User
displayName: USER123 User
employeeNumber: USER123
givenName: Test
userPassword:: e1NIQX1pK1BKUTdGZ24vKy94UnF0Wm0wS0JLMzRQSjA9
# search result
# numResponses: 2
# numEntries: 1
Si on essaye de décoder le mot de passe depuis le format base64, on obtient le contenu de l'attribut userPassword
# echo e1NIQX1pK1BKUTdGZ24vKy94UnF0Wm0wS0JLMzRQSjA9 | base64 -d
{SHA}i+PJQ7Fgn/+/xRqtZm0KBK34PJ0=
#
Le mot de passe a été encodé par l'application cliente (LDAPbrowser) et stocké en SHA dans l'annuaire.
Il est cependant possible d'avoir un cryptage systématique, en utilisant l'overplayPasswordPolicy
Cet overlay disponible pour OpenLDAP permet de gérer les politiques de mots de passe pour une database donnée.
On peut donc avoir une politique de mot de passe par défaut différente par database (root Suffix), sachant qu'on peut également avoir une politique de mot de passe liée à un objet de l'annuaire.
L'ajout de cet overlay s'effectue au niveau de la configuration globale. La modification peut s'effectuer dynamiquement via un fichier LDIF :
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy
La configuration de l'overlay se fait au niveau de chaque database. Dans notre exemple, elle porte le numéro 3 (valider par rapport à votre installation dans /etc/openldap/slapd.d/cn=config).
dn: olcOverlay=ppolicy,olcDatabase={3}bdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcPpolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=com
olcPPolicyUseLockout: TRUE
olcPPolicyHashCleartext: TRUE
Les attributs intéressants sont :
C'est ce dernier paramètre qui permet de crypter automatiquement les mots de passe passés en clair, par exemple via un fichier LDIF.
La définition d'une politique de mots de passe s'effectue également par un fichier LDIF. On a une seule politique par défaut mais on peut utiliser une politique sur un objet.
dn: cn=default,ou=policies,dc=example,dc=com
objectClass: top
objectClass: device
objectClass: pwdPolicy
cn: default
pwdAttribute: userPassword
pwdMaxAge: 7776000
pwdMinAge: 86400
pwdExpireWarning: 864000
pwdInHistory: 4
pwdMinLength: 8
pwdMaxFailure: 5
pwdLockout: TRUE
pwdLockoutDuration: 900
pwdGraceAuthNLimit: 5
pwdFailureCountInterval: 0
pwdMustChange: TRUE
pwdAllowUserChange: TRUE
pwdSafeModify: FALSE
pwdCheckQuality: 1
La signification des attributs est :
Dans le cas de comptes de services, il est plus prudent de ne pas avoir d'expiration de compte.
dn: cn=servicesaccounts, ou=policies, dc=example,dc=com
cn: servicesaccounts
objectClass: top
objectClass: device
objectClass: pwdPolicy
pwdAllowUserChange: TRUE
pwdAttribute: userPassword
pwdExpireWarning: 0
pwdFailureCountInterval: 0
pwdGraceAuthNLimit: 5
pwdLockout: FALSE
pwdLockoutDuration: 0
pwdInHistory: 0
pwdMaxAge: 0
pwdMaxFailure: 0
pwdMinAge: 0
pwdMinLength: 15
pwdMustChange: FALSE
pwdSafeModify: FALSE
Les principales différences portent sur les durées (pas d'expiration), sur le blocage (pas de blocage). Par contre la longueur du mot de passe est passée à 15 caractères.
On peut affecter une politique de mots de passe spécifique à un compte via un LDIF :
dn: uid=USER123,ou=users,dc=example,dc=com
changetype: modify
replace: pwdPolicySubEntry
pwdPolicySubEntry: cn=servicesaccounts, ou=policies, dc=example,dc=com