The branch, master has been updated
       via  d12cb47724c selftest: Update user_account_control tests to pass 
against Windows 2019
       via  35292bd3222 tests/krb5: Allow replicating accounts to the created 
RODC
       via  ef5666bc51c tests/krb5: Create RODC account for testing
       via  3cc9e77f38f tests/krb5: Allow replicating accounts to the RODC
       via  af633992e31 tests/krb5: Add get_secrets() method to get the secret 
attributes of a DN
       via  a5bf7aad54b tests/krb5: Add method to get RODC krbtgt credentials
       via  7bc52cecb44 tests/krb5: Sign-extend kvno from 32-bit integer
       via  19a2af02f57 pyldb: Avoid use-after-free in msg_diff()
       via  c2bbe774ce0 ldb_msg: Don't fail in ldb_msg_copy() if source DN is 
NULL
       via  a99a76722d6 pytest:segfault: Add test for ldb.msg_diff()
       via  943079fd94f tests/krb5: Generate padata for FAST tests
       via  c9fd8ffd892 tests/krb5: Add get_cached_creds() method to create 
persistent accounts for testing
       via  0e99382d73f tests/krb5: Get encpart decryption key from 
kdc_exchange_dict
       via  a5186f92803 tests/krb5: Get expected cname from TGT for TGS-REQ 
messages
       via  4ba5e82ae53 tests/krb5: Allow specifying status code to be checked
      from  d40f57321a1 WHATSNEW: Document changes for "kernel share modes"

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


- Log -----------------------------------------------------------------
commit d12cb47724c2e8d19a28286d4c3ef72271a002fd
Author: Andrew Bartlett <abart...@samba.org>
Date:   Mon Aug 30 18:17:47 2021 +1200

    selftest: Update user_account_control tests to pass against Windows 2019
    
    This gets us closer to passing against Windows 2019, without
    making major changes to what was tested.  More tests are needed,
    but it is important to get what was being tested tested again.
    
    Account types (eg UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT)
    are now required on all objects, this can't be omitted any more.
    
    Also for UF_NORMAL_ACCOUNT for these accounts without a password
    set |UF_PASSWD_NOTREQD must be included.
    
    Signed-off-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Alexander Bokovoy <a...@samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abart...@samba.org>
    Autobuild-Date(master): Wed Sep 15 08:49:11 UTC 2021 on sn-devel-184

commit 35292bd32225b39ad7a03c3aa53027458f0671eb
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 21:24:31 2021 +1200

    tests/krb5: Allow replicating accounts to the created RODC
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit ef5666bc51ca80e1acdadd525a9c61762756c8e3
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 21:24:05 2021 +1200

    tests/krb5: Create RODC account for testing
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 3cc9e77f38f6698aa01abca4285a520c7c0cd2ac
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 22:13:24 2021 +1200

    tests/krb5: Allow replicating accounts to the RODC
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit af633992e31e839cdd7f77740c1f25d129be2f79
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 20:58:01 2021 +1200

    tests/krb5: Add get_secrets() method to get the secret attributes of a DN
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit a5bf7aad54b7053417a24ae0918ee42ceed7bf21
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 20:20:23 2021 +1200

    tests/krb5: Add method to get RODC krbtgt credentials
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 7bc52cecb442c4bcbd39372a8b98bb033e4d1540
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 21:14:18 2021 +1200

    tests/krb5: Sign-extend kvno from 32-bit integer
    
    This helps to avoid problems with RODC kvnos that have the high bit set.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 19a2af02f57d99db8ed3c6b028c3abdf4b553700
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 11:15:17 2021 +1200

    pyldb: Avoid use-after-free in msg_diff()
    
    Make a deep copy of the message elements in msg_diff() so that if either
    of the input messages are deallocated early, the result does not refer
    to non-existing elements.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit c2bbe774ce03661666a1f48922a9ab681ef4f64b
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Tue Sep 14 11:08:41 2021 +1200

    ldb_msg: Don't fail in ldb_msg_copy() if source DN is NULL
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit a99a76722d6046a5d63032e3d2bb3f791da948a6
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Mon Sep 13 11:34:56 2021 +1200

    pytest:segfault: Add test for ldb.msg_diff()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14836
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 943079fd94fec66cdc2ba4ea1b2beb2971473004
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Wed Sep 8 11:28:52 2021 +1200

    tests/krb5: Generate padata for FAST tests
    
    This gives us access to parameters of kdc_exchange_dict and enables us
    to simplify the logic.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit c9fd8ffd8927ef42fd555e690f966f65aa01332e
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Fri Sep 3 15:36:24 2021 +1200

    tests/krb5: Add get_cached_creds() method to create persistent accounts for 
testing
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 0e99382d73f44eed7e19e83e430938d587e762d0
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Fri Sep 3 09:55:10 2021 +1200

    tests/krb5: Get encpart decryption key from kdc_exchange_dict
    
    Instead of using check_padata_fn to get the encpart decryption key, we
    can get the key from the AS-REQ preauth phase or from the TGT, depending
    on whether the message is an AS-REQ or a TGS-REQ. This allows removal of
    check_padata_fn and some duplicated code.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit a5186f92803009c81eca2957e1bf2eb0ff7b6dff
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Fri Sep 3 09:40:02 2021 +1200

    tests/krb5: Get expected cname from TGT for TGS-REQ messages
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

commit 4ba5e82ae53410ec9a0bc7d47b181a88c15d9387
Author: Joseph Sutton <josephsut...@catalyst.net.nz>
Date:   Wed Sep 1 19:26:43 2021 +1200

    tests/krb5: Allow specifying status code to be checked
    
    This allows us to check the status code that may be sent in an error
    reply to a TGS-REQ message.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642
    
    Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz>

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

Summary of changes:
 lib/ldb/common/ldb_msg.c                          |   6 +-
 lib/ldb/pyldb.c                                   |  18 +-
 python/samba/tests/krb5/fast_tests.py             | 136 ++---
 python/samba/tests/krb5/kdc_base_test.py          | 586 +++++++++++++++++++---
 python/samba/tests/krb5/raw_testcase.py           | 134 +++--
 python/samba/tests/segfault.py                    |  12 +
 selftest/knownfail.d/user_account_control         |   1 +
 source4/dsdb/tests/python/user_account_control.py | 114 ++++-
 8 files changed, 787 insertions(+), 220 deletions(-)
 create mode 100644 selftest/knownfail.d/user_account_control


Changeset truncated at 500 lines:

diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c
index 0179c35659b..57dfc5a04c2 100644
--- a/lib/ldb/common/ldb_msg.c
+++ b/lib/ldb/common/ldb_msg.c
@@ -876,8 +876,10 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
        msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
        if (msg2 == NULL) return NULL;
 
-       msg2->dn = ldb_dn_copy(msg2, msg2->dn);
-       if (msg2->dn == NULL) goto failed;
+       if (msg2->dn != NULL) {
+               msg2->dn = ldb_dn_copy(msg2, msg2->dn);
+               if (msg2->dn == NULL) goto failed;
+       }
 
        for (i=0;i<msg2->num_elements;i++) {
                struct ldb_message_element *el = &msg2->elements[i];
diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c
index f849e7eb8e6..f1538b37c6b 100644
--- a/lib/ldb/pyldb.c
+++ b/lib/ldb/pyldb.c
@@ -1804,6 +1804,7 @@ static PyObject *py_ldb_msg_diff(PyLdbObject *self, 
PyObject *args)
        struct ldb_message *diff;
        struct ldb_context *ldb;
        PyObject *py_ret;
+       TALLOC_CTX *mem_ctx = NULL;
 
        if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
                return NULL;
@@ -1818,19 +1819,32 @@ static PyObject *py_ldb_msg_diff(PyLdbObject *self, 
PyObject *args)
                return NULL;
        }
 
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
        ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
-       ldb_ret = ldb_msg_difference(ldb, ldb,
+       ldb_ret = ldb_msg_difference(ldb, mem_ctx,
                                     pyldb_Message_AsMessage(py_msg_old),
                                     pyldb_Message_AsMessage(py_msg_new),
                                     &diff);
        if (ldb_ret != LDB_SUCCESS) {
+               talloc_free(mem_ctx);
                PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb 
Message diff");
                return NULL;
        }
 
+       diff = ldb_msg_copy(mem_ctx, diff);
+       if (diff == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
        py_ret = PyLdbMessage_FromMessage(diff);
 
-       talloc_unlink(ldb, diff);
+       talloc_free(mem_ctx);
 
        return py_ret;
 }
diff --git a/python/samba/tests/krb5/fast_tests.py 
b/python/samba/tests/krb5/fast_tests.py
index 6f3738257b5..ae696e88c78 100755
--- a/python/samba/tests/krb5/fast_tests.py
+++ b/python/samba/tests/krb5/fast_tests.py
@@ -45,7 +45,6 @@ from samba.tests.krb5.rfc4120_constants import (
     KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
     KRB_AS_REP,
     KRB_TGS_REP,
-    KU_AS_REP_ENC_PART,
     KU_TICKET,
     NT_PRINCIPAL,
     NT_SRV_INST,
@@ -207,18 +206,12 @@ class FAST_Tests(KDCBaseTest):
         ])
 
     def test_simple_tgs_wrong_principal(self):
-        mach_creds = self.get_mach_creds()
-        mach_name = mach_creds.get_username()
-        expected_cname = self.PrincipalName_create(
-            name_type=NT_PRINCIPAL, names=[mach_name])
-
         self._run_test_sequence([
             {
                 'rep_type': KRB_TGS_REP,
                 'expected_error_mode': 0,
                 'use_fast': False,
-                'gen_tgt_fn': self.get_mach_tgt,
-                'expected_cname': expected_cname
+                'gen_tgt_fn': self.get_mach_tgt
             }
         ])
 
@@ -1067,19 +1060,6 @@ class FAST_Tests(KDCBaseTest):
         # challenge is only considered a replay if the ciphertext is identical
         # to a previous challenge. Windows does not perform this check.
 
-        class GenerateEncChallengePadataReplay:
-            def __init__(replay):
-                replay._padata = None
-
-            def __call__(replay, key, armor_key):
-                if replay._padata is None:
-                    client_challenge_key = (
-                        self.generate_client_challenge_key(armor_key, key))
-                    replay._padata = self.get_challenge_pa_data(
-                        client_challenge_key)
-
-                return replay._padata
-
         self._run_test_sequence([
             {
                 'rep_type': KRB_AS_REP,
@@ -1092,28 +1072,72 @@ class FAST_Tests(KDCBaseTest):
                 'rep_type': KRB_AS_REP,
                 'expected_error_mode': 0,
                 'use_fast': True,
-                'gen_padata_fn': GenerateEncChallengePadataReplay(),
+                'gen_padata_fn': self.generate_enc_challenge_padata_replay,
                 'fast_armor': FX_FAST_ARMOR_AP_REQUEST,
                 'gen_armor_tgt_fn': self.get_mach_tgt,
                 'repeat': 2
             }
         ])
 
-    def generate_enc_timestamp_padata(self, key, _armor_key):
-        return self.get_enc_timestamp_pa_data_from_key(key)
+    def generate_enc_timestamp_padata(self,
+                                      kdc_exchange_dict,
+                                      callback_dict,
+                                      req_body):
+        key = kdc_exchange_dict['preauth_key']
+
+        padata = self.get_enc_timestamp_pa_data_from_key(key)
+        return [padata], req_body
+
+    def generate_enc_challenge_padata(self,
+                                      kdc_exchange_dict,
+                                      callback_dict,
+                                      req_body,
+                                      skew=0):
+        armor_key = kdc_exchange_dict['armor_key']
+        key = kdc_exchange_dict['preauth_key']
 
-    def generate_enc_challenge_padata(self, key, armor_key, skew=0):
         client_challenge_key = (
             self.generate_client_challenge_key(armor_key, key))
-        return self.get_challenge_pa_data(client_challenge_key, skew=skew)
+        padata = self.get_challenge_pa_data(client_challenge_key, skew=skew)
+        return [padata], req_body
+
+    def generate_enc_challenge_padata_wrong_key_kdc(self,
+                                      kdc_exchange_dict,
+                                      callback_dict,
+                                      req_body):
+        armor_key = kdc_exchange_dict['armor_key']
+        key = kdc_exchange_dict['preauth_key']
 
-    def generate_enc_challenge_padata_wrong_key_kdc(self, key, armor_key):
         kdc_challenge_key = (
             self.generate_kdc_challenge_key(armor_key, key))
-        return self.get_challenge_pa_data(kdc_challenge_key)
+        padata = self.get_challenge_pa_data(kdc_challenge_key)
+        return [padata], req_body
+
+    def generate_enc_challenge_padata_wrong_key(self,
+                                                kdc_exchange_dict,
+                                                callback_dict,
+                                                req_body):
+        key = kdc_exchange_dict['preauth_key']
+
+        padata = self.get_challenge_pa_data(key)
+        return [padata], req_body
+
+    def generate_enc_challenge_padata_replay(self,
+                                             kdc_exchange_dict,
+                                             callback_dict,
+                                             req_body):
+        padata = callback_dict.get('replay_padata')
+
+        if padata is None:
+            armor_key = kdc_exchange_dict['armor_key']
+            key = kdc_exchange_dict['preauth_key']
 
-    def generate_enc_challenge_padata_wrong_key(self, key, _armor_key):
-        return self.get_challenge_pa_data(key)
+            client_challenge_key = (
+                self.generate_client_challenge_key(armor_key, key))
+            padata = self.get_challenge_pa_data(client_challenge_key)
+            callback_dict['replay_padata'] = padata
+
+        return [padata], req_body
 
     def generate_empty_fast(self,
                             _kdc_exchange_dict,
@@ -1158,13 +1182,11 @@ class FAST_Tests(KDCBaseTest):
         target_sname = self.PrincipalName_create(
             name_type=NT_SRV_INST, names=[target_service, target_username])
         target_decryption_key = self.TicketDecryptionKey_from_creds(
-            target_creds, etype=kcrypto.Enctype.RC4)
+            target_creds)
 
         fast_cookie = None
         preauth_etype_info2 = None
 
-        preauth_key = None
-
         for kdc_dict in test_sequence:
             rep_type = kdc_dict.pop('rep_type')
             self.assertIn(rep_type, (KRB_AS_REP, KRB_TGS_REP))
@@ -1236,7 +1258,12 @@ class FAST_Tests(KDCBaseTest):
             else:  # KRB_TGS_REP
                 srealm = target_realm
 
-            expected_cname = kdc_dict.pop('expected_cname', client_cname)
+            if rep_type == KRB_TGS_REP:
+                tgt_cname = tgt.cname
+            else:
+                tgt_cname = client_cname
+
+            expected_cname = kdc_dict.pop('expected_cname', tgt_cname)
             expected_anon = kdc_dict.pop('expected_anon',
                                          False)
             expected_crealm = kdc_dict.pop('expected_crealm', client_realm)
@@ -1293,52 +1320,30 @@ class FAST_Tests(KDCBaseTest):
                                       padata):
                 return list(padata), req_body
 
-            def _check_padata_preauth_key(_kdc_exchange_dict,
-                                          _callback_dict,
-                                          _rep,
-                                          _padata):
-                as_rep_usage = KU_AS_REP_ENC_PART
-                return preauth_key, as_rep_usage
-
             pac_options = kdc_dict.pop('pac_options', '1')  # claims support
 
             kdc_options = kdc_dict.pop('kdc_options', kdc_options_default)
 
             gen_padata_fn = kdc_dict.pop('gen_padata_fn', None)
-            if gen_padata_fn is not None:
-                self.assertEqual(KRB_AS_REP, rep_type)
+
+            if rep_type == KRB_AS_REP and gen_padata_fn is not None:
                 self.assertIsNotNone(preauth_etype_info2)
 
                 preauth_key = self.PasswordKey_from_etype_info2(
                     client_creds,
                     preauth_etype_info2[0],
                     client_creds.get_kvno())
-                padata = [gen_padata_fn(preauth_key, armor_key)]
             else:
                 preauth_key = None
-                padata = []
-
-            if rep_type == KRB_AS_REP:
-                check_padata_fn = _check_padata_preauth_key
-            else:
-                check_padata_fn = self.check_simple_tgs_padata
 
             if use_fast:
-                inner_padata = padata
-                outer_padata = []
+                generate_fast_padata_fn = gen_padata_fn
+                generate_padata_fn = (functools.partial(_generate_padata_copy,
+                                                         padata=[fast_cookie])
+                                       if fast_cookie is not None else None)
             else:
-                inner_padata = []
-                outer_padata = padata
-
-            if use_fast and fast_cookie is not None:
-                outer_padata.append(fast_cookie)
-
-            generate_fast_padata_fn = (functools.partial(_generate_padata_copy,
-                                                         padata=inner_padata)
-                                       if inner_padata else None)
-            generate_padata_fn = (functools.partial(_generate_padata_copy,
-                                                    padata=outer_padata)
-                                  if outer_padata else None)
+                generate_fast_padata_fn = None
+                generate_padata_fn = gen_padata_fn
 
             gen_authdata_fn = kdc_dict.pop('gen_authdata_fn', None)
             if gen_authdata_fn is not None:
@@ -1376,13 +1381,13 @@ class FAST_Tests(KDCBaseTest):
                     generate_padata_fn=generate_padata_fn,
                     check_error_fn=check_error_fn,
                     check_rep_fn=check_rep_fn,
-                    check_padata_fn=check_padata_fn,
                     check_kdc_private_fn=self.generic_check_kdc_private,
                     callback_dict={},
                     expected_error_mode=expected_error_mode,
                     client_as_etypes=etypes,
                     expected_salt=expected_salt,
                     authenticator_subkey=authenticator_subkey,
+                    preauth_key=preauth_key,
                     auth_data=auth_data,
                     armor_key=armor_key,
                     armor_tgt=armor_tgt,
@@ -1409,7 +1414,6 @@ class FAST_Tests(KDCBaseTest):
                     generate_padata_fn=generate_padata_fn,
                     check_error_fn=check_error_fn,
                     check_rep_fn=check_rep_fn,
-                    check_padata_fn=check_padata_fn,
                     check_kdc_private_fn=self.generic_check_kdc_private,
                     expected_error_mode=expected_error_mode,
                     callback_dict={},
diff --git a/python/samba/tests/krb5/kdc_base_test.py 
b/python/samba/tests/krb5/kdc_base_test.py
index 49a3227c26e..0e138352b06 100644
--- a/python/samba/tests/krb5/kdc_base_test.py
+++ b/python/samba/tests/krb5/kdc_base_test.py
@@ -22,6 +22,7 @@ from datetime import datetime, timezone
 import tempfile
 import binascii
 import collections
+import secrets
 
 from collections import namedtuple
 import ldb
@@ -30,18 +31,24 @@ from samba import generate_random_password
 from samba.auth import system_session
 from samba.credentials import Credentials, SPECIFIED, MUST_USE_KERBEROS
 from samba.dcerpc import drsblobs, drsuapi, misc, krb5pac, krb5ccache, security
-from samba.drs_utils import drsuapi_connect
+from samba.drs_utils import drs_Replicate, drsuapi_connect
 from samba.dsdb import (
+    DSDB_SYNTAX_BINARY_DN,
     DS_DOMAIN_FUNCTION_2000,
     DS_DOMAIN_FUNCTION_2008,
     DS_GUID_COMPUTERS_CONTAINER,
     DS_GUID_USERS_CONTAINER,
     UF_WORKSTATION_TRUST_ACCOUNT,
-    UF_NORMAL_ACCOUNT
+    UF_NO_AUTH_DATA_REQUIRED,
+    UF_NORMAL_ACCOUNT,
+    UF_NOT_DELEGATED,
+    UF_PARTIAL_SECRETS_ACCOUNT,
+    UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
 )
+from samba.join import DCJoinContext
 from samba.ndr import ndr_pack, ndr_unpack
 from samba import net
-from samba.samdb import SamDB
+from samba.samdb import SamDB, dsdb_Dn
 
 from samba.tests import delete_force
 import samba.tests.krb5.kcrypto as kcrypto
@@ -85,20 +92,43 @@ class KDCBaseTest(RawKerberosTest):
         cls._lp = None
 
         cls._ldb = None
+        cls._rodc_ldb = None
 
         cls._functional_level = None
 
+        # An identifier to ensure created accounts have unique names. Windows
+        # caches accounts based on usernames, so account names being different
+        # across test runs avoids previous test runs affecting the results.
+        cls.account_base = f'krb5_{secrets.token_hex(5)}_'
+        cls.account_id = 0
+
         # A set containing DNs of accounts created as part of testing.
         cls.accounts = set()
 
+        cls.account_cache = {}
+
+        cls._rodc_ctx = None
+
+        cls.ldb_cleanups = []
+
     @classmethod
     def tearDownClass(cls):
         # Clean up any accounts created by create_account. This is
         # done in tearDownClass() rather than tearDown(), so that
         # accounts need only be created once for permutation tests.
         if cls._ldb is not None:
+            for cleanup in reversed(cls.ldb_cleanups):
+                try:
+                    cls._ldb.modify(cleanup)
+                except ldb.LdbError:
+                    pass
+
             for dn in cls.accounts:
                 delete_force(cls._ldb, dn)
+
+        if cls._rodc_ctx is not None:
+            cls._rodc_ctx.cleanup_old_join(force=True)
+
         super().tearDownClass()
 
     def setUp(self):
@@ -125,6 +155,49 @@ class KDCBaseTest(RawKerberosTest):
 
         return self._ldb
 
+    def get_rodc_samdb(self):
+        if self._rodc_ldb is None:
+            creds = self.get_admin_creds()
+            lp = self.get_lp()
+
+            session = system_session()
+            type(self)._rodc_ldb = SamDB(url="ldap://%s"; % self.host,
+                                         session_info=session,
+                                         credentials=creds,
+                                         lp=lp,
+                                         am_rodc=True)
+
+        return self._rodc_ldb
+
+    def get_server_dn(self, samdb):
+        server = samdb.get_serverName()
+
+        res = samdb.search(base=server,
+                           scope=ldb.SCOPE_BASE,
+                           attrs=['serverReference'])
+        dn = ldb.Dn(samdb, res[0]['serverReference'][0].decode('utf8'))
+
+        return dn
+
+    def get_mock_rodc_ctx(self):
+        if self._rodc_ctx is None:
+            admin_creds = self.get_admin_creds()
+            lp = self.get_lp()
+
+            rodc_name = 'KRB5RODC'
+            site_name = 'Default-First-Site-Name'
+
+            type(self)._rodc_ctx = DCJoinContext(server=self.dc_host,
+                                                 creds=admin_creds,
+                                                 lp=lp,
+                                                 site=site_name,
+                                                 netbios_name=rodc_name,
+                                                 targetdir=None,
+                                                 domain=None)
+            self.create_rodc(self._rodc_ctx)
+
+        return self._rodc_ctx
+
     def get_domain_functional_level(self, ldb):
         if self._functional_level is None:
             res = ldb.search(base='',
@@ -213,7 +286,132 @@ class KDCBaseTest(RawKerberosTest):
 
         return (creds, dn)
 
-    def get_keys(self, samdb, dn):
+    def create_rodc(self, ctx):
+        ctx.nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn]
+        ctx.full_nc_list = [ctx.base_dn, ctx.config_dn, ctx.schema_dn]
+        ctx.krbtgt_dn = f'CN=krbtgt_{ctx.myname},CN=Users,{ctx.base_dn}'
+
+        ctx.never_reveal_sid = 
[f'<SID={ctx.domsid}-{security.DOMAIN_RID_RODC_DENY}>',
+                                f'<SID={security.SID_BUILTIN_ADMINISTRATORS}>',
+                                
f'<SID={security.SID_BUILTIN_SERVER_OPERATORS}>',
+                                
f'<SID={security.SID_BUILTIN_BACKUP_OPERATORS}>',
+                                
f'<SID={security.SID_BUILTIN_ACCOUNT_OPERATORS}>']
+        ctx.reveal_sid = f'<SID={ctx.domsid}-{security.DOMAIN_RID_RODC_ALLOW}>'
+
+        mysid = ctx.get_mysid()
+        admin_dn = f'<SID={mysid}>'
+        ctx.managedby = admin_dn
+
+        ctx.userAccountControl = (UF_WORKSTATION_TRUST_ACCOUNT |
+                                  UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |
+                                  UF_PARTIAL_SECRETS_ACCOUNT)
+
+        ctx.connection_dn = f'CN=RODC Connection (FRS),{ctx.ntds_dn}'
+        ctx.secure_channel_type = misc.SEC_CHAN_RODC
+        ctx.RODC = True
+        ctx.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC |
+                             drsuapi.DRSUAPI_DRS_PER_SYNC |
+                             drsuapi.DRSUAPI_DRS_GET_ANC |
+                             drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
+                             drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
+        ctx.domain_replica_flags = ctx.replica_flags | 
drsuapi.DRSUAPI_DRS_CRITICAL_ONLY
+
+        ctx.build_nc_lists()
+
+        ctx.cleanup_old_join()
+
+        try:
+            ctx.join_add_objects()
+        except Exception:
+            # cleanup the failed join (checking we still have a live LDB
+            # connection to the remote DC first)
+            ctx.refresh_ldb_connection()
+            ctx.cleanup_old_join()
+            raise
+
+    def replicate_account_to_rodc(self, dn):
+        samdb = self.get_samdb()
+        rodc_samdb = self.get_rodc_samdb()
+
+        repl_val = f'{samdb.get_dsServiceName()}:{dn}:SECRETS_ONLY'
+
+        msg = ldb.Message()


-- 
Samba Shared Repository

Reply via email to