1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

tests/krb5: Test performing NTLMSSP logons at different times

Signed-off-by: Jo Sutton <josutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Jo Sutton 2024-04-26 13:20:54 +12:00 committed by Andrew Bartlett
parent e5357c75a6
commit ad0740751e
2 changed files with 376 additions and 0 deletions

View File

@ -100,6 +100,12 @@ class GmsaSeries:
int(self.start_of_interval(n) + self.rollover_interval - two_minutes)
)
def outside_previous_password_valid_window(self, n: int) -> NtTime:
return NtTime(self.start_of_interval(n) + MAX_CLOCK_SKEW)
def within_previous_password_valid_window(self, n: int) -> NtTime:
return NtTime(self.outside_previous_password_valid_window(n) - 1)
class GmsaTests(GkdiBaseTest, KDCBaseTest):
def _as_req(
@ -1138,6 +1144,375 @@ class GmsaTests(GkdiBaseTest, KDCBaseTest):
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_when_current_key_is_valid(self):
"""Test that we can perform a gensec logon at a time when we are sure
the current gMSA password is valid."""
password_interval = 18
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_when_current_key_is_expired(self):
"""Test that we can perform a gensec logon using NTLMSSP at a time when
the current gMSA password has expired."""
password_interval = 40
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
# Set the time to the moment the original password has expired, and
# perform a gensec logon.
expired_time = series.start_of_interval(1)
self.set_db_time(samdb, expired_time)
# Calculate the password with which to authenticate.
current_series = self.gmsa_series_for_account(samdb, creds, password_interval)
managed_pwd = self.expected_gmsa_password_blob(
samdb,
creds,
current_series.interval_gkid(0),
previous_gkid=current_series.interval_gkid(-1),
query_expiration_gkid=current_series.interval_gkid(1),
)
# Set the new password.
self.assertIsNotNone(
managed_pwd.passwords.current, "current password must be present"
)
creds.set_utf16_password(managed_pwd.passwords.current)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_when_next_key_is_expired(self):
password_interval = 42
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
expired_time = series.start_of_interval(2)
self.set_db_time(samdb, expired_time)
# Calculate the password with which to authenticate.
current_series = self.gmsa_series_for_account(samdb, creds, password_interval)
managed_pwd = self.expected_gmsa_password_blob(
samdb,
creds,
current_series.interval_gkid(0),
previous_gkid=current_series.interval_gkid(-1),
query_expiration_gkid=current_series.interval_gkid(1),
)
# Set the new password.
self.assertIsNotNone(
managed_pwd.passwords.current, "current password must be present"
)
creds.set_utf16_password(managed_pwd.passwords.current)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_during_clock_skew_window_when_current_key_is_valid(
self,
):
password_interval = 43
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
self.set_db_time(samdb, series.during_skew_window(0))
# Calculate the password with which to authenticate.
current_series = self.gmsa_series_for_account(samdb, creds, password_interval)
managed_pwd = self.expected_gmsa_password_blob(
samdb,
creds,
current_series.interval_gkid(0),
previous_gkid=current_series.interval_gkid(-1),
query_expiration_gkid=current_series.interval_gkid(1),
)
# Set the new password.
self.assertIsNotNone(
managed_pwd.passwords.current, "current password must be present"
)
creds.set_utf16_password(managed_pwd.passwords.current)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_during_clock_skew_window_when_current_key_is_expired(
self,
):
password_interval = 44
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
self.set_db_time(samdb, series.during_skew_window(1))
# Calculate the password with which to authenticate.
current_series = self.gmsa_series_for_account(samdb, creds, password_interval)
managed_pwd = self.expected_gmsa_password_blob(
samdb,
creds,
current_series.interval_gkid(0),
previous_gkid=current_series.interval_gkid(-1),
query_expiration_gkid=current_series.interval_gkid(1),
)
# Set the new password.
self.assertIsNotNone(
managed_pwd.passwords.current, "current password must be present"
)
creds.set_utf16_password(managed_pwd.passwords.current)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_during_clock_skew_window_when_next_key_is_expired(
self,
):
password_interval = 47
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
self.set_db_time(samdb, series.during_skew_window(2))
# Calculate the password with which to authenticate.
current_series = self.gmsa_series_for_account(samdb, creds, password_interval)
managed_pwd = self.expected_gmsa_password_blob(
samdb,
creds,
current_series.interval_gkid(0),
previous_gkid=current_series.interval_gkid(-1),
query_expiration_gkid=current_series.interval_gkid(1),
)
# Set the new password.
self.assertIsNotNone(
managed_pwd.passwords.current, "current password must be present"
)
creds.set_utf16_password(managed_pwd.passwords.current)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_can_perform_gensec_ntlmssp_logon_with_previous_password_within_five_minutes(
self,
):
password_interval = 123
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
# Set the time to within five minutes of the original passwords expiry,
# and perform a gensec logon with the original password.
expired_time = series.within_previous_password_valid_window(1)
self.set_db_time(samdb, expired_time)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_cannot_perform_gensec_ntlmssp_logon_with_previous_but_one_password_within_five_minutes(
self,
):
password_interval = 123
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
# Set the time to within five minutes of the *following* passwords expiry,
# and perform a gensec logon with the original password.
expired_time = series.within_previous_password_valid_window(2)
self.set_db_time(samdb, expired_time)
# Expect the gensec logon to fail.
self.gensec_ntlmssp_logon(creds, samdb, expect_success=False)
def test_gmsa_can_perform_gensec_ntlmssp_logon_with_previous_password_beyond_five_minutes(
self,
):
password_interval = 456
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
# Set the time to five minutes beyond the original passwords expiry,
# and try to perform a gensec logon with the original password.
expired_time = series.outside_previous_password_valid_window(1)
self.set_db_time(samdb, expired_time)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(creds.get_sid()), token_sids[0])
def test_gmsa_cannot_perform_gensec_ntlmssp_logon_with_previous_password_five_minutes_apart(
self,
):
password_interval = 789
samdb = self.get_local_samdb()
series = self.gmsa_series(password_interval)
self.set_db_time(samdb, series.start_of_interval(0))
creds = self.gmsa_account(
samdb=samdb, interval=password_interval, kerberos_enabled=False
)
gmsa_sid = creds.get_sid()
# Set the time to after the original passwords expiry, and perform a
# gensec logon with the original password.
db_time = series.during_interval(1)
self.set_db_time(samdb, db_time)
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(gmsa_sid), token_sids[0])
# Set the time to not quite five minutes later, and perform a gensec
# logon with the original password.
self.set_db_time(samdb, NtTime(db_time + MAX_CLOCK_SKEW - 1))
# Perform a gensec logon.
session = self.gensec_ntlmssp_logon(creds, samdb)
# Ensure that the first SID contained within the security token is the gMSAs SID.
token = session.security_token
token_sids = token.sids
self.assertGreater(len(token_sids), 0)
# Ensure that they match.
self.assertEqual(security.dom_sid(gmsa_sid), token_sids[0])
# Now set the time to exactly five minutes later, and try to perform a
# gensec logon with the original password.
self.set_db_time(samdb, NtTime(db_time + MAX_CLOCK_SKEW))
# Expect the gensec logon to fail.
self.gensec_ntlmssp_logon(creds, samdb, expect_success=False)
def test_gmsa_can_perform_netlogon(self):
creds = self.gmsa_account(kerberos_enabled=False)
self._test_samlogon(

View File

@ -0,0 +1 @@
^samba\.tests\.krb5\.gmsa_tests\.samba\.tests\.krb5\.gmsa_tests\.GmsaTests\.test_gmsa_cannot_perform_gensec_ntlmssp_logon_with_previous_password_five_minutes_apart\(ad_dc:local\)$