From: Joseph Sutton Date: Sun, 11 Dec 2022 22:05:05 +0000 (+1300) Subject: tests/krb5: Allow changing the SID of a user's PAC X-Git-Tag: talloc-2.4.1~1668 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bd4af42130c40fff5bcbab938da0f99e1b3ea4de;p=thirdparty%2Fsamba.git tests/krb5: Allow changing the SID of a user's PAC This lets us simulate a ticket of a user from another domain. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/krb5/group_tests.py b/python/samba/tests/krb5/group_tests.py index 0044203e81d..12bc3eff6b1 100755 --- a/python/samba/tests/krb5/group_tests.py +++ b/python/samba/tests/krb5/group_tests.py @@ -107,7 +107,11 @@ class GroupTests(KDCBaseTest): # Get a ticket with the SIDs in the PAC replaced with ones we specify. This # is useful for creating arbitrary tickets that can be used to perform a # TGS-REQ. - def ticket_with_sids(self, ticket, new_sids, domain_sid): + def ticket_with_sids(self, + ticket, + new_sids, + domain_sid, + user_rid): krbtgt_creds = self.get_krbtgt_creds() krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) @@ -117,14 +121,19 @@ class GroupTests(KDCBaseTest): modify_pac_fn = partial(self.set_pac_sids, new_sids=new_sids, - domain_sid=domain_sid) + domain_sid=domain_sid, + user_rid=user_rid) return self.modified_ticket(ticket, modify_pac_fn=modify_pac_fn, checksum_keys=checksum_keys) # Replace the SIDs in a PAC with 'new_sids'. - def set_pac_sids(self, pac, new_sids, domain_sid): + def set_pac_sids(self, + pac, + new_sids, + domain_sid, + user_rid): base_sids = [] extra_sids = [] resource_sids = [] @@ -167,6 +176,10 @@ class GroupTests(KDCBaseTest): else: self.fail(f'invalid SID type {sid_type}') + found_logon_info = True + + user_sid = security.dom_sid(f'{domain_sid}-{user_rid}') + pac_buffers = pac.buffers for pac_buffer in pac_buffers: # Find the LOGON_INFO PAC buffer. @@ -191,6 +204,9 @@ class GroupTests(KDCBaseTest): else: logon_info.info3.base.groups.rids = None + logon_info.info3.base.domain_sid = security.dom_sid(domain_sid) + logon_info.info3.base.rid = int(user_rid) + # Add Resource SIDs and set the RESOURCE_GROUPS flag as needed. logon_info.resource_groups.groups.count = len(resource_sids) if resource_sids: @@ -205,9 +221,18 @@ class GroupTests(KDCBaseTest): logon_info.info3.base.user_flags &= ~( netlogon.NETLOGON_RESOURCE_GROUPS) - break - else: - self.fail('no LOGON_INFO PAC buffer') + found_logon_info = True + + # Also replace the user's SID in the UPN DNS buffer. + elif pac_buffer.type == krb5pac.PAC_TYPE_UPN_DNS_INFO: + upn_dns_info_ex = pac_buffer.info.ex + + upn_dns_info_ex.objectsid = user_sid + + # But don't replace the user's SID in the Requester SID buffer, or + # we'll get a SID mismatch. + + self.assertTrue(found_logon_info, 'no LOGON_INFO PAC buffer') pac.buffers = pac_buffers @@ -1019,6 +1044,9 @@ class GroupTests(KDCBaseTest): # Optional SIDs to replace those in the PAC prior to a TGS-REQ. tgs_sids = case.pop('tgs:sids', None) + # Optional user SID to replace that in the PAC prior to a TGS-REQ. + tgs_user_sid = case.pop('tgs:user_sid', None) + # The SIDs we expect to see in the PAC after a AS-REQ or a TGS-REQ. as_expected = case.pop('as:expected', None) tgs_expected = case.pop('tgs:expected', None) @@ -1050,6 +1078,11 @@ class GroupTests(KDCBaseTest): 'specified compression for TGS request, but ' 'no expected SIDs provided') + if tgs_user_sid is not None: + self.assertIsNotNone(tgs_sids, + 'specified TGS-REQ user SID, but no ' + 'accompanying SIDs provided') + samdb = self.get_samdb() domain_sid = samdb.get_domain_sid() @@ -1083,9 +1116,19 @@ class GroupTests(KDCBaseTest): groups = self.setup_groups(samdb, group_setup, user_principal) del group_setup - expected_groups = self.map_sids(as_expected, groups, domain_sid) - tgs_sids_mapped = self.map_sids(tgs_sids, groups, domain_sid) - tgs_expected_mapped = self.map_sids(tgs_expected, groups, domain_sid) + if tgs_user_sid is None: + tgs_user_sid = user_sid + elif tgs_user_sid in groups: + tgs_user_sid = groups[tgs_user_sid].sid + + tgs_domain_sid, tgs_user_rid = tgs_user_sid.rsplit('-', 1) + + expected_groups = self.map_sids(as_expected, groups, + domain_sid) + tgs_sids_mapped = self.map_sids(tgs_sids, groups, + tgs_domain_sid) + tgs_expected_mapped = self.map_sids(tgs_expected, groups, + tgs_domain_sid) till = self.get_KerberosTime(offset=36000) kdc_options = '0' @@ -1128,13 +1171,20 @@ class GroupTests(KDCBaseTest): if tgs_sids is not None: # Replace the SIDs in the PAC with the ones provided by the test. - ticket = self.ticket_with_sids(ticket, tgs_sids_mapped, domain_sid) + ticket = self.ticket_with_sids(ticket, + tgs_sids_mapped, + tgs_domain_sid, + tgs_user_rid) target_creds, sname = self.get_target(tgs_to_krbtgt, tgs_compression) decryption_key = self.TicketDecryptionKey_from_creds(target_creds) subkey = self.RandomKey(ticket.session_key.etype) + requester_sid = None + if tgs_to_krbtgt: + requester_sid = user_sid + # Perform a TGS-REQ with the user account. kdc_exchange_dict = self.tgs_exchange_dict( @@ -1144,8 +1194,9 @@ class GroupTests(KDCBaseTest): expected_sname=sname, expected_account_name=user_name, expected_groups=tgs_expected_mapped, - expected_sid=user_sid, - expected_domain_sid=domain_sid, + expected_sid=tgs_user_sid, + expected_requester_sid=requester_sid, + expected_domain_sid=tgs_domain_sid, expected_supported_etypes=target_supported_etypes, ticket_decryption_key=decryption_key, check_rep_fn=self.generic_check_kdc_rep, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index a3fcc701ab0..beae57d07dc 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -2456,6 +2456,7 @@ class RawKerberosTest(TestCaseInTempDir): unexpected_groups=None, expected_upn_name=None, expected_sid=None, + expected_requester_sid=None, expected_domain_sid=None, expected_supported_etypes=None, expected_flags=None, @@ -2526,6 +2527,7 @@ class RawKerberosTest(TestCaseInTempDir): 'unexpected_groups': unexpected_groups, 'expected_upn_name': expected_upn_name, 'expected_sid': expected_sid, + 'expected_requester_sid': expected_requester_sid, 'expected_domain_sid': expected_domain_sid, 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, @@ -2592,6 +2594,7 @@ class RawKerberosTest(TestCaseInTempDir): unexpected_groups=None, expected_upn_name=None, expected_sid=None, + expected_requester_sid=None, expected_domain_sid=None, expected_supported_etypes=None, expected_flags=None, @@ -2663,6 +2666,7 @@ class RawKerberosTest(TestCaseInTempDir): 'unexpected_groups': unexpected_groups, 'expected_upn_name': expected_upn_name, 'expected_sid': expected_sid, + 'expected_requester_sid': expected_requester_sid, 'expected_domain_sid': expected_domain_sid, 'expected_supported_etypes': expected_supported_etypes, 'expected_flags': expected_flags, @@ -3378,12 +3382,15 @@ class RawKerberosTest(TestCaseInTempDir): expected_types.append(krb5pac.PAC_TYPE_ATTRIBUTES_INFO) expect_requester_sid = kdc_exchange_dict['expect_requester_sid'] + expected_requester_sid = kdc_exchange_dict['expected_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 expected_requester_sid is not None: + expect_requester_sid = True if expect_requester_sid: expected_types.append(krb5pac.PAC_TYPE_REQUESTER_SID) @@ -3482,8 +3489,11 @@ class RawKerberosTest(TestCaseInTempDir): and expect_requester_sid): requester_sid = pac_buffer.info.sid + if expected_requester_sid is None: + expected_requester_sid = expected_sid if expected_sid is not None: - self.assertEqual(expected_sid, str(requester_sid)) + self.assertEqual(expected_requester_sid, + str(requester_sid)) elif pac_buffer.type in {krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO, krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO}: