Hi all,
I have exactly the same issue.
My repro config is within the .tgz attached to this email. admin user is cn=admin,dc=example,dc=com and test user is uid=chantra,ou=users,dc=example,dc=com password for both of them is "foobarcode".
To reproduce, on Debian Lenny, * untar the archive * cd ldaps * ./install.sh (WARNING: ONLY DO THIS ON A TEST MACHINE, current setup/db will be ERASED).
That will stop slapd, override the config with the repro config, erase the current database, inject the testing one with slapadd, give credential to /var/lib/ldap to openldap user, start slapd
Then, run: for i in {1..10}; do ./ldapauth.sh $i; sleep 2; done; ./ldaps.sh
which will perform 10 failed authentication, with a pause of 2 seconds. Finally, ldaps.sh will output the details of user uid=chantra,ou=users,dc=example,dc=com
@Jiri, have you found a solution yet?
In my repro, here is the result after the 10 failed auth:
# chantra, users, example.com dn: uid=chantra,ou=users,dc=example,dc=com structuralObjectClass: inetOrgPerson entryUUID: 2e93af32-2d8d-102e-8fab-21ae2aafa5d0 creatorsName: createTimestamp: 20090904105519Z entryCSN: 20090904105519.875933Z#000000#000#000000 modifiersName: modifyTimestamp: 20090904105519Z pwdFailureTime: 20090904105614Z pwdFailureTime: 20090904105616Z pwdFailureTime: 20090904105618Z pwdFailureTime: 20090904105620Z entryDN: uid=chantra,ou=users,dc=example,dc=com subschemaSubentry: cn=Subschema hasSubordinates: FALSE
Again, here, we see only 4 pwdFailureTime (the 5th should have locked user ). Output of syslog is in the attached file called: pwdaccountlockout.txt but, the main part might be:
Sep 4 12:53:11 lenny32-tpl slapd[4079]: bdb_modify_internal: 0x00000004: uid=chantra,ou=users,dc=example,dc=com Sep 4 12:53:11 lenny32-tpl slapd[4079]: => access_allowed: delete access to "uid=chantra,ou=users,dc=example,dc=com" "pwdAccountLockedTime" requested Sep 4 12:53:11 lenny32-tpl slapd[4079]: => dn: [2] Sep 4 12:53:11 lenny32-tpl slapd[4079]: => acl_get: [3] attr pwdAccountLockedTime Sep 4 12:53:11 lenny32-tpl slapd[4079]: => slap_access_allowed: result not in cache (pwdAccountLockedTime) Sep 4 12:53:11 lenny32-tpl slapd[4079]: => acl_mask: access to entry "uid=chantra,ou=users,dc=example,dc=com", attr "pwdAccountLockedTime" requested Sep 4 12:53:11 lenny32-tpl slapd[4079]: => acl_mask: to all values by "", (=0) Sep 4 12:53:11 lenny32-tpl slapd[4079]: <= check a_dn_pat: cn=admin,dc=example,dc=com Sep 4 12:53:11 lenny32-tpl slapd[4079]: <= check a_dn_pat: * Sep 4 12:53:11 lenny32-tpl slapd[4079]: <= acl_mask: [2] applying read(=rscxd) (stop) Sep 4 12:53:11 lenny32-tpl slapd[4079]: <= acl_mask: [2] mask: read(=rscxd) Sep 4 12:53:11 lenny32-tpl slapd[4079]: => slap_access_allowed: delete access denied by read(=rscxd) Sep 4 12:53:11 lenny32-tpl slapd[4079]: => access_allowed: no more rules Sep 4 12:53:11 lenny32-tpl slapd[4079]: hdb_modify: modify failed (50)
Same here, changing: access to * by dn="cn=admin,dc=example,dc=com" write by * read
to access to * by dn="cn=admin,dc=example,dc=com" write by * write
will write pwdAccountLockedtime, but then, users or even anonymous will get far too much credentials :s
I also tried with the settings of openldap-2.4.17/tests/data/slapd-ppolicy.conf, e.g: access to attrs=userpassword by self write by * auth
access to * by self write by * read
to no avail.
Michael mentioned to try 2.4.17 which as changes that might affect pwdLockout (actually, ITS#6168 was because users where locked out while pwdLockout was set to FALSE, AFAICS), to no avail
Then, I tried the setting from the archive on Fedora11, and Debian Etch, same issue... There is surely something that I am missing here, but shouldn't pwdAccountLockedTime being handled by the daemon? no access rule should be set ( except the for the fact that the admin user can write/delete it).
What rule am I missing here?
If needed, I can provide a VMDK of the repro, let me know and I will upload it somewhere.
Cheers,
chantra
Hi,
I am having troubles making the ppolicy overlay to prevent password guessing attacks with pwdLockout with slapd-2.4.11-1 in Debian Lenny.
I set pwdMaxFailure to 3. In the user object I am testing with, I
never get
more than two entries for pwdFailureTime and pwdAccountLockedTime is
never
added at all.
I tracked the problem down to the ACL settings in slapd.conf. With my
default
access to * by dn="cn=admin,dc=example,dc=net" write by * read , I get the above result. When I rewrite the last line to "by *
write", it works.
The pwdFailureTime is updated, because it is defined as NO-USER-MODIFICATION, which bypasses te ACL checks for write. The problem happens when pwdMaxFailure failed logins are reached, and ppolicy.c tries to update pwdFailureTime and pwdAccountLockedTime
in a single request.
How is this supposed to work?
Shouldn't pwdAccountLockedTime also be defined with NO-USER-MODIFICATION?
couldn't the update request in ppolicy.c be executed with higher privileges? I tried to set up an non-anonymous bind in pam_ldap but this did not help.
is there some recommended ACL setting to grant the necessary privileges so that ppolicy.c can update pwdAccountLockedTime, but users can't? I am a splapd newbie, so maybe I don't see something obvious, but in the log below, I see: "acl_mask: to all values by "", (=0)" -- that looks like an anonymous bind, right? Allowing write for the pwdAccountLockedTime attribute to anyone does not seem a good idea ;-)
Thanks for any insight!
Jiri
P.S.: some detailed notes from my debugging are attached below:
I am authenticating with pam-ldap. When I mis-type the password of a user and do a search on the user object (with a +, to see the operational attributes), the pwdFailureTime is created. This is good.
When I preform the bad login again, I get a second value for pwdFailureTime. Still good.
But on the next login, instead of getting a third value for pwdFailureTime and an updated value for pwdAccountLockedTime, nothing happens. I put some more debug info into ppolicy_bind_response() like this:
- We only count those failures
- which are not due to expire.
*/ Debug(LDAP_DEBUG_ANY, "xxx: counting pwdFailureTime %i/%d\n", i, fc, 0); } } if ((ppb->pp.pwdMaxFailure > 0) && (fc >= ppb->pp.pwdMaxFailure - 1)) { Debug(LDAP_DEBUG_ANY, "xxx: trying to insert pwdAccountLockedTime\n", 0, 0, 0);
... in the logs (with loglevel 65535), I really see:
Aug 8 00:05:42 localhost slapd[15416]: xxx: counting pwdFailureTime 0/1 Aug 8 00:05:42 localhost slapd[15416]: xxx: counting pwdFailureTime 1/2 Aug 8 00:05:42 localhost slapd[15416]: xxx: trying to insert pwdAccountLockedTime [snip] Aug 8 00:05:42 localhost slapd[15416]: => access_allowed: delete access to "uid=j.bohac,ou=users,dc=example,dc=net" "pwdAccountLockedTime" requested Aug 8 00:05:42 localhost slapd[15416]: => acl_get: [2] attr pwdAccountLockedTime Aug 8 00:05:42 localhost slapd[15416]: => slap_access_allowed: result not in cache (pwdAccountLockedTime) Aug 8 00:05:42 localhost slapd[15416]: => acl_mask: access to entry "uid=j.bohac,ou=users,dc=example,dc=net", attr "pwdAccountLockedTime" requested Aug 8 00:05:42 localhost slapd[15416]: => acl_mask: to all values by "", (=0) Aug 8 00:05:42 localhost slapd[15416]: <= check a_dn_pat: cn=admin,dc=example,dc=net Aug 8 00:05:42 localhost slapd[15416]: <= check a_dn_pat: * Aug 8 00:05:42 localhost slapd[15416]: <= acl_mask: [2] applying read(=rscxd) (stop) Aug 8 00:05:42 localhost slapd[15416]: <= acl_mask: [2] mask: read(=rscxd) Aug 8 00:05:42 localhost slapd[15416]: => slap_access_allowed: delete access denied by read(=rscxd) Aug 8 00:05:42 localhost slapd[15416]: => access_allowed: no more rules
!DSPAM:4aa1064790404668414040!