diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2013-03-30 23:57:47 +0100 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2013-03-30 23:58:47 +0100 |
commit | d7990dee92e4e2ece7ede72f15f6ed6057640e1c (patch) | |
tree | 884863ee7fcaa95d3eaa2a845fdfae93017bd5cc | |
parent | ea6bff3e4490c24f71b803add8bda4e992ec7c0e (diff) |
Update the shadowLastChange on password change in pynslcd
-rw-r--r-- | pynslcd/pam.py | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/pynslcd/pam.py b/pynslcd/pam.py index a1a24d0..b2bf50e 100644 --- a/pynslcd/pam.py +++ b/pynslcd/pam.py @@ -20,6 +20,7 @@ import logging import socket +import time from ldap.controls.ppolicy import PasswordPolicyControl, PasswordPolicyError from ldap.filter import escape_filter_chars @@ -30,6 +31,7 @@ import common import constants import passwd import search +import shadow def authenticate(binddn, password): @@ -79,6 +81,29 @@ def pwmod(conn, userdn, oldpassword, newpassword): raise +def update_lastchange(conns, userdn): + """Try to update the shadowLastChange attribute of the entry.""" + attribute = shadow.attmap['shadowLastChange'] + if attribute == '${shadowLastChange:--1}': + attribute = 'shadowLastChange' + if not attribute or '$' in attribute: + raise ValueError('shadowLastChange has unsupported mapping') + # build the value for the new attribute + if attribute.lower() == 'pwdlastset': + # for AD we use another timestamp */ + value = '%d000000000' % (time.time() / 100L + (134774L * 864L)) + else: + # time in days since Jan 1, 1970 + value = '%d' % (time.time() / (60 * 60 * 24)) + # perform the modification, return at first success + for conn in conns: + try: + conn.modify_s(userdn, [(ldap.MOD_REPLACE, attribute, [value])]) + return + except ldap.LDAPError: + pass # ignore error and try next connection + + class PAMRequest(common.Request): def validate(self, parameters): @@ -268,6 +293,8 @@ class PAMPasswordModificationRequest(PAMRequest): try: conn, authz, msg = authenticate(binddn, password) pwmod(conn, parameters['userdn'], parameters['oldpassword'], parameters['newpassword']) + # try to update lastchange with normal or user connection + update_lastchange((self.conn, conn), parameters['userdn']) except ldap.INVALID_CREDENTIALS, e: try: msg = e[0]['desc'] |