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

Jule Anger janger at samba.org
Fri Oct 7 09:57:01 UTC 2022


The branch, v4-16-test has been updated
       via  1a4d3a2db79 python-drs: Add client-side debug and fallback for GET_ANC
       via  0a8330ab7dc s4-libnet: Add messages to object count mismatch failures
       via  584a4c00575 selftest: Enable "old Samba" mode regarding GET_ANC/GET_TGT
       via  a0e0c7e9894 s4-rpc_server:getncchanges Add "old Samba" mode regarding GET_ANC/GET_TGT
       via  997b8f8341f selftest: Add tests for GetNCChanges GET_ANC using samba-tool drs clone-dc-database
       via  2d2156b01de selftest: Prepare for "old Samba" mode regarding getncchanges GET_ANC/GET_TGT
       via  dd2c5f96981 pytest/samba_tool_drs_no_dns: use TestCaseInTempDir.rm_files/.rm_dirs
       via  42b5bfa68e2 pytest/samba_tool_drs: use TestCaseInTempDir.rm_files/.rm_dirs
       via  6a6db20068f pytest/samdb: use TestCaseInTempDir.rm_files/.rm_dirs
       via  fba1864d7a7 pytest/join: use TestCaseInTempDir.rm_files/dirs
       via  6e217c047d2 pytest/samdb_api: use TestCaseInTempDir.rm_files
       via  70de6108924 pytest/downgradedatabase: use TestCaseInTempDir.rm_files
       via  2003f7cf749 pytest: add file removal helpers for TestCaseInTempDir
       via  7c2697e9c84 s3:auth: Flush the GETPWSID in memory cache for NTLM auth
      from  2f71273a736 s3: smbd: Fix memory leak in smbd_server_connection_terminate_done().

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


- Log -----------------------------------------------------------------
commit 1a4d3a2db79dbf48b772b7bbbcf5988a43958642
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 15 17:10:24 2022 +1200

    python-drs: Add client-side debug and fallback for GET_ANC
    
    Samba 4.5 and earlier will fail to do GET_ANC correctly and will not
    replicate non-critical parents of objects with isCriticalSystemObject=TRUE
    when DRSUAPI_DRS_CRITICAL_ONLY is set.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit bff2bc9c7d69ec2fbe9339c2353a0a846182f1ea)
    
    Autobuild-User(v4-16-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-16-test): Fri Oct  7 09:56:12 UTC 2022 on sn-devel-184

commit 0a8330ab7dc2bad3b2ab24dc5e5e368b3979ea05
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Sep 20 13:37:30 2022 +1200

    s4-libnet: Add messages to object count mismatch failures
    
    This helps explain these better than WERR_GEN_FAILURE.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 483c48f52d6ff5e8149ed12bfeb2b6608c946f01)

commit 584a4c005751e3964d070e40573f8620706fc647
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 29 14:54:14 2022 +1300

    selftest: Enable "old Samba" mode regarding GET_ANC/GET_TGT
    
    The chgdcpass server now emulates older verions of Samba that
    fail to implement DRSUAPI_DRS_GET_ANC correctly and totally fails to support
    DRSUAPI_DRS_GET_TGT.
    
    We now show this is in effect by the fact that tests now fail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit b0bbc94d4124d63b1d5a35ccbc88ffd51d520ba0)

commit a0e0c7e9894f8c3ff073dbff1a7e77e9a6b2f06b
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 29 14:53:38 2022 +1300

    s4-rpc_server:getncchanges Add "old Samba" mode regarding GET_ANC/GET_TGT
    
    This emulates older verions of Samba that fail to implement
    DRSUAPI_DRS_GET_ANC correctly and totally fails to support
    DRSUAPI_DRS_GET_TGT.
    
    This will allow testing of a client-side fallback, allowing migration
    from sites that run very old Samba versions over DRSUAPI (currently
    the only option is to attempt an in-place upgrade).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 314bc44fa9b8fc99c80bfcfff71f2cec67bbda36)

commit 997b8f8341f27919b0ae24d24680637f14406d54
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 29 03:05:03 2022 +0000

    selftest: Add tests for GetNCChanges GET_ANC using samba-tool drs clone-dc-database
    
    This test, compared with the direct to RPC tests, will succeed, then fail once the
    server is changed to emulate Samba 4.5 and and again succeed once the python code
    changes to allow skipping the DRSUAPI_DRS_CRITICAL_ONLY step
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 7ff743d65dcf27ffe0c6861720e8ce531bfa378d)

commit 2d2156b01dea36fdac02fdd6bb5f2e36ef81d2b7
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 15 09:36:45 2022 +1200

    selftest: Prepare for "old Samba" mode regarding getncchanges GET_ANC/GET_TGT
    
    The chgdcpass environment will emulate older verions of Samba
    that fail to implement DRSUAPI_DRS_GET_ANC correctly and
    totally fails to support DRSUAPI_DRS_GET_TGT.
    
    This will allow testing of a client-side fallback, allowing migration
    from sites that run very old Samba versions over DRSUAPI (currently
    the only option is to attempt an in-place upgrade).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 62b426243f4eaa4978c249b6e6ce90d35aeaefe4)

commit dd2c5f96981e6ea06447490dbf65d883134060b2
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 15 13:23:32 2022 +1200

    pytest/samba_tool_drs_no_dns: use TestCaseInTempDir.rm_files/.rm_dirs
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 24f7d71416753b792d6fe029da6f366adb10383e)

commit 42b5bfa68e25a2878bc0f441061a2e8195874573
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 8 19:53:57 2022 +1200

    pytest/samba_tool_drs: use TestCaseInTempDir.rm_files/.rm_dirs
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 3f0aab45c81c9f9b6b87eb68bc785902619dc10d)

commit 6a6db20068fb28cbc3b70a92b0b51d08621272c5
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 15 13:22:24 2022 +1200

    pytest/samdb: use TestCaseInTempDir.rm_files/.rm_dirs
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 251360d6e58986dd53f0317319544e930dc61444)

commit fba1864d7a74e82676bf55a8c162ead90adb445c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 15 13:21:16 2022 +1200

    pytest/join: use TestCaseInTempDir.rm_files/dirs
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 7455c53fa4f7871b3980f820d22b0fd411195704)

commit 6e217c047d2123e27e735aa7b168f564d0b719e6
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 15 13:20:41 2022 +1200

    pytest/samdb_api: use TestCaseInTempDir.rm_files
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 4e3dabad0be0900a203896c2c2acb270d31b0a42)

commit 70de610892409421aeb9047b26a551881966acdc
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Jun 15 13:19:28 2022 +1200

    pytest/downgradedatabase: use TestCaseInTempDir.rm_files
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 85bc1552e3919d049d39a065824172a24933d38b)

commit 2003f7cf7497d8a0dfc11c230c8f3a28c53eea64
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Jun 9 13:16:31 2022 +1200

    pytest: add file removal helpers for TestCaseInTempDir
    
    In several places we end a test by deleting a number of files and
    directories, but we do it rather haphazardly with unintentionally
    differing error handling. For example, in some tests we currently have
    something like:
    
            try:
                shutil.rmtree(os.path.join(self.tempdir, "a"))
                os.remove(os.path.join(self.tempdir, "b"))
                shutil.rmtree(os.path.join(self.tempdir, "c"))
            except Exception:
                pass
    
    where if, for example, the removal of "b" fails, the removal of "c" will
    not be attempted. That will result in the tearDown method raising an
    exception, and we're no better off. If the above code is replaced with
    
            self.rm_files('b')
            self.rm_dirs('a', 'c')
    
    the failure to remove 'b' will cause a test error, *unless* the failure
    was due to a FileNotFoundError (a.k.a. an OSError with errno ENOENT),
    in which case we ignore it, as was probably the original intention.
    
    If on the other hand, we have
    
            self.rm_files('b', must_exist=True)
            self.rm_dirs('a', 'c')
    
    then the FileNotFoundError causes a failure (not an error).
    
    We take a little bit of care to stay within self.tempdir, to protect
    test authors who accidentally write something like `self.rm_dirs('/')`.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15191
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Noel Power <npower at samba.org>
    (cherry picked from commit 2359741b2854a8de9d151fe189be80a4bd087ff9)

commit 7c2697e9c84ad94001d0b6aa73c6bb91a079ef78
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Sep 12 16:31:05 2022 +0200

    s3:auth: Flush the GETPWSID in memory cache for NTLM auth
    
    Example valgrind output:
    
    ==22502== 22,747,002 bytes in 21,049 blocks are possibly lost in loss record 1,075 of 1,075
    ==22502==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
    ==22502==    by 0x11D7089C: _talloc_pooled_object (in /usr/lib64/libtalloc.so.2.1.16)
    ==22502==    by 0x9027834: tcopy_passwd (in /usr/lib64/libsmbconf.so.0)
    ==22502==    by 0x6A1E1A3: pdb_copy_sam_account (in /usr/lib64/libsamba-passdb.so.0.27.2)
    ==22502==    by 0x6A28AB7: pdb_getsampwnam (in /usr/lib64/libsamba-passdb.so.0.27.2)
    ==22502==    by 0x65D0BC4: check_sam_security (in /usr/lib64/samba/libauth-samba4.so)
    ==22502==    by 0x65C70F0: ??? (in /usr/lib64/samba/libauth-samba4.so)
    ==22502==    by 0x65C781A: auth_check_ntlm_password (in /usr/lib64/samba/libauth-samba4.so)
    ==22502==    by 0x14E464: ??? (in /usr/sbin/winbindd)
    ==22502==    by 0x151CED: winbind_dual_SamLogon (in /usr/sbin/winbindd)
    ==22502==    by 0x152072: winbindd_dual_pam_auth_crap (in /usr/sbin/winbindd)
    ==22502==    by 0x167DE0: ??? (in /usr/sbin/winbindd)
    ==22502==    by 0x12F29B12: tevent_common_invoke_fd_handler (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F30086: ??? (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F2E056: ??? (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F2925C: _tevent_loop_once (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x16A243: ??? (in /usr/sbin/winbindd)
    ==22502==    by 0x16AA04: ??? (in /usr/sbin/winbindd)
    ==22502==    by 0x12F29F68: tevent_common_invoke_immediate_handler (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F29F8F: tevent_common_loop_immediate (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F2FE3C: ??? (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F2E056: ??? (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F2925C: _tevent_loop_once (in /usr/lib64/libtevent.so.0.9.39)
    ==22502==    by 0x12F4C7: main (in /usr/sbin/winbindd)
    
    You can find one for each string in pdb_copy_sam_account(), in total
    this already has 67 MB in total for this valgrind run.
    
    pdb_getsampwnam() -> memcache_add_talloc(NULL, PDB_GETPWSID_CACHE, ...)
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15169
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Sep 16 20:30:31 UTC 2022 on sn-devel-184
    
    (cherry picked from commit 9ef2f7345f0d387567fca598cc7008af95598903)

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

Summary of changes:
 python/samba/drs_utils.py                          | 47 ++++++++++-
 python/samba/join.py                               | 54 ++++++++++--
 python/samba/tests/__init__.py                     | 35 ++++++++
 python/samba/tests/blackbox/downgradedatabase.py   | 14 ++--
 python/samba/tests/join.py                         |  6 +-
 python/samba/tests/samdb.py                        |  8 +-
 python/samba/tests/samdb_api.py                    | 10 +--
 selftest/knownfail.d/samba-4.5-emulation           |  4 +
 selftest/target/Samba4.pm                          | 12 +++
 source3/auth/check_samsec.c                        |  8 +-
 source4/dsdb/repl/replicated_objects.c             | 11 +++
 source4/rpc_server/drsuapi/getncchanges.c          | 52 ++++++++++--
 source4/selftest/tests.py                          | 23 +++--
 source4/torture/drs/python/samba_tool_drs.py       | 13 +--
 .../torture/drs/python/samba_tool_drs_critical.py  | 98 ++++++++++++++++++++++
 .../torture/drs/python/samba_tool_drs_no_dns.py    | 14 +---
 16 files changed, 335 insertions(+), 74 deletions(-)
 create mode 100644 selftest/knownfail.d/samba-4.5-emulation
 create mode 100644 source4/torture/drs/python/samba_tool_drs_critical.py


Changeset truncated at 500 lines:

diff --git a/python/samba/drs_utils.py b/python/samba/drs_utils.py
index feab89b0d8e..02a32e2f3a6 100644
--- a/python/samba/drs_utils.py
+++ b/python/samba/drs_utils.py
@@ -207,6 +207,44 @@ class drs_Replicate(object):
                 supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10 and
                 (req.more_flags & drsuapi.DRSUAPI_DRS_GET_TGT) == 0)
 
+    @staticmethod
+    def _should_calculate_missing_anc_locally(error_code, req):
+        # If the error indicates we fail to resolve the parent object
+        # for a new object, then we assume we are replicating from a
+        # buggy server (Samba 4.5 and earlier) that doesn't really
+        # understand how to implement GET_ANC
+
+        return ((error_code == werror.WERR_DS_DRA_MISSING_PARENT) and
+                (req.replica_flags & drsuapi.DRSUAPI_DRS_GET_ANC) != 0)
+
+
+    def _calculate_missing_anc_locally(self, ctr):
+        self.guids_seen = set()
+
+        # walk objects in ctr, add to guid_seen as we see them
+        # note if an object doesn't have a parent
+
+        object_to_check = ctr.first_object
+
+        while True:
+            if object_to_check is None:
+                break
+
+            self.guids_seen.add(str(object_to_check.object.identifier.guid))
+
+            if object_to_check.parent_object_guid is not None \
+               and object_to_check.parent_object_guid \
+               != misc.GUID("00000000-0000-0000-0000-000000000000") \
+               and str(object_to_check.parent_object_guid) not in self.guids_seen:
+                obj_dn = ldb.Dn(self.samdb, object_to_check.object.identifier.dn)
+                parent_dn = obj_dn.parent()
+                print(f"Object {parent_dn} with "
+                      f"GUID {object_to_check.parent_object_guid} "
+                      "was not sent by the server in this chunk")
+
+            object_to_check = object_to_check.next_object
+
+
     def process_chunk(self, level, ctr, schema, req_level, req, first_chunk):
         '''Processes a single chunk of received replication data'''
         # pass the replication into the py_net.c python bindings for processing
@@ -329,8 +367,13 @@ class drs_Replicate(object):
                     # of causing the DC to restart the replication from scratch)
                     first_chunk = True
                     continue
-                else:
-                    raise e
+
+                if self._should_calculate_missing_anc_locally(e.args[0],
+                                                              req):
+                    print("Missing parent object - calculating missing objects locally")
+
+                    self._calculate_missing_anc_locally(ctr)
+                raise e
 
             first_chunk = False
             num_objects += ctr.object_count
diff --git a/python/samba/join.py b/python/samba/join.py
index 4399367c817..df2eaf497ab 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -968,17 +968,53 @@ class DCJoinContext(object):
                            destination_dsa_guid, rodc=ctx.RODC,
                            replica_flags=ctx.replica_flags)
             if not ctx.subdomain:
-                # Replicate first the critical object for the basedn
-                if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
-                    print("Replicating critical objects from the base DN of the domain")
-                    ctx.domain_replica_flags |= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY
+                # Replicate first the critical objects for the basedn
+
+                # We do this to match Windows.  The default case is to
+                # do a critical objects replication, then a second
+                # with all objects.
+
+                print("Replicating critical objects from the base DN of the domain")
+                try:
                     repl.replicate(ctx.base_dn, source_dsa_invocation_id,
                                    destination_dsa_guid, rodc=ctx.RODC,
-                                   replica_flags=ctx.domain_replica_flags)
-                    ctx.domain_replica_flags ^= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY
-                repl.replicate(ctx.base_dn, source_dsa_invocation_id,
-                               destination_dsa_guid, rodc=ctx.RODC,
-                               replica_flags=ctx.domain_replica_flags)
+                                   replica_flags=ctx.domain_replica_flags | drsuapi.DRSUAPI_DRS_CRITICAL_ONLY)
+                except WERRORError as e:
+
+                    if e.args[0] == werror.WERR_DS_DRA_MISSING_PARENT:
+                        ctx.logger.warning("First pass of replication with "
+                                           "DRSUAPI_DRS_CRITICAL_ONLY "
+                                           "not possible due to a missing parent object.  "
+                                           "This is typical of a Samba "
+                                           "4.5 or earlier server. "
+                                           "We will replicate the all objects instead.")
+                    else:
+                        raise
+
+                # Now replicate all the objects in the domain (unless
+                # we were run with --critical-only).
+                #
+                # Doing the replication of users as a second pass
+                # matches more closely the Windows behaviour, which is
+                # actually to do this on first startup.
+                #
+                # Use --critical-only if you want that (but you don't
+                # really, it is better to see any errors here).
+                if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+                    try:
+                        repl.replicate(ctx.base_dn, source_dsa_invocation_id,
+                                       destination_dsa_guid, rodc=ctx.RODC,
+                                       replica_flags=ctx.domain_replica_flags)
+                    except WERRORError as e:
+
+                        if e.args[0] == werror.WERR_DS_DRA_MISSING_PARENT and \
+                           ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+                            ctx.logger.warning("Replication with DRSUAPI_DRS_CRITICAL_ONLY "
+                                               "failed due to a missing parent object.  "
+                                               "This may be a Samba 4.5 or earlier server "
+                                               "and is not compatible with --critical-only")
+                        raise
+
             print("Done with always replicated NC (base, config, schema)")
 
             # At this point we should already have an entry in the ForestDNS
diff --git a/python/samba/tests/__init__.py b/python/samba/tests/__init__.py
index 3bb7995052c..e37ceac9bc9 100644
--- a/python/samba/tests/__init__.py
+++ b/python/samba/tests/__init__.py
@@ -37,6 +37,7 @@ import samba.dcerpc.base
 from random import randint
 from random import SystemRandom
 from contextlib import contextmanager
+import shutil
 import string
 try:
     from samba.samdb import SamDB
@@ -295,6 +296,40 @@ class TestCaseInTempDir(TestCase):
                 print("could not remove temporary file: %s" % e,
                       file=sys.stderr)
 
+    def rm_files(self, *files, allow_missing=False, _rm=os.remove):
+        """Remove listed files from the temp directory.
+
+        The files must be true files in the directory itself, not in
+        sub-directories.
+
+        By default a non-existent file will cause a test failure (or
+        error if used outside a test in e.g. tearDown), but if
+        allow_missing is true, the absence will be ignored.
+        """
+        for f in files:
+            path = os.path.join(self.tempdir, f)
+
+            # os.path.join will happily step out of the tempdir,
+            # so let's just check.
+            if os.path.dirname(path) != self.tempdir:
+                raise ValueError("{path} might be outside {self.tempdir}")
+
+            try:
+                _rm(path)
+            except FileNotFoundError as e:
+                if not allow_missing:
+                    raise AssertionError(f"{f} not in {self.tempdir}: {e}")
+
+                print(f"{f} not in {self.tempdir}")
+
+    def rm_dirs(self, *dirs, allow_missing=False):
+        """Remove listed directories from temp directory.
+
+        This works like rm_files, but only removes directories,
+        including their contents.
+        """
+        self.rm_files(*dirs, allow_missing=allow_missing, _rm=shutil.rmtree)
+
 
 def env_loadparm():
     lp = param.LoadParm()
diff --git a/python/samba/tests/blackbox/downgradedatabase.py b/python/samba/tests/blackbox/downgradedatabase.py
index f6da011ede4..8d80ef6e804 100644
--- a/python/samba/tests/blackbox/downgradedatabase.py
+++ b/python/samba/tests/blackbox/downgradedatabase.py
@@ -18,7 +18,6 @@
 from samba.tests import BlackboxTestCase
 import os
 import ldb
-import shutil
 from subprocess import check_output
 from samba.samdb import SamDB
 
@@ -57,13 +56,12 @@ class DowngradeTestBase(BlackboxTestCase):
         self.dbs.append(self.sam_path)
 
     def tearDown(self):
-        shutil.rmtree(os.path.join(self.tempdir, "private"))
-        shutil.rmtree(os.path.join(self.tempdir, "etc"))
-        shutil.rmtree(os.path.join(self.tempdir, "state"))
-        shutil.rmtree(os.path.join(self.tempdir, "bind-dns"))
-        shutil.rmtree(os.path.join(self.tempdir, "msg.lock"))
-        os.unlink(os.path.join(self.tempdir, "names.tdb"))
-        os.unlink(os.path.join(self.tempdir, "gencache.tdb"))
+        self.rm_dirs("private",
+                     "etc",
+                     "state",
+                     "bind-dns",
+                     "msg.lock")
+        self.rm_files("names.tdb", "gencache.tdb")
         super(DowngradeTestBase, self).tearDown()
 
     # Parse out the comments above each record that ldbdump produces
diff --git a/python/samba/tests/join.py b/python/samba/tests/join.py
index db9d8a892b7..da34171da28 100644
--- a/python/samba/tests/join.py
+++ b/python/samba/tests/join.py
@@ -74,10 +74,8 @@ class JoinTestCase(DNSTKeyTest):
         if paths is not None:
             shutil.rmtree(paths.private_dir)
             shutil.rmtree(paths.state_dir)
-            shutil.rmtree(os.path.join(self.tempdir, "etc"))
-            shutil.rmtree(os.path.join(self.tempdir, "msg.lock"))
-            os.unlink(os.path.join(self.tempdir, "names.tdb"))
-            shutil.rmtree(os.path.join(self.tempdir, "bind-dns"))
+            self.rm_dirs("etc", "msg.lock", "bind-dns")
+            self.rm_files("names.tdb")
 
         self.join_ctx.cleanup_old_join(force=True)
 
diff --git a/python/samba/tests/samdb.py b/python/samba/tests/samdb.py
index 834c5a204a6..f7697f83fdc 100644
--- a/python/samba/tests/samdb.py
+++ b/python/samba/tests/samdb.py
@@ -19,7 +19,6 @@
 
 import logging
 import os
-import shutil
 
 from samba.auth import system_session
 from samba.provision import provision
@@ -54,11 +53,8 @@ class SamDBTestCase(TestCaseInTempDir):
         self.lp = self.result.lp
 
     def tearDown(self):
-        for f in ['names.tdb']:
-            os.remove(os.path.join(self.tempdir, f))
-
-        for d in ['etc', 'msg.lock', 'private', 'state', 'bind-dns']:
-            shutil.rmtree(os.path.join(self.tempdir, d))
+        self.rm_files('names.tdb')
+        self.rm_dirs('etc', 'msg.lock', 'private', 'state', 'bind-dns')
 
         super(SamDBTestCase, self).tearDown()
 
diff --git a/python/samba/tests/samdb_api.py b/python/samba/tests/samdb_api.py
index a7260180187..710d0bc310f 100644
--- a/python/samba/tests/samdb_api.py
+++ b/python/samba/tests/samdb_api.py
@@ -29,15 +29,7 @@ class SamDBApiTestCase(TestCaseInTempDir):
         super(SamDBApiTestCase, self).setUp()
 
     def tearDown(self):
-        try:
-            os.remove(self.tempdir + "/test.db")
-        except OSError as e:
-            self.assertEqual(e.errno, errno.ENOENT)
-
-        try:
-            os.remove(self.tempdir + "/existing.db")
-        except OSError as e:
-            self.assertEqual(e.errno, errno.ENOENT)
+        self.rm_files("test.db", "existing.db", allow_missing=True)
 
         super(SamDBApiTestCase, self).tearDown()
 
diff --git a/selftest/knownfail.d/samba-4.5-emulation b/selftest/knownfail.d/samba-4.5-emulation
new file mode 100644
index 00000000000..1fc79361e40
--- /dev/null
+++ b/selftest/knownfail.d/samba-4.5-emulation
@@ -0,0 +1,4 @@
+# This fails as there is no second DC in this enviroment, so it is always the owner
+samba4.drs.getnc_exop.python\(chgdcpass\).getnc_exop.DrsReplicaSyncTestCase.test_FSMONotOwner\(chgdcpass\)
+# This fails because GET_ANC is now poorly implemented (matching Samba 4.5)
+^samba4.drs.getnc_exop.python\(chgdcpass\).getnc_exop.DrsReplicaSyncTestCase.test_link_utdv_hwm\(chgdcpass\)
diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm
index 4c263f55de4..b004042738a 100755
--- a/selftest/target/Samba4.pm
+++ b/selftest/target/Samba4.pm
@@ -2053,10 +2053,22 @@ sub provision_chgdcpass($$)
 	# This environment disallows the use of this password
 	# (and also removes the default AD complexity checks)
 	my $unacceptable_password = "Paßßword-widk3Dsle32jxdBdskldsk55klASKQ";
+
+	# This environment also sets some settings that are unusual,
+	# to test specific behaviours.  In particular, this
+	# environment fails to correctly support DRSUAPI_DRS_GET_ANC
+	# like Samba before 4.5 and DRSUAPI_DRS_GET_TGT before 4.8
+	#
+	# Additionally, disabling DRSUAPI_DRS_GET_TGT causes all links
+	# to be sent last (in the final chunk), which is like Samba
+	# before 4.8.
+
 	my $extra_smb_conf = "
 	check password script = $self->{srcdir}/selftest/checkpassword_arg1.sh ${unacceptable_password}
 	allow dcerpc auth level connect:lsarpc = yes
 	dcesrv:max auth states = 8
+        drs:broken_samba_4.5_get_anc_emulation = true
+        drs:get_tgt_support = false
 ";
 	my $extra_provision_options = ["--dns-backend=BIND9_DLZ"];
 	my $ret = $self->provision($prefix,
diff --git a/source3/auth/check_samsec.c b/source3/auth/check_samsec.c
index bd8ca8de2f0..88387328159 100644
--- a/source3/auth/check_samsec.c
+++ b/source3/auth/check_samsec.c
@@ -24,6 +24,7 @@
 #include "auth.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "passdb.h"
+#include "lib/util/memcache.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
@@ -562,8 +563,6 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge,
 	nt_status = make_server_info_sam(mem_ctx, sampass, server_info);
 	unbecome_root();
 
-	TALLOC_FREE(sampass);
-
 	if (!NT_STATUS_IS_OK(nt_status)) {
 		DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
 		goto done;
@@ -582,6 +581,11 @@ NTSTATUS check_sam_security(const DATA_BLOB *challenge,
 	(*server_info)->nss_token |= user_info->was_mapped;
 
 done:
+	/*
+	 * Always flush the getpwsid cache or this will grow indefinetly for
+	 * each NTLM auththentication.
+	 */
+	memcache_flush(NULL, PDB_GETPWSID_CACHE);
 	TALLOC_FREE(sampass);
 	data_blob_free(&user_sess_key);
 	data_blob_free(&lm_sess_key);
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index de61d8e1335..6a07a88961b 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -747,14 +747,25 @@ WERROR dsdb_replicated_objects_convert(struct ldb_context *ldb,
 		/* Assuming we didn't skip or error, increment the number of objects */
 		out->num_objects++;
 	}
+
+	DBG_INFO("Proceesed %"PRIu32" DRS objects, saw %"PRIu32" objects "
+		 "and expected %"PRIu32" objects\n",
+		 out->num_objects, i, object_count);
+
 	out->objects = talloc_realloc(out, out->objects,
 				      struct dsdb_extended_replicated_object,
 				      out->num_objects);
 	if (out->num_objects != 0 && out->objects == NULL) {
+		DBG_ERR("FAILURE: talloc_realloc() failed after "
+			"processing %"PRIu32" DRS objects!\n",
+			out->num_objects);
 		talloc_free(out);
 		return WERR_FOOBAR;
 	}
 	if (i != object_count) {
+		DBG_ERR("FAILURE: saw %"PRIu32" DRS objects, server said we "
+			"should expected to see %"PRIu32" objects!\n",
+			i, object_count);
 		talloc_free(out);
 		return WERR_FOOBAR;
 	}
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c
index c3330a622af..7f50587dd1e 100644
--- a/source4/rpc_server/drsuapi/getncchanges.c
+++ b/source4/rpc_server/drsuapi/getncchanges.c
@@ -60,6 +60,7 @@ struct drsuapi_getncchanges_state {
 	struct GUID ncRoot_guid;
 	bool is_schema_nc;
 	bool is_get_anc;
+	bool broken_samba_4_5_get_anc_emulation;
 	bool is_get_tgt;
 	uint64_t min_usn;
 	uint64_t max_usn;
@@ -1019,6 +1020,17 @@ struct drsuapi_changed_objects {
 	uint64_t usn;
 };
 
+
+/*
+  sort the objects we send by tree order (Samba 4.5 emulation)
+ */
+static int site_res_cmp_anc_order(struct drsuapi_changed_objects *m1,
+				  struct drsuapi_changed_objects *m2,
+				  struct drsuapi_getncchanges_state *getnc_state)
+{
+	return ldb_dn_compare(m2->dn, m1->dn);
+}
+
 /*
   sort the objects we send first by uSNChanged
  */
@@ -2281,8 +2293,13 @@ static WERROR getncchanges_get_obj_to_send(const struct ldb_message *msg,
 	 * If required, also add any ancestors that the client may need to know
 	 * about before it can resolve this object. These get prepended to the
 	 * ret_obj_list so the client adds them first.
+	 *
+	 * We allow this to be disabled to permit testing of a
+	 * client-side fallback for the broken behaviour in Samba 4.5
+	 * and earlier.
 	 */
-	if (getnc_state->is_get_anc) {
+	if (getnc_state->is_get_anc
+	    && !getnc_state->broken_samba_4_5_get_anc_emulation) {
 		werr = getncchanges_add_ancestors(obj, msg->dn, mem_ctx,
 						  sam_ctx, getnc_state,
 						  schema, session_key,
@@ -3097,9 +3114,35 @@ allowed:
 			}
 		}
 
+		if (req10->extended_op == DRSUAPI_EXOP_NONE) {
+			getnc_state->is_get_anc =
+				((req10->replica_flags & DRSUAPI_DRS_GET_ANC) != 0);
+			if (getnc_state->is_get_anc
+				&& lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
+						    NULL,
+						    "drs",
+						    "broken_samba_4.5_get_anc_emulation",
+						   false)) {
+				getnc_state->broken_samba_4_5_get_anc_emulation = true;
+			}
+			if (lpcfg_parm_bool(dce_call->conn->dce_ctx->lp_ctx,
+					     NULL,
+					     "drs",
+					     "get_tgt_support",
+					     true)) {
+				getnc_state->is_get_tgt =
+					((req10->more_flags & DRSUAPI_DRS_GET_TGT) != 0);
+			}
+		}
+
 		/* RID_ALLOC returns 3 objects in a fixed order */
 		if (req10->extended_op == DRSUAPI_EXOP_FSMO_RID_ALLOC) {
 			/* Do nothing */
+		} else if (getnc_state->broken_samba_4_5_get_anc_emulation) {
+			LDB_TYPESAFE_QSORT(changes,
+					   getnc_state->num_records,
+					   getnc_state,
+					   site_res_cmp_anc_order);
 		} else {
 			LDB_TYPESAFE_QSORT(changes,
 					   getnc_state->num_records,
@@ -3123,13 +3166,6 @@ allowed:
 		talloc_free(search_res);
 		talloc_free(changes);
 
-		if (req10->extended_op == DRSUAPI_EXOP_NONE) {
-			getnc_state->is_get_anc =
-				((req10->replica_flags & DRSUAPI_DRS_GET_ANC) != 0);
-			getnc_state->is_get_tgt =
-				((req10->more_flags & DRSUAPI_DRS_GET_TGT) != 0);
-		}
-
 		/*
 		 * when using GET_ANC or GET_TGT, cache the objects that have
 		 * been already sent, to avoid sending them multiple times
diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py
index d415f270701..3ee001e147d 100755
--- a/source4/selftest/tests.py
+++ b/source4/selftest/tests.py
@@ -1460,6 +1460,9 @@ planoldpythontestsuite(env, "ridalloc_exop",
 #
 # That is why this test is run on the isolated environment and not on
 # those connected with ad_dc (vampiredc/promoteddc)
+#
+# The chgdcpass enviroment is likewise isolated and emulates Samba 4.5
+# with regard to GET_ANC
 
 env = 'schema_pair_dc'
 planoldpythontestsuite("%s:local" % env, "samba_tool_drs",
@@ -1467,6 +1470,12 @@ planoldpythontestsuite("%s:local" % env, "samba_tool_drs",
                        name="samba4.drs.samba_tool_drs.python(%s)" % env,
                        environ={'DC1': '$DC_SERVER', 'DC2': '$SERVER'},
                        extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])
+for env in ['chgdcpass', 'schema_pair_dc']:
+    planoldpythontestsuite("%s:local" % env, "samba_tool_drs_critical",
+                           extra_path=[os.path.join(samba4srcdir, 'torture/drs/python')],
+                           name="samba4.drs.samba_tool_drs_critical.python(%s)" % env,
+                           environ={'DC1': '$DC_SERVER', 'DC2': '$SERVER'},
+                           extra_args=['-U$DOMAIN/$DC_USERNAME%$DC_PASSWORD'])


-- 
Samba Shared Repository



More information about the samba-cvs mailing list