Index: conffiles/etc/univention/s4connector/s4/mapping.py =================================================================== --- conffiles/etc/univention/s4connector/s4/mapping.py (Revision 75940) +++ conffiles/etc/univention/s4connector/s4/mapping.py (Arbeitskopie) @@ -759,6 +759,9 @@ post_ucs_modify_functions=[ univention.s4connector.s4.ntsecurity_descriptor.ntsd_to_ucs, ], + pre_con_modify_functions=[ + univention.s4connector.s4.ntsecurity_descriptor.ntsd_is_unchanged_in_s4, + ], post_con_create_functions = [ univention.s4connector.s4.ntsecurity_descriptor.ntsd_to_s4, ], Index: modules/univention/s4connector/__init__.py =================================================================== --- modules/univention/s4connector/__init__.py (Revision 75940) +++ modules/univention/s4connector/__init__.py (Arbeitskopie) @@ -378,6 +378,7 @@ ucs_create_functions=[], con_create_extenstions=[], post_con_create_functions=[], + pre_con_modify_functions=[], post_con_modify_functions=[], post_ucs_modify_functions=[], post_attributes=None, @@ -417,6 +418,7 @@ self.con_create_extenstions = con_create_extenstions self.post_con_create_functions = post_con_create_functions + self.pre_con_modify_functions = pre_con_modify_functions self.post_con_modify_functions = post_con_modify_functions self.post_ucs_modify_functions = post_ucs_modify_functions @@ -1507,7 +1509,7 @@ except (ldap.SERVER_DOWN, SystemExit): raise except: # FIXME: which exception is to be caught? - self._debug_traceback(ud.ERROR, "failed in post_con_modify_functions") + self._debug_traceback(ud.ERROR, "failed in post_ucs_modify_functions") result = False if result: Index: modules/univention/s4connector/s4/__init__.py =================================================================== --- modules/univention/s4connector/s4/__init__.py (Revision 75940) +++ modules/univention/s4connector/s4/__init__.py (Arbeitskopie) @@ -2595,6 +2595,22 @@ else: ud.debug(ud.LDAP, ud.INFO, "to modify: %s" % object['dn']) ud.debug(ud.LDAP, ud.ALL, "sync_from_ucs: modlist: %s" % modlist) + + if hasattr(self.property[property_type], "pre_con_modify_functions"): + for f in self.property[property_type].pre_con_modify_functions: + ud.debug(ud.LDAP, ud.INFO, "Call pre_con_modify_function: %s" % f) + if not f(self, property_type, object): + ud.debug(ud.LDAP, ud.INFO, "sync_from_ucs: Veto by pre_con_modify_function %s" % f) + ud.debug(ud.LDAP, ud.INFO, "sync_from_ucs: Skipping modify") + + ud.debug(ud.LDAP, ud.INFO, "sync_from_ucs: unlock UCS entryUUID: %s" % entryUUID) + self.lockingdb.unlock_ucs(entryUUID) + + self._check_dn_mapping(pre_mapped_ucs_dn, object['dn']) + return True + ud.debug(ud.LDAP, ud.INFO, "Call pre_con_modify_function: %s (ok)" % f) + + if modlist: try: self.lo_s4.lo.modify_ext_s(compatible_modstring(object['dn']), compatible_modlist(modlist), serverctrls=self.serverctrls_for_add_and_modify) except: Index: modules/univention/s4connector/s4/ntsecurity_descriptor.py =================================================================== --- modules/univention/s4connector/s4/ntsecurity_descriptor.py (Revision 75940) +++ modules/univention/s4connector/s4/ntsecurity_descriptor.py (Arbeitskopie) @@ -72,6 +72,27 @@ domain_sid = security.dom_sid(s4connector.s4_sid) return decode_sd_in_ndr_to_sddl(domain_sid, ntsd_ndr) +# Pre-modify function + +def ntsd_is_unchanged_in_s4(s4connector, key, object): + (s4_dn, s4_attributes) = s4connector.lo_s4.lo.search_s(s4_dn, ldap.SCOPE_BASE, '(objectClass=*)', ['nTSecurityDescriptor', 'uSNChanged', 'objectGUID'])[0] + ntsd_ndr = s4_attributes.get('nTSecurityDescriptor') + if ntsd_ndr: + domain_sid = security.dom_sid(s4connector.s4_sid) + s4_ntsd_sddl = decode_sd_in_ndr_to_sddl(domain_sid, ntsd_ndr[0]) + if s4_ntsd_sddl == ucs_ntsd_sddl: + ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: nTSecurityDescriptors are equal') + return True + + guid_blob = s4_attributes.get('objectGUID')[0] + objectGUID = str(ndr_unpack(misc.GUID, guid_blob)) + old_s4_object = s4connector.s4cache.get_entry(objectGUID) + if old_s4_object: + if old_s4_object.get('uSNChanged')[0] != s4_attributes.get('uSNChanged')[0]: + ud.debug(ud.LDAP, ud.PROCESS, "ntsd_to_s4: skipping, S4-Object changed: %s" % object['dn']) + return False + return True + # Post-create/modify functions @@ -88,7 +109,7 @@ return ucs_ntsd_sddl = object['attributes']['msNTSecurityDescriptor'][0] - (s4_dn, s4_attributes) = s4connector.lo_s4.lo.search_s(s4_dn, ldap.SCOPE_BASE, '(objectClass=*)', ['nTSecurityDescriptor', 'uSNChanged' , 'objectGUID'])[0] + (s4_dn, s4_attributes) = s4connector.lo_s4.lo.search_s(s4_dn, ldap.SCOPE_BASE, '(objectClass=*)', ['nTSecurityDescriptor', 'objectGUID'])[0] ntsd_ndr = s4_attributes.get('nTSecurityDescriptor') if ntsd_ndr: domain_sid = security.dom_sid(s4connector.s4_sid) @@ -97,14 +118,6 @@ ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: nTSecurityDescriptors are equal') return - guid_blob = s4_attributes.get('objectGUID')[0] - objectGUID = str(ndr_unpack(misc.GUID, guid_blob)) - old_s4_object = s4connector.s4cache.get_entry(objectGUID) - if old_s4_object: - if old_s4_object.get('uSNChanged')[0] != s4_attributes.get('uSNChanged')[0]: - ud.debug(ud.LDAP, ud.PROCESS, "ntsd_to_s4: skipping, S4-Object changed: %s" % object['dn']) - return - ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_s4: changing nTSecurityDescriptor from %s to %s' % (s4_ntsd_sddl, ucs_ntsd_sddl)) ucs_ntsd_ndr = encode_sddl_to_sd_in_ndr(domain_sid, ucs_ntsd_sddl)