From fd00ae37858dd753c23238eaa8f4684dd64e7755 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 17 May 2024 14:19:31 +1200 Subject: [PATCH 1/6] dsdb: Reduce minimum maxPwdAge from 1 day to nil This allows us to have tests, which pass on Windows, that use a very short maxPwdAge. Signed-off-by: Andrew Bartlett Reviewed-by: Jo Sutton (cherry picked from commit 3669479f22f2109a64250ffabd1f6453882d29f1) --- source4/dsdb/samdb/ldb_modules/operational.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c index 20613a753841e..f525dba2081dd 100644 --- a/source4/dsdb/samdb/ldb_modules/operational.c +++ b/source4/dsdb/samdb/ldb_modules/operational.c @@ -783,13 +783,13 @@ static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *mod * * Possible values are in the range of: * - * maxPwdAge: -864000000001 + * maxPwdAge: -2 * to * maxPwdAge: -9223372036854775808 (INT64_MIN) * */ maxPwdAge = get_user_max_pwd_age(module, msg, parent, domain_dn); - if (maxPwdAge >= -864000000000) { + if (maxPwdAge >= -1) { /* * This is not really possible... */ -- 2.39.1 From 2c1a446ac98002fcb8b098953485c47476487668 Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Fri, 22 Mar 2024 12:58:19 +1300 Subject: [PATCH 2/6] tests/krb5: Fix PK-INIT test framework to allow expired password keys Signed-off-by: Jo Sutton Reviewed-by: Andrew Bartlett (cherry picked from commit 7cc8f455191faacf32efc474c27e99d45ef2e024) --- python/samba/tests/krb5/raw_testcase.py | 3 +++ python/samba/tests/krb5/rfc4120_constants.py | 1 + 2 files changed, 4 insertions(+) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 90d286a66bec8..c77145ad60d23 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -65,6 +65,7 @@ from samba.tests.krb5.rfc4120_constants import ( FX_FAST_ARMOR_AP_REQUEST, KDC_ERR_CLIENT_REVOKED, KDC_ERR_GENERIC, + KDC_ERR_KEY_EXPIRED, KDC_ERR_POLICY, KDC_ERR_PREAUTH_FAILED, KDC_ERR_SKEW, @@ -5046,6 +5047,8 @@ class RawKerberosTest(TestCase): if ('1' in sent_pac_options and error_code not in (0, KDC_ERR_GENERIC)): expected_patypes += (PADATA_PAC_OPTIONS,) + elif error_code == KDC_ERR_KEY_EXPIRED: + expected_patypes += (PADATA_PK_AS_REP,) elif error_code != KDC_ERR_GENERIC: if expect_etype_info: expected_patypes += (PADATA_ETYPE_INFO,) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index dff6017b71057..b26126fc9f9da 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -99,6 +99,7 @@ KDC_ERR_ETYPE_NOSUPP = 14 KDC_ERR_SUMTYPE_NOSUPP = 15 KDC_ERR_CLIENT_REVOKED = 18 KDC_ERR_TGT_REVOKED = 20 +KDC_ERR_KEY_EXPIRED = 23 KDC_ERR_PREAUTH_FAILED = 24 KDC_ERR_PREAUTH_REQUIRED = 25 KDC_ERR_SERVER_NOMATCH = 26 -- 2.39.1 From 878b0a25fd0d1b730a3c4be01c079979d20e70bd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 19 Mar 2024 14:37:24 +1300 Subject: [PATCH 3/6] python/tests/krb5: Prepare for PKINIT tests with UF_SMARTCARD_REQUIRED Signed-off-by: Andrew Bartlett Reviewed-by: Jo Sutton (backported from commit b2fe1ea1c6aba116b31a1c803b4e0d36ac1a32ee) [jsutton@samba.org Fixed conflicting import statements in python/samba/tests/krb5/pkinit_tests.py] --- python/samba/tests/krb5/kdc_base_test.py | 19 +++++++++++++++++-- python/samba/tests/krb5/pkinit_tests.py | 15 ++++++++++++--- python/samba/tests/krb5/raw_testcase.py | 15 +++++++++++++-- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 373c73ecb9a30..20d2e614fb022 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -81,6 +81,7 @@ from samba.dsdb import ( UF_SERVER_TRUST_ACCOUNT, UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION, UF_WORKSTATION_TRUST_ACCOUNT, + UF_SMARTCARD_REQUIRED ) from samba.dcerpc.misc import ( SEC_CHAN_BDC, @@ -921,6 +922,7 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): creds.set_upn(upn) creds.set_spn(spn) creds.set_type(account_type) + creds.set_user_account_control(account_control) self.creds_set_enctypes(creds) @@ -2005,6 +2007,7 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): 'assigned_policy': None, 'assigned_silo': None, 'logon_hours': None, + 'smartcard_required': False } account_opts = { @@ -2057,7 +2060,8 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): force_nt4_hash, assigned_policy, assigned_silo, - logon_hours): + logon_hours, + smartcard_required): if account_type is self.AccountType.USER: self.assertIsNone(delegation_to_spn) self.assertIsNone(delegation_from_dn) @@ -2080,6 +2084,8 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): user_account_control |= UF_NOT_DELEGATED if no_auth_data_required: user_account_control |= UF_NO_AUTH_DATA_REQUIRED + if smartcard_required: + user_account_control |= UF_SMARTCARD_REQUIRED if additional_details: details = {k: v for k, v in additional_details} @@ -2137,7 +2143,16 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): preserve=use_cache) expected_etypes = None - if force_nt4_hash: + + # We don't force fetching the keys other than the NT hash as + # how the server stores the unused KDC keys for the + # smartcard_required case is not important and makes unrelated + # tests break because of differences between Samba and + # Windows. + # + # The NT hash is different, as it is returned to the client in + # the PAC so is visible in the network behaviour. + if force_nt4_hash or smartcard_required: expected_etypes = {kcrypto.Enctype.RC4} keys = self.get_keys(creds, expected_etypes=expected_etypes) self.creds_set_keys(creds, keys) diff --git a/python/samba/tests/krb5/pkinit_tests.py b/python/samba/tests/krb5/pkinit_tests.py index 3d47c799f8680..afbbb45bf73c0 100755 --- a/python/samba/tests/krb5/pkinit_tests.py +++ b/python/samba/tests/krb5/pkinit_tests.py @@ -35,6 +35,8 @@ from cryptography.hazmat.primitives.asymmetric import dh, padding from cryptography.x509.oid import NameOID import samba.tests +from samba import credentials, generate_random_password, ntstatus +from samba.dcerpc import security, netlogon from samba.tests.krb5 import kcrypto from samba.tests.krb5.kdc_base_test import KDCBaseTest from samba.tests.krb5.raw_testcase import PkInit @@ -43,6 +45,7 @@ from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_CLIENT_NOT_TRUSTED, KDC_ERR_ETYPE_NOSUPP, KDC_ERR_MODIFIED, + KDC_ERR_POLICY, KDC_ERR_PREAUTH_EXPIRED, KDC_ERR_PREAUTH_FAILED, KDC_ERR_PREAUTH_REQUIRED, @@ -69,7 +72,7 @@ class PkInitTests(KDCBaseTest): self.do_asn1_print = global_asn1_print self.do_hexdump = global_hexdump - def _get_creds(self, account_type=KDCBaseTest.AccountType.USER): + def _get_creds(self, account_type=KDCBaseTest.AccountType.USER, use_cache=False, smartcard_required=False): """Return credentials with an account having a UPN for performing PK-INIT.""" samdb = self.get_samdb() @@ -77,7 +80,9 @@ class PkInitTests(KDCBaseTest): return self.get_cached_creds( account_type=account_type, - opts={'upn': f'{{account}}.{realm}@{realm}'}) + opts={'upn': f'{{account}}.{realm}@{realm}', + 'smartcard_required': smartcard_required}, + use_cache=use_cache) def test_pkinit_no_des3(self): """Test public-key PK-INIT without specifying the DES3 encryption @@ -568,6 +573,8 @@ class PkInitTests(KDCBaseTest): target_creds, *, expect_error=0, + expect_status=False, + expected_status=None, expect_edata=False, etypes=None, freshness=None, @@ -656,7 +663,9 @@ class PkInitTests(KDCBaseTest): expected_salt=creds.get_salt(), preauth_key=preauth_key, kdc_options=str(kdc_options), - expect_edata=expect_edata) + expect_edata=expect_edata, + expect_status=expect_status, + expected_status=expected_status) till = self.get_KerberosTime(offset=36000) diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index c77145ad60d23..0024604dafbc5 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -54,7 +54,9 @@ from samba.dcerpc.misc import ( SEC_CHAN_WKSTA, SEC_CHAN_BDC, ) - +from samba.dsdb import ( + UF_SMARTCARD_REQUIRED +) import samba.tests from samba.tests import TestCase @@ -408,6 +410,7 @@ class KerberosCredentials(Credentials): 'spn', 'tgs_supported_enctypes', 'upn', + 'user_account_control' ] non_etype_bits = ( @@ -439,6 +442,8 @@ class KerberosCredentials(Credentials): self.sid = None self.account_type = None + self.user_account_control = None + self._private_key = None def set_as_supported_enctypes(self, value): @@ -450,6 +455,9 @@ class KerberosCredentials(Credentials): def set_ap_supported_enctypes(self, value): self.ap_supported_enctypes = int(value) + def set_user_account_control(self, value): + self.user_account_control = int(value) + etype_map = collections.OrderedDict([ (kcrypto.Enctype.AES256, security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96), @@ -4760,7 +4768,10 @@ class RawKerberosTest(TestCase): creds = kdc_exchange_dict['creds'] nt_password = bytes(ntlm_package.nt_password.hash) - self.assertEqual(creds.get_nt_hash(), nt_password) + if creds.user_account_control & UF_SMARTCARD_REQUIRED: + self.assertNotEqual(creds.get_nt_hash(), nt_password) + else: + self.assertEqual(creds.get_nt_hash(), nt_password) lm_password = bytes(ntlm_package.lm_password.hash) self.assertEqual(bytes(16), lm_password) -- 2.39.1 From af58a16fb86a49b5f2c1ccb7fbb803c4e1d5eca9 Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Tue, 25 Jun 2024 12:51:48 +1200 Subject: [PATCH 4/6] tests/krb5: Allow creation of disabled accounts for testing BUG: https://bugzilla.samba.org/show_bug.cgi?id=15655 Signed-off-by: Jo Sutton Reviewed-by: Douglas Bagnall (backported from commit 6dc6168719cf232ac2c1d747f10aad9b13300c02) [jsutton@samba.org Fixed conflicting import statements in python/samba/tests/krb5/kdc_base_test.py] --- python/samba/tests/krb5/kdc_base_test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 20d2e614fb022..d983c631a468e 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -74,6 +74,7 @@ from samba.dsdb import ( GTYPE_SECURITY_DOMAIN_LOCAL_GROUP, GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP, + UF_ACCOUNTDISABLE, UF_NORMAL_ACCOUNT, UF_NOT_DELEGATED, UF_NO_AUTH_DATA_REQUIRED, @@ -2007,7 +2008,8 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): 'assigned_policy': None, 'assigned_silo': None, 'logon_hours': None, - 'smartcard_required': False + 'smartcard_required': False, + 'enabled': True, } account_opts = { @@ -2061,7 +2063,8 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): assigned_policy, assigned_silo, logon_hours, - smartcard_required): + smartcard_required, + enabled): if account_type is self.AccountType.USER: self.assertIsNone(delegation_to_spn) self.assertIsNone(delegation_from_dn) @@ -2086,6 +2089,8 @@ class KDCBaseTest(TestCaseInTempDir, RawKerberosTest): user_account_control |= UF_NO_AUTH_DATA_REQUIRED if smartcard_required: user_account_control |= UF_SMARTCARD_REQUIRED + if not enabled: + user_account_control |= UF_ACCOUNTDISABLE if additional_details: details = {k: v for k, v in additional_details} -- 2.39.1 From 2c0f82b609b9ad50d05d9028206a604214624364 Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Thu, 27 Jun 2024 12:29:52 +1200 Subject: [PATCH 5/6] tests/krb5: Add tests for errors produced when logging in with unusable accounts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Heimdal matches Windows in the no‐FAST case, but produces NTSTATUS codes when it shouldn’t in the FAST case. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15655 Signed-off-by: Jo Sutton Reviewed-by: Douglas Bagnall (cherry picked from commit c5ee0b60b20011aeaa60c2f549c2a78269c97c8f) --- python/samba/tests/krb5/lockout_tests.py | 210 ++++++++++++++++++++++- selftest/knownfail_heimdal_kdc | 8 + selftest/knownfail_mit_kdc | 5 + 3 files changed, 221 insertions(+), 2 deletions(-) diff --git a/python/samba/tests/krb5/lockout_tests.py b/python/samba/tests/krb5/lockout_tests.py index d91eb1df79d1f..c5d8dff6a2f10 100755 --- a/python/samba/tests/krb5/lockout_tests.py +++ b/python/samba/tests/krb5/lockout_tests.py @@ -58,11 +58,12 @@ from samba.tests import connect_samdb, env_get_var_value, env_loadparm from samba.tests.krb5.as_req_tests import AsReqBaseTest from samba.tests.krb5 import kcrypto -from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.kdc_tgs_tests import KdcTgsBaseTests from samba.tests.krb5.raw_testcase import KerberosCredentials import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 from samba.tests.krb5.rfc4120_constants import ( KDC_ERR_CLIENT_REVOKED, + KDC_ERR_KEY_EXPIRED, KDC_ERR_PREAUTH_FAILED, KRB_AS_REP, KRB_ERROR, @@ -518,7 +519,7 @@ def ldap_pwd_change(pipe, return ConnectionResult.SUCCESS -class LockoutTests(KDCBaseTest): +class LockoutTests(KdcTgsBaseTests): def setUp(self): super().setUp() @@ -611,6 +612,211 @@ class LockoutTests(KDCBaseTest): def test_lockout_transaction_kdc_ntstatus(self): self.do_lockout_transaction(partial(connect_kdc, expect_status=True)) + # Test that performing AS‐REQs with accounts in various states of + # unusability results in appropriate NTSTATUS and Kerberos error codes. + + def test_lockout_status_disabled(self): + self._run_lockout_status( + self._get_creds_disabled(), + expected_status=ntstatus.NT_STATUS_ACCOUNT_DISABLED, + expected_error=KDC_ERR_CLIENT_REVOKED, + ) + + def test_lockout_status_locked_out(self): + self._run_lockout_status( + self._get_creds_locked_out(), + expected_status=ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT, + expected_error=KDC_ERR_CLIENT_REVOKED, + ) + + def test_lockout_status_expired(self): + self._run_lockout_status( + self._get_creds_expired(), + expected_status=ntstatus.NT_STATUS_ACCOUNT_EXPIRED, + expected_error=KDC_ERR_CLIENT_REVOKED, + ) + + def test_lockout_status_must_change(self): + self._run_lockout_status( + self._get_creds_must_change(), + expected_status=ntstatus.NT_STATUS_PASSWORD_MUST_CHANGE, + expected_error=KDC_ERR_KEY_EXPIRED, + ) + + def test_lockout_status_password_expired(self): + self._run_lockout_status( + self._get_creds_password_expired(), + expected_status=ntstatus.NT_STATUS_PASSWORD_EXPIRED, + expected_error=KDC_ERR_KEY_EXPIRED, + ) + + # Test that performing the same AS‐REQs, this time with FAST, does not + # result in NTSTATUS codes. + + def test_lockout_status_disabled_fast(self): + self._run_lockout_status_fast( + self._get_creds_disabled(), expected_error=KDC_ERR_CLIENT_REVOKED + ) + + def test_lockout_status_locked_out_fast(self): + self._run_lockout_status_fast( + self._get_creds_locked_out(), expected_error=KDC_ERR_CLIENT_REVOKED + ) + + def test_lockout_status_expired_fast(self): + self._run_lockout_status_fast( + self._get_creds_expired(), expected_error=KDC_ERR_CLIENT_REVOKED + ) + + def test_lockout_status_must_change_fast(self): + self._run_lockout_status_fast( + self._get_creds_must_change(), expected_error=KDC_ERR_KEY_EXPIRED + ) + + def test_lockout_status_password_expired_fast(self): + self._run_lockout_status_fast( + self._get_creds_password_expired(), expected_error=KDC_ERR_KEY_EXPIRED + ) + + def _get_creds_disabled(self): + return self.get_cached_creds( + account_type=self.AccountType.USER, opts={"enabled": False} + ) + + def _get_creds_locked_out(self) -> KerberosCredentials: + samdb = self.get_samdb() + + user_creds = self.get_cached_creds( + account_type=self.AccountType.USER, use_cache=False + ) + user_dn = user_creds.get_dn() + + # Lock out the account. + + old_utf16pw = '"Secret007"'.encode("utf-16le") # invalid pwd + new_utf16pw = '"Secret008"'.encode("utf-16le") + + msg = ldb.Message(user_dn) + msg["0"] = ldb.MessageElement(old_utf16pw, ldb.FLAG_MOD_DELETE, "unicodePwd") + msg["1"] = ldb.MessageElement(new_utf16pw, ldb.FLAG_MOD_ADD, "unicodePwd") + + for _ in range(self.lockout_threshold): + try: + samdb.modify(msg) + except ldb.LdbError as err: + num, _ = err.args + + # We get an error, but the bad password count should + # still be updated. + self.assertEqual(num, ldb.ERR_CONSTRAINT_VIOLATION) + else: + self.fail("pwd change should have failed") + + # Ensure the account is locked out. + + res = samdb.search( + user_dn, scope=ldb.SCOPE_BASE, attrs=["msDS-User-Account-Control-Computed"] + ) + self.assertEqual(1, len(res)) + + uac = int(res[0].get("msDS-User-Account-Control-Computed", idx=0)) + self.assertTrue(uac & dsdb.UF_LOCKOUT) + + return user_creds + + def _get_creds_expired(self) -> KerberosCredentials: + return self.get_cached_creds( + account_type=self.AccountType.USER, + opts={"additional_details": self.freeze({"accountExpires": "1"})}, + ) + + def _get_creds_must_change(self) -> KerberosCredentials: + return self.get_cached_creds( + account_type=self.AccountType.USER, + opts={"additional_details": self.freeze({"pwdLastSet": "0"})}, + ) + + def _get_creds_password_expired(self) -> KerberosCredentials: + samdb = self.get_samdb() + self.addCleanup(samdb.set_maxPwdAge, samdb.get_maxPwdAge()) + low_pwd_age = -2 + samdb.set_maxPwdAge(low_pwd_age) + + return self.get_cached_creds(account_type=self.AccountType.USER) + + def _run_lockout_status( + self, + user_creds: KerberosCredentials, + *, + expected_status: int, + expected_error: int, + ) -> None: + user_name = user_creds.get_username() + cname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=user_name.split("/") + ) + + krbtgt_creds = self.get_krbtgt_creds() + realm = krbtgt_creds.get_realm() + + sname = self.get_krbtgt_sname() + + preauth_key = self.PasswordKey_from_creds(user_creds, kcrypto.Enctype.AES256) + + ts_enc_padata = self.get_enc_timestamp_pa_data_from_key(preauth_key) + padata = [ts_enc_padata] + + def _generate_padata_copy(_kdc_exchange_dict, _callback_dict, req_body): + return padata, req_body + + kdc_exchange_dict = self.as_exchange_dict( + creds=user_creds, + expected_crealm=realm, + expected_cname=cname, + expected_srealm=realm, + expected_sname=sname, + expected_account_name=user_name, + expected_supported_etypes=krbtgt_creds.tgs_supported_enctypes, + expect_edata=True, + expect_status=True, + expected_status=expected_status, + ticket_decryption_key=self.TicketDecryptionKey_from_creds(krbtgt_creds), + generate_padata_fn=_generate_padata_copy, + check_error_fn=self.generic_check_kdc_error, + check_rep_fn=None, + check_kdc_private_fn=self.generic_check_kdc_private, + expected_error_mode=expected_error, + expected_salt=user_creds.get_salt(), + preauth_key=preauth_key, + kdc_options=str(krb5_asn1.KDCOptions("postdated")), + pac_request=True, + ) + + # Try making a Kerberos AS-REQ to the KDC. This might fail, either due + # to the user's account being locked out or due to using the wrong + # password. + self._generic_kdc_exchange( + kdc_exchange_dict, + cname=cname, + realm=realm, + sname=sname, + till_time=self.get_KerberosTime(offset=36000), + etypes=self.get_default_enctypes(user_creds), + ) + + def _run_lockout_status_fast( + self, user_creds: KerberosCredentials, *, expected_error: int + ) -> None: + self._armored_as_req( + user_creds, + self.get_krbtgt_creds(), + self.get_tgt(self.get_mach_creds()), + expected_error=expected_error, + expect_edata=self.expect_padata_outer, + # FAST‐armored responses never contain an NTSTATUS code. + expect_status=False, + ) + def test_lockout_transaction_ntlm(self): self.do_lockout_transaction(connect_ntlm) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 811d320272901..b3df84e895902 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -156,3 +156,11 @@ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_no_compound_id_support_no_claims_valid_existing_device_claims_target_policy\(ad_dc\)$ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_no_compound_id_support_no_claims_valid_existing_device_claims\(ad_dc\)$ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_rodc_issued\(ad_dc\)$ +# +# Lockout tests +# +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_disabled_fast\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_expired_fast\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_locked_out_fast\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_must_change_fast\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_password_expired_fast\(ad_dc:local\)$ diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 7256fb3f1107c..6b67251a40443 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -532,6 +532,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.lockout_tests.samba.tests.krb5.lockout_tests.LockoutTests.test_lockout_transaction_kdc_ntstatus.ad_dc:local ^samba.tests.krb5.lockout_tests.samba.tests.krb5.lockout_tests.LockoutTests.test_lockout_transaction_rename_kdc.ad_dc:local ^samba.tests.krb5.lockout_tests.samba.tests.krb5.lockout_tests.LockoutTests.test_lockout_transaction_rename_kdc_ntstatus.ad_dc:local +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_disabled\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_expired\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_locked_out\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_must_change\(ad_dc:local\)$ +^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_password_expired\(ad_dc:local\)$ # # Encryption type tests # -- 2.39.1 From 01984f5d3d2f4813b3d799c0c5195834d0e4365b Mon Sep 17 00:00:00 2001 From: Jo Sutton Date: Wed, 12 Jun 2024 14:42:38 +1200 Subject: [PATCH 6/6] third_party/heimdal: Import lorikeet-heimdal-202406240121 (commit 4315286377278234be2f3b6d52225a17b6116d54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This lets us match the Windows FAST reply when the password is expired. Windows clients were upset by the NTSTATUS field in the edata, apparently interpreting it to mean “insufficient resource”. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15655 Signed-off-by: Jo Sutton Reviewed-by: Douglas Bagnall (cherry picked from commit fe90576871b5d644b9e888fd7a0b0351feaba750) --- selftest/knownfail_heimdal_kdc | 8 -------- third_party/heimdal/kdc/fast.c | 13 ++++++++++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index b3df84e895902..811d320272901 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -156,11 +156,3 @@ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_no_compound_id_support_no_claims_valid_existing_device_claims_target_policy\(ad_dc\)$ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_no_compound_id_support_no_claims_valid_existing_device_claims\(ad_dc\)$ ^samba\.tests\.krb5\.conditional_ace_tests\.samba\.tests\.krb5\.conditional_ace_tests\.TgsReqServicePolicyTests\.test_pac_device_info_rodc_issued\(ad_dc\)$ -# -# Lockout tests -# -^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_disabled_fast\(ad_dc:local\)$ -^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_expired_fast\(ad_dc:local\)$ -^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_locked_out_fast\(ad_dc:local\)$ -^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_must_change_fast\(ad_dc:local\)$ -^samba\.tests\.krb5\.lockout_tests\.samba\.tests\.krb5\.lockout_tests\.LockoutTests\.test_lockout_status_password_expired_fast\(ad_dc:local\)$ diff --git a/third_party/heimdal/kdc/fast.c b/third_party/heimdal/kdc/fast.c index bc77f74664c4b..d6b6ab2bbb361 100644 --- a/third_party/heimdal/kdc/fast.c +++ b/third_party/heimdal/kdc/fast.c @@ -482,7 +482,18 @@ _kdc_fast_mk_error(astgs_request_t r, heim_assert(r != NULL, "invalid request in _kdc_fast_mk_error"); - if (r->e_data.length) { + if (!armor_crypto && r->e_data.length) { + /* + * If we’re not armoring the response with FAST, r->e_data + * takes precedence over the e‐data that would normally be + * generated. r->e_data typically contains a + * Microsoft‐specific NTSTATUS code. + * + * But if FAST is in use, Windows Server suppresses the + * NTSTATUS code in favour of an armored response + * encapsulating an ordinary KRB‐ERROR. So we ignore r->e_data + * in that case. + */ e_data = &r->e_data; } else { ret = _kdc_fast_mk_e_data(r, -- 2.39.1