[SCM] Samba Shared Repository - branch v4-8-test updated

Karolin Seeger kseeger at samba.org
Mon Nov 5 13:29:02 UTC 2018


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 <abartlet at 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 <abartlet at samba.org>
    Reviewed-by: Tim Beale <timbeale at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at 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 <kseeger at samba.org>
    Autobuild-Date(v4-8-test): Mon Nov  5 14:28:49 CET 2018 on sn-devel-144

commit 98db8eb90c25a3f8d748cbb55ff3732fe5eb68b9
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 7a36cb30b716d56b84e894851c1a18e9eb3a0964)

commit 47745ae56288b836c73516dedb33edc5e324b8dc
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 0386307e34097f5d9233c970983c7306d1705a87)

commit 141285407df6cd23ac20ce5eb352983e81ce0969
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 1ef145d9d72d847055f6aba8a0070b3e1cfdabbc)

commit b23722a7f6023f1ac1ce39cc2e764605a940d356
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 738b52eb0856c8fcdbb8589e8061bcc14700c23a)

commit 07a48914d2a4c814f3237d39eb3976dd8f1bd6f6
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 70a306d0bd6806d1fd00d45e3d8cc70c73d09f79)

commit 45641745dd5d93d8b8d3403de34185c3afc70d9f
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 42e69a86ca583e3cb20c63b9c6930b4b3425485d)

commit f7ec40472d680207d0f60f4159927003417bd24e
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 966c7febaf0245516481bde924ea6cd738eeb78b)

commit 5d562c1a0f60f6d14203cffca0d4f345b1389900
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit f81771c8593327e058b9cb4330d7e77083df3ea9)

commit b90f5a98cd47c36f559cf5386035948f5f03657b
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit a801799ebe26780653f4ed3fa3fc633e31871f7d)

commit dffea1b1c32973f53d12a89b58ae6de7211ad09f
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit c5c99b569569ce36cac94e967ca53e3182abd6f7)

commit 997a3b23b96e6f3a399cd41ac956ce41ea6971f8
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit bb9c9e49a5e82f19626cb1b12ec9189fff5114e8)

commit f3aed1e7f19f7a9c34df832fb60759867ab6088d
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 364ed537e0bcb3a97cae0f2d1ff72de9423ce0e6)

commit 933d5f375d82831306013744c56c42331249000d
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 60131b4452d43b3792e7f27a4190c88e7aabb1b4)

commit e02b0bcb8c8f72459f2ca9a0e5094a1b6fe231e8
Author: Stefan Metzmacher <metze at 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 <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 0189f23f5bda263c7462366ee16b2fe4bcda0119)

commit 4154d31eeb47ced6f7163f65766a2d7b89c87486
Author: Tim Beale <timbeale at 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 <timbeale at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>
    Pair-programmed-with: Andrew Bartlett <abartlet at samba.org>
    (cherry picked from commit 22208f52e6096fbe9413b8ff339d9446851e0874)

commit d8c9c93c90b70455ad39ae4acd78a8f71c290fb7
Author: Andrew Bartlett <abartlet at 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 <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at 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



More information about the samba-cvs mailing list