I've set password policies on my OpenLDAP 2.4. Unfortunately things do not work as expected and although extensively searched on forums and Google, I cannot get the proper results. What am I missing in what I did or should have done?
What goes wrong:
- Password policies seem not to be validated or I do get a failure message
The failures depend on pwdinHistory setting to zero (no failure) to > 0 failure like given below
5798c94a <= acl_access_allowed: granted to database root
5798c94a bdb_modify_internal: replace userPassword
5798c94a bdb_modify_internal: replace pwdChangedTime
5798c94a bdb_modify_internal: add pwdHistory
5798c94a bdb_modify_internal: replace pwdChangedTime
5798c94a bdb_modify_internal: add pwdHistory
5798c94a bdb_modify_internal: 20 modify/add: pwdHistory: value #0 already exists
5798c94a hdb_modify: modify failed (20)
5798c94a send_ldap_result: conn=1000 op=18 p=3
5798c94a send_ldap_result: err=20 matched="" text="modify/add: pwdHistory: value #0 already exists"
5798c94a send_ldap_response: msgid=62 tag=103 err=20
ber_flush2: 61 bytes to sd 15
0000: 30 3b 02 01 3e 67 36 0a 01 14 04 00 04 2f 6d 6f 0;..>g6....../mo
0010: 64 69 66 79 2f 61 64 64 3a 20 70 77 64 48 69 73 dify/add: pwdHis
0020: 74 6f 72 79 3a 20 76 61 6c 75 65 20 23 30 20 61 tory: value #0 a
0030: 6c 72 65 61 64 79 20 65 78 69 73 74 73 lready exists
ldap_write: want=61, written=61
0000: 30 3b 02 01 3e 67 36 0a 01 14 04 00 04 2f 6d 6f 0;..>g6....../mo
0010: 64 69 66 79 2f 61 64 64 3a 20 70 77 64 48 69 73 dify/add: pwdHis
0020: 74 6f 72 79 3a 20 76 61 6c 75 65 20 23 30 20 61 tory: value #0 a
0030: 6c 72 65 61 64 79 20 65 78 69 73 74 73 lready exists
5798c94a conn=1000 op=18 RESULT tag=103 err=20 text=modify/add: pwdHistory: value #0 already exists
5798c94a slap_graduate_commit_csn: removing 0x7f8a0c107960 20160727144634.392449Z#000000#000#000000
This makes, as far as I tested, no difference with just using a default policy or when using a default and specific policy with pwdPolicySubentry attribute in the user.
I've used ACL's on my LDAP schema.
My purpose:
Use a default policy which basically says to use no policy
Add a specific policy for users in a subtree.
Below are the steps and LDAP LDIF files used to build the OpenLDAP.
Included here are the LDIF files for:
config, base and sub part of tree, replication ou and user, application users (service accounts), ldap managers ou, ACL's, OU's needed for application specific content, policy.
Excluded here (but done) are the LDIF files for: enable logging, replication, TLS/SSL.
The LDIF files first line contains the LDIF filename and the command used to apply them
# ldapadd -Y EXTERNAL -H ldapi:/// -f 01_addrootpw.ldif
dn: olcDatabase={0}config,cn=config
changetype: modify
add: olcRootPW
olcRootPW: {SSHA}hashhashhashhashhashhash
# ldapadd -Y EXTERNAL -H ldapi:/// -f 02_root-base.ldif
# change olcRootPW to your Root password
# change domain parts to your domain
dn: olcDatabase={1}monitor,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to * by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.base="cn=Manager,ou=ldapbeheerders,dc=example,dc=nl" read by * none
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcSuffix
olcSuffix: dc=example,dc=nl
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootDN
olcRootDN: cn=Manager,ou=ldapbeheerders,dc=example,dc=nl
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: {SSHA} hashhashhashhashhashhash
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: {0}to attrs=userPassword,shadowLastChange by dn="cn=Manager,ou=ldapbeheerders,dc=example,dc=nl" write by anonymous auth by self write by * none
olcAccess: {1}to dn.base="" by * read
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 03_ldap-manager.ldif
dn: dc=example,dc=nl
objectClass: top
objectClass: dcObject
objectclass: organization
o: example nl
dc: example
dn: ou=ldapbeheerders,dc=example,dc=nl
objectclass: organizationalUnit
ou: ldapbeheerders
dn: cn=Manager,ou=ldapbeheerders,dc=example,dc=nl
objectclass: organizationalRole
cn: Manager
description: Directory Manager
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 04_replication_user.ldif
dn: ou=replicatie,dc=example,dc=nl
objectclass: organizationalUnit
ou: replicatie
description: replicatie groep
dn: cn=replicator,ou=replicatie,dc=example,dc=nl
cn: replicator
sn: user
objectClass: person
userPassword: passwordincleartext
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 05_applications.ldif
# Create ou generic application scheme
dn: ou=applicaties,dc=example,dc=nl
objectclass: organizationalUnit
ou: applicaties
# Aanmaak ou APP1 applicatieschema
dn: ou=APP1,dc=example,dc=nl
objectclass: organizationalUnit
ou: APP1
# Aanmaak ou APP2 applicatieschemas
dn: ou=APP2,dc=example,dc=nl
objectclass: organizationalUnit
ou: APP2
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 06_ServiceAccounts.ldif
dn: ou=ServiceAccounts,dc=example,dc=nl
objectclass: organizationalUnit
ou: ServiceAccounts
description: Service Accounts Applicaties
#Service account APP1
dn: cn=SAAPP1,ou=ServiceAccounts,dc=example,dc=nl
cn: SAAPP1
sn: user
objectClass: person
userPassword: {SSHA}hashedpassword
description: Service Account APP1
#Service account APP2
dn: cn=SAAPP2,ou=ServiceAccounts,dc=example,dc=nl
cn: SAAPP2
sn: user
objectClass: person
userPassword: {SSHA} hashedpassword
description: Service Account APP2
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 07_ACL.ldif
dn: olcDatabase={2}hdb,cn=config
changetype: modify
replace: olcAccess
olcAccess: to attrs=userPassword
by anonymous auth
by self write
by * break
olcAccess: to dn="ou=replicatie,dc=example,dc=nl"
by self write
by * none
olcAccess: to *
by dn.base="cn=replicator,ou=replicatie,dc=example,dc=nl" read
by * break
olcAccess: to dn.subtree="cn=default,ou=policies,dc=example,dc=nl"
by dn.children="ou=ldapbeheerders,dc=example,dc=nl" write
by * none
olcAccess: to dn="ou=ldapbeheerders,dc=example,dc=nl"
by dn.children="ou=ldapbeheerders,dc=example,dc=nl" write
by * none
olcAccess: to dn="ou=ServiceAccounts,dc=example,dc=nl"
by self search
by * none
olcAccess: to dn.subtree="ou=applicaties,dc=example,dc=nl"
by dn.children="ou=ServiceAccounts,dc=example,dc=nl" write
by * none
olcAccess: to dn.subtree="ou=APP1,dc=example,dc=nl"
by dn.base="cn=SAAPP1,ou=ServiceAccounts,dc=example,dc=nl" write
by * none
olcAccess: to dn.subtree="ou=APP2,dc=example,dc=nl"
by dn.base="cn=SAAPP2,ou=ServiceAccounts,dc=example,dc=nl" write
by * none
olcAccess: to dn.children="dc=example,dc=nl"
by * read
olcAccess: to dn.children="dc=nl"
by * read
# ldapadd -x -D cn=Manager,ou=ldapbeheerders,dc=example,dc=nl -W -f 08_Add-testusers.ldif
dn: uid=APP1_1,ou=APP1gebruikers,ou=APP1,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP1_1
cn: APP1_1 gebruiker
sn: gebruiker
pwdPolicySubentry: cn=default,ou=policies,ou=APP1,dc=example,dc=nl
dn: uid=APP1_2,ou=APP1gebruikers,ou=APP1,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP1_2
cn: APP1_2 gebruiker
sn: gebruiker
pwdPolicySubentry: cn=default,ou=policies,ou=APP1,dc=example,dc=nl
dn: cn=APP2_1,ou=APP2gebruikers,ou=APP2,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP2_1
cn: APP2_1 gebruiker
sn: gebruiker
dn: cn=APP2_2,ou=APP2gebruikers,ou=APP2,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP2_2
cn: APP2_2 gebruiker
sn: gebruiker
dn: cn=APP2_3,ou=gebruikers,ou=applicaties,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP2_3
cn: APP2_3 gebruikercat
sn: gebruiker
dn: cn=APP2_4,ou=gebruikers,ou=applicaties,dc=example,dc=nl
objectClass: inetOrgPerson
objectClass: organizationalPerson
ObjectClass: person
objectClass: top
uid: APP2_4
cn: APP2_4 gebruiker
sn: gebruiker
Below is the part where the password policies are configured.
# ldapadd -Y EXTERNAL -H ldapi:/// -f P01_ppolicymodule.ldif
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModuleLoad: ppolicy.la
olcModulePath: /usr/lib64/openldap
# ldapadd -Y EXTERNAL -H ldapi:/// -f P02_ppolicyoverlay.ldif
dn: olcOverlay=ppolicy,olcDatabase={2}hdb,cn=config
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=nl
olcPPolicyUseLockout: TRUE
olcPPolicyHashCleartext: TRUE
# ldapadd -x -D 'cn=Manager,ou=ldapbeheerders,dc=example,dc=nl' -W -f P03_default_ppolicy.ldif
dn: ou=policies,dc=example,dc=nl
objectClass: top
objectClass: organizationalUnit
ou: policies
dn: cn=default,ou=policies,dc=example,dc=nl
objectClass: top
objectClass: device
objectClass: pwdPolicyChecker
objectClass: pwdPolicy
cn: default
pwdAttribute: userPassword
pwdInHistory: 8
pwdMinLength: 8
pwdMaxFailure: 5
pwdFailureCountInterval: 1800
pwdCheckQuality: 1
pwdMustChange: TRUE
pwdGraceAuthNLimit: 0
pwdMaxAge: 7776000
pwdExpireWarning: 1209600
pwdLockoutDuration: 900
pwdLockout: TRUE
pwdSafeModify: FALSE
# ldapadd -x -D 'cn=Manager,ou=ldapbeheerders,dc=example,dc=nl' -W -f P04_APP1_ppolicies.ldif
dn: ou=policies,ou=APP1,dc=example,dc=nl
ou: policies
objectClass: top
objectClass: organizationalUnit
dn: cn=default,ou=policies,ou=APP1,dc=example,dc=nl
objectClass: top
objectClass: device
objectClass: pwdPolicy
cn: default
pwdAttribute: userPassword
pwdAllowUserChange: TRUE
pwdCheckQuality: 0
pwdExpireWarning: 374400
pwdFailureCountInterval: 1800
pwdGraceAuthNLimit: 5
pwdInHistory: 12
pwdLockout: TRUE
pwdLockoutDuration: 0
pwdMaxAge: 2592000
pwdMaxFailure: 5
pwdMinAge: 0
pwdMinLength: 8
pwdMustChange: TRUE
pwdSafeModify: FALSE