def move(self, dn, newdn): newrdn = get_rdn (newdn) parent1 = get_parent_dn (dn) parent2 = get_parent_dn (newdn) if parent1 != parent2: self.lo.rename_s(s4.compatible_modstring (unicode (dn)), s4.compatible_modstring (unicode (newrdn)), s4.compatible_modstring (unicode (parent2))) else: self.lo.modrdn_s(s4.compatible_modstring (unicode (dn)), s4.compatible_modstring (unicode (newrdn)))
def move(self, dn, newdn): newrdn = get_rdn(newdn) parent1 = get_parent_dn(dn) parent2 = get_parent_dn(newdn) if parent1 != parent2: self.lo.rename_s(s4.compatible_modstring(unicode(dn)), s4.compatible_modstring(unicode(newrdn)), s4.compatible_modstring(unicode(parent2))) else: self.lo.modrdn_s(s4.compatible_modstring(unicode(dn)), s4.compatible_modstring(unicode(newrdn)))
def set_attributes(self, dn, **attributes): old_attributes = self.get(dn, attr=attributes.keys()) ldif = modlist.modifyModlist(old_attributes, attributes) comp_dn = s4.compatible_modstring(unicode(dn)) self.lo.modify_ext_s(comp_dn, ldif, serverctrls=self.serverctrls_for_add_and_modify)
def set_attribute_with_provision_ctrl(self, dn, key, value): LDB_CONTROL_PROVISION_OID = '1.3.6.1.4.1.7165.4.3.16' ctrls = [LDAPControl(LDB_CONTROL_PROVISION_OID, criticality=0) ] + self.serverctrls_for_add_and_modify self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)), [(ldap.MOD_REPLACE, key, value)], serverctrls=ctrls)
def create(self, dn, attrs): attrs = dict( (name, [attr] if not isinstance(attr, (list, tuple)) else attr) for name, attr in attrs.items()) ldif = modlist.addModlist(attrs) self.lo.add_ext_s(s4.compatible_modstring(unicode(dn)), ldif, serverctrls=self.serverctrls_for_add_and_modify)
def set_attributes(self, dn, **attributes): old_attributes = self.get(dn, attr=attributes.keys()) attributes = dict( (name, [attr] if not isinstance(attr, (list, tuple)) else attr) for name, attr in attributes.items()) ldif = modlist.modifyModlist(old_attributes, attributes) comp_dn = s4.compatible_modstring(unicode(dn)) if ldif: self.lo.modify_ext_s( comp_dn, ldif, serverctrls=self.serverctrls_for_add_and_modify)
def append_to_attribute(self, dn, key, value): self.lo.modify_s( s4.compatible_modstring(unicode(dn)), [(ldap.MOD_ADD, key, s4.compatible_modstring(unicode(value)))])
def delete_attribute(self, dn, key): self.lo.modify_s(s4.compatible_modstring(unicode(dn)), [(ldap.MOD_DELETE, key, None)])
def delete_attribute(self, dn, key): self.lo.modify_s (s4.compatible_modstring (unicode (dn)), [(ldap.MOD_DELETE, key, None)])
def append_to_attribute(self, dn, key, value): self.lo.modify_ext_s( s4.compatible_modstring(unicode(dn)), [(ldap.MOD_ADD, key, s4.compatible_modstring(unicode(value)))], serverctrls=self.serverctrls_for_add_and_modify)
def create(self, dn, attrs): ldif = modlist.addModlist(attrs) self.lo.add_ext_s(s4.compatible_modstring(unicode(dn)), ldif, serverctrls=self.serverctrls_for_add_and_modify)
def delete(self, dn): self.lo.delete_s(s4.compatible_modstring (unicode (dn)))
def create(self, dn, attrs): ldif = modlist.addModlist(attrs) self.lo.add_s(s4.compatible_modstring (unicode (dn)),ldif)
def remove_from_attribute(self, dn, key, value): self.lo.modify_s (s4.compatible_modstring (unicode (dn)), [(ldap.MOD_DELETE, key, s4.compatible_modstring (unicode (value)))])
def append_to_attribute(self, dn, key, value): self.lo.modify_s (s4.compatible_modstring (unicode (dn)), [(ldap.MOD_ADD, key, s4.compatible_modstring (unicode (value)))])
def remove_from_attribute(self, dn, key, value): self.lo.modify_s( s4.compatible_modstring(unicode(dn)), [(ldap.MOD_DELETE, key, s4.compatible_modstring(unicode(value)))])
def create(self, dn, attrs): ldif = modlist.addModlist(attrs) self.lo.add_s(s4.compatible_modstring(unicode(dn)), ldif)
def password_sync_ucs_to_s4(s4connector, key, object): _d = ud.function('ldap.s4.password_sync_ucs_to_s4') ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4 called") modify = False old_ucs_object = object.get('old_ucs_object', {}) new_ucs_object = object.get('new_ucs_object', {}) if old_ucs_object or new_ucs_object: for attr in ['sambaLMPassword', 'sambaNTPassword', 'sambaPwdLastSet', 'sambaPwdMustChange', 'krb5PrincipalName', 'krb5Key', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService']: old_values = set(old_ucs_object.get(attr, [])) new_values = set(new_ucs_object.get(attr, [])) if old_values != new_values: modify = True break else: # add mode modify = True if not modify: ud.debug(ud.LDAP, ud.INFO, 'password_sync_ucs_to_s4: the password for %s has not been changed. Skipping password sync.' % (object['dn'])) return try: ud.debug(ud.LDAP, ud.INFO, "Object DN=%s" % object['dn']) except: # FIXME: which exception is to be caught? ud.debug(ud.LDAP, ud.INFO, "Object DN not printable") ucs_object = s4connector._object_mapping(key, object, 'con') try: ud.debug(ud.LDAP, ud.INFO, " UCS DN = %s" % ucs_object['dn']) except: # FIXME: which exception is to be caught? ud.debug(ud.LDAP, ud.INFO, " UCS DN not printable") try: ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaLMPassword', 'sambaNTPassword', 'sambaPwdLastSet', 'sambaPwdMustChange', 'krb5PrincipalName', 'krb5Key', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService'], required=True) except ldap.NO_SUCH_OBJECT: ud.debug(ud.LDAP, ud.PROCESS, "password_sync_ucs_to_s4: The UCS object (%s) was not found. The object was removed." % ucs_object['dn']) return services = ucs_object_attributes.get('univentionService', []) if 'Samba 4' in services: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: %s is a S4 server, skip password sync" % ucs_object['dn']) return sambaPwdLastSet = None if 'sambaPwdLastSet' in ucs_object_attributes: sambaPwdLastSet = long(ucs_object_attributes['sambaPwdLastSet'][0]) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaPwdLastSet: %s" % sambaPwdLastSet) if 'sambaPwdMustChange' in ucs_object_attributes: sambaPwdMustChange = long(ucs_object_attributes['sambaPwdMustChange'][0]) ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_to_s4: Ignoring sambaPwdMustChange: %s" % sambaPwdMustChange) ucsLMhash = ucs_object_attributes.get('sambaLMPassword', [None])[0] ucsNThash = ucs_object_attributes.get('sambaNTPassword', [None])[0] krb5Principal = ucs_object_attributes.get('krb5PrincipalName', [None])[0] krb5Key = ucs_object_attributes.get('krb5Key', []) if not ucsNThash: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaNTPassword missing in UCS LDAP, trying krb5Key") ucsNThash = extract_NThash_from_krb5key(krb5Key) if not ucsNThash: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get NT Password-Hash from UCS LDAP") # 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']) 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] # ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Password-Hash from S4: %s" % unicodePwd_attr) s4NThash = None if unicodePwd_attr: s4NThash = binascii.b2a_hex(unicodePwd_attr).upper() else: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get NT Password-Hash from S4") s4LMhash = None if dBCSPwd_attr: s4LMhash = binascii.b2a_hex(dBCSPwd_attr).upper() else: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: Failed to get LM Password-Hash from S4") modlist = [] if krb5Principal != userPrincipalName_attr: if krb5Principal: if not userPrincipalName_attr: # new and not old modlist.append((ldap.MOD_ADD, 'userPrincipalName', krb5Principal)) else: # new and old differ if krb5Principal.lower() != userPrincipalName_attr.lower(): ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_to_s4: userPrincipalName != krb5Principal: '%s' != '%s'" % (userPrincipalName_attr, krb5Principal)) modlist.append((ldap.MOD_REPLACE, 'userPrincipalName', krb5Principal)) else: if userPrincipalName_attr: # old and not new modlist.append((ldap.MOD_DELETE, 'userPrincipalName', userPrincipalName_attr)) if not ucsNThash == s4NThash: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: NT Hash S4: %s NT Hash UCS: %s" % (s4NThash, ucsNThash)) # Now if ucsNThash is empty there should at least some timestamp in UCS, # otherwise it's probably not a good idea to remove the unicodePwd. # Usecase: LDB module on ucs_3.0-0-ucsschool slaves creates XP computers/windows in UDM without password if ucsNThash or sambaPwdLastSet: pwd_set = True unicodePwd_new = None if ucsNThash: try: unicodePwd_new = binascii.a2b_hex(ucsNThash) except TypeError as exc: if ucsNThash.startswith("NO PASSWORD"): pwd_set = False else: raise if pwd_set: if unicodePwd_attr: modlist.append((ldap.MOD_DELETE, 'unicodePwd', unicodePwd_attr)) if unicodePwd_new: modlist.append((ldap.MOD_ADD, 'unicodePwd', unicodePwd_new)) if not ucsLMhash == s4LMhash: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: LM Hash S4: %s LM Hash UCS: %s" % (s4LMhash, ucsLMhash)) pwd_set = True if dBCSPwd_attr: modlist.append((ldap.MOD_DELETE, 'dBCSPwd', dBCSPwd_attr)) if ucsLMhash: dBCSPwd_new = binascii.a2b_hex(ucsLMhash) modlist.append((ldap.MOD_ADD, 'dBCSPwd', dBCSPwd_new)) if pwd_set or not supplementalCredentials: if krb5Principal: # encoding of Samba4 supplementalCredentials if supplementalCredentials: modlist.append((ldap.MOD_DELETE, 'supplementalCredentials', supplementalCredentials)) if krb5Key: supplementalCredentials_new = calculate_supplementalCredentials(krb5Key, supplementalCredentials) if supplementalCredentials_new: modlist.append((ldap.MOD_ADD, 'supplementalCredentials', supplementalCredentials_new)) else: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: no supplementalCredentials_new") # if supplementalCredentials: # modlist.append((ldap.MOD_REPLACE, 'msDS-KeyVersionNumber', krb5KeyVersionNumber)) # else: # modlist.append((ldap.MOD_ADD, 'msDS-KeyVersionNumber', krb5KeyVersionNumber)) if sambaPwdLastSet is None: sambaPwdLastSet = int(time.time()) newpwdlastset = str(univention.s4connector.s4.samba2s4_time(sambaPwdLastSet)) elif sambaPwdLastSet in [0, 1]: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: samba pwd expired, set newpwdLastSet to 0") newpwdlastset = 0 else: newpwdlastset = univention.s4connector.s4.samba2s4_time(sambaPwdLastSet) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet in modlist: %s" % newpwdlastset) modlist.append((ldap.MOD_REPLACE, 'pwdLastSet', str(newpwdlastset))) modlist.append((ldap.MOD_REPLACE, 'badPwdCount', '0')) modlist.append((ldap.MOD_REPLACE, 'badPasswordTime', '0')) modlist.append((ldap.MOD_REPLACE, 'lockoutTime', '0')) else: ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: No password change to sync to S4 ") # check pwdLastSet if sambaPwdLastSet is not None: if sambaPwdLastSet in [0, 1]: newpwdlastset = 0 else: newpwdlastset = univention.s4connector.s4.samba2s4_time(sambaPwdLastSet) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: sambaPwdLastSet: %d" % sambaPwdLastSet) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: newpwdlastset : %s" % newpwdlastset) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: pwdLastSet (AD): %s" % pwdLastSet) if newpwdlastset != pwdLastSet and abs(newpwdlastset - pwdLastSet) >= 10000000: modlist.append((ldap.MOD_REPLACE, 'pwdLastSet', str(newpwdlastset))) # TODO: Password History ctrl_bypass_password_hash = LDAPControl('1.3.6.1.4.1.7165.4.3.12', criticality=0) ud.debug(ud.LDAP, ud.INFO, "password_sync_ucs_to_s4: modlist: %s" % modlist) if modlist: s4connector.lo_s4.lo.modify_ext_s(compatible_modstring(object['dn']), modlist, serverctrls=[ctrl_bypass_password_hash])
def delete(self, dn): self.lo.delete_s(s4.compatible_modstring(unicode(dn)))
def password_sync_s4_to_ucs(s4connector, key, ucs_object, modifyUserPassword=True): _d = ud.function('ldap.s4.password_sync_s4_to_ucs') ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs called") if ucs_object['modtype'] == 'modify': if 'pwdLastSet' not in ucs_object.get('changed_attributes', []): ud.debug(ud.LDAP, ud.INFO, 'password_sync_s4_to_ucs: the password for %s has not been changed. Skipping password sync.' % (ucs_object['dn'])) return object = s4connector._object_mapping(key, ucs_object, 'ucs') s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['objectSid', 'pwdLastSet']) if s4connector.isInCreationList(object['dn']): s4connector.removeFromCreationList(object['dn']) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Synchronisation of password has been canceled. Object was just created.") return pwdLastSet = None 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] if unicodePwd_attr: ntPwd = binascii.b2a_hex(unicodePwd_attr).upper() lmPwd = '' dBCSPwd = s4_search_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] ntPwd_ucs = '' lmPwd_ucs = '' krb5Principal = '' userPassword = '' modlist = [] ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaPwdMustChange', 'sambaPwdLastSet', 'sambaNTPassword', 'sambaLMPassword', 'krb5PrincipalName', 'krb5Key', 'krb5KeyVersionNumber', 'userPassword', 'shadowLastChange', 'shadowMax', 'krb5PasswordEnd', 'univentionService']) services = ucs_object_attributes.get('univentionService', []) if 'S4 SlavePDC' in services: ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: %s is a S4 SlavePDC server, skip password sync" % ucs_object['dn']) return if 'sambaNTPassword' in ucs_object_attributes: ntPwd_ucs = ucs_object_attributes['sambaNTPassword'][0] if 'sambaLMPassword' in ucs_object_attributes: lmPwd_ucs = ucs_object_attributes['sambaLMPassword'][0] if 'krb5PrincipalName' in ucs_object_attributes: krb5Principal = ucs_object_attributes['krb5PrincipalName'][0] if 'userPassword' in ucs_object_attributes: userPassword = ucs_object_attributes['userPassword'][0] sambaPwdLastSet = None if 'sambaPwdLastSet' in ucs_object_attributes: sambaPwdLastSet = ucs_object_attributes['sambaPwdLastSet'][0] ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet: %s" % sambaPwdLastSet) sambaPwdMustChange = '' if 'sambaPwdMustChange' in ucs_object_attributes: sambaPwdMustChange = ucs_object_attributes['sambaPwdMustChange'][0] ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Found sambaPwdMustChange: %s" % sambaPwdMustChange) krb5Key_ucs = ucs_object_attributes.get('krb5Key', []) userPassword_ucs = ucs_object_attributes.get('userPassword', [None])[0] krb5KeyVersionNumber = ucs_object_attributes.get('krb5KeyVersionNumber', [None])[0] pwd_changed = False if ntPwd != ntPwd_ucs: pwd_changed = True modlist.append(('sambaNTPassword', ntPwd_ucs, str(ntPwd))) if lmPwd != lmPwd_ucs: pwd_changed = True modlist.append(('sambaLMPassword', lmPwd_ucs, str(lmPwd))) if pwd_changed: if krb5Principal: # decoding of Samba4 supplementalCredentials krb5Key_new = calculate_krb5key(unicodePwd_attr, supplementalCredentials, int(msDS_KeyVersionNumber)) modlist.append(('krb5Key', krb5Key_ucs, krb5Key_new)) if int(msDS_KeyVersionNumber) != int(krb5KeyVersionNumber): modlist.append(('krb5KeyVersionNumber', krb5KeyVersionNumber, msDS_KeyVersionNumber)) # 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") old_shadowLastChange = ucs_object_attributes.get('shadowLastChange', [None])[0] new_shadowLastChange = old_shadowLastChange # shadowMax (set to value of univentionPWExpiryInterval, otherwise delete) # krb5PasswordEnd (set to today + univentionPWExpiryInterval, otherwise delete) old_shadowMax = ucs_object_attributes.get('shadowMax', [None])[0] new_shadowMax = old_shadowMax old_krb5end = ucs_object_attributes.get('krb5PasswordEnd', [None])[0] new_krb5end = old_krb5end pwdLastSet_unix = univention.s4connector.s4.s42samba_time(pwdLastSet) newSambaPwdLastSet = str(pwdLastSet_unix) if pwdLastSet == 0: # pwd change on next login new_shadowMax = '1' expiry = long(time.time()) new_krb5end = time.strftime("%Y%m%d000000Z", time.gmtime(expiry)) else: # not pwd change on next login new_shadowLastChange = str(pwdLastSet_unix / 3600 / 24) userobject = s4connector.get_ucs_object('user', ucs_object['dn']) if not userobject: ud.debug(ud.LDAP, ud.ERROR, "password_sync_s4_to_ucs: couldn't get user-object from UCS") return False pwhistoryPolicy = userobject.loadPolicyObject('policies/pwhistory') try: expiryInterval = int(pwhistoryPolicy['expiryInterval']) except (TypeError, ValueError): # expiryInterval is empty or no legal int-string pwhistoryPolicy['expiryInterval'] = '' expiryInterval = -1 ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: password expiryInterval for %s is %s" % (ucs_object['dn'], expiryInterval)) if expiryInterval in (-1, 0): new_shadowMax = '' new_krb5end = '' else: new_shadowMax = str(expiryInterval) new_krb5end = time.strftime("%Y%m%d000000Z", time.gmtime((pwdLastSet_unix + (int(expiryInterval) * 3600 * 24)))) if new_shadowLastChange != old_shadowLastChange: 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)) if new_shadowMax != old_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 new_krb5end != old_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)) if sambaPwdLastSet: if sambaPwdLastSet != newSambaPwdLastSet: modlist.append(('sambaPwdLastSet', sambaPwdLastSet, newSambaPwdLastSet)) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet in modlist (replace): %s" % newSambaPwdLastSet) else: modlist.append(('sambaPwdLastSet', '', newSambaPwdLastSet)) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: sambaPwdLastSet in modlist (set): %s" % newSambaPwdLastSet) if sambaPwdMustChange: modlist.append(('sambaPwdMustChange', sambaPwdMustChange, '')) ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: Removing sambaPwdMustChange") if len(modlist) > 0: ud.debug(ud.LDAP, ud.INFO, "password_sync_s4_to_ucs: modlist: %s" % modlist) s4connector.lo.lo.modify(ucs_object['dn'], modlist) else: ud.debug(ud.LDAP, ud.WARN, "password_sync_ucs_s4_to_ucs: Failed to get Password-Hash from S4")
def set_attribute(self, dn, key, value): if key not in s4.DECODE_IGNORELIST: value = s4.compatible_modstring(unicode(value)) self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)), [(ldap.MOD_REPLACE, key, value)], serverctrls=self.serverctrls_for_add_and_modify)
def lockout_sync_ucs_to_s4(s4connector, key, object): """ Sync unlock *modification* from OpenLDAP to Samba/AD: sync OpenLDAP ("L" not in sambaAcctFlags) -> Samba/AD lockoutTime = 0 sync OpenLDAP ("L" in sambaAcctFlags) -> Samba/AD lockoutTime = sambaBadPasswordTime and OpenLDAP sambaBadPasswordTime -> Samba/AD badPasswordTime """ function_name = 'lockout_sync_ucs_to_s4' _d = ud.function('ldap.s4.%s' % function_name) ud.debug(ud.LDAP, ud.INFO, "%s called" % function_name) if object['modtype'] not in ('modify', 'add'): return new_ucs_object = object.get('new_ucs_object', {}) if not new_ucs_object: # only set by sync_from_ucs in MODIFY case return old_ucs_object = object.get('old_ucs_object', {}) if not old_ucs_object: # only set by sync_from_ucs in MODIFY case return new_sambaAcctFlags = new_ucs_object.get('sambaAcctFlags', [''])[0] is_locked = "L" in new_sambaAcctFlags old_sambaAcctFlags = old_ucs_object.get('sambaAcctFlags', [''])[0] was_locked = "L" in old_sambaAcctFlags if is_locked == was_locked: # Require a change in the pickled state return modlist = [] if not is_locked: s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['lockoutTime', 'badPasswordTime']) if 'lockoutTime' not in s4_object_attributes: return lockoutTime = s4_object_attributes['lockoutTime'][0] if lockoutTime == "0": return # Now object.get('new_ucs_object') may be a stale pickled state, so let's lookup the current OpenLDAP object state # Unfortunately "object" doesn't hold the current OpenLDAP DN, so we need to map back first ucs_object = s4connector._object_mapping(key, object) try: ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaAcctFlags', 'sambaBadPasswordTime'], required=True) except ldap.NO_SUCH_OBJECT: ud.debug(ud.LDAP, ud.WARN, "%s: The UCS object (%s) was not found. The object was removed." % (function_name, ucs_object['dn'])) return sambaAcctFlags = ucs_object_attributes.get('sambaAcctFlags', [''])[0] if "L" in sambaAcctFlags: ## currently locked again return sambaBadPasswordTime = ucs_object_attributes.get('sambaBadPasswordTime', [''])[0] if sambaBadPasswordTime and sambaBadPasswordTime != "0": ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is unlocked, but sambaBadPasswordTime is set." % (function_name, ucs_object['dn'])) return # Ok here we have: # 1. Account currently not locked in OpenLDAP but in Samba/AD # 2. Lockout state has changed to unlocked at some pickled point in the past modlist.append((ldap.MOD_REPLACE, "lockoutTime", "0")) modlist.append((ldap.MOD_REPLACE, "badPasswordTime", "0")) ud.debug(ud.LDAP, ud.PROCESS, "%s: Marking account as unlocked in Samba/AD" % (function_name,)) else: s4_object_attributes = s4connector.lo_s4.get(compatible_modstring(object['dn']), ['lockoutTime', 'badPasswordTime']) lockoutTime = s4_object_attributes.get('lockoutTime', ['0'])[0] # Now object.get('new_ucs_object') may be a stale pickled state, so let's lookup the current OpenLDAP object state # Unfortunately "object" doesn't hold the current OpenLDAP DN, so we need to map back first ucs_object = s4connector._object_mapping(key, object) try: ucs_object_attributes = s4connector.lo.get(ucs_object['dn'], ['sambaAcctFlags', 'sambaBadPasswordTime'], required=True) except ldap.NO_SUCH_OBJECT: ud.debug(ud.LDAP, ud.WARN, "%s: The UCS object (%s) was not found. The object was removed." % (function_name, ucs_object['dn'])) return sambaAcctFlags = ucs_object_attributes.get('sambaAcctFlags', [''])[0] if "L" not in sambaAcctFlags: ## currently not locked any longer return sambaBadPasswordTime = ucs_object_attributes.get('sambaBadPasswordTime', [''])[0] if not sambaBadPasswordTime: ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is locked, but sambaBadPasswordTime is missing." % (function_name, ucs_object['dn'])) return if sambaBadPasswordTime == "0": ud.debug(ud.LDAP, ud.ERROR, "%s: The UCS object (%s) is locked, but sambaBadPasswordTime is 0." % (function_name, ucs_object['dn'])) return if sambaBadPasswordTime == lockoutTime: ## already locked return # Ok here we have: # 1. Account currently locked in OpenLDAP but not in Samba/AD # 2. Lockout state has changed to locked at some pickled point in the past modlist.append((ldap.MOD_REPLACE, "lockoutTime", sambaBadPasswordTime)) modlist.append((ldap.MOD_REPLACE, "badPasswordTime", sambaBadPasswordTime)) ud.debug(ud.LDAP, ud.PROCESS, "%s: Marking account as locked in Samba/AD" % (function_name,)) ud.debug(ud.LDAP, ud.INFO, "%s: Setting lockoutTime to the value of sambaBadPasswordTime: %s" % (function_name, sambaBadPasswordTime)) if modlist: ud.debug(ud.LDAP, ud.ALL, "%s: modlist: %s" % (function_name, modlist)) s4connector.lo_s4.lo.modify_ext_s(compatible_modstring(object['dn']), modlist)
def delete_attribute(self, dn, key): self.lo.modify_ext_s(s4.compatible_modstring(unicode(dn)), [(ldap.MOD_DELETE, key, None)], serverctrls=self.serverctrls_for_add_and_modify)
def set_attribute(self, dn, key, value): self.lo.modify_s( s4.compatible_modstring(unicode(dn)), [(ldap.MOD_REPLACE, key, s4.compatible_modstring(unicode(value)))])
def remove_from_attribute(self, dn, key, value): self.lo.modify_ext_s( s4.compatible_modstring(unicode(dn)), [(ldap.MOD_DELETE, key, s4.compatible_modstring(unicode(value)))], serverctrls=self.serverctrls_for_add_and_modify)
def set_attribute(self, dn, key, value): self.lo.modify_s (s4.compatible_modstring (unicode (dn)), [(ldap.MOD_REPLACE, key, s4.compatible_modstring (unicode (value)))])