[Date Prev][Date Next] [Chronological] [Thread] [Top]

ppolicy and ACLs of pwdAccountLockedTime?



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
------