[krbdev.mit.edu #8667] Account lockout code duplication between KDB module

Greg Hudson via RT rt-comment at KRBDEV-PROD-APP-1.mit.edu
Thu Apr 19 12:03:43 EDT 2018


Account lockout is implemented via two DAL functions: 
check_policy_as() to deny an AS request if the principal is locked 
out, and audit_as_req() to update any lockout state after a 
successful or failed AS-REQ.  A KDB module can make these decisions 
any way it wants, or deliberately not implement account lockout.  But 
in-tree KDB modules and modules which want to behave similarly will:

* retrieve "disable_last_success" and "disable_lockout" boolean 
relations from the DB config section in the profile.
* look up the policy associated with the principal (unless 
disable_lockout is set)
* determine if the account is locked out as a function of:
  - the policy pw_max_fail and pw_lockout duration fields
  - the principal fail_auth_count and last_failed fields
  - the principal last administrative unlock time (from tl-data)
  - the current timestamp
* in audit_as_req(), update the principal fields as a function of:
  - whether the principal is already locked out
  - the success or failure of the AS operation
  - the disable_lockout and disable_last_success configuration
  - the principal last administrative unlock time
  - the policy pw_failcnt_interval field
  - the current timestamp

This behavior yields a tangled mess of DB-specific operations and 
common decision-making logic:

* Enable/disable configuration is common.
* Retrieving the policy name reference from the principal entry is 
common (and currently irritating to implement; see issue #7951).
* Fetching the policy object is DB-specific, in the sense that re-
entering libkdb5 to do it would cause a recursive lock of 
krb5_db2_mutex in DB2.
* Computing whether the principal is locked out is common.
* Computing the updates required is common.
* Making the updates is DB-specific.  (For instance, in the 
forthcoming LMDB module we want to do it with a transactional update 
to the lockout record, without touching the primary principal DB.)

Right now each KDB module implements all of the above.  Moving the 
common decision-making logic into exposed libkdb5 functions might be 
a benefit.  Possibly interfaces might include:

* conf section name -> disable_last_success, disable_lockout booleans

* principal entry -> policy name reference (or more likely -> 
osa_princ_ent_t; this is issue #7951)

* principal entry, policy entry, timestamp -> is_locked_out boolean

* principal entry, policy entry, timestamp, disable_last_success, 
disable_lockout, success/failure status -> set_last_success, 
set_last_failure, zero_fail_count booleans (set_last_failure also 
means the failure count should be incremented, possibly after zeroing 
it)

It is an open question whether the added libkdb5 API surface is worth 
the amount of decision-making logic these interfaces would factor 
out, especially for the last one.


More information about the krb5-bugs mailing list