diff --git a/python/samba/tests/krb5/as_req_tests.py b/python/samba/tests/krb5/as_req_tests.py index c491ea6dce1..e8712b5bf8a 100755 --- a/python/samba/tests/krb5/as_req_tests.py +++ b/python/samba/tests/krb5/as_req_tests.py @@ -75,7 +75,7 @@ class AsReqBaseTest(KDCBaseTest): till = self.get_KerberosTime(offset=36000) if etypes is None: - etypes = self.get_default_enctypes() + etypes = self.get_default_enctypes(client_creds) if kdc_options is None: kdc_options = krb5_asn1.KDCOptions('forwardable') if expected_error is not None: @@ -194,7 +194,7 @@ class AsReqKerberosTests(AsReqBaseTest): expected_salt = client_creds.get_salt() if any(etype in initial_etypes - for etype in self.get_default_enctypes()): + for etype in self.get_default_enctypes(client_creds)): expected_error_mode = KDC_ERR_PREAUTH_REQUIRED else: expected_error_mode = KDC_ERR_ETYPE_NOSUPP diff --git a/python/samba/tests/krb5/group_tests.py b/python/samba/tests/krb5/group_tests.py index 9f9f1e60c89..c83e4178fa5 100755 --- a/python/samba/tests/krb5/group_tests.py +++ b/python/samba/tests/krb5/group_tests.py @@ -1871,7 +1871,7 @@ class GroupTests(KDCBaseTest): till = self.get_KerberosTime(offset=36000) kdc_options = '0' - etypes = self.get_default_enctypes() + etypes = self.get_default_enctypes(user_creds) # Perform an AS-REQ with the user account. as_rep, kdc_exchange_dict = self._test_as_exchange( diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index ba41a6ba688..f947d45428d 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -426,7 +426,9 @@ class KDCBaseTest(RawKerberosTest): return self._functional_level - def get_default_enctypes(self): + def get_default_enctypes(self, creds): + self.assertIsNotNone(creds, 'expected client creds to be passed in') + functional_level = self.get_domain_functional_level() default_enctypes = [] @@ -436,8 +438,8 @@ class KDCBaseTest(RawKerberosTest): default_enctypes.append(kcrypto.Enctype.AES256) default_enctypes.append(kcrypto.Enctype.AES128) - # RC4 should always be supported - default_enctypes.append(kcrypto.Enctype.RC4) + if self.expect_nt_hash or creds.get_workstation(): + default_enctypes.append(kcrypto.Enctype.RC4) return default_enctypes @@ -956,10 +958,12 @@ class KDCBaseTest(RawKerberosTest): return bind, identifier, attributes - def get_keys(self, dn, expected_etypes=None): + def get_keys(self, creds, expected_etypes=None): admin_creds = self.get_admin_creds() samdb = self.get_samdb() + dn = creds.get_dn() + bind, identifier, attributes = self.get_secrets( str(dn), destination_dsa_guid=misc.GUID(samdb.get_ntds_GUID()), @@ -998,7 +1002,7 @@ class KDCBaseTest(RawKerberosTest): keys[kcrypto.Enctype.RC4] = pwd.hex() if expected_etypes is None: - expected_etypes = self.get_default_enctypes() + expected_etypes = self.get_default_enctypes(creds) self.assertCountEqual(expected_etypes, keys) @@ -1044,7 +1048,7 @@ class KDCBaseTest(RawKerberosTest): fast_support=False, claims_support=False, compound_id_support=False): - default_enctypes = self.get_default_enctypes() + default_enctypes = self.get_default_enctypes(creds) supported_enctypes = KerberosCredentials.etypes_to_bits( default_enctypes) @@ -1657,7 +1661,7 @@ class KDCBaseTest(RawKerberosTest): expected_etypes = None if force_nt4_hash: expected_etypes = {kcrypto.Enctype.RC4} - keys = self.get_keys(dn, expected_etypes=expected_etypes) + keys = self.get_keys(creds, expected_etypes=expected_etypes) self.creds_set_keys(creds, keys) # Handle secret replication to the RODC. @@ -1841,7 +1845,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_kvno(rodc_kvno) creds.set_dn(krbtgt_dn) - keys = self.get_keys(krbtgt_dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) # The RODC krbtgt account should support the default enctypes, @@ -1894,7 +1898,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_kvno(rodc_kvno) creds.set_dn(dn) - keys = self.get_keys(dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) if self.get_domain_functional_level() >= DS_DOMAIN_FUNCTION_2008: @@ -1945,7 +1949,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_kvno(kvno) creds.set_dn(dn) - keys = self.get_keys(dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) # The krbtgt account should support the default enctypes, although @@ -1996,7 +2000,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_workstation(username[:-1]) creds.set_dn(dn) - keys = self.get_keys(dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) if self.get_domain_functional_level() >= DS_DOMAIN_FUNCTION_2008: @@ -2046,7 +2050,7 @@ class KDCBaseTest(RawKerberosTest): creds.set_kvno(kvno) creds.set_dn(dn) - keys = self.get_keys(dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) if self.get_domain_functional_level() >= DS_DOMAIN_FUNCTION_2008: @@ -2504,7 +2508,7 @@ class KDCBaseTest(RawKerberosTest): salt = creds.get_salt() - etype = self.get_default_enctypes() + etype = self.get_default_enctypes(creds) cname = self.PrincipalName_create(name_type=client_name_type, names=user_name.split('/')) if sname is None: @@ -3039,7 +3043,9 @@ class KDCBaseTest(RawKerberosTest): lm_verifier=None) num, _ = err.exception.args - if protected: + if not self.expect_nt_hash: + self.assertEqual(ntstatus.NT_STATUS_NTLM_BLOCKED, num) + elif protected: self.assertEqual(ntstatus.NT_STATUS_ACCOUNT_RESTRICTION, num) else: self.assertEqual(ntstatus.NT_STATUS_WRONG_PASSWORD, num) @@ -3055,7 +3061,9 @@ class KDCBaseTest(RawKerberosTest): password3=None) num, _ = err.exception.args - if protected: + if not self.expect_nt_hash: + self.assertEqual(ntstatus.NT_STATUS_NTLM_BLOCKED, num) + elif protected: self.assertEqual(ntstatus.NT_STATUS_ACCOUNT_RESTRICTION, num) else: self.assertEqual(ntstatus.NT_STATUS_WRONG_PASSWORD, num) @@ -3142,13 +3150,17 @@ class KDCBaseTest(RawKerberosTest): validation_level, netr_flags)) except NTSTATUSError as err: - self.assertTrue(protected, 'got unexpected error') - num, _ = err.args - if num != ntstatus.NT_STATUS_ACCOUNT_RESTRICTION: - raise + if protected: + if num != ntstatus.NT_STATUS_ACCOUNT_RESTRICTION: + raise + else: + self.assertFalse(self.expect_nt_hash, 'got unexpected error') + if num != ntstatus.NT_STATUS_NTLM_BLOCKED: + raise else: self.assertFalse(protected, 'expected error') + self.assertTrue(self.expect_nt_hash, 'expected error') self.assertEqual(1, authoritative) self.assertEqual(0, flags) diff --git a/python/samba/tests/krb5/lockout_tests.py b/python/samba/tests/krb5/lockout_tests.py index a8a85634c58..46e516a5366 100755 --- a/python/samba/tests/krb5/lockout_tests.py +++ b/python/samba/tests/krb5/lockout_tests.py @@ -129,7 +129,7 @@ def connect_kdc(pipe, krbtgt_decryption_key = ( as_req_base.TicketDecryptionKey_from_creds(krbtgt_creds)) - etypes = as_req_base.get_default_enctypes() + etypes = as_req_base.get_default_enctypes(user_creds) if expect_error: expected_error_modes = (KDC_ERR_CLIENT_REVOKED, diff --git a/python/samba/tests/krb5/protected_users_tests.py b/python/samba/tests/krb5/protected_users_tests.py index 8c325bf4747..c9ed23b5fb9 100755 --- a/python/samba/tests/krb5/protected_users_tests.py +++ b/python/samba/tests/krb5/protected_users_tests.py @@ -190,10 +190,15 @@ class ProtectedUsersTests(KDCBaseTest): client_creds.set_password(new_password) - self.get_keys(client_dn, - expected_etypes={kcrypto.Enctype.AES256, - kcrypto.Enctype.AES128, - kcrypto.Enctype.RC4}) + expected_etypes = { + kcrypto.Enctype.AES256, + kcrypto.Enctype.AES128, + } + if self.expect_nt_hash: + expected_etypes.add(kcrypto.Enctype.RC4) + + self.get_keys(client_creds, + expected_etypes=expected_etypes) # Test that DES-CBC-CRC cannot be used whether or not the user is # protected. diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 18a93caf93d..20e6a169dba 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -719,6 +719,12 @@ class RawKerberosTest(TestCaseInTempDir): forced_rc4 = '0' cls.forced_rc4 = bool(int(forced_rc4)) + expect_nt_hash = samba.tests.env_get_var_value('EXPECT_NT_HASH', + allow_missing=True) + if expect_nt_hash is None: + expect_nt_hash = '1' + cls.expect_nt_hash = bool(int(expect_nt_hash)) + def setUp(self): super().setUp() self.do_asn1_print = False @@ -977,15 +983,22 @@ class RawKerberosTest(TestCaseInTempDir): return c # Overridden by KDCBaseTest. At this level we don't know what actual - # enctypes are supported, so assume they all are. This matches the - # behaviour that tests expect by default. - def get_default_enctypes(self): - return [ + # enctypes are supported, so the best we can do is go by whether NT hashes + # are expected and whether the account is a workstation or not. This + # matches the behaviour that tests expect by default. + def get_default_enctypes(self, creds): + self.assertIsNotNone(creds) + + default_enctypes = [ kcrypto.Enctype.AES256, kcrypto.Enctype.AES128, - kcrypto.Enctype.RC4, ] + if self.expect_nt_hash or creds.get_workstation(): + default_enctypes.append(kcrypto.Enctype.RC4) + + return default_enctypes + def asn1_dump(self, name, obj, asn1_print=None): if asn1_print is None: asn1_print = self.do_asn1_print @@ -3955,7 +3968,8 @@ class RawKerberosTest(TestCaseInTempDir): return max(filter(lambda e: e in etypes, proposed_etypes), default=None) - supported_etypes = self.get_default_enctypes() + creds = kdc_exchange_dict['creds'] + supported_etypes = self.get_default_enctypes(creds) aes_etypes = set() if kcrypto.Enctype.AES256 in supported_etypes: diff --git a/python/samba/tests/krb5/spn_tests.py b/python/samba/tests/krb5/spn_tests.py index 42e7b3428d6..5bcc0bde369 100755 --- a/python/samba/tests/krb5/spn_tests.py +++ b/python/samba/tests/krb5/spn_tests.py @@ -199,7 +199,7 @@ class SpnTests(KDCBaseTest): kvno = int(res[0].get('msDS-KeyVersionNumber', idx=0)) creds.set_kvno(kvno) - keys = self.get_keys(rodc_dn) + keys = self.get_keys(creds) self.creds_set_keys(creds, keys) return creds