From 5559755e15e72712dfc12f88cf0fc16c6565136c Mon Sep 17 00:00:00 2001 From: shirely Date: Fri, 29 Jul 2022 16:24:16 +0800 Subject: [PATCH] fix CVE-2022-32746 CVE-2022-2031 CVE-2022-32744 CVE-2022-32742 CVE-2022-32745 --- backport-CVE-2022-2031-CVE-2022-32744.patch | 11383 ++++++++++++++++++ backport-CVE-2022-32742.patch | 216 + backport-CVE-2022-32745.patch | 163 + backport-CVE-2022-32746.patch | 1854 +++ samba.spec | 14 +- 5 files changed, 13629 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2022-2031-CVE-2022-32744.patch create mode 100644 backport-CVE-2022-32742.patch create mode 100644 backport-CVE-2022-32745.patch create mode 100644 backport-CVE-2022-32746.patch diff --git a/backport-CVE-2022-2031-CVE-2022-32744.patch b/backport-CVE-2022-2031-CVE-2022-32744.patch new file mode 100644 index 0000000..fcb80a5 --- /dev/null +++ b/backport-CVE-2022-2031-CVE-2022-32744.patch @@ -0,0 +1,11383 @@ +From c8ef1ef980a1281ec7edd1788dad9e22889d995a Mon Sep 17 00:00:00 2001 +From: Isaac Boukris +Date: Sat, 19 Sep 2020 14:16:20 +0200 +Subject: [PATCH 19/99] s4:mit-kdb: Force canonicalization for looking up + principals + +See also +https://github.com/krb5/krb5/commit/ac8865a22138ab0c657208c41be8fd6bc7968148 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Isaac Boukris +Signed-off-by: Andreas Schneider +Reviewed-by: Alexander Bokovoy + +Autobuild-User(master): Andreas Schneider +Autobuild-Date(master): Mon Nov 29 09:32:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 90febd2a33b88af49af595fe0e995d6ba0f33a1b) +--- + selftest/knownfail_mit_kdc | 14 -------------- + source4/heimdal/lib/hdb/hdb.h | 1 + + source4/kdc/db-glue.c | 7 ++++++- + source4/kdc/mit_samba.c | 8 ++++++++ + source4/kdc/sdb.h | 1 + + 5 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index cc7b501c6bf..c046a46a4f3 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -379,8 +379,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied +@@ -408,8 +406,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_other_sname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link +@@ -422,10 +418,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_cname_host +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_cname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_correct_realm +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_other_cname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_tgt_wrong_realm + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm +@@ -471,12 +463,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_user_pac_request_true + # + # PAC requester SID tests + # +diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h +index 5ef9d9565f3..dafaffc6c2d 100644 +--- a/source4/heimdal/lib/hdb/hdb.h ++++ b/source4/heimdal/lib/hdb/hdb.h +@@ -63,6 +63,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK }; + #define HDB_F_ALL_KVNOS 2048 /* we want all the keys, live or not */ + #define HDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define HDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define HDB_F_FORCE_CANON 16384 /* force canonicalition */ + + /* hdb_capability_flags */ + #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1 +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 3a7e2176653..ac47fe78373 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -957,11 +957,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + krb5_clear_error_message(context); + goto out; + } +- } else if ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) { ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ + * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. + */ + ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); + if (ret) { +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 4239332f0d9..53c137de2fd 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -221,6 +221,14 @@ int mit_samba_get_principal(struct mit_samba_context *ctx, + return ENOMEM; + } + ++#if KRB5_KDB_API_VERSION >= 10 ++ /* ++ * The MIT KDC code that wants the canonical name in all lookups, and ++ * takes care to canonicalize only when appropriate. ++ */ ++ sflags |= SDB_F_FORCE_CANON; ++#endif ++ + if (kflags & KRB5_KDB_FLAG_CANONICALIZE) { + sflags |= SDB_F_CANON; + } +diff --git a/source4/kdc/sdb.h b/source4/kdc/sdb.h +index c929acccce6..a9115ec23d7 100644 +--- a/source4/kdc/sdb.h ++++ b/source4/kdc/sdb.h +@@ -116,6 +116,7 @@ struct sdb_entry_ex { + #define SDB_F_KVNO_SPECIFIED 128 /* we want a particular KVNO */ + #define SDB_F_FOR_AS_REQ 4096 /* fetch is for a AS REQ */ + #define SDB_F_FOR_TGS_REQ 8192 /* fetch is for a TGS REQ */ ++#define SDB_F_FORCE_CANON 16384 /* force canonicalition */ + + void sdb_free_entry(struct sdb_entry_ex *e); + void free_sdb_entry(struct sdb_entry *s); +-- +2.25.1 + + +From f40a974045a34c40f378dd9d96a4d401c3bb9a72 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 21 Dec 2021 12:17:11 +0100 +Subject: [PATCH 20/99] s4:kdc: Also cannoicalize krbtgt principals when + enforcing canonicalization + +Signed-off-by: Andreas Schneider +Reviewed-by: Stefan Metzmacher +(cherry picked from commit f1ec950aeb47283a504018bafa21f54c3282e70c) +--- + source4/kdc/db-glue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index ac47fe78373..d017741e30a 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -920,7 +920,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; + +- if (flags & (SDB_F_CANON)) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { + /* + * When requested to do so, ensure that the + * both realm values in the principal are set +-- +2.25.1 + + +From 8373345853a59265a9e6d2a826983aa8a4b7a4ea Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:30:38 +1300 +Subject: [PATCH 21/99] selftest: Check received LDB error code when + STRICT_CHECKING=0 + +We were instead only checking the expected error. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ad4d6fb01fd8083e68f07c427af8932574810cdc) +--- + source4/dsdb/tests/python/priv_attrs.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/dsdb/tests/python/priv_attrs.py b/source4/dsdb/tests/python/priv_attrs.py +index aa35dcc1317..4dfdfb9cbb8 100644 +--- a/source4/dsdb/tests/python/priv_attrs.py ++++ b/source4/dsdb/tests/python/priv_attrs.py +@@ -167,7 +167,7 @@ class PrivAttrsTests(samba.tests.TestCase): + creds_tmp.set_kerberos_state(DONT_USE_KERBEROS) # kinit is too expensive to use in a tight loop + return creds_tmp + +- def assertGotLdbError(self, got, wanted): ++ def assertGotLdbError(self, wanted, got): + if not self.strict_checking: + self.assertNotEqual(got, ldb.SUCCESS) + else: +-- +2.25.1 + + +From bc1e71396ad41c37f5fa2101cb5e5e44dc221364 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:53:18 +1300 +Subject: [PATCH 22/99] tests/krb5: Remove unused variable + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 57b1b76154d699b9d70ad04fa5e94c4b30f0e4bf) +--- + python/samba/tests/krb5/raw_testcase.py | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 42f2e94f5aa..36a6134e6c9 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -2855,7 +2855,6 @@ class RawKerberosTest(TestCaseInTempDir): + + expect_etype_info2 = () + expect_etype_info = False +- unexpect_etype_info = True + expected_aes_type = 0 + expected_rc4_type = 0 + if kcrypto.Enctype.RC4 in proposed_etypes: +@@ -2868,7 +2867,6 @@ class RawKerberosTest(TestCaseInTempDir): + if etype > expected_aes_type: + expected_aes_type = etype + if etype in (kcrypto.Enctype.RC4,) and error_code != 0: +- unexpect_etype_info = False + if etype > expected_rc4_type: + expected_rc4_type = etype + +-- +2.25.1 + + +From 3059417db81edb174da640eb78d4dd6dab5f3120 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:34:11 +1300 +Subject: [PATCH 23/99] tests/krb5: Deduplicate AS-REQ tests + +salt_tests was running the tests defined in the base class as well as +its own tests. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit f0b222e3ecf72c8562bc97bedd9f3a92980b60d5) +--- + python/samba/tests/krb5/as_req_tests.py | 163 ++++++++++++------------ + python/samba/tests/krb5/salt_tests.py | 4 +- + 2 files changed, 85 insertions(+), 82 deletions(-) + +diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py +index 08081928363..315720f85d6 100755 +--- a/python/samba/tests/krb5/as_req_tests.py ++++ b/python/samba/tests/krb5/as_req_tests.py +@@ -38,87 +38,8 @@ from samba.tests.krb5.rfc4120_constants import ( + global_asn1_print = False + global_hexdump = False + +-@DynamicTestCase +-class AsReqKerberosTests(KDCBaseTest): +- +- @classmethod +- def setUpDynamicTestCases(cls): +- for (name, idx) in cls.etype_test_permutation_name_idx(): +- for pac in [None, True, False]: +- tname = "%s_pac_%s" % (name, pac) +- targs = (idx, pac) +- cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs) +- +- def setUp(self): +- super(AsReqKerberosTests, self).setUp() +- self.do_asn1_print = global_asn1_print +- self.do_hexdump = global_hexdump +- +- def _test_as_req_nopreauth(self, +- initial_etypes, +- pac=None, +- initial_kdc_options=None): +- client_creds = self.get_client_creds() +- client_account = client_creds.get_username() +- client_as_etypes = self.get_default_enctypes() +- krbtgt_creds = self.get_krbtgt_creds(require_keys=False) +- krbtgt_account = krbtgt_creds.get_username() +- realm = krbtgt_creds.get_realm() +- +- cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[client_account]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=[krbtgt_account, realm]) +- +- expected_crealm = realm +- expected_cname = cname +- expected_srealm = realm +- expected_sname = sname +- expected_salt = client_creds.get_salt() +- +- if any(etype in client_as_etypes and etype in initial_etypes +- for etype in (kcrypto.Enctype.AES256, +- kcrypto.Enctype.AES128, +- kcrypto.Enctype.RC4)): +- expected_error_mode = KDC_ERR_PREAUTH_REQUIRED +- else: +- expected_error_mode = KDC_ERR_ETYPE_NOSUPP +- +- kdc_exchange_dict = self.as_exchange_dict( +- expected_crealm=expected_crealm, +- expected_cname=expected_cname, +- expected_srealm=expected_srealm, +- expected_sname=expected_sname, +- generate_padata_fn=None, +- check_error_fn=self.generic_check_kdc_error, +- check_rep_fn=None, +- expected_error_mode=expected_error_mode, +- client_as_etypes=client_as_etypes, +- expected_salt=expected_salt, +- kdc_options=str(initial_kdc_options), +- pac_request=pac) +- +- self._generic_kdc_exchange(kdc_exchange_dict, +- cname=cname, +- realm=realm, +- sname=sname, +- etypes=initial_etypes) +- +- def _test_as_req_no_preauth_with_args(self, etype_idx, pac): +- name, etypes = self.etype_test_permutation_by_idx(etype_idx) +- self._test_as_req_nopreauth( +- pac=pac, +- initial_etypes=etypes, +- initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) +- +- def test_as_req_enc_timestamp(self): +- client_creds = self.get_client_creds() +- self._run_as_req_enc_timestamp(client_creds) +- +- def test_as_req_enc_timestamp_mac(self): +- client_creds = self.get_mach_creds() +- self._run_as_req_enc_timestamp(client_creds) + ++class AsReqBaseTest(KDCBaseTest): + def _run_as_req_enc_timestamp(self, client_creds): + client_account = client_creds.get_username() + client_as_etypes = self.get_default_enctypes() +@@ -207,6 +128,88 @@ class AsReqKerberosTests(KDCBaseTest): + return etype_info2 + + ++@DynamicTestCase ++class AsReqKerberosTests(AsReqBaseTest): ++ ++ @classmethod ++ def setUpDynamicTestCases(cls): ++ for (name, idx) in cls.etype_test_permutation_name_idx(): ++ for pac in [None, True, False]: ++ tname = "%s_pac_%s" % (name, pac) ++ targs = (idx, pac) ++ cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs) ++ ++ def setUp(self): ++ super(AsReqKerberosTests, self).setUp() ++ self.do_asn1_print = global_asn1_print ++ self.do_hexdump = global_hexdump ++ ++ def _test_as_req_nopreauth(self, ++ initial_etypes, ++ pac=None, ++ initial_kdc_options=None): ++ client_creds = self.get_client_creds() ++ client_account = client_creds.get_username() ++ client_as_etypes = self.get_default_enctypes() ++ krbtgt_creds = self.get_krbtgt_creds(require_keys=False) ++ krbtgt_account = krbtgt_creds.get_username() ++ realm = krbtgt_creds.get_realm() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[client_account]) ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) ++ ++ expected_crealm = realm ++ expected_cname = cname ++ expected_srealm = realm ++ expected_sname = sname ++ expected_salt = client_creds.get_salt() ++ ++ if any(etype in client_as_etypes and etype in initial_etypes ++ for etype in (kcrypto.Enctype.AES256, ++ kcrypto.Enctype.AES128, ++ kcrypto.Enctype.RC4)): ++ expected_error_mode = KDC_ERR_PREAUTH_REQUIRED ++ else: ++ expected_error_mode = KDC_ERR_ETYPE_NOSUPP ++ ++ kdc_exchange_dict = self.as_exchange_dict( ++ expected_crealm=expected_crealm, ++ expected_cname=expected_cname, ++ expected_srealm=expected_srealm, ++ expected_sname=expected_sname, ++ generate_padata_fn=None, ++ check_error_fn=self.generic_check_kdc_error, ++ check_rep_fn=None, ++ expected_error_mode=expected_error_mode, ++ client_as_etypes=client_as_etypes, ++ expected_salt=expected_salt, ++ kdc_options=str(initial_kdc_options), ++ pac_request=pac) ++ ++ self._generic_kdc_exchange(kdc_exchange_dict, ++ cname=cname, ++ realm=realm, ++ sname=sname, ++ etypes=initial_etypes) ++ ++ def _test_as_req_no_preauth_with_args(self, etype_idx, pac): ++ name, etypes = self.etype_test_permutation_by_idx(etype_idx) ++ self._test_as_req_nopreauth( ++ pac=pac, ++ initial_etypes=etypes, ++ initial_kdc_options=krb5_asn1.KDCOptions('forwardable')) ++ ++ def test_as_req_enc_timestamp(self): ++ client_creds = self.get_client_creds() ++ self._run_as_req_enc_timestamp(client_creds) ++ ++ def test_as_req_enc_timestamp_mac(self): ++ client_creds = self.get_mach_creds() ++ self._run_as_req_enc_timestamp(client_creds) ++ ++ + if __name__ == "__main__": + global_asn1_print = False + global_hexdump = False +diff --git a/python/samba/tests/krb5/salt_tests.py b/python/samba/tests/krb5/salt_tests.py +index ecbf618e40e..db777f8b7bc 100755 +--- a/python/samba/tests/krb5/salt_tests.py ++++ b/python/samba/tests/krb5/salt_tests.py +@@ -21,7 +21,7 @@ import os + + import ldb + +-from samba.tests.krb5.as_req_tests import AsReqKerberosTests ++from samba.tests.krb5.as_req_tests import AsReqBaseTest + import samba.tests.krb5.kcrypto as kcrypto + + sys.path.insert(0, "bin/python") +@@ -31,7 +31,7 @@ global_asn1_print = False + global_hexdump = False + + +-class SaltTests(AsReqKerberosTests): ++class SaltTests(AsReqBaseTest): + + def setUp(self): + super().setUp() +-- +2.25.1 + + +From 083a777e3d2b18d2e59ee4e04a4387c8db7ec185 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 16:02:00 +1300 +Subject: [PATCH 24/99] tests/krb5: Run test_rpc against member server + +We were instead always running against the DC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 167bd2070483004cd0b9a96ffb40ea73c6ddf579) +--- + python/samba/tests/krb5/test_rpc.py | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py +index 03c125f518a..2d483986e83 100755 +--- a/python/samba/tests/krb5/test_rpc.py ++++ b/python/samba/tests/krb5/test_rpc.py +@@ -58,7 +58,7 @@ class RpcTests(KDCBaseTest): + + samdb = self.get_samdb() + +- mach_name = samdb.host_dns_name() ++ mach_name = self.host + service = "cifs" + + # Create the user account. +@@ -67,7 +67,7 @@ class RpcTests(KDCBaseTest): + use_cache=False) + user_name = user_credentials.get_username() + +- mach_credentials = self.get_dc_creds() ++ mach_credentials = self.get_server_creds() + + # Talk to the KDC to obtain the service ticket, which gets placed into + # the cache. The machine account name has to match the name in the +@@ -114,8 +114,7 @@ class RpcTests(KDCBaseTest): + self.assertEqual(user_name, account_name.string) + + def test_rpc_anonymous(self): +- samdb = self.get_samdb() +- mach_name = samdb.host_dns_name() ++ mach_name = self.host + + anon_creds = credentials.Credentials() + anon_creds.set_anonymous() +@@ -125,7 +124,7 @@ class RpcTests(KDCBaseTest): + + (account_name, _) = conn.GetUserName(None, None, None) + +- self.assertEqual('ANONYMOUS LOGON', account_name.string) ++ self.assertEqual('ANONYMOUS LOGON', account_name.string.upper()) + + + if __name__ == "__main__": +-- +2.25.1 + + +From b797f39871100c8d33900af72608d2dc6ec9f435 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:37:35 +1300 +Subject: [PATCH 25/99] tests/krb5: Allow PasswordKey_create() to use s2kparams + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit a560c2e9ad8abb824d1805c86c656943745f81eb) +--- + python/samba/tests/krb5/raw_testcase.py | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 36a6134e6c9..da3f69c79c6 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -1167,10 +1167,11 @@ class RawKerberosTest(TestCaseInTempDir): + key = kcrypto.Key(etype, contents) + return RodcPacEncryptionKey(key, kvno) + +- def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None): ++ def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None, ++ params=None): + self.assertIsNotNone(pwd) + self.assertIsNotNone(salt) +- key = kcrypto.string_to_key(etype, pwd, salt) ++ key = kcrypto.string_to_key(etype, pwd, salt, params=params) + return RodcPacEncryptionKey(key, kvno) + + def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None): +@@ -1182,9 +1183,11 @@ class RawKerberosTest(TestCaseInTempDir): + nthash = creds.get_nt_hash() + return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno) + ++ params = etype_info2.get('s2kparams') ++ + password = creds.get_password() + return self.PasswordKey_create( +- etype=e, pwd=password, salt=salt, kvno=kvno) ++ etype=e, pwd=password, salt=salt, kvno=kvno, params=params) + + def TicketDecryptionKey_from_creds(self, creds, etype=None): + +-- +2.25.1 + + +From 9fbb213304ecebac5b7620b8f183a5baddeb287d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:40:35 +1300 +Subject: [PATCH 26/99] tests/krb5: Split out methods to create renewable or + invalid tickets + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit e930274aa43810d6485c3c8a7c82958ecb409630) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 68 +++++++++++++----------- + 1 file changed, 36 insertions(+), 32 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index abac5a47a56..0578969ba69 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1786,6 +1786,40 @@ class KdcTgsTests(KDCBaseTest): + + self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) + ++ def _modify_renewable(self, enc_part): ++ # Set the renewable flag. ++ renewable_flag = krb5_asn1.TicketFlags('renewable') ++ pos = len(tuple(renewable_flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + '1' + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ # Set the renew-till time to be in the future. ++ renew_till = self.get_KerberosTime(offset=100 * 60 * 60) ++ enc_part['renew-till'] = renew_till ++ ++ return enc_part ++ ++ def _modify_invalid(self, enc_part): ++ # Set the invalid flag. ++ invalid_flag = krb5_asn1.TicketFlags('invalid') ++ pos = len(tuple(invalid_flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + '1' + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ # Set the ticket start time to be in the past. ++ past_time = self.get_KerberosTime(offset=-100 * 60 * 60) ++ enc_part['starttime'] = past_time ++ ++ return enc_part ++ + def _get_tgt(self, + client_creds, + renewable=False, +@@ -1880,39 +1914,9 @@ class KdcTgsTests(KDCBaseTest): + } + + if renewable: +- def flags_modify_fn(enc_part): +- # Set the renewable flag. +- renewable_flag = krb5_asn1.TicketFlags('renewable') +- pos = len(tuple(renewable_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags +- +- # Set the renew-till time to be in the future. +- renew_till = self.get_KerberosTime(offset=100 * 60 * 60) +- enc_part['renew-till'] = renew_till +- +- return enc_part ++ flags_modify_fn = self._modify_renewable + elif invalid: +- def flags_modify_fn(enc_part): +- # Set the invalid flag. +- invalid_flag = krb5_asn1.TicketFlags('invalid') +- pos = len(tuple(invalid_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags +- +- # Set the ticket start time to be in the past. +- past_time = self.get_KerberosTime(offset=-100 * 60 * 60) +- enc_part['starttime'] = past_time +- +- return enc_part ++ flags_modify_fn = self._modify_invalid + else: + flags_modify_fn = None + +-- +2.25.1 + + +From 9d8786faa9fa6ca1182ec2b382882361a588f54d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 11:52:31 +1300 +Subject: [PATCH 27/99] tests/krb5: Adjust error codes to better match Windows + with PacRequestorEnforcement=2 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit d95705172bcf6fe24817800a4c0009e9cc8be595) +--- + python/samba/tests/krb5/alias_tests.py | 7 +- + python/samba/tests/krb5/kdc_tgs_tests.py | 130 ++++++++---------- + .../ms_kile_client_principal_lookup_tests.py | 39 ++---- + python/samba/tests/krb5/s4u_tests.py | 57 ++++---- + python/samba/tests/krb5/test_rpc.py | 8 +- + selftest/knownfail_heimdal_kdc | 64 +++++++++ + selftest/knownfail_mit_kdc | 11 ++ + 7 files changed, 183 insertions(+), 133 deletions(-) + +diff --git a/python/samba/tests/krb5/alias_tests.py b/python/samba/tests/krb5/alias_tests.py +index 60213845a44..1f63775c189 100755 +--- a/python/samba/tests/krb5/alias_tests.py ++++ b/python/samba/tests/krb5/alias_tests.py +@@ -28,7 +28,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, +- KDC_ERR_CLIENT_NAME_MISMATCH, ++ KDC_ERR_TGT_REVOKED, + NT_PRINCIPAL, + ) + +@@ -168,7 +168,7 @@ class AliasTests(KDCBaseTest): + ctype=None) + return [padata], req_body + +- expected_error_mode = KDC_ERR_CLIENT_NAME_MISMATCH ++ expected_error_mode = KDC_ERR_TGT_REVOKED + + # Make a request using S4U2Self. The request should fail. + kdc_exchange_dict = self.tgs_exchange_dict( +@@ -184,7 +184,8 @@ class AliasTests(KDCBaseTest): + tgt=tgt, + authenticator_subkey=authenticator_subkey, + kdc_options='0', +- expect_pac=True) ++ expect_pac=True, ++ expect_edata=False) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 0578969ba69..7ea15f0fbab 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -23,7 +23,7 @@ import os + import ldb + + +-from samba import dsdb, ntstatus ++from samba import dsdb + + from samba.dcerpc import krb5pac, security + +@@ -38,8 +38,6 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_ERROR, + KRB_TGS_REP, + KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION, +- KDC_ERR_CLIENT_NAME_MISMATCH, + KDC_ERR_GENERIC, + KDC_ERR_MODIFIED, + KDC_ERR_POLICY, +@@ -262,7 +260,7 @@ class KdcTgsTests(KDCBaseTest): + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + + if expect_error: +- expected_error_mode = KDC_ERR_BADOPTION ++ expected_error_mode = KDC_ERR_TGT_REVOKED + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: +@@ -288,7 +286,8 @@ class KdcTgsTests(KDCBaseTest): + authenticator_subkey=authenticator_subkey, + kdc_options=kdc_options, + pac_request=pac_request, +- expect_pac=expect_pac) ++ expect_pac=expect_pac, ++ expect_edata=False) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=cname, +@@ -516,8 +515,7 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) + +- self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=False) # Note: not expected ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_req_no_pac_attrs(self): + creds = self._get_creds() +@@ -531,11 +529,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, remove_requester_sid=True) + +- samdb = self.get_samdb() +- sid = self.get_objectSid(samdb, creds.get_dn()) +- +- self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=True, expected_sid=sid) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_req_from_rodc_no_pac_attrs(self): + creds = self._get_creds(replication_allowed=True, +@@ -548,101 +542,99 @@ class KdcTgsTests(KDCBaseTest): + def test_tgs_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True, remove_pac=True) +- self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True, remove_pac=True) +- self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) + self._s4u2self(tgt, creds, +- expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), +- expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, +- expect_edata=True) ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expect_edata=False) + + def test_user2user_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True) +- self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION) ++ self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test making a request with authdata and without a PAC. + def test_tgs_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True, remove_pac=True, + allow_empty_authdata=True) +- self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True, remove_pac=True, + allow_empty_authdata=True) +- self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) + self._s4u2self(tgt, creds, +- expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION), +- expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER, +- expect_edata=True) ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expect_edata=False) + + def test_user2user_authdata_no_pac(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) +- self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION) ++ self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + # Test changing the SID in the PAC to that of another account. + def test_tgs_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, renewable=True, new_rid=existing_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, invalid=True, new_rid=existing_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) + self._s4u2self(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_requester_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_logon_info_sid_mismatch_existing(self): + creds = self._get_creds() +@@ -656,49 +648,49 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid() + tgt = self._get_tgt(creds, new_rid=existing_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test changing the SID in the PAC to a non-existent one. + def test_tgs_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, renewable=True, + new_rid=nonexistent_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, invalid=True, + new_rid=nonexistent_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) + self._s4u2self(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_logon_info_sid_mismatch_nonexisting(self): + creds = self._get_creds() +@@ -712,7 +704,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, new_rid=nonexistent_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the client is revealed to the RODC. + def test_tgs_rodc_revealed(self): +@@ -753,7 +745,7 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -762,7 +754,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True, + new_rid=existing_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -771,7 +763,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True, + new_rid=existing_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -779,7 +771,7 @@ class KdcTgsTests(KDCBaseTest): + existing_rid = self._get_existing_rid(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) +- self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -788,7 +780,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_requester_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -797,7 +789,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_logon_info_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, +@@ -815,7 +807,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the SID in the PAC is changed to a + # non-existent one. +@@ -824,7 +816,7 @@ class KdcTgsTests(KDCBaseTest): + revealed_to_rodc=True) + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_renew_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -832,7 +824,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, renewable=True, from_rodc=True, + new_rid=nonexistent_rid) +- self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_validate_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -840,14 +832,14 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, invalid=True, from_rodc=True, + new_rid=nonexistent_rid) +- self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_s4u2self_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) +- self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + + def test_user2user_rodc_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -855,7 +847,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) + self._user2user(tgt, creds, +- expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -863,7 +855,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid, + can_modify_logon_info=False) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_rodc_logon_info_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, +@@ -879,7 +871,7 @@ class KdcTgsTests(KDCBaseTest): + nonexistent_rid = self._get_non_existent_rid() + tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid, + remove_requester_sid=True) +- self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH) ++ self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + # Test with an RODC-issued ticket where the client is not revealed to the + # RODC. +@@ -1111,8 +1103,7 @@ class KdcTgsTests(KDCBaseTest): + names=[user_name]) + + self._user2user(tgt, creds, sname=sname, +- expected_error=(KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION)) ++ expected_error=KDC_ERR_BADMATCH) + + def test_user2user_other_sname(self): + other_name = self.get_new_username() +@@ -1134,8 +1125,7 @@ class KdcTgsTests(KDCBaseTest): + sname = self.get_krbtgt_sname() + + self._user2user(tgt, creds, sname=sname, +- expected_error=(KDC_ERR_BADMATCH, +- KDC_ERR_BADOPTION)) ++ expected_error=KDC_ERR_BADMATCH) + + def test_user2user_wrong_srealm(self): + creds = self._get_creds() +@@ -1206,7 +1196,9 @@ class KdcTgsTests(KDCBaseTest): + + tgt = self._modify_tgt(tgt, cname=cname) + +- self._user2user(tgt, creds, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) ++ self._user2user(tgt, creds, ++ expected_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_C_PRINCIPAL_UNKNOWN)) + + def test_user2user_non_existent_sname(self): + creds = self._get_creds() +@@ -1522,8 +1514,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, renewable=True, + remove_requester_sid=True) + +- self._renew_tgt(tgt, expected_error=0, expect_pac=True, +- expect_requester_sid=False) # Note: not expected ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_requester_sid_missing_rodc_renew(self): + creds = self._get_creds(replication_allowed=True, +@@ -1539,9 +1530,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True, + remove_requester_sid=True) + +- self._renew_tgt(tgt, expected_error=0, expect_pac=True, +- expected_sid=sid, +- expect_requester_sid=True) ++ self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + + def test_tgs_pac_request_none(self): + creds = self._get_creds() +@@ -1655,10 +1644,10 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + +- ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=False) ++ ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=True) + +- pac = self.get_ticket_pac(ticket, expect_pac=False) +- self.assertIsNone(pac) ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) + + def test_s4u2self_pac_request_true(self): + creds = self._get_creds() +@@ -1753,10 +1742,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, from_rodc=True) + +- ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + + pac = self.get_ticket_pac(ticket, expect_pac=False) +- self.assertIsNone(pac) ++ self.assertIsNotNone(pac) + + def test_tgs_rodc_pac_request_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1784,7 +1773,8 @@ class KdcTgsTests(KDCBaseTest): + 'sAMAccountName') + samdb.modify(msg) + +- self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN) ++ self._run_tgs(tgt, expected_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_C_PRINCIPAL_UNKNOWN)) + + def _modify_renewable(self, enc_part): + # Set the renewable flag. +diff --git a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +index 0aa3309b814..e6b90d3e16a 100755 +--- a/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py ++++ b/python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py +@@ -32,6 +32,7 @@ from samba.tests.krb5.rfc4120_constants import ( + NT_PRINCIPAL, + NT_SRV_INST, + KDC_ERR_C_PRINCIPAL_UNKNOWN, ++ KDC_ERR_TGT_REVOKED, + ) + + global_asn1_print = False +@@ -322,21 +323,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype, +- service_creds=mc, expect_pac=False) +- self.check_tgs_reply(rep) +- +- # Check the contents of the service ticket +- ticket = rep['ticket'] +- enc_part = self.decode_service_ticket(mc, ticket) +- # +- # We get an empty authorization-data element in the ticket. +- # i.e. no PAC +- self.assertEqual([], enc_part['authorization-data']) +- # check the crealm and cname +- cname = enc_part['cname'] +- self.assertEqual(NT_PRINCIPAL, cname['name-type']) +- self.assertEqual(alt_name.encode('UTF8'), cname['name-string'][0]) +- self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) ++ service_creds=mc, expect_pac=False, ++ expect_edata=False, ++ expected_error_mode=KDC_ERR_TGT_REVOKED) ++ self.check_error_rep(rep, KDC_ERR_TGT_REVOKED) + + def test_nt_principal_step_4_b(self): + ''' Step 4, pre-authentication +@@ -703,21 +693,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest): + + (rep, enc_part) = self.tgs_req( + cname, sname, uc.get_realm(), ticket, key, etype, +- service_creds=mc, expect_pac=False) +- self.check_tgs_reply(rep) +- +- # Check the contents of the service ticket +- ticket = rep['ticket'] +- enc_part = self.decode_service_ticket(mc, ticket) +- # +- # We get an empty authorization-data element in the ticket. +- # i.e. no PAC +- self.assertEqual([], enc_part['authorization-data']) +- # check the crealm and cname +- cname = enc_part['cname'] +- self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type']) +- self.assertEqual(ename.encode('UTF8'), cname['name-string'][0]) +- self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm']) ++ service_creds=mc, expect_pac=False, ++ expect_edata=False, ++ expected_error_mode=KDC_ERR_TGT_REVOKED) ++ self.check_error_rep(rep, KDC_ERR_TGT_REVOKED) + + def test_nt_enterprise_principal_step_6_b(self): + ''' Step 4, pre-authentication +diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py +index a80a7b3427e..5f37525f393 100755 +--- a/python/samba/tests/krb5/s4u_tests.py ++++ b/python/samba/tests/krb5/s4u_tests.py +@@ -42,6 +42,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_INAPP_CKSUM, + KDC_ERR_MODIFIED, + KDC_ERR_SUMTYPE_NOSUPP, ++ KDC_ERR_TGT_REVOKED, + KU_PA_ENC_TIMESTAMP, + KU_AS_REP_ENC_PART, + KU_TGS_REP_ENC_PART_SUB_KEY, +@@ -278,6 +279,8 @@ class S4UKerberosTests(KDCBaseTest): + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) + ++ expect_edata = kdc_dict.pop('expect_edata', None) ++ + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): +@@ -309,7 +312,8 @@ class S4UKerberosTests(KDCBaseTest): + tgt=service_tgt, + authenticator_subkey=authenticator_subkey, + kdc_options=str(kdc_options), +- expect_claims=False) ++ expect_claims=False, ++ expect_edata=expect_edata) + + self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, +@@ -343,15 +347,14 @@ class S4UKerberosTests(KDCBaseTest): + + self._run_s4u2self_test( + { +- 'expected_error_mode': (KDC_ERR_GENERIC, +- KDC_ERR_BADOPTION), +- 'expected_status': ntstatus.NT_STATUS_INVALID_PARAMETER, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'client_opts': { + 'not_delegated': False + }, + 'kdc_options': 'forwardable', + 'modify_service_tgt_fn': forwardable_no_pac, +- 'expected_flags': 'forwardable' ++ 'expected_flags': 'forwardable', ++ 'expect_edata': False + }) + + # Test performing an S4U2Self operation without requesting a forwardable +@@ -674,8 +677,8 @@ class S4UKerberosTests(KDCBaseTest): + # contain a PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': (KDC_ERR_MODIFIED, ++ KDC_ERR_TGT_REVOKED), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False +@@ -686,9 +689,10 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': 0, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_delegation': True, +- 'modify_service_tgt_fn': self.remove_ticket_pac ++ 'modify_service_tgt_fn': self.remove_ticket_pac, ++ 'expect_edata': False + }) + + def test_constrained_delegation_no_client_pac_no_auth_data_required(self): +@@ -696,8 +700,8 @@ class S4UKerberosTests(KDCBaseTest): + # contain a PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': (KDC_ERR_MODIFIED, ++ KDC_ERR_BADOPTION), + 'allow_delegation': True, + 'modify_client_tkt_fn': self.remove_ticket_pac, + 'expect_edata': False, +@@ -711,13 +715,14 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED), ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_delegation': True, + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True +- } ++ }, ++ 'expect_pac': False, ++ 'expect_edata': False + }) + + def test_constrained_delegation_non_forwardable(self): +@@ -812,12 +817,11 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': KDC_ERR_BADOPTION, +- 'expected_status': +- ntstatus.NT_STATUS_NOT_FOUND, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD +- 'modify_service_tgt_fn': self.remove_ticket_pac ++ 'modify_service_tgt_fn': self.remove_ticket_pac, ++ 'expect_edata': False + }) + + def test_rbcd_no_client_pac_no_auth_data_required_a(self): +@@ -858,15 +862,14 @@ class S4UKerberosTests(KDCBaseTest): + # PAC. + self._run_delegation_test( + { +- 'expected_error_mode': KDC_ERR_BADOPTION, +- 'expected_status': +- ntstatus.NT_STATUS_NOT_FOUND, ++ 'expected_error_mode': KDC_ERR_TGT_REVOKED, + 'allow_rbcd': True, + 'pac_options': '0001', # supports RBCD + 'modify_service_tgt_fn': self.remove_ticket_pac, + 'service2_opts': { + 'no_auth_data_required': True +- } ++ }, ++ 'expect_edata': False + }) + + def test_rbcd_non_forwardable(self): +@@ -941,8 +944,8 @@ class S4UKerberosTests(KDCBaseTest): + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + if checksum == krb5pac.PAC_TYPE_TICKET_CHECKSUM: +- expected_error_mode = (KDC_ERR_BADOPTION, +- KDC_ERR_MODIFIED) ++ expected_error_mode = (KDC_ERR_MODIFIED, ++ KDC_ERR_BADOPTION) + else: + expected_error_mode = KDC_ERR_GENERIC + +@@ -1061,8 +1064,7 @@ class S4UKerberosTests(KDCBaseTest): + for checksum in self.pac_checksum_types: + with self.subTest(checksum=checksum): + if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM: +- expected_error_mode = (KDC_ERR_MODIFIED, +- KDC_ERR_BAD_INTEGRITY) ++ expected_error_mode = KDC_ERR_MODIFIED + expected_status = ntstatus.NT_STATUS_WRONG_PASSWORD + else: + expected_error_mode = 0 +@@ -1162,8 +1164,7 @@ class S4UKerberosTests(KDCBaseTest): + with self.subTest(checksum=checksum, ctype=ctype): + if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM: + if ctype == Cksumtype.SHA1: +- expected_error_mode = (KDC_ERR_SUMTYPE_NOSUPP, +- KDC_ERR_BAD_INTEGRITY) ++ expected_error_mode = KDC_ERR_SUMTYPE_NOSUPP + expected_status = ntstatus.NT_STATUS_LOGON_FAILURE + else: + expected_error_mode = KDC_ERR_GENERIC +diff --git a/python/samba/tests/krb5/test_rpc.py b/python/samba/tests/krb5/test_rpc.py +index 2d483986e83..5a3c7339cea 100755 +--- a/python/samba/tests/krb5/test_rpc.py ++++ b/python/samba/tests/krb5/test_rpc.py +@@ -24,7 +24,10 @@ import ldb + + from samba import NTSTATUSError, credentials + from samba.dcerpc import lsa +-from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN ++from samba.ntstatus import ( ++ NT_STATUS_ACCESS_DENIED, ++ NT_STATUS_NO_IMPERSONATION_TOKEN ++) + + from samba.tests.krb5.kdc_base_test import KDCBaseTest + +@@ -103,7 +106,8 @@ class RpcTests(KDCBaseTest): + self.fail() + + enum, _ = e.args +- self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum) ++ self.assertIn(enum, {NT_STATUS_ACCESS_DENIED, ++ NT_STATUS_NO_IMPERSONATION_TOKEN}) + return + + (account_name, _) = conn.GetUserName(None, None, None) +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 0f62627ae31..cfbe698fb15 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -71,16 +71,21 @@ + # S4U tests + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required) + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$ ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -97,3 +102,62 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed ++# ++# Alias tests ++# ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete ++^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename ++# ++# KDC TGS tests ++# ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index c046a46a4f3..31010c16391 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -368,6 +368,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # KDC TGT tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied +@@ -379,6 +381,10 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied +@@ -394,6 +400,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link +@@ -403,6 +410,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname +@@ -432,6 +441,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # + # PAC attributes tests + # +-- +2.25.1 + + +From 011a468c786bac72ce8ad40544ffa7798fa38a97 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:04:36 +1300 +Subject: [PATCH 28/99] tests/krb5: Remove unnecessary expect_pac arguments + +The value of expect_pac is not considered if we are expecting an error. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 28d501875a98fa2817262eb8ec68bf91528428c2) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 7ea15f0fbab..6160ef649e8 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -412,7 +412,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_remove_pac_client_no_auth_data_required(self): + client_creds = self.get_cached_creds( +@@ -427,7 +427,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_remove_pac(self): + client_creds = self.get_client_creds() +@@ -440,7 +440,7 @@ class KdcTgsTests(KDCBaseTest): + self.assertIsNone(pac) + + self._make_tgs_request(client_creds, service_creds, tgt, +- expect_pac=False, expect_error=True) ++ expect_error=True) + + def test_upn_dns_info_ex_user(self): + client_creds = self.get_client_creds() +-- +2.25.1 + + +From a696ddc90a9f31997478620807c7a4991fc851ab Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 30 Nov 2021 09:26:40 +1300 +Subject: [PATCH 29/99] tests/krb5: Add tests for invalid TGTs + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 7574ba9f580fca552b80532a49d00e657fbdf4fd) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 16 ++++++++++++++++ + python/samba/tests/krb5/rfc4120_constants.py | 1 + + selftest/knownfail_mit_kdc | 3 ++- + 3 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 6160ef649e8..f5f091610ac 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -44,6 +44,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_C_PRINCIPAL_UNKNOWN, + KDC_ERR_S_PRINCIPAL_UNKNOWN, + KDC_ERR_TGT_REVOKED, ++ KRB_ERR_TKT_NYV, + KDC_ERR_WRONG_REALM, + NT_PRINCIPAL, + NT_SRV_INST, +@@ -511,6 +512,21 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds) + self._user2user(tgt, creds, expected_error=0) + ++ def test_tgs_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._run_tgs(tgt, expected_error=KRB_ERR_TKT_NYV) ++ ++ def test_s4u2self_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._s4u2self(tgt, creds, expected_error=KRB_ERR_TKT_NYV) ++ ++ def test_user2user_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV) ++ + def test_tgs_req_no_requester_sid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) +diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py +index 5251e291fde..a9fdc5735dd 100644 +--- a/python/samba/tests/krb5/rfc4120_constants.py ++++ b/python/samba/tests/krb5/rfc4120_constants.py +@@ -76,6 +76,7 @@ KDC_ERR_TGT_REVOKED = 20 + KDC_ERR_PREAUTH_FAILED = 24 + KDC_ERR_PREAUTH_REQUIRED = 25 + KDC_ERR_BAD_INTEGRITY = 31 ++KRB_ERR_TKT_NYV = 33 + KDC_ERR_NOT_US = 35 + KDC_ERR_BADMATCH = 36 + KDC_ERR_SKEW = 37 +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 31010c16391..2aa7fb2b370 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -385,7 +385,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_no_krbtgt_link +@@ -415,6 +415,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_req_invalid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_no_krbtgt_link +-- +2.25.1 + + +From 7197641eda7ba738cfcce40d43314588c6474251 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:10:45 +1300 +Subject: [PATCH 30/99] tests/krb5: Add tests for TGS requests with a non-TGT + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 778029c1dc443b87f4ed4b9d2c613d0e6fc45b0d) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 51 ++++++++++++++++++++++++ + selftest/knownfail_mit_kdc | 2 + + 2 files changed, 53 insertions(+) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index f5f091610ac..52297c963e8 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -40,6 +40,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_BADMATCH, + KDC_ERR_GENERIC, + KDC_ERR_MODIFIED, ++ KDC_ERR_NOT_US, + KDC_ERR_POLICY, + KDC_ERR_C_PRINCIPAL_UNKNOWN, + KDC_ERR_S_PRINCIPAL_UNKNOWN, +@@ -1234,6 +1235,56 @@ class KdcTgsTests(KDCBaseTest): + expected_error=(KDC_ERR_GENERIC, + KDC_ERR_S_PRINCIPAL_UNKNOWN)) + ++ def test_tgs_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._run_tgs(service_ticket, ++ expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY)) ++ ++ def test_renew_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ service_ticket = self.modified_ticket( ++ service_ticket, ++ modify_fn=self._modify_renewable, ++ checksum_keys=self.get_krbtgt_checksum_key()) ++ ++ self._renew_tgt(service_ticket, ++ expected_error=KDC_ERR_POLICY) ++ ++ def test_validate_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ service_ticket = self.modified_ticket( ++ service_ticket, ++ modify_fn=self._modify_invalid, ++ checksum_keys=self.get_krbtgt_checksum_key()) ++ ++ self._validate_tgt(service_ticket, ++ expected_error=KDC_ERR_POLICY) ++ ++ def test_s4u2self_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._s4u2self(service_ticket, creds, ++ expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY)) ++ + def test_user2user_service_ticket(self): + creds = self._get_creds() + tgt = self._get_tgt(creds) +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 2aa7fb2b370..8f8b0b18f18 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -381,6 +381,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac +@@ -442,6 +443,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # +-- +2.25.1 + + +From e24898c41c572dc8ec1374e67a4e029207b21ee2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:09:18 +1300 +Subject: [PATCH 31/99] tests/krb5: Add TGS-REQ tests with FAST + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ec823c2a83c639f1d7c422153a53d366750e5f2a) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 184 ++++++++++++++++++++++- + selftest/knownfail_heimdal_kdc | 13 ++ + selftest/knownfail_mit_kdc | 17 +++ + 3 files changed, 212 insertions(+), 2 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 52297c963e8..99a91528fa8 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -32,6 +32,7 @@ os.environ["PYTHONUNBUFFERED"] = "1" + + import samba.tests.krb5.kcrypto as kcrypto + from samba.tests.krb5.kdc_base_test import KDCBaseTest ++from samba.tests.krb5.raw_testcase import Krb5EncryptionKey + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, +@@ -513,6 +514,11 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds) + self._user2user(tgt, creds, expected_error=0) + ++ def test_fast_req(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ self._fast(tgt, creds, expected_error=0) ++ + def test_tgs_req_invalid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True) +@@ -528,6 +534,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, invalid=True) + self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV) + ++ def test_fast_req_invalid(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, invalid=True) ++ self._fast(tgt, creds, expected_error=KRB_ERR_TKT_NYV, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_req_no_requester_sid(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, remove_requester_sid=True) +@@ -583,6 +595,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, remove_pac=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_no_pac(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, remove_pac=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test making a request with authdata and without a PAC. + def test_tgs_authdata_no_pac(self): + creds = self._get_creds() +@@ -613,6 +631,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_authdata_no_pac(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test changing the SID in the PAC to that of another account. + def test_tgs_sid_mismatch_existing(self): + creds = self._get_creds() +@@ -646,6 +670,14 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_sid_mismatch_existing(self): ++ creds = self._get_creds() ++ existing_rid = self._get_existing_rid() ++ tgt = self._get_tgt(creds, new_rid=existing_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_requester_sid_mismatch_existing(self): + creds = self._get_creds() + existing_rid = self._get_existing_rid() +@@ -702,6 +734,14 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_sid_mismatch_nonexisting(self): ++ creds = self._get_creds() ++ nonexistent_rid = self._get_non_existent_rid() ++ tgt = self._get_tgt(creds, new_rid=nonexistent_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds() + nonexistent_rid = self._get_non_existent_rid() +@@ -799,6 +839,16 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_sid_mismatch_existing(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ existing_rid = self._get_existing_rid(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_rodc_requester_sid_mismatch_existing(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -866,6 +916,15 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(tgt, creds, + expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_sid_mismatch_nonexisting(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ nonexistent_rid = self._get_non_existent_rid() ++ tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid) ++ self._fast(tgt, creds, ++ expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + def test_tgs_rodc_requester_sid_mismatch_nonexisting(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -955,6 +1014,14 @@ class KdcTgsTests(KDCBaseTest): + self._remove_rodc_partial_secrets() + self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + ++ def test_fast_rodc_no_partial_secrets(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._remove_rodc_partial_secrets() ++ self._fast(tgt, creds, expected_error=KDC_ERR_POLICY, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the RODC account does not have an + # msDS-KrbTgtLink. + def test_tgs_rodc_no_krbtgt_link(self): +@@ -992,6 +1059,14 @@ class KdcTgsTests(KDCBaseTest): + self._remove_rodc_krbtgt_link() + self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY) + ++ def test_fast_rodc_no_krbtgt_link(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._remove_rodc_krbtgt_link() ++ self._fast(tgt, creds, expected_error=KDC_ERR_POLICY, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is not allowed to + # replicate to the RODC. + def test_tgs_rodc_not_allowed(self): +@@ -1019,6 +1094,12 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_not_allowed(self): ++ creds = self._get_creds(revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is denied from + # replicating to the RODC. + def test_tgs_rodc_denied(self): +@@ -1051,6 +1132,13 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_denied(self): ++ creds = self._get_creds(replication_denied=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test with an RODC-issued ticket where the client is both allowed and + # denied replicating to the RODC. + def test_tgs_rodc_allowed_denied(self): +@@ -1088,6 +1176,14 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._get_tgt(creds, from_rodc=True) + self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_fast_rodc_allowed_denied(self): ++ creds = self._get_creds(replication_allowed=True, ++ replication_denied=True, ++ revealed_to_rodc=True) ++ tgt = self._get_tgt(creds, from_rodc=True) ++ self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED, ++ expected_sname=self.get_krbtgt_sname()) ++ + # Test user-to-user with incorrect service principal names. + def test_user2user_matching_sname_host(self): + creds = self._get_creds() +@@ -1295,6 +1391,17 @@ class KdcTgsTests(KDCBaseTest): + self._user2user(service_ticket, creds, + expected_error=(KDC_ERR_MODIFIED, KDC_ERR_POLICY)) + ++ # Expected to fail against Windows, which does not produce a policy error. ++ def test_fast_service_ticket(self): ++ creds = self._get_creds() ++ tgt = self._get_tgt(creds) ++ ++ service_creds = self.get_service_creds() ++ service_ticket = self.get_service_ticket(tgt, service_creds) ++ ++ self._fast(service_ticket, creds, ++ expected_error=KDC_ERR_POLICY) ++ + def test_pac_attrs_none(self): + creds = self._get_creds() + self.get_tgt(creds, pac_request=None, +@@ -1792,6 +1899,34 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_fast_pac_request_none(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=None) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_fast_pac_request_false(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=False) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, ++ expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket, expect_pac=True) ++ self.assertIsNotNone(pac) ++ ++ def test_fast_pac_request_true(self): ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds, pac_request=True) ++ ++ ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_tgs_rodc_pac_request_none(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -2192,13 +2327,28 @@ class KdcTgsTests(KDCBaseTest): + srealm=srealm, + expect_pac=expect_pac) + ++ def _fast(self, armor_tgt, armor_tgt_creds, expected_error, ++ expected_sname=None, expect_pac=True): ++ user_creds = self._get_mach_creds() ++ user_tgt = self.get_tgt(user_creds) ++ ++ target_creds = self.get_service_creds() ++ ++ return self._tgs_req(user_tgt, expected_error, target_creds, ++ armor_tgt=armor_tgt, ++ expected_sname=expected_sname, ++ expect_pac=expect_pac) ++ + def _tgs_req(self, tgt, expected_error, target_creds, ++ armor_tgt=None, + kdc_options='0', + expected_cname=None, ++ expected_sname=None, + additional_ticket=None, + generate_padata_fn=None, + sname=None, + srealm=None, ++ use_fast=False, + expect_claims=True, + expect_pac=True, + expect_pac_attrs=None, +@@ -2214,7 +2364,8 @@ class KdcTgsTests(KDCBaseTest): + + if sname is False: + sname = None +- expected_sname = self.get_krbtgt_sname() ++ if expected_sname is None: ++ expected_sname = self.get_krbtgt_sname() + else: + if sname is None: + target_name = target_creds.get_username() +@@ -2229,7 +2380,8 @@ class KdcTgsTests(KDCBaseTest): + name_type=NT_PRINCIPAL, + names=['host', target_name]) + +- expected_sname = sname ++ if expected_sname is None: ++ expected_sname = sname + + if additional_ticket is not None: + additional_tickets = [additional_ticket.ticket] +@@ -2241,6 +2393,28 @@ class KdcTgsTests(KDCBaseTest): + + subkey = self.RandomKey(tgt.session_key.etype) + ++ if armor_tgt is not None: ++ armor_subkey = self.RandomKey(subkey.etype) ++ explicit_armor_key = self.generate_armor_key(armor_subkey, ++ armor_tgt.session_key) ++ armor_key = kcrypto.cf2(explicit_armor_key.key, ++ subkey.key, ++ b'explicitarmor', ++ b'tgsarmor') ++ armor_key = Krb5EncryptionKey(armor_key, None) ++ ++ generate_fast_fn = self.generate_simple_fast ++ generate_fast_armor_fn = self.generate_ap_req ++ ++ pac_options = '1' # claims support ++ else: ++ armor_subkey = None ++ armor_key = None ++ generate_fast_fn = None ++ generate_fast_armor_fn = None ++ ++ pac_options = None ++ + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + if expected_error: +@@ -2260,12 +2434,18 @@ class KdcTgsTests(KDCBaseTest): + expected_sname=expected_sname, + ticket_decryption_key=decryption_key, + generate_padata_fn=generate_padata_fn, ++ generate_fast_fn=generate_fast_fn, ++ generate_fast_armor_fn=generate_fast_armor_fn, + check_error_fn=check_error_fn, + check_rep_fn=check_rep_fn, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error, + expected_status=expected_status, + tgt=tgt, ++ armor_key=armor_key, ++ armor_tgt=armor_tgt, ++ armor_subkey=armor_subkey, ++ pac_options=pac_options, + authenticator_subkey=subkey, + kdc_options=kdc_options, + expect_edata=expect_edata, +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index cfbe698fb15..42b70e97f60 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -112,6 +112,19 @@ + # + # KDC TGS tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 8f8b0b18f18..1723481c931 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -368,6 +368,23 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # KDC TGT tests + # ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac +-- +2.25.1 + + +From 42f09fdbdbdc1c2a6fc6c29e8df9c54c345c8fbf Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 12:37:08 +1300 +Subject: [PATCH 32/99] tests/krb5: Align PAC buffer checking to more closely + match Windows with PacRequestorEnforcement=2 + +We set EXPECT_EXTRA_PAC_BUFFERS to 0 for the moment. This signifies that +these checks are currently not enforced, which avoids a lot of test +failures. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ebc9137cee94dee9dcf0e47d5bc0dc83de7aaaa1) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 121 ++++++++++++++++------- + python/samba/tests/krb5/raw_testcase.py | 39 ++++++-- + selftest/knownfail_heimdal_kdc | 9 ++ + selftest/knownfail_mit_kdc | 6 ++ + source4/selftest/tests.py | 58 +++++++---- + 5 files changed, 168 insertions(+), 65 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 99a91528fa8..f14439a4ab5 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -497,12 +497,18 @@ class KdcTgsTests(KDCBaseTest): + def test_renew_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, renewable=True) +- self._renew_tgt(tgt, expected_error=0) ++ self._renew_tgt(tgt, expected_error=0, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_validate_req(self): + creds = self._get_creds() + tgt = self._get_tgt(creds, invalid=True) +- self._validate_tgt(tgt, expected_error=0) ++ self._validate_tgt(tgt, expected_error=0, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_s4u2self_req(self): + creds = self._get_creds() +@@ -774,13 +780,17 @@ class KdcTgsTests(KDCBaseTest): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, renewable=True, from_rodc=True) +- self._renew_tgt(tgt, expected_error=0) ++ self._renew_tgt(tgt, expected_error=0, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_validate_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) + tgt = self._get_tgt(creds, invalid=True, from_rodc=True) +- self._validate_tgt(tgt, expected_error=0) ++ self._validate_tgt(tgt, expected_error=0, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_s4u2self_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, +@@ -1434,7 +1444,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + def test_pac_attrs_renew_false(self): + creds = self._get_creds() +@@ -1447,7 +1458,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=False) ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + def test_pac_attrs_renew_true(self): + creds = self._get_creds() +@@ -1460,7 +1472,8 @@ class KdcTgsTests(KDCBaseTest): + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, + expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, +@@ -1473,8 +1486,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, +@@ -1487,8 +1500,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1501,8 +1514,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_none(self): + creds = self._get_creds() +@@ -1515,7 +1528,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_false(self): + creds = self._get_creds() +@@ -1528,7 +1542,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_renew_true(self): + creds = self._get_creds() +@@ -1541,7 +1556,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_none(self): + creds = self._get_creds(replication_allowed=True, +@@ -1555,7 +1571,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_false(self): + creds = self._get_creds(replication_allowed=True, +@@ -1569,7 +1586,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_pac_attrs_missing_rodc_renew_true(self): + creds = self._get_creds(replication_allowed=True, +@@ -1583,7 +1601,8 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=0, + expect_pac=True, +- expect_pac_attrs=False) ++ expect_pac_attrs=False, ++ expect_requester_sid=True) + + def test_tgs_pac_attrs_none(self): + creds = self._get_creds() +@@ -1593,8 +1612,7 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs_pac_request=None) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=None) ++ expect_pac_attrs=False) + + def test_tgs_pac_attrs_false(self): + creds = self._get_creds() +@@ -1603,7 +1621,8 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs=True, + expect_pac_attrs_pac_request=False) + +- self._run_tgs(tgt, expected_error=0, expect_pac=False) ++ self._run_tgs(tgt, expected_error=0, expect_pac=False, ++ expect_pac_attrs=False) + + def test_tgs_pac_attrs_true(self): + creds = self._get_creds() +@@ -1613,8 +1632,7 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs_pac_request=True) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expect_pac_attrs=True, +- expect_pac_attrs_pac_request=True) ++ expect_pac_attrs=False) + + def test_as_requester_sid(self): + creds = self._get_creds() +@@ -1639,8 +1657,7 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=True) + + self._run_tgs(tgt, expected_error=0, expect_pac=True, +- expected_sid=sid, +- expect_requester_sid=True) ++ expect_requester_sid=False) + + def test_tgs_requester_sid_renew(self): + creds = self._get_creds() +@@ -1655,6 +1672,8 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, + expected_sid=sid, + expect_requester_sid=True) + +@@ -1672,6 +1691,7 @@ class KdcTgsTests(KDCBaseTest): + tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True) + + self._renew_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=False, + expected_sid=sid, + expect_requester_sid=True) + +@@ -1738,7 +1758,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=None) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1750,7 +1773,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + +@@ -1762,7 +1788,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=True) + tgt = self._modify_tgt(tgt, renewable=True) + +- tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1774,7 +1803,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=None) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1786,7 +1818,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=False, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False) + +@@ -1798,7 +1833,10 @@ class KdcTgsTests(KDCBaseTest): + tgt = self.get_tgt(creds, pac_request=True) + tgt = self._modify_tgt(tgt, invalid=True) + +- tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None) ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=True, ++ expect_requester_sid=True) + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +@@ -1946,7 +1984,7 @@ class KdcTgsTests(KDCBaseTest): + + ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) + +- pac = self.get_ticket_pac(ticket, expect_pac=False) ++ pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + + def test_tgs_rodc_pac_request_true(self): +@@ -2279,12 +2317,21 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + +- def _validate_tgt(self, tgt, expected_error, expect_pac=True): ++ def _validate_tgt(self, tgt, expected_error, expect_pac=True, ++ expect_pac_attrs=None, ++ expect_pac_attrs_pac_request=None, ++ expect_requester_sid=None, ++ expected_sid=None): + krbtgt_creds = self.get_krbtgt_creds() + kdc_options = str(krb5_asn1.KDCOptions('validate')) +- return self._tgs_req(tgt, expected_error, krbtgt_creds, +- kdc_options=kdc_options, +- expect_pac=expect_pac) ++ return self._tgs_req( ++ tgt, expected_error, krbtgt_creds, ++ kdc_options=kdc_options, ++ expect_pac=expect_pac, ++ expect_pac_attrs=expect_pac_attrs, ++ expect_pac_attrs_pac_request=expect_pac_attrs_pac_request, ++ expect_requester_sid=expect_requester_sid, ++ expected_sid=expected_sid) + + def _s4u2self(self, tgt, tgt_creds, expected_error, expect_pac=True, + expect_edata=False, expected_status=None): +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index da3f69c79c6..14e655313fc 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -602,6 +602,13 @@ class RawKerberosTest(TestCaseInTempDir): + expect_pac = '1' + cls.expect_pac = bool(int(expect_pac)) + ++ expect_extra_pac_buffers = samba.tests.env_get_var_value( ++ 'EXPECT_EXTRA_PAC_BUFFERS', ++ allow_missing=True) ++ if expect_extra_pac_buffers is None: ++ expect_extra_pac_buffers = '1' ++ cls.expect_extra_pac_buffers = bool(int(expect_extra_pac_buffers)) ++ + def setUp(self): + super().setUp() + self.do_asn1_print = False +@@ -2624,17 +2631,34 @@ class RawKerberosTest(TestCaseInTempDir): + if not self.tkt_sig_support: + require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + ++ expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP ++ + expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs'] ++ ++ if expect_pac_attrs: ++ expect_pac_attrs_pac_request = kdc_exchange_dict[ ++ 'expect_pac_attrs_pac_request'] ++ else: ++ expect_pac_attrs_pac_request = kdc_exchange_dict[ ++ 'pac_request'] ++ ++ if expect_pac_attrs is None: ++ if self.expect_extra_pac_buffers: ++ expect_pac_attrs = expect_extra_pac_buffers ++ else: ++ require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) + if expect_pac_attrs: + expected_types.append(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) +- elif expect_pac_attrs is None: +- require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) + + expect_requester_sid = kdc_exchange_dict['expect_requester_sid'] ++ ++ if expect_requester_sid is None: ++ if self.expect_extra_pac_buffers: ++ expect_requester_sid = expect_extra_pac_buffers ++ else: ++ require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID) + if expect_requester_sid: + expected_types.append(krb5pac.PAC_TYPE_REQUESTER_SID) +- elif expect_requester_sid is None: +- require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID) + + buffer_types = [pac_buffer.type + for pac_buffer in pac.buffers] +@@ -2722,9 +2746,6 @@ class RawKerberosTest(TestCaseInTempDir): + requested_pac = bool(flags & 1) + given_pac = bool(flags & 2) + +- expect_pac_attrs_pac_request = kdc_exchange_dict[ +- 'expect_pac_attrs_pac_request'] +- + self.assertEqual(expect_pac_attrs_pac_request is True, + requested_pac) + self.assertEqual(expect_pac_attrs_pac_request is None, +@@ -2734,8 +2755,8 @@ class RawKerberosTest(TestCaseInTempDir): + and expect_requester_sid): + requester_sid = pac_buffer.info.sid + +- self.assertIsNotNone(expected_sid) +- self.assertEqual(expected_sid, str(requester_sid)) ++ if expected_sid is not None: ++ self.assertEqual(expected_sid, str(requester_sid)) + + def generic_check_kdc_error(self, + kdc_exchange_dict, +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 42b70e97f60..475abc03182 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -127,11 +127,15 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +@@ -147,10 +151,14 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +@@ -170,6 +178,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 1723481c931..1e63bb33d03 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -389,6 +389,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_krbtgt_link +@@ -451,6 +454,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_krbtgt_link +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index ff523edd26b..7234767baa5 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -905,12 +905,14 @@ for env in ['fileserver_smb1', 'nt4_member', 'clusteredmember', 'ktest', 'nt4_dc + have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) + tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) + expect_pac = int('SAMBA4_USES_HEIMDAL' in config_hash) ++extra_pac_buffers = 0 + planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", + environ={'SERVICE_USERNAME':'$SERVER', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac}) ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) + planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", + environ={'ADMIN_USERNAME':'$USERNAME', + 'ADMIN_PASSWORD':'$PASSWORD', +@@ -918,21 +920,24 @@ planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", + 'STRICT_CHECKING':'0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac}) ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) + planoldpythontestsuite("rodc:local", "samba.tests.krb5.rodc_tests", + environ={'ADMIN_USERNAME':'$USERNAME', + 'ADMIN_PASSWORD':'$PASSWORD', + 'STRICT_CHECKING':'0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac}) ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) + + planoldpythontestsuite("ad_dc_default", "samba.tests.dsdb_dns") + + planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests", + environ={'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac}) ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) + + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", + environ={ +@@ -941,7 +946,8 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", + environ={ +@@ -950,7 +956,8 @@ planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + for env in ['ad_dc_default', 'ad_member']: + planoldpythontestsuite(env, "samba.tests.krb5.test_rpc", +@@ -960,7 +967,8 @@ for env in ['ad_dc_default', 'ad_member']: + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", + environ={ +@@ -969,7 +977,8 @@ planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planoldpythontestsuite("ad_member_idmap_nss:local", + "samba.tests.krb5.test_min_domain_uid", +@@ -992,7 +1001,8 @@ planoldpythontestsuite("ad_member_idmap_nss:local", + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + + for env in ["ad_dc", smbv1_disabled_testenv]: +@@ -1587,7 +1597,8 @@ for env in ["fl2008r2dc", "fl2003dc"]: + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + + planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', +@@ -1597,7 +1608,8 @@ planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + + for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: +@@ -1620,7 +1632,8 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", + 'ADMIN_PASSWORD': '$PASSWORD', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", + environ={ +@@ -1629,12 +1642,14 @@ planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests", + environ={'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac}) ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.kdc_tgs_tests", +@@ -1644,7 +1659,8 @@ planpythontestsuite( + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite( + "ad_dc", +@@ -1655,7 +1671,8 @@ planpythontestsuite( + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite( + "ad_dc", +@@ -1666,7 +1683,8 @@ planpythontestsuite( + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite( + "ad_dc", +@@ -1677,7 +1695,8 @@ planpythontestsuite( + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + planpythontestsuite( + "ad_dc", +@@ -1688,7 +1707,8 @@ planpythontestsuite( + 'STRICT_CHECKING': '0', + 'FAST_SUPPORT': have_fast_support, + 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + + for env in [ +-- +2.25.1 + + +From 17e724b5bbfcaa96f2d4f4d9be790a0f7effe877 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 13:10:52 +1300 +Subject: [PATCH 33/99] tests/krb5: Add tests for validation with requester SID + PAC buffer + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ca80c47406e0f2b6fac2c55229306e21ccef9745) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 67 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 3 ++ + selftest/knownfail_mit_kdc | 4 ++ + 3 files changed, 74 insertions(+) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index f14439a4ab5..50079a1710c 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1726,6 +1726,73 @@ class KdcTgsTests(KDCBaseTest): + + self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) + ++ def test_tgs_requester_sid_validate(self): ++ creds = self._get_creds() ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, invalid=True) ++ ++ self._validate_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=True, ++ expect_pac_attrs_pac_request=None, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ ++ def test_tgs_requester_sid_rodc_validate(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True) ++ ++ self._validate_tgt(tgt, expected_error=0, expect_pac=True, ++ expect_pac_attrs=False, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ ++ def test_tgs_requester_sid_missing_validate(self): ++ creds = self._get_creds() ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, invalid=True, ++ remove_requester_sid=True) ++ ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) ++ ++ def test_tgs_requester_sid_missing_rodc_validate(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ ++ samdb = self.get_samdb() ++ sid = self.get_objectSid(samdb, creds.get_dn()) ++ ++ tgt = self.get_tgt(creds, pac_request=None, ++ expect_pac=True, ++ expected_sid=sid, ++ expect_requester_sid=True) ++ tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True, ++ remove_requester_sid=True) ++ ++ self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED) ++ + def test_tgs_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 475abc03182..c67cc302283 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -158,7 +158,10 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 1e63bb33d03..76253fc7b4b 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -512,8 +512,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing +-- +2.25.1 + + +From 79ba192a73f601a86a59ef16aaf47c649790a980 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 15:32:32 +1300 +Subject: [PATCH 34/99] tests/krb5: Add comments for tests that fail against + Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 749349efab9b401d33a4fc286473a924364a41c9) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 50079a1710c..ecc38538e61 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -792,6 +792,8 @@ class KdcTgsTests(KDCBaseTest): + expect_pac_attrs=False, + expect_requester_sid=True) + ++ # This test fails on Windows, which gives KDC_ERR_C_PRINCIPAL_UNKNOWN when ++ # attempting to use S4U2Self with a TGT from an RODC. + def test_s4u2self_rodc_revealed(self): + creds = self._get_creds(replication_allowed=True, + revealed_to_rodc=True) +@@ -2370,6 +2372,8 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + ++ # These tests fail against Windows, which does not implement ticket ++ # renewal. + def _renew_tgt(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, expected_sid=None): +@@ -2384,6 +2388,8 @@ class KdcTgsTests(KDCBaseTest): + expect_requester_sid=expect_requester_sid, + expected_sid=expected_sid) + ++ # These tests fail against Windows, which does not implement ticket ++ # validation. + def _validate_tgt(self, tgt, expected_error, expect_pac=True, + expect_pac_attrs=None, + expect_pac_attrs_pac_request=None, +-- +2.25.1 + + +From 78a82907caa55f9e6118fc2f7aa01509257fa166 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 18 Nov 2021 13:14:51 +1300 +Subject: [PATCH 35/99] heimdal:kdc: Fix error message for user-to-user + +We were checking the wrong variable to see whether a PAC was found or not. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 11fb9476ad3c09415d12b3cdf7934c293cbefcb2) +--- + source4/heimdal/kdc/krb5tgs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index fb2ef8230c9..cde68b41714 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -1629,7 +1629,7 @@ server_lookup: + ret = KRB5KDC_ERR_BADOPTION; + kdc_log(context, config, 0, + "Ticket not signed with PAC; user-to-user failed (%s).", +- mspac ? "Ticket unsigned" : "No PAC"); ++ user2user_pac ? "Ticket unsigned" : "No PAC"); + goto out; + } + +-- +2.25.1 + + +From 9b5612a88c0a56b0a08595d21c87d1dff00e495a Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 18 Nov 2021 16:22:34 +1300 +Subject: [PATCH 36/99] s4:torture: Fix typo + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9cfb88ba04818b5e9cec3c96422e8e4a3080d490) +--- + source4/torture/krb5/kdc-canon-heimdal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/torture/krb5/kdc-canon-heimdal.c b/source4/torture/krb5/kdc-canon-heimdal.c +index e9466f2d9d7..38b3f1e7a62 100644 +--- a/source4/torture/krb5/kdc-canon-heimdal.c ++++ b/source4/torture/krb5/kdc-canon-heimdal.c +@@ -262,7 +262,7 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_ + KRB5_NT_PRINCIPAL, + "krb5 libs unexpectedly " + "did not set principal " +- "as NT_SRV_HST!"); ++ "as NT_PRINCIPAL!"); + } else { + torture_assert_int_equal(test_context->tctx, + test_context->as_req.req_body.cname->name_type, +-- +2.25.1 + + +From 37f9d30cbdaeb082382304d5cd6442ffcdca331e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:34 +1300 +Subject: [PATCH 37/99] heimdal:kdc: Adjust no-PAC error code to match Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit f7a2fef8f49a86f63c3dc2f6a2d7d979fb53238a) +--- + selftest/knownfail_heimdal_kdc | 19 ------------------- + source4/heimdal/kdc/krb5tgs.c | 2 +- + 2 files changed, 1 insertion(+), 20 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index c67cc302283..cf196a3260a 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -71,21 +71,15 @@ + # S4U tests + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required) +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$ +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -130,11 +124,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting +@@ -142,15 +131,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +@@ -171,16 +156,12 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index cde68b41714..6c5c51aa448 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -78,7 +78,7 @@ check_PAC(krb5_context context, + return ret; + + if (pac == NULL) +- return KRB5KDC_ERR_BADOPTION; ++ return KRB5KDC_ERR_TGT_REVOKED; + + /* Verify the server signature. */ + ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal, +-- +2.25.1 + + +From 1bd26a254f2b7861852142e256c6d3bf7f718857 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:45 +1300 +Subject: [PATCH 38/99] kdc: Adjust SID mismatch error code to match Windows + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit d5d22bf84a71492342287e54b555c9f024e7e71c) +--- + selftest/knownfail_heimdal_kdc | 35 ---------------------------------- + selftest/knownfail_mit_kdc | 8 -------- + source4/kdc/pac-glue.c | 6 +----- + 3 files changed, 1 insertion(+), 48 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index cf196a3260a..fc2a3554f0d 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -97,13 +97,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed + # +-# Alias tests +-# +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete +-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename +-# + # KDC TGS tests + # + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac +@@ -119,23 +112,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +@@ -147,23 +128,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 76253fc7b4b..806aaa707d7 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -385,8 +385,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none +@@ -402,8 +400,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) +@@ -431,8 +427,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname +@@ -467,8 +461,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting + # + # PAC attributes tests + # +diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c +index e0e483662c0..2a96a683cd9 100644 +--- a/source4/kdc/pac-glue.c ++++ b/source4/kdc/pac-glue.c +@@ -1237,11 +1237,7 @@ krb5_error_code samba_kdc_validate_pac_blob( + "PAC[%s] != CLI[%s]\n", + dom_sid_str_buf(&pac_sid, &buf1), + dom_sid_str_buf(client_sid, &buf2)); +-#if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */ +- code = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; +-#else /* Heimdal (where this is an enum) */ +- code = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; +-#endif ++ code = KRB5KDC_ERR_TGT_REVOKED; + goto out; + } + +-- +2.25.1 + + +From 99a11ec7e78aa8bc477de18253f068f3a0c84c19 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:05:17 +1300 +Subject: [PATCH 39/99] tests/krb5: Add test for S4U2Self with wrong sname + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit bac5f75059450898937be891e863826e1350b62c) +--- + python/samba/tests/krb5/s4u_tests.py | 32 +++++++++++++++++++++++++++- + selftest/knownfail_heimdal_kdc | 1 + + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py +index 5f37525f393..2953766ef21 100755 +--- a/python/samba/tests/krb5/s4u_tests.py ++++ b/python/samba/tests/krb5/s4u_tests.py +@@ -36,6 +36,7 @@ from samba.tests.krb5.raw_testcase import ( + from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, ++ KDC_ERR_BADMATCH, + KDC_ERR_BADOPTION, + KDC_ERR_BAD_INTEGRITY, + KDC_ERR_GENERIC, +@@ -243,7 +244,9 @@ class S4UKerberosTests(KDCBaseTest): + client_dn = client_creds.get_dn() + sid = self.get_objectSid(samdb, client_dn) + +- service_name = service_creds.get_username()[:-1] ++ service_name = kdc_dict.pop('service_name', None) ++ if service_name is None: ++ service_name = service_creds.get_username()[:-1] + service_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=['host', service_name]) + +@@ -474,6 +477,33 @@ class S4UKerberosTests(KDCBaseTest): + 'expected_flags': 'forwardable' + }) + ++ # Do an S4U2Self with the sname in the request different to that of the ++ # service. We expect an error. ++ def test_s4u2self_wrong_sname(self): ++ other_creds = self.get_cached_creds( ++ account_type=self.AccountType.COMPUTER, ++ opts={ ++ 'trusted_to_auth_for_delegation': True, ++ 'id': 0 ++ }) ++ other_sname = other_creds.get_username()[:-1] ++ ++ self._run_s4u2self_test( ++ { ++ 'expected_error_mode': KDC_ERR_BADMATCH, ++ 'expect_edata': False, ++ 'client_opts': { ++ 'not_delegated': False ++ }, ++ 'service_opts': { ++ 'trusted_to_auth_for_delegation': True ++ }, ++ 'service_name': other_sname, ++ 'kdc_options': 'forwardable', ++ 'modify_service_tgt_fn': functools.partial( ++ self.set_ticket_forwardable, flag=True) ++ }) ++ + def _run_delegation_test(self, kdc_dict): + client_opts = kdc_dict.pop('client_opts', None) + client_creds = self.get_cached_creds( +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index fc2a3554f0d..fd05719cc4c 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -81,6 +81,7 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +-- +2.25.1 + + +From daef3c8a3607575e077c2eff55a06867201d6f2b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:00:07 +1300 +Subject: [PATCH 40/99] kdc: Match Windows error code for mismatching sname + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit b6a25f5f016aef39c3b1d7be8b3ecfe021c03c83) +--- + selftest/knownfail_heimdal_kdc | 3 --- + source4/kdc/db-glue.c | 2 +- + 2 files changed, 1 insertion(+), 4 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index fd05719cc4c..d89d69deed2 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -81,7 +81,6 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -130,6 +129,4 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index d017741e30a..bed0ff773f9 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -2599,7 +2599,7 @@ samba_kdc_check_s4u2self(krb5_context context, + */ + if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) { + talloc_free(frame); +- return KRB5KDC_ERR_BADOPTION; ++ return KRB5KRB_AP_ERR_BADMATCH; + } + + talloc_free(frame); +-- +2.25.1 + + +From 0368939b7d60c08aa8f84dbb53a88d5c9ec96058 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 20:15:41 +1300 +Subject: [PATCH 41/99] kdc: Always add the PAC if the header TGT is from an + RODC + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 690a00a40c0a3f77da6e4dca42b630f2793a98b8) +--- + selftest/knownfail_heimdal_kdc | 1 - + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index d89d69deed2..3b78491c837 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -128,5 +128,4 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index ecd182702c3..8c3ce71529c 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -471,7 +471,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!server_skdc_entry->is_krbtgt) { ++ if (!is_untrusted && !server_skdc_entry->is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +-- +2.25.1 + + +From 2903a913bf3ca96b9dd3f636b05530adc6e7994f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:32:44 +1300 +Subject: [PATCH 42/99] tests/krb5: Add tests for renewal and validation of + RODC TGTs with PAC requests + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 73a48063469205099f02efdf3b8f0f1040dc7a3d) +--- + python/samba/tests/krb5/kdc_tgs_tests.py | 90 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 6 ++ + selftest/knownfail_mit_kdc | 6 ++ + 3 files changed, 102 insertions(+) + +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index ecc38538e61..2923d53772a 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -1867,6 +1867,51 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_rodc_renew_pac_request_none(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=None) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_renew_pac_request_false(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_renew_pac_request_true(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=True) ++ tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True) ++ ++ tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_validate_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +@@ -1912,6 +1957,51 @@ class KdcTgsTests(KDCBaseTest): + pac = self.get_ticket_pac(ticket) + self.assertIsNotNone(pac) + ++ def test_rodc_validate_pac_request_none(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=None) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_validate_pac_request_false(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=False, expect_pac=None) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ ++ def test_rodc_validate_pac_request_true(self): ++ creds = self._get_creds(replication_allowed=True, ++ revealed_to_rodc=True) ++ tgt = self.get_tgt(creds, pac_request=True) ++ tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True) ++ ++ tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None, ++ expect_pac_attrs=False, ++ expect_requester_sid=True) ++ ++ ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True) ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + def test_s4u2self_pac_request_none(self): + creds = self._get_creds() + tgt = self.get_tgt(creds, pac_request=None) +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 3b78491c837..cc2396b2d38 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -116,6 +116,12 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 806aaa707d7..36be42d0481 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -400,6 +400,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) +-- +2.25.1 + + +From 81a6fa876fd48af9998ee209d96e3cde1511e9f5 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 13:24:57 +1300 +Subject: [PATCH 43/99] Revert "CVE-2020-25719 s4/torture: Expect additional + PAC buffers" + +This reverts commit fa4c9bcefdeed0a7106aab84df20b02435febc1f. + +We should not be generating these additional PAC buffers for service +tickets, only for TGTs. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit e61983c7f2c4daade83b237efb990d0c0645b3a3) +--- + selftest/knownfail_heimdal_kdc | 39 ++++++++++++++++++++++++++++++++ + source4/torture/rpc/remote_pac.c | 24 ++------------------ + 2 files changed, 41 insertions(+), 22 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index cc2396b2d38..1e42007f31f 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -135,3 +135,42 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed ++# ++# PAC tests ++# ++^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local ++^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local ++^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc ++^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc +diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c +index 5a1567f1bde..16249799e36 100644 +--- a/source4/torture/rpc/remote_pac.c ++++ b/source4/torture/rpc/remote_pac.c +@@ -308,7 +308,7 @@ static bool test_PACVerify(struct torture_context *tctx, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed"); + +- num_pac_buffers = 7; ++ num_pac_buffers = 5; + if (expect_pac_upn_dns_info) { + num_pac_buffers += 1; + } +@@ -365,18 +365,6 @@ static bool test_PACVerify(struct torture_context *tctx, + pac_buf->info != NULL, + "PAC_TYPE_TICKET_CHECKSUM info"); + +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO"); +- torture_assert(tctx, +- pac_buf->info != NULL, +- "PAC_TYPE_ATTRIBUTES_INFO info"); +- +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID"); +- torture_assert(tctx, +- pac_buf->info != NULL, +- "PAC_TYPE_REQUESTER_SID info"); +- + ok = netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name, + negotiate_flags, pac_data, session_info); + +@@ -1140,7 +1128,7 @@ static bool test_S4U2Proxy(struct torture_context *tctx, + (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); + torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed"); + +- num_pac_buffers = 9; ++ num_pac_buffers = 7; + + torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version"); + torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers"); +@@ -1180,14 +1168,6 @@ static bool test_S4U2Proxy(struct torture_context *tctx, + talloc_asprintf(tctx, "%s@%s", self_princ, cli_credentials_get_realm(credentials)), + "wrong transited_services[0]"); + +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO"); +- torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_ATTRIBUTES_INFO info"); +- +- pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID); +- torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID"); +- torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_REQUESTER_SID info"); +- + return netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name, + negotiate_flags, pac_data, session_info); + } +-- +2.25.1 + + +From 88b71db4bb8315c6d53c820bfc7b680bf04114a9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:42:22 +1300 +Subject: [PATCH 44/99] kdc: Don't include extra PAC buffers in service tickets + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 90025b6a4d250a15c0f988a9a9150ecfb63069ef) +--- + selftest/knownfail_heimdal_kdc | 42 ---------------------------------- + source4/kdc/wdc-samba4.c | 31 +++++++++++++++++-------- + 2 files changed, 21 insertions(+), 52 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 1e42007f31f..219ab11e16a 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -123,11 +123,8 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_) + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +@@ -135,42 +132,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +-# +-# PAC tests +-# +-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local +-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local +-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc +-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 8c3ce71529c..17af76f4edb 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -132,6 +132,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + krb5_error_code ret; + NTSTATUS nt_status; + bool is_in_db, is_untrusted; ++ bool is_krbtgt; + size_t num_types = 0; + uint32_t *types = NULL; + uint32_t forced_next_type = 0; +@@ -471,7 +472,9 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + goto out; + } + +- if (!is_untrusted && !server_skdc_entry->is_krbtgt) { ++ is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); ++ ++ if (!is_untrusted && !is_krbtgt) { + /* + * The client may have requested no PAC when obtaining the + * TGT. +@@ -576,17 +579,25 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- /* just copy... */ +- break; ++ if (is_krbtgt) { ++ /* just copy... */ ++ break; ++ } else { ++ continue; ++ } + case PAC_TYPE_REQUESTER_SID: +- /* +- * Replace in the RODC case, otherwise +- * requester_sid_blob is NULL and we just copy. +- */ +- if (requester_sid_blob != NULL) { +- type_blob = *requester_sid_blob; ++ if (is_krbtgt) { ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; ++ } else { ++ continue; + } +- break; + default: + /* just copy... */ + break; +-- +2.25.1 + + +From 081d6b571a81266b39b0efb70c1de492e3d60ae0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 10:53:49 +1300 +Subject: [PATCH 45/99] kdc: Remove PAC_TYPE_ATTRIBUTES_INFO from RODC-issued + tickets + +Windows ignores PAC_TYPE_ATTRIBUTES_INFO and always issues a PAC when +presented with an RODC-issued TGT. By removing this PAC buffer from +RODC-issued tickets, we ensure that an RODC-issued ticket will still +result in a PAC if it is first renewed or validated by the main DC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 4b60e9516497c2e7f1545fe50887d0336b9893f2) +--- + selftest/knownfail_heimdal_kdc | 13 ------------- + source4/kdc/wdc-samba4.c | 2 +- + 2 files changed, 1 insertion(+), 14 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 219ab11e16a..7dccc3d4c0d 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -112,16 +112,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +@@ -129,6 +119,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 17af76f4edb..713720bcb99 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -579,7 +579,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + type_blob = data_blob_const(&zero_byte, 1); + break; + case PAC_TYPE_ATTRIBUTES_INFO: +- if (is_krbtgt) { ++ if (!is_untrusted && is_krbtgt) { + /* just copy... */ + break; + } else { +-- +2.25.1 + + +From 992a924dfa401daa630931c5dbec2fe9537c7ea9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 12:46:40 +1300 +Subject: [PATCH 46/99] tests/krb5: Add a test for S4U2Self with no + authorization data required + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 192d6edfe912105ec344dc554f872a24c03540a3) +--- + python/samba/tests/krb5/s4u_tests.py | 34 ++++++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 1 + + 2 files changed, 35 insertions(+) + +diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py +index 2953766ef21..6ec9af11423 100755 +--- a/python/samba/tests/krb5/s4u_tests.py ++++ b/python/samba/tests/krb5/s4u_tests.py +@@ -324,6 +324,13 @@ class S4UKerberosTests(KDCBaseTest): + sname=service_sname, + etypes=etypes) + ++ if not expected_error_mode: ++ # Check that the ticket contains a PAC. ++ ticket = kdc_exchange_dict['rep_ticket_creds'] ++ ++ pac = self.get_ticket_pac(ticket) ++ self.assertIsNotNone(pac) ++ + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + +@@ -504,6 +511,24 @@ class S4UKerberosTests(KDCBaseTest): + self.set_ticket_forwardable, flag=True) + }) + ++ # Do an S4U2Self where the service does not require authorization data. The ++ # resulting ticket should still contain a PAC. ++ def test_s4u2self_no_auth_data_required(self): ++ self._run_s4u2self_test( ++ { ++ 'client_opts': { ++ 'not_delegated': False ++ }, ++ 'service_opts': { ++ 'trusted_to_auth_for_delegation': True, ++ 'no_auth_data_required': True ++ }, ++ 'kdc_options': 'forwardable', ++ 'modify_service_tgt_fn': functools.partial( ++ self.set_ticket_forwardable, flag=True), ++ 'expected_flags': 'forwardable' ++ }) ++ + def _run_delegation_test(self, kdc_dict): + client_opts = kdc_dict.pop('client_opts', None) + client_creds = self.get_cached_creds( +@@ -654,6 +679,15 @@ class S4UKerberosTests(KDCBaseTest): + etypes=etypes, + additional_tickets=additional_tickets) + ++ if not expected_error_mode: ++ # Check whether the ticket contains a PAC. ++ ticket = kdc_exchange_dict['rep_ticket_creds'] ++ pac = self.get_ticket_pac(ticket, expect_pac=expect_pac) ++ if expect_pac: ++ self.assertIsNotNone(pac) ++ else: ++ self.assertIsNone(pac) ++ + # Ensure we used all the parameters given to us. + self.assertEqual({}, kdc_dict) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 7dccc3d4c0d..363107f476e 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -80,6 +80,7 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +-- +2.25.1 + + +From 5e6c25f1ed08045f5341e425621e32a75e84ff27 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 17:30:50 +1300 +Subject: [PATCH 47/99] heimdal:kdc: Always generate a PAC for S4U2Self + +If we decided not to put a PAC into the ticket, mspac would be NULL +here, and the resulting ticket would not contain a PAC. This could +happen if there was a request to omit the PAC or the service did not +require authorization data. Ensure that we always generate a PAC. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 1f4f3018c5001b289b91959a72d00575c8fc0ac1) +--- + selftest/knownfail_heimdal_kdc | 2 -- + source4/heimdal/kdc/krb5tgs.c | 13 +++++++------ + 2 files changed, 7 insertions(+), 8 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 363107f476e..ace0550fd15 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -80,7 +80,6 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required +@@ -113,7 +112,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index 6c5c51aa448..dc356b4daa5 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -1846,12 +1846,13 @@ server_lookup: + if (mspac) { + krb5_pac_free(context, mspac); + mspac = NULL; +- ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); +- if (ret) { +- kdc_log(context, config, 0, "PAC generation failed for -- %s", +- tpn); +- goto out; +- } ++ } ++ ++ ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); ++ if (ret) { ++ kdc_log(context, config, 0, "PAC generation failed for -- %s", ++ tpn); ++ goto out; + } + + /* +-- +2.25.1 + + +From 612c769ab7061906f2089e7af15c3745be610201 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 25 Nov 2021 09:29:42 +1300 +Subject: [PATCH 48/99] selftest: Properly check extra PAC buffers with Heimdal + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit ee4aa21c487fa80082a548b2e4f115a791e30340) +--- + selftest/knownfail_heimdal_kdc | 12 ++++++++++++ + source4/selftest/tests.py | 2 +- + 2 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index ace0550fd15..4d7d6a67b92 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -79,8 +79,15 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed ++^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -112,6 +119,11 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) ++^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index 7234767baa5..f2ea9adb67f 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -905,7 +905,7 @@ for env in ['fileserver_smb1', 'nt4_member', 'clusteredmember', 'ktest', 'nt4_dc + have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) + tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) + expect_pac = int('SAMBA4_USES_HEIMDAL' in config_hash) +-extra_pac_buffers = 0 ++extra_pac_buffers = int('SAMBA4_USES_HEIMDAL' in config_hash) + planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", + environ={'SERVICE_USERNAME':'$SERVER', +-- +2.25.1 + + +From 0426d20aeabba4dbd76bffbadd97a5c8afe2091e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 23 Nov 2021 19:38:35 +1300 +Subject: [PATCH 49/99] heimdal:kdc: Do not generate extra PAC buffers for + S4U2Self service ticket + +Normally samba_wdc_get_pac() is used to generate the PAC for a TGT, but +when generating a service ticket for S4U2Self, we want to avoid adding +the additional PAC_ATTRIBUTES_INFO and PAC_REQUESTER_SID buffers. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 9bd26804852d957f81cb311e5142f9190f9afa65) +--- + selftest/knownfail_heimdal_kdc | 12 ------------ + source4/heimdal/kdc/kerberos5.c | 2 +- + source4/heimdal/kdc/krb5tgs.c | 3 ++- + source4/heimdal/kdc/windc.c | 5 +++-- + source4/heimdal/kdc/windc_plugin.h | 2 ++ + source4/kdc/wdc-samba4.c | 11 ++++++++--- + 6 files changed, 16 insertions(+), 19 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 4d7d6a67b92..ace0550fd15 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -79,15 +79,8 @@ + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed +-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable + # + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required + ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required +@@ -119,11 +112,6 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid) +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c +index 11b334e46fe..ad026dd617b 100644 +--- a/source4/heimdal/kdc/kerberos5.c ++++ b/source4/heimdal/kdc/kerberos5.c +@@ -1777,7 +1777,7 @@ _kdc_as_rep(krb5_context context, + + sent_pac_request = send_pac_p(context, req, &pac_request); + +- ret = _kdc_pac_generate(context, client, pk_reply_key, ++ ret = _kdc_pac_generate(context, client, server, pk_reply_key, + sent_pac_request ? &pac_request : NULL, + &p); + if (ret) { +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index dc356b4daa5..38dba8493ae 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -1848,7 +1848,8 @@ server_lookup: + mspac = NULL; + } + +- ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac); ++ ret = _kdc_pac_generate(context, s4u2self_impersonated_client, server, ++ NULL, NULL, &mspac); + if (ret) { + kdc_log(context, config, 0, "PAC generation failed for -- %s", + tpn); +diff --git a/source4/heimdal/kdc/windc.c b/source4/heimdal/kdc/windc.c +index 93b973f576b..0a5ae5025ec 100644 +--- a/source4/heimdal/kdc/windc.c ++++ b/source4/heimdal/kdc/windc.c +@@ -73,6 +73,7 @@ krb5_kdc_windc_init(krb5_context context) + krb5_error_code + _kdc_pac_generate(krb5_context context, + hdb_entry_ex *client, ++ hdb_entry_ex *server, + const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, + krb5_pac *pac) +@@ -88,9 +89,9 @@ _kdc_pac_generate(krb5_context context, + + if (windcft->pac_pk_generate != NULL && pk_reply_key != NULL) + return (windcft->pac_pk_generate)(windcctx, context, +- client, pk_reply_key, ++ client, server, pk_reply_key, + pac_request, pac); +- return (windcft->pac_generate)(windcctx, context, client, ++ return (windcft->pac_generate)(windcctx, context, client, server, + pac_request, pac); + } + +diff --git a/source4/heimdal/kdc/windc_plugin.h b/source4/heimdal/kdc/windc_plugin.h +index c7f2bcb5ed9..d239d0260e7 100644 +--- a/source4/heimdal/kdc/windc_plugin.h ++++ b/source4/heimdal/kdc/windc_plugin.h +@@ -55,12 +55,14 @@ struct hdb_entry_ex; + typedef krb5_error_code + (*krb5plugin_windc_pac_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ ++ struct hdb_entry_ex *, /* server */ + const krb5_boolean *, /* pac_request */ + krb5_pac *); + + typedef krb5_error_code + (*krb5plugin_windc_pac_pk_generate)(void *, krb5_context, + struct hdb_entry_ex *, /* client */ ++ struct hdb_entry_ex *, /* server */ + const krb5_keyblock *, /* pk_replykey */ + const krb5_boolean *, /* pac_request */ + krb5_pac *); +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index 713720bcb99..b1d011c09a9 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -37,6 +37,7 @@ + */ + static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, + const krb5_keyblock *pk_reply_key, + const krb5_boolean *pac_request, + krb5_pac *pac) +@@ -55,6 +56,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + struct samba_kdc_entry *skdc_entry = + talloc_get_type_abort(client->ctx, + struct samba_kdc_entry); ++ bool is_krbtgt; + + mem_ctx = talloc_named(client->ctx, 0, "samba_get_pac context"); + if (!mem_ctx) { +@@ -65,13 +67,15 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + cred_ndr_ptr = &cred_ndr; + } + ++ is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal); ++ + nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry, + &logon_blob, + cred_ndr_ptr, + &upn_blob, +- &pac_attrs_blob, ++ is_krbtgt ? &pac_attrs_blob : NULL, + pac_request, +- &requester_sid_blob, ++ is_krbtgt ? &requester_sid_blob : NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); +@@ -101,10 +105,11 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context, + + static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context, + struct hdb_entry_ex *client, ++ struct hdb_entry_ex *server, + const krb5_boolean *pac_request, + krb5_pac *pac) + { +- return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac); ++ return samba_wdc_get_pac(priv, context, client, server, NULL, pac_request, pac); + } + + static krb5_error_code samba_wdc_reget_pac2(krb5_context context, +-- +2.25.1 + + +From 2eef0f950bc8c2ed2309798a75d88823a81eefff Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 24 Nov 2021 20:41:54 +1300 +Subject: [PATCH 50/99] kdc: Require that PAC_REQUESTER_SID buffer is present + for TGTs + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Nov 30 03:33:26 UTC 2021 on sn-devel-184 + +(cherry picked from commit 38c5bad4a853b19fe9a51fb059e150b153c4632a) +--- + selftest/knownfail_heimdal_kdc | 6 ------ + source4/kdc/wdc-samba4.c | 6 ++++++ + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index ace0550fd15..e9a560555da 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -112,9 +112,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c +index b1d011c09a9..d7ce34fb3a9 100644 +--- a/source4/kdc/wdc-samba4.c ++++ b/source4/kdc/wdc-samba4.c +@@ -459,6 +459,12 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context, + talloc_free(mem_ctx); + return EINVAL; + } ++ if (delegated_proxy_principal == NULL && requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ talloc_free(mem_ctx); ++ return KRB5KDC_ERR_TGT_REVOKED; ++ } + + /* + * The server account may be set not to want the PAC. +-- +2.25.1 + + +From d34d201773ae9c05e424a5c5d568c94483f1be69 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 7 Dec 2021 13:15:38 +1300 +Subject: [PATCH 51/99] kdc: Canonicalize realm for enterprise principals + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett + +Autobuild-User(master): Andrew Bartlett +Autobuild-Date(master): Tue Dec 7 04:54:35 UTC 2021 on sn-devel-184 + +(cherry picked from commit 8bd7b316bd61ef35f6e0baa0b65f0ef00910112c) +--- + selftest/knownfail.d/kdc-enterprise | 63 ----------------------------- + selftest/knownfail_heimdal_kdc | 3 -- + selftest/knownfail_mit_kdc | 36 +++++++++++++++++ + source4/kdc/db-glue.c | 24 +++++------ + 4 files changed, 47 insertions(+), 79 deletions(-) + delete mode 100644 selftest/knownfail.d/kdc-enterprise + +diff --git a/selftest/knownfail.d/kdc-enterprise b/selftest/knownfail.d/kdc-enterprise +deleted file mode 100644 +index c9b6c98a2ee..00000000000 +--- a/selftest/knownfail.d/kdc-enterprise ++++ /dev/null +@@ -1,63 +0,0 @@ +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( +-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_UPN\( +- +- +- +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\( +-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\( +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index e9a560555da..692b9ecdd72 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -5,9 +5,6 @@ + # + # Heimdal currently fails the following MS-KILE client principal lookup + # tests +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_1_3 +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_4 +-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_5 + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_6_a + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_enterprise_principal_step_6_b + ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_4_a +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 36be42d0481..6a4ddaa00ec 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -56,17 +56,53 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN_RemoveDollar\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\( ++samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_RemoveDollar\( + samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN\( +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index bed0ff773f9..5752ffb821c 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -980,19 +980,17 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + goto out; + } + +- if (smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) { +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ krb5_clear_error_message(context); ++ goto out; + } + } + +-- +2.25.1 + + +From 3ac74c8b94d6c2d109ee07712f55be01190a6816 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Dec 2021 19:16:00 +1300 +Subject: [PATCH 52/99] tests/krb5: Correctly determine whether tickets are + service tickets + +Previously we expected tickets to contain a ticket checksum if the sname +was not the krbtgt. However, the ticket checksum should not be present +if we are performing an AS-REQ to our own account. Now we determine a +ticket is a service ticket only if the request is also a TGS-REQ. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andrew Bartlett +(cherry picked from commit 100be7eb8e70ba270a8e92957a5e47466160a901) +--- + python/samba/tests/krb5/compatability_tests.py | 10 ++++++---- + python/samba/tests/krb5/kdc_base_test.py | 2 +- + python/samba/tests/krb5/raw_testcase.py | 18 ++++++++++-------- + python/samba/tests/krb5/rodc_tests.py | 4 ++-- + 4 files changed, 19 insertions(+), 15 deletions(-) + +diff --git a/python/samba/tests/krb5/compatability_tests.py b/python/samba/tests/krb5/compatability_tests.py +index ed2dc565b6d..65e9e3788d5 100755 +--- a/python/samba/tests/krb5/compatability_tests.py ++++ b/python/samba/tests/krb5/compatability_tests.py +@@ -132,13 +132,14 @@ class SimpleKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, key) ++ self.verify_ticket(tgt, key, service_ticket=False) + + # Get a service ticket from the DC. + service_ticket = self.get_service_ticket(tgt, target_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(service_ticket, key, expect_ticket_checksum=True) ++ self.verify_ticket(service_ticket, key, service_ticket=True, ++ expect_ticket_checksum=True) + + def test_mit_ticket_signature(self): + # Ensure that a DC does not issue tickets signed with its krbtgt key. +@@ -152,13 +153,14 @@ class SimpleKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, key) ++ self.verify_ticket(tgt, key, service_ticket=False) + + # Get a service ticket from the DC. + service_ticket = self.get_service_ticket(tgt, target_creds) + + # Ensure the PAC does not contain the expected checksums. +- self.verify_ticket(service_ticket, key, expect_ticket_checksum=False) ++ self.verify_ticket(service_ticket, key, service_ticket=True, ++ expect_ticket_checksum=False) + + def as_pre_auth_req(self, creds, etypes): + user = creds.get_username() +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 6e96b982167..9506048ee2a 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -1395,7 +1395,7 @@ class KDCBaseTest(RawKerberosTest): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + self.verify_ticket(service_ticket_creds, krbtgt_key, +- expect_pac=expect_pac, ++ service_ticket=True, expect_pac=expect_pac, + expect_ticket_checksum=self.tkt_sig_support) + + self.tkt_cache[cache_key] = service_ticket_creds +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 14e655313fc..a2241707d44 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -2587,7 +2587,11 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertIsNotNone(ticket_decryption_key) + + if ticket_decryption_key is not None: +- self.verify_ticket(ticket_creds, krbtgt_keys, expect_pac=expect_pac, ++ service_ticket = (not self.is_tgs(expected_sname) ++ and rep_msg_type == KRB_TGS_REP) ++ self.verify_ticket(ticket_creds, krbtgt_keys, ++ service_ticket=service_ticket, ++ expect_pac=expect_pac, + expect_ticket_checksum=expect_ticket_checksum + or self.tkt_sig_support) + +@@ -2624,14 +2628,14 @@ class RawKerberosTest(TestCaseInTempDir): + expected_types.append(krb5pac.PAC_TYPE_DEVICE_INFO) + expected_types.append(krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO) + +- if not self.is_tgs(expected_sname): ++ if not self.is_tgs(expected_sname) and rep_msg_type == KRB_TGS_REP: + expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + + require_strict = {krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO} + if not self.tkt_sig_support: + require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM) + +- expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP ++ expect_extra_pac_buffers = self.is_tgs(expected_sname) + + expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs'] + +@@ -3233,11 +3237,9 @@ class RawKerberosTest(TestCaseInTempDir): + ticket_blob) + self.assertEqual(expected_checksum, checksum) + +- def verify_ticket(self, ticket, krbtgt_keys, expect_pac=True, ++ def verify_ticket(self, ticket, krbtgt_keys, service_ticket, ++ expect_pac=True, + expect_ticket_checksum=True): +- # Check if the ticket is a TGT. +- is_tgt = self.is_tgt(ticket) +- + # Decrypt the ticket. + + key = ticket.decryption_key +@@ -3336,7 +3338,7 @@ class RawKerberosTest(TestCaseInTempDir): + kdc_ctype, + kdc_checksum) + +- if is_tgt: ++ if not service_ticket: + self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums) + else: + ticket_checksum, ticket_ctype = checksums.get( +diff --git a/python/samba/tests/krb5/rodc_tests.py b/python/samba/tests/krb5/rodc_tests.py +index 0e252d90262..83ee35d650a 100755 +--- a/python/samba/tests/krb5/rodc_tests.py ++++ b/python/samba/tests/krb5/rodc_tests.py +@@ -58,14 +58,14 @@ class RodcKerberosTests(KDCBaseTest): + tgt = self.get_tgt(user_creds, to_rodc=True) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(tgt, rodc_key) ++ self.verify_ticket(tgt, rodc_key, service_ticket=False) + + # Get a service ticket from the RODC. + service_ticket = self.get_service_ticket(tgt, target_creds, + to_rodc=True) + + # Ensure the PAC contains the expected checksums. +- self.verify_ticket(service_ticket, rodc_key) ++ self.verify_ticket(service_ticket, rodc_key, service_ticket=True) + + + if __name__ == "__main__": +-- +2.25.1 + + +From 9a1bee7c95d04577ce129f86c0b23f4f73cd9aae Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 8 Feb 2022 12:15:36 +1300 +Subject: [PATCH 53/99] tests/krb5: Add helper function to modify ticket flags + +Signed-off-by: Joseph Sutton +Reviewed-by: Stefan Metzmacher +(cherry picked from commit ded5115f73dff5b8b2f3212988e03f9dbe0c2aa3) +--- + python/samba/tests/krb5/kdc_base_test.py | 14 ++++++++++++++ + python/samba/tests/krb5/kdc_tgs_tests.py | 18 ++---------------- + python/samba/tests/krb5/s4u_tests.py | 17 +++-------------- + 3 files changed, 19 insertions(+), 30 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 9506048ee2a..58b87eab25b 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -1602,6 +1602,20 @@ class KDCBaseTest(RawKerberosTest): + enc_part, asn1Spec=krb5_asn1.EncTicketPart()) + return enc_ticket_part + ++ def modify_ticket_flag(self, enc_part, flag, value): ++ self.assertIsInstance(value, bool) ++ ++ flag = krb5_asn1.TicketFlags(flag) ++ pos = len(tuple(flag)) - 1 ++ ++ flags = enc_part['flags'] ++ self.assertLessEqual(pos, len(flags)) ++ ++ new_flags = flags[:pos] + str(int(value)) + flags[pos + 1:] ++ enc_part['flags'] = new_flags ++ ++ return enc_part ++ + def get_objectSid(self, samdb, dn): + ''' Get the objectSID for a DN + Note: performs an Ldb query. +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 2923d53772a..8cd27dec2aa 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -2177,14 +2177,7 @@ class KdcTgsTests(KDCBaseTest): + + def _modify_renewable(self, enc_part): + # Set the renewable flag. +- renewable_flag = krb5_asn1.TicketFlags('renewable') +- pos = len(tuple(renewable_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags ++ enc_part = self.modify_ticket_flag(enc_part, 'renewable', value=True) + + # Set the renew-till time to be in the future. + renew_till = self.get_KerberosTime(offset=100 * 60 * 60) +@@ -2194,14 +2187,7 @@ class KdcTgsTests(KDCBaseTest): + + def _modify_invalid(self, enc_part): + # Set the invalid flag. +- invalid_flag = krb5_asn1.TicketFlags('invalid') +- pos = len(tuple(invalid_flag)) - 1 +- +- flags = enc_part['flags'] +- self.assertLessEqual(pos, len(flags)) +- +- new_flags = flags[:pos] + '1' + flags[pos + 1:] +- enc_part['flags'] = new_flags ++ enc_part = self.modify_ticket_flag(enc_part, 'invalid', value=True) + + # Set the ticket start time to be in the past. + past_time = self.get_KerberosTime(offset=-100 * 60 * 60) +diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py +index 6ec9af11423..49dd89cd764 100755 +--- a/python/samba/tests/krb5/s4u_tests.py ++++ b/python/samba/tests/krb5/s4u_tests.py +@@ -1336,20 +1336,9 @@ class S4UKerberosTests(KDCBaseTest): + modify_pac_fn=modify_pac_fn) + + def set_ticket_forwardable(self, ticket, flag, update_pac_checksums=True): +- flag = '1' if flag else '0' +- +- def modify_fn(enc_part): +- # Reset the forwardable flag +- forwardable_pos = (len(tuple(krb5_asn1.TicketFlags('forwardable'))) +- - 1) +- +- flags = enc_part['flags'] +- self.assertLessEqual(forwardable_pos, len(flags)) +- enc_part['flags'] = (flags[:forwardable_pos] + +- flag + +- flags[forwardable_pos+1:]) +- +- return enc_part ++ modify_fn = functools.partial(self.modify_ticket_flag, ++ flag='forwardable', ++ value=flag) + + if update_pac_checksums: + checksum_keys = self.get_krbtgt_checksum_key() +-- +2.25.1 + + +From 19d76f103100f1a915486eb0bad2264dd203e71e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 4 Mar 2022 16:57:27 +1300 +Subject: [PATCH 54/99] selftest: Simplify krb5 test environments + +It's not necessary to repeat the required environment variables for +every test. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +(cherry picked from commit e729606631b5bfaf7c4ad8c1e70697adf8274777) + +[jsutton@samba.org Fixed conflicts caused by missing check_cname, + check_padata and fast_support variables] +--- + source4/selftest/tests.py | 191 +++++++------------------------------- + 1 file changed, 35 insertions(+), 156 deletions(-) + +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index f2ea9adb67f..dc340623f3e 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -903,106 +903,59 @@ for env in ['fileserver_smb1', 'nt4_member', 'clusteredmember', 'ktest', 'nt4_dc + planoldpythontestsuite(env, "samba.tests.imports") + + have_fast_support = int('SAMBA_USES_MITKDC' in config_hash) ++claims_support = 0 ++compound_id_support = 0 + tkt_sig_support = int('SAMBA4_USES_HEIMDAL' in config_hash) + expect_pac = int('SAMBA4_USES_HEIMDAL' in config_hash) + extra_pac_buffers = int('SAMBA4_USES_HEIMDAL' in config_hash) ++krb5_environ = { ++ 'SERVICE_USERNAME': '$SERVER', ++ 'ADMIN_USERNAME': '$DC_USERNAME', ++ 'ADMIN_PASSWORD': '$DC_PASSWORD', ++ 'FOR_USER': '$DC_USERNAME', ++ 'STRICT_CHECKING':'0', ++ 'FAST_SUPPORT': have_fast_support, ++ 'CLAIMS_SUPPORT': claims_support, ++ 'COMPOUND_ID_SUPPORT': compound_id_support, ++ 'TKT_SIG_SUPPORT': tkt_sig_support, ++ 'EXPECT_PAC': expect_pac, ++ 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers, ++} + planoldpythontestsuite("none", "samba.tests.krb5.kcrypto") + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.simple_tests", +- environ={'SERVICE_USERNAME':'$SERVER', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) ++ environ=krb5_environ) + planoldpythontestsuite("ad_dc_default:local", "samba.tests.krb5.s4u_tests", +- environ={'ADMIN_USERNAME':'$USERNAME', +- 'ADMIN_PASSWORD':'$PASSWORD', +- 'FOR_USER':'$USERNAME', +- 'STRICT_CHECKING':'0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) ++ environ=krb5_environ) + planoldpythontestsuite("rodc:local", "samba.tests.krb5.rodc_tests", +- environ={'ADMIN_USERNAME':'$USERNAME', +- 'ADMIN_PASSWORD':'$PASSWORD', +- 'STRICT_CHECKING':'0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) ++ environ=krb5_environ) + + planoldpythontestsuite("ad_dc_default", "samba.tests.dsdb_dns") + + planoldpythontestsuite("fl2008r2dc:local", "samba.tests.krb5.xrealm_tests", +- environ={'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) ++ environ=krb5_environ) + + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ccache", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planoldpythontestsuite("ad_dc_default", "samba.tests.krb5.test_ldap", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + for env in ['ad_dc_default', 'ad_member']: + planoldpythontestsuite(env, "samba.tests.krb5.test_rpc", +- environ={ +- 'ADMIN_USERNAME': '$DC_USERNAME', +- 'ADMIN_PASSWORD': '$DC_PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planoldpythontestsuite("ad_dc_smb1", "samba.tests.krb5.test_smb", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planoldpythontestsuite("ad_member_idmap_nss:local", + "samba.tests.krb5.test_min_domain_uid", +- environ={ +- 'ADMIN_USERNAME': '$DC_USERNAME', +- 'ADMIN_PASSWORD': '$DC_PASSWORD', +- 'STRICT_CHECKING': '0' +- }) ++ environ=krb5_environ) + planoldpythontestsuite("ad_member_idmap_nss:local", + "samba.tests.krb5.test_idmap_nss", + environ={ +- 'ADMIN_USERNAME': '$DC_USERNAME', +- 'ADMIN_PASSWORD': '$DC_PASSWORD', ++ **krb5_environ, + 'MAPPED_USERNAME': 'bob', + 'MAPPED_PASSWORD': 'Secret007', + 'UNMAPPED_USERNAME': 'jane', + 'UNMAPPED_PASSWORD': 'Secret007', + 'INVALID_USERNAME': 'joe', + 'INVALID_PASSWORD': 'Secret007', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers + }) + + for env in ["ad_dc", smbv1_disabled_testenv]: +@@ -1591,26 +1544,10 @@ plansmbtorture4testsuite('krb5.kdc', env, ['ncacn_np:$SERVER_IP', "-k", "yes", ' + "samba4.krb5.kdc with account having identical UPN and SPN") + for env in ["fl2008r2dc", "fl2003dc"]: + planoldpythontestsuite(env, "samba.tests.krb5.as_req_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + + planoldpythontestsuite('fl2008r2dc', 'samba.tests.krb5.salt_tests', +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + + for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: + if env == "rodc": +@@ -1627,89 +1564,31 @@ for env in ["rodc", "promoted_dc", "fl2000dc", "fl2008r2dc"]: + "samba4.krb5.kdc with machine account") + + planpythontestsuite("ad_dc", "samba.tests.krb5.as_canonicalization_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite("ad_dc", "samba.tests.krb5.compatability_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite("ad_dc", "samba.tests.krb5.kdc_tests", +- environ={'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers}) ++ environ=krb5_environ) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.kdc_tgs_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.fast_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.ms_kile_client_principal_lookup_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.spn_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + planpythontestsuite( + "ad_dc", + "samba.tests.krb5.alias_tests", +- environ={ +- 'ADMIN_USERNAME': '$USERNAME', +- 'ADMIN_PASSWORD': '$PASSWORD', +- 'STRICT_CHECKING': '0', +- 'FAST_SUPPORT': have_fast_support, +- 'TKT_SIG_SUPPORT': tkt_sig_support, +- 'EXPECT_PAC': expect_pac, +- 'EXPECT_EXTRA_PAC_BUFFERS': extra_pac_buffers +- }) ++ environ=krb5_environ) + + for env in [ + 'vampire_dc', +-- +2.25.1 + + +From 8f4b78907bbfe915988d52724c66dae0e2eefa9b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 15 Jun 2022 19:37:39 +1200 +Subject: [PATCH 55/99] CVE-2022-2031 s4:kdc: Add MIT support for + ATTRIBUTES_INFO and REQUESTER_SID PAC buffers + +So that we do not confuse TGTs and kpasswd tickets, it is critical to +check that the REQUESTER_SID buffer exists in TGTs, and to ensure that +it is not propagated to service tickets. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton + +[jsutton@samba.org Brought in changes to add ATTRIBUTES_INFO and + REQUESTER_SID buffers to new PACs, and updated knownfails] +--- + selftest/knownfail_mit_kdc | 17 ----- + source4/kdc/mit-kdb/kdb_samba_policies.c | 5 +- + source4/kdc/mit_samba.c | 93 +++++++++++++++++++++++- + source4/kdc/mit_samba.h | 1 + + 4 files changed, 94 insertions(+), 22 deletions(-) + +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 6a4ddaa00ec..095da10238c 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -423,7 +423,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied +@@ -459,7 +458,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link +@@ -490,7 +488,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied +@@ -508,21 +505,17 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_true +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_false +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_pac_attrs + # +@@ -537,21 +530,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # PAC requester SID tests + # +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_as_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_nonexisting +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate +-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing +diff --git a/source4/kdc/mit-kdb/kdb_samba_policies.c b/source4/kdc/mit-kdb/kdb_samba_policies.c +index f35210669c2..dada3b79144 100644 +--- a/source4/kdc/mit-kdb/kdb_samba_policies.c ++++ b/source4/kdc/mit-kdb/kdb_samba_policies.c +@@ -162,6 +162,7 @@ done: + + static krb5_error_code ks_get_pac(krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -176,6 +177,7 @@ static krb5_error_code ks_get_pac(krb5_context context, + code = mit_samba_get_pac(mit_ctx, + context, + client, ++ server, + client_key, + pac); + if (code != 0) { +@@ -423,7 +425,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + */ + if (with_pac && generate_pac) { + DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name); +- code = ks_get_pac(context, client_entry, client_key, &pac); ++ code = ks_get_pac(context, client_entry, server, client_key, &pac); + if (code != 0) { + goto done; + } +@@ -474,6 +476,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context, + + code = ks_get_pac(context, + client_entry, ++ server, + client_key, + &pac); + if (code != 0 && code != ENOENT) { +diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c +index 53c137de2fd..ef4e8c2ed38 100644 +--- a/source4/kdc/mit_samba.c ++++ b/source4/kdc/mit_samba.c +@@ -433,6 +433,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac) + { +@@ -443,9 +444,12 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + DATA_BLOB **cred_ndr_ptr = NULL; + DATA_BLOB cred_blob = data_blob_null; + DATA_BLOB *pcred_blob = NULL; ++ DATA_BLOB *pac_attrs_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + NTSTATUS nt_status; + krb5_error_code code; + struct samba_kdc_entry *skdc_entry; ++ bool is_krbtgt; + + skdc_entry = talloc_get_type_abort(client->e_data, + struct samba_kdc_entry); +@@ -464,12 +468,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + } + #endif + ++ is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ); ++ + nt_status = samba_kdc_get_pac_blobs(tmp_ctx, + skdc_entry, + &logon_info_blob, + cred_ndr_ptr, + &upn_dns_info_blob, +- NULL, NULL, NULL, ++ is_krbtgt ? &pac_attrs_blob : NULL, ++ NULL, ++ is_krbtgt ? &requester_sid_blob : NULL, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(tmp_ctx); +@@ -497,8 +505,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + logon_info_blob, + pcred_blob, + upn_dns_info_blob, +- NULL, +- NULL, ++ pac_attrs_blob, ++ requester_sid_blob, + NULL, + pac); + +@@ -522,6 +530,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + DATA_BLOB *pac_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *deleg_blob = NULL; ++ DATA_BLOB *requester_sid_blob = NULL; + struct samba_kdc_entry *client_skdc_entry = NULL; + struct samba_kdc_entry *krbtgt_skdc_entry = NULL; + struct samba_kdc_entry *server_skdc_entry = NULL; +@@ -537,8 +546,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + ssize_t upn_dns_info_idx = -1; + ssize_t srv_checksum_idx = -1; + ssize_t kdc_checksum_idx = -1; ++ ssize_t tkt_checksum_idx = -1; ++ ssize_t attrs_info_idx = -1; ++ ssize_t requester_sid_idx = -1; + krb5_pac new_pac = NULL; + bool ok; ++ bool is_krbtgt; + + /* Create a memory context early so code can use talloc_stackframe() */ + tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context"); +@@ -546,6 +559,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + return ENOMEM; + } + ++ is_krbtgt = ks_is_tgs_principal(ctx, server->princ); ++ + if (client != NULL) { + client_skdc_entry = + talloc_get_type_abort(client->e_data, +@@ -604,7 +619,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + NULL, + &upn_blob, + NULL, NULL, +- NULL, ++ &requester_sid_blob, + NULL); + if (!NT_STATUS_IS_OK(nt_status)) { + code = EINVAL; +@@ -763,6 +778,45 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + kdc_checksum_idx = i; + break; ++ case PAC_TYPE_TICKET_CHECKSUM: ++ if (tkt_checksum_idx != -1) { ++ DBG_WARNING("ticket checksum type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ tkt_checksum_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ tkt_checksum_idx = i; ++ break; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (attrs_info_idx != -1) { ++ DBG_WARNING("attributes info type[%u] twice " ++ "[%zd] and [%zu]: \n", ++ types[i], ++ attrs_info_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ attrs_info_idx = i; ++ break; ++ case PAC_TYPE_REQUESTER_SID: ++ if (requester_sid_idx != -1) { ++ DBG_WARNING("requester sid type[%u] twice" ++ "[%zd] and [%zu]: \n", ++ types[i], ++ requester_sid_idx, ++ i); ++ SAFE_FREE(types); ++ code = EINVAL; ++ goto done; ++ } ++ requester_sid_idx = i; ++ break; + default: + continue; + } +@@ -792,6 +846,13 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + code = EINVAL; + goto done; + } ++ if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) && ++ requester_sid_idx == -1) { ++ DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n")); ++ SAFE_FREE(types); ++ code = KRB5KDC_ERR_TGT_REVOKED; ++ goto done; ++ } + + /* Build an updated PAC */ + code = krb5_pac_init(context, &new_pac); +@@ -857,6 +918,10 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + } + break; + case PAC_TYPE_SRV_CHECKSUM: ++ if (requester_sid_idx == -1 && requester_sid_blob != NULL) { ++ /* inject REQUESTER_SID */ ++ forced_next_type = PAC_TYPE_REQUESTER_SID; ++ } + /* + * This is generated in the main KDC code + */ +@@ -866,6 +931,26 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx, + * This is generated in the main KDC code + */ + continue; ++ case PAC_TYPE_ATTRIBUTES_INFO: ++ if (!is_untrusted && is_krbtgt) { ++ /* just copy... */ ++ break; ++ } ++ ++ continue; ++ case PAC_TYPE_REQUESTER_SID: ++ if (!is_krbtgt) { ++ continue; ++ } ++ ++ /* ++ * Replace in the RODC case, otherwise ++ * requester_sid_blob is NULL and we just copy. ++ */ ++ if (requester_sid_blob != NULL) { ++ type_blob = *requester_sid_blob; ++ } ++ break; + default: + /* just copy... */ + break; +diff --git a/source4/kdc/mit_samba.h b/source4/kdc/mit_samba.h +index 636c77ec97c..4431e82a1b2 100644 +--- a/source4/kdc/mit_samba.h ++++ b/source4/kdc/mit_samba.h +@@ -50,6 +50,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx, + int mit_samba_get_pac(struct mit_samba_context *smb_ctx, + krb5_context context, + krb5_db_entry *client, ++ krb5_db_entry *server, + krb5_keyblock *client_key, + krb5_pac *pac); + +-- +2.25.1 + + +From 6199a0763507ae96aad8d6b6dff50245d505404d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 16 Jun 2022 10:33:29 +1200 +Subject: [PATCH 56/99] heimdal:kdc: Accommodate NULL data parameter in + krb5_pac_get_buffer() + +Signed-off-by: Joseph Sutton +--- + source4/heimdal/lib/krb5/pac.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c +index 05bcc523080..100de904662 100644 +--- a/source4/heimdal/lib/krb5/pac.c ++++ b/source4/heimdal/lib/krb5/pac.c +@@ -394,10 +394,12 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, + if (p->pac->buffers[i].type != type) + continue; + +- ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); +- if (ret) { +- krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); +- return ret; ++ if (data) { ++ ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); ++ if (ret) { ++ krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); ++ return ret; ++ } + } + return 0; + } +-- +2.25.1 + + +From b0d3fd37a8884cf18f9c2bffc416035747d49977 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:17:02 +1200 +Subject: [PATCH 57/99] CVE-2022-2031 s4:kpasswd: Account for missing target + principal + +This field is supposed to be optional. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index 2117c1c1696..b53c1a4618a 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -143,16 +143,18 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + +- target_realm = smb_krb5_principal_get_realm( +- mem_ctx, context, target_principal); +- code = krb5_unparse_name_flags(context, +- target_principal, +- KRB5_PRINCIPAL_UNPARSE_NO_REALM, +- &target_name); +- if (code != 0) { +- DBG_WARNING("Failed to parse principal\n"); +- *error_string = "String conversion failed"; +- return KRB5_KPASSWD_HARDERROR; ++ if (target_principal != NULL) { ++ target_realm = smb_krb5_principal_get_realm( ++ mem_ctx, context, target_principal); ++ code = krb5_unparse_name_flags(context, ++ target_principal, ++ KRB5_PRINCIPAL_UNPARSE_NO_REALM, ++ &target_name); ++ if (code != 0) { ++ DBG_WARNING("Failed to parse principal\n"); ++ *error_string = "String conversion failed"; ++ return KRB5_KPASSWD_HARDERROR; ++ } + } + + if ((target_name != NULL && target_realm == NULL) || +-- +2.25.1 + + +From e21702d20b6d4507708791c5a6a674b8bdadaab0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:17:41 +1200 +Subject: [PATCH 58/99] CVE-2022-2031 s4:kpasswd: Add MIT fallback for decoding + setpw structure + +The target principal and realm fields of the setpw structure are +supposed to be optional, but in MIT Kerberos they are mandatory. For +better compatibility and ease of testing, fall back to parsing the +simpler (containing only the new password) structure if the MIT function +fails to decode it. + +Although the target principal and realm fields should be optional, one +is not supposed to specified without the other, so we don't have to deal +with the case where only one is specified. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-mit.c | 94 ++++++++++++++++++++++++++----- + 1 file changed, 79 insertions(+), 15 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index b53c1a4618a..9c4d2801669 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -28,6 +28,7 @@ + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "../lib/util/asn1.h" + + #define RFC3244_VERSION 0xff80 + +@@ -35,6 +36,52 @@ krb5_error_code decode_krb5_setpw_req(const krb5_data *code, + krb5_data **password_out, + krb5_principal *target_out); + ++/* ++ * A fallback for when MIT refuses to parse a setpw structure without the ++ * (optional) target principal and realm ++ */ ++static bool decode_krb5_setpw_req_simple(TALLOC_CTX *mem_ctx, ++ const DATA_BLOB *decoded_data, ++ DATA_BLOB *clear_data) ++{ ++ struct asn1_data *asn1 = NULL; ++ bool ret; ++ ++ asn1 = asn1_init(mem_ctx, 3); ++ if (asn1 == NULL) { ++ return false; ++ } ++ ++ ret = asn1_load(asn1, *decoded_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_start_tag(asn1, ASN1_SEQUENCE(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_start_tag(asn1, ASN1_CONTEXT(0)); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_read_OctetString(asn1, mem_ctx, clear_data); ++ if (!ret) { ++ goto out; ++ } ++ ++ ret = asn1_end_tag(asn1); ++ if (!ret) { ++ goto out; ++ } ++ ret = asn1_end_tag(asn1); ++ ++out: ++ asn1_free(asn1); ++ ++ return ret; ++} ++ + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, + struct auth_session_info *session_info, +@@ -93,9 +140,10 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + const char **error_string) + { + krb5_context context = kdc->smb_krb5_context->krb5_context; ++ DATA_BLOB clear_data; + krb5_data k_dec_data; +- krb5_data *k_clear_data; +- krb5_principal target_principal; ++ krb5_data *k_clear_data = NULL; ++ krb5_principal target_principal = NULL; + krb5_error_code code; + DATA_BLOB password; + char *target_realm = NULL; +@@ -114,29 +162,45 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + code = decode_krb5_setpw_req(&k_dec_data, + &k_clear_data, + &target_principal); +- if (code != 0) { +- DBG_WARNING("decode_krb5_setpw_req failed: %s\n", +- error_message(code)); +- ok = kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to decode packet", +- kpasswd_reply); ++ if (code == 0) { ++ clear_data.data = (uint8_t *)k_clear_data->data; ++ clear_data.length = k_clear_data->length; ++ } else { ++ target_principal = NULL; ++ ++ /* ++ * The MIT decode failed, so fall back to trying the simple ++ * case, without target_principal. ++ */ ++ ok = decode_krb5_setpw_req_simple(mem_ctx, ++ decoded_data, ++ &clear_data); + if (!ok) { +- *error_string = "Failed to create reply"; +- return KRB5_KPASSWD_HARDERROR; ++ DBG_WARNING("decode_krb5_setpw_req failed: %s\n", ++ error_message(code)); ++ ok = kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to decode packet", ++ kpasswd_reply); ++ if (!ok) { ++ *error_string = "Failed to create reply"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ return 0; + } +- return 0; + } + + ok = convert_string_talloc_handle(mem_ctx, + lpcfg_iconv_handle(kdc->task->lp_ctx), + CH_UTF8, + CH_UTF16, +- (const char *)k_clear_data->data, +- k_clear_data->length, ++ clear_data.data, ++ clear_data.length, + (void **)&password.data, + &password.length); +- krb5_free_data(context, k_clear_data); ++ if (k_clear_data != NULL) { ++ krb5_free_data(context, k_clear_data); ++ } + if (!ok) { + DBG_WARNING("String conversion failed\n"); + *error_string = "String conversion failed"; +-- +2.25.1 + + +From f4ea2a80d8440c4c7261229bd9285bce97226094 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:34:01 +1200 +Subject: [PATCH 59/99] CVE-2022-32744 tests/krb5: Correctly handle specifying + account kvno + +The environment variable is a string, but we expect an integer. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index a2241707d44..4120edf93b9 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -724,7 +724,7 @@ class RawKerberosTest(TestCaseInTempDir): + fallback_default=False, + allow_missing=kvno_allow_missing) + if kvno is not None: +- c.set_kvno(kvno) ++ c.set_kvno(int(kvno)) + aes256_key = self.env_get_var('AES256_KEY_HEX', prefix, + fallback_default=False, + allow_missing=aes256_allow_missing) +-- +2.25.1 + + +From 440aa37cc462ac9a230636e6758152c3a520fed4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 20:52:04 +1200 +Subject: [PATCH 60/99] CVE-2022-2031 tests/krb5: Split out _make_tgs_request() + +This allows us to make use of it in other tests. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to having older version of + _make_tgs_request()] +--- + python/samba/tests/krb5/kdc_base_test.py | 77 ++++++++++++++++++++++++ + python/samba/tests/krb5/kdc_tgs_tests.py | 76 ----------------------- + 2 files changed, 77 insertions(+), 76 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 58b87eab25b..2117663b26b 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -67,6 +67,7 @@ from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KDC_ERR_PREAUTH_REQUIRED, ++ KDC_ERR_TGT_REVOKED, + KRB_AS_REP, + KRB_TGS_REP, + KRB_ERROR, +@@ -1538,6 +1539,82 @@ class KDCBaseTest(RawKerberosTest): + + return ticket_creds + ++ def _make_tgs_request(self, client_creds, service_creds, tgt, ++ pac_request=None, expect_pac=True, ++ expect_error=False, ++ expected_account_name=None, ++ expected_upn_name=None, ++ expected_sid=None): ++ client_account = client_creds.get_username() ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[client_account]) ++ ++ service_account = service_creds.get_username() ++ sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=[service_account]) ++ ++ realm = service_creds.get_realm() ++ ++ expected_crealm = realm ++ expected_cname = cname ++ expected_srealm = realm ++ expected_sname = sname ++ ++ expected_supported_etypes = service_creds.tgs_supported_enctypes ++ ++ etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) ++ ++ kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) ++ ++ target_decryption_key = self.TicketDecryptionKey_from_creds( ++ service_creds) ++ ++ authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) ++ ++ if expect_error: ++ expected_error_mode = KDC_ERR_TGT_REVOKED ++ check_error_fn = self.generic_check_kdc_error ++ check_rep_fn = None ++ else: ++ expected_error_mode = 0 ++ check_error_fn = None ++ check_rep_fn = self.generic_check_kdc_rep ++ ++ kdc_exchange_dict = self.tgs_exchange_dict( ++ expected_crealm=expected_crealm, ++ expected_cname=expected_cname, ++ expected_srealm=expected_srealm, ++ expected_sname=expected_sname, ++ expected_account_name=expected_account_name, ++ expected_upn_name=expected_upn_name, ++ expected_sid=expected_sid, ++ expected_supported_etypes=expected_supported_etypes, ++ ticket_decryption_key=target_decryption_key, ++ check_error_fn=check_error_fn, ++ check_rep_fn=check_rep_fn, ++ check_kdc_private_fn=self.generic_check_kdc_private, ++ expected_error_mode=expected_error_mode, ++ tgt=tgt, ++ authenticator_subkey=authenticator_subkey, ++ kdc_options=kdc_options, ++ pac_request=pac_request, ++ expect_pac=expect_pac, ++ expect_edata=False) ++ ++ rep = self._generic_kdc_exchange(kdc_exchange_dict, ++ cname=cname, ++ realm=realm, ++ sname=sname, ++ etypes=etypes) ++ if expect_error: ++ self.check_error_rep(rep, expected_error_mode) ++ ++ return None ++ else: ++ self.check_reply(rep, KRB_TGS_REP) ++ ++ return kdc_exchange_dict['rep_ticket_creds'] ++ + # Named tuple to contain values of interest when the PAC is decoded. + PacData = namedtuple( + "PacData", +diff --git a/python/samba/tests/krb5/kdc_tgs_tests.py b/python/samba/tests/krb5/kdc_tgs_tests.py +index 8cd27dec2aa..e52f46152fa 100755 +--- a/python/samba/tests/krb5/kdc_tgs_tests.py ++++ b/python/samba/tests/krb5/kdc_tgs_tests.py +@@ -230,82 +230,6 @@ class KdcTgsTests(KDCBaseTest): + pac_data.account_sid, + "rep = {%s},%s" % (rep, pac_data)) + +- def _make_tgs_request(self, client_creds, service_creds, tgt, +- pac_request=None, expect_pac=True, +- expect_error=False, +- expected_account_name=None, +- expected_upn_name=None, +- expected_sid=None): +- client_account = client_creds.get_username() +- cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[client_account]) +- +- service_account = service_creds.get_username() +- sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, +- names=[service_account]) +- +- realm = service_creds.get_realm() +- +- expected_crealm = realm +- expected_cname = cname +- expected_srealm = realm +- expected_sname = sname +- +- expected_supported_etypes = service_creds.tgs_supported_enctypes +- +- etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) +- +- kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) +- +- target_decryption_key = self.TicketDecryptionKey_from_creds( +- service_creds) +- +- authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) +- +- if expect_error: +- expected_error_mode = KDC_ERR_TGT_REVOKED +- check_error_fn = self.generic_check_kdc_error +- check_rep_fn = None +- else: +- expected_error_mode = 0 +- check_error_fn = None +- check_rep_fn = self.generic_check_kdc_rep +- +- kdc_exchange_dict = self.tgs_exchange_dict( +- expected_crealm=expected_crealm, +- expected_cname=expected_cname, +- expected_srealm=expected_srealm, +- expected_sname=expected_sname, +- expected_account_name=expected_account_name, +- expected_upn_name=expected_upn_name, +- expected_sid=expected_sid, +- expected_supported_etypes=expected_supported_etypes, +- ticket_decryption_key=target_decryption_key, +- check_error_fn=check_error_fn, +- check_rep_fn=check_rep_fn, +- check_kdc_private_fn=self.generic_check_kdc_private, +- expected_error_mode=expected_error_mode, +- tgt=tgt, +- authenticator_subkey=authenticator_subkey, +- kdc_options=kdc_options, +- pac_request=pac_request, +- expect_pac=expect_pac, +- expect_edata=False) +- +- rep = self._generic_kdc_exchange(kdc_exchange_dict, +- cname=cname, +- realm=realm, +- sname=sname, +- etypes=etypes) +- if expect_error: +- self.check_error_rep(rep, expected_error_mode) +- +- return None +- else: +- self.check_reply(rep, KRB_TGS_REP) +- +- return kdc_exchange_dict['rep_ticket_creds'] +- + def test_request(self): + client_creds = self.get_client_creds() + service_creds = self.get_service_creds() +-- +2.25.1 + + +From efb69ab420f2c5a3074fff6192fbc9a1cd387870 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:06:53 +1200 +Subject: [PATCH 61/99] CVE-2022-32744 tests/krb5: Correctly calculate salt for + pre-existing accounts + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 1 + + python/samba/tests/krb5/raw_testcase.py | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 2117663b26b..685a6f71f88 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -1048,6 +1048,7 @@ class KDCBaseTest(RawKerberosTest): + + kvno = int(res[0]['msDS-KeyVersionNumber'][0]) + creds.set_kvno(kvno) ++ creds.set_workstation(username[:-1]) + creds.set_dn(dn) + + keys = self.get_keys(samdb, dn) +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 4120edf93b9..a9a98c36cbf 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -834,6 +834,7 @@ class RawKerberosTest(TestCaseInTempDir): + allow_missing_password=allow_missing_password, + allow_missing_keys=allow_missing_keys) + c.set_gensec_features(c.get_gensec_features() | FEATURE_SEAL) ++ c.set_workstation('') + return c + + def get_rodc_krbtgt_creds(self, +-- +2.25.1 + + +From 3bbb7bc57f0de9dfe8fa979b7e122cafc4f9c139 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:13:54 +1200 +Subject: [PATCH 62/99] CVE-2022-2031 tests/krb5: Add new definitions for + kpasswd + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/rfc4120.asn1 | 6 ++++++ + python/samba/tests/krb5/rfc4120_constants.py | 13 +++++++++++++ + python/samba/tests/krb5/rfc4120_pyasn1.py | 13 ++++++++++++- + 3 files changed, 31 insertions(+), 1 deletion(-) + +diff --git a/python/samba/tests/krb5/rfc4120.asn1 b/python/samba/tests/krb5/rfc4120.asn1 +index e0831e1f86f..cac884be985 100644 +--- a/python/samba/tests/krb5/rfc4120.asn1 ++++ b/python/samba/tests/krb5/rfc4120.asn1 +@@ -567,6 +567,12 @@ PA-FX-FAST-REPLY ::= CHOICE { + ... + } + ++ChangePasswdDataMS ::= SEQUENCE { ++ newpasswd [0] OCTET STRING, ++ targname [1] PrincipalName OPTIONAL, ++ targrealm [2] Realm OPTIONAL ++} ++ + -- MS-KILE End + -- + -- +diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py +index a9fdc5735dd..7f0f44500c7 100644 +--- a/python/samba/tests/krb5/rfc4120_constants.py ++++ b/python/samba/tests/krb5/rfc4120_constants.py +@@ -27,11 +27,13 @@ ARCFOUR_HMAC_MD5 = int( + + # Message types + KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error')) ++KRB_AP_REP = int(krb5_asn1.MessageTypeValues('krb-ap-rep')) + KRB_AP_REQ = int(krb5_asn1.MessageTypeValues('krb-ap-req')) + KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep')) + KRB_AS_REQ = int(krb5_asn1.MessageTypeValues('krb-as-req')) + KRB_TGS_REP = int(krb5_asn1.MessageTypeValues('krb-tgs-rep')) + KRB_TGS_REQ = int(krb5_asn1.MessageTypeValues('krb-tgs-req')) ++KRB_PRIV = int(krb5_asn1.MessageTypeValues('krb-priv')) + + # PAData types + PADATA_ENC_TIMESTAMP = int( +@@ -76,6 +78,7 @@ KDC_ERR_TGT_REVOKED = 20 + KDC_ERR_PREAUTH_FAILED = 24 + KDC_ERR_PREAUTH_REQUIRED = 25 + KDC_ERR_BAD_INTEGRITY = 31 ++KDC_ERR_TKT_EXPIRED = 32 + KRB_ERR_TKT_NYV = 33 + KDC_ERR_NOT_US = 35 + KDC_ERR_BADMATCH = 36 +@@ -87,6 +90,16 @@ KDC_ERR_WRONG_REALM = 68 + KDC_ERR_CLIENT_NAME_MISMATCH = 75 + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93 + ++# Kpasswd error codes ++KPASSWD_SUCCESS = 0 ++KPASSWD_MALFORMED = 1 ++KPASSWD_HARDERROR = 2 ++KPASSWD_AUTHERROR = 3 ++KPASSWD_SOFTERROR = 4 ++KPASSWD_ACCESSDENIED = 5 ++KPASSWD_BAD_VERSION = 6 ++KPASSWD_INITIAL_FLAG_NEEDED = 7 ++ + # Extended error types + KERB_AP_ERR_TYPE_SKEW_RECOVERY = int( + krb5_asn1.KerbErrorDataTypeValues('kERB-AP-ERR-TYPE-SKEW-RECOVERY')) +diff --git a/python/samba/tests/krb5/rfc4120_pyasn1.py b/python/samba/tests/krb5/rfc4120_pyasn1.py +index 348dd8c63fb..3c02b0efbc1 100644 +--- a/python/samba/tests/krb5/rfc4120_pyasn1.py ++++ b/python/samba/tests/krb5/rfc4120_pyasn1.py +@@ -1,5 +1,5 @@ + # Auto-generated by asn1ate v.0.6.1.dev0 from rfc4120.asn1 +-# (last modified on 2021-06-25 12:10:34.484667) ++# (last modified on 2022-05-13 20:03:06.039817) + + # KerberosV5Spec2 + from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful +@@ -364,6 +364,17 @@ Authenticator.componentType = namedtype.NamedTypes( + ) + + ++class ChangePasswdDataMS(univ.Sequence): ++ pass ++ ++ ++ChangePasswdDataMS.componentType = namedtype.NamedTypes( ++ namedtype.NamedType('newpasswd', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))), ++ namedtype.OptionalNamedType('targname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), ++ namedtype.OptionalNamedType('targrealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2))) ++) ++ ++ + class ChecksumTypeValues(univ.Integer): + pass + +-- +2.25.1 + + +From 39db18962f5368957293cf678e4e7249a8b81ca8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:17:45 +1200 +Subject: [PATCH 63/99] CVE-2022-2031 tests/krb5: Add methods to create ASN1 + kpasswd structures + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 95 +++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index a9a98c36cbf..df41dff688d 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -54,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_AS_REP, + KRB_AS_REQ, + KRB_ERROR, ++ KRB_PRIV, + KRB_TGS_REP, + KRB_TGS_REQ, + KU_AP_REQ_AUTH, +@@ -63,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KU_FAST_FINISHED, + KU_FAST_REP, + KU_FAST_REQ_CHKSUM, ++ KU_KRB_PRIV, + KU_NON_KERB_CKSUM_SALT, + KU_TGS_REP_ENC_PART_SESSION, + KU_TGS_REP_ENC_PART_SUB_KEY, +@@ -1780,6 +1782,99 @@ class RawKerberosTest(TestCaseInTempDir): + PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self()) + return self.PA_DATA_create(PADATA_FOR_USER, pa_s4u2self) + ++ def ChangePasswdDataMS_create(self, ++ new_password, ++ target_princ=None, ++ target_realm=None): ++ ChangePasswdDataMS_obj = { ++ 'newpasswd': new_password, ++ } ++ if target_princ is not None: ++ ChangePasswdDataMS_obj['targname'] = target_princ ++ if target_realm is not None: ++ ChangePasswdDataMS_obj['targrealm'] = target_realm ++ ++ change_password_data = self.der_encode( ++ ChangePasswdDataMS_obj, asn1Spec=krb5_asn1.ChangePasswdDataMS()) ++ ++ return change_password_data ++ ++ def KRB_PRIV_create(self, ++ subkey, ++ user_data, ++ s_address, ++ timestamp=None, ++ usec=None, ++ seq_number=None, ++ r_address=None): ++ EncKrbPrivPart_obj = { ++ 'user-data': user_data, ++ 's-address': s_address, ++ } ++ if timestamp is not None: ++ EncKrbPrivPart_obj['timestamp'] = timestamp ++ if usec is not None: ++ EncKrbPrivPart_obj['usec'] = usec ++ if seq_number is not None: ++ EncKrbPrivPart_obj['seq-number'] = seq_number ++ if r_address is not None: ++ EncKrbPrivPart_obj['r-address'] = r_address ++ ++ enc_krb_priv_part = self.der_encode( ++ EncKrbPrivPart_obj, asn1Spec=krb5_asn1.EncKrbPrivPart()) ++ ++ enc_data = self.EncryptedData_create(subkey, ++ KU_KRB_PRIV, ++ enc_krb_priv_part) ++ ++ KRB_PRIV_obj = { ++ 'pvno': 5, ++ 'msg-type': KRB_PRIV, ++ 'enc-part': enc_data, ++ } ++ ++ krb_priv = self.der_encode( ++ KRB_PRIV_obj, asn1Spec=krb5_asn1.KRB_PRIV()) ++ ++ return krb_priv ++ ++ def kpasswd_create(self, ++ subkey, ++ user_data, ++ version, ++ seq_number, ++ ap_req, ++ local_address, ++ remote_address): ++ self.assertIsNotNone(self.s, 'call self.connect() first') ++ ++ timestamp, usec = self.get_KerberosTimeWithUsec() ++ ++ krb_priv = self.KRB_PRIV_create(subkey, ++ user_data, ++ s_address=local_address, ++ timestamp=timestamp, ++ usec=usec, ++ seq_number=seq_number, ++ r_address=remote_address) ++ ++ size = 6 + len(ap_req) + len(krb_priv) ++ self.assertLess(size, 0x10000) ++ ++ msg = bytearray() ++ msg.append(size >> 8) ++ msg.append(size & 0xff) ++ msg.append(version >> 8) ++ msg.append(version & 0xff) ++ msg.append(len(ap_req) >> 8) ++ msg.append(len(ap_req) & 0xff) ++ # Note: for sets, there could be a little-endian four-byte length here. ++ ++ msg.extend(ap_req) ++ msg.extend(krb_priv) ++ ++ return msg ++ + def _generic_kdc_exchange(self, + kdc_exchange_dict, # required + cname=None, # optional +-- +2.25.1 + + +From 3852adddff6df4d9f6f4cc1add11b06c272d29ef Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:21:37 +1200 +Subject: [PATCH 64/99] CVE-2022-2031 tests/krb5: Add 'port' parameter to + connect() + +This allows us to use the kpasswd port, 464. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index df41dff688d..421143781ae 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -638,10 +638,11 @@ class RawKerberosTest(TestCaseInTempDir): + if self.do_hexdump: + sys.stderr.write("disconnect[%s]\n" % reason) + +- def _connect_tcp(self, host): +- tcp_port = 88 ++ def _connect_tcp(self, host, port=None): ++ if port is None: ++ port = 88 + try: +- self.a = socket.getaddrinfo(host, tcp_port, socket.AF_UNSPEC, ++ self.a = socket.getaddrinfo(host, port, socket.AF_UNSPEC, + socket.SOCK_STREAM, socket.SOL_TCP, + 0) + self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2]) +@@ -654,9 +655,9 @@ class RawKerberosTest(TestCaseInTempDir): + self.s.close() + raise + +- def connect(self, host): ++ def connect(self, host, port=None): + self.assertNotConnected() +- self._connect_tcp(host) ++ self._connect_tcp(host, port) + if self.do_hexdump: + sys.stderr.write("connected[%s]\n" % host) + +-- +2.25.1 + + +From b9e880b3d9cf5666947cae60adc0846385b04f54 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:20:28 +1200 +Subject: [PATCH 65/99] CVE-2022-2031 tests/krb5: Add methods to send and + receive generic messages + +This allows us to send and receive kpasswd messages, while avoiding the +existing logic for encoding and decoding other Kerberos message types. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/raw_testcase.py | 44 +++++++++++++++---------- + 1 file changed, 27 insertions(+), 17 deletions(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 421143781ae..2aed5530455 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -920,24 +920,28 @@ class RawKerberosTest(TestCaseInTempDir): + return blob + + def send_pdu(self, req, asn1_print=None, hexdump=None): ++ k5_pdu = self.der_encode( ++ req, native_decode=False, asn1_print=asn1_print, hexdump=False) ++ self.send_msg(k5_pdu, hexdump=hexdump) ++ ++ def send_msg(self, msg, hexdump=None): ++ header = struct.pack('>I', len(msg)) ++ req_pdu = header ++ req_pdu += msg ++ self.hex_dump("send_msg", header, hexdump=hexdump) ++ self.hex_dump("send_msg", msg, hexdump=hexdump) ++ + try: +- k5_pdu = self.der_encode( +- req, native_decode=False, asn1_print=asn1_print, hexdump=False) +- header = struct.pack('>I', len(k5_pdu)) +- req_pdu = header +- req_pdu += k5_pdu +- self.hex_dump("send_pdu", header, hexdump=hexdump) +- self.hex_dump("send_pdu", k5_pdu, hexdump=hexdump) + while True: + sent = self.s.send(req_pdu, 0) + if sent == len(req_pdu): +- break ++ return + req_pdu = req_pdu[sent:] + except socket.error as e: +- self._disconnect("send_pdu: %s" % e) ++ self._disconnect("send_msg: %s" % e) + raise + except IOError as e: +- self._disconnect("send_pdu: %s" % e) ++ self._disconnect("send_msg: %s" % e) + raise + + def recv_raw(self, num_recv=0xffff, hexdump=None, timeout=None): +@@ -963,16 +967,14 @@ class RawKerberosTest(TestCaseInTempDir): + return rep_pdu + + def recv_pdu_raw(self, asn1_print=None, hexdump=None, timeout=None): +- rep_pdu = None +- rep = None + raw_pdu = self.recv_raw( + num_recv=4, hexdump=hexdump, timeout=timeout) + if raw_pdu is None: +- return (None, None) ++ return None + header = struct.unpack(">I", raw_pdu[0:4]) + k5_len = header[0] + if k5_len == 0: +- return (None, "") ++ return "" + missing = k5_len + rep_pdu = b'' + while missing > 0: +@@ -981,6 +983,14 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertGreaterEqual(len(raw_pdu), 1) + rep_pdu += raw_pdu + missing = k5_len - len(rep_pdu) ++ return rep_pdu ++ ++ def recv_reply(self, asn1_print=None, hexdump=None, timeout=None): ++ rep_pdu = self.recv_pdu_raw(asn1_print=asn1_print, ++ hexdump=hexdump, ++ timeout=timeout) ++ if not rep_pdu: ++ return None, rep_pdu + k5_raw = self.der_decode( + rep_pdu, + asn1Spec=None, +@@ -1002,9 +1012,9 @@ class RawKerberosTest(TestCaseInTempDir): + return (rep, rep_pdu) + + def recv_pdu(self, asn1_print=None, hexdump=None, timeout=None): +- (rep, rep_pdu) = self.recv_pdu_raw(asn1_print=asn1_print, +- hexdump=hexdump, +- timeout=timeout) ++ (rep, rep_pdu) = self.recv_reply(asn1_print=asn1_print, ++ hexdump=hexdump, ++ timeout=timeout) + return rep + + def assertIsConnected(self): +-- +2.25.1 + + +From 57edd8e2e043bd226c91ab0791297c1d98549ff1 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:26:56 +1200 +Subject: [PATCH 66/99] tests/krb5: Fix enum typo + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 685a6f71f88..14f1d1a243d 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -248,9 +248,9 @@ class KDCBaseTest(RawKerberosTest): + which is used by tearDownClass to clean up the created accounts. + ''' + if ou is None: +- if account_type is account_type.COMPUTER: ++ if account_type is self.AccountType.COMPUTER: + guid = DS_GUID_COMPUTERS_CONTAINER +- elif account_type is account_type.SERVER: ++ elif account_type is self.AccountType.SERVER: + guid = DS_GUID_DOMAIN_CONTROLLERS_CONTAINER + else: + guid = DS_GUID_USERS_CONTAINER +-- +2.25.1 + + +From e44b70b862e93fb9a8139a7188ed7021d705d223 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:30:12 +1200 +Subject: [PATCH 67/99] tests/krb5: Add option for creating accounts with + expired passwords + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + python/samba/tests/krb5/kdc_base_test.py | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 14f1d1a243d..777b3b4aaf1 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -242,7 +242,8 @@ class KDCBaseTest(RawKerberosTest): + + def create_account(self, samdb, name, account_type=AccountType.USER, + spn=None, upn=None, additional_details=None, +- ou=None, account_control=0, add_dollar=True): ++ ou=None, account_control=0, add_dollar=True, ++ expired_password=False): + '''Create an account for testing. + The dn of the created account is added to self.accounts, + which is used by tearDownClass to clean up the created accounts. +@@ -294,6 +295,8 @@ class KDCBaseTest(RawKerberosTest): + details["servicePrincipalName"] = spn + if upn is not None: + details["userPrincipalName"] = upn ++ if expired_password: ++ details["pwdLastSet"] = "0" + if additional_details is not None: + details.update(additional_details) + samdb.add(details) +@@ -653,6 +656,7 @@ class KDCBaseTest(RawKerberosTest): + 'revealed_to_rodc': False, + 'revealed_to_mock_rodc': False, + 'no_auth_data_required': False, ++ 'expired_password': False, + 'supported_enctypes': None, + 'not_delegated': False, + 'delegation_to_spn': None, +@@ -695,6 +699,7 @@ class KDCBaseTest(RawKerberosTest): + revealed_to_rodc, + revealed_to_mock_rodc, + no_auth_data_required, ++ expired_password, + supported_enctypes, + not_delegated, + delegation_to_spn, +@@ -754,7 +759,8 @@ class KDCBaseTest(RawKerberosTest): + spn=spn, + additional_details=details, + account_control=user_account_control, +- add_dollar=add_dollar) ++ add_dollar=add_dollar, ++ expired_password=expired_password) + + keys = self.get_keys(samdb, dn) + self.creds_set_keys(creds, keys) +-- +2.25.1 + + +From 2815de0510e222bc93f5b602b2cdd5c51f8adeb4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:34:59 +1200 +Subject: [PATCH 68/99] CVE-2022-2031 tests/krb5: Allow requesting a TGT to a + different sname and realm + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflict due to lacking rc4_support parameter] + +[jsutton@samba.org Fixed conflicts due to lacking client_name_type and + expected_cname parameters] +--- + python/samba/tests/krb5/kdc_base_test.py | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index 777b3b4aaf1..c0ca881985a 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -1344,10 +1344,12 @@ class KDCBaseTest(RawKerberosTest): + expected_flags=None, unexpected_flags=None, + pac_request=True, expect_pac=True, fresh=False): + user_name = tgt.cname['name-string'][0] ++ ticket_sname = tgt.sname + if target_name is None: + target_name = target_creds.get_username()[:-1] + cache_key = (user_name, target_name, service, to_rodc, kdc_options, + pac_request, str(expected_flags), str(unexpected_flags), ++ str(ticket_sname), + expect_pac) + + if not fresh: +@@ -1414,6 +1416,7 @@ class KDCBaseTest(RawKerberosTest): + expected_flags=None, unexpected_flags=None, + expected_account_name=None, expected_upn_name=None, + expected_sid=None, ++ sname=None, realm=None, + pac_request=True, expect_pac=True, + expect_pac_attrs=None, expect_pac_attrs_pac_request=None, + expect_requester_sid=None, +@@ -1422,6 +1425,7 @@ class KDCBaseTest(RawKerberosTest): + cache_key = (user_name, to_rodc, kdc_options, pac_request, + str(expected_flags), str(unexpected_flags), + expected_account_name, expected_upn_name, expected_sid, ++ str(sname), str(realm), + expect_pac, expect_pac_attrs, + expect_pac_attrs_pac_request, expect_requester_sid) + +@@ -1431,15 +1435,21 @@ class KDCBaseTest(RawKerberosTest): + if tgt is not None: + return tgt + +- realm = creds.get_realm() ++ if realm is None: ++ realm = creds.get_realm() + + salt = creds.get_salt() + + etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[user_name]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=['krbtgt', realm]) ++ if sname is None: ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ expected_sname = self.PrincipalName_create( ++ name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) ++ else: ++ expected_sname = sname + + till = self.get_KerberosTime(offset=36000) + +@@ -1505,9 +1515,6 @@ class KDCBaseTest(RawKerberosTest): + + expected_realm = realm.upper() + +- expected_sname = self.PrincipalName_create( +- name_type=NT_SRV_INST, names=['krbtgt', realm.upper()]) +- + rep, kdc_exchange_dict = self._test_as_exchange( + cname=cname, + realm=realm, +-- +2.25.1 + + +From e56d66f729ba1713e59b2fb938cc09e69831ac0e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:57:57 +1200 +Subject: [PATCH 69/99] CVE-2022-2031 tests/krb5: Add kpasswd_exchange() method + +Now we can test the kpasswd service from Python. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts in imports] +--- + python/samba/tests/krb5/raw_testcase.py | 264 ++++++++++++++++++++++-- + 1 file changed, 251 insertions(+), 13 deletions(-) + +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 2aed5530455..57010ae73bd 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -26,6 +26,8 @@ import binascii + import itertools + import collections + ++from enum import Enum ++ + from pyasn1.codec.der.decoder import decode as pyasn1_der_decode + from pyasn1.codec.der.encoder import encode as pyasn1_der_encode + from pyasn1.codec.native.decoder import decode as pyasn1_native_decode +@@ -33,6 +35,8 @@ from pyasn1.codec.native.encoder import encode as pyasn1_native_encode + + from pyasn1.codec.ber.encoder import BitStringEncoder + ++from pyasn1.error import PyAsn1Error ++ + from samba.credentials import Credentials + from samba.dcerpc import krb5pac, security + from samba.gensec import FEATURE_SEAL +@@ -50,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_PREAUTH_FAILED, + KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, + KERB_ERR_TYPE_EXTENDED, ++ KRB_AP_REP, + KRB_AP_REQ, + KRB_AS_REP, + KRB_AS_REQ, +@@ -59,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KRB_TGS_REQ, + KU_AP_REQ_AUTH, + KU_AS_REP_ENC_PART, ++ KU_AP_REQ_ENC_PART, + KU_ENC_CHALLENGE_KDC, + KU_FAST_ENC, + KU_FAST_FINISHED, +@@ -73,6 +79,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KU_TGS_REQ_AUTH_DAT_SESSION, + KU_TGS_REQ_AUTH_DAT_SUBKEY, + KU_TICKET, ++ NT_PRINCIPAL, + NT_SRV_INST, + NT_WELLKNOWN, + PADATA_ENCRYPTED_CHALLENGE, +@@ -515,6 +522,10 @@ class KerberosTicketCreds: + class RawKerberosTest(TestCaseInTempDir): + """A raw Kerberos Test case.""" + ++ class KpasswdMode(Enum): ++ SET = object() ++ CHANGE = object() ++ + pac_checksum_types = {krb5pac.PAC_TYPE_SRV_CHECKSUM, + krb5pac.PAC_TYPE_KDC_CHECKSUM, + krb5pac.PAC_TYPE_TICKET_CHECKSUM} +@@ -1886,6 +1897,224 @@ class RawKerberosTest(TestCaseInTempDir): + + return msg + ++ def get_enc_part(self, obj, key, usage): ++ self.assertElementEqual(obj, 'pvno', 5) ++ ++ enc_part = obj['enc-part'] ++ self.assertElementEqual(enc_part, 'etype', key.etype) ++ self.assertElementKVNO(enc_part, 'kvno', key.kvno) ++ ++ enc_part = key.decrypt(usage, enc_part['cipher']) ++ ++ return enc_part ++ ++ def kpasswd_exchange(self, ++ ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode, ++ target_princ=None, ++ target_realm=None, ++ ap_options=None, ++ send_seq_number=True): ++ if mode is self.KpasswdMode.SET: ++ version = 0xff80 ++ user_data = self.ChangePasswdDataMS_create(new_password, ++ target_princ, ++ target_realm) ++ elif mode is self.KpasswdMode.CHANGE: ++ self.assertIsNone(target_princ, ++ 'target_princ only valid for pw set') ++ self.assertIsNone(target_realm, ++ 'target_realm only valid for pw set') ++ ++ version = 1 ++ user_data = new_password.encode('utf-8') ++ else: ++ self.fail(f'invalid mode {mode}') ++ ++ subkey = self.RandomKey(kcrypto.Enctype.AES256) ++ ++ if ap_options is None: ++ ap_options = '0' ++ ap_options = str(krb5_asn1.APOptions(ap_options)) ++ ++ kdc_exchange_dict = { ++ 'tgt': ticket, ++ 'authenticator_subkey': subkey, ++ 'auth_data': None, ++ 'ap_options': ap_options, ++ } ++ ++ if send_seq_number: ++ seq_number = random.randint(0, 0xfffffffe) ++ else: ++ seq_number = None ++ ++ ap_req = self.generate_ap_req(kdc_exchange_dict, ++ None, ++ req_body=None, ++ armor=False, ++ usage=KU_AP_REQ_AUTH, ++ seq_number=seq_number) ++ ++ self.connect(self.host, port=464) ++ self.assertIsNotNone(self.s) ++ ++ family = self.s.family ++ ++ if family == socket.AF_INET: ++ addr_type = 2 # IPv4 ++ elif family == socket.AF_INET6: ++ addr_type = 24 # IPv6 ++ else: ++ self.fail(f'unknown family {family}') ++ ++ def create_address(ip): ++ return { ++ 'addr-type': addr_type, ++ 'address': socket.inet_pton(family, ip), ++ } ++ ++ local_ip = self.s.getsockname()[0] ++ local_address = create_address(local_ip) ++ ++ # remote_ip = self.s.getpeername()[0] ++ # remote_address = create_address(remote_ip) ++ ++ # TODO: due to a bug (?), MIT Kerberos will not accept the request ++ # unless r-address is set to our _local_ address. Heimdal, on the other ++ # hand, requires the r-address is set to the remote address (as ++ # expected). To avoid problems, avoid sending r-address for now. ++ remote_address = None ++ ++ msg = self.kpasswd_create(subkey, ++ user_data, ++ version, ++ seq_number, ++ ap_req, ++ local_address, ++ remote_address) ++ ++ self.send_msg(msg) ++ rep_pdu = self.recv_pdu_raw() ++ ++ self._disconnect('transaction done') ++ ++ self.assertIsNotNone(rep_pdu) ++ ++ header = rep_pdu[:6] ++ reply = rep_pdu[6:] ++ ++ reply_len = (header[0] << 8) | header[1] ++ reply_version = (header[2] << 8) | header[3] ++ ap_rep_len = (header[4] << 8) | header[5] ++ ++ self.assertEqual(reply_len, len(rep_pdu)) ++ self.assertEqual(1, reply_version) # KRB5_KPASSWD_VERS_CHANGEPW ++ self.assertLess(ap_rep_len, reply_len) ++ ++ self.assertNotEqual(0x7e, rep_pdu[1]) ++ self.assertNotEqual(0x5e, rep_pdu[1]) ++ ++ if ap_rep_len: ++ # We received an AP-REQ and KRB-PRIV as a response. This may or may ++ # not indicate an error, depending on the status code. ++ ap_rep = reply[:ap_rep_len] ++ krb_priv = reply[ap_rep_len:] ++ ++ key = ticket.session_key ++ ++ ap_rep = self.der_decode(ap_rep, asn1Spec=krb5_asn1.AP_REP()) ++ self.assertElementEqual(ap_rep, 'msg-type', KRB_AP_REP) ++ enc_part = self.get_enc_part(ap_rep, key, KU_AP_REQ_ENC_PART) ++ enc_part = self.der_decode( ++ enc_part, asn1Spec=krb5_asn1.EncAPRepPart()) ++ ++ self.assertElementPresent(enc_part, 'ctime') ++ self.assertElementPresent(enc_part, 'cusec') ++ # self.assertElementMissing(enc_part, 'subkey') # TODO ++ # self.assertElementPresent(enc_part, 'seq-number') # TODO ++ ++ try: ++ krb_priv = self.der_decode(krb_priv, asn1Spec=krb5_asn1.KRB_PRIV()) ++ except PyAsn1Error: ++ self.fail() ++ ++ self.assertElementEqual(krb_priv, 'msg-type', KRB_PRIV) ++ priv_enc_part = self.get_enc_part(krb_priv, subkey, KU_KRB_PRIV) ++ priv_enc_part = self.der_decode( ++ priv_enc_part, asn1Spec=krb5_asn1.EncKrbPrivPart()) ++ ++ self.assertElementMissing(priv_enc_part, 'timestamp') ++ self.assertElementMissing(priv_enc_part, 'usec') ++ # self.assertElementPresent(priv_enc_part, 'seq-number') # TODO ++ # self.assertElementEqual(priv_enc_part, 's-address', remote_address) # TODO ++ # self.assertElementMissing(priv_enc_part, 'r-address') # TODO ++ ++ result_data = priv_enc_part['user-data'] ++ else: ++ # We received a KRB-ERROR as a response, indicating an error. ++ krb_error = self.der_decode(reply, asn1Spec=krb5_asn1.KRB_ERROR()) ++ ++ sname = self.PrincipalName_create( ++ name_type=NT_PRINCIPAL, ++ names=['kadmin', 'changepw']) ++ realm = self.get_krbtgt_creds().get_realm().upper() ++ ++ self.assertElementEqual(krb_error, 'pvno', 5) ++ self.assertElementEqual(krb_error, 'msg-type', KRB_ERROR) ++ self.assertElementMissing(krb_error, 'ctime') ++ self.assertElementMissing(krb_error, 'usec') ++ self.assertElementPresent(krb_error, 'stime') ++ self.assertElementPresent(krb_error, 'susec') ++ ++ error_code = krb_error['error-code'] ++ if isinstance(expected_code, int): ++ self.assertEqual(error_code, expected_code) ++ else: ++ self.assertIn(error_code, expected_code) ++ ++ self.assertElementMissing(krb_error, 'crealm') ++ self.assertElementMissing(krb_error, 'cname') ++ self.assertElementEqual(krb_error, 'realm', realm.encode('utf-8')) ++ self.assertElementEqualPrincipal(krb_error, 'sname', sname) ++ self.assertElementMissing(krb_error, 'e-text') ++ ++ result_data = krb_error['e-data'] ++ ++ status = result_data[:2] ++ message = result_data[2:] ++ ++ status_code = (status[0] << 8) | status[1] ++ if isinstance(expected_code, int): ++ self.assertEqual(status_code, expected_code) ++ else: ++ self.assertIn(status_code, expected_code) ++ ++ if not message: ++ self.assertEqual(0, status_code, ++ 'got an error result, but no message') ++ return ++ ++ # Check the first character of the message. ++ if message[0]: ++ if isinstance(expected_msg, bytes): ++ self.assertEqual(message, expected_msg) ++ else: ++ self.assertIn(message, expected_msg) ++ else: ++ # We got AD password policy information. ++ self.assertEqual(30, len(message)) ++ ++ (empty_bytes, ++ min_length, ++ history_length, ++ properties, ++ expire_time, ++ min_age) = struct.unpack('>HIIIQQ', message) ++ + def _generic_kdc_exchange(self, + kdc_exchange_dict, # required + cname=None, # optional +@@ -1996,7 +2225,7 @@ class RawKerberosTest(TestCaseInTempDir): + self.assertIsNotNone(generate_fast_fn) + fast_ap_req = generate_fast_armor_fn(kdc_exchange_dict, + callback_dict, +- req_body, ++ None, + armor=True) + + fast_armor_type = kdc_exchange_dict['fast_armor_type'] +@@ -3211,31 +3440,39 @@ class RawKerberosTest(TestCaseInTempDir): + kdc_exchange_dict, + _callback_dict, + req_body, +- armor): ++ armor, ++ usage=None, ++ seq_number=None): ++ req_body_checksum = None ++ + if armor: ++ self.assertIsNone(req_body) ++ + tgt = kdc_exchange_dict['armor_tgt'] + authenticator_subkey = kdc_exchange_dict['armor_subkey'] +- +- req_body_checksum = None + else: + tgt = kdc_exchange_dict['tgt'] + authenticator_subkey = kdc_exchange_dict['authenticator_subkey'] +- body_checksum_type = kdc_exchange_dict['body_checksum_type'] + +- req_body_blob = self.der_encode(req_body, +- asn1Spec=krb5_asn1.KDC_REQ_BODY()) ++ if req_body is not None: ++ body_checksum_type = kdc_exchange_dict['body_checksum_type'] ++ ++ req_body_blob = self.der_encode( ++ req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY()) + +- req_body_checksum = self.Checksum_create(tgt.session_key, +- KU_TGS_REQ_AUTH_CKSUM, +- req_body_blob, +- ctype=body_checksum_type) ++ req_body_checksum = self.Checksum_create( ++ tgt.session_key, ++ KU_TGS_REQ_AUTH_CKSUM, ++ req_body_blob, ++ ctype=body_checksum_type) + + auth_data = kdc_exchange_dict['auth_data'] + + subkey_obj = None + if authenticator_subkey is not None: + subkey_obj = authenticator_subkey.export_obj() +- seq_number = random.randint(0, 0xfffffffe) ++ if seq_number is None: ++ seq_number = random.randint(0, 0xfffffffe) + (ctime, cusec) = self.get_KerberosTimeWithUsec() + authenticator_obj = self.Authenticator_create( + crealm=tgt.crealm, +@@ -3250,7 +3487,8 @@ class RawKerberosTest(TestCaseInTempDir): + authenticator_obj, + asn1Spec=krb5_asn1.Authenticator()) + +- usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH ++ if usage is None: ++ usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH + authenticator = self.EncryptedData_create(tgt.session_key, + usage, + authenticator_blob) +-- +2.25.1 + + +From b2c3b060baedf638d7b8ee7f3b2bc1c7f9b695ac Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:35:03 +1200 +Subject: [PATCH 70/99] CVE-2022-32744 selftest: Specify Administrator kvno for + Python krb5 tests + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/selftest/tests.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index dc340623f3e..c5fdf7fe294 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -912,6 +912,7 @@ krb5_environ = { + 'SERVICE_USERNAME': '$SERVER', + 'ADMIN_USERNAME': '$DC_USERNAME', + 'ADMIN_PASSWORD': '$DC_PASSWORD', ++ 'ADMIN_KVNO': '1', + 'FOR_USER': '$DC_USERNAME', + 'STRICT_CHECKING':'0', + 'FAST_SUPPORT': have_fast_support, +-- +2.25.1 + + +From 6fc3d93b4fe81be8e8f134c46d461d5815edda91 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 19:59:16 +1200 +Subject: [PATCH 71/99] CVE-2022-2031 tests/krb5: Add tests for kpasswd service + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts in usage.py and knownfails; removed + MIT KDC 1.20-specific knownfails as it's not supported] + +[jsutton@samba.org Fixed conflicts in usage.py, knownfails, and + tests.py] +--- + python/samba/tests/krb5/kdc_base_test.py | 4 +- + python/samba/tests/krb5/kpasswd_tests.py | 1021 ++++++++++++++++++++++ + python/samba/tests/krb5/raw_testcase.py | 8 + + python/samba/tests/usage.py | 1 + + selftest/knownfail_heimdal_kdc | 26 + + selftest/knownfail_mit_kdc | 26 + + source4/selftest/tests.py | 4 + + 7 files changed, 1089 insertions(+), 1 deletion(-) + create mode 100755 python/samba/tests/krb5/kpasswd_tests.py + +diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py +index c0ca881985a..f0306dde110 100644 +--- a/python/samba/tests/krb5/kdc_base_test.py ++++ b/python/samba/tests/krb5/kdc_base_test.py +@@ -1586,7 +1586,9 @@ class KDCBaseTest(RawKerberosTest): + authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256) + + if expect_error: +- expected_error_mode = KDC_ERR_TGT_REVOKED ++ expected_error_mode = expect_error ++ if expected_error_mode is True: ++ expected_error_mode = KDC_ERR_TGT_REVOKED + check_error_fn = self.generic_check_kdc_error + check_rep_fn = None + else: +diff --git a/python/samba/tests/krb5/kpasswd_tests.py b/python/samba/tests/krb5/kpasswd_tests.py +new file mode 100755 +index 00000000000..3a6c7d818dc +--- /dev/null ++++ b/python/samba/tests/krb5/kpasswd_tests.py +@@ -0,0 +1,1021 @@ ++#!/usr/bin/env python3 ++# Unix SMB/CIFS implementation. ++# Copyright (C) Stefan Metzmacher 2020 ++# Copyright (C) Catalyst.Net Ltd ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++import os ++import sys ++ ++from functools import partial ++ ++from samba import generate_random_password, unix2nttime ++from samba.dcerpc import krb5pac, security ++from samba.sd_utils import SDUtils ++ ++from samba.tests.krb5.kdc_base_test import KDCBaseTest ++from samba.tests.krb5.rfc4120_constants import ( ++ KDC_ERR_TGT_REVOKED, ++ KDC_ERR_TKT_EXPIRED, ++ KPASSWD_ACCESSDENIED, ++ KPASSWD_HARDERROR, ++ KPASSWD_INITIAL_FLAG_NEEDED, ++ KPASSWD_MALFORMED, ++ KPASSWD_SOFTERROR, ++ KPASSWD_SUCCESS, ++ NT_PRINCIPAL, ++ NT_SRV_INST, ++) ++ ++sys.path.insert(0, 'bin/python') ++os.environ['PYTHONUNBUFFERED'] = '1' ++ ++global_asn1_print = False ++global_hexdump = False ++ ++ ++# Note: these tests do not pass on Windows, which returns different error codes ++# to the ones we have chosen, and does not always return additional error data. ++class KpasswdTests(KDCBaseTest): ++ ++ def setUp(self): ++ super().setUp() ++ self.do_asn1_print = global_asn1_print ++ self.do_hexdump = global_hexdump ++ ++ samdb = self.get_samdb() ++ ++ # Get the old 'dSHeuristics' if it was set ++ dsheuristics = samdb.get_dsheuristics() ++ ++ # Reset the 'dSHeuristics' as they were before ++ self.addCleanup(samdb.set_dsheuristics, dsheuristics) ++ ++ # Set the 'dSHeuristics' to activate the correct 'userPassword' ++ # behaviour ++ samdb.set_dsheuristics('000000001') ++ ++ # Get the old 'minPwdAge' ++ minPwdAge = samdb.get_minPwdAge() ++ ++ # Reset the 'minPwdAge' as it was before ++ self.addCleanup(samdb.set_minPwdAge, minPwdAge) ++ ++ # Set it temporarily to '0' ++ samdb.set_minPwdAge('0') ++ ++ def _get_creds(self, expired=False): ++ opts = { ++ 'expired_password': expired ++ } ++ ++ # Create the account. ++ creds = self.get_cached_creds(account_type=self.AccountType.USER, ++ opts=opts, ++ use_cache=False) ++ ++ return creds ++ ++ def issued_by_rodc(self, ticket): ++ krbtgt_creds = self.get_mock_rodc_krbtgt_creds() ++ ++ krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, ++ } ++ ++ return self.modified_ticket( ++ ticket, ++ new_ticket_key=krbtgt_key, ++ checksum_keys=checksum_keys) ++ ++ def get_kpasswd_sname(self): ++ return self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=['kadmin', 'changepw']) ++ ++ def get_ticket_lifetime(self, ticket): ++ enc_part = ticket.ticket_private ++ ++ authtime = enc_part['authtime'] ++ starttime = enc_part.get('starttime', authtime) ++ endtime = enc_part['endtime'] ++ ++ starttime = self.get_EpochFromKerberosTime(starttime) ++ endtime = self.get_EpochFromKerberosTime(endtime) ++ ++ return endtime - starttime ++ ++ def add_requester_sid(self, pac, sid): ++ pac_buffers = pac.buffers ++ ++ buffer_types = [pac_buffer.type for pac_buffer in pac_buffers] ++ self.assertNotIn(krb5pac.PAC_TYPE_REQUESTER_SID, buffer_types) ++ ++ requester_sid = krb5pac.PAC_REQUESTER_SID() ++ requester_sid.sid = security.dom_sid(sid) ++ ++ requester_sid_buffer = krb5pac.PAC_BUFFER() ++ requester_sid_buffer.type = krb5pac.PAC_TYPE_REQUESTER_SID ++ requester_sid_buffer.info = requester_sid ++ ++ pac_buffers.append(requester_sid_buffer) ++ ++ pac.buffers = pac_buffers ++ pac.num_buffers += 1 ++ ++ return pac ++ ++ # Test setting a password with kpasswd. ++ def test_kpasswd_set(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Test the newly set password. ++ creds.update_password(new_password) ++ self.get_tgt(creds, fresh=True) ++ ++ # Test changing a password with kpasswd. ++ def test_kpasswd_change(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test the newly set password. ++ creds.update_password(new_password) ++ self.get_tgt(creds, fresh=True) ++ ++ # Test kpasswd without setting the canonicalize option. ++ def test_kpasswd_no_canonicalize(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option reset and a non-canonical ++ # (by conversion to title case) realm. ++ def test_kpasswd_no_canonicalize_realm_case(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ realm = creds.get_realm().capitalize() # We use a title-cased realm. ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='0') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option set. ++ def test_kpasswd_canonicalize(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='canonicalize') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='canonicalize') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd with the canonicalize option set and a non-canonical (by ++ # conversion to title case) realm. ++ def test_kpasswd_canonicalize_realm_case(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ realm = creds.get_realm().capitalize() # We use a title-cased realm. ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='canonicalize') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ++ # Get an initial ticket to kpasswd. We set the canonicalize flag here. ++ ticket = self.get_tgt(creds, sname=sname, ++ realm=realm, ++ kdc_options='canonicalize') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects a password that does not meet complexity ++ # requirements. ++ def test_kpasswd_too_weak(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SOFTERROR ++ expected_msg = b'Password does not meet complexity requirements' ++ ++ # Set the password. ++ new_password = 'password' ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects an empty new password. ++ def test_kpasswd_empty(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SOFTERROR, KPASSWD_HARDERROR ++ expected_msg = (b'Password too short, password must be at least 7 ' ++ b'characters long.', ++ b'String conversion failed!') ++ ++ # Set the password. ++ new_password = '' ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'String conversion failed!' ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test kpasswd rejects a request that does not include a random sequence ++ # number. ++ def test_kpasswd_no_seq_number(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_unwrap failed - NT_STATUS_ACCESS_DENIED\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ send_seq_number=False) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE, ++ send_seq_number=False) ++ ++ # Test kpasswd rejects a ticket issued by an RODC. ++ def test_kpasswd_from_rodc(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Have the ticket be issued by the RODC. ++ ticket = self.issued_by_rodc(ticket) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test setting a password, specifying the principal of the target user. ++ def test_kpasswd_set_target_princ_only(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_MALFORMED ++ expected_msg = (b'Realm and principal must be both present, or ' ++ b'neither present', ++ b'Failed to decode packet') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname) ++ ++ # Test that kpasswd rejects a password set specifying only the realm of the ++ # target user. ++ def test_kpasswd_set_target_realm_only(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_MALFORMED, KPASSWD_ACCESSDENIED ++ expected_msg = (b'Realm and principal must be both present, or ' ++ b'neither present', ++ b'Failed to decode packet', ++ b'No such user when changing password') ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_realm=creds.get_realm()) ++ ++ # Show that a user cannot set a password, specifying both principal and ++ # realm of the target user, without having control access. ++ def test_kpasswd_set_target_princ_and_realm_no_access(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_ACCESSDENIED ++ expected_msg = b'Not permitted to change password' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname, ++ target_realm=creds.get_realm()) ++ ++ # Test setting a password, specifying both principal and realm of the ++ # target user, whem the user has control access on their account. ++ def test_kpasswd_set_target_princ_and_realm_access(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ username = creds.get_username() ++ tgt = self.get_tgt(creds) ++ ++ cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ++ samdb = self.get_samdb() ++ sd_utils = SDUtils(samdb) ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Give the user control access on their account. ++ ace = f'(A;;CR;;;{user_sid})' ++ sd_utils.dacl_add_ace(user_dn, ace) ++ ++ # Get a non-initial ticket to kpasswd. Since we have the right to ++ # change the account's password, we don't need an initial ticket. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET, ++ target_princ=cname, ++ target_realm=creds.get_realm()) ++ ++ # Test setting a password when the existing password has expired. ++ def test_kpasswd_set_expired_password(self): ++ # Create an account for testing, with an expired password. ++ creds = self._get_creds(expired=True) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Test changing a password when the existing password has expired. ++ def test_kpasswd_change_expired_password(self): ++ # Create an account for testing, with an expired password. ++ creds = self._get_creds(expired=True) ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Check the lifetime of a kpasswd ticket is not more than two minutes. ++ def test_kpasswd_ticket_lifetime(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Check the lifetime of the ticket is equal to two minutes. ++ lifetime = self.get_ticket_lifetime(ticket) ++ self.assertEqual(2 * 60, lifetime) ++ ++ # Ensure we cannot perform a TGS-REQ with a kpasswd ticket. ++ def test_kpasswd_ticket_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This fails due to missing REQUESTER_SID buffer. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=(KDC_ERR_TGT_REVOKED, ++ KDC_ERR_TKT_EXPIRED)) ++ ++ def modify_requester_sid_time(self, ticket, sid, lifetime): ++ # Get the krbtgt key. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key, ++ } ++ ++ # Set authtime and starttime to an hour in the past, to show that they ++ # do not affect ticket rejection. ++ start_time = self.get_KerberosTime(offset=-60 * 60) ++ ++ # Set the endtime of the ticket relative to our current time, so that ++ # the ticket has 'lifetime' seconds remaining to live. ++ end_time = self.get_KerberosTime(offset=lifetime) ++ ++ # Modify the times in the ticket. ++ def modify_ticket_times(enc_part): ++ enc_part['authtime'] = start_time ++ if 'starttime' in enc_part: ++ enc_part['starttime'] = start_time ++ ++ enc_part['endtime'] = end_time ++ ++ return enc_part ++ ++ # We have to set the times in both the ticket and the PAC, otherwise ++ # Heimdal will complain. ++ def modify_pac_time(pac): ++ pac_buffers = pac.buffers ++ ++ for pac_buffer in pac_buffers: ++ if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME: ++ logon_time = self.get_EpochFromKerberosTime(start_time) ++ pac_buffer.info.logon_time = unix2nttime(logon_time) ++ break ++ else: ++ self.fail('failed to find LOGON_NAME PAC buffer') ++ ++ pac.buffers = pac_buffers ++ ++ return pac ++ ++ # Add a requester SID to show that the KDC will then accept this ++ # kpasswd ticket as if it were a TGT. ++ def modify_pac_fn(pac): ++ pac = self.add_requester_sid(pac, sid=sid) ++ pac = modify_pac_time(pac) ++ return pac ++ ++ # Do the actual modification. ++ return self.modified_ticket(ticket, ++ new_ticket_key=krbtgt_key, ++ modify_fn=modify_ticket_times, ++ modify_pac_fn=modify_pac_fn, ++ checksum_keys=checksum_keys) ++ ++ # Ensure we cannot perform a TGS-REQ with a kpasswd ticket containing a ++ # requester SID and having a remaining lifetime of two minutes. ++ def test_kpasswd_ticket_requester_sid_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Get the user's SID. ++ samdb = self.get_samdb() ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Modify the ticket to add a requester SID and give it two minutes to ++ # live. ++ ticket = self.modify_requester_sid_time(ticket, ++ sid=user_sid, ++ lifetime=2 * 60) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This fails due to the lifetime being too short. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=KDC_ERR_TKT_EXPIRED) ++ ++ # Show we can perform a TGS-REQ with a kpasswd ticket containing a ++ # requester SID if the remaining lifetime exceeds two minutes. ++ def test_kpasswd_ticket_requester_sid_lifetime_tgs(self): ++ creds = self.get_client_creds() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(), ++ kdc_options='0') ++ ++ # Change the sname of the ticket to match that of a TGT. ++ realm = creds.get_realm() ++ krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=['krbtgt', realm]) ++ ticket.set_sname(krbtgt_sname) ++ ++ # Get the user's SID. ++ samdb = self.get_samdb() ++ ++ user_dn = creds.get_dn() ++ user_sid = self.get_objectSid(samdb, user_dn) ++ ++ # Modify the ticket to add a requester SID and give it two minutes and ++ # ten seconds to live. ++ ticket = self.modify_requester_sid_time(ticket, ++ sid=user_sid, ++ lifetime=2 * 60 + 10) ++ ++ # Try to use that ticket to get a service ticket. ++ service_creds = self.get_service_creds() ++ ++ # This succeeds. ++ self._make_tgs_request(creds, service_creds, ticket, ++ expect_error=False) ++ ++ # Test that kpasswd rejects requests with a service ticket. ++ def test_kpasswd_non_initial(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds) ++ ++ # Get a non-initial ticket to kpasswd. ++ krbtgt_creds = self.get_krbtgt_creds() ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0') ++ ++ expected_code = KPASSWD_INITIAL_FLAG_NEEDED ++ expected_msg = b'Expected an initial ticket' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Show that kpasswd accepts requests with a service ticket modified to set ++ # the 'initial' flag. ++ def test_kpasswd_initial(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ # Get a service ticket, and modify it to set the 'initial' flag. ++ def get_ticket(): ++ tgt = self.get_tgt(creds, fresh=True) ++ ++ # Get a non-initial ticket to kpasswd. ++ ticket = self.get_service_ticket(tgt, ++ krbtgt_creds, ++ service='kadmin', ++ target_name='changepw', ++ kdc_options='0', ++ fresh=True) ++ ++ set_initial_flag = partial(self.modify_ticket_flag, flag='initial', ++ value=True) ++ ++ checksum_keys = self.get_krbtgt_checksum_key() ++ return self.modified_ticket(ticket, ++ modify_fn=set_initial_flag, ++ checksum_keys=checksum_keys) ++ ++ expected_code = KPASSWD_SUCCESS ++ expected_msg = b'Password changed' ++ ++ ticket = get_ticket() ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ creds.update_password(new_password) ++ ticket = get_ticket() ++ ++ # Change the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test that kpasswd rejects requests where the ticket is encrypted with a ++ # key other than the krbtgt's. ++ def test_kpasswd_wrong_key(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to the Administrator account. ++ admin_creds = self.get_admin_creds() ++ admin_key = self.TicketDecryptionKey_from_creds(admin_creds) ++ self.assertIsNotNone(admin_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: admin_key, ++ } ++ ++ # Re-encrypt the ticket using the Administrator's key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=admin_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of the Administrator account. ++ admin_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=['Administrator']) ++ ticket.set_sname(admin_sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ def test_kpasswd_wrong_key_service(self): ++ # Create an account for testing. ++ creds = self.get_cached_creds(account_type=self.AccountType.COMPUTER, ++ use_cache=False) ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to our account. ++ our_key = self.TicketDecryptionKey_from_creds(creds) ++ self.assertIsNotNone(our_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: our_key, ++ } ++ ++ # Re-encrypt the ticket using our key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=our_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of our account. ++ username = creds.get_username() ++ sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=username.split('/')) ++ ticket.set_sname(sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ # Test that kpasswd rejects requests where the ticket is encrypted with a ++ # key belonging to a server account other than the krbtgt. ++ def test_kpasswd_wrong_key_server(self): ++ # Create an account for testing. ++ creds = self._get_creds() ++ ++ sname = self.get_kpasswd_sname() ++ ++ # Get an initial ticket to kpasswd. ++ ticket = self.get_tgt(creds, sname=sname, ++ kdc_options='0') ++ ++ # Get a key belonging to the DC's account. ++ dc_creds = self.get_dc_creds() ++ dc_key = self.TicketDecryptionKey_from_creds(dc_creds) ++ self.assertIsNotNone(dc_key.kvno, ++ 'a kvno is required to tell the DB ' ++ 'which key to look up.') ++ checksum_keys = { ++ krb5pac.PAC_TYPE_KDC_CHECKSUM: dc_key, ++ } ++ ++ # Re-encrypt the ticket using the DC's key. ++ ticket = self.modified_ticket(ticket, ++ new_ticket_key=dc_key, ++ checksum_keys=checksum_keys) ++ ++ # Set the sname of the ticket to that of the DC's account. ++ dc_username = dc_creds.get_username() ++ dc_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL, ++ names=dc_username.split('/')) ++ ticket.set_sname(dc_sname) ++ ++ expected_code = KPASSWD_HARDERROR ++ expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(ticket, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ ++ ++if __name__ == '__main__': ++ global_asn1_print = False ++ global_hexdump = False ++ import unittest ++ unittest.main() +diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py +index 57010ae73bd..4a78a8eadf3 100644 +--- a/python/samba/tests/krb5/raw_testcase.py ++++ b/python/samba/tests/krb5/raw_testcase.py +@@ -500,6 +500,10 @@ class KerberosCredentials(Credentials): + def get_upn(self): + return self.upn + ++ def update_password(self, password): ++ self.set_password(password) ++ self.set_kvno(self.get_kvno() + 1) ++ + + class KerberosTicketCreds: + def __init__(self, ticket, session_key, +@@ -518,6 +522,10 @@ class KerberosTicketCreds: + self.ticket_private = ticket_private + self.encpart_private = encpart_private + ++ def set_sname(self, sname): ++ self.ticket['sname'] = sname ++ self.sname = sname ++ + + class RawKerberosTest(TestCaseInTempDir): + """A raw Kerberos Test case.""" +diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py +index 6bbd96e7a08..a1210ada579 100644 +--- a/python/samba/tests/usage.py ++++ b/python/samba/tests/usage.py +@@ -109,6 +109,7 @@ EXCLUDE_USAGE = { + 'python/samba/tests/krb5/alias_tests.py', + 'python/samba/tests/krb5/test_min_domain_uid.py', + 'python/samba/tests/krb5/test_idmap_nss.py', ++ 'python/samba/tests/krb5/kpasswd_tests.py', + } + + EXCLUDE_HELP = { +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 692b9ecdd72..9f2b855af4c 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -109,3 +109,29 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 095da10238c..c8187ba5db3 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -541,3 +541,29 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_nonexisting + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py +index c5fdf7fe294..102b17f5376 100755 +--- a/source4/selftest/tests.py ++++ b/source4/selftest/tests.py +@@ -1590,6 +1590,10 @@ planpythontestsuite( + "ad_dc", + "samba.tests.krb5.alias_tests", + environ=krb5_environ) ++planoldpythontestsuite( ++ 'ad_dc', ++ 'samba.tests.krb5.kpasswd_tests', ++ environ=krb5_environ) + + for env in [ + 'vampire_dc', +-- +2.25.1 + + +From 2ee46c16d2aa706b686b50ccb66a2a3ad9852c50 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:21:06 +1200 +Subject: [PATCH 72/99] CVE-2022-2031 s4:kpasswd: Correctly generate error + strings + +The error_data we create already has an explicit length, and should not +be zero-terminated, so we omit the trailing null byte. Previously, +Heimdal builds would leave a superfluous trailing null byte on error +strings, while MIT builds would omit the final character. + +The two bytes added to the string's length are for the prepended error +code. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_heimdal_kdc | 12 ------------ + selftest/knownfail_mit_kdc | 15 --------------- + source4/kdc/kpasswd-helper.c | 13 ++++++------- + 3 files changed, 6 insertions(+), 34 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 9f2b855af4c..5fd6e4aa0ed 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -114,24 +114,12 @@ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index c8187ba5db3..6c8d6e45cdd 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -544,26 +544,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + # Kpasswd tests + # +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/kdc/kpasswd-helper.c b/source4/kdc/kpasswd-helper.c +index 995f54825b5..55a2f5b3bf6 100644 +--- a/source4/kdc/kpasswd-helper.c ++++ b/source4/kdc/kpasswd-helper.c +@@ -48,17 +48,16 @@ bool kpasswd_make_error_reply(TALLOC_CTX *mem_ctx, + } + + /* +- * The string 's' has two terminating nul-bytes which are also +- * reflected by 'slen'. Normally Kerberos doesn't expect that strings +- * are nul-terminated, but Heimdal does! ++ * The string 's' has one terminating nul-byte which is also ++ * reflected by 'slen'. We subtract it from the length. + */ +-#ifndef SAMBA4_USES_HEIMDAL +- if (slen < 2) { ++ if (slen < 1) { + talloc_free(s); + return false; + } +- slen -= 2; +-#endif ++ slen--; ++ ++ /* Two bytes are added to the length to account for the error code. */ + if (2 + slen < slen) { + talloc_free(s); + return false; +-- +2.25.1 + + +From b1003099c202d05b7d3f570fe313039aebdec3f9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:48:59 +1200 +Subject: [PATCH 73/99] CVE-2022-2031 s4:kpasswd: Don't return AP-REP on + failure + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_mit_kdc | 1 - + source4/kdc/kpasswd-service.c | 2 ++ + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 6c8d6e45cdd..41a793ae082 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -545,7 +545,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index 061aedc80e5..22e1295c11e 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -256,6 +256,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &error_string); + if (code != 0) { ++ ap_rep_blob = data_blob_null; + error_code = code; + goto reply; + } +@@ -265,6 +266,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + &kpasswd_dec_reply, + &enc_data_blob); + if (!NT_STATUS_IS_OK(status)) { ++ ap_rep_blob = data_blob_null; + error_code = KRB5_KPASSWD_HARDERROR; + error_string = talloc_asprintf(tmp_ctx, + "gensec_wrap failed - %s\n", +-- +2.25.1 + + +From 38c83abffd325ee23649c190b8ffb3d27a2bdb68 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 27 May 2022 19:29:34 +1200 +Subject: [PATCH 74/99] CVE-2022-2031 lib:krb5_wrap: Generate valid error codes + in smb_krb5_mk_error() + +The error code passed in will be an offset from ERROR_TABLE_BASE_krb5, +so we need to subtract that before creating the error. Heimdal does this +internally, so it isn't needed there. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + lib/krb5_wrap/krb5_samba.c | 2 +- + selftest/knownfail_mit_kdc | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c +index 76c2dcd2126..610efcc9b87 100644 +--- a/lib/krb5_wrap/krb5_samba.c ++++ b/lib/krb5_wrap/krb5_samba.c +@@ -237,7 +237,7 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, + return code; + } + +- errpkt.error = error_code; ++ errpkt.error = error_code - ERROR_TABLE_BASE_krb5; + + errpkt.text.length = 0; + if (e_text != NULL) { +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 41a793ae082..e4300b4d20e 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -545,9 +545,13 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-- +2.25.1 + + +From 481a70c37464d356f60a30c5f51ffae755c4e6f0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:49:43 +1200 +Subject: [PATCH 75/99] CVE-2022-2031 s4:kpasswd: Return a kpasswd error code + in KRB-ERROR + +If we attempt to return an error code outside of Heimdal's allowed range +[KRB5KDC_ERR_NONE, KRB5_ERR_RCSID), it will be replaced with a GENERIC +error, and the error text will be set to the meaningless result of +krb5_get_error_message(). Avoid this by ensuring the error code is in +the correct range. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + selftest/knownfail_heimdal_kdc | 2 -- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/kpasswd-service.c | 2 +- + 3 files changed, 1 insertion(+), 7 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 5fd6e4aa0ed..cb4f190d75f 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -114,9 +114,7 @@ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index e4300b4d20e..41a793ae082 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -545,13 +545,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index 22e1295c11e..379ddebf3ad 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -315,7 +315,7 @@ reply: + } + + code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context, +- error_code, ++ KRB5KDC_ERR_NONE + error_code, + NULL, /* e_text */ + &k_dec_data, + NULL, /* client */ +-- +2.25.1 + + +From 9da789c73dd6675789b93fc0df0dfc8b274a86c3 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:06:31 +1200 +Subject: [PATCH 76/99] CVE-2022-2031 gensec_krb5: Add helper function to check + if client sent an initial ticket + +This will be used in the kpasswd service to ensure that the client has +an initial ticket to kadmin/changepw, and not a service ticket. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/gensec/gensec_krb5.c | 20 +----- + source4/auth/gensec/gensec_krb5_helpers.c | 72 ++++++++++++++++++++++ + source4/auth/gensec/gensec_krb5_helpers.h | 32 ++++++++++ + source4/auth/gensec/gensec_krb5_internal.h | 47 ++++++++++++++ + source4/auth/gensec/wscript_build | 4 ++ + 5 files changed, 157 insertions(+), 18 deletions(-) + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.c + create mode 100644 source4/auth/gensec/gensec_krb5_helpers.h + create mode 100644 source4/auth/gensec/gensec_krb5_internal.h + +diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c +index 7d87b3ac6b9..104e4639c44 100644 +--- a/source4/auth/gensec/gensec_krb5.c ++++ b/source4/auth/gensec/gensec_krb5.c +@@ -44,27 +44,11 @@ + #include "../lib/util/asn1.h" + #include "auth/kerberos/pac_utils.h" + #include "gensec_krb5.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" + + _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *); + +-enum GENSEC_KRB5_STATE { +- GENSEC_KRB5_SERVER_START, +- GENSEC_KRB5_CLIENT_START, +- GENSEC_KRB5_CLIENT_MUTUAL_AUTH, +- GENSEC_KRB5_DONE +-}; +- +-struct gensec_krb5_state { +- enum GENSEC_KRB5_STATE state_position; +- struct smb_krb5_context *smb_krb5_context; +- krb5_auth_context auth_context; +- krb5_data enc_ticket; +- krb5_keyblock *keyblock; +- krb5_ticket *ticket; +- bool gssapi; +- krb5_flags ap_req_options; +-}; +- + static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state) + { + if (!gensec_krb5_state->smb_krb5_context) { +diff --git a/source4/auth/gensec/gensec_krb5_helpers.c b/source4/auth/gensec/gensec_krb5_helpers.c +new file mode 100644 +index 00000000000..21f2f1e884e +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_helpers.c +@@ -0,0 +1,72 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "includes.h" ++#include "auth/auth.h" ++#include "auth/gensec/gensec.h" ++#include "auth/gensec/gensec_internal.h" ++#include "gensec_krb5_internal.h" ++#include "gensec_krb5_helpers.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++static struct gensec_krb5_state *get_private_state(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ if (strcmp(gensec_security->ops->name, "krb5") != 0) { ++ /* We require that the krb5 mechanism is being used. */ ++ return NULL; ++ } ++ ++ gensec_krb5_state = talloc_get_type(gensec_security->private_data, ++ struct gensec_krb5_state); ++ return gensec_krb5_state; ++} ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security) ++{ ++ struct gensec_krb5_state *gensec_krb5_state = NULL; ++ ++ gensec_krb5_state = get_private_state(gensec_security); ++ if (gensec_krb5_state == NULL) { ++ return -1; ++ } ++ ++ if (gensec_krb5_state->ticket == NULL) { ++ /* We don't have a ticket */ ++ return -1; ++ } ++ ++#ifdef SAMBA4_USES_HEIMDAL ++ return gensec_krb5_state->ticket->ticket.flags.initial; ++#else /* MIT KERBEROS */ ++ return (gensec_krb5_state->ticket->enc_part2->flags & TKT_FLG_INITIAL) ? 1 : 0; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} +diff --git a/source4/auth/gensec/gensec_krb5_helpers.h b/source4/auth/gensec/gensec_krb5_helpers.h +new file mode 100644 +index 00000000000..d7b694dad0c +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_helpers.h +@@ -0,0 +1,32 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++struct gensec_security; ++ ++/* ++ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of ++ * error. ++ */ ++int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security); +diff --git a/source4/auth/gensec/gensec_krb5_internal.h b/source4/auth/gensec/gensec_krb5_internal.h +new file mode 100644 +index 00000000000..0bb796f1b2a +--- /dev/null ++++ b/source4/auth/gensec/gensec_krb5_internal.h +@@ -0,0 +1,47 @@ ++/* ++ Unix SMB/CIFS implementation. ++ ++ Kerberos backend for GENSEC ++ ++ Copyright (C) Andrew Bartlett 2004 ++ Copyright (C) Andrew Tridgell 2001 ++ Copyright (C) Luke Howard 2002-2003 ++ Copyright (C) Stefan Metzmacher 2004-2005 ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "includes.h" ++#include "auth/gensec/gensec.h" ++#include "system/kerberos.h" ++#include "auth/kerberos/kerberos.h" ++ ++enum GENSEC_KRB5_STATE { ++ GENSEC_KRB5_SERVER_START, ++ GENSEC_KRB5_CLIENT_START, ++ GENSEC_KRB5_CLIENT_MUTUAL_AUTH, ++ GENSEC_KRB5_DONE ++}; ++ ++struct gensec_krb5_state { ++ enum GENSEC_KRB5_STATE state_position; ++ struct smb_krb5_context *smb_krb5_context; ++ krb5_auth_context auth_context; ++ krb5_data enc_ticket; ++ krb5_keyblock *keyblock; ++ krb5_ticket *ticket; ++ bool gssapi; ++ krb5_flags ap_req_options; ++}; +diff --git a/source4/auth/gensec/wscript_build b/source4/auth/gensec/wscript_build +index d14a50ff273..20271f1665b 100644 +--- a/source4/auth/gensec/wscript_build ++++ b/source4/auth/gensec/wscript_build +@@ -18,6 +18,10 @@ bld.SAMBA_MODULE('gensec_krb5', + enabled=bld.AD_DC_BUILD_IS_ENABLED() + ) + ++bld.SAMBA_SUBSYSTEM('gensec_krb5_helpers', ++ source='gensec_krb5_helpers.c', ++ deps='gensec_krb5', ++ enabled=bld.AD_DC_BUILD_IS_ENABLED()) + + bld.SAMBA_MODULE('gensec_gssapi', + source='gensec_gssapi.c', +-- +2.25.1 + + +From 298884abb35db7b6a8c6100dfd7bb8b57b1117fd Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:52:41 +1200 +Subject: [PATCH 77/99] CVE-2022-2031 s4:kpasswd: Require an initial ticket + +Ensure that for password changes the client uses an AS-REQ to get the +ticket to kpasswd, and not a TGS-REQ. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails] +--- + selftest/knownfail_heimdal_kdc | 1 - + selftest/knownfail_mit_kdc | 1 - + source4/kdc/kpasswd-service-heimdal.c | 17 +++++++++++++++++ + source4/kdc/kpasswd-service-mit.c | 17 +++++++++++++++++ + source4/kdc/wscript_build | 1 + + 5 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index cb4f190d75f..ab7230060ab 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -115,7 +115,6 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 41a793ae082..0389672e5d9 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -546,7 +546,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +diff --git a/source4/kdc/kpasswd-service-heimdal.c b/source4/kdc/kpasswd-service-heimdal.c +index c804852c3a7..1a6c2b60d03 100644 +--- a/source4/kdc/kpasswd-service-heimdal.c ++++ b/source4/kdc/kpasswd-service-heimdal.c +@@ -24,6 +24,7 @@ + #include "param/param.h" + #include "auth/auth.h" + #include "auth/gensec/gensec.h" ++#include "gensec_krb5_helpers.h" + #include "kdc/kdc-server.h" + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" +@@ -31,6 +32,7 @@ + + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *password, + DATA_BLOB *kpasswd_reply, +@@ -42,6 +44,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + const char *reject_string = NULL; + struct samr_DomInfo1 *dominfo; + bool ok; ++ int ret; ++ ++ /* ++ * We're doing a password change (rather than a password set), so check ++ * that we were given an initial ticket. ++ */ ++ ret = gensec_krb5_initial_ticket(gensec_security); ++ if (ret != 1) { ++ *error_string = "Expected an initial ticket"; ++ return KRB5_KPASSWD_INITIAL_FLAG_NEEDED; ++ } + + status = samdb_kpasswd_change_password(mem_ctx, + kdc->task->lp_ctx, +@@ -81,6 +94,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + + static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *decoded_data, + DATA_BLOB *kpasswd_reply, +@@ -173,6 +187,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + free_ChangePasswdDataMS(&chpw); + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -272,6 +287,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -280,6 +296,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + case KRB5_KPASSWD_VERS_SETPW: { + return kpasswd_set_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + decoded_data, + kpasswd_reply, +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index 9c4d2801669..de4c6f3f622 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -24,6 +24,7 @@ + #include "param/param.h" + #include "auth/auth.h" + #include "auth/gensec/gensec.h" ++#include "gensec_krb5_helpers.h" + #include "kdc/kdc-server.h" + #include "kdc/kpasswd_glue.h" + #include "kdc/kpasswd-service.h" +@@ -84,6 +85,7 @@ out: + + static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *password, + DATA_BLOB *kpasswd_reply, +@@ -95,6 +97,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + const char *reject_string = NULL; + struct samr_DomInfo1 *dominfo; + bool ok; ++ int ret; ++ ++ /* ++ * We're doing a password change (rather than a password set), so check ++ * that we were given an initial ticket. ++ */ ++ ret = gensec_krb5_initial_ticket(gensec_security); ++ if (ret != 1) { ++ *error_string = "Expected an initial ticket"; ++ return KRB5_KPASSWD_INITIAL_FLAG_NEEDED; ++ } + + status = samdb_kpasswd_change_password(mem_ctx, + kdc->task->lp_ctx, +@@ -134,6 +147,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc, + + static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + TALLOC_CTX *mem_ctx, ++ const struct gensec_security *gensec_security, + struct auth_session_info *session_info, + DATA_BLOB *decoded_data, + DATA_BLOB *kpasswd_reply, +@@ -250,6 +264,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -350,6 +365,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + + return kpasswd_change_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + &password, + kpasswd_reply, +@@ -358,6 +374,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + case RFC3244_VERSION: { + return kpasswd_set_password(kdc, + mem_ctx, ++ gensec_security, + session_info, + decoded_data, + kpasswd_reply, +diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build +index 0edca94e75f..13ba3947cf6 100644 +--- a/source4/kdc/wscript_build ++++ b/source4/kdc/wscript_build +@@ -88,6 +88,7 @@ bld.SAMBA_SUBSYSTEM('KPASSWD-SERVICE', + krb5samba + samba_server_gensec + KPASSWD_GLUE ++ gensec_krb5_helpers + ''') + + bld.SAMBA_SUBSYSTEM('KDC-GLUE', +-- +2.25.1 + + +From a1df5b86e967dc190af5ba2ba07d8ef8b400b4b1 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 17:11:49 +1200 +Subject: [PATCH 78/99] s4:kpasswd: Restructure code for clarity + +View with 'git show -b'. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/kpasswd-service-heimdal.c | 46 +++++++++++++-------------- + 1 file changed, 22 insertions(+), 24 deletions(-) + +diff --git a/source4/kdc/kpasswd-service-heimdal.c b/source4/kdc/kpasswd-service-heimdal.c +index 1a6c2b60d03..a0352d1ad35 100644 +--- a/source4/kdc/kpasswd-service-heimdal.c ++++ b/source4/kdc/kpasswd-service-heimdal.c +@@ -160,30 +160,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + return 0; + } + +- if (chpw.targname != NULL && chpw.targrealm != NULL) { +- code = krb5_build_principal_ext(context, +- &target_principal, +- strlen(*chpw.targrealm), +- *chpw.targrealm, +- 0); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- code = copy_PrincipalName(chpw.targname, +- &target_principal->name); +- if (code != 0) { +- free_ChangePasswdDataMS(&chpw); +- krb5_free_principal(context, target_principal); +- return kpasswd_make_error_reply(mem_ctx, +- KRB5_KPASSWD_MALFORMED, +- "Failed to parse principal", +- kpasswd_reply); +- } +- } else { ++ if (chpw.targname == NULL || chpw.targrealm == NULL) { + free_ChangePasswdDataMS(&chpw); + return kpasswd_change_password(kdc, + mem_ctx, +@@ -193,7 +170,28 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc, + kpasswd_reply, + error_string); + } ++ code = krb5_build_principal_ext(context, ++ &target_principal, ++ strlen(*chpw.targrealm), ++ *chpw.targrealm, ++ 0); ++ if (code != 0) { ++ free_ChangePasswdDataMS(&chpw); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } ++ code = copy_PrincipalName(chpw.targname, ++ &target_principal->name); + free_ChangePasswdDataMS(&chpw); ++ if (code != 0) { ++ krb5_free_principal(context, target_principal); ++ return kpasswd_make_error_reply(mem_ctx, ++ KRB5_KPASSWD_MALFORMED, ++ "Failed to parse principal", ++ kpasswd_reply); ++ } + + if (target_principal->name.name_string.len >= 2) { + is_service_principal = true; +-- +2.25.1 + + +From 981948677c895e4e1d3b074f8a1a9c82fd65a80a Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 10:17:00 +0200 +Subject: [PATCH 79/99] CVE-2022-2031 testprogs: Fix auth with smbclient and + krb5 ccache + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton +--- + testprogs/blackbox/test_kpasswd_heimdal.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/testprogs/blackbox/test_kpasswd_heimdal.sh b/testprogs/blackbox/test_kpasswd_heimdal.sh +index 43f38b09de2..a73c6665a18 100755 +--- a/testprogs/blackbox/test_kpasswd_heimdal.sh ++++ b/testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -71,7 +71,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" --use-kerberos=required || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --use-krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + testit "change user password with 'samba-tool user password' (unforced)" \ + $VALGRIND $PYTHON $samba_tool user password -W$DOMAIN -U$TEST_USERNAME%$TEST_PASSWORD --use-kerberos=off --newpassword=$TEST_PASSWORD_NEW || failed=`expr $failed + 1` +@@ -84,7 +84,7 @@ testit "kinit with user password" \ + do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1` + + test_smbclient "Test login with user kerberos ccache" \ +- "ls" "$SMB_UNC" --use-kerberos=required || failed=`expr $failed + 1` ++ "ls" "$SMB_UNC" --use-krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1` + + ########################################################### + ### check that a short password is rejected +-- +2.25.1 + + +From 5dd0ef1991944a740b1d0107487d25d1acf5ebef Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Thu, 19 May 2022 16:35:28 +0200 +Subject: [PATCH 80/99] CVE-2022-2031 testprogs: Add kadmin/changepw + canonicalization test with MIT kpasswd + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton +--- + selftest/knownfail.d/kadmin_changepw | 1 + + testprogs/blackbox/test_kpasswd_heimdal.sh | 35 +++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + create mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git a/selftest/knownfail.d/kadmin_changepw b/selftest/knownfail.d/kadmin_changepw +new file mode 100644 +index 00000000000..97c14793ea5 +--- /dev/null ++++ b/selftest/knownfail.d/kadmin_changepw +@@ -0,0 +1 @@ ++^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git a/testprogs/blackbox/test_kpasswd_heimdal.sh b/testprogs/blackbox/test_kpasswd_heimdal.sh +index a73c6665a18..698044a3fd3 100755 +--- a/testprogs/blackbox/test_kpasswd_heimdal.sh ++++ b/testprogs/blackbox/test_kpasswd_heimdal.sh +@@ -7,7 +7,7 @@ + + if [ $# -lt 6 ]; then + cat < "${PREFIX}/tmpkpasswdscript" < "${KRB5_CONFIG}" ++ testit "MIT kpasswd change user password" \ ++ "${texpect}" "${PREFIX}/tmpkpasswdscript" "${mit_kpasswd}" \ ++ "${TEST_PRINCIPAL}" || ++ failed=$((failed + 1)) ++ KRB5_CONFIG="${SAVE_KRB5_CONFIG}" ++ export KRB5_CONFIG ++fi ++ ++TEST_PASSWORD="${TEST_PASSWORD_NEW}" ++TEST_PASSWORD_NEW="testPaSS@03force%" ++ + ########################################################### + ### Force password change at login + ########################################################### +-- +2.25.1 + + +From 3fd067c7d63e132a84bfc155769012e4261a9f07 Mon Sep 17 00:00:00 2001 +From: Andreas Schneider +Date: Tue, 24 May 2022 09:54:18 +0200 +Subject: [PATCH 81/99] CVE-2022-2031 s4:kdc: Implement is_kadmin_changepw() + helper function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Andreas Schneider +Reviewed-by: Joseph Sutton + +[jsutton@samba.org Adapted entry to entry_ex->entry] +--- + source4/kdc/db-glue.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 5752ffb821c..45159e6e64d 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -816,6 +816,14 @@ static int principal_comp_strcmp(krb5_context context, + component, string, false); + } + ++static bool is_kadmin_changepw(krb5_context context, ++ krb5_const_principal principal) ++{ ++ return krb5_princ_size(context, principal) == 2 && ++ (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) && ++ (principal_comp_strcmp(context, principal, 1, "changepw") == 0); ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -1110,11 +1118,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + * 'change password', as otherwise we could get into + * trouble, and not enforce the password expirty. + * Instead, only do it when request is for the kpasswd service */ +- if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER +- && krb5_princ_size(context, principal) == 2 +- && (principal_comp_strcmp(context, principal, 0, "kadmin") == 0) +- && (principal_comp_strcmp(context, principal, 1, "changepw") == 0) +- && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER && ++ is_kadmin_changepw(context, principal) && ++ lpcfg_is_my_domain_or_realm(lp_ctx, realm)) { + entry_ex->entry.flags.change_pw = 1; + } + +-- +2.25.1 + + +From 5e7d75d8754d157d10e3e7d730445bddd91e5b9e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 82/99] CVE-2022-2031 s4:kdc: Split out a + samba_kdc_get_entry_principal() function + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry] + +[jsutton@samba.org Fixed conflicts caused by superfluous whitespace] +--- + source4/kdc/db-glue.c | 192 +++++++++++++++++++++++------------------- + 1 file changed, 107 insertions(+), 85 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 45159e6e64d..ac0c206b5c1 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -824,6 +824,101 @@ static bool is_kadmin_changepw(krb5_context context, + (principal_comp_strcmp(context, principal, 1, "changepw") == 0); + } + ++static krb5_error_code samba_kdc_get_entry_principal( ++ krb5_context context, ++ struct samba_kdc_db_context *kdc_db_ctx, ++ const char *samAccountName, ++ enum samba_kdc_ent_type ent_type, ++ unsigned flags, ++ krb5_const_principal in_princ, ++ krb5_principal *out_princ) ++{ ++ struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; ++ krb5_error_code ret = 0; ++ ++ /* ++ * If we are set to canonicalize, we get back the fixed UPPER ++ * case realm, and the real username (ie matching LDAP ++ * samAccountName) ++ * ++ * Otherwise, if we are set to enterprise, we ++ * get back the whole principal as-sent ++ * ++ * Finally, if we are not set to canonicalize, we get back the ++ * fixed UPPER case realm, but the as-sent username ++ */ ++ ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { ++ if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, ++ lpcfg_realm(lp_ctx), "krbtgt", ++ lpcfg_realm(lp_ctx), NULL); ++ if (ret) { ++ return ret; ++ } ++ smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ /* ++ * this appears to be required regardless of ++ * the canonicalize flag from the client ++ */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else if ((flags & SDB_F_FORCE_CANON) || ++ ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the AS-REQ case ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that wants ++ * the canonical name in all lookups, and takes care to ++ * canonicalize only when appropriate. ++ */ ++ ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); ++ if (ret) { ++ return ret; ++ } ++ } else { ++ ret = krb5_copy_principal(context, in_princ, out_princ); ++ if (ret) { ++ return ret; ++ } ++ ++ /* While we have copied the client principal, tests ++ * show that Win2k3 returns the 'corrected' realm, not ++ * the client-specified realm. This code attempts to ++ * replace the client principal's realm with the one ++ * we determine from our records */ ++ ++ /* this has to be with malloc() */ ++ ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); ++ if (ret) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ + /* + * Construct an hdb_entry from a directory entry. + */ +@@ -913,93 +1008,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + userAccountControl |= msDS_User_Account_Control_Computed; + } + +- /* +- * If we are set to canonicalize, we get back the fixed UPPER +- * case realm, and the real username (ie matching LDAP +- * samAccountName) +- * +- * Otherwise, if we are set to enterprise, we +- * get back the whole principal as-sent +- * +- * Finally, if we are not set to canonicalize, we get back the +- * fixed UPPER case realm, but the as-sent username +- */ +- + if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { + p->is_krbtgt = true; +- +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- smb_krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } +- +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) { +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. +- */ +- ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- } else { +- ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ +- +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx)); +- if (ret) { +- krb5_clear_error_message(context); +- goto out; +- } + } + + /* First try and figure out the flags based on the userAccountControl */ +@@ -1185,6 +1195,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + } + } + ++ ret = samba_kdc_get_entry_principal(context, ++ kdc_db_ctx, ++ samAccountName, ++ ent_type, ++ flags, ++ principal, ++ &entry_ex->entry.principal); ++ if (ret != 0) { ++ krb5_clear_error_message(context); ++ goto out; ++ } ++ + entry_ex->entry.valid_start = NULL; + + entry_ex->entry.max_life = malloc(sizeof(*entry_ex->entry.max_life)); +-- +2.25.1 + + +From 8b9fe095b91ce62338829a6ac7012170e6af8898 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 17:19:58 +1200 +Subject: [PATCH 83/99] CVE-2022-2031 s4:kdc: Refactor + samba_kdc_get_entry_principal() + +This eliminates some duplicate branches. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Pair-Programmed-With: Andreas Schneider +Reviewed-by: Andreas Schneider +--- + source4/kdc/db-glue.c | 116 ++++++++++++++++++++---------------------- + 1 file changed, 55 insertions(+), 61 deletions(-) + +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index ac0c206b5c1..385c118a073 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -834,7 +834,8 @@ static krb5_error_code samba_kdc_get_entry_principal( + krb5_principal *out_princ) + { + struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx; +- krb5_error_code ret = 0; ++ krb5_error_code code = 0; ++ bool canon = flags & (SDB_F_CANON|SDB_F_FORCE_CANON); + + /* + * If we are set to canonicalize, we get back the fixed UPPER +@@ -848,75 +849,68 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) { +- if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- ret = smb_krb5_make_principal(context, out_princ, +- lpcfg_realm(lp_ctx), "krbtgt", +- lpcfg_realm(lp_ctx), NULL); +- if (ret) { +- return ret; +- } +- smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST); +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- /* +- * this appears to be required regardless of +- * the canonicalize flag from the client +- */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } +- } ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- } else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) { +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else if ((flags & SDB_F_FORCE_CANON) || +- ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) { ++ return 0; ++ } ++ ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { + /* + * SDB_F_CANON maps from the canonicalize flag in the + * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the AS-REQ case ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. + * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that wants +- * the canonical name in all lookups, and takes care to +- * canonicalize only when appropriate. ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. + */ +- ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL); +- if (ret) { +- return ret; +- } +- } else { +- ret = krb5_copy_principal(context, in_princ, out_princ); +- if (ret) { +- return ret; +- } +- +- /* While we have copied the client principal, tests +- * show that Win2k3 returns the 'corrected' realm, not +- * the client-specified realm. This code attempts to +- * replace the client principal's realm with the one +- * we determine from our records */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + +- /* this has to be with malloc() */ +- ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx)); +- if (ret) { +- return ret; +- } ++ /* ++ * For a krbtgt entry, this appears to be required regardless of the ++ * canonicalize flag from the client. ++ */ ++ code = krb5_copy_principal(context, in_princ, out_princ); ++ if (code != 0) { ++ return code; + } + +- return 0; ++ /* ++ * While we have copied the client principal, tests show that Win2k3 ++ * returns the 'corrected' realm, not the client-specified realm. This ++ * code attempts to replace the client principal's realm with the one ++ * we determine from our records ++ */ ++ code = smb_krb5_principal_set_realm(context, ++ *out_princ, ++ lpcfg_realm(lp_ctx)); ++ ++ return code; + } + + /* +-- +2.25.1 + + +From 04e452890ada8390828aa4c5c87ceefe44daa50f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 18 May 2022 16:56:01 +1200 +Subject: [PATCH 84/99] CVE-2022-2031 s4:kdc: Fix canonicalisation of + kadmin/changepw principal + +Since this principal goes through the samba_kdc_fetch_server() path, +setting the canonicalisation flag would cause the principal to be +replaced with the sAMAccountName; this meant requests to +kadmin/changepw@REALM would result in a ticket to krbtgt@REALM. Now we +properly handle canonicalisation for the kadmin/changepw principal. + +View with 'git show -b'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Pair-Programmed-With: Andreas Schneider +Signed-off-by: Andreas Schneider +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; removed MIT KDC + 1.20-specific knownfails] +--- + selftest/knownfail.d/kadmin_changepw | 1 - + selftest/knownfail_heimdal_kdc | 2 - + source4/kdc/db-glue.c | 84 +++++++++++++++------------- + 3 files changed, 46 insertions(+), 41 deletions(-) + delete mode 100644 selftest/knownfail.d/kadmin_changepw + +diff --git a/selftest/knownfail.d/kadmin_changepw b/selftest/knownfail.d/kadmin_changepw +deleted file mode 100644 +index 97c14793ea5..00000000000 +--- a/selftest/knownfail.d/kadmin_changepw ++++ /dev/null +@@ -1 +0,0 @@ +-^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index ab7230060ab..6abbbf75391 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -112,8 +112,6 @@ + # + # Kpasswd tests + # +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 385c118a073..d2d7136608e 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -830,6 +830,7 @@ static krb5_error_code samba_kdc_get_entry_principal( + const char *samAccountName, + enum samba_kdc_ent_type ent_type, + unsigned flags, ++ bool is_kadmin_changepw, + krb5_const_principal in_princ, + krb5_principal *out_princ) + { +@@ -849,46 +850,52 @@ static krb5_error_code samba_kdc_get_entry_principal( + * fixed UPPER case realm, but the as-sent username + */ + +- if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { +- /* +- * When requested to do so, ensure that the +- * both realm values in the principal are set +- * to the upper case, canonical realm +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- "krbtgt", +- lpcfg_realm(lp_ctx), +- NULL); +- if (code != 0) { +- return code; +- } +- smb_krb5_principal_set_type(context, +- *out_princ, +- KRB5_NT_SRV_INST); ++ /* ++ * We need to ensure that the kadmin/changepw principal isn't able to ++ * issue krbtgt tickets, even if canonicalization is turned on. ++ */ ++ if (!is_kadmin_changepw) { ++ if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) { ++ /* ++ * When requested to do so, ensure that the ++ * both realm values in the principal are set ++ * to the upper case, canonical realm ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ "krbtgt", ++ lpcfg_realm(lp_ctx), ++ NULL); ++ if (code != 0) { ++ return code; ++ } ++ smb_krb5_principal_set_type(context, ++ *out_princ, ++ KRB5_NT_SRV_INST); + +- return 0; +- } ++ return 0; ++ } + +- if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || +- (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { +- /* +- * SDB_F_CANON maps from the canonicalize flag in the +- * packet, and has a different meaning between AS-REQ +- * and TGS-REQ. We only change the principal in the +- * AS-REQ case. +- * +- * The SDB_F_FORCE_CANON if for new MIT KDC code that +- * wants the canonical name in all lookups, and takes +- * care to canonicalize only when appropriate. +- */ +- code = smb_krb5_make_principal(context, +- out_princ, +- lpcfg_realm(lp_ctx), +- samAccountName, +- NULL); +- return code; ++ if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) || ++ (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) { ++ /* ++ * SDB_F_CANON maps from the canonicalize flag in the ++ * packet, and has a different meaning between AS-REQ ++ * and TGS-REQ. We only change the principal in the ++ * AS-REQ case. ++ * ++ * The SDB_F_FORCE_CANON if for new MIT KDC code that ++ * wants the canonical name in all lookups, and takes ++ * care to canonicalize only when appropriate. ++ */ ++ code = smb_krb5_make_principal(context, ++ out_princ, ++ lpcfg_realm(lp_ctx), ++ samAccountName, ++ NULL); ++ return code; ++ } + } + + /* +@@ -1194,6 +1201,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + samAccountName, + ent_type, + flags, ++ entry_ex->entry.flags.change_pw, + principal, + &entry_ex->entry.principal); + if (ret != 0) { +-- +2.25.1 + + +From a46d0ac59f074f999217586f18ba8772a645b246 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 24 May 2022 17:53:49 +1200 +Subject: [PATCH 85/99] CVE-2022-2031 s4:kdc: Limit kpasswd ticket lifetime to + two minutes or less + +This matches the behaviour of Windows. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Adapted entry to entry_ex->entry; included + samba_kdc.h header file] +--- + selftest/knownfail_heimdal_kdc | 1 - + selftest/knownfail_mit_kdc | 1 - + source4/kdc/db-glue.c | 5 +++++ + source4/kdc/mit-kdb/kdb_samba_principals.c | 2 +- + source4/kdc/samba_kdc.h | 2 ++ + 5 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 6abbbf75391..4fb838f0e11 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -113,7 +113,6 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 0389672e5d9..ed8f7069319 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -546,7 +546,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index d2d7136608e..073ec83c8cf 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -1226,6 +1226,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context, + kdc_db_ctx->policy.usr_tkt_lifetime); + } + ++ if (entry_ex->entry.flags.change_pw) { ++ /* Limit lifetime of kpasswd tickets to two minutes or less. */ ++ *entry_ex->entry.max_life = MIN(*entry_ex->entry.max_life, CHANGEPW_LIFETIME); ++ } ++ + entry_ex->entry.max_renew = malloc(sizeof(*entry_ex->entry.max_life)); + if (entry_ex->entry.max_renew == NULL) { + ret = ENOMEM; +diff --git a/source4/kdc/mit-kdb/kdb_samba_principals.c b/source4/kdc/mit-kdb/kdb_samba_principals.c +index 3917b9824c6..da21251179b 100644 +--- a/source4/kdc/mit-kdb/kdb_samba_principals.c ++++ b/source4/kdc/mit-kdb/kdb_samba_principals.c +@@ -27,6 +27,7 @@ + #include + #include + ++#include "kdc/samba_kdc.h" + #include "kdc/mit_samba.h" + #include "kdb_samba.h" + +@@ -34,7 +35,6 @@ + #define DBGC_CLASS DBGC_KERBEROS + + #define ADMIN_LIFETIME 60*60*3 /* 3 hours */ +-#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ + + krb5_error_code ks_get_principal(krb5_context context, + krb5_const_principal principal, +diff --git a/source4/kdc/samba_kdc.h b/source4/kdc/samba_kdc.h +index e228a82ce6a..8010d7c35ed 100644 +--- a/source4/kdc/samba_kdc.h ++++ b/source4/kdc/samba_kdc.h +@@ -62,4 +62,6 @@ struct samba_kdc_entry { + + extern struct hdb_method hdb_samba4_interface; + ++#define CHANGEPW_LIFETIME 60*2 /* 2 minutes */ ++ + #endif /* _SAMBA_KDC_H_ */ +-- +2.25.1 + + +From c7408dd944ee5a0de5f04079d158f4575fb9036a Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:18:17 +1200 +Subject: [PATCH 86/99] CVE-2022-2031 s4:kdc: Reject tickets during the last + two minutes of their life + +For Heimdal, this now matches the behaviour of Windows. The object of +this requirement is to ensure we don't allow kpasswd tickets, not having +a lifetime of more than two minutes, to be passed off as TGTs. + +An existing requirement for TGTs to contain a REQUESTER_SID PAC buffer +suffices to prevent kpasswd ticket misuse, so this is just an additional +precaution on top. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org As we don't have access to the ticket or the request + in the plugin, rewrote check directly in Heimdal KDC] +--- + selftest/knownfail_heimdal_kdc | 1 - + source4/heimdal/kdc/krb5tgs.c | 19 ++++++++++++++++++- + 2 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 4fb838f0e11..dfe04dd1448 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -113,7 +113,6 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c +index 38dba8493ae..15be136496f 100644 +--- a/source4/heimdal/kdc/krb5tgs.c ++++ b/source4/heimdal/kdc/krb5tgs.c +@@ -33,6 +33,9 @@ + + #include "kdc_locl.h" + ++/* Awful hack to get access to 'struct samba_kdc_entry'. */ ++#include "../../kdc/samba_kdc.h" ++ + /* + * return the realm of a krbtgt-ticket or NULL + */ +@@ -130,6 +133,7 @@ check_PAC(krb5_context context, + static krb5_error_code + check_tgs_flags(krb5_context context, + krb5_kdc_configuration *config, ++ const hdb_entry_ex *krbtgt_in, + KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et) + { + KDCOptions f = b->kdc_options; +@@ -244,6 +248,17 @@ check_tgs_flags(krb5_context context, + et->endtime = min(*et->renew_till, et->endtime); + } + ++ if (tgt->endtime - kdc_time <= CHANGEPW_LIFETIME) { ++ /* Check that the ticket has not arrived across a trust. */ ++ const struct samba_kdc_entry *skdc_entry = krbtgt_in->ctx; ++ if (!skdc_entry->is_trust) { ++ /* This may be a kpasswd ticket rather than a TGT, so don't accept it. */ ++ kdc_log(context, config, 0, ++ "Ticket is not a ticket-granting ticket"); ++ return KRB5KRB_AP_ERR_TKT_EXPIRED; ++ } ++ } ++ + #if 0 + /* checks for excess flags */ + if(f.request_anonymous && !config->allow_anonymous){ +@@ -510,6 +525,7 @@ tgs_make_reply(krb5_context context, + hdb_entry_ex *client, + krb5_principal client_principal, + const char *tgt_realm, ++ const hdb_entry_ex *krbtgt_in, + hdb_entry_ex *krbtgt, + krb5_pac mspac, + uint16_t rodc_id, +@@ -538,7 +554,7 @@ tgs_make_reply(krb5_context context, + ALLOC(et.starttime); + *et.starttime = kdc_time; + +- ret = check_tgs_flags(context, config, b, tgt, &et); ++ ret = check_tgs_flags(context, config, krbtgt_in, b, tgt, &et); + if(ret) + goto out; + +@@ -2129,6 +2145,7 @@ server_lookup: + client, + cp, + tgt_realm, ++ krbtgt, + krbtgt_out, + mspac, + rodc_id, +-- +2.25.1 + + +From 389a5523485dfbd48e87b6ee9c39c6c2e16294a0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 15:23:55 +1200 +Subject: [PATCH 87/99] CVE-2022-2031 tests/krb5: Test truncated forms of + server principals + +We should not be able to use krb@REALM instead of krbtgt@REALM. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to having older version of + _run_as_req_enc_timestamp()] +--- + python/samba/tests/krb5/as_req_tests.py | 40 ++++++++++++++++++++++--- + selftest/knownfail_heimdal_kdc | 4 +++ + selftest/knownfail_mit_kdc | 4 +++ + 3 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py +index 315720f85d6..054a49b64aa 100755 +--- a/python/samba/tests/krb5/as_req_tests.py ++++ b/python/samba/tests/krb5/as_req_tests.py +@@ -27,6 +27,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest + import samba.tests.krb5.kcrypto as kcrypto + import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 + from samba.tests.krb5.rfc4120_constants import ( ++ KDC_ERR_S_PRINCIPAL_UNKNOWN, + KDC_ERR_ETYPE_NOSUPP, + KDC_ERR_PREAUTH_REQUIRED, + KU_PA_ENC_TIMESTAMP, +@@ -40,7 +41,8 @@ global_hexdump = False + + + class AsReqBaseTest(KDCBaseTest): +- def _run_as_req_enc_timestamp(self, client_creds): ++ def _run_as_req_enc_timestamp(self, client_creds, sname=None, ++ expected_error=None): + client_account = client_creds.get_username() + client_as_etypes = self.get_default_enctypes() + client_kvno = client_creds.get_kvno() +@@ -50,8 +52,9 @@ class AsReqBaseTest(KDCBaseTest): + + cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_account]) +- sname = self.PrincipalName_create(name_type=NT_SRV_INST, +- names=[krbtgt_account, realm]) ++ if sname is None: ++ sname = self.PrincipalName_create(name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) + + expected_crealm = realm + expected_cname = cname +@@ -63,7 +66,10 @@ class AsReqBaseTest(KDCBaseTest): + + initial_etypes = client_as_etypes + initial_kdc_options = krb5_asn1.KDCOptions('forwardable') +- initial_error_mode = KDC_ERR_PREAUTH_REQUIRED ++ if expected_error is not None: ++ initial_error_mode = expected_error ++ else: ++ initial_error_mode = KDC_ERR_PREAUTH_REQUIRED + + rep, kdc_exchange_dict = self._test_as_exchange(cname, + realm, +@@ -80,6 +86,10 @@ class AsReqBaseTest(KDCBaseTest): + None, + initial_kdc_options, + pac_request=True) ++ ++ if expected_error is not None: ++ return None ++ + etype_info2 = kdc_exchange_dict['preauth_etype_info2'] + self.assertIsNotNone(etype_info2) + +@@ -209,6 +219,28 @@ class AsReqKerberosTests(AsReqBaseTest): + client_creds = self.get_mach_creds() + self._run_as_req_enc_timestamp(client_creds) + ++ # Ensure we can't use truncated well-known principals such as krb@REALM ++ # instead of krbtgt@REALM. ++ def test_krbtgt_wrong_principal(self): ++ client_creds = self.get_client_creds() ++ ++ krbtgt_creds = self.get_krbtgt_creds() ++ ++ krbtgt_account = krbtgt_creds.get_username() ++ realm = krbtgt_creds.get_realm() ++ ++ # Truncate the name of the krbtgt principal. ++ krbtgt_account = krbtgt_account[:3] ++ ++ wrong_krbtgt_princ = self.PrincipalName_create( ++ name_type=NT_SRV_INST, ++ names=[krbtgt_account, realm]) ++ ++ self._run_as_req_enc_timestamp( ++ client_creds, ++ sname=wrong_krbtgt_princ, ++ expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN) ++ + + if __name__ == "__main__": + global_asn1_print = False +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index dfe04dd1448..7ad9ee85778 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -116,3 +116,7 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc ++# ++# AS-REQ tests ++# ++^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index ed8f7069319..ad0fa84aedb 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -549,3 +549,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc ++# ++# AS-REQ tests ++# ++^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +-- +2.25.1 + + +From 959ed604ee1588f9a92c269a014fbf12b72fb8a4 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 25 May 2022 20:00:55 +1200 +Subject: [PATCH 88/99] CVE-2022-2031 s4:kdc: Don't use strncmp to compare + principal components + +We would only compare the first 'n' characters, where 'n' is the length +of the principal component string, so 'k@REALM' would erroneously be +considered equal to 'krbtgt@REALM'. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/db-glue.c | 27 ++++++++++++++++++++++----- + 3 files changed, 22 insertions(+), 13 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 7ad9ee85778..dfe04dd1448 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -116,7 +116,3 @@ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-# +-# AS-REQ tests +-# +-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index ad0fa84aedb..ed8f7069319 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -549,7 +549,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +-# +-# AS-REQ tests +-# +-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\( +diff --git a/source4/kdc/db-glue.c b/source4/kdc/db-glue.c +index 073ec83c8cf..cfa2097acbd 100644 +--- a/source4/kdc/db-glue.c ++++ b/source4/kdc/db-glue.c +@@ -769,15 +769,19 @@ static int principal_comp_strcmp_int(krb5_context context, + bool do_strcasecmp) + { + const char *p; +- size_t len; + + #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) + p = krb5_principal_get_comp_string(context, principal, component); + if (p == NULL) { + return -1; + } +- len = strlen(p); ++ if (do_strcasecmp) { ++ return strcasecmp(p, string); ++ } else { ++ return strcmp(p, string); ++ } + #else ++ size_t len; + krb5_data *d; + if (component >= krb5_princ_size(context, principal)) { + return -1; +@@ -789,13 +793,26 @@ static int principal_comp_strcmp_int(krb5_context context, + } + + p = d->data; +- len = d->length; +-#endif ++ ++ len = strlen(string); ++ ++ /* ++ * We explicitly return -1 or 1. Subtracting of the two lengths might ++ * give the wrong result if the result overflows or loses data when ++ * narrowed to int. ++ */ ++ if (d->length < len) { ++ return -1; ++ } else if (d->length > len) { ++ return 1; ++ } ++ + if (do_strcasecmp) { + return strncasecmp(p, string, len); + } else { +- return strncmp(p, string, len); ++ return memcmp(p, string, len); + } ++#endif + } + + static int principal_comp_strcasecmp(krb5_context context, +-- +2.25.1 + + +From 4b0304ab670a5dc3819f93633c190f722e3906d7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:36:30 +1200 +Subject: [PATCH 89/99] CVE-2022-32744 s4:kdc: Rename keytab_name -> + kpasswd_keytab_name + +This makes explicitly clear the purpose of this keytab. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed conflicts due to lacking HDBGET support] +--- + source4/kdc/kdc-heimdal.c | 4 ++-- + source4/kdc/kdc-server.h | 2 +- + source4/kdc/kdc-service-mit.c | 4 ++-- + source4/kdc/kpasswd-service.c | 2 +- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c +index ce32d3cb1b3..ca202bd6f9d 100644 +--- a/source4/kdc/kdc-heimdal.c ++++ b/source4/kdc/kdc-heimdal.c +@@ -444,8 +444,8 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd) + return; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "kdc: Failed to set keytab name", + true); +diff --git a/source4/kdc/kdc-server.h b/source4/kdc/kdc-server.h +index fd883c2e4b4..89b30f122f5 100644 +--- a/source4/kdc/kdc-server.h ++++ b/source4/kdc/kdc-server.h +@@ -40,7 +40,7 @@ struct kdc_server { + struct ldb_context *samdb; + bool am_rodc; + uint32_t proxy_timeout; +- const char *keytab_name; ++ const char *kpasswd_keytab_name; + void *private_data; + }; + +diff --git a/source4/kdc/kdc-service-mit.c b/source4/kdc/kdc-service-mit.c +index 5d4180aa7cc..22663b6ecc8 100644 +--- a/source4/kdc/kdc-service-mit.c ++++ b/source4/kdc/kdc-service-mit.c +@@ -291,8 +291,8 @@ NTSTATUS mitkdc_task_init(struct task_server *task) + return NT_STATUS_INTERNAL_ERROR; + } + +- kdc->keytab_name = talloc_asprintf(kdc, "KDB:"); +- if (kdc->keytab_name == NULL) { ++ kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "KDB:"); ++ if (kdc->kpasswd_keytab_name == NULL) { + task_server_terminate(task, + "KDC: Out of memory", + true); +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index 379ddebf3ad..aec30850173 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -170,7 +170,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, +- kdc->keytab_name, ++ kdc->kpasswd_keytab_name, + CRED_SPECIFIED); + if (rv != 0) { + DBG_ERR("Failed to set credentials keytab name\n"); +-- +2.25.1 + + +From faa0a83813d7e24016381da5a4b8c7f664d95acc Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 8 Jun 2022 13:53:29 +1200 +Subject: [PATCH 90/99] s4:kdc: Remove kadmin mode from HDB plugin + +It appears we no longer require it. + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/kdc/hdb-samba4-plugin.c | 35 +++++++-------------------------- + 1 file changed, 7 insertions(+), 28 deletions(-) + +diff --git a/source4/kdc/hdb-samba4-plugin.c b/source4/kdc/hdb-samba4-plugin.c +index 6f76124995d..4b90a766f76 100644 +--- a/source4/kdc/hdb-samba4-plugin.c ++++ b/source4/kdc/hdb-samba4-plugin.c +@@ -21,40 +21,20 @@ + + #include "includes.h" + #include "kdc/kdc-glue.h" +-#include "kdc/db-glue.h" +-#include "lib/util/samba_util.h" + #include "lib/param/param.h" +-#include "source4/lib/events/events.h" + + static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, const char *arg) + { + NTSTATUS nt_status; +- void *ptr; +- struct samba_kdc_base_context *base_ctx; +- +- if (sscanf(arg, "&%p", &ptr) == 1) { +- base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); +- } else if (arg[0] == '\0' || file_exist(arg)) { +- /* This mode for use in kadmin, rather than in Samba */ +- +- setup_logging("hdb_samba4", DEBUG_DEFAULT_STDERR); +- +- base_ctx = talloc_zero(NULL, struct samba_kdc_base_context); +- if (!base_ctx) { +- return ENOMEM; +- } +- +- base_ctx->ev_ctx = s4_event_context_init(base_ctx); +- base_ctx->lp_ctx = loadparm_init_global(false); +- if (arg[0]) { +- lpcfg_load(base_ctx->lp_ctx, arg); +- } else { +- lpcfg_load_default(base_ctx->lp_ctx); +- } +- } else { ++ void *ptr = NULL; ++ struct samba_kdc_base_context *base_ctx = NULL; ++ ++ if (sscanf(arg, "&%p", &ptr) != 1) { + return EINVAL; + } + ++ base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); ++ + /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ + nt_status = hdb_samba4_create_kdc(base_ctx, context, db); + +@@ -90,8 +70,7 @@ static void hdb_samba4_fini(void *ctx) + + /* Only used in the hdb-backed keytab code + * for a keytab of 'samba4&
' or samba4, to find +- * kpasswd's key in the main DB, and to +- * copy all the keys into a file (libnet_keytab_export) ++ * kpasswd's key in the main DB + * + * The
is the string form of a pointer to a talloced struct hdb_samba_context + */ +-- +2.25.1 + + +From e21efbabccbf9c422347e9e94b3f217186556ee7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 26 May 2022 16:39:20 +1200 +Subject: [PATCH 91/99] CVE-2022-32744 s4:kdc: Modify HDB plugin to only look + up kpasswd principal + +This plugin is now only used by the kpasswd service. Thus, ensuring we +only look up the kadmin/changepw principal means we can't be fooled into +accepting tickets for other service principals. We make sure not to +specify a specific kvno, to ensure that we do not accept RODC-issued +tickets. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Renamed entry to entry_ex; fixed knownfail conflicts; + retained knownfail for test_kpasswd_from_rodc which now causes the KDC + to panic] +--- + selftest/knownfail_heimdal_kdc | 3 -- + source4/kdc/hdb-samba4-plugin.c | 2 +- + source4/kdc/hdb-samba4.c | 66 +++++++++++++++++++++++++++++++++ + source4/kdc/kdc-glue.h | 3 ++ + 4 files changed, 70 insertions(+), 4 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index dfe04dd1448..1b5063d2630 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -113,6 +113,3 @@ + # Kpasswd tests + # + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/kdc/hdb-samba4-plugin.c b/source4/kdc/hdb-samba4-plugin.c +index 4b90a766f76..dba25e825de 100644 +--- a/source4/kdc/hdb-samba4-plugin.c ++++ b/source4/kdc/hdb-samba4-plugin.c +@@ -36,7 +36,7 @@ static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, + base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context); + + /* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */ +- nt_status = hdb_samba4_create_kdc(base_ctx, context, db); ++ nt_status = hdb_samba4_kpasswd_create_kdc(base_ctx, context, db); + + if (NT_STATUS_IS_OK(nt_status)) { + return 0; +diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c +index 43e836f8360..a8aae50b5b0 100644 +--- a/source4/kdc/hdb-samba4.c ++++ b/source4/kdc/hdb-samba4.c +@@ -136,6 +136,47 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db, + return code; + } + ++static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db, ++ krb5_const_principal _principal, ++ unsigned flags, ++ krb5_kvno _kvno, ++ hdb_entry_ex *entry_ex) ++{ ++ struct samba_kdc_db_context *kdc_db_ctx = NULL; ++ krb5_error_code ret; ++ krb5_principal kpasswd_principal = NULL; ++ ++ kdc_db_ctx = talloc_get_type_abort(db->hdb_db, ++ struct samba_kdc_db_context); ++ ++ ret = smb_krb5_make_principal(context, &kpasswd_principal, ++ lpcfg_realm(kdc_db_ctx->lp_ctx), ++ "kadmin", "changepw", ++ NULL); ++ if (ret) { ++ return ret; ++ } ++ smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST); ++ ++ /* ++ * For the kpasswd service, always ensure we get the latest kvno. This ++ * also means we (correctly) refuse RODC-issued tickets. ++ */ ++ flags &= ~HDB_F_KVNO_SPECIFIED; ++ ++ /* Don't bother looking up a client or krbtgt. */ ++ flags &= ~(SDB_F_GET_CLIENT|SDB_F_GET_KRBTGT); ++ ++ ret = hdb_samba4_fetch_kvno(context, db, ++ kpasswd_principal, ++ flags, ++ 0, ++ entry_ex); ++ ++ krb5_free_principal(context, kpasswd_principal); ++ return ret; ++} ++ + static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags, + hdb_entry_ex *entry) + { +@@ -194,6 +235,14 @@ static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigne + return ret; + } + ++static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db, ++ unsigned flags, ++ hdb_entry_ex *entry) ++{ ++ DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n"); ++ smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab"); ++} ++ + static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db) + { + talloc_free(db); +@@ -522,3 +571,20 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, + + return NT_STATUS_OK; + } ++ ++NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, ++ krb5_context context, struct HDB **db) ++{ ++ NTSTATUS nt_status; ++ ++ nt_status = hdb_samba4_create_kdc(base_ctx, context, db); ++ if (!NT_STATUS_IS_OK(nt_status)) { ++ return nt_status; ++ } ++ ++ (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno; ++ (*db)->hdb_firstkey = hdb_samba4_nextkey_panic; ++ (*db)->hdb_nextkey = hdb_samba4_nextkey_panic; ++ ++ return NT_STATUS_OK; ++} +diff --git a/source4/kdc/kdc-glue.h b/source4/kdc/kdc-glue.h +index c083b8c6429..ff8684e1666 100644 +--- a/source4/kdc/kdc-glue.h ++++ b/source4/kdc/kdc-glue.h +@@ -45,6 +45,9 @@ kdc_code kpasswdd_process(struct kdc_server *kdc, + NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx, + krb5_context context, struct HDB **db); + ++NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx, ++ krb5_context context, struct HDB **db); ++ + /* from kdc-glue.c */ + int kdc_check_pac(krb5_context krb5_context, + DATA_BLOB server_sig, +-- +2.25.1 + + +From b64e1b4a510c81628feeb68af75afd3275ea75c3 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 30 May 2022 19:16:02 +1200 +Subject: [PATCH 92/99] CVE-2022-32744 s4:kpasswd: Ensure we pass the kpasswd + server principal into krb5_rd_req_ctx() + +To ensure that, when decrypting the kpasswd ticket, we look up the +correct principal and don't trust the sname from the ticket, we should +pass the principal name of the kpasswd service into krb5_rd_req_ctx(). +However, gensec_krb5_update_internal() will pass in NULL unless the +principal in our credentials is CRED_SPECIFIED. + +At present, our principal will be considered obtained as CRED_SMB_CONF +(from the cli_credentials_set_conf() a few lines up), so we explicitly +set the realm again, but this time as CRED_SPECIFIED. Now the value of +server_in_keytab that we provide to smb_krb5_rd_req_decoded() will not +be NULL. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Removed knownfail as KDC no longer panics] +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 2 -- + source4/kdc/kpasswd-service.c | 30 ++++++++++++++++++++++++++++++ + 3 files changed, 30 insertions(+), 6 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 1b5063d2630..692b9ecdd72 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -109,7 +109,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-# +-# Kpasswd tests +-# +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index ed8f7069319..6cad47701ae 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -547,5 +547,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc +diff --git a/source4/kdc/kpasswd-service.c b/source4/kdc/kpasswd-service.c +index aec30850173..d2f1bb02906 100644 +--- a/source4/kdc/kpasswd-service.c ++++ b/source4/kdc/kpasswd-service.c +@@ -29,6 +29,7 @@ + #include "kdc/kdc-server.h" + #include "kdc/kpasswd-service.h" + #include "kdc/kpasswd-helper.h" ++#include "param/param.h" + + #define HEADER_LEN 6 + #ifndef RFC3244_VERSION +@@ -161,6 +162,20 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + goto done; + } + ++ /* ++ * After calling cli_credentials_set_conf(), explicitly set the realm ++ * with CRED_SPECIFIED. We need to do this so the result of ++ * principal_from_credentials() called from the gensec layer is ++ * CRED_SPECIFIED rather than CRED_SMB_CONF, avoiding a fallback to ++ * match-by-key (very undesirable in this case). ++ */ ++ ok = cli_credentials_set_realm(server_credentials, ++ lpcfg_realm(kdc->task->lp_ctx), ++ CRED_SPECIFIED); ++ if (!ok) { ++ goto done; ++ } ++ + ok = cli_credentials_set_username(server_credentials, + "kadmin/changepw", + CRED_SPECIFIED); +@@ -168,6 +183,21 @@ kdc_code kpasswd_process(struct kdc_server *kdc, + goto done; + } + ++ /* Check that the server principal is indeed CRED_SPECIFIED. */ ++ { ++ char *principal = NULL; ++ enum credentials_obtained obtained; ++ ++ principal = cli_credentials_get_principal_and_obtained(server_credentials, ++ tmp_ctx, ++ &obtained); ++ if (obtained < CRED_SPECIFIED) { ++ goto done; ++ } ++ ++ TALLOC_FREE(principal); ++ } ++ + rv = cli_credentials_set_keytab_name(server_credentials, + kdc->task->lp_ctx, + kdc->kpasswd_keytab_name, +-- +2.25.1 + + +From 22bd1bc2d7308167ea316c6b48f130d378ab4c8b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:17:11 +1200 +Subject: [PATCH 93/99] CVE-2022-2031 tests/krb5: Add test that we cannot + provide a TGT to kpasswd + +The kpasswd service should require a kpasswd service ticket, and +disallow TGTs. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Fixed knownfail conflicts] +--- + python/samba/tests/krb5/kpasswd_tests.py | 28 ++++++++++++++++++++++++ + selftest/knownfail_heimdal_kdc | 4 ++++ + selftest/knownfail_mit_kdc | 4 ++++ + 3 files changed, 36 insertions(+) + +diff --git a/python/samba/tests/krb5/kpasswd_tests.py b/python/samba/tests/krb5/kpasswd_tests.py +index 3a6c7d818dc..0db857f7bbd 100755 +--- a/python/samba/tests/krb5/kpasswd_tests.py ++++ b/python/samba/tests/krb5/kpasswd_tests.py +@@ -31,6 +31,7 @@ from samba.tests.krb5.rfc4120_constants import ( + KDC_ERR_TGT_REVOKED, + KDC_ERR_TKT_EXPIRED, + KPASSWD_ACCESSDENIED, ++ KPASSWD_AUTHERROR, + KPASSWD_HARDERROR, + KPASSWD_INITIAL_FLAG_NEEDED, + KPASSWD_MALFORMED, +@@ -779,6 +780,33 @@ class KpasswdTests(KDCBaseTest): + self._make_tgs_request(creds, service_creds, ticket, + expect_error=False) + ++ # Show that we cannot provide a TGT to kpasswd to change the password. ++ def test_kpasswd_tgt(self): ++ # Create an account for testing, and get a TGT. ++ creds = self._get_creds() ++ tgt = self.get_tgt(creds) ++ ++ # Change the sname of the ticket to match that of kadmin/changepw. ++ tgt.set_sname(self.get_kpasswd_sname()) ++ ++ expected_code = KPASSWD_AUTHERROR ++ expected_msg = b'A TGT may not be used as a ticket to kpasswd' ++ ++ # Set the password. ++ new_password = generate_random_password(32, 32) ++ self.kpasswd_exchange(tgt, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.SET) ++ ++ # Change the password. ++ self.kpasswd_exchange(tgt, ++ new_password, ++ expected_code, ++ expected_msg, ++ mode=self.KpasswdMode.CHANGE) ++ + # Test that kpasswd rejects requests with a service ticket. + def test_kpasswd_non_initial(self): + # Create an account for testing, and get a TGT. +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 692b9ecdd72..7b439478eca 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -109,3 +109,7 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting ++# ++# Kpasswd tests ++# ++^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 6cad47701ae..7e0cdd9a3b7 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -547,3 +547,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc ++# ++# Kpasswd tests ++# ++samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +-- +2.25.1 + + +From be9945a4d8e774e8255dd9ae0ed29c9a953ce3ff Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:07 +1200 +Subject: [PATCH 94/99] CVE-2022-2031 auth: Add ticket type field to + auth_user_info_dc and auth_session_info + +This field may be used to convey whether we were provided with a TGT or +a non-TGT. We ensure both structures are zeroed out to avoid incorrect +results being produced by an uninitialised field. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + auth/auth_sam_reply.c | 2 +- + auth/auth_util.c | 2 +- + librpc/idl/auth.idl | 23 +++++++++++++++++++++++ + source4/auth/ntlm/auth_developer.c | 2 +- + source4/auth/sam.c | 2 +- + source4/auth/session.c | 2 ++ + source4/auth/system_session.c | 6 +++--- + 7 files changed, 32 insertions(+), 7 deletions(-) + +diff --git a/auth/auth_sam_reply.c b/auth/auth_sam_reply.c +index b5b6362dc93..2e27e5715d1 100644 +--- a/auth/auth_sam_reply.c ++++ b/auth/auth_sam_reply.c +@@ -416,7 +416,7 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx, + return NT_STATUS_INVALID_LEVEL; + } + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* +diff --git a/auth/auth_util.c b/auth/auth_util.c +index fe01babd107..ec9094d0f15 100644 +--- a/auth/auth_util.c ++++ b/auth/auth_util.c +@@ -44,7 +44,7 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx, + return NULL; + } + +- dst = talloc(mem_ctx, struct auth_session_info); ++ dst = talloc_zero(mem_ctx, struct auth_session_info); + if (dst == NULL) { + DBG_ERR("talloc failed\n"); + TALLOC_FREE(frame); +diff --git a/librpc/idl/auth.idl b/librpc/idl/auth.idl +index 7de3d4c6bfb..59ed2c3c5ea 100644 +--- a/librpc/idl/auth.idl ++++ b/librpc/idl/auth.idl +@@ -75,6 +75,26 @@ interface auth + [unique,charset(UTF8),string] char *sanitized_username; + } auth_user_info_unix; + ++ /* ++ * If the user was authenticated with a Kerberos ticket, this indicates ++ * the type of the ticket; TGT, or non-TGT (i.e. service ticket). If ++ * unset, the type is unknown. This indicator is useful for the KDC and ++ * the kpasswd service, which share the same account and keys. By ++ * ensuring it is provided with the appopriate ticket type, each service ++ * avoids accepting a ticket meant for the other. ++ * ++ * The heuristic used to determine the type is the presence or absence ++ * of a REQUESTER_SID buffer in the PAC; we use its presence to assume ++ * we have a TGT. This heuristic will fail for older Samba versions and ++ * Windows prior to Nov. 2021 updates, which lack support for this ++ * buffer. ++ */ ++ typedef enum { ++ TICKET_TYPE_UNKNOWN = 0, ++ TICKET_TYPE_TGT = 1, ++ TICKET_TYPE_NON_TGT = 2 ++ } ticket_type; ++ + /* This is the interim product of the auth subsystem, before + * privileges and local groups are handled */ + typedef [public] struct { +@@ -83,6 +103,7 @@ interface auth + auth_user_info *info; + [noprint] DATA_BLOB user_session_key; + [noprint] DATA_BLOB lm_session_key; ++ ticket_type ticket_type; + } auth_user_info_dc; + + typedef [public] struct { +@@ -112,6 +133,8 @@ interface auth + * We generate this in auth_generate_session_info() + */ + GUID unique_session_token; ++ ++ ticket_type ticket_type; + } auth_session_info; + + typedef [public] struct { +diff --git a/source4/auth/ntlm/auth_developer.c b/source4/auth/ntlm/auth_developer.c +index 1823989c68d..6e92252d5c5 100644 +--- a/source4/auth/ntlm/auth_developer.c ++++ b/source4/auth/ntlm/auth_developer.c +@@ -76,7 +76,7 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx, + } + NT_STATUS_NOT_OK_RETURN(nt_status); + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +diff --git a/source4/auth/sam.c b/source4/auth/sam.c +index 8b233bab3ad..7c609655fcb 100644 +--- a/source4/auth/sam.c ++++ b/source4/auth/sam.c +@@ -363,7 +363,7 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx, + TALLOC_CTX *tmp_ctx; + struct ldb_message_element *el; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + tmp_ctx = talloc_new(user_info_dc); +diff --git a/source4/auth/session.c b/source4/auth/session.c +index 8cf8670d848..34ad557eebb 100644 +--- a/source4/auth/session.c ++++ b/source4/auth/session.c +@@ -222,6 +222,8 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx, + + session_info->credentials = NULL; + ++ session_info->ticket_type = user_info_dc->ticket_type; ++ + talloc_steal(mem_ctx, session_info); + *_session_info = session_info; + talloc_free(tmp_ctx); +diff --git a/source4/auth/system_session.c b/source4/auth/system_session.c +index e46b4584817..17cfc4bab8b 100644 +--- a/source4/auth/system_session.c ++++ b/source4/auth/system_session.c +@@ -119,7 +119,7 @@ NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +@@ -195,7 +195,7 @@ static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx, + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; + +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + user_info_dc->num_sids = 7; +@@ -364,7 +364,7 @@ _PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx, + { + struct auth_user_info_dc *user_info_dc; + struct auth_user_info *info; +- user_info_dc = talloc(mem_ctx, struct auth_user_info_dc); ++ user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc); + NT_STATUS_HAVE_NO_MEMORY(user_info_dc); + + /* This returns a pointer to a struct dom_sid, which is the +-- +2.25.1 + + +From b7e3cb83005ef28c70dc8d64cd0a57ba80ae9f4e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:35 +1200 +Subject: [PATCH 95/99] CVE-2022-2031 s4:auth: Use PAC to determine whether + ticket is a TGT + +We use the presence or absence of a REQUESTER_SID PAC buffer to +determine whether the ticket is a TGT. We will later use this to reject +TGTs where a service ticket is expected. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider +--- + source4/auth/kerberos/kerberos_pac.c | 44 ++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c +index 54ef4d61b02..bd0ae20e007 100644 +--- a/source4/auth/kerberos/kerberos_pac.c ++++ b/source4/auth/kerberos/kerberos_pac.c +@@ -282,6 +282,28 @@ + return ret; + } + ++static krb5_error_code kerberos_pac_buffer_present(krb5_context context, ++ const krb5_pac pac, ++ uint32_t type) ++{ ++#ifdef SAMBA4_USES_HEIMDAL ++ return krb5_pac_get_buffer(context, pac, type, NULL); ++#else /* MIT */ ++ krb5_error_code ret; ++ krb5_data data; ++ ++ /* ++ * MIT won't let us pass NULL for the data parameter, so we are forced ++ * to allocate a new buffer and then immediately free it. ++ */ ++ ret = krb5_pac_get_buffer(context, pac, type, &data); ++ if (ret == 0) { ++ krb5_free_data_contents(context, &data); ++ } ++ return ret; ++#endif /* SAMBA4_USES_HEIMDAL */ ++} ++ + krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + krb5_pac pac, + krb5_context context, +@@ -414,6 +436,28 @@ krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx, + return EINVAL; + } + } ++ ++ /* ++ * Based on the presence of a REQUESTER_SID PAC buffer, ascertain ++ * whether the ticket is a TGT. This helps the KDC and kpasswd service ++ * ensure they do not accept tickets meant for the other. ++ * ++ * This heuristic will fail for older Samba versions and Windows prior ++ * to Nov. 2021 updates, which lack support for the REQUESTER_SID PAC ++ * buffer. ++ */ ++ ret = kerberos_pac_buffer_present(context, pac, PAC_TYPE_REQUESTER_SID); ++ if (ret == ENOENT) { ++ /* This probably isn't a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_NON_TGT; ++ } else if (ret != 0) { ++ talloc_free(tmp_ctx); ++ return ret; ++ } else { ++ /* This probably is a TGT. */ ++ user_info_dc_out->ticket_type = TICKET_TYPE_TGT; ++ } ++ + *user_info_dc = user_info_dc_out; + + return 0; +-- +2.25.1 + + +From 63d353e7b5ef235a86bf6df595951dc831108234 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 10 Jun 2022 19:18:53 +1200 +Subject: [PATCH 96/99] CVE-2022-2031 s4:kpasswd: Do not accept TGTs as kpasswd + tickets + +If TGTs can be used as kpasswd tickets, the two-minute lifetime of a +authentic kpasswd ticket may be bypassed. Furthermore, kpasswd tickets +are not supposed to be cached, but using this flaw, a stolen credentials +cache containing a TGT may be used to change that account's password, +and thus is made more valuable to an attacker. + +Since all TGTs should be issued with a REQUESTER_SID PAC buffer, and +service tickets without it, we assert the absence of this buffer to +ensure we're not accepting a TGT. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049 + +Signed-off-by: Joseph Sutton +Reviewed-by: Andreas Schneider + +[jsutton@samba.org Fixed knownfail conflicts] + +[jsutton@samba.org Fixed knownfail conflicts] +--- + selftest/knownfail_heimdal_kdc | 4 ---- + selftest/knownfail_mit_kdc | 4 ---- + source4/kdc/kpasswd-helper.c | 20 ++++++++++++++++++++ + source4/kdc/kpasswd-helper.h | 2 ++ + source4/kdc/kpasswd-service-heimdal.c | 13 +++++++++++++ + source4/kdc/kpasswd-service-mit.c | 13 +++++++++++++ + 6 files changed, 48 insertions(+), 8 deletions(-) + +diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc +index 7b439478eca..692b9ecdd72 100644 +--- a/selftest/knownfail_heimdal_kdc ++++ b/selftest/knownfail_heimdal_kdc +@@ -109,7 +109,3 @@ + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing + ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting +-# +-# Kpasswd tests +-# +-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc +index 7e0cdd9a3b7..6cad47701ae 100644 +--- a/selftest/knownfail_mit_kdc ++++ b/selftest/knownfail_mit_kdc +@@ -547,7 +547,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc + ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc +-# +-# Kpasswd tests +-# +-samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc +diff --git a/source4/kdc/kpasswd-helper.c b/source4/kdc/kpasswd-helper.c +index 55a2f5b3bf6..2ffdb79aea5 100644 +--- a/source4/kdc/kpasswd-helper.c ++++ b/source4/kdc/kpasswd-helper.c +@@ -241,3 +241,23 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + + return status; + } ++ ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string) ++{ ++ switch(session_info->ticket_type) { ++ case TICKET_TYPE_TGT: ++ /* TGTs are disallowed here. */ ++ *error_string = "A TGT may not be used as a ticket to kpasswd"; ++ return KRB5_KPASSWD_AUTHERROR; ++ case TICKET_TYPE_NON_TGT: ++ /* Non-TGTs are permitted, and expected. */ ++ break; ++ default: ++ /* In case we forgot to set the type. */ ++ *error_string = "Failed to ascertain that ticket to kpasswd is not a TGT"; ++ return KRB5_KPASSWD_HARDERROR; ++ } ++ ++ return 0; ++} +diff --git a/source4/kdc/kpasswd-helper.h b/source4/kdc/kpasswd-helper.h +index 8fad81e0a5d..94a6e2acfdd 100644 +--- a/source4/kdc/kpasswd-helper.h ++++ b/source4/kdc/kpasswd-helper.h +@@ -43,4 +43,6 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx, + enum samPwdChangeReason *reject_reason, + struct samr_DomInfo1 **dominfo); + ++krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info, ++ const char **error_string); + #endif /* _KPASSWD_HELPER_H */ +diff --git a/source4/kdc/kpasswd-service-heimdal.c b/source4/kdc/kpasswd-service-heimdal.c +index a0352d1ad35..4d009b9eb24 100644 +--- a/source4/kdc/kpasswd-service-heimdal.c ++++ b/source4/kdc/kpasswd-service-heimdal.c +@@ -253,6 +253,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -264,6 +265,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case KRB5_KPASSWD_VERS_CHANGEPW: { + DATA_BLOB password = data_blob_null; +diff --git a/source4/kdc/kpasswd-service-mit.c b/source4/kdc/kpasswd-service-mit.c +index de4c6f3f622..6b051567b6e 100644 +--- a/source4/kdc/kpasswd-service-mit.c ++++ b/source4/kdc/kpasswd-service-mit.c +@@ -332,6 +332,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + { + struct auth_session_info *session_info; + NTSTATUS status; ++ krb5_error_code code; + + status = gensec_session_info(gensec_security, + mem_ctx, +@@ -344,6 +345,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc, + return KRB5_KPASSWD_HARDERROR; + } + ++ /* ++ * Since the kpasswd service shares its keys with the krbtgt, we might ++ * have received a TGT rather than a kpasswd ticket. We need to check ++ * the ticket type to ensure that TGTs cannot be misused in this manner. ++ */ ++ code = kpasswd_check_non_tgt(session_info, ++ error_string); ++ if (code != 0) { ++ DBG_WARNING("%s\n", *error_string); ++ return code; ++ } ++ + switch(verno) { + case 1: { + DATA_BLOB password; +-- +2.25.1 + + +From 185a6d12935f55ad996de502e416114cc1f5aba0 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 23 Jun 2022 13:59:11 +1200 +Subject: [PATCH 97/99] CVE-2022-2031 testprogs: Add test for short-lived + ticket across an incoming trust + +We ensure that the KDC does not reject a TGS-REQ with our short-lived +TGT over an incoming trust. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047 + +Signed-off-by: Joseph Sutton +--- + testprogs/blackbox/test_kinit_trusts_heimdal.sh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/testprogs/blackbox/test_kinit_trusts_heimdal.sh b/testprogs/blackbox/test_kinit_trusts_heimdal.sh +index 52b1ac6589c..29ea1c510ce 100755 +--- a/testprogs/blackbox/test_kinit_trusts_heimdal.sh ++++ b/testprogs/blackbox/test_kinit_trusts_heimdal.sh +@@ -55,6 +55,10 @@ testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppa + test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" --use-krb5-ccache=$KRB5CCNAME || failed=`expr $failed + 1` + rm -rf $KRB5CCNAME_PATH + ++testit "kinit with password and two minute lifetime" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac --server=krbtgt/$REALM@$TRUST_REALM --lifetime=2m $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` ++test_smbclient "Test login with user kerberos ccache and two minute lifetime" 'ls' "$unc" --use-krb5-ccache=$KRB5CCNAME || failed=`expr $failed + 1` ++rm -rf $KRB5CCNAME_PATH ++ + # Test with smbclient4 + smbclient="$samba4bindir/smbclient4" + testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` +@@ -95,5 +99,5 @@ testit "wbinfo check outgoing trust pw" $VALGRIND $wbinfo --check-secret --domai + + test_smbclient "Test user login with the changed outgoing secret" 'ls' "$unc" --use-kerberos=required -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1` + +-rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache ++rm -f $PREFIX/tmpccache $PREFIX/tmppassfile + exit $failed +-- +2.25.1 diff --git a/backport-CVE-2022-32742.patch b/backport-CVE-2022-32742.patch new file mode 100644 index 0000000..049d0c9 --- /dev/null +++ b/backport-CVE-2022-32742.patch @@ -0,0 +1,216 @@ +From d6aef6838a674ab95ff9172f4ac67707667f9e00 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Tue, 7 Jun 2022 09:40:45 -0700 +Subject: [PATCH 98/99] CVE-2022-32742: s4: torture: Add raw.write.bad-write + test. + +Reproduces the test code in: + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Add knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 + + source4/torture/raw/write.c | 89 ++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + create mode 100644 selftest/knownfail.d/bad-write + +diff --git a/selftest/knownfail.d/bad-write b/selftest/knownfail.d/bad-write +new file mode 100644 +index 00000000000..5fc16606a13 +--- /dev/null ++++ b/selftest/knownfail.d/bad-write +@@ -0,0 +1,2 @@ ++^samba3.raw.write.bad-write\(nt4_dc_smb1\) ++^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git a/source4/torture/raw/write.c b/source4/torture/raw/write.c +index 0a2f50f425b..661485bb548 100644 +--- a/source4/torture/raw/write.c ++++ b/source4/torture/raw/write.c +@@ -25,6 +25,7 @@ + #include "libcli/libcli.h" + #include "torture/util.h" + #include "torture/raw/proto.h" ++#include "libcli/raw/raw_proto.h" + + #define CHECK_STATUS(status, correct) do { \ + if (!NT_STATUS_EQUAL(status, correct)) { \ +@@ -694,6 +695,93 @@ done: + return ret; + } + ++/* ++ test a deliberately bad SMB1 write. ++*/ ++static bool test_bad_write(struct torture_context *tctx, ++ struct smbcli_state *cli) ++{ ++ bool ret = false; ++ int fnum = -1; ++ struct smbcli_request *req = NULL; ++ const char *fname = BASEDIR "\\badwrite.txt"; ++ bool ok = false; ++ ++ if (!torture_setup_dir(cli, BASEDIR)) { ++ torture_fail(tctx, "failed to setup basedir"); ++ } ++ ++ torture_comment(tctx, "Testing RAW_BAD_WRITE\n"); ++ ++ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); ++ if (fnum == -1) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Failed to create %s - %s\n", ++ fname, ++ smbcli_errstr(cli->tree))); ++ } ++ ++ req = smbcli_request_setup(cli->tree, ++ SMBwrite, ++ 5, ++ 0); ++ if (req == NULL) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "talloc fail\n")); ++ } ++ ++ SSVAL(req->out.vwv, VWV(0), fnum); ++ SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */ ++ SIVAL(req->out.vwv, VWV(2), 0); /* offset */ ++ SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */ ++ ++ if (!smbcli_request_send(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Send failed\n")); ++ } ++ ++ if (!smbcli_request_receive(req)) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, "Reveive failed\n")); ++ } ++ ++ /* ++ * Check for expected error codes. ++ * ntvfs returns NT_STATUS_UNSUCCESSFUL. ++ */ ++ ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) || ++ NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL)); ++ ++ if (!ok) { ++ torture_fail_goto(tctx, ++ done, ++ talloc_asprintf(tctx, ++ "Should have returned " ++ "NT_STATUS_INVALID_PARAMETER or " ++ "NT_STATUS_UNSUCCESSFUL " ++ "got %s\n", ++ nt_errstr(req->status))); ++ } ++ ++ ret = true; ++ ++done: ++ if (req != NULL) { ++ smbcli_request_destroy(req); ++ } ++ if (fnum != -1) { ++ smbcli_close(cli->tree, fnum); ++ } ++ smb_raw_exit(cli->session); ++ smbcli_deltree(cli->tree, BASEDIR); ++ return ret; ++} ++ + /* + basic testing of write calls + */ +@@ -705,6 +793,7 @@ struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx) + torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock); + torture_suite_add_1smb_test(suite, "write close", test_writeclose); + torture_suite_add_1smb_test(suite, "writex", test_writex); ++ torture_suite_add_1smb_test(suite, "bad-write", test_bad_write); + + return suite; + } +-- +2.25.1 + + +From a4707e4a955d01edf493cd0d7ab8b1ecb4ca7991 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Wed, 8 Jun 2022 13:50:51 -0700 +Subject: [PATCH 99/99] CVE-2022-32742: s3: smbd: Harden the smbreq_bufrem() + macro. + +Fixes the raw.write.bad-write test. + +NB. We need the two (==0) changes in source3/smbd/reply.c +as the gcc optimizer now knows that the return from +smbreq_bufrem() can never be less than zero. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085 + +Remove knownfail. + +Signed-off-by: Jeremy Allison +Reviewed-by: David Disseldorp +--- + selftest/knownfail.d/bad-write | 2 -- + source3/include/smb_macros.h | 2 +- + source3/smbd/reply.c | 4 ++-- + 3 files changed, 3 insertions(+), 5 deletions(-) + delete mode 100644 selftest/knownfail.d/bad-write + +diff --git a/selftest/knownfail.d/bad-write b/selftest/knownfail.d/bad-write +deleted file mode 100644 +index 5fc16606a13..00000000000 +--- a/selftest/knownfail.d/bad-write ++++ /dev/null +@@ -1,2 +0,0 @@ +-^samba3.raw.write.bad-write\(nt4_dc_smb1\) +-^samba3.raw.write.bad-write\(ad_dc_smb1\) +diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h +index ba2c76764d1..9f1d00835d7 100644 +--- a/source3/include/smb_macros.h ++++ b/source3/include/smb_macros.h +@@ -152,7 +152,7 @@ + + /* the remaining number of bytes in smb buffer 'buf' from pointer 'p'. */ + #define smb_bufrem(buf, p) (smb_buflen(buf)-PTR_DIFF(p, smb_buf(buf))) +-#define smbreq_bufrem(req, p) (req->buflen - PTR_DIFF(p, req->buf)) ++#define smbreq_bufrem(req, p) ((req)->buflen < PTR_DIFF((p), (req)->buf) ? 0 : (req)->buflen - PTR_DIFF((p), (req)->buf)) + + + /* Note that chain_size must be available as an extern int to this macro. */ +diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c +index 879d5b2ae21..88c62b891ae 100644 +--- a/source3/smbd/reply.c ++++ b/source3/smbd/reply.c +@@ -344,7 +344,7 @@ size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + *err = NT_STATUS_INVALID_PARAMETER; + return 0; + } +@@ -382,7 +382,7 @@ size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req, + { + ssize_t bufrem = smbreq_bufrem(req, src); + +- if (bufrem < 0) { ++ if (bufrem == 0) { + return 0; + } + +-- +2.25.1 diff --git a/backport-CVE-2022-32745.patch b/backport-CVE-2022-32745.patch new file mode 100644 index 0000000..0bcdb25 --- /dev/null +++ b/backport-CVE-2022-32745.patch @@ -0,0 +1,163 @@ +From c231d424b89ba718262ed376431a982baaeef33f Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 17:03:10 +1300 +Subject: [PATCH 15/99] CVE-2022-32745 s4/dsdb/samldb: Check for empty values + array + +This avoids potentially trying to access the first element of an empty +array. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/samldb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c +index b89d93910fd..3ecbd00e68e 100644 +--- a/source4/dsdb/samdb/ldb_modules/samldb.c ++++ b/source4/dsdb/samdb/ldb_modules/samldb.c +@@ -751,7 +751,7 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac) + return ret; + } + +- if (el == NULL) { ++ if (el == NULL || el->num_values == 0) { + return LDB_SUCCESS; + } + +@@ -919,7 +919,7 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac) + return ret; + } + +- if (el == NULL) { ++ if (el == NULL || el->num_values == 0) { + return LDB_SUCCESS; + } + +-- +2.25.1 + + +From d2dbb3b6818d429b12d54e68510286d033d4abd7 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 17 Feb 2022 11:11:53 +1300 +Subject: [PATCH 16/99] CVE-2022-32745 s4/dsdb/util: Use correct value for loop + count limit + +Currently, we can crash the server by sending a large number of values +of a specific attribute (such as sAMAccountName) spread across a few +message elements. If val_count is larger than the total number of +elements, we get an access beyond the elements array. + +Similarly, we can include unrelated message elements prior to the +message elements of the attribute in question, so that not all of the +attribute's values are copied into the returned elements values array. +This can cause the server to access uninitialised data, likely resulting +in a crash or unexpected behaviour. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c +index 405febf0b3d..14947746837 100644 +--- a/source4/dsdb/samdb/ldb_modules/util.c ++++ b/source4/dsdb/samdb/ldb_modules/util.c +@@ -1546,7 +1546,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + + v = _el->values; + +- for (i = 0; i < val_count; i++) { ++ for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { + if ((operation == LDB_MODIFY) && + (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) +-- +2.25.1 + + +From d85bb9f5edc08ce2042be366c720dd027788f5bd Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Thu, 17 Feb 2022 11:13:38 +1300 +Subject: [PATCH 17/99] CVE-2022-32745 s4/dsdb/util: Don't call memcpy() with a + NULL pointer + +Doing so is undefined behaviour. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c +index 14947746837..35ae110b5ef 100644 +--- a/source4/dsdb/samdb/ldb_modules/util.c ++++ b/source4/dsdb/samdb/ldb_modules/util.c +@@ -1548,15 +1548,19 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + + for (i = 0; i < msg->num_elements; i++) { + if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) { ++ const struct ldb_message_element *tmp_el = &msg->elements[i]; + if ((operation == LDB_MODIFY) && +- (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) ++ (LDB_FLAG_MOD_TYPE(tmp_el->flags) + == LDB_FLAG_MOD_DELETE)) { + continue; + } ++ if (tmp_el->values == NULL || tmp_el->num_values == 0) { ++ continue; ++ } + memcpy(v, +- msg->elements[i].values, +- msg->elements[i].num_values); +- v += msg->elements[i].num_values; ++ tmp_el->values, ++ tmp_el->num_values); ++ v += tmp_el->num_values; + } + } + +-- +2.25.1 + + +From 6af497232e4ed24c33a29b77825fa854a73b5427 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 3 Jun 2022 16:16:31 +1200 +Subject: [PATCH 18/99] CVE-2022-32745 s4/dsdb/util: Correctly copy values into + message element + +To use memcpy(), we need to specify the number of bytes to copy, rather +than the number of ldb_val structures. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c +index 35ae110b5ef..e7fe8f855df 100644 +--- a/source4/dsdb/samdb/ldb_modules/util.c ++++ b/source4/dsdb/samdb/ldb_modules/util.c +@@ -1559,7 +1559,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx, + } + memcpy(v, + tmp_el->values, +- tmp_el->num_values); ++ tmp_el->num_values * sizeof(*v)); + v += tmp_el->num_values; + } + } +-- +2.25.1 + + diff --git a/backport-CVE-2022-32746.patch b/backport-CVE-2022-32746.patch new file mode 100644 index 0000000..9c25231 --- /dev/null +++ b/backport-CVE-2022-32746.patch @@ -0,0 +1,1854 @@ +From a258b3c0636b208de699b1e693d86f5ee9985cfd Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:09:53 +1200 +Subject: [PATCH 01/99] CVE-2022-32746 s4/dsdb/objectclass_attrs: Fix typo + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +index 6ab46a729a2..2a77353cdfc 100644 +--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c ++++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c +@@ -263,7 +263,7 @@ static int attr_handler(struct oc_context *ac) + LDB_CONTROL_AS_SYSTEM_OID); + if (!dsdb_module_am_system(ac->module) && !as_system) { + ldb_asprintf_errstring(ldb, +- "objectclass_attrs: attribute '%s' on entry '%s' must can only be modified as system", ++ "objectclass_attrs: attribute '%s' on entry '%s' can only be modified as system", + msg->elements[i].name, + ldb_dn_get_linearized(msg->dn)); + return LDB_ERR_CONSTRAINT_VIOLATION; +-- +2.25.1 + + +From e2ef0f299aed8c0f9660f1d7912472d23e81fee8 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 15:37:15 +1200 +Subject: [PATCH 02/99] CVE-2022-32746 s4:dsdb:tests: Add test for deleting a + disallowed SPN + +If an account has an SPN that requires Write Property to set, we should +still be able to delete it with just Validated Write. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + selftest/knownfail.d/acl-spn-delete | 1 + + source4/dsdb/tests/python/acl.py | 26 ++++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 selftest/knownfail.d/acl-spn-delete + +diff --git a/selftest/knownfail.d/acl-spn-delete b/selftest/knownfail.d/acl-spn-delete +new file mode 100644 +index 00000000000..32018413c49 +--- /dev/null ++++ b/selftest/knownfail.d/acl-spn-delete +@@ -0,0 +1 @@ ++^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\( +diff --git a/source4/dsdb/tests/python/acl.py b/source4/dsdb/tests/python/acl.py +index 70dca9b7678..3e5f7a44a79 100755 +--- a/source4/dsdb/tests/python/acl.py ++++ b/source4/dsdb/tests/python/acl.py +@@ -2285,6 +2285,32 @@ class AclSPNTests(AclTests): + else: + self.fail(f'able to add disallowed SPN {not_allowed_spn}') + ++ def test_delete_disallowed_spn(self): ++ # Grant Validated-SPN property. ++ mod = f'(OA;;SW;{security.GUID_DRS_VALIDATE_SPN};;{self.user_sid1})' ++ self.sd_utils.dacl_add_ace(self.computerdn, mod) ++ ++ spn_base = f'HOST/{self.computername}' ++ ++ not_allowed_spn = f'{spn_base}/{self.dcctx.get_domain_name()}' ++ ++ # Add a disallowed SPN as admin. ++ msg = Message(Dn(self.ldb_admin, self.computerdn)) ++ msg['servicePrincipalName'] = MessageElement(not_allowed_spn, ++ FLAG_MOD_ADD, ++ 'servicePrincipalName') ++ self.ldb_admin.modify(msg) ++ ++ # Ensure we are able to delete a disallowed SPN. ++ msg = Message(Dn(self.ldb_user1, self.computerdn)) ++ msg['servicePrincipalName'] = MessageElement(not_allowed_spn, ++ FLAG_MOD_DELETE, ++ 'servicePrincipalName') ++ try: ++ self.ldb_user1.modify(msg) ++ except LdbError: ++ self.fail(f'unable to delete disallowed SPN {not_allowed_spn}') ++ + + # tests SEC_ADS_LIST vs. SEC_ADS_LIST_OBJECT + @DynamicTestCase +-- +2.25.1 + + +From 6bc5e73000a639bab3c3d6789bdf879d5395bf9c Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:41:02 +1200 +Subject: [PATCH 03/99] CVE-2022-32746 s4/dsdb/partition: Fix LDB flags + comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(req_msg->elements[el_idx].flags & LDB_FLAG_MOD_MASK) != 0 + +which is true whenever any of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/partition.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c +index 2544a106d13..2d90ca5d1b3 100644 +--- a/source4/dsdb/samdb/ldb_modules/partition.c ++++ b/source4/dsdb/samdb/ldb_modules/partition.c +@@ -493,8 +493,8 @@ static int partition_copy_all_callback_action( + * them here too + */ + for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) { +- if (req_msg->elements[el_idx].flags & LDB_FLAG_MOD_DELETE +- || ((req_msg->elements[el_idx].flags & LDB_FLAG_MOD_REPLACE) && ++ if (LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_DELETE ++ || ((LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_REPLACE) && + req_msg->elements[el_idx].num_values == 0)) { + if (ldb_msg_find_element(modify_msg, + req_msg->elements[el_idx].name) != NULL) { +-- +2.25.1 + + +From 39371352d8fc1d3ab0dd2baeacebd9ce48b4ef02 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 14:49:51 +1200 +Subject: [PATCH 04/99] CVE-2022-32746 s4:torture: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set. Correct +the expression to what it was probably intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/torture/drs/rpc/dssync.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/source4/torture/drs/rpc/dssync.c b/source4/torture/drs/rpc/dssync.c +index f63e8a4ae7d..047bee116e9 100644 +--- a/source4/torture/drs/rpc/dssync.c ++++ b/source4/torture/drs/rpc/dssync.c +@@ -527,7 +527,9 @@ static bool test_analyse_objects(struct torture_context *tctx, + el = &new_msg->elements[idx]; + a = dsdb_attribute_by_lDAPDisplayName(ldap_schema, + el->name); +- if (!(el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE))) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + /* DRS only value */ + is_warning = false; + } else if (a->linkID & 1) { +-- +2.25.1 + + +From 27efd19085d01e1e3702afb5dfd82eaf72c13bf9 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 21 Jun 2022 15:22:47 +1200 +Subject: [PATCH 05/99] CVE-2022-32746 s4/dsdb/acl: Fix LDB flags comparison + +LDB_FLAG_MOD_* values are not actually flags, and the previous +comparison was equivalent to + +(el->flags & LDB_FLAG_MOD_MASK) == 0 + +which is only true if none of the LDB_FLAG_MOD_* values are set, so we +would not successfully return if the element was a DELETE. Correct the +expression to what it was intended to be. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + selftest/knownfail.d/acl-spn-delete | 1 - + source4/dsdb/samdb/ldb_modules/acl.c | 5 +++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + delete mode 100644 selftest/knownfail.d/acl-spn-delete + +diff --git a/selftest/knownfail.d/acl-spn-delete b/selftest/knownfail.d/acl-spn-delete +deleted file mode 100644 +index 32018413c49..00000000000 +--- a/selftest/knownfail.d/acl-spn-delete ++++ /dev/null +@@ -1 +0,0 @@ +-^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\( +diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c +index 21e83276bfd..8016a2d4bd0 100644 +--- a/source4/dsdb/samdb/ldb_modules/acl.c ++++ b/source4/dsdb/samdb/ldb_modules/acl.c +@@ -734,8 +734,9 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, + * If not add or replace (eg delete), + * return success + */ +- if ((el->flags +- & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) { ++ if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD && ++ LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE) ++ { + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } +-- +2.25.1 + + +From 7c4439c7b7ff4caa7152f810ec9e83732fa70c3c Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:43:52 +1300 +Subject: [PATCH 06/99] CVE-2022-32746 ldb:rdn_name: Use LDB_FLAG_MOD_TYPE() + for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/modules/rdn_name.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c +index e69ad9315ae..25cffe07591 100644 +--- a/lib/ldb/modules/rdn_name.c ++++ b/lib/ldb/modules/rdn_name.c +@@ -545,7 +545,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (e != NULL) { + ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead", + ldb_dn_get_linearized(req->op.mod.message->dn)); +- if (e->flags == LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(e->flags) == LDB_FLAG_MOD_REPLACE) { + return LDB_ERR_CONSTRAINT_VIOLATION; + } else { + return LDB_ERR_UNWILLING_TO_PERFORM; +-- +2.25.1 + + +From 47e2b1080e603b36b5d54a3e00f005983e6911e2 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 19:49:19 +1200 +Subject: [PATCH 07/99] CVE-2022-32746 s4/dsdb/repl_meta_data: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index ab506cec488..29ffda75c87 100644 +--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3525,7 +3525,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_REPLACE) { + return ldb_module_operr(module); + } + +@@ -3558,11 +3558,11 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_DELETE) { + return ldb_module_operr(module); + } + +- if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[1].flags) != LDB_FLAG_MOD_ADD) { + return ldb_module_operr(module); + } + +@@ -3645,7 +3645,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_operr(module); + } + +- if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[0].flags) != LDB_FLAG_MOD_ADD) { + talloc_free(ac); + return ldb_module_operr(module); + } +-- +2.25.1 + + +From f2b821f24e9b144c2cb1a9ec85f3bf1fdd2c2a8e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:11:33 +1200 +Subject: [PATCH 08/99] CVE-2022-32746 s4/dsdb/tombstone_reanimate: Use + LDB_FLAG_MOD_TYPE() for flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 64e05195798..5f8911c66be 100644 +--- a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -104,7 +104,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + if (el_dn == NULL) { + return false; + } +- if (el_dn->flags != LDB_FLAG_MOD_REPLACE) { ++ if (LDB_FLAG_MOD_TYPE(el_dn->flags) != LDB_FLAG_MOD_REPLACE) { + return false; + } + if (el_dn->num_values != 1) { +@@ -117,7 +117,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req, + return false; + } + +- if (el_deleted->flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(el_deleted->flags) != LDB_FLAG_MOD_DELETE) { + return false; + } + +-- +2.25.1 + + +From ba27d18c2e8e1d0cf1828bb6d072489e5c6c9159 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Tue, 14 Jun 2022 21:12:39 +1200 +Subject: [PATCH 09/99] CVE-2022-32746 s4/registry: Use LDB_FLAG_MOD_TYPE() for + flags equality check + +Now unrelated flags will no longer affect the result. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + source4/lib/registry/ldb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source4/lib/registry/ldb.c b/source4/lib/registry/ldb.c +index e089355975b..db383a560da 100644 +--- a/source4/lib/registry/ldb.c ++++ b/source4/lib/registry/ldb.c +@@ -859,7 +859,7 @@ static WERROR ldb_set_value(struct hive_key *parent, + + /* Try first a "modify" and if this doesn't work do try an "add" */ + for (i = 0; i < msg->num_elements; i++) { +- if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) { ++ if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) { + msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; + } + } +-- +2.25.1 + + +From 1294192b821d2d3af444b750baa75924042f1162 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:10:32 +1300 +Subject: [PATCH 10/99] CVE-2022-32746 ldb: Add flag to mark message element + values as shared + +When making a shallow copy of an ldb message, mark the message elements +of the copy as sharing their values with the message elements in the +original message. + +This flag value will be heeded in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 43 +++++++++++++++++++++++++++++++----- + lib/ldb/include/ldb_module.h | 6 +++++ + 2 files changed, 43 insertions(+), 6 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 57dfc5a04c2..2a9ce384bb9 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -833,11 +833,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg) + ldb_msg_element_compare_name); + } + +-/* +- shallow copy a message - copying only the elements array so that the caller +- can safely add new elements without changing the message +-*/ +-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx, + const struct ldb_message *msg) + { + struct ldb_message *msg2; +@@ -863,6 +859,35 @@ failed: + return NULL; + } + ++/* ++ shallow copy a message - copying only the elements array so that the caller ++ can safely add new elements without changing the message ++*/ ++struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx, ++ const struct ldb_message *msg) ++{ ++ struct ldb_message *msg2; ++ unsigned int i; ++ ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); ++ if (msg2 == NULL) { ++ return NULL; ++ } ++ ++ for (i = 0; i < msg2->num_elements; ++i) { ++ /* ++ * Mark this message's elements as sharing their values with the ++ * original message, so that we don't inadvertently modify or ++ * free them. We don't mark the original message element as ++ * shared, so the original message element should not be ++ * modified or freed while the shallow copy lives. ++ */ ++ struct ldb_message_element *el = &msg2->elements[i]; ++ el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES; ++ } ++ ++ return msg2; ++} + + /* + copy a message, allocating new memory for all parts +@@ -873,7 +898,7 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + struct ldb_message *msg2; + unsigned int i, j; + +- msg2 = ldb_msg_copy_shallow(mem_ctx, msg); ++ msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg); + if (msg2 == NULL) return NULL; + + if (msg2->dn != NULL) { +@@ -894,6 +919,12 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx, + goto failed; + } + } ++ ++ /* ++ * Since we copied this element's values, we can mark them as ++ * not shared. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; + } + + return msg2; +diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h +index 8c1e5ee7936..4c7c85a17f0 100644 +--- a/lib/ldb/include/ldb_module.h ++++ b/lib/ldb/include/ldb_module.h +@@ -96,6 +96,12 @@ struct ldb_module; + */ + #define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100 + ++/* ++ * indicates that this element's values are shared with another element (for ++ * example, in a shallow copy of an ldb_message) and should not be freed ++ */ ++#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200 ++ + /* an extended match rule that always fails to match */ + #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1" + +-- +2.25.1 + + +From 3a68efe1bbba4923f02b89a7f675398fbd73265e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 12:35:13 +1300 +Subject: [PATCH 11/99] CVE-2022-32746 ldb: Ensure shallow copy modifications + do not affect original message + +Using the newly added ldb flag, we can now detect when a message has +been shallow-copied so that its elements share their values with the +original message elements. Then when adding values to the copied +message, we now make a copy of the shared values array first. + +This should prevent a use-after-free that occurred in LDB modules when +new values were added to a shallow copy of a message by calling +talloc_realloc() on the original values array, invalidating the 'values' +pointer in the original message element. The original values pointer can +later be used in the database audit logging module which logs database +requests, and potentially cause a crash. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 52 ++++++++++++++++++++++++++++++++------ + lib/ldb/include/ldb.h | 6 +++++ + source4/dsdb/common/util.c | 20 +++++---------- + 3 files changed, 56 insertions(+), 22 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 2a9ce384bb9..44d3b29e9a7 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -417,6 +417,47 @@ int ldb_msg_add(struct ldb_message *msg, + return LDB_SUCCESS; + } + ++/* ++ * add a value to a message element ++ */ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val) ++{ ++ struct ldb_val *vals; ++ ++ if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) { ++ /* ++ * Another message is using this message element's values array, ++ * so we don't want to make any modifications to the original ++ * message, or potentially invalidate its own values by calling ++ * talloc_realloc(). Make a copy instead. ++ */ ++ el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES; ++ ++ vals = talloc_array(mem_ctx, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ if (el->values != NULL) { ++ memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val)); ++ } ++ } else { ++ vals = talloc_realloc(mem_ctx, el->values, struct ldb_val, ++ el->num_values + 1); ++ if (vals == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ } ++ el->values = vals; ++ el->values[el->num_values] = *val; ++ el->num_values++; ++ ++ return LDB_SUCCESS; ++} ++ + /* + add a value to a message + */ +@@ -426,7 +467,6 @@ int ldb_msg_add_value(struct ldb_message *msg, + struct ldb_message_element **return_el) + { + struct ldb_message_element *el; +- struct ldb_val *vals; + int ret; + + el = ldb_msg_find_element(msg, attr_name); +@@ -437,14 +477,10 @@ int ldb_msg_add_value(struct ldb_message *msg, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values+1); +- if (!vals) { +- return LDB_ERR_OPERATIONS_ERROR; ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; + } +- el->values = vals; +- el->values[el->num_values] = *val; +- el->num_values++; + + if (return_el) { + *return_el = el; +diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h +index bc44157eaf4..129beefeaf5 100644 +--- a/lib/ldb/include/ldb.h ++++ b/lib/ldb/include/ldb.h +@@ -1981,6 +1981,12 @@ int ldb_msg_add_empty(struct ldb_message *msg, + int flags, + struct ldb_message_element **return_el); + ++/** ++ add a value to a message element ++*/ ++int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx, ++ struct ldb_message_element *el, ++ const struct ldb_val *val); + /** + add a element to a ldb_message + */ +diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c +index 9b4afa45215..721e1e9d41d 100644 +--- a/source4/dsdb/common/util.c ++++ b/source4/dsdb/common/util.c +@@ -815,7 +815,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -850,14 +850,10 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +@@ -871,7 +867,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + const char *value) + { + struct ldb_message_element *el; +- struct ldb_val val, *vals; ++ struct ldb_val val; + char *v; + unsigned int i; + bool found = false; +@@ -906,14 +902,10 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + } + } + +- vals = talloc_realloc(msg->elements, el->values, struct ldb_val, +- el->num_values + 1); +- if (vals == NULL) { ++ ret = ldb_msg_element_add_value(msg->elements, el, &val); ++ if (ret != LDB_SUCCESS) { + return ldb_oom(sam_ldb); + } +- el->values = vals; +- el->values[el->num_values] = val; +- ++(el->num_values); + + return LDB_SUCCESS; + } +-- +2.25.1 + + +From a25b97d0540fdb5a4a75fd85807d8963f14b607d Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 16 Feb 2022 16:30:03 +1300 +Subject: [PATCH 12/99] CVE-2022-32746 ldb: Add functions for appending to an + ldb_message + +Currently, there are many places where we use ldb_msg_add_empty() to add +an empty element to a message, and then call ldb_msg_add_value() or +similar to add values to that element. However, this performs an +unnecessary search of the message's elements to locate the new element. +Moreover, if an element with the same attribute name already exists +earlier in the message, the values will be added to that element, +instead of to the intended newly added element. + +A similar pattern exists where we add values to a message, and then call +ldb_msg_find_element() to locate that message element and sets its flags +to (e.g.) LDB_FLAG_MOD_REPLACE. This also performs an unnecessary +search, and may locate the wrong message element for setting the flags. + +To avoid these problems, add functions for appending a value to a +message, so that a particular value can be added to the end of a message +in a single operation. + +For ADD requests, it is important that no two message elements share the +same attribute name, otherwise things will break. (Normally, +ldb_msg_normalize() is called before processing the request to help +ensure this.) Thus, we must be careful not to append an attribute to an +ADD message, unless we are sure (e.g. through ldb_msg_find_element()) +that an existing element for that attribute is not present. + +These functions will be used in the next commit. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++- + lib/ldb/include/ldb.h | 24 ++++++ + 2 files changed, 185 insertions(+), 4 deletions(-) + +diff --git a/lib/ldb/common/ldb_msg.c b/lib/ldb/common/ldb_msg.c +index 44d3b29e9a7..9cd7998e21c 100644 +--- a/lib/ldb/common/ldb_msg.c ++++ b/lib/ldb/common/ldb_msg.c +@@ -509,12 +509,15 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + + + /* +- add a string element to a message ++ add a string element to a message, specifying flags + */ +-int ldb_msg_add_string(struct ldb_message *msg, +- const char *attr_name, const char *str) ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags) + { + struct ldb_val val; ++ int ret; ++ struct ldb_message_element *el = NULL; + + val.data = discard_const_p(uint8_t, str); + val.length = strlen(str); +@@ -524,7 +527,25 @@ int ldb_msg_add_string(struct ldb_message *msg, + return LDB_SUCCESS; + } + +- return ldb_msg_add_value(msg, attr_name, &val, NULL); ++ ret = ldb_msg_add_value(msg, attr_name, &val, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (flags != 0) { ++ el->flags = flags; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ add a string element to a message ++*/ ++int ldb_msg_add_string(struct ldb_message *msg, ++ const char *attr_name, const char *str) ++{ ++ return ldb_msg_add_string_flags(msg, attr_name, str, 0); + } + + /* +@@ -586,6 +607,142 @@ int ldb_msg_add_fmt(struct ldb_message *msg, + return ldb_msg_add_steal_value(msg, attr_name, &val); + } + ++static int ldb_msg_append_value_impl(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags, ++ struct ldb_message_element **return_el) ++{ ++ struct ldb_message_element *el = NULL; ++ int ret; ++ ++ ret = ldb_msg_add_empty(msg, attr_name, flags, &el); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ ret = ldb_msg_element_add_value(msg->elements, el, val); ++ if (ret != LDB_SUCCESS) { ++ return ret; ++ } ++ ++ if (return_el != NULL) { ++ *return_el = el; ++ } ++ ++ return LDB_SUCCESS; ++} ++ ++/* ++ append a value to a message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags) ++{ ++ return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL); ++} ++ ++/* ++ append a value to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags) ++{ ++ int ret; ++ struct ldb_message_element *el = NULL; ++ ++ ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el); ++ if (ret == LDB_SUCCESS) { ++ talloc_steal(el->values, val->data); ++ } ++ return ret; ++} ++ ++/* ++ append a string element to a message, stealing it into the 'right' place ++*/ ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a string element to a message ++*/ ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, int flags) ++{ ++ struct ldb_val val; ++ ++ val.data = discard_const_p(uint8_t, str); ++ val.length = strlen(str); ++ ++ if (val.length == 0) { ++ /* allow empty strings as non-existent attributes */ ++ return LDB_SUCCESS; ++ } ++ ++ return ldb_msg_append_value(msg, attr_name, &val, flags); ++} ++ ++/* ++ append a DN element to a message ++ WARNING: this uses the linearized string from the dn, and does not ++ copy the string. ++*/ ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags) ++{ ++ char *str = ldb_dn_alloc_linearized(msg, dn); ++ ++ if (str == NULL) { ++ /* we don't want to have unknown DNs added */ ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ return ldb_msg_append_steal_string(msg, attr_name, str, flags); ++} ++ ++/* ++ append a printf formatted element to a message ++*/ ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) ++{ ++ struct ldb_val val; ++ va_list ap; ++ char *str = NULL; ++ ++ va_start(ap, fmt); ++ str = talloc_vasprintf(msg, fmt, ap); ++ va_end(ap); ++ ++ if (str == NULL) { ++ return LDB_ERR_OPERATIONS_ERROR; ++ } ++ ++ val.data = (uint8_t *)str; ++ val.length = strlen(str); ++ ++ return ldb_msg_append_steal_value(msg, attr_name, &val, flags); ++} ++ + /* + compare two ldb_message_element structures + assumes case sensitive comparison +diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h +index 129beefeaf5..63d8aedd672 100644 +--- a/lib/ldb/include/ldb.h ++++ b/lib/ldb/include/ldb.h +@@ -2002,12 +2002,36 @@ int ldb_msg_add_steal_value(struct ldb_message *msg, + struct ldb_val *val); + int ldb_msg_add_steal_string(struct ldb_message *msg, + const char *attr_name, char *str); ++int ldb_msg_add_string_flags(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); + int ldb_msg_add_string(struct ldb_message *msg, + const char *attr_name, const char *str); + int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name, + struct ldb_dn *dn); + int ldb_msg_add_fmt(struct ldb_message *msg, + const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); ++/** ++ append a element to a ldb_message ++*/ ++int ldb_msg_append_value(struct ldb_message *msg, ++ const char *attr_name, ++ const struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_value(struct ldb_message *msg, ++ const char *attr_name, ++ struct ldb_val *val, ++ int flags); ++int ldb_msg_append_steal_string(struct ldb_message *msg, ++ const char *attr_name, char *str, ++ int flags); ++int ldb_msg_append_string(struct ldb_message *msg, ++ const char *attr_name, const char *str, ++ int flags); ++int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name, ++ struct ldb_dn *dn, int flags); ++int ldb_msg_append_fmt(struct ldb_message *msg, int flags, ++ const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5); + + /** + compare two message elements - return 0 on match +-- +2.25.1 + + +From 0446581bcce7c2d7f5ec22d8510a6e2069463d39 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 21 Feb 2022 16:27:37 +1300 +Subject: [PATCH 13/99] CVE-2022-32746 ldb: Make use of functions for appending + to an ldb_message + +This aims to minimise usage of the error-prone pattern of searching for +a just-added message element in order to make modifications to it (and +potentially finding the wrong element). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009 + +Signed-off-by: Joseph Sutton +--- + lib/ldb/ldb_map/ldb_map.c | 5 +- + lib/ldb/ldb_map/ldb_map_inbound.c | 9 +- + lib/ldb/modules/rdn_name.c | 22 +--- + source3/passdb/pdb_samba_dsdb.c | 14 +-- + source4/dns_server/dnsserver_common.c | 12 +- + source4/dsdb/common/util.c | 114 ++++++++++++++---- + source4/dsdb/samdb/ldb_modules/descriptor.c | 10 +- + source4/dsdb/samdb/ldb_modules/objectguid.c | 20 +-- + .../dsdb/samdb/ldb_modules/partition_init.c | 14 +-- + .../dsdb/samdb/ldb_modules/repl_meta_data.c | 24 +--- + source4/dsdb/samdb/ldb_modules/samldb.c | 78 +++++------- + .../samdb/ldb_modules/tombstone_reanimate.c | 12 +- + source4/nbt_server/wins/winsdb.c | 13 +- + source4/rpc_server/lsa/dcesrv_lsa.c | 55 +++------ + source4/winbind/idmap.c | 10 +- + 15 files changed, 183 insertions(+), 229 deletions(-) + +diff --git a/lib/ldb/ldb_map/ldb_map.c b/lib/ldb/ldb_map/ldb_map.c +index b453dff80d2..c7b0c228631 100644 +--- a/lib/ldb/ldb_map/ldb_map.c ++++ b/lib/ldb/ldb_map/ldb_map.c +@@ -946,10 +946,7 @@ struct ldb_request *map_build_fixup_req(struct map_context *ac, + if ( ! dn || ! ldb_dn_validate(msg->dn)) { + goto failed; + } +- if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) { ++ if (ldb_msg_append_string(msg, IS_MAPPED, dn, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git a/lib/ldb/ldb_map/ldb_map_inbound.c b/lib/ldb/ldb_map/ldb_map_inbound.c +index 324295737da..50b9427c26c 100644 +--- a/lib/ldb/ldb_map/ldb_map_inbound.c ++++ b/lib/ldb/ldb_map/ldb_map_inbound.c +@@ -569,12 +569,9 @@ static int map_modify_do_local(struct map_context *ac) + /* No local record present, add it instead */ + /* Add local 'IS_MAPPED' */ + /* TODO: use GUIDs here instead */ +- if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED, +- LDB_FLAG_MOD_ADD, NULL) != 0) { +- return LDB_ERR_OPERATIONS_ERROR; +- } +- ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED, +- ac->remote_req->op.mod.message->dn); ++ ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED, ++ ac->remote_req->op.mod.message->dn, ++ LDB_FLAG_MOD_ADD); + if (ret != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } +diff --git a/lib/ldb/modules/rdn_name.c b/lib/ldb/modules/rdn_name.c +index 25cffe07591..3cb62bf567b 100644 +--- a/lib/ldb/modules/rdn_name.c ++++ b/lib/ldb/modules/rdn_name.c +@@ -308,16 +308,10 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares) + } + rdn_val = ldb_val_dup(msg, rdn_val_p); + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } +- if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto error; +- } +- if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto error; + } + +@@ -466,11 +460,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +@@ -479,11 +469,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req) + if (ret != 0) { + return ldb_module_oom(module); + } +- ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL); +- if (ret != 0) { +- return ldb_module_oom(module); +- } +- ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL); ++ ret = ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_ADD); + if (ret != 0) { + return ldb_module_oom(module); + } +diff --git a/source3/passdb/pdb_samba_dsdb.c b/source3/passdb/pdb_samba_dsdb.c +index 4f1d2f697f0..d9c31e57186 100644 +--- a/source3/passdb/pdb_samba_dsdb.c ++++ b/source3/passdb/pdb_samba_dsdb.c +@@ -2776,18 +2776,10 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m, + } + + msg->num_elements = 0; +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_empty() failed\n")); +- TALLOC_FREE(tmp_ctx); +- ldb_transaction_cancel(state->ldb); +- return false; +- } +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &new_val, NULL); +- if (ret != LDB_SUCCESS) { +- DEBUG(0, ("ldb_msg_add_value() failed\n")); ++ DEBUG(0, ("ldb_msg_append_value() failed\n")); + TALLOC_FREE(tmp_ctx); + ldb_transaction_cancel(state->ldb); + return false; +diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c +index d1f896d6755..2b4d719b342 100644 +--- a/source4/dns_server/dnsserver_common.c ++++ b/source4/dns_server/dnsserver_common.c +@@ -1122,15 +1122,9 @@ WERROR dns_common_replace(struct ldb_context *samdb, + } + + if (was_tombstoned || become_tombstoned) { +- ret = ldb_msg_add_empty(msg, "dNSTombstoned", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- werr = DNS_ERR(SERVER_FAILURE); +- goto exit; +- } +- +- ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s", +- become_tombstoned ? "TRUE" : "FALSE"); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "dNSTombstoned", "%s", ++ become_tombstoned ? "TRUE" : "FALSE"); + if (ret != LDB_SUCCESS) { + werr = DNS_ERR(SERVER_FAILURE); + goto exit; +diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c +index 721e1e9d41d..beb2883cad2 100644 +--- a/source4/dsdb/common/util.c ++++ b/source4/dsdb/common/util.c +@@ -923,6 +923,16 @@ int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct l + return ldb_msg_add_string(msg, attr_name, s); + } + ++int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_add_string_flags(msg, attr_name, s, flags); ++} ++ + /* + * Add an unsigned int element to a message + * +@@ -941,6 +951,12 @@ int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct + return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v); + } + ++int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ + /* + add a (signed) int64_t element to a message + */ +@@ -972,6 +988,68 @@ int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc + return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v); + } + ++/* ++ append a int element to a message ++*/ ++int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%d", v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, unsigned int v, int flags) ++{ ++ return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags); ++} ++ ++/* ++ append a (signed) int64_t element to a message ++*/ ++int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, int64_t v, int flags) ++{ ++ const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v); ++ if (s == NULL) { ++ return ldb_oom(sam_ldb); ++ } ++ return ldb_msg_append_string(msg, attr_name, s, flags); ++} ++ ++/* ++ * Append an unsigned int64_t (uint64_t) element to a message ++ * ++ * The issue here is that we have not yet first cast to int32_t explicitly, ++ * before we cast to an signed int to printf() into the %d or cast to a ++ * int64_t before we then cast to a long long to printf into a %lld. ++ * ++ * There are *no* unsigned integers in Active Directory LDAP, even the RID ++ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities. ++ * (See the schema, and the syntax definitions in schema_syntax.c). ++ * ++ */ ++int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, ++ const char *attr_name, uint64_t v, int flags) ++{ ++ return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags); ++} ++ + /* + add a samr_Password element to a message + */ +@@ -2813,15 +2891,8 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, + tdo_msg->num_elements = 0; + TALLOC_FREE(tdo_msg->elements); + +- ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- ldb_transaction_cancel(ldb); +- TALLOC_FREE(frame); +- return NT_STATUS_NO_MEMORY; +- } +- ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming", +- &new_val, NULL); ++ ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming", ++ &new_val, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + ldb_transaction_cancel(ldb); + TALLOC_FREE(frame); +@@ -3186,6 +3257,7 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb, + /* + adds the given GUID to the given ldb_message. This value is added + for the given attr_name (may be either "objectGUID" or "parentGUID"). ++ This function is used in processing 'add' requests. + */ + int dsdb_msg_add_guid(struct ldb_message *msg, + struct GUID *guid, +@@ -5655,7 +5727,8 @@ int dsdb_user_obj_set_defaults(struct ldb_context *ldb, + } + + /** +- * Sets 'sAMAccountType on user object based on userAccountControl ++ * Sets 'sAMAccountType on user object based on userAccountControl. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5667,21 +5740,19 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + { + int ret; + uint32_t account_type; +- struct ldb_message_element *el; + + account_type = ds_uf2atype(user_account_control); + if (account_type == 0) { + ldb_set_errstring(ldb, "dsdb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (account_type_p) { + *account_type_p = account_type; +@@ -5691,7 +5762,8 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message * + } + + /** +- * Determine and set primaryGroupID based on userAccountControl value ++ * Determine and set primaryGroupID based on userAccountControl value. ++ * This function is used in processing both 'add' and 'modify' requests. + * @param ldb Current ldb_context + * @param usr_obj ldb_message representing User object + * @param user_account_control Value for userAccountControl flags +@@ -5703,17 +5775,15 @@ int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_messa + { + int ret; + uint32_t rid; +- struct ldb_message_element *el; + + rid = ds_uf2prim_group_rid(user_account_control); + +- ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj, +- "primaryGroupID", rid); ++ ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj, ++ "primaryGroupID", rid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(usr_obj, "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + if (group_rid_p) { + *group_rid_p = rid; +diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c +index 8a4c2c3591f..10ed577328d 100644 +--- a/source4/dsdb/samdb/ldb_modules/descriptor.c ++++ b/source4/dsdb/samdb/ldb_modules/descriptor.c +@@ -861,14 +861,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req) + return ldb_module_done(req, NULL, NULL, LDB_SUCCESS); + } + +- ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor", +- LDB_FLAG_MOD_REPLACE, +- &sd_element); +- if (ret != LDB_SUCCESS) { +- return ldb_oom(ldb); +- } +- ret = ldb_msg_add_value(msg, "nTSecurityDescriptor", +- sd, NULL); ++ ret = ldb_msg_append_value(msg, "nTSecurityDescriptor", ++ sd, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_oom(ldb); + } +diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c +index bc3260cf0d8..0fe995a5763 100644 +--- a/source4/dsdb/samdb/ldb_modules/objectguid.c ++++ b/source4/dsdb/samdb/ldb_modules/objectguid.c +@@ -41,7 +41,6 @@ + */ + static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + { +- struct ldb_message_element *el; + char *s; + int ret; + +@@ -54,16 +53,13 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + return LDB_ERR_OPERATIONS_ERROR; + } + +- ret = ldb_msg_add_string(msg, attr, s); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = ldb_msg_append_string(msg, attr, s, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +@@ -73,23 +69,19 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t) + static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg, + const char *attr, uint64_t v) + { +- struct ldb_message_element *el; + int ret; + + if (ldb_msg_find_element(msg, attr) != NULL) { + return LDB_SUCCESS; + } + +- ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v); ++ /* always set as replace. This works because on add ops, the flag ++ is ignored */ ++ ret = samdb_msg_append_uint64(ldb, msg, msg, attr, v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } + +- el = ldb_msg_find_element(msg, attr); +- /* always set as replace. This works because on add ops, the flag +- is ignored */ +- el->flags = LDB_FLAG_MOD_REPLACE; +- + return LDB_SUCCESS; + } + +diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c +index 58c65ccedd0..484b5bffb27 100644 +--- a/source4/dsdb/samdb/ldb_modules/partition_init.c ++++ b/source4/dsdb/samdb/ldb_modules/partition_init.c +@@ -742,10 +742,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + + mod_msg->dn = ldb_dn_new(mod_msg, ldb, DSDB_PARTITION_DN); +- ret = ldb_msg_add_empty(mod_msg, DSDB_PARTITION_ATTR, LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } + + casefold_dn = ldb_dn_get_casefold(dn); + +@@ -785,18 +781,16 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) + } + partition_record = talloc_asprintf(mod_msg, "%s:%s", casefold_dn, filename); + +- ret = ldb_msg_add_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record); ++ ret = ldb_msg_append_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } + + if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) { + /* this new partition is a partial replica */ +- ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL); +- if (ret != LDB_SUCCESS) { +- return ret; +- } +- ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn)); ++ ret = ldb_msg_append_fmt(mod_msg, LDB_FLAG_MOD_ADD, ++ "partialReplica", "%s", ldb_dn_get_linearized(dn)); + if (ret != LDB_SUCCESS) { + return ret; + } +diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +index 29ffda75c87..eec1e639856 100644 +--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c ++++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +@@ -3888,22 +3888,12 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are + ldb_operr(ldb)); + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); + } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- talloc_free(ares); +- return ldb_module_done(ac->req, NULL, NULL, +- ldb_oom(ldb)); +- } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + talloc_free(ares); + return ldb_module_done(ac->req, NULL, NULL, + ldb_oom(ldb)); +@@ -5161,16 +5151,10 @@ static int replmd_name_modify(struct replmd_replicated_request *ar, + goto failed; + } + +- if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) { +- goto failed; +- } +- if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) { ++ if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } +- if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) { ++ if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) { + goto failed; + } + +diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c +index 24971d521aa..b89d93910fd 100644 +--- a/source4/dsdb/samdb/ldb_modules/samldb.c ++++ b/source4/dsdb/samdb/ldb_modules/samldb.c +@@ -1103,14 +1103,11 @@ static int samldb_rodc_add(struct samldb_ctx *ac) + return LDB_ERR_OTHER; + + found: +- ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber", +- LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL); +- if (ret != LDB_SUCCESS) { +- return ldb_operr(ldb); +- } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "msDS-SecondaryKrbTgtNumber", krbtgt_number); ++ ldb_msg_remove_attr(ac->msg, "msDS-SecondaryKrbTgtNumber"); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "msDS-SecondaryKrbTgtNumber", krbtgt_number, ++ LDB_FLAG_INTERNAL_DISABLE_VALIDATION); + if (ret != LDB_SUCCESS) { + return ldb_operr(ldb); + } +@@ -1792,7 +1789,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + struct ldb_context *ldb = ldb_module_get_ctx(ac->module); + void *skip_allocate_sids = ldb_get_opaque(ldb, + "skip_allocate_sids"); +- struct ldb_message_element *el, *el2; ++ struct ldb_message_element *el; + struct dom_sid *sid; + int ret; + +@@ -1926,23 +1923,17 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + /* "isCriticalSystemObject" might be set */ + if (user_account_control & + (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "TRUE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "TRUE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- "FALSE"); ++ ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject", ++ "FALSE", LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */ +@@ -2018,14 +2009,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", +- account_type); ++ ret = samdb_msg_add_uint_flags(ldb, ac->msg, ac->msg, ++ "sAMAccountType", ++ account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el2 = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el2->flags = LDB_FLAG_MOD_REPLACE; + } + break; + } +@@ -2945,26 +2935,23 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + + if (old_atype != new_atype) { +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "sAMAccountType", new_atype); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "sAMAccountType", new_atype, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */ + if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) { + /* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */ + ldb_msg_remove_attr(ac->msg, "lockoutTime"); +- ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime", +- (NTTIME)0); ++ ret = samdb_msg_append_uint64(ldb, ac->msg, ac->msg, "lockoutTime", ++ (NTTIME)0, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "lockoutTime"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* +@@ -2975,14 +2962,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + * creating the attribute. + */ + if (old_is_critical != new_is_critical || old_atype != new_atype) { +- ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject", +- new_is_critical ? "TRUE": "FALSE"); ++ ret = ldb_msg_append_string(ac->msg, "isCriticalSystemObject", ++ new_is_critical ? "TRUE": "FALSE", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "isCriticalSystemObject"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + if (!ldb_msg_find_element(ac->msg, "primaryGroupID") && +@@ -2995,14 +2980,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac) + } + } + +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, +- "primaryGroupID", new_pgrid); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, ++ "primaryGroupID", new_pgrid, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, +- "primaryGroupID"); +- el->flags = LDB_FLAG_MOD_REPLACE; + } + + /* Propagate eventual "userAccountControl" attribute changes */ +@@ -3205,13 +3188,12 @@ static int samldb_lockout_time(struct samldb_ctx *ac) + + /* lockoutTime == 0 resets badPwdCount */ + ldb_msg_remove_attr(ac->msg, "badPwdCount"); +- ret = samdb_msg_add_int(ldb, ac->msg, ac->msg, +- "badPwdCount", 0); ++ ret = samdb_msg_append_int(ldb, ac->msg, ac->msg, ++ "badPwdCount", 0, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "badPwdCount"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +@@ -3309,13 +3291,11 @@ static int samldb_group_type_change(struct samldb_ctx *ac) + ldb_set_errstring(ldb, "samldb: Unrecognized account type!"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } +- ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType", +- account_type); ++ ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, "sAMAccountType", ++ account_type, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + return LDB_SUCCESS; + } +diff --git a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +index 5f8911c66be..99c5955e9e7 100644 +--- a/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c ++++ b/source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c +@@ -294,14 +294,13 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, + "reanimate: Unrecognized account type!"); + } +- ret = samdb_msg_add_uint(ldb, ac->mod_msg, ac->mod_msg, +- "sAMAccountType", account_type); ++ ret = samdb_msg_append_uint(ldb, ac->mod_msg, ac->mod_msg, ++ "sAMAccountType", account_type, ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, + "reanimate: Failed to add sAMAccountType to restored object."); + } +- el = ldb_msg_find_element(ac->mod_msg, "sAMAccountType"); +- el->flags = LDB_FLAG_MOD_REPLACE; + + /* Default values set by Windows */ + ret = samdb_find_or_add_attribute(ldb, ac->mod_msg, +@@ -324,12 +323,11 @@ static int tr_prepare_attributes(struct tr_context *ac) + return ret; + } + +- ret = ldb_msg_add_string(ac->mod_msg, "objectCategory", value); ++ ret = ldb_msg_append_string(ac->mod_msg, "objectCategory", value, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + return ret; + } +- el = ldb_msg_find_element(ac->mod_msg, "objectCategory"); +- el->flags = LDB_FLAG_MOD_ADD; + } + + return LDB_SUCCESS; +diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c +index e4a7c2042ed..2a05e96bca4 100644 +--- a/source4/nbt_server/wins/winsdb.c ++++ b/source4/nbt_server/wins/winsdb.c +@@ -102,13 +102,11 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion) + msg->dn = dn; + + +- ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL); ++ ret = ldb_msg_append_string(msg, "objectClass", "winsMaxVersion", ++ LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion"); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) goto failed; +- ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion); ++ ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE, ++ "maxVersion", "%llu", (long long)newMaxVersion); + if (ret != LDB_SUCCESS) goto failed; + + ret = ldb_modify(wins_db, msg); +@@ -779,8 +777,7 @@ static struct ldb_message *winsdb_message(struct ldb_context *ldb, + ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]); + } + if (rec->registered_by) { +- ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL); +- ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by); ++ ret |= ldb_msg_append_string(msg, "registeredBy", rec->registered_by, 0); + } + if (ret != LDB_SUCCESS) goto failed; + return msg; +diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c +index 15b068aec62..a165ab2b9d6 100644 +--- a/source4/rpc_server/lsa/dcesrv_lsa.c ++++ b/source4/rpc_server/lsa/dcesrv_lsa.c +@@ -1778,12 +1778,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx, + goto done; + } + +- ret = ldb_msg_add_empty(dest, attribute, flags, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value); ++ ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -1874,13 +1869,7 @@ static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx, + continue; + } + +- ret = ldb_msg_add_empty(msg, attribute, +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } +- +- ret = ldb_msg_add_value(msg, attribute, &v, NULL); ++ ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -2166,28 +2155,30 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call, + } + + if (add_incoming || del_incoming) { +- ret = ldb_msg_add_empty(msg, "trustAuthIncoming", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_incoming) { +- ret = ldb_msg_add_value(msg, "trustAuthIncoming", +- &trustAuthIncoming, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthIncoming", ++ &trustAuthIncoming, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthIncoming", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } + } + } + if (add_outgoing || del_outgoing) { +- ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- return NT_STATUS_NO_MEMORY; +- } + if (add_outgoing) { +- ret = ldb_msg_add_value(msg, "trustAuthOutgoing", +- &trustAuthOutgoing, NULL); ++ ret = ldb_msg_append_value(msg, "trustAuthOutgoing", ++ &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE); ++ if (ret != LDB_SUCCESS) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ } else { ++ ret = ldb_msg_add_empty(msg, "trustAuthOutgoing", ++ LDB_FLAG_MOD_REPLACE, NULL); + if (ret != LDB_SUCCESS) { + return NT_STATUS_NO_MEMORY; + } +@@ -4635,14 +4626,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat + goto done; + } + +- ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo", +- LDB_FLAG_MOD_REPLACE, NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NO_MEMORY; +- goto done; +- } +- ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo", +- &ft_blob, NULL); ++ ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo", ++ &ft_blob, LDB_FLAG_MOD_REPLACE); + if (ret != LDB_SUCCESS) { + status = NT_STATUS_NO_MEMORY; + goto done; +diff --git a/source4/winbind/idmap.c b/source4/winbind/idmap.c +index c4039be473a..c6375f8357a 100644 +--- a/source4/winbind/idmap.c ++++ b/source4/winbind/idmap.c +@@ -672,14 +672,8 @@ static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx, + vals[1].data = (uint8_t *)hwm_string; + vals[1].length = strlen(hwm_string); + } else { +- ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD, +- NULL); +- if (ret != LDB_SUCCESS) { +- status = NT_STATUS_NONE_MAPPED; +- goto failed; +- } +- +- ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string); ++ ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string, ++ LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) + { + status = NT_STATUS_NONE_MAPPED; +-- +2.25.1 diff --git a/samba.spec b/samba.spec index 565eab1..dfe3f65 100644 --- a/samba.spec +++ b/samba.spec @@ -49,7 +49,7 @@ Name: samba Version: 4.15.3 -Release: 6 +Release: 7 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -74,6 +74,10 @@ Patch4: backport-0005-CVE-2021-44142.patch Patch5: backport-0001-CVE-2022-0336.patch Patch6: backport-0002-CVE-2022-0336.patch Patch7: backport-CVE-2021-44141.patch +Patch8: backport-CVE-2022-32746.patch +Patch9: backport-CVE-2022-32745.patch +Patch10: backport-CVE-2022-2031-CVE-2022-32744.patch +Patch11: backport-CVE-2022-32742.patch BuildRequires: avahi-devel bison dbus-devel docbook-style-xsl e2fsprogs-devel flex gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel @@ -2267,6 +2271,7 @@ fi %{python3_sitearch}/samba/tests/krb5/__pycache__/kdc_base_test.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/kdc_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/kdc_tgs_tests.*.pyc +%{python3_sitearch}/samba/tests/krb5/__pycache__/kpasswd_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/ms_kile_client_principal_lookup_tests.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/raw_testcase.*.pyc %{python3_sitearch}/samba/tests/krb5/__pycache__/rfc4120_constants.*.pyc @@ -2292,6 +2297,7 @@ fi %{python3_sitearch}/samba/tests/krb5/kdc_base_test.py %{python3_sitearch}/samba/tests/krb5/kdc_tests.py %{python3_sitearch}/samba/tests/krb5/kdc_tgs_tests.py +%{python3_sitearch}/samba/tests/krb5/kpasswd_tests.py %{python3_sitearch}/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py %{python3_sitearch}/samba/tests/krb5/raw_testcase.py %{python3_sitearch}/samba/tests/krb5/rfc4120_constants.py @@ -3394,6 +3400,12 @@ fi %endif %changelog +* Tue Aug 02 2022 xinghe - 4.15.3-7 +- Type:cves +- ID:CVE-2022-32746 CVE-2022-2031 CVE-2022-32744 CVE-2022-32742 CVE-2022-32745 +- SUG:NA +- DESC:fix CVE-2022-32746 CVE-2022-2031 CVE-2022-32744 CVE-2022-32742 CVE-2022-32745 + * Wed Jul 20 2022 gaihuiying - 4.15.3-6 - Type:bugfix - ID:NA -- Gitee