From: Jo Sutton Date: Wed, 17 Apr 2024 22:13:04 +0000 (+1200) Subject: tests/krb5: Add tests that gMSA keys are updated in the database when appropriate X-Git-Tag: tdb-1.4.11~1069 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1b765edbc95b5cf9fead82c4e40af747123c6855;p=thirdparty%2Fsamba.git tests/krb5: Add tests that gMSA keys are updated in the database when appropriate Signed-off-by: Jo Sutton Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/krb5/gmsa_tests.py b/python/samba/tests/krb5/gmsa_tests.py index d65a5ad0e6a..0bdfd1687dd 100755 --- a/python/samba/tests/krb5/gmsa_tests.py +++ b/python/samba/tests/krb5/gmsa_tests.py @@ -51,7 +51,7 @@ from samba.gkdi import ( from samba.tests import connect_samdb from samba.tests.krb5 import kcrypto -from samba.tests.gkdi import GkdiBaseTest +from samba.tests.gkdi import GkdiBaseTest, ROOT_KEY_START_TIME from samba.tests.krb5.kdc_base_test import KDCBaseTest from samba.tests.krb5.raw_testcase import KerberosCredentials from samba.tests.krb5.rfc4120_constants import ( @@ -840,6 +840,137 @@ class GmsaTests(GkdiBaseTest, KDCBaseTest): ) self.check_managed_pwd(samdb, creds, expected_managed_pwd=expected) + def test_retrieving_managed_password_triggers_keys_update(self): + # Create a root key with a start time early enough to be usable at the + # time the gMSA is purported to be created. + samdb = self.get_samdb() + domain_dn = self.get_server_dn(samdb) + self.create_root_key(samdb, domain_dn, use_start_time=ROOT_KEY_START_TIME) + + password_interval = 16 + + local_samdb = self.get_local_samdb() + series = GmsaSeries(Gkid(100, 0, 0), gkdi_rollover_interval(password_interval)) + self.set_db_time(local_samdb, series.start_of_interval(0)) + + creds = self.gmsa_account(samdb=local_samdb, interval=password_interval) + dn = creds.get_dn() + + current_nt_time = self.current_nt_time(local_samdb) + self.set_db_time(local_samdb, current_nt_time) + + # Search the local database for the account’s keys. + res = local_samdb.search( + dn, scope=ldb.SCOPE_BASE, attrs=["unicodePwd", "supplementalCredentials"] + ) + self.assertEqual(1, len(res)) + + previous_nt_hash = res[0].get("unicodePwd", idx=0) + previous_supplemental_creds = self.unpack_supplemental_credentials( + res[0].get("supplementalCredentials", idx=0) + ) + + # Search for the managed password over LDAP, triggering an update of the + # keys in the database. + res = samdb.search(dn, scope=ldb.SCOPE_BASE, attrs=["msDS-ManagedPassword"]) + self.assertEqual(1, len(res)) + + # Verify that the password is present in the result. + managed_password = res[0].get("msDS-ManagedPassword", idx=0) + self.assertIsNotNone(managed_password, "should be allowed to view the password") + + # Search the local database again for the account’s keys, which should + # have been updated. + res = local_samdb.search( + dn, scope=ldb.SCOPE_BASE, attrs=["unicodePwd", "supplementalCredentials"] + ) + self.assertEqual(1, len(res)) + + nt_hash = res[0].get("unicodePwd", idx=0) + supplemental_creds = self.unpack_supplemental_credentials( + res[0].get("supplementalCredentials", idx=0) + ) + + self.assertNotEqual( + previous_nt_hash, nt_hash, "NT hash has not been updated (yet)" + ) + self.assertNotEqual( + previous_supplemental_creds, + supplemental_creds, + "supplementalCredentials has not been updated (yet)", + ) + + def test_authentication_triggers_keys_update(self): + # Create a root key with a start time early enough to be usable at the + # time the gMSA is purported to be created. But don’t create it on a + # local samdb with a specifically set time, because (if the key isn’t + # deleted later) we could end up with multiple keys with identical + # creation and start times, and tests failing when the test and the + # server don’t agree on which root key to use at a specific time. + samdb = self.get_samdb() + domain_dn = self.get_server_dn(samdb) + self.create_root_key(samdb, domain_dn, use_start_time=ROOT_KEY_START_TIME) + + password_interval = 16 + + local_samdb = self.get_local_samdb() + series = GmsaSeries(Gkid(100, 0, 0), gkdi_rollover_interval(password_interval)) + self.set_db_time(local_samdb, series.start_of_interval(0)) + + creds = self.gmsa_account(samdb=local_samdb, interval=password_interval) + dn = creds.get_dn() + + current_nt_time = self.current_nt_time(local_samdb) + self.set_db_time(local_samdb, current_nt_time) + + # Search the local database for the account’s keys. + res = local_samdb.search( + dn, scope=ldb.SCOPE_BASE, attrs=["unicodePwd", "supplementalCredentials"] + ) + self.assertEqual(1, len(res)) + + previous_nt_hash = res[0].get("unicodePwd", idx=0) + previous_supplemental_creds = self.unpack_supplemental_credentials( + res[0].get("supplementalCredentials", idx=0) + ) + + # Calculate the password with which to authenticate. + managed_pwd = self.expected_current_gmsa_password_blob( + samdb, creds, future_key_is_acceptable=False + ) + + # Set the new password. + self.assertIsNotNone( + managed_pwd.passwords.current, "current password must be present" + ) + creds.set_utf16_password(managed_pwd.passwords.current) + + # Perform an authentication using the new password. The KDC should + # recognize that the keys in the database are out of date and update + # them. + self._as_req(creds, self.get_service_creds(), kcrypto.Enctype.AES256) + + # Search the local database again for the account’s keys, which should + # have been updated. + res = local_samdb.search( + dn, scope=ldb.SCOPE_BASE, attrs=["unicodePwd", "supplementalCredentials"] + ) + self.assertEqual(1, len(res)) + + nt_hash = res[0].get("unicodePwd", idx=0) + supplemental_creds = self.unpack_supplemental_credentials( + res[0].get("supplementalCredentials", idx=0) + ) + + self.assertNotEqual( + previous_nt_hash, nt_hash, "NT hash has not been updated (yet)" + ) + self.assertNotEqual( + previous_supplemental_creds, + supplemental_creds, + "supplementalCredentials has not been updated (yet)", + ) + def test_gmsa_can_perform_gensec_ntlmssp_logon(self): creds = self.gmsa_account(kerberos_enabled=False) diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index f4366462d79..c16e6908ed3 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -159,3 +159,8 @@ ^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\)$ +# +# GMSA tests +# +^samba\.tests\.krb5\.gmsa_tests\.samba\.tests\.krb5\.gmsa_tests\.GmsaTests\.test_authentication_triggers_keys_update\(ad_dc:local\)$ +^samba\.tests\.krb5\.gmsa_tests\.samba\.tests\.krb5\.gmsa_tests\.GmsaTests\.test_retrieving_managed_password_triggers_keys_update\(ad_dc:local\)$ diff --git a/selftest/knownfail_mit_kdc_1_20 b/selftest/knownfail_mit_kdc_1_20 index e30836f1d12..8afe69b8a95 100644 --- a/selftest/knownfail_mit_kdc_1_20 +++ b/selftest/knownfail_mit_kdc_1_20 @@ -139,5 +139,7 @@ # # gMSA tests # +^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_authentication_triggers_keys_update\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_as_req_with_aes256\(ad_dc:local\)$ ^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_gmsa_can_perform_as_req_with_rc4\(ad_dc:local\)$ +^samba.tests.krb5.gmsa_tests.samba.tests.krb5.gmsa_tests.GmsaTests.test_retrieving_managed_password_triggers_keys_update\(ad_dc:local\)$