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

Jule Anger janger at samba.org
Fri Feb 3 10:29:02 UTC 2023


The branch, v4-17-test has been updated
       via  cee7ecee5ca s4-drsuapi: Give an error that matches windows on destination_dsa_guid lookup failure
       via  c7658589fa5 s4-drsuapi: Clarify role of drs_security_access_check_nc_root()
       via  dee90673865 s4-rpc_server: Pre-check destination_dsa_guid in GetNCChanges for validity
       via  be0cb189202 s4-drsuapi: Use samdb_get_ntds_obj_by_guid() to find RODC in REPL_SECRET
       via  fba94e5d504 s4-dsdb: Require that the NTDS object is an nTDSDSA objectclass
       via  bcb89bd81d4 s4-dsdb: Split samdb_get_ntds_obj_by_guid() out of samdb_is_rodc()
       via  a78c2094ff5 s4-rpc_server/drsuapi: Return correct error code for an invalid DN to EXOP_REPL_OBJ/EXOP_REPL_OBJ
       via  764702f788c s4-drs: Make drs_ObjectIdentifier_to_dn() safer and able to cope with DummyDN values
       via  7c32d3d75aa s4-dsdb: rework drs_ObjectIdentifier_to_dn() into drs_ObjectIdentifier_to_dn_and_nc_root()
       via  85cc464195b s4-rpc_server/drsuapi: Use dsdb_normalise_dn_and_find_nc_root()
       via  96adf5afc01 s4-dsdb: Add dsdb_normalise_dn_and_find_nc_root() around dsdb_find_nc_root()
       via  deac11ab428 s4-dsdb: Add better debugging to dsdb_objects_have_same_nc()
       via  4413c277ef0 s4-dsdb: Make dsdb_find_nc_root() first try and use DSDB_CONTROL_CURRENT_PARTITION_OID
       via  24adeb3ad11 s4-dsdb: Schedule SD propegation only after successful rename
       via  fedd276dbf1 s4-selftest/drs: Confirm GetNCChanges REPL_SECRET works with a DummyDN and real GUID
       via  f6ebb660e54 s4-selftest/drs: Confirm GetNCChanges full replication works with a DummyDN and real GUID
       via  fcc25f6baf8 s4-selftest/drs: Confirm GetNCChanges REPL_OBJ works with a DummyDN and real GUID
       via  b0bbea3fdcd s4-selftest/drs Allow re-run of DRS tests after failed cleanup
       via  2cb965046b8 s4-selftest/drs Allow some DRS tests to operate against an IP
       via  a81be075983 s4-selftest/drs Add test of expected return code for invaid DNs in GetNCChanges
       via  00d1f6223f2 s4-dsdb: Add tests of SamDB.get_nc_root()
      from  ddf64adea13 s3/lib: Prevent use after free of messaging_ctdb_fde_ev structs

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-17-test


- Log -----------------------------------------------------------------
commit cee7ecee5caea78beae099cbde4f34c7c0c663b7
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
    
    (cherry picked from commit 0f2978bbc0ed5b65d75c20472650a749643312e7)
    
    Autobuild-User(v4-17-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-17-test): Fri Feb  3 10:28:42 UTC 2023 on sn-devel-184

commit c7658589fa53a7905678361409341a916b0d41f5
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>
    (cherry picked from commit 1838f349c94b878de1740af35351a2e8e0c8cffb)

commit dee9067386531241846680e50dc892cc906b0a07
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>
    (cherry picked from commit 115a3a10440f44ba11029be5ae3a05534a7b98c0)

commit be0cb18920243a422fe5bd77bb9ce241e71b4b62
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>
    (cherry picked from commit 09ec6a1db2d3b831548bf7d66475c486be29b1d1)

commit fba94e5d50433e8869e72d0ae2bb68fa2abab03e
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>
    (cherry picked from commit adb776149e5ac0eb346992775610627106e1a986)

commit bcb89bd81d4e51fbd06e205816e0b891dc0c1889
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>
    (cherry picked from commit d5a2af3feae98057ba29de444d308d499d633941)

commit a78c2094ff503b775688dd46dc48ccf8f0934f09
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>
    (cherry picked from commit cbe18353d8d7b2a35b965e4fc8c895ac497e67e8)

commit 764702f788c3b59d1f9b21a8deec4fe37f680c1a
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.
    
    RN: Use of the Azure AD Connect cloud sync tool is now supported for
    password hash synchronisation, allowing Samba AD Domains to synchronise
    passwords with this popular cloud environment.
    
    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>
    (cherry picked from commit 73f3ece8b2b44ac4b3323a08fb969f29bf2b0380)

commit 7c32d3d75aa31b868527d992e08e8d63fc76faac
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>
    (cherry picked from commit aee2039e63ceeb5e69a0461fb77e0f18278e4dc4)

commit 85cc464195bf9cf70159d113f33582af02ac6614
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>
    (cherry picked from commit e96dfc74b3ece40fe64a33aa8b8d810b576982bd)

commit 96adf5afc01ee07f2b9ecd2415c6bda5d7e1ff1a
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>
    (cherry picked from commit 8e1122420efd11a91aa1c5d60c0cc8fd9ffaf157)

commit deac11ab428b73a712da15f55be135f2741be14d
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>
    (cherry picked from commit 0f501b2316af6568003e520848c1ec80c286fd36)

commit 4413c277ef09dfba6d9d69bfa2886402bcc5c369
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>
    (cherry picked from commit d0444be4b74bdad6a731bc5fcf86da6142b03539)

commit 24adeb3ad11c693aefbbea25570527cc87cd977d
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>
    (cherry picked from commit 7032b86cd5c1456318558ed95f8890e353117ced)

commit fedd276dbf1f792fe27eed6165b21aea4764718d
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>
    (cherry picked from commit 7c43388576f768db564aaf15a47d3f9ce5796fb3)

commit f6ebb660e545caad452620394debbc12547bba71
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>
    (cherry picked from commit 539221dda33f03a1abf5ee5f3153db0fe1a9bfe6)

commit fcc25f6baf8be5b0c9171a7f4e3ac87f66532c67
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>
    (cherry picked from commit 70faccae6d595056174af8d63b3437c9fe3805aa)

commit b0bbea3fdcdbca0629cbb2f12b5378b8ba7ac423
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>
    (cherry picked from commit 3204d1350b21704474e577cb5f3f2439b673c421)

commit 2cb965046b88a7755369dd5c48809d7c76929d7e
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>
    (cherry picked from commit a150a2dcb1fc7fc7f606838de17ad4d3e6072bda)

commit a81be07598363ce778482eeecd429c83278dd936
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>
    (cherry picked from commit bee45e6b29b97e0cab19a9c3cf692d9a7585a717)

commit 00d1f6223f2b13c46d061c58ab944f4459c4eed0
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>
    (cherry picked from commit 2c7bb58703c1fa26782ac6959ea7d81fccf3905c)

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

Summary of changes:
 python/samba/tests/dsdb.py                  | 122 ++++++++++
 source4/dsdb/common/dsdb_dn.c               | 183 ++++++++++++++-
 source4/dsdb/common/util.c                  | 335 ++++++++++++++++++++++++++--
 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, 1174 insertions(+), 151 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 be0a2cd4a33..a30ae662c1e 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -3550,9 +3550,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 +3601,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 +3625,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 +4159,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 +4249,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;
+
+	case LDB_REPLY_REFERRAL:
+		talloc_free(ares);
+		return ldb_request_done(req, LDB_SUCCESS);
+
+	case LDB_REPLY_DONE:
+		partition_ctrl
+			= ldb_reply_get_control(ares,
+						DSDB_CONTROL_CURRENT_PARTITION_OID);
+		if (!context->want_partition_dn ||
+			partition_ctrl == NULL) {
+			ret = ares->error;
+			talloc_free(ares);
+
+			return ldb_request_done(req, ret);
+		}
+
+		partition
+			= talloc_get_type_abort(partition_ctrl->data,
+						struct dsdb_control_current_partition);
+		context->partition_dn


-- 
Samba Shared Repository



More information about the samba-cvs mailing list