From 300985b91bdc8cc383b51276bf2c27e6d70d0006 Mon Sep 17 00:00:00 2001 From: Arvid Requate Date: Tue, 24 Jul 2018 12:57:18 +0200 Subject: [PATCH 1/2] Bug #47391: Cleanup: Don't s4search twice --- .../modules/univention/s4connector/s4/password.py | 39 +++++++--------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/services/univention-s4-connector/modules/univention/s4connector/s4/password.py b/services/univention-s4-connector/modules/univention/s4connector/s4/password.py index 948bfe627f..583c4a55bf 100644 --- a/services/univention-s4-connector/modules/univention/s4connector/s4/password.py +++ b/services/univention-s4-connector/modules/univention/s4connector/s4/password.py @@ -532,26 +532,20 @@ def password_sync_ucs_to_s4(s4connector, key, object): # ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from UCS: %s" % ucsNThash) - s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['pwdLastSet', 'objectSid']) + s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['pwdLastSet', 'unicodePwd', 'userPrincipalName', 'supplementalCredentials', 'msDS-KeyVersionNumber', 'dBCSPwd']) pwdLastSet = None if 'pwdLastSet' in s4_object_attributes: pwdLastSet = long(s4_object_attributes['pwdLastSet'][0]) objectSid = univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet from S4 : %s" % pwdLastSet) - # rid = None - # if s4_object_attributes.has_key('objectSid'): - # rid = str(univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]).split('-')[-1]) pwd_set = False - filter_expr = format_escaped('(objectSid={0!e})', objectSid) - res = s4connector.lo_s4.search(filter=filter_expr, attr=['unicodePwd', 'userPrincipalName', 'supplementalCredentials', 'msDS-KeyVersionNumber', 'dBCSPwd']) - s4_search_attributes = res[0][1] - - unicodePwd_attr = s4_search_attributes.get('unicodePwd', [None])[0] - dBCSPwd_attr = s4_search_attributes.get('dBCSPwd', [None])[0] - userPrincipalName_attr = s4_search_attributes.get('userPrincipalName', [None])[0] - supplementalCredentials = s4_search_attributes.get('supplementalCredentials', [None])[0] - msDS_KeyVersionNumber = s4_search_attributes.get('msDS-KeyVersionNumber', [0])[0] + + unicodePwd_attr = s4_object_attributes.get('unicodePwd', [None])[0] + dBCSPwd_attr = s4_object_attributes.get('dBCSPwd', [None])[0] + userPrincipalName_attr = s4_object_attributes.get('userPrincipalName', [None])[0] + supplementalCredentials = s4_object_attributes.get('supplementalCredentials', [None])[0] + msDS_KeyVersionNumber = s4_object_attributes.get('msDS-KeyVersionNumber', [0])[0] # ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from S4: %s" % unicodePwd_attr) s4NThash = None @@ -666,7 +660,7 @@ def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=Tru return object = s4connector._object_mapping(key, ucs_object, 'ucs') - s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['objectSid', 'pwdLastSet']) + s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['pwdLastSet', 'unicodePwd', 'supplementalCredentials', 'msDS-KeyVersionNumber', 'dBCSPwd']) if s4connector.isInCreationList(object['dn']): s4connector.removeFromCreationList(object['dn']) @@ -677,27 +671,18 @@ def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=Tru if 'pwdLastSet' in s4_object_attributes: pwdLastSet = long(s4_object_attributes['pwdLastSet'][0]) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: pwdLastSet from S4: %s (%s)" % (pwdLastSet, s4_object_attributes)) - objectSid = univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]) - - # rid = None - # if s4_object_attributes.has_key('objectSid'): - # rid = str(univention.s4connector.s4.decode_sid(s4_object_attributes['objectSid'][0]).split('-')[-1]) - - filter_expr = format_escaped('(objectSid={0!e})', objectSid) - res = s4connector.lo_s4.search(filter=filter_expr, attr=['unicodePwd', 'supplementalCredentials', 'msDS-KeyVersionNumber', 'dBCSPwd']) - s4_search_attributes = res[0][1] - unicodePwd_attr = s4_search_attributes.get('unicodePwd', [None])[0] + unicodePwd_attr = s4_object_attributes.get('unicodePwd', [None])[0] if unicodePwd_attr: ntPwd = binascii.b2a_hex(unicodePwd_attr).upper() lmPwd = '' - dBCSPwd = s4_search_attributes.get('dBCSPwd', [None])[0] + dBCSPwd = s4_object_attributes.get('dBCSPwd', [None])[0] if dBCSPwd: lmPwd = binascii.b2a_hex(dBCSPwd).upper() - supplementalCredentials = s4_search_attributes.get('supplementalCredentials', [None])[0] - msDS_KeyVersionNumber = s4_search_attributes.get('msDS-KeyVersionNumber', [0])[0] + supplementalCredentials = s4_object_attributes.get('supplementalCredentials', [None])[0] + msDS_KeyVersionNumber = s4_object_attributes.get('msDS-KeyVersionNumber', [0])[0] ntPwd_ucs = '' lmPwd_ucs = '' -- 2.11.0 From 7fd75260f61042825db1053597c45ce4f92f93c7 Mon Sep 17 00:00:00 2001 From: Arvid Requate Date: Tue, 24 Jul 2018 13:18:27 +0200 Subject: [PATCH 2/2] Bug #47391: sync_to_ucs: update shadowLastChange if pwdLastSet changed, even if the hashes didn't --- .../modules/univention/s4connector/__init__.py | 1 + .../modules/univention/s4connector/s4/password.py | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/services/univention-s4-connector/modules/univention/s4connector/__init__.py b/services/univention-s4-connector/modules/univention/s4connector/__init__.py index a1ef180c33..9e18f955bb 100644 --- a/services/univention-s4-connector/modules/univention/s4connector/__init__.py +++ b/services/univention-s4-connector/modules/univention/s4connector/__init__.py @@ -1554,6 +1554,7 @@ class ucs: ud.debug(ud.LDAP, ud.INFO, "sync_to_ucs: old_s4_object: %s" % old_s4_object) ud.debug(ud.LDAP, ud.INFO, "sync_to_ucs: new_s4_object: %s" % original_object['attributes']) if old_s4_object: + object['old_s4_object'] = old_s4_object for attr in original_object['attributes']: if old_s4_object.get(attr) != original_object['attributes'].get(attr): object['changed_attributes'].append(attr) diff --git a/services/univention-s4-connector/modules/univention/s4connector/s4/password.py b/services/univention-s4-connector/modules/univention/s4connector/s4/password.py index 583c4a55bf..2556fe1d38 100644 --- a/services/univention-s4-connector/modules/univention/s4connector/s4/password.py +++ b/services/univention-s4-connector/modules/univention/s4connector/s4/password.py @@ -737,12 +737,22 @@ def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=Tru # Append modification as well to modlist, to apply in one transaction if modifyUserPassword: modlist.append(('userPassword', userPassword_ucs, '{K5KEY}')) + else: + ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: No password change to sync to UCS") + + try: + old_pwdLastSet = object['old_s4_object']['pwdLastSet'][0] + except (KeyError, IndexError): + old_pwdLastSet = None + if pwdLastSet != old_pwdLastSet: + ud.debug(ud.LDAP, ud.ALL, "password_sync_s4_to_ucs: updating shadowLastChange") # Update password expiry interval # # update shadowLastChange to now old_shadowLastChange = ucs_object_attributes.get('shadowLastChange', [None])[0] - new_shadowLastChange = str(long(time.time()) / 3600 / 24) + pwdLastSet_unix = univention.s4connector.s4.s42unix_time(pwdLastSet) + new_shadowLastChange = str(pwdLastSet_unix) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update shadowLastChange to %s for %s" % (new_shadowLastChange, ucs_object['dn'])) modlist.append(('shadowLastChange', old_shadowLastChange, new_shadowLastChange)) # shadowMax (set to value of univentionPWExpiryInterval, otherwise delete) @@ -758,17 +768,14 @@ def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=Tru pwexp_value = pwexp.get('value', [None])[0] if pwexp_value: new_shadowMax = pwexp_value - new_krb5end = time.strftime("%Y%m%d000000Z", time.gmtime((long(time.time()) + (int(pwexp_value) * 3600 * 24)))) + new_krb5end = time.strftime("%Y%m%d000000Z", pwdLastSet_unix + (int(pwexp_value) * 3600 * 24)))) if old_shadowMax or new_shadowMax: ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update shadowMax to %s for %s" % (new_shadowMax, ucs_object['dn'])) modlist.append(('shadowMax', old_shadowMax, new_shadowMax)) if old_krb5end or new_krb5end: ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: update krb5PasswordEnd to %s for %s" % (new_krb5end, ucs_object['dn'])) modlist.append(('krb5PasswordEnd', old_krb5end, new_krb5end)) - else: - ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: No password change to sync to UCS") - if pwd_changed and (pwdLastSet or pwdLastSet == 0): newSambaPwdMustChange = sambaPwdMustChange if pwdLastSet == 0: # pwd change on next login newSambaPwdMustChange = str(pwdLastSet) -- 2.11.0