Index: base/univention-python/debian/changelog =================================================================== --- base/univention-python/debian/changelog (Revision 81009) +++ base/univention-python/debian/changelog (Arbeitskopie) @@ -1,3 +1,10 @@ +univention-python (10.0.4-1) UNRELEASED; urgency=medium + + * Bug 43628: Support lookup of specific attributes via PostReadControl + (RFC 4527) + + -- Arvid Requate Mon, 10 Jul 2017 19:28:18 +0200 + univention-python (10.0.3-4) unstable; urgency=medium * Bug #41234: Revert changes made with Bug #36169 due to fix of Bug #36343 Index: base/univention-python/debian/control =================================================================== --- base/univention-python/debian/control (Revision 81009) +++ base/univention-python/debian/control (Arbeitskopie) @@ -12,6 +12,7 @@ Architecture: all Depends: ${misc:Depends}, ${python:Depends}, python-ldap, + python-pyasn1-modules, python-dns, python-univention-debug, python-cracklib Index: base/univention-python/modules/uldap.py =================================================================== --- base/univention-python/modules/uldap.py (Revision 81009) +++ base/univention-python/modules/uldap.py (Arbeitskopie) @@ -34,6 +34,7 @@ import ldap import ldap.schema import ldap.sasl +from ldap.controls.readentry import PostReadControl import univention.debug from univention.config_registry import ConfigRegistry from ldapurl import LDAPUrl @@ -401,7 +402,7 @@ self.__schema = ldap.schema.SubSchema(self.lo.read_subschemasubentry_s(self.lo.search_subschemasubentry_s()), 0) return self.__schema - def add(self, dn, al): + def add(self, dn, al, postread_attrs=None): """Add LDAP entry with dn and attributes in add_list=(attribute-name, old-values. new-values) or (attribute-name, new-values).""" univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.add dn=%s' % dn) @@ -416,15 +417,39 @@ nal[key] |= set(val) nal = self.__encode_entry([(k, list(v)) for k, v in nal.items()]) + + if postread_attrs: + serverctrls = [PostReadControl(True, postread_attrs),] + return self.add_ext_s(dn, nal, serverctrls=serverctrls) + else: + return self.add_s(dn, nal) + + def add_s(self, dn, al): + """Redirect add_s directly to lo""" try: - self.lo.add_ext_s(dn, nal) + self.lo.add_ext_s(dn, al) except ldap.REFERRAL as exc: if not self.follow_referral: raise lo_ref = self._handle_referral(exc) - lo_ref.add_ext_s(dn, nal) + lo_ref.add_ext_s(dn, al) - def modify(self, dn, changes): + def add_ext_s(self, dn, al, serverctrls=None): + """Redirect add_ext_s directly to lo""" + try: + msgid = self.lo.add_ext(dn, al, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid) + except ldap.REFERRAL as exc: + if not self.follow_referral: + raise + lo_ref = self._handle_referral(exc) + msgid = lo_ref.add_ext(dn, al, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid) + for c in resp_ctrls: + if c.controlType == PostReadControl.controlType: + return c.entry + + def modify(self, dn, changes, postread_attrs=None): """Modify LDAP entry dn with attributes in changes=(attribute-name, old-values, new-values).""" univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.modify %s' % dn) @@ -454,16 +479,32 @@ ml.append((op, key, val)) ml = self.__encode_entry(ml) + if postread_attrs: + serverctrls = [PostReadControl(True, postread_attrs),] + else: + serverctrls = [] + + resp_entry = {} # check if we need to rename the object new_dn, new_rdn = self.__get_new_dn(dn, ml) if not self.compare_dn(dn, new_dn): univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, 'rename %s' % (new_rdn,)) - self.lo.rename_s(dn, new_rdn, None, delold=1) + if postread_attrs: + resp_entry = self.rename_ext_s(dn, new_rdn, None, delold=1, serverctrls=serverctrls) + else: + self.lo.rename_s(dn, new_rdn, None, delold=1) dn = new_dn if ml: - self.modify_s(dn, ml) - return dn + if postread_attrs: + resp_entry = self.modify_ext_s(dn, ml, serverctrls=serverctrls) + else: + self.modify_s(dn, ml) + if postread_attrs: + return (dn, resp_entry) + else: + return dn + @classmethod def __get_new_dn(self, dn, ml): """ @@ -494,31 +535,74 @@ lo_ref = self._handle_referral(exc) lo_ref.modify_ext_s(dn, ml) - def rename(self, dn, newdn): + def modify_ext_s(self, dn, ml, serverctrls=None): + """Redirect modify_ext_s directly to lo""" + try: + msgid = self.lo.modify_ext(dn, ml, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid) + except ldap.REFERRAL as exc: + if not self.follow_referral: + raise + lo_ref = self._handle_referral(exc) + msgid = lo_ref.modify_ext(dn, ml, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid) + for c in resp_ctrls: + if c.controlType == PostReadControl.controlType: + return c.entry + + def rename(self, dn, newdn, postread_attrs=None): univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename %s -> %s' % (dn, newdn)) oldsdn = self.parentDn(dn) newrdn = ldap.dn.dn2str([ldap.dn.str2dn(newdn)[0]]) newsdn = ldap.dn.dn2str(ldap.dn.str2dn(newdn)[1:]) + if postread_attrs: + serverctrls = [PostReadControl(True, postread_attrs),] + else: + serverctrls = [] + + resp_entry = {} if not newsdn.lower() == oldsdn.lower(): univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: move %s to %s in %s' % (dn, newrdn, newsdn)) - try: - self.lo.rename_s(dn, newrdn, newsdn) - except ldap.REFERRAL as exc: - if not self.follow_referral: - raise - lo_ref = self._handle_referral(exc) - lo_ref.rename_s(dn, newrdn, newsdn) + if postread_attrs: + resp_entry = self.rename_ext_s(dn, newrdn, newsdn, serverctrls=serverctrls) + else: + self.rename_s(dn, newrdn, newsdn) else: univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.rename: modrdn %s to %s' % (dn, newrdn)) - try: - self.lo.rename_s(dn, newrdn) - except ldap.REFERRAL as exc: - if not self.follow_referral: - raise - lo_ref = self._handle_referral(exc) - lo_ref.rename_s(dn, newrdn) + if postread_attrs: + resp_entry = self.rename_ext_s(dn, newrdn, serverctrls=serverctrls) + else: + self.rename_s(dn, newrdn) + if postread_attrs: + return resp_entry + + def rename_s(self, dn, newrdn, newsuperior=None): + """Redirect rename_s directly to lo""" + try: + self.lo.rename_s(dn, newrdn, newsuperior) + except ldap.REFERRAL as exc: + if not self.follow_referral: + raise + lo_ref = self._handle_referral(exc) + lo_ref.rename_s(dn, newrdn, newsuperior) + + def rename_ext_s(self, dn, newrdn, newsuperior=None, serverctrls=None): + """Redirect rename_ext_s directly to lo""" + try: + msgid = self.lo.rename(dn, newrdn, newsuperior, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = self.lo.result3(msgid) + except ldap.REFERRAL as exc: + if not self.follow_referral: + raise + lo_ref = self._handle_referral(exc) + lo_ref.rename(dn, newrdn, newsuperior, serverctrls=serverctrls) + rtype, rdata, rmsgid, resp_ctrls = lo_ref.result3(msgid) + for c in resp_ctrls: + if c.controlType == PostReadControl.controlType: + return c.entry + def delete(self, dn): univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.delete %s' % dn) if dn: Index: management/univention-directory-manager-modules/debian/changelog =================================================================== --- management/univention-directory-manager-modules/debian/changelog (Revision 81009) +++ management/univention-directory-manager-modules/debian/changelog (Arbeitskopie) @@ -1,3 +1,10 @@ +univention-directory-manager-modules (12.0.18-1) UNRELEASED; urgency=medium + + * Bug 43628: Support lookup of specific attributes via PostReadControl + (RFC 4527) + + -- Arvid Requate Mon, 10 Jul 2017 19:32:17 +0200 + univention-directory-manager-modules (12.0.17-74) unstable; urgency=medium * Bug #42015: Applied patch from Florian Best - Fix LDAP error when Index: management/univention-directory-manager-modules/debian/control =================================================================== --- management/univention-directory-manager-modules/debian/control (Revision 81009) +++ management/univention-directory-manager-modules/debian/control (Arbeitskopie) @@ -14,7 +14,7 @@ Architecture: all Depends: ${misc:Depends}, ${python:Depends}, python (>= 2.7), - python-univention (>> 6.0.21), + python-univention (>= 10.0.4-1), python-univention-heimdal (>= 4.0.1-1), makepasswd, python-m2crypto, Index: management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py =================================================================== --- management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py (Revision 81009) +++ management/univention-directory-manager-modules/modules/univention/admin/handlers/__init__.py (Arbeitskopie) @@ -108,6 +108,8 @@ self.options = [] self.old_options = [] self.alloc = [] + self.postread_attrs = None + self.resp_entry = {} if not isinstance(self.lo, univention.admin.uldap.access): if not isinstance(self.lo, univention.uldap.access): @@ -672,6 +674,22 @@ self.call_udm_property_hook('hook_open', self) self.save() + def create(self, postread_attrs=None): + if postread_attrs: + self.postread_attrs = postread_attrs + res = base.create(self) + if self.postread_attrs: + self.oldattr.update(self.resp_entry) + return res + + def modify(self, modify_childs=1, ignore_license=0, postread_attrs=None): + if postread_attrs: + self.postread_attrs = postread_attrs + res = base.modify(self, modify_childs=1, ignore_license=0) + if self.postread_attrs: + self.oldattr.update(self.resp_entry) + return res + def _remove_option(self, name): if name in self.options: self.options.remove(name) @@ -781,7 +799,10 @@ # if anything goes wrong we need to remove the already created object, otherwise we run into 'already exists' errors try: - self.lo.add(self.dn, al) + if self.postread_attrs: + self.resp_entry = self.lo.add(self.dn, al, postread_attrs=self.postread_attrs) + else: + self.lo.add(self.dn, al) self._exists = True self._ldap_post_create() except: @@ -826,13 +847,19 @@ # FIXME: timeout without exception if objectClass of Object is not exsistant !! univention.debug.debug(univention.debug.ADMIN, 99, 'Modify dn=%r;\nmodlist=%r;\noldattr=%r;' % (self.dn, ml, self.oldattr)) - self.lo.modify(self.dn, ml, ignore_license=ignore_license) + if self.postread_attrs: + dn, self.resp_entry = self.lo.modify(self.dn, ml, ignore_license=ignore_license, postread_attrs=self.postread_attrs) + else: + self.lo.modify(self.dn, ml, ignore_license=ignore_license) self._ldap_post_modify() self.call_udm_property_hook('hook_ldap_post_modify', self) self.save() - return self.dn + if self.postread_attrs: + return (dn, self.resp_entry) + else: + return self.dn def set_default_values(self): # Make sure all default values are set... Index: management/univention-directory-manager-modules/modules/univention/admin/uldap.py =================================================================== --- management/univention-directory-manager-modules/modules/univention/admin/uldap.py (Revision 81009) +++ management/univention-directory-manager-modules/modules/univention/admin/uldap.py (Arbeitskopie) @@ -458,7 +458,7 @@ univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'getPolicies modules dn %s result' % dn) return self.lo.getPolicies(dn, policies, attrs, result, fixedattrs) - def add(self, dn, al, exceptions=False): + def add(self, dn, al, exceptions=False, postread_attrs=None): self._validateLicense() if not self.allow_modify: univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'add dn: %s' % dn) @@ -466,9 +466,9 @@ return [] univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s al=%s' % (dn, al)) if exceptions: - return self.lo.add(dn, al) + return self.lo.add(dn, al, postread_attrs=postread_attrs) try: - return self.lo.add(dn, al) + return self.lo.add(dn, al, postread_attrs=postread_attrs) except ldap.ALREADY_EXISTS as msg: univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg)) raise univention.admin.uexceptions.objectExists(dn) @@ -481,7 +481,7 @@ univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'add dn=%s err=%s' % (dn, msg)) raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg) - def modify(self, dn, changes, exceptions=False, ignore_license=0): + def modify(self, dn, changes, exceptions=False, ignore_license=0, postread_attrs=None): self._validateLicense() if not self.allow_modify and not ignore_license: univention.debug.debug(univention.debug.ADMIN, univention.debug.ERROR, 'modify dn: %s' % dn) @@ -489,9 +489,9 @@ return [] univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s ml=%s' % (dn, changes)) if exceptions: - return self.lo.modify(dn, changes) + return self.lo.modify(dn, changes, postread_attrs=postread_attrs) try: - return self.lo.modify(dn, changes) + return self.lo.modify(dn, changes, postread_attrs=postread_attrs) except ldap.NO_SUCH_OBJECT as msg: univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg)) raise univention.admin.uexceptions.noObject(dn) @@ -504,7 +504,7 @@ univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'mod dn=%s err=%s' % (dn, msg)) raise univention.admin.uexceptions.ldapError(_err2str(msg), original_exception=msg) - def rename(self, dn, newdn, move_childs=0, ignore_license=False): + def rename(self, dn, newdn, move_childs=0, ignore_license=False, postread_attrs=None): if not move_childs == 0: raise univention.admin.uexceptions.noObject(_("Moving children is not supported.")) self._validateLicense() @@ -514,7 +514,7 @@ return [] univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s newdn=%s' % (dn, newdn)) try: - return self.lo.rename(dn, newdn) + return self.lo.rename(dn, newdn, postread_attrs=postread_attrs) except ldap.NO_SUCH_OBJECT as msg: univention.debug.debug(univention.debug.LDAP, univention.debug.ALL, 'ren dn=%s err=%s' % (dn, msg)) raise univention.admin.uexceptions.noObject(dn) Index: services/univention-s4-connector/debian/changelog =================================================================== --- services/univention-s4-connector/debian/changelog (Revision 81009) +++ services/univention-s4-connector/debian/changelog (Arbeitskopie) @@ -1,3 +1,10 @@ +univention-s4-connector (11.0.8-1) UNRELEASED; urgency=medium + + * Bug 43628: during sync_to_ucs remember entryCSN of msGPO changes + to be able to identify and skip them later in sync_from_ucs. + + -- Arvid Requate Mon, 10 Jul 2017 19:33:24 +0200 + univention-s4-connector (11.0.7-12) unstable; urgency=medium * Bug #43072: s4connector/dns: fix ptr_record deletion. Index: services/univention-s4-connector/debian/control =================================================================== --- services/univention-s4-connector/debian/control (Revision 81009) +++ services/univention-s4-connector/debian/control (Arbeitskopie) @@ -16,7 +16,7 @@ python-univention (>=8.0.3-1), python-univention-license, python-univention-heimdal (>= 4.0.2-2), - python-univention-directory-manager (>= 7.0.232-2), + python-univention-directory-manager (>= 12.0.18-1), python-pysqlite2 Provides: ${python:Provides} Description: UCS - Modules for connector sychronisation Index: services/univention-s4-connector/modules/univention/s4connector/__init__.py =================================================================== --- services/univention-s4-connector/modules/univention/s4connector/__init__.py (Revision 81009) +++ services/univention-s4-connector/modules/univention/s4connector/__init__.py (Arbeitskopie) @@ -482,7 +482,7 @@ self.open_ucs() - for section in ['DN Mapping UCS', 'DN Mapping CON', 'UCS rejected', 'UCS deleted']: + for section in ['DN Mapping UCS', 'DN Mapping CON', 'UCS rejected', 'UCS deleted', 'UCS entryCSN']: if not self.config.has_section(section): self.config.add_section(section) @@ -623,6 +623,41 @@ if ucs: self._remove_config_option('DN Mapping UCS', self._encode_dn_as_config_option(ucs.lower())) + def _remember_entryCSN_commited_by_connector(self, entryUUID, entryCSN): + """Remember the entryCSN of a change committed by the S4-Connector itself""" + _d = ud.function('ldap._remember_entryCSN_commited_by_connector') + value = self._get_config_option('UCS entryCSN', entryUUID) + if value: + entryCSN_set = set(value.split(',')) + entryCSN_set.add(entryCSN) + value = ','.join(entryCSN_set) + else: + value = entryCSN + self._set_config_option('UCS entryCSN', entryUUID, value) + + def _get_last_entryCSN_commited_by_connector(self, entryUUID): + """Remember the entryCSN of a change committed by the S4-Connector itself""" + _d = ud.function('ldap._get_last_entryCSN_commited_by_connector') + return self._get_config_option('UCS entryCSN', entryUUID) + + def _forget_entryCSN(self, entryUUID, entryCSN): + _d = ud.function('ldap._forget_entryCSN') + value = self._get_config_option('UCS entryCSN', entryUUID) + if value: + entryCSN_set = set(value.split(',')) + if entryCSN in entryCSN_set: + entryCSN_set.remove(entryCSN) + if entryCSN_set: + value = ','.join(entryCSN_set) + self._set_config_option('UCS entryCSN', entryUUID, value) + else: + self._remove_config_option('UCS entryCSN', entryUUID) + return True + else: + return False + else: + return False + def _get_dn_by_ucs(self, dn_ucs): _d = ud.function('ldap._get_dn_by_ucs') return self._decode_dn_from_config_option(self._get_config_option('DN Mapping UCS', self._encode_dn_as_config_option(dn_ucs.lower()))) @@ -766,6 +801,12 @@ break entryUUID = new.get('entryUUID', [None])[0] + if key == 'msGPO': + entryCSN = new.get('entryCSN', [None])[0] + if self._forget_entryCSN(entryUUID, entryCSN): + ud.debug(ud.LDAP, ud.PROCESS, "__sync_file_from_ucs: Object with entryUUID %s: Ignoring own change %s" % (entryUUID, entryCSN)) + return True + if entryUUID: if self.was_entryUUID_deleted(entryUUID): if self._get_entryUUID(dn) == entryUUID: @@ -1222,7 +1263,7 @@ else: ud.debug(ud.LDAP, ud.INFO, '__set_values: Skip: %s' % con_attribute) - def __modify_custom_attributes(self, property_type, object, ucs_object, module, position, modtype="modify"): + def __modify_custom_attributes(self, property_type, object, ucs_object, module, position, modtype="modify", postread_attrs=None): if 'custom_attributes' in object: ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: custom attributes found: %s' % object['custom_attributes']) modlist = object['custom_attributes']['modlist'] @@ -1245,7 +1286,17 @@ modlist.append(('objectClass', oc[0][1]['objectClass'], noc)) ud.debug(ud.LDAP, ud.INFO, '__modify_custom_attributes: modlist: %s' % modlist) - self.lo.modify(ucs_object.dn, modlist) + if postread_attrs: + resp = self.lo.modify(ucs_object.dn, modlist, postread_attrs=postread_attrs) + try: + resp_entry = resp[1] + entryUUID = resp_entry['entryUUID'][0] + entryCSN = resp_entry['entryCSN'][0] + self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN) + except (IndexError, KeyError): + pass + else: + self.lo.modify(ucs_object.dn, modlist) return True else: @@ -1264,7 +1315,16 @@ self.__set_values(property_type, object, ucs_object, modtype='add') for function in self.property[property_type].ucs_create_functions: function(self, property_type, ucs_object) - return ucs_object.create() and self.__modify_custom_attributes(property_type, object, ucs_object, module, position) + if property_type == 'msGPO': + res = ucs_object.create(postread_attrs=['entryCSN', 'entryUUID']) + if res: + entryUUID = ucs_object.oldattr['entryUUID'][0] + entryCSN = ucs_object.oldattr['entryCSN'][0] + self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN) + res = self.__modify_custom_attributes(property_type, object, ucs_object, module, position, postread_attrs=['entryCSN', 'entryUUID']) + else: + res = ucs_object.create() + return res def modify_in_ucs(self, property_type, object, module, position): _d = ud.function('ldap.modify_in_ucs') @@ -1278,7 +1338,19 @@ ucs_object_dn = object[dntype] ucs_object = univention.admin.objects.get(module, None, self.lo, dn=ucs_object_dn, position='') self.__set_values(property_type, object, ucs_object) - return ucs_object.modify() and self.__modify_custom_attributes(property_type, object, ucs_object, module, position) + if property_type == 'msGPO': + res = ucs_object.modify(postread_attrs=['entryCSN', 'entryUUID']) + if res: + try: + entryUUID = ucs_object.oldattr['entryUUID'][0] + entryCSN = ucs_object.oldattr['entryCSN'][0] + self._remember_entryCSN_commited_by_connector(entryUUID, entryCSN) + except (IndexError, KeyError): + pass + res = self.__modify_custom_attributes(property_type, object, ucs_object, module, position, postread_attrs=['entryCSN', 'entryUUID']) + else: + res = ucs_object.modify() + return res def move_in_ucs(self, property_type, object, module, position): _d = ud.function('ldap.move_in_ucs') @@ -1363,6 +1435,8 @@ ucs_object.open() ucs_object.remove() self.update_deleted_cache_after_removal(entryUUID, objectGUID) + if property_type == 'msGPO': + self._forget_entryCSN(entryUUID) return True except Exception, e: ud.debug(ud.LDAP, ud.INFO, "delete object exception: %s" % e) Index: services/univention-s4-connector/modules/univention/s4connector/s4/ntsecurity_descriptor.py =================================================================== --- services/univention-s4-connector/modules/univention/s4connector/s4/ntsecurity_descriptor.py (Revision 81009) +++ services/univention-s4-connector/modules/univention/s4connector/s4/ntsecurity_descriptor.py (Arbeitskopie) @@ -36,7 +36,6 @@ import univention.debug2 as ud from samba.dcerpc import security from samba.ndr import ndr_pack, ndr_unpack -from samba.dcerpc import misc def encode_sddl_to_sd_in_ndr(domain_sid, ntsd_sddl): @@ -88,7 +87,7 @@ return ucs_ntsd_sddl = object['attributes']['msNTSecurityDescriptor'][0] - s4_attributes = s4connector.lo_s4.get(s4_dn, attr=['nTSecurityDescriptor', 'uSNChanged', 'objectGUID']) + s4_attributes = s4connector.lo_s4.get(s4_dn, attr=['nTSecurityDescriptor']) ntsd_ndr = s4_attributes.get('nTSecurityDescriptor') if ntsd_ndr: @@ -98,14 +97,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) @@ -153,4 +144,11 @@ ml.append(('msNTSecurityDescriptor', ucs_ntsd_sddl, s4_ntsd_sddl)) if ml: ud.debug(ud.LDAP, ud.INFO, 'ntsd_to_ucs: modlist = %s' % ml) - s4connector.lo.lo.modify(ucs_dn, ml) + resp = s4connector.lo.lo.modify(ucs_dn, ml, postread_attrs=['entryCSN', 'entryUUID']) + try: + resp_entry = resp[1] + entryUUID = resp_entry['entryUUID'][0] + entryCSN = resp_entry['entryCSN'][0] + s4connector._remember_entryCSN_commited_by_connector(entryUUID, entryCSN) + except (IndexError, KeyError): + pass