[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Tue Jan 31 13:44:01 UTC 2023


The branch, master has been updated
       via  0f2978bbc0e s4-drsuapi: Give an error that matches windows on destination_dsa_guid lookup failure
       via  1838f349c94 s4-drsuapi: Clarify role of drs_security_access_check_nc_root()
       via  115a3a10440 s4-rpc_server: Pre-check destination_dsa_guid in GetNCChanges for validity
       via  09ec6a1db2d s4-drsuapi: Use samdb_get_ntds_obj_by_guid() to find RODC in REPL_SECRET
       via  adb776149e5 s4-dsdb: Require that the NTDS object is an nTDSDSA objectclass
       via  d5a2af3feae s4-dsdb: Split samdb_get_ntds_obj_by_guid() out of samdb_is_rodc()
       via  cbe18353d8d s4-rpc_server/drsuapi: Return correct error code for an invalid DN to EXOP_REPL_OBJ/EXOP_REPL_OBJ
       via  73f3ece8b2b s4-drs: Make drs_ObjectIdentifier_to_dn() safer and able to cope with DummyDN values
       via  aee2039e63c s4-dsdb: rework drs_ObjectIdentifier_to_dn() into drs_ObjectIdentifier_to_dn_and_nc_root()
       via  e96dfc74b3e s4-rpc_server/drsuapi: Use dsdb_normalise_dn_and_find_nc_root()
       via  8e1122420ef s4-dsdb: Add dsdb_normalise_dn_and_find_nc_root() around dsdb_find_nc_root()
       via  0f501b2316a s4-dsdb: Add better debugging to dsdb_objects_have_same_nc()
       via  d0444be4b74 s4-dsdb: Make dsdb_find_nc_root() first try and use DSDB_CONTROL_CURRENT_PARTITION_OID
       via  7032b86cd5c s4-dsdb: Schedule SD propegation only after successful rename
       via  7c43388576f s4-selftest/drs: Confirm GetNCChanges REPL_SECRET works with a DummyDN and real GUID
       via  539221dda33 s4-selftest/drs: Confirm GetNCChanges full replication works with a DummyDN and real GUID
       via  70faccae6d5 s4-selftest/drs: Confirm GetNCChanges REPL_OBJ works with a DummyDN and real GUID
       via  3204d1350b2 s4-selftest/drs Allow re-run of DRS tests after failed cleanup
       via  a150a2dcb1f s4-selftest/drs Allow some DRS tests to operate against an IP
       via  bee45e6b29b s4-selftest/drs Add test of expected return code for invaid DNs in GetNCChanges
       via  2c7bb58703c s4-dsdb: Add tests of SamDB.get_nc_root()
       via  d43adae8559 s4-dsdb: Rework dsdb_find_dn_by_guid() to use GUID_buf_string()
      from  f6712c70986 script:autobuild: Make sure we can send a failure mail

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0f2978bbc0ed5b65d75c20472650a749643312e7
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 15:24:57 2023 +1300

    s4-drsuapi: Give an error that matches windows on destination_dsa_guid lookup failure
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Tue Jan 31 13:43:54 UTC 2023 on atb-devel-224

commit 1838f349c94b878de1740af35351a2e8e0c8cffb
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 16:01:48 2023 +1300

    s4-drsuapi: Clarify role of drs_security_access_check_nc_root()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 115a3a10440f44ba11029be5ae3a05534a7b98c0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 14:18:11 2023 +1300

    s4-rpc_server: Pre-check destination_dsa_guid in GetNCChanges for validity
    
    This allows our new tests to pass as these need to be checked first.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 09ec6a1db2d3b831548bf7d66475c486be29b1d1
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 15:24:01 2023 +1300

    s4-drsuapi: Use samdb_get_ntds_obj_by_guid() to find RODC in REPL_SECRET
    
    We need to find the RODC per the destination_dsa_guid to mark the secrets as
    having been replicated, and by using samdb_get_ntds_obj_by_guid() we are stricter
    in the checks, as the RODC has to be the right objectClass (nTDSDSA) and under
    the CN=Configuration partition.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit adb776149e5ac0eb346992775610627106e1a986
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 15:18:47 2023 +1300

    s4-dsdb: Require that the NTDS object is an nTDSDSA objectclass
    
    This should avoid a user being able to specify the GUID of a different
    type of object.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit d5a2af3feae98057ba29de444d308d499d633941
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 15:17:44 2023 +1300

    s4-dsdb: Split samdb_get_ntds_obj_by_guid() out of samdb_is_rodc()
    
    This will allow the logic here to be tighened up and shared
    in the next few commits.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit cbe18353d8d7b2a35b965e4fc8c895ac497e67e8
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Dec 16 14:22:20 2022 +1300

    s4-rpc_server/drsuapi: Return correct error code for an invalid DN to EXOP_REPL_OBJ/EXOP_REPL_OBJ
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 73f3ece8b2b44ac4b3323a08fb969f29bf2b0380
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jan 31 13:29:05 2023 +1300

    s4-drs: Make drs_ObjectIdentifier_to_dn() safer and able to cope with DummyDN values
    
    We want to totally ignore the string DN if there is a GUID,
    as clients like "Microsoft Azure AD connect cloud sync" will
    set a literal "DummyDN" string.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit aee2039e63ceeb5e69a0461fb77e0f18278e4dc4
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 12 09:47:36 2022 +1300

    s4-dsdb: rework drs_ObjectIdentifier_to_dn() into drs_ObjectIdentifier_to_dn_and_nc_root()
    
    This make this funciton the gatekeeper between the wire format and the
    internal struct ldb_dn, checking if the DN exists and which NC
    it belongs to along the way, and presenting only a DB-returned
    DN for internal processing.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit e96dfc74b3ece40fe64a33aa8b8d810b576982bd
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 12 16:15:44 2022 +1300

    s4-rpc_server/drsuapi: Use dsdb_normalise_dn_and_find_nc_root()
    
    This reuses the search done for dsdb_find_nc_root() to normalise the DN.
    
    This will allow a GUID-input DN to be compared safely with a RID Manager DN
    or Naming Context.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 8e1122420efd11a91aa1c5d60c0cc8fd9ffaf157
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 12 16:15:03 2022 +1300

    s4-dsdb: Add dsdb_normalise_dn_and_find_nc_root() around dsdb_find_nc_root()
    
    Reuse the search done for dsdb_find_nc_root() to normalise the DN.
    
    This will allow a GUID-input DN to be compared safely with a RID Manager DN
    or Naming Context.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 0f501b2316af6568003e520848c1ec80c286fd36
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Dec 15 18:52:20 2022 +1300

    s4-dsdb: Add better debugging to dsdb_objects_have_same_nc()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit d0444be4b74bdad6a731bc5fcf86da6142b03539
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 5 22:21:29 2022 +1300

    s4-dsdb: Make dsdb_find_nc_root() first try and use DSDB_CONTROL_CURRENT_PARTITION_OID
    
    This allows lookup of a DN with a GUID only or GUID and string,
    possibly not yet in the database, yet still getting the correct result.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 7032b86cd5c1456318558ed95f8890e353117ced
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Jan 26 09:44:01 2023 +1300

    s4-dsdb: Schedule SD propegation only after successful rename
    
    This avoids needing to anticipate errors that the rename might give
    while allowing the dsdb_find_nc_root() routine to become stricter.
    
    The problem is that dsdb_find_nc_root() will soon do a real search and
    so fail more often, but these failures will give "wrong" error codes.
    
    We do not need to do this work if the operation fails, so put this in
    the callback.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 7c43388576f768db564aaf15a47d3f9ce5796fb3
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Dec 15 16:02:55 2022 +1300

    s4-selftest/drs: Confirm GetNCChanges REPL_SECRET works with a DummyDN and real GUID
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 539221dda33f03a1abf5ee5f3153db0fe1a9bfe6
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Dec 15 16:02:27 2022 +1300

    s4-selftest/drs: Confirm GetNCChanges full replication works with a DummyDN and real GUID
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 70faccae6d595056174af8d63b3437c9fe3805aa
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Dec 2 15:30:05 2022 +1300

    s4-selftest/drs: Confirm GetNCChanges REPL_OBJ works with a DummyDN and real GUID
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 3204d1350b21704474e577cb5f3f2439b673c421
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Dec 2 11:56:38 2022 +1300

    s4-selftest/drs Allow re-run of DRS tests after failed cleanup
    
    Using a random base is a useful start, even if the better solution also includes a self.AddCleanup()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit a150a2dcb1fc7fc7f606838de17ad4d3e6072bda
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Dec 2 11:42:55 2022 +1300

    s4-selftest/drs Allow some DRS tests to operate against an IP
    
    This is not comprehensive, but makes some manual test runs easier by
    avoiding the need for DNS names to resolve.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit bee45e6b29b97e0cab19a9c3cf692d9a7585a717
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Dec 2 10:07:53 2022 +1300

    s4-selftest/drs Add test of expected return code for invaid DNs in GetNCChanges
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 2c7bb58703c1fa26782ac6959ea7d81fccf3905c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Dec 15 12:05:55 2022 +1300

    s4-dsdb: Add tests of SamDB.get_nc_root()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=10635
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit d43adae855914870f82881890cb1540d679d3fb9
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Jan 25 14:19:16 2023 +1300

    s4-dsdb: Rework dsdb_find_dn_by_guid() to use GUID_buf_string()
    
    This avoids a talloc_strdup() and so a failure path.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/tests/dsdb.py                  | 122 ++++++++++
 source4/dsdb/common/dsdb_dn.c               | 183 ++++++++++++++-
 source4/dsdb/common/util.c                  | 343 ++++++++++++++++++++++++++--
 source4/dsdb/samdb/ldb_modules/descriptor.c | 134 +++++++----
 source4/rpc_server/drsuapi/drsutil.c        |  28 ++-
 source4/rpc_server/drsuapi/getncchanges.c   | 182 ++++++++++++---
 source4/rpc_server/drsuapi/updaterefs.c     |  39 +++-
 source4/torture/drs/python/drs_base.py      |  15 +-
 source4/torture/drs/python/getnc_exop.py    | 169 +++++++++++++-
 source4/torture/drs/python/getncchanges.py  |  52 ++++-
 source4/torture/drs/python/repl_move.py     |  11 +-
 source4/torture/drs/python/repl_rodc.py     |  46 ++++
 source4/torture/drs/python/repl_schema.py   |   9 +-
 13 files changed, 1176 insertions(+), 157 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/tests/dsdb.py b/python/samba/tests/dsdb.py
index f4f7a705626..6c52994ece7 100644
--- a/python/samba/tests/dsdb.py
+++ b/python/samba/tests/dsdb.py
@@ -1029,6 +1029,128 @@ class DsdbTests(TestCase):
                                 str(part_dn) + "," + str(domain_dn)),
                          self.samdb.normalize_dn_in_domain(part_dn))
 
+class DsdbNCRootTests(TestCase):
+
+    def setUp(self):
+        super().setUp()
+        self.lp = samba.tests.env_loadparm()
+        self.creds = Credentials()
+        self.creds.guess(self.lp)
+        self.session = system_session()
+        self.samdb = SamDB(session_info=self.session,
+                           credentials=self.creds,
+                           lp=self.lp)
+        self.remote = False
+
+    # These all use the local mode of operation inside
+    # dsdb_find_nc_root() using the partitions control
+    def test_dsdb_dn_nc_root_sid(self):
+        dom_sid = self.samdb.get_domain_sid()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"<SID={dom_sid}>")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(domain_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_admin_sid(self):
+        dom_sid = self.samdb.get_domain_sid()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"<SID={dom_sid}-500>")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(domain_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_users_container(self):
+        dom_sid = self.samdb.get_domain_sid()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"CN=Users,{domain_dn}")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(domain_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_new_dn(self):
+        dom_sid = self.samdb.get_domain_sid()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"CN=Xnotexisting,CN=Users,{domain_dn}")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(domain_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_new_dn_with_guid(self):
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"<GUID=828e3baf-fa02-4d82-ba5d-6f647dab5fd8>;CN=Xnotexisting,CN=Users,{domain_dn}")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(domain_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_guid(self):
+        ntds_guid = self.samdb.get_ntds_GUID()
+        configuration_dn = self.samdb.get_config_basedn()
+        dn = ldb.Dn(self.samdb, f"<GUID={ntds_guid}>")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(configuration_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_misleading_to_noexisting_guid(self):
+        ntds_guid = self.samdb.get_ntds_GUID()
+        configuration_dn = self.samdb.get_config_basedn()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"<GUID={ntds_guid}>;CN=Xnotexisting,CN=Users,{domain_dn}")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(configuration_dn, nc_root)
+
+    def test_dsdb_dn_nc_root_misleading_to_existing_guid(self):
+        ntds_guid = self.samdb.get_ntds_GUID()
+        configuration_dn = self.samdb.get_config_basedn()
+        domain_dn = ldb.Dn(self.samdb, self.samdb.domain_dn())
+        dn = ldb.Dn(self.samdb, f"<GUID={ntds_guid}>;{domain_dn}")
+        try:
+            nc_root = self.samdb.get_nc_root(dn)
+        except ldb.LdbError as e:
+            (code, msg) = e.args
+            self.fail("Got unexpected exception %d - %s "
+                      % (code, msg))
+        self.assertEqual(configuration_dn, nc_root)
+
+class DsdbRemoteNCRootTests(DsdbNCRootTests):
+    def setUp(self):
+        super().setUp()
+        # Reconnect to the remote LDAP port
+        self.samdb = SamDB(url="ldap://%s" % samba.tests.env_get_var_value('SERVER'),
+                           session_info=self.session,
+                           credentials=self.get_credentials(),
+                           lp=self.lp)
+        self.remote = True
+
 
 class DsdbFullScanTests(TestCase):
 
diff --git a/source4/dsdb/common/dsdb_dn.c b/source4/dsdb/common/dsdb_dn.c
index e348ab6aa94..c86848fd697 100644
--- a/source4/dsdb/common/dsdb_dn.c
+++ b/source4/dsdb/common/dsdb_dn.c
@@ -359,10 +359,12 @@ int dsdb_dn_string_comparison(struct ldb_context *ldb, void *mem_ctx,
 }
 
 /*
-  format a drsuapi_DsReplicaObjectIdentifier naming context as a string
+ * format a drsuapi_DsReplicaObjectIdentifier naming context as a string for debugging
+ *
+ * When forming a DN for DB access you must use drs_ObjectIdentifier_to_dn()
  */
-char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx,
-				     struct drsuapi_DsReplicaObjectIdentifier *nc)
+char *drs_ObjectIdentifier_to_debug_string(TALLOC_CTX *mem_ctx,
+					   struct drsuapi_DsReplicaObjectIdentifier *nc)
 {
 	char *ret = NULL;
 	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
@@ -386,13 +388,172 @@ char *drs_ObjectIdentifier_to_string(TALLOC_CTX *mem_ctx,
 	return ret;
 }
 
-struct ldb_dn *drs_ObjectIdentifier_to_dn(TALLOC_CTX *mem_ctx,
-					  struct ldb_context *ldb,
-					  struct drsuapi_DsReplicaObjectIdentifier *nc)
+/*
+ * Safely convert a drsuapi_DsReplicaObjectIdentifier into an LDB DN
+ *
+ * We need to have GUID and SID prority and not allow extended
+ * components in the DN.
+ *
+ * We must also totally honour the prority even if the string DN is not valid or able to parse as a DN.
+ */
+static struct ldb_dn *drs_ObjectIdentifier_to_dn(TALLOC_CTX *mem_ctx,
+						 struct ldb_context *ldb,
+						 struct drsuapi_DsReplicaObjectIdentifier *nc)
+{
+	struct ldb_dn *new_dn = NULL;
+
+	if (!GUID_all_zero(&nc->guid)) {
+		struct GUID_txt_buf buf;
+		char *guid = GUID_buf_string(&nc->guid, &buf);
+
+		new_dn = ldb_dn_new_fmt(mem_ctx,
+					ldb,
+					"<GUID=%s>",
+					guid);
+		if (new_dn == NULL) {
+			DBG_ERR("Failed to prepare drs_ObjectIdentifier "
+				"GUID %s into a DN\n",
+				guid);
+			return NULL;
+		}
+
+		return new_dn;
+	}
+
+	if (nc->__ndr_size_sid != 0 && nc->sid.sid_rev_num != 0) {
+		struct dom_sid_buf buf;
+		char *sid = dom_sid_str_buf(&nc->sid, &buf);
+
+		new_dn = ldb_dn_new_fmt(mem_ctx,
+					ldb,
+					"<SID=%s>",
+					sid);
+		if (new_dn == NULL) {
+			DBG_ERR("Failed to prepare drs_ObjectIdentifier "
+				"SID %s into a DN\n",
+				sid);
+			return NULL;
+		}
+		return new_dn;
+	}
+
+	if (nc->__ndr_size_dn != 0 && nc->dn) {
+		int dn_comp_num = 0;
+		bool new_dn_valid = false;
+
+		new_dn = ldb_dn_new(mem_ctx, ldb, nc->dn);
+		if (new_dn == NULL) {
+			/* Set to WARNING as this is user-controlled, don't print the value into the logs */
+			DBG_WARNING("Failed to parse string DN in "
+				    "drs_ObjectIdentifier into an LDB DN\n");
+			return NULL;
+		}
+
+		new_dn_valid = ldb_dn_validate(new_dn);
+		if (!new_dn_valid) {
+			/*
+			 * Set to WARNING as this is user-controlled,
+			 * but can print the value into the logs as it
+			 * parsed a bit
+			 */
+			DBG_WARNING("Failed to validate string DN [%s] in "
+				    "drs_ObjectIdentifier as an LDB DN\n",
+				    ldb_dn_get_linearized(new_dn));
+			return NULL;
+		}
+
+		dn_comp_num = ldb_dn_get_comp_num(new_dn);
+		if (dn_comp_num <= 0) {
+			/*
+			 * Set to WARNING as this is user-controlled,
+			 * but can print the value into the logs as it
+			 * parsed a bit
+			 */
+			DBG_WARNING("DN [%s] in drs_ObjectIdentifier "
+				    "must have 1 or more components\n",
+				    ldb_dn_get_linearized(new_dn));
+			return NULL;
+		}
+
+		if (ldb_dn_is_special(new_dn)) {
+			/*
+			 * Set to WARNING as this is user-controlled,
+			 * but can print the value into the logs as it
+			 * parsed a bit
+			 */
+			DBG_WARNING("New string DN [%s] in "
+				    "drs_ObjectIdentifier is a "
+				    "special LDB DN\n",
+				    ldb_dn_get_linearized(new_dn));
+			return NULL;
+		}
+
+		/*
+		 * We want this just to be a string DN, extended
+		 * components are manually handled above
+		 */
+		if (ldb_dn_has_extended(new_dn)) {
+			/*
+			 * Set to WARNING as this is user-controlled,
+			 * but can print the value into the logs as it
+			 * parsed a bit
+			 */
+			DBG_WARNING("Refusing to parse New string DN [%s] in "
+				    "drs_ObjectIdentifier as an "
+				    "extended LDB DN "
+				    "(GUIDs and SIDs should be in the "
+				    ".guid and .sid IDL elelements, "
+				    "not in the string\n",
+				    ldb_dn_get_extended_linearized(mem_ctx,
+								   new_dn,
+								   1));
+			return NULL;
+		}
+		return new_dn;
+	}
+
+	DBG_WARNING("Refusing to parse empty string DN "
+		    "(and no GUID or SID) "
+		    "drs_ObjectIdentifier into a empty "
+		    "(eg RootDSE) LDB DN\n");
+	return NULL;
+}
+
+/*
+ * Safely convert a drsuapi_DsReplicaObjectIdentifier into a validated
+ * LDB DN of an existing DB entry, and/or find the NC root
+ *
+ * We need to have GUID and SID prority and not allow extended
+ * components in the DN.
+ *
+ * We must also totally honour the prority even if the string DN is
+ * not valid or able to parse as a DN.
+ *
+ * Finally, we must return the DN as found in the DB, as otherwise a
+ * subsequence ldb_dn_compare(dn, nc_root) will fail (as this is based
+ * on the string components).
+ */
+int drs_ObjectIdentifier_to_dn_and_nc_root(TALLOC_CTX *mem_ctx,
+					   struct ldb_context *ldb,
+					   struct drsuapi_DsReplicaObjectIdentifier *nc,
+					   struct ldb_dn **normalised_dn,
+					   struct ldb_dn **nc_root)
 {
-	char *dn_string = drs_ObjectIdentifier_to_string(mem_ctx, nc);
-	struct ldb_dn *new_dn;
-	new_dn = ldb_dn_new(mem_ctx, ldb, dn_string);
-	talloc_free(dn_string);
-	return new_dn;
+	int ret;
+	struct ldb_dn *new_dn = NULL;
+
+	new_dn = drs_ObjectIdentifier_to_dn(mem_ctx,
+					    ldb,
+					    nc);
+	if (new_dn == NULL) {
+		return LDB_ERR_INVALID_DN_SYNTAX;
+	}
+
+	ret = dsdb_normalise_dn_and_find_nc_root(ldb,
+						 mem_ctx,
+						 new_dn,
+						 normalised_dn,
+						 nc_root);
+	TALLOC_FREE(new_dn);
+	return ret;
 }
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index f5de9d82cdf..0167267d370 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -3161,18 +3161,14 @@ int dsdb_find_dn_by_guid(struct ldb_context *ldb,
 	int ret;
 	struct ldb_result *res;
 	const char *attrs[] = { NULL };
-	char *guid_str = GUID_string(mem_ctx, guid);
-
-	if (!guid_str) {
-		return ldb_operr(ldb);
-	}
+	struct GUID_txt_buf buf;
+	char *guid_str = GUID_buf_string(guid, &buf);
 
 	ret = dsdb_search(ldb, mem_ctx, &res, NULL, LDB_SCOPE_SUBTREE, attrs,
 			  DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
 			  DSDB_SEARCH_SHOW_EXTENDED_DN |
 			  DSDB_SEARCH_ONE_ONLY | dsdb_flags,
 			  "objectGUID=%s", guid_str);
-	talloc_free(guid_str);
 	if (ret != LDB_SUCCESS) {
 		return ret;
 	}
@@ -3550,9 +3546,49 @@ int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
 	return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
 }
 
+/*
+ * Return the NTDS object for a GUID, confirming it is in the
+ * configuration partition and a nTDSDSA object
+ */
+int samdb_get_ntds_obj_by_guid(TALLOC_CTX *mem_ctx,
+			       struct ldb_context *sam_ctx,
+			       const struct GUID *objectGUID,
+			       const char **attrs,
+			       struct ldb_message **msg)
+{
+	int ret;
+	struct ldb_result *res;
+	struct GUID_txt_buf guid_buf;
+	char *guid_str = GUID_buf_string(objectGUID, &guid_buf);
+	struct ldb_dn *config_dn = NULL;
+
+	config_dn = ldb_get_config_basedn(sam_ctx);
+	if (config_dn == NULL) {
+		return ldb_operr(sam_ctx);
+	}
+
+	ret = dsdb_search(sam_ctx,
+			  mem_ctx,
+			  &res,
+			  config_dn,
+			  LDB_SCOPE_SUBTREE,
+			  attrs,
+			  DSDB_SEARCH_ONE_ONLY,
+			  "(&(objectGUID=%s)(objectClass=nTDSDSA))",
+			  guid_str);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	if (msg) {
+		*msg = talloc_steal(mem_ctx, res->msgs[0]);
+	}
+	TALLOC_FREE(res);
+	return ret;
+}
+
 
 /*
-  see if a computer identified by its invocationId is a RODC
+  see if a computer identified by its objectGUID is a RODC
 */
 int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bool *is_rodc)
 {
@@ -3561,20 +3597,15 @@ int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bo
 	   3) if not present then not a RODC
 	   4) if present and TRUE then is a RODC
 	*/
-	struct ldb_dn *config_dn;
 	const char *attrs[] = { "msDS-isRODC", NULL };
 	int ret;
-	struct ldb_result *res;
+	struct ldb_message *msg;
 	TALLOC_CTX *tmp_ctx = talloc_new(sam_ctx);
 
-	config_dn = ldb_get_config_basedn(sam_ctx);
-	if (!config_dn) {
-		talloc_free(tmp_ctx);
-		return ldb_operr(sam_ctx);
-	}
-
-	ret = dsdb_search(sam_ctx, tmp_ctx, &res, config_dn, LDB_SCOPE_SUBTREE, attrs,
-			  DSDB_SEARCH_ONE_ONLY, "objectGUID=%s", GUID_string(tmp_ctx, objectGUID));
+	ret = samdb_get_ntds_obj_by_guid(tmp_ctx,
+					 sam_ctx,
+					 objectGUID,
+					 attrs, &msg);
 
 	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
 		*is_rodc = false;
@@ -3590,7 +3621,7 @@ int samdb_is_rodc(struct ldb_context *sam_ctx, const struct GUID *objectGUID, bo
 		return ret;
 	}
 
-	ret = ldb_msg_find_attr_as_bool(res->msgs[0], "msDS-isRODC", 0);
+	ret = ldb_msg_find_attr_as_bool(msg, "msDS-isRODC", 0);
 	*is_rodc = (ret == 1);
 
 	talloc_free(tmp_ctx);
@@ -4124,10 +4155,12 @@ static int dsdb_dn_compare_ptrs(struct ldb_dn **dn1, struct ldb_dn **dn2)
 }
 
 /*
-  find a NC root given a DN within the NC
+  find a NC root given a DN within the NC by reading the rootDSE namingContexts
  */
-int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
-		      struct ldb_dn **nc_root)
+static int dsdb_find_nc_root_string_based(struct ldb_context *samdb,
+					  TALLOC_CTX *mem_ctx,
+					  struct ldb_dn *dn,
+					  struct ldb_dn **nc_root)
 {
 	const char *root_attrs[] = { "namingContexts", NULL };
 	TALLOC_CTX *tmp_ctx;
@@ -4212,6 +4245,266 @@ int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb
        return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
 }
 
+struct dsdb_get_partition_and_dn {
+	TALLOC_CTX *mem_ctx;
+	unsigned int count;
+	struct ldb_dn *dn;
+	struct ldb_dn *partition_dn;
+	bool want_partition_dn;
+};
+
+static int dsdb_get_partition_and_dn(struct ldb_request *req,
+				     struct ldb_reply *ares)
+{
+	int ret;
+	struct dsdb_get_partition_and_dn *context = req->context;
+	struct ldb_control *partition_ctrl = NULL;
+	struct dsdb_control_current_partition *partition = NULL;
+
+	if (!ares) {
+		return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
+	}
+	if (ares->error != LDB_SUCCESS
+	    && ares->error != LDB_ERR_NO_SUCH_OBJECT) {
+		return ldb_request_done(req, ares->error);
+	}
+
+	switch (ares->type) {
+	case LDB_REPLY_ENTRY:
+		if (context->count != 0) {
+			return ldb_request_done(req,
+						LDB_ERR_CONSTRAINT_VIOLATION);
+		}
+		context->count++;
+
+		context->dn = talloc_steal(context->mem_ctx,
+					   ares->message->dn);
+		break;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list