The branch, v4-8-test has been updated via 994c6c6 dsdb: Add comments explaining the limitations of our current backlink behaviour via 98db8eb s4:samldb: internally use extended dns while changing the primaryGroupID field via 47745ae s4:repl_meta_data: add support for DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID via 1412854 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_replace() via b23722a s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_delete() via 07a4891 s4:repl_meta_data: add missing to a DEBUG message in replmd_modify_la_add() via 4564174 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_add() via f7ec404 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_handle_linked_attribs() via 5d562c1 blackbox/dbcheck-links: Test broken links with missing <SID=...> on linked attributes via b90f5a9 dbchecker: Fix missing <SID=...> on linked attributes via dffea1b dbchecker: improve verbose output of do_modify() via 997a3b2 s4:dsdb: add DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID oid via f3aed1e testprogs/blackbox: add samba4.blackbox.test_primary_group test via 933d5f3 s4:dsdb: fix comment on DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME via e02b0bc schema_samba4.ldif: add allocation of DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME via 4154d31 dbchecker: Fixing up incorrect DNs wasn't working via d8c9c93 dbcheck: Use symbolic control name for DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS from 3587cca vfs_fruit: optionally delete AppleDouble files without Resourcefork data
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-8-test - Log ----------------------------------------------------------------- commit 994c6c6f4fe164084c496bcdca2b776138bba43a Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 30 15:56:43 2018 +1300 dsdb: Add comments explaining the limitations of our current backlink behaviour BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Tim Beale <timbe...@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Oct 30 10:32:51 CET 2018 on sn-devel-144 (cherry picked from commit 852e1db12b0afa04a738c03bb2609c084fe96a7f) Autobuild-User(v4-8-test): Karolin Seeger <ksee...@samba.org> Autobuild-Date(v4-8-test): Mon Nov 5 14:28:49 CET 2018 on sn-devel-144 commit 98db8eb90c25a3f8d748cbb55ff3732fe5eb68b9 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Aug 24 15:33:49 2018 +0200 s4:samldb: internally use extended dns while changing the primaryGroupID field This is important, otherwise we'll loose the <SID=> component of the linked attribute. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 7a36cb30b716d56b84e894851c1a18e9eb3a0964) commit 47745ae56288b836c73516dedb33edc5e324b8dc Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 15:56:18 2018 +0200 s4:repl_meta_data: add support for DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID This will be used by dbcheck in the next commits. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 0386307e34097f5d9233c970983c7306d1705a87) commit 141285407df6cd23ac20ce5eb352983e81ce0969 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 18:43:25 2018 +0200 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_replace() This will simplify further changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 1ef145d9d72d847055f6aba8a0070b3e1cfdabbc) commit b23722a7f6023f1ac1ce39cc2e764605a940d356 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 18:43:25 2018 +0200 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_delete() This will simplify further changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 738b52eb0856c8fcdbb8589e8061bcc14700c23a) commit 07a48914d2a4c814f3237d39eb3976dd8f1bd6f6 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 19:34:08 2018 +0200 s4:repl_meta_data: add missing \n to a DEBUG message in replmd_modify_la_add() BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 70a306d0bd6806d1fd00d45e3d8cc70c73d09f79) commit 45641745dd5d93d8b8d3403de34185c3afc70d9f Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 18:43:25 2018 +0200 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_la_add() This will simplify further changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 42e69a86ca583e3cb20c63b9c6930b4b3425485d) commit f7ec40472d680207d0f60f4159927003417bd24e Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 18:43:25 2018 +0200 s4:repl_meta_data: pass down struct replmd_replicated_request to replmd_modify_handle_linked_attribs() This will simplify further changes. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 966c7febaf0245516481bde924ea6cd738eeb78b) commit 5d562c1a0f60f6d14203cffca0d4f345b1389900 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 15:56:18 2018 +0200 blackbox/dbcheck-links: Test broken links with missing <SID=...> on linked attributes BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit f81771c8593327e058b9cb4330d7e77083df3ea9) commit b90f5a98cd47c36f559cf5386035948f5f03657b Author: Stefan Metzmacher <me...@samba.org> Date: Fri Oct 12 15:56:18 2018 +0200 dbchecker: Fix missing <SID=...> on linked attributes BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit a801799ebe26780653f4ed3fa3fc633e31871f7d) commit dffea1b1c32973f53d12a89b58ae6de7211ad09f Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 8 17:14:28 2018 +0200 dbchecker: improve verbose output of do_modify() This makes it easier to debug dbcheck problems. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit c5c99b569569ce36cac94e967ca53e3182abd6f7) commit 997a3b23b96e6f3a399cd41ac956ce41ea6971f8 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 8 17:13:52 2018 +0200 s4:dsdb: add DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID oid This will be used to fix missing <SID=> components in future. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit bb9c9e49a5e82f19626cb1b12ec9189fff5114e8) commit f3aed1e7f19f7a9c34df832fb60759867ab6088d Author: Stefan Metzmacher <me...@samba.org> Date: Tue Oct 16 15:16:18 2018 +0200 testprogs/blackbox: add samba4.blackbox.test_primary_group test This demonstrates the bug, that happens when the primaryGroupID of a user is changed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13418 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 364ed537e0bcb3a97cae0f2d1ff72de9423ce0e6) commit 933d5f375d82831306013744c56c42331249000d Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 8 17:13:13 2018 +0200 s4:dsdb: fix comment on DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 60131b4452d43b3792e7f27a4190c88e7aabb1b4) commit e02b0bcb8c8f72459f2ca9a0e5094a1b6fe231e8 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Oct 8 15:35:52 2018 +0200 schema_samba4.ldif: add allocation of DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME This was already allocated in source4/dsdb/samdb/samdb.h with commit 22208f52e6096fbe9413b8ff339d9446851e0874. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 0189f23f5bda263c7462366ee16b2fe4bcda0119) commit 4154d31eeb47ced6f7163f65766a2d7b89c87486 Author: Tim Beale <timbe...@catalyst.net.nz> Date: Fri May 25 14:05:27 2018 +1200 dbchecker: Fixing up incorrect DNs wasn't working dbcheck would fail to fix up attributes where the extended DN's GUID is correct, but the DN itself is incorrect. The code failed attempting to remove the old/incorrect DN, e.g. NOTE: old (due to rename or delete) DN string component for objectCategory in object CN=alice,CN=Users,DC=samba,DC=example,DC=com - <GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>; CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=bad,DC=com Change DN to <GUID=7bfdf9d8-62f9-420c-8a71-e3d3e931c91e>; CN=Person,CN=Schema,CN=Configuration,DC=samba,DC=example,DC=com? [y/N/all/none] y Failed to fix old DN string on attribute objectCategory : (16, "attribute 'objectCategory': no matching attribute value while deleting attribute on 'CN=alice,CN=Users,DC=samba,DC=example,DC=com'") The problem was the LDB message specified the value to delete with its full DN, including the GUID. The LDB code then helpfully corrected this value on the way through, so that the DN got updated to reflect the correct DN (i.e. 'DC=example,DC=com') of the object matching that GUID, rather than the incorrect DN (i.e. 'DC=bad,DC=com') that we were trying to remove. Because the requested value and the existing DB value didn't match, the operation failed. We can avoid this problem by passing down just the DN (not the extended DN) of the value we want to delete. Without the GUID portion of the DN, the LDB code will no longer try to correct it on the way through, and the dbcheck operation will succeed. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13495 Signed-off-by: Tim Beale <timbe...@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> Pair-programmed-with: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 22208f52e6096fbe9413b8ff339d9446851e0874) commit d8c9c93c90b70455ad39ae4acd78a8f71c290fb7 Author: Andrew Bartlett <abart...@samba.org> Date: Fri Jun 29 14:53:19 2018 +1200 dbcheck: Use symbolic control name for DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS While we do not wish to encourage use of this control, manually typed OIDs are even more trouble, so pass out via pydsdb. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Gary Lockyer <g...@catalyst.net.nz> (cherry picked from commit c7fd68088d84232a2f4074ca278b5448ef624afd) ----------------------------------------------------------------------- Summary of changes: python/samba/dbchecker.py | 66 +++- source4/dsdb/pydsdb.c | 3 + source4/dsdb/samdb/ldb_modules/extended_dn_store.c | 7 + source4/dsdb/samdb/ldb_modules/linked_attributes.c | 18 +- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 333 ++++++++++++++++----- source4/dsdb/samdb/ldb_modules/samldb.c | 41 ++- source4/dsdb/samdb/samdb.h | 6 + ...ected-after-dbcheck-oneway-link-corruption.ldif | 19 ++ ...eck-link-output-missing-link-sid-corruption.txt | 8 + ...-dbcheck-link-output-oneway-link-corruption.txt | 5 + source4/selftest/tests.py | 2 + source4/setup/schema_samba4.ldif | 2 + testprogs/blackbox/dbcheck-links.sh | 175 +++++++++++ testprogs/blackbox/test_primary_group.sh | 90 ++++++ 14 files changed, 687 insertions(+), 88 deletions(-) create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-after-dbcheck-oneway-link-corruption.ldif create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-missing-link-sid-corruption.txt create mode 100644 source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-oneway-link-corruption.txt create mode 100755 testprogs/blackbox/test_primary_group.sh Changeset truncated at 500 lines: diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index b2b8b0c..2619b9b 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -59,6 +59,7 @@ class dbcheck(object): self.fix_all_string_dn_component_mismatch = False self.fix_all_GUID_dn_component_mismatch = False self.fix_all_SID_dn_component_mismatch = False + self.fix_all_SID_dn_component_missing = False self.fix_all_old_dn_string_component_mismatch = False self.fix_all_metadata = False self.fix_time_metadata = False @@ -378,10 +379,11 @@ systemFlags: -1946157056%s""" % (dn, guid_suffix), def do_modify(self, m, controls, msg, validate=True): '''perform a modify with optional verbose output''' + controls = controls + ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK] if self.verbose: self.report(self.samdb.write_ldif(m, ldb.CHANGETYPE_MODIFY)) + self.report("controls: %r" % controls) try: - controls = controls + ["local_oid:%s:0" % dsdb.DSDB_CONTROL_DBCHECK] self.samdb.modify(m, controls=controls, validate=validate) except Exception, err: if self.in_transaction: @@ -650,7 +652,8 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) m.dn = dn m['old_value'] = ldb.MessageElement(val, ldb.FLAG_MOD_DELETE, attrname) m['new_value'] = ldb.MessageElement(str(dsdb_dn), ldb.FLAG_MOD_ADD, attrname) - if self.do_modify(m, ["show_recycled:1"], + if self.do_modify(m, ["show_recycled:1", + "local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME], "Failed to fix old DN string on attribute %s" % (attrname)): self.report("Fixed old DN string on attribute %s" % (attrname)) @@ -671,6 +674,38 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) "Failed to fix incorrect DN %s on attribute %s" % (mismatch_type, attrname)): self.report("Fixed incorrect DN %s on attribute %s" % (mismatch_type, attrname)) + def err_dn_component_missing_target_sid(self, dn, attrname, val, dsdb_dn, target_sid_blob): + """handle a DN string being incorrect""" + self.report("ERROR: missing DN SID component for %s in object %s - %s" % (attrname, dn, val)) + + if len(dsdb_dn.prefix) != 0: + self.report("Not fixing missing DN SID on DN+BINARY or DN+STRING") + return + + correct_dn = ldb.Dn(self.samdb, dsdb_dn.dn.extended_str()) + correct_dn.set_extended_component("SID", target_sid_blob) + + if not self.confirm_all('Change DN to %s?' % correct_dn.extended_str(), + 'fix_all_SID_dn_component_missing'): + self.report("Not fixing missing DN SID component") + return + + target_guid_blob = correct_dn.get_extended_component("GUID") + guid_sid_dn = ldb.Dn(self.samdb, "") + guid_sid_dn.set_extended_component("GUID", target_guid_blob) + guid_sid_dn.set_extended_component("SID", target_sid_blob) + + m = ldb.Message() + m.dn = dn + m['new_value'] = ldb.MessageElement(guid_sid_dn.extended_str(), ldb.FLAG_MOD_ADD, attrname) + controls = [ + "show_recycled:1", + "local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID + ] + if self.do_modify(m, controls, + "Failed to ADD missing DN SID on attribute %s" % (attrname)): + self.report("Fixed missing DN SID on attribute %s" % (attrname)) + def err_unknown_attribute(self, obj, attrname): '''handle an unknown attribute error''' self.report("ERROR: unknown attribute '%s' in %s" % (attrname, obj.dn)) @@ -759,7 +794,7 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) m = ldb.Message() m.dn = obj.dn m['value'] = ldb.MessageElement(forward_vals, ldb.FLAG_MOD_REPLACE, forward_attr) - if self.do_modify(m, ["local_oid:1.3.6.1.4.1.7165.4.3.19.2:1"], + if self.do_modify(m, ["local_oid:%s:1" % dsdb.DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS], "Failed to fix duplicate links in attribute '%s'" % forward_attr): self.report("Fixed duplicate links in attribute '%s'" % (forward_attr)) duplicate_cache_key = "%s:%s" % (str(obj.dn), forward_attr) @@ -1283,20 +1318,35 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) res[0].dn, "GUID") continue - if res[0].dn.get_extended_component("SID") != dsdb_dn.dn.get_extended_component("SID"): + target_sid = res[0].dn.get_extended_component("SID") + link_sid = dsdb_dn.dn.get_extended_component("SID") + if link_sid is None and target_sid is not None: + error_count += 1 + self.err_dn_component_missing_target_sid(obj.dn, attrname, val, + dsdb_dn, target_sid) + continue + if link_sid != target_sid: error_count += 1 self.err_dn_component_target_mismatch(obj.dn, attrname, val, dsdb_dn, res[0].dn, "SID") continue + # Only for non-links, not even forward-only links + # (otherwise this breaks repl_meta_data): + # # Now we have checked the GUID and SID, offer to fix old - # DN strings as a non-error (for forward links with no + # DN strings as a non-error (DNs, not links so no # backlink). Samba does not maintain this string # otherwise, so we don't increment error_count. if reverse_link_name is None: - if str(res[0].dn) != str(dsdb_dn.dn): - self.err_dn_string_component_old(obj.dn, attrname, val, dsdb_dn, - res[0].dn) + if linkID == 0 and str(res[0].dn) != str(dsdb_dn.dn): + # Pass in the old/bad DN without the <GUID=...> part, + # otherwise the LDB code will correct it on the way through + # (Note: we still want to preserve the DSDB DN prefix in the + # case of binary DNs) + bad_dn = dsdb_dn.prefix + dsdb_dn.dn.get_linearized() + self.err_dn_string_component_old(obj.dn, attrname, bad_dn, + dsdb_dn, res[0].dn) continue # check the reverse_link is correct if there should be one diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c index 8cf3ef5..7f25f75 100644 --- a/source4/dsdb/pydsdb.c +++ b/source4/dsdb/pydsdb.c @@ -1569,6 +1569,9 @@ void initdsdb(void) ADD_DSDB_STRING(DSDB_SYNTAX_OR_NAME); ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK); ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_MODIFY_RO_REPLICA); + ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_DUPLICATE_LINKS); + ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_NAME); + ADD_DSDB_STRING(DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID); ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS); ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID); ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID); diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c index a32ab8d..8e5a2ba 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_store.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_store.c @@ -376,6 +376,7 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req unsigned int i, j; struct extended_dn_context *ac; struct ldb_control *fix_links_control = NULL; + struct ldb_control *fix_link_sid_ctrl = NULL; int ret; if (ldb_dn_is_special(req->op.mod.message->dn)) { @@ -400,6 +401,12 @@ static int extended_dn_modify(struct ldb_module *module, struct ldb_request *req return ldb_next_request(module, req); } + fix_link_sid_ctrl = ldb_request_get_control(ac->req, + DSDB_CONTROL_DBCHECK_FIX_LINK_DN_SID); + if (fix_link_sid_ctrl != NULL) { + return ldb_next_request(module, req); + } + for (i=0; i < req->op.mod.message->num_elements; i++) { const struct ldb_message_element *el = &req->op.mod.message->elements[i]; const struct dsdb_attribute *schema_attr diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c index c6beb25..c3f1a14 100644 --- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c +++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c @@ -25,7 +25,23 @@ * * Component: ldb linked_attributes module * - * Description: Module to ensure linked attribute pairs remain in sync + * Description: Module to ensure linked attribute pairs (i.e. forward-links + * and backlinks) remain in sync. + * + * Backlinks are 'plain' links (without extra metadata). When the link target + * object is modified (e.g. renamed), we use the backlinks to keep the link + * source object updated. Note there are some cases where we can't do this: + * - one-way links, which don't have a corresponding backlink + * - two-way deactivated links, i.e. when a user is removed from a group, + * the forward 'member' link still exists (but is inactive), however, the + * 'memberOf' backlink is deleted. + * In these cases, we can end up with a dangling forward link which is + * incorrect (i.e. the target has been renamed or deleted). We have dbcheck + * rules to detect and fix this, and cope otherwise by filtering at runtime + * (i.e. in the extended_dn module). + * + * See also repl_meta_data.c, which handles updating links for deleted + * objects, as well as link changes received from another DC. * * Author: Andrew Bartlett */ diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 62f58ad..c2eafd0 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -112,6 +112,8 @@ struct replmd_replicated_request { bool is_urgent; bool isDeleted; + + bool fix_link_sid; }; static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar); @@ -2398,12 +2400,11 @@ static int replmd_update_la_val(TALLOC_CTX *mem_ctx, struct ldb_val *v, struct d */ static int replmd_modify_la_add(struct ldb_module *module, struct replmd_private *replmd_private, - const struct dsdb_schema *schema, + struct replmd_replicated_request *ac, struct ldb_message *msg, struct ldb_message_element *el, struct ldb_message_element *old_el, const struct dsdb_attribute *schema_attr, - uint64_t seq_num, time_t t, struct ldb_dn *msg_dn, struct ldb_request *parent) @@ -2416,17 +2417,10 @@ static int replmd_modify_la_add(struct ldb_module *module, unsigned old_num_values = old_el ? old_el->num_values : 0; unsigned num_values = 0; unsigned max_num_values; - const struct GUID *invocation_id; struct ldb_context *ldb = ldb_module_get_ctx(module); NTTIME now; unix_to_nt_time(&now, t); - invocation_id = samdb_ntds_invocation_id(ldb); - if (!invocation_id) { - talloc_free(tmp_ctx); - return LDB_ERR_OPERATIONS_ERROR; - } - /* get the DNs to be added, fully parsed. * * We need full parsing because they came off the wire and we don't @@ -2453,7 +2447,7 @@ static int replmd_modify_la_add(struct ldb_module *module, max_num_values = old_num_values + el->num_values; if (max_num_values < old_num_values) { DEBUG(0, ("we seem to have overflow in replmd_modify_la_add. " - "old values: %u, new values: %u, sum: %u", + "old values: %u, new values: %u, sum: %u\n", old_num_values, el->num_values, max_num_values)); talloc_free(tmp_ctx); return LDB_ERR_OPERATIONS_ERROR; @@ -2489,6 +2483,109 @@ static int replmd_modify_la_add(struct ldb_module *module, return err; } + if (ac->fix_link_sid) { + char *fixed_dnstring = NULL; + struct dom_sid tmp_sid = { 0, }; + DATA_BLOB sid_blob = data_blob_null; + enum ndr_err_code ndr_err; + NTSTATUS status; + int num; + + if (exact == NULL) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + if (dns[i].dsdb_dn->dn_format != DSDB_NORMAL_DN) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + /* + * Only "<GUID=...><SID=...>" is allowed. + * + * We get the GUID to just to find the old + * value and the SID in order to add it + * to the found value. + */ + + num = ldb_dn_get_comp_num(dns[i].dsdb_dn->dn); + if (num != 0) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + num = ldb_dn_get_extended_comp_num(dns[i].dsdb_dn->dn); + if (num != 2) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + status = dsdb_get_extended_dn_sid(exact->dsdb_dn->dn, + &tmp_sid, "SID"); + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + /* this is what we expect */ + } else if (NT_STATUS_IS_OK(status)) { + struct GUID_txt_buf guid_str; + ldb_debug_set(ldb, LDB_DEBUG_FATAL, + "i[%u] SID NOT MISSING... Attribute %s already " + "exists for target GUID %s, SID %s, DN: %s", + i, el->name, + GUID_buf_string(&exact->guid, + &guid_str), + dom_sid_string(tmp_ctx, &tmp_sid), + dsdb_dn_get_extended_linearized(tmp_ctx, + exact->dsdb_dn, 1)); + talloc_free(tmp_ctx); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } else { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + status = dsdb_get_extended_dn_sid(dns[i].dsdb_dn->dn, + &tmp_sid, "SID"); + if (!NT_STATUS_IS_OK(status)) { + struct GUID_txt_buf guid_str; + ldb_asprintf_errstring(ldb, + "NO SID PROVIDED... Attribute %s already " + "exists for target GUID %s", + el->name, + GUID_buf_string(&exact->guid, + &guid_str)); + talloc_free(tmp_ctx); + return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS; + } + + ndr_err = ndr_push_struct_blob(&sid_blob, tmp_ctx, &tmp_sid, + (ndr_push_flags_fn_t)ndr_push_dom_sid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + ret = ldb_dn_set_extended_component(exact->dsdb_dn->dn, "SID", &sid_blob); + data_blob_free(&sid_blob); + if (ret != LDB_SUCCESS) { + talloc_free(tmp_ctx); + return ret; + } + + fixed_dnstring = dsdb_dn_get_extended_linearized( + new_values, exact->dsdb_dn, 1); + if (fixed_dnstring == NULL) { + talloc_free(tmp_ctx); + return ldb_operr(ldb); + } + + /* + * We just replace the existing value... + */ + *exact->v = data_blob_string_const(fixed_dnstring); + + continue; + } + if (exact != NULL) { /* * We are trying to add one that exists, which is only @@ -2522,15 +2619,16 @@ static int replmd_modify_la_add(struct ldb_module *module, ret = replmd_update_la_val(new_values, exact->v, dns[i].dsdb_dn, exact->dsdb_dn, - invocation_id, seq_num, - seq_num, now, false); + &ac->our_invocation_id, + ac->seq_num, ac->seq_num, + now, false); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = replmd_add_backlink(module, replmd_private, - schema, + ac->schema, msg_dn, &dns[i].guid, true, @@ -2572,14 +2670,14 @@ static int replmd_modify_la_add(struct ldb_module *module, } ret = replmd_add_backlink(module, replmd_private, - schema, msg_dn, + ac->schema, msg_dn, &dns[i].guid, true, schema_attr, parent); /* Make the new linked attribute ldb_val. */ ret = replmd_build_la_val(new_values, &new_values[num_values], - dns[i].dsdb_dn, invocation_id, - seq_num, now); + dns[i].dsdb_dn, &ac->our_invocation_id, + ac->seq_num, now); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; @@ -2618,12 +2716,11 @@ static int replmd_modify_la_add(struct ldb_module *module, */ static int replmd_modify_la_delete(struct ldb_module *module, struct replmd_private *replmd_private, - const struct dsdb_schema *schema, + struct replmd_replicated_request *ac, struct ldb_message *msg, struct ldb_message_element *el, struct ldb_message_element *old_el, const struct dsdb_attribute *schema_attr, - uint64_t seq_num, time_t t, struct ldb_dn *msg_dn, struct ldb_request *parent) @@ -2637,16 +2734,10 @@ static int replmd_modify_la_delete(struct ldb_module *module, bool vanish_links = false; unsigned int num_to_delete = el->num_values; uint32_t rmd_flags; - const struct GUID *invocation_id; NTTIME now; unix_to_nt_time(&now, t); - invocation_id = samdb_ntds_invocation_id(ldb); - if (!invocation_id) { - return LDB_ERR_OPERATIONS_ERROR; - } - if (old_el == NULL || old_el->num_values == 0) { /* there is nothing to delete... */ if (num_to_delete == 0) { @@ -2710,7 +2801,7 @@ static int replmd_modify_la_delete(struct ldb_module *module, } } ret = replmd_add_backlink(module, replmd_private, - schema, msg_dn, &p->guid, + ac->schema, msg_dn, &p->guid, false, schema_attr, parent); if (ret != LDB_SUCCESS) { @@ -2728,8 +2819,9 @@ static int replmd_modify_la_delete(struct ldb_module *module, ret = replmd_update_la_val(old_el->values, p->v, p->dsdb_dn, p->dsdb_dn, - invocation_id, seq_num, - seq_num, now, true); + &ac->our_invocation_id, + ac->seq_num, ac->seq_num, + now, true); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; @@ -2791,7 +2883,7 @@ static int replmd_modify_la_delete(struct ldb_module *module, /* remove the backlink */ ret = replmd_add_backlink(module, replmd_private, - schema, + ac->schema, msg_dn, &p->guid, false, schema_attr, @@ -2825,14 +2917,15 @@ static int replmd_modify_la_delete(struct ldb_module *module, ret = replmd_update_la_val(old_el->values, exact->v, exact->dsdb_dn, exact->dsdb_dn, - invocation_id, seq_num, seq_num, + &ac->our_invocation_id, + ac->seq_num, ac->seq_num, now, true); if (ret != LDB_SUCCESS) { talloc_free(tmp_ctx); return ret; } ret = replmd_add_backlink(module, replmd_private, - schema, msg_dn, + ac->schema, msg_dn, &p->guid, false, schema_attr, parent); @@ -2882,12 +2975,11 @@ static int replmd_modify_la_delete(struct ldb_module *module, */ static int replmd_modify_la_replace(struct ldb_module *module, struct replmd_private *replmd_private, - const struct dsdb_schema *schema, + struct replmd_replicated_request *ac, struct ldb_message *msg, struct ldb_message_element *el, struct ldb_message_element *old_el, const struct dsdb_attribute *schema_attr, - uint64_t seq_num, time_t t, struct ldb_dn *msg_dn, struct ldb_request *parent) @@ -2896,7 +2988,6 @@ static int replmd_modify_la_replace(struct ldb_module *module, struct parsed_dn *dns, *old_dns; TALLOC_CTX *tmp_ctx = talloc_new(msg); int ret; - const struct GUID *invocation_id; struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_val *new_values = NULL; const char *ldap_oid = schema_attr->syntax->ldap_oid; @@ -2907,11 +2998,6 @@ static int replmd_modify_la_replace(struct ldb_module *module, unix_to_nt_time(&now, t); - invocation_id = samdb_ntds_invocation_id(ldb); -- Samba Shared Repository