summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-03-30 23:57:47 +0100
committerArthur de Jong <arthur@arthurdejong.org>2013-03-30 23:58:47 +0100
commitd7990dee92e4e2ece7ede72f15f6ed6057640e1c (patch)
tree884863ee7fcaa95d3eaa2a845fdfae93017bd5cc
parentea6bff3e4490c24f71b803add8bda4e992ec7c0e (diff)
Update the shadowLastChange on password change in pynslcd
-rw-r--r--pynslcd/pam.py27
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']