From 0ac800d0081fb893effaa555d3117102556a7b75 Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Fri, 3 Mar 2023 11:48:22 +1300 Subject: [PATCH] tests/krb5: Add tests for device info These tests verify that the groups in the device info structure in the PAC are exactly as expected under various scenarios. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- python/samba/tests/krb5/device_tests.py | 2045 +++++++++++++++++++++++ python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 35 + selftest/knownfail_mit_kdc | 48 + source4/selftest/tests.py | 4 + 5 files changed, 2133 insertions(+) create mode 100755 python/samba/tests/krb5/device_tests.py diff --git a/python/samba/tests/krb5/device_tests.py b/python/samba/tests/krb5/device_tests.py new file mode 100755 index 00000000000..8aed597b551 --- /dev/null +++ b/python/samba/tests/krb5/device_tests.py @@ -0,0 +1,2045 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Stefan Metzmacher 2020 +# Copyright (C) Catalyst.Net Ltd 2022 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys +import os + +sys.path.insert(0, 'bin/python') +os.environ['PYTHONUNBUFFERED'] = '1' + +import random +import re + +from samba.dcerpc import netlogon, security +from samba.tests import DynamicTestCase, env_get_var_value +from samba.tests.krb5 import kcrypto +from samba.tests.krb5.kdc_base_test import GroupType, KDCBaseTest, Principal +from samba.tests.krb5.raw_testcase import Krb5EncryptionKey, RawKerberosTest +from samba.tests.krb5.rfc4120_constants import ( + AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5, + KRB_TGS_REP, +) + +SidType = RawKerberosTest.SidType + +global_asn1_print = False +global_hexdump = False + + +@DynamicTestCase +class DeviceTests(KDCBaseTest): + # Placeholder objects that represent accounts undergoing testing. + user = object() + mach = object() + trust_user = object() + trust_mach = object() + + # Constants for group SID attributes. + default_attrs = security.SE_GROUP_DEFAULT_FLAGS + resource_attrs = default_attrs | security.SE_GROUP_RESOURCE + + asserted_identity = security.SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY + compounded_auth = security.SID_COMPOUNDED_AUTHENTICATION + + user_trust_domain = 'S-1-5-21-123-456-111' + mach_trust_domain = 'S-1-5-21-123-456-222' + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + # Some general information on how Windows handles device info: + + # All the SIDs in the computer's info3.sids end up in device.domain_groups + # (if they are in any domain), or in device.sids (if they are not). Even if + # netlogon.NETLOGON_EXTRA_SIDS is not set. + + # The remainder of the SIDs in device.domain_groups come from an LDAP + # search of the computer's domain-local groups. + + # None of the SIDs in the computer's logon_info.resource_groups.groups go + # anywhere. Even if netlogon.NETLOGON_RESOURCE_GROUPS is set. + + # In summary: + # info3.base.groups => device.groups + # info3.sids => device.sids (if not in a domain) + # info3.sids => device.domain_groups (if in a domain) + # searched-for domain-local groups => device.domain_groups + + # These searched-for domain-local groups are based on _all_ the groups in + # info3.base.groups and info3.sids. So if the account is no longer a member + # of a (universal or global) group that belongs to a domain-local group, + # but has that universal or global group in info3.base.groups or + # info3.sids, then the domain-local group will still get added to the + # PAC. But the resource groups don't affect this (presumably, they are + # being filtered out). Also, those groups the search is based on do not go + # in themselves, even if they are domain-local groups. + + cases = [ + { + # Make a TGS request to the krbtgt. + 'test': 'basic to krbtgt', + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + # Indicate this request is to the krbtgt. + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + # Make a TGS request to a service that supports SID compression. + 'test': 'device to service compressed', + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + # The compounded authentication SID indicates that we used FAST + # with a device's TGT. + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + # Make a TGS request to a service that lacks support for SID + # compression. + 'test': 'device to service uncompressed', + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # SID compression is unsupported. + 'tgs:compression': False, + # There is no change in the reply PAC. + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + # Make a TGS request to a service that lacks support for compound + # identity. + 'test': 'device to service no compound id', + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # Compound identity is unsupported. + 'tgs:compound_id': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + # The device info is still generated. + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'universal groups to krbtgt', + 'groups': { + # The user and computer each belong to a couple of universal + # groups. + 'group0': (GroupType.UNIVERSAL, {'group1'}), + 'group1': (GroupType.UNIVERSAL, {user}), + 'group2': (GroupType.UNIVERSAL, {'group3'}), + 'group3': (GroupType.UNIVERSAL, {mach}), + }, + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # The user's groups appear in the PAC of the TGT. + ('group0', SidType.BASE_SID, default_attrs), + ('group1', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # So too for the computer's groups. + ('group2', SidType.BASE_SID, default_attrs), + ('group3', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # The user's groups appear in the TGS reply PAC. + ('group0', SidType.BASE_SID, default_attrs), + ('group1', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'universal groups to service', + 'groups': { + 'group0': (GroupType.UNIVERSAL, {'group1'}), + 'group1': (GroupType.UNIVERSAL, {user}), + 'group2': (GroupType.UNIVERSAL, {'group3'}), + 'group3': (GroupType.UNIVERSAL, {mach}), + }, + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('group0', SidType.BASE_SID, default_attrs), + ('group1', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + ('group2', SidType.BASE_SID, default_attrs), + ('group3', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('group0', SidType.BASE_SID, default_attrs), + ('group1', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The computer's groups appear in the device info structure of + # the TGS reply PAC. + ('group2', SidType.BASE_SID, default_attrs), + ('group3', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'domain-local groups to krbtgt', + 'groups': { + # The user and computer each belong to a couple of domain-local + # groups. + 'group0': (GroupType.DOMAIN_LOCAL, {'group1'}), + 'group1': (GroupType.DOMAIN_LOCAL, {user}), + 'group2': (GroupType.DOMAIN_LOCAL, {'group3'}), + 'group3': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # The user's domain-local group memberships do not appear. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # Nor do the computer's. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # The user's groups do not appear in the TGS reply PAC. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'domain-local groups to service compressed', + 'groups': { + 'group0': (GroupType.DOMAIN_LOCAL, {'group1'}), + 'group1': (GroupType.DOMAIN_LOCAL, {user}), + 'group2': (GroupType.DOMAIN_LOCAL, {'group3'}), + 'group3': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # These groups appear as resource SIDs. + ('group0', SidType.RESOURCE_SID, resource_attrs), + ('group1', SidType.RESOURCE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The computer's groups appear together as resource SIDs. + frozenset([ + ('group2', SidType.RESOURCE_SID, resource_attrs), + ('group3', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'domain-local groups to service uncompressed', + 'groups': { + 'group0': (GroupType.DOMAIN_LOCAL, {'group1'}), + 'group1': (GroupType.DOMAIN_LOCAL, {user}), + 'group2': (GroupType.DOMAIN_LOCAL, {'group3'}), + 'group3': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'as:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + # The user's groups now appear as extra SIDs. + ('group0', SidType.EXTRA_SID, resource_attrs), + ('group1', SidType.EXTRA_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The computer's groups are still resource SIDs. + frozenset([ + ('group2', SidType.RESOURCE_SID, resource_attrs), + ('group3', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test what happens if the computer is removed from a group prior to + # the TGS request. + { + 'test': 'remove transitive domain-local groups to krbtgt', + 'groups': { + # The computer is transitively a member of a couple of + # domain-local groups... + 'dom-local-outer-0': (GroupType.DOMAIN_LOCAL, {'dom-local-inner'}), + 'dom-local-outer-1': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + # ...via another domain-local group and a universal group. + 'dom-local-inner': (GroupType.DOMAIN_LOCAL, {mach}), + 'universal-inner': (GroupType.UNIVERSAL, {mach}), + }, + # Just prior to the TGS request, the computer is removed from both + # inner groups. Domain-local groups will have not been added to the + # PAC at this point. + 'tgs:mach:removed': { + 'dom-local-inner', + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # Only the universal group appears in the PAC. + ('universal-inner', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'remove transitive domain-local groups to service compressed', + 'groups': { + 'dom-local-outer-0': (GroupType.DOMAIN_LOCAL, {'dom-local-inner'}), + 'dom-local-outer-1': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + 'dom-local-inner': (GroupType.DOMAIN_LOCAL, {mach}), + 'universal-inner': (GroupType.UNIVERSAL, {mach}), + }, + 'tgs:mach:removed': { + 'dom-local-inner', + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + ('universal-inner', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The universal group appears in the device info... + ('universal-inner', SidType.BASE_SID, default_attrs), + # ...along with the second domain-local group, even though the + # computer no longer belongs to it. + frozenset([ + ('dom-local-outer-1', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'remove transitive domain-local groups to service uncompressed', + 'groups': { + 'dom-local-outer-0': (GroupType.DOMAIN_LOCAL, {'dom-local-inner'}), + 'dom-local-outer-1': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + 'dom-local-inner': (GroupType.DOMAIN_LOCAL, {mach}), + 'universal-inner': (GroupType.UNIVERSAL, {mach}), + }, + 'tgs:mach:removed': { + 'dom-local-inner', + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + ('universal-inner', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + ('universal-inner', SidType.BASE_SID, default_attrs), + frozenset([ + ('dom-local-outer-1', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test what happens if the computer is added to a group prior to the + # TGS request. + { + 'test': 'add transitive domain-local groups to krbtgt', + 'groups': { + # We create a pair of groups, to be used presently. + 'dom-local-outer': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + 'universal-inner': (GroupType.UNIVERSAL, {}), + }, + # Just prior to the TGS request, the computer is added to the inner + # group. + 'tgs:mach:added': { + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'add transitive domain-local groups to service compressed', + 'groups': { + 'dom-local-outer': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + 'universal-inner': (GroupType.UNIVERSAL, {}), + }, + 'tgs:mach:added': { + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The computer was not a member of the universal group at the + # time of obtaining a TGT, and said group did not make it into + # the PAC. Group expansion is only concerned with domain-local + # groups, none of which the machine currently belongs + # to. Therefore, neither group is present in the device info + # structure. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'add transitive domain-local groups to service uncompressed', + 'groups': { + 'dom-local-outer': (GroupType.DOMAIN_LOCAL, {'universal-inner'}), + 'universal-inner': (GroupType.UNIVERSAL, {}), + }, + 'tgs:mach:added': { + 'universal-inner', + }, + 'as:mach:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Simulate a machine ticket coming in over a trust. + { + 'test': 'from trust domain-local groups to service compressed', + 'groups': { + # The machine belongs to a couple of domain-local groups in our + # domain. + 'foo': (GroupType.DOMAIN_LOCAL, {trust_mach}), + 'bar': (GroupType.DOMAIN_LOCAL, {'foo'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + # The machine SID is from a different domain. + 'tgs:mach_sid': trust_mach, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The domain-local groups end up in the device info. + frozenset([ + ('foo', SidType.RESOURCE_SID, resource_attrs), + ('bar', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'from trust domain-local groups to service uncompressed', + 'groups': { + 'foo': (GroupType.DOMAIN_LOCAL, {trust_mach}), + 'bar': (GroupType.DOMAIN_LOCAL, {'foo'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:mach_sid': trust_mach, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + frozenset([ + ('foo', SidType.RESOURCE_SID, resource_attrs), + ('bar', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Simulate the user ticket coming in over a trust. + { + 'test': 'user from trust domain-local groups to krbtgt', + 'groups': { + # The user belongs to a couple of domain-local groups in our + # domain. + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + }, + 'tgs:to_krbtgt': True, + # Both SIDs are from a different domain. + 'tgs:user_sid': trust_user, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # The dummy resource SID remains in the PAC. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + }, + { + 'test': 'user from trust domain-local groups to service compressed', + 'groups': { + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:user_sid': trust_user, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + ('group0', SidType.RESOURCE_SID, resource_attrs), + ('group1', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'user from trust domain-local groups to service uncompressed', + 'groups': { + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:user_sid': trust_user, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + ('group0', SidType.EXTRA_SID, resource_attrs), + ('group1', SidType.EXTRA_SID, resource_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Simulate both tickets coming in over a trust. + { + 'test': 'both from trust domain-local groups to krbtgt', + 'groups': { + # The user and machine each belong to a couple of domain-local + # groups in our domain. + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + 'group2': (GroupType.DOMAIN_LOCAL, {trust_mach}), + 'group3': (GroupType.DOMAIN_LOCAL, {'group2'}), + }, + 'tgs:to_krbtgt': True, + # Both SIDs are from a different domain. + 'tgs:user_sid': trust_user, + 'tgs:mach_sid': trust_mach, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-444', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # The dummy resource SID remains in the PAC. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + }, + { + 'test': 'both from trust domain-local groups to service compressed', + 'groups': { + # The machine belongs to a couple of domain-local groups in our + # domain. + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + 'group2': (GroupType.DOMAIN_LOCAL, {trust_mach}), + 'group3': (GroupType.DOMAIN_LOCAL, {'group2'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:user_sid': trust_user, + 'tgs:mach_sid': trust_mach, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-444', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + ('group0', SidType.RESOURCE_SID, resource_attrs), + ('group1', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # The domain-local groups end up in the device info. + frozenset([ + ('group2', SidType.RESOURCE_SID, resource_attrs), + ('group3', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'both from trust domain-local groups to service uncompressed', + 'groups': { + 'group0': (GroupType.DOMAIN_LOCAL, {trust_user}), + 'group1': (GroupType.DOMAIN_LOCAL, {'group0'}), + 'group2': (GroupType.DOMAIN_LOCAL, {trust_mach}), + 'group3': (GroupType.DOMAIN_LOCAL, {'group2'}), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': False, + 'tgs:user_sid': trust_user, + 'tgs:mach_sid': trust_mach, + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-333', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + # This dummy resource SID comes from the trusted domain. + (f'{mach_trust_domain}-444', SidType.RESOURCE_SID, resource_attrs), + }, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + ('group0', SidType.EXTRA_SID, resource_attrs), + ('group1', SidType.EXTRA_SID, resource_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + frozenset([ + ('group2', SidType.RESOURCE_SID, resource_attrs), + ('group3', SidType.RESOURCE_SID, resource_attrs), + ]), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test how resource SIDs are propagated into the device info structure. + { + 'test': 'mach resource sids', + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + # Of these SIDs, the Base SIDs and Extra SIDs are all + # propagated into the device info structure, regardless of + # their attrs, while the Resource SIDs are all dropped. + (123, SidType.BASE_SID, default_attrs), + (333, SidType.BASE_SID, default_attrs), + (333, SidType.BASE_SID, resource_attrs), + (1000, SidType.BASE_SID, resource_attrs), + (497, SidType.EXTRA_SID, resource_attrs), # the Claims Valid RID. + (333, SidType.RESOURCE_SID, default_attrs), + (498, SidType.RESOURCE_SID, resource_attrs), + (99999, SidType.RESOURCE_SID, default_attrs), + (12345678, SidType.RESOURCE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, default_attrs), + (333, SidType.BASE_SID, default_attrs), + (333, SidType.BASE_SID, resource_attrs), + (1000, SidType.BASE_SID, resource_attrs), + frozenset({ + (497, SidType.RESOURCE_SID, resource_attrs), + }), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Add a Base SID to the user's PAC, and confirm it is propagated into + # the PAC of the service ticket. + { + 'test': 'base sid to krbtgt', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'base sid to service', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Add a Base SID with resource attrs to the user's PAC, and confirm it + # is propagated into the PAC of the service ticket. + { + 'test': 'base sid resource attrs to krbtgt', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'base sid resource attrs to service', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (123, SidType.BASE_SID, resource_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Add a couple of Extra SIDs to the user's PAC, and confirm they are + # propagated into the PAC of the service ticket. + { + 'test': 'extra sids to krbtgt', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + ('S-1-5-2-3-5', SidType.EXTRA_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + ('S-1-5-2-3-5', SidType.EXTRA_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'extra sids to service', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + ('S-1-5-2-3-5', SidType.EXTRA_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + ('S-1-5-2-3-5', SidType.EXTRA_SID, resource_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test what happens if we remove the CLAIMS_VALID and ASSERTED_IDENTITY + # SIDs from either of the PACs, so we can see at what point these SIDs + # are added. + { + 'test': 'removed special sids to krbtgt', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + # We don't specify asserted identity or claims valid SIDs for + # the user... + }, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # ...nor for the computer. + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + # They don't show up in the service ticket. + }, + }, + { + 'test': 'removed special sids to service', + 'tgs:user:sids': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + ('S-1-5-2-3-4', SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # These special SIDs don't show up in the device info either. + }, + }, + # Test a group being the primary one for the user and machine. + { + 'test': 'primary universal to krbtgt', + 'groups': { + 'primary-user': (GroupType.UNIVERSAL, {user}), + 'primary-mach': (GroupType.UNIVERSAL, {mach}), + }, + # Set these groups as the account's primary groups. + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + # They appear in the PAC as normal. + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'primary universal to service compressed', + 'groups': { + 'primary-user': (GroupType.UNIVERSAL, {user}), + 'primary-mach': (GroupType.UNIVERSAL, {mach}), + }, + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'primary universal to service uncompressed', + 'groups': { + 'primary-user': (GroupType.UNIVERSAL, {user}), + 'primary-mach': (GroupType.UNIVERSAL, {mach}), + }, + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # SID compression is unsupported. + 'tgs:compression': False, + 'tgs:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test domain-local primary groups. + { + 'test': 'primary domain-local to krbtgt', + 'groups': { + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + # Though Windows normally disallows setting domain-locals group as + # primary groups, Samba does not. + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + # The domain-local groups appear as our primary GIDs, but do + # not appear in the base SIDs. + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'primary domain-local to service compressed', + 'groups': { + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'primary domain-local to service uncompressed', + 'groups': { + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'primary_group': 'primary-user', + 'mach:primary_group': 'primary-mach', + 'as:expected': { + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'as:mach:expected': { + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # SID compression is unsupported. + 'tgs:compression': False, + 'tgs:expected': { + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test the scenario where we belong to a now-domain-local group, and + # possess an old TGT issued when the group was still our primary one. + { + 'test': 'old primary domain-local to krbtgt', + 'groups': { + # Domain-local groups to which the accounts belong. + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'tgs:user:sids': { + # In the PACs, the groups have the attributes of an ordinary + # group... + ('primary-user', SidType.BASE_SID, default_attrs), + # ...and remain our primary ones. + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + # The groups don't change. + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'old primary domain-local to service compressed', + 'groups': { + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'tgs:user:sids': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + # The groups are added a second time to the PAC, now as + # resource groups. + ('primary-user', SidType.RESOURCE_SID, resource_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + frozenset([('primary-mach', SidType.RESOURCE_SID, resource_attrs)]), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'old primary domain-local to service uncompressed', + 'groups': { + 'primary-user': (GroupType.DOMAIN_LOCAL, {user}), + 'primary-mach': (GroupType.DOMAIN_LOCAL, {mach}), + }, + 'tgs:user:sids': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # SID compression is unsupported. + 'tgs:compression': False, + 'tgs:expected': { + ('primary-user', SidType.BASE_SID, default_attrs), + ('primary-user', SidType.PRIMARY_GID, None), + # This time, the group is added to Extra SIDs. + ('primary-user', SidType.EXTRA_SID, resource_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('primary-mach', SidType.BASE_SID, default_attrs), + ('primary-mach', SidType.PRIMARY_GID, None), + frozenset([('primary-mach', SidType.RESOURCE_SID, resource_attrs)]), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test the scenario where each account possesses an old TGT issued when + # a now-domain-local group was still its primary one. The accounts no + # longer belong to those groups, which themselves belong to other + # domain-local groups. + { + 'test': 'old primary domain-local transitive to krbtgt', + 'groups': { + 'user-outer': (GroupType.DOMAIN_LOCAL, {'user-inner'}), + 'user-inner': (GroupType.DOMAIN_LOCAL, {}), + 'mach-outer': (GroupType.DOMAIN_LOCAL, {'mach-inner'}), + 'mach-inner': (GroupType.DOMAIN_LOCAL, {}), + }, + 'tgs:user:sids': { + # In the PACs, the groups have the attributes of an ordinary + # group... + ('user-inner', SidType.BASE_SID, default_attrs), + # ...and remain our primary ones. + ('user-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('mach-inner', SidType.BASE_SID, default_attrs), + ('mach-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': True, + 'tgs:expected': { + # The groups don't change. + ('user-inner', SidType.BASE_SID, default_attrs), + ('user-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'old primary domain-local transitive to service compressed', + 'groups': { + 'user-outer': (GroupType.DOMAIN_LOCAL, {'user-inner'}), + 'user-inner': (GroupType.DOMAIN_LOCAL, {}), + 'mach-outer': (GroupType.DOMAIN_LOCAL, {'mach-inner'}), + 'mach-inner': (GroupType.DOMAIN_LOCAL, {}), + }, + 'tgs:user:sids': { + ('user-inner', SidType.BASE_SID, default_attrs), + ('user-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('mach-inner', SidType.BASE_SID, default_attrs), + ('mach-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:compression': True, + 'tgs:expected': { + ('user-inner', SidType.BASE_SID, default_attrs), + ('user-inner', SidType.PRIMARY_GID, None), + # The second resource groups are added a second time to the PAC + # as resource groups. + ('user-outer', SidType.RESOURCE_SID, resource_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('mach-inner', SidType.BASE_SID, default_attrs), + ('mach-inner', SidType.PRIMARY_GID, None), + frozenset([('mach-outer', SidType.RESOURCE_SID, resource_attrs)]), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + { + 'test': 'old primary domain-local transitive to service uncompressed', + 'groups': { + 'user-outer': (GroupType.DOMAIN_LOCAL, {'user-inner'}), + 'user-inner': (GroupType.DOMAIN_LOCAL, {}), + 'mach-outer': (GroupType.DOMAIN_LOCAL, {'mach-inner'}), + 'mach-inner': (GroupType.DOMAIN_LOCAL, {}), + }, + 'tgs:user:sids': { + ('user-inner', SidType.BASE_SID, default_attrs), + ('user-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:mach:sids': { + ('mach-inner', SidType.BASE_SID, default_attrs), + ('mach-inner', SidType.PRIMARY_GID, None), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + # SID compression is unsupported. + 'tgs:compression': False, + 'tgs:expected': { + ('user-inner', SidType.BASE_SID, default_attrs), + ('user-inner', SidType.PRIMARY_GID, None), + # This time, the group is added to Extra SIDs. + ('user-outer', SidType.EXTRA_SID, resource_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + ('mach-inner', SidType.BASE_SID, default_attrs), + ('mach-inner', SidType.PRIMARY_GID, None), + frozenset([('mach-outer', SidType.RESOURCE_SID, resource_attrs)]), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + frozenset([(security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs)]), + }, + }, + # Test how the various categories of SIDs are propagated into the + # device info structure. + { + 'test': 'device info sid grouping', + 'tgs:mach:sids': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # These base SIDs are simply propagated into the device info, + # irrespective of whatever attributes they have. + (1, SidType.BASE_SID, default_attrs), + (2, SidType.BASE_SID, 12345), + # Extra SIDs not from a domain are also propagated. + ('S-1-5-2-3-4', SidType.EXTRA_SID, 789), + ('S-1-5-20', SidType.EXTRA_SID, 999), + ('S-1-5-21', SidType.EXTRA_SID, 999), + ('S-1-6-0', SidType.EXTRA_SID, 999), + ('S-1-6-2-3-4', SidType.EXTRA_SID, 789), + # Extra SIDs from our own domain are collated into a group. + (3, SidType.EXTRA_SID, default_attrs), + (4, SidType.EXTRA_SID, 12345), + # Extra SIDs from other domains are collated into separate groups. + ('S-1-5-21-0-0-0-490', SidType.EXTRA_SID, 5), + ('S-1-5-21-0-0-0-491', SidType.EXTRA_SID, 6), + ('S-1-5-21-0-0-1-492', SidType.EXTRA_SID, 7), + ('S-1-5-21-0-0-1-493', SidType.EXTRA_SID, 8), + ('S-1-5-21-0-0-1-494', SidType.EXTRA_SID, 9), + # A non-domain SID (too few subauths), ... + ('S-1-5-21-242424-12345-2', SidType.EXTRA_SID, 1111111111), + # ... a domain SID, ... + ('S-1-5-21-242424-12345-321321-2', SidType.EXTRA_SID, 1111111111), + # ... and a non-domain SID (too many subauths). + ('S-1-5-21-242424-12345-321321-654321-2', SidType.EXTRA_SID, default_attrs), + # Special SIDs. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:to_krbtgt': False, + 'tgs:expected': { + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.PRIMARY_GID, None), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (compounded_auth, SidType.EXTRA_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + 'tgs:device:expected': { + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.BASE_SID, default_attrs), + (security.DOMAIN_RID_DOMAIN_MEMBERS, SidType.PRIMARY_GID, None), + # Base SIDs. + (1, SidType.BASE_SID, default_attrs), + (2, SidType.BASE_SID, 12345), + # Extra SIDs from other domains. + ('S-1-5-2-3-4', SidType.EXTRA_SID, 789), + ('S-1-5-20', SidType.EXTRA_SID, 999), + ('S-1-5-21', SidType.EXTRA_SID, 999), + ('S-1-6-0', SidType.EXTRA_SID, 999), + ('S-1-6-2-3-4', SidType.EXTRA_SID, 789), + # Extra SIDs from our own domain. + frozenset({ + (3, SidType.RESOURCE_SID, default_attrs), + (4, SidType.RESOURCE_SID, 12345), + }), + # Extra SIDs from other domains. + frozenset({ + ('S-1-5-21-0-0-0-490', SidType.RESOURCE_SID, 5), + ('S-1-5-21-0-0-0-491', SidType.RESOURCE_SID, 6), + # These SIDs end up placed with the CLAIMS_VALID SID. + (security.SID_CLAIMS_VALID, SidType.RESOURCE_SID, default_attrs), + }), + frozenset({ + ('S-1-5-21-0-0-1-492', SidType.RESOURCE_SID, 7), + ('S-1-5-21-0-0-1-493', SidType.RESOURCE_SID, 8), + ('S-1-5-21-0-0-1-494', SidType.RESOURCE_SID, 9), + }), + # Non-domain SID. + ('S-1-5-21-242424-12345-2', SidType.EXTRA_SID, 1111111111), + # Domain SID. + frozenset({ + ('S-1-5-21-242424-12345-321321-2', SidType.RESOURCE_SID, 1111111111), + }), + # Non-domain SID. + ('S-1-5-21-242424-12345-321321-654321-2', SidType.EXTRA_SID, default_attrs), + # Special SIDs. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + }, + }, + ] + + @classmethod + def setUpDynamicTestCases(cls): + FILTER = env_get_var_value('FILTER', allow_missing=True) + SKIP_INVALID = env_get_var_value('SKIP_INVALID', allow_missing=True) + + for case in cls.cases: + invalid = case.pop('configuration_invalid', False) + if SKIP_INVALID and invalid: + # Some group setups are invalid on Windows, so we allow them to + # be skipped. + continue + name = case.pop('test') + if FILTER and not re.search(FILTER, name): + continue + name = re.sub(r'\W+', '_', name) + + cls.generate_dynamic_test('test_device_info', name, + dict(case)) + + def _test_device_info_with_args(self, case): + # The group arrangement for the test. + group_setup = case.pop('groups', None) + + # Groups that should be the primary group for the user and machine + # respectively. + primary_group = case.pop('primary_group', None) + mach_primary_group = case.pop('mach:primary_group', None) + + # Whether the TGS-REQ should be directed to the krbtgt. + tgs_to_krbtgt = case.pop('tgs:to_krbtgt', None) + + # Whether the target server of the TGS-REQ should support compound + # identity or resource SID compression. + tgs_compound_id = case.pop('tgs:compound_id', None) + tgs_compression = case.pop('tgs:compression', None) + + # Optional SIDs to replace those in the PACs prior to a TGS-REQ. + tgs_user_sids = case.pop('tgs:user:sids', None) + tgs_mach_sids = case.pop('tgs:mach:sids', None) + + # Optional groups which the machine is added to or removed from prior + # to a TGS-REQ , to test how the groups in the device PAC are expanded. + tgs_mach_added = case.pop('tgs:mach:added', None) + tgs_mach_removed = case.pop('tgs:mach:removed', None) + + # Optional account SIDs to replace those in the PACs prior to a + # TGS-REQ. + tgs_user_sid = case.pop('tgs:user_sid', None) + tgs_mach_sid = case.pop('tgs:mach_sid', None) + + # User flags that may be set or reset in the PAC prior to a TGS-REQ. + tgs_mach_set_user_flags = case.pop('tgs:mach:set_user_flags', None) + tgs_mach_reset_user_flags = case.pop('tgs:mach:reset_user_flags', 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) + as_mach_expected = case.pop('as:mach:expected', None) + tgs_expected = case.pop('tgs:expected', None) + tgs_device_expected = case.pop('tgs:device:expected', None) + + # There should be no parameters remaining in the testcase. + self.assertFalse(case, 'unexpected parameters in testcase') + + if as_expected is None: + self.assertIsNotNone(tgs_expected, + 'no set of expected SIDs is provided') + + if as_mach_expected is None: + self.assertIsNotNone(tgs_expected, + 'no set of expected machine SIDs is provided') + + if tgs_to_krbtgt is None: + tgs_to_krbtgt = False + + if tgs_compound_id is None and not tgs_to_krbtgt: + # Assume the service supports compound identity by default. + tgs_compound_id = True + + if tgs_to_krbtgt: + self.assertIsNone(tgs_device_expected, + 'device SIDs are not added for a krbtgt request') + + self.assertIsNotNone(tgs_expected, + 'no set of expected TGS SIDs is provided') + + if tgs_user_sid is not None: + self.assertIsNotNone(tgs_user_sids, + 'specified TGS-REQ user SID, but no ' + 'accompanying user SIDs provided') + + if tgs_mach_sid is not None: + self.assertIsNotNone(tgs_mach_sids, + 'specified TGS-REQ mach SID, but no ' + 'accompanying machine SIDs provided') + + if tgs_mach_set_user_flags is None: + tgs_mach_set_user_flags = 0 + else: + self.assertIsNotNone(tgs_mach_sids, + 'specified TGS-REQ set user flags, but no ' + 'accompanying machine SIDs provided') + + if tgs_mach_reset_user_flags is None: + tgs_mach_reset_user_flags = 0 + else: + self.assertIsNotNone(tgs_mach_sids, + 'specified TGS-REQ reset user flags, but no ' + 'accompanying machine SIDs provided') + + user_use_cache = not group_setup and ( + not primary_group) + mach_use_cache = not group_setup and ( + not mach_primary_group) and ( + not tgs_mach_added) and ( + not tgs_mach_removed) + + samdb = self.get_samdb() + + domain_sid = samdb.get_domain_sid() + + # Create the user account. It needs to be freshly created rather than + # cached if there is a possibility of adding it to one or more groups. + user_creds = self.get_cached_creds( + account_type=self.AccountType.USER, + use_cache=user_use_cache) + user_dn = user_creds.get_dn() + user_sid = self.get_objectSid(samdb, user_dn) + user_name = user_creds.get_username() + + trust_user_rid = random.randint(2000, 0xfffffffe) + trust_user_sid = f'{self.user_trust_domain}-{trust_user_rid}' + + trust_mach_rid = random.randint(2000, 0xfffffffe) + trust_mach_sid = f'{self.mach_trust_domain}-{trust_mach_rid}' + + # Create the machine account. It needs to be freshly created rather + # than cached if there is a possibility of adding it to one or more + # groups. + mach_creds = self.get_cached_creds( + account_type=self.AccountType.COMPUTER, + use_cache=mach_use_cache) + mach_dn = mach_creds.get_dn() + mach_dn_str = str(mach_dn) + mach_sid = self.get_objectSid(samdb, mach_dn) + + user_principal = Principal(user_dn, user_sid) + mach_principal = Principal(mach_dn, mach_sid) + trust_user_principal = Principal(None, trust_user_sid) + trust_mach_principal = Principal(None, trust_mach_sid) + preexisting_groups = { + self.user: user_principal, + self.mach: mach_principal, + self.trust_user: trust_user_principal, + self.trust_mach: trust_mach_principal, + } + primary_groups = {} + if primary_group is not None: + primary_groups[user_principal] = primary_group + if mach_primary_group is not None: + primary_groups[mach_principal] = mach_primary_group + groups = self.setup_groups(samdb, + preexisting_groups, + group_setup, + primary_groups) + del group_setup + + 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_user_domain_sid, tgs_user_rid = tgs_user_sid.rsplit('-', 1) + + if tgs_mach_sid is None: + tgs_mach_sid = mach_sid + elif tgs_mach_sid in groups: + tgs_mach_sid = groups[tgs_mach_sid].sid + + tgs_mach_domain_sid, tgs_mach_rid = tgs_mach_sid.rsplit('-', 1) + + expected_groups = self.map_sids(as_expected, groups, + domain_sid) + mach_expected_groups = self.map_sids(as_mach_expected, groups, + domain_sid) + tgs_user_sids_mapped = self.map_sids(tgs_user_sids, groups, + tgs_user_domain_sid) + tgs_mach_sids_mapped = self.map_sids(tgs_mach_sids, groups, + tgs_mach_domain_sid) + tgs_expected_mapped = self.map_sids(tgs_expected, groups, + tgs_user_domain_sid) + tgs_device_expected_mapped = self.map_sids(tgs_device_expected, groups, + tgs_mach_domain_sid) + + user_tgt = self.get_tgt(user_creds, + expected_groups=expected_groups, + unexpected_groups=None) + + mach_tgt = self.get_tgt(mach_creds, + expected_groups=mach_expected_groups, + unexpected_groups=None) + + if tgs_user_sids is not None: + # Replace the SIDs in the user's PAC with the ones provided by the + # test. + user_tgt = self.ticket_with_sids(user_tgt, + tgs_user_sids_mapped, + tgs_user_domain_sid, + tgs_user_rid) + + if tgs_mach_sids is not None: + # Replace the SIDs in the machine's PAC with the ones provided by + # the test. + mach_tgt = self.ticket_with_sids(mach_tgt, + tgs_mach_sids_mapped, + tgs_mach_domain_sid, + tgs_mach_rid, + set_user_flags=tgs_mach_set_user_flags, + reset_user_flags=tgs_mach_reset_user_flags) + + if tgs_mach_removed is not None: + for removed in tgs_mach_removed: + group_dn = self.map_to_dn(removed, groups, domain_sid=None) + self.remove_from_group(mach_dn, group_dn) + + if tgs_mach_added is not None: + for added in tgs_mach_added: + group_dn = self.map_to_dn(added, groups, domain_sid=None) + self.add_to_group(mach_dn_str, group_dn, 'member', + expect_attr=False) + + subkey = self.RandomKey(user_tgt.session_key.etype) + + armor_subkey = self.RandomKey(subkey.etype) + explicit_armor_key = self.generate_armor_key(armor_subkey, + mach_tgt.session_key) + armor_key = kcrypto.cf2(explicit_armor_key.key, + subkey.key, + b'explicitarmor', + b'tgsarmor') + armor_key = Krb5EncryptionKey(armor_key, None) + + target_creds, sname = self.get_target( + to_krbtgt=tgs_to_krbtgt, + compound_id=tgs_compound_id, + compression=tgs_compression) + srealm = target_creds.get_realm() + + decryption_key = self.TicketDecryptionKey_from_creds( + target_creds) + + target_supported_etypes = target_creds.tgs_supported_enctypes + + etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) + + kdc_options = '0' + pac_options = '1' # claims support + + requester_sid = None + if tgs_to_krbtgt: + requester_sid = user_sid + + expect_resource_groups_flag = None + if tgs_mach_reset_user_flags & netlogon.NETLOGON_RESOURCE_GROUPS: + expect_resource_groups_flag = False + elif tgs_mach_set_user_flags & netlogon.NETLOGON_RESOURCE_GROUPS: + expect_resource_groups_flag = True + + # Perform a TGS-REQ with the user account. + + kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=user_tgt.crealm, + expected_cname=user_tgt.cname, + expected_srealm=srealm, + expected_sname=sname, + expected_account_name=user_name, + ticket_decryption_key=decryption_key, + generate_fast_fn=self.generate_simple_fast, + generate_fast_armor_fn=self.generate_ap_req, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=user_tgt, + armor_key=armor_key, + armor_tgt=mach_tgt, + armor_subkey=armor_subkey, + pac_options=pac_options, + authenticator_subkey=subkey, + kdc_options=kdc_options, + expect_pac=True, + expect_pac_attrs=tgs_to_krbtgt, + expect_pac_attrs_pac_request=tgs_to_krbtgt, + expected_sid=tgs_user_sid, + expected_requester_sid=requester_sid, + expected_domain_sid=tgs_user_domain_sid, + expected_device_domain_sid=tgs_mach_domain_sid, + expected_supported_etypes=target_supported_etypes, + expect_resource_groups_flag=expect_resource_groups_flag, + expected_groups=tgs_expected_mapped, + unexpected_groups=None, + expect_device_claims=None, + expect_device_info=not tgs_to_krbtgt, + expected_device_groups=tgs_device_expected_mapped) + + rep = self._generic_kdc_exchange(kdc_exchange_dict, + cname=None, + realm=srealm, + sname=sname, + etypes=etypes) + self.check_reply(rep, KRB_TGS_REP) + + +if __name__ == '__main__': + global_asn1_print = False + global_hexdump = False + import unittest + unittest.main() diff --git a/python/samba/tests/usage.py b/python/samba/tests/usage.py index 27c2810e800..229f8336ad8 100644 --- a/python/samba/tests/usage.py +++ b/python/samba/tests/usage.py @@ -118,6 +118,7 @@ EXCLUDE_USAGE = { 'python/samba/tests/krb5/group_tests.py', 'lib/compression/tests/scripts/three-byte-hash', 'python/samba/tests/krb5/etype_tests.py', + 'python/samba/tests/krb5/device_tests.py', } EXCLUDE_HELP = { diff --git a/selftest/knownfail_heimdal_kdc b/selftest/knownfail_heimdal_kdc index 45589036603..1248614ac80 100644 --- a/selftest/knownfail_heimdal_kdc +++ b/selftest/knownfail_heimdal_kdc @@ -154,3 +154,38 @@ ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_nested_group_addition_tgs_req_to_krbtgt.ad_dc ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_user_group_addition_tgs_req_to_krbtgt.ad_dc ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_user_group_addition_tgs_req_to_service.ad_dc +# +# Device info tests +# +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_add_transitive_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_add_transitive_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_resource_attrs_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_resource_attrs_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_both_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_both_from_trust_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_info_sid_grouping.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_no_compound_id.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_extra_sids_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_extra_sids_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_from_trust_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_mach_resource_sids.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_transitive_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_transitive_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_domain_local_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_domain_local_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_universal_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_universal_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_remove_transitive_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_remove_transitive_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_removed_special_sids_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_universal_groups_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_user_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_user_from_trust_domain_local_groups_to_service_uncompressed.ad_dc diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 5a40cbbe025..243ff608c24 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -2142,3 +2142,51 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_nested_group_addition_tgs_req_to_krbtgt.ad_dc ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_user_group_addition_tgs_req_to_krbtgt.ad_dc ^samba.tests.krb5.group_tests.samba.tests.krb5.group_tests.GroupTests.test_group_user_group_addition_tgs_req_to_service.ad_dc +# +# Device info tests +# +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_add_transitive_domain_local_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_add_transitive_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_add_transitive_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_resource_attrs_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_resource_attrs_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_base_sid_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_basic_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_both_from_trust_domain_local_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_both_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_both_from_trust_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_info_sid_grouping.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_no_compound_id.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_device_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_domain_local_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_extra_sids_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_extra_sids_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_from_trust_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_mach_resource_sids.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_transitive_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_transitive_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_old_primary_domain_local_transitive_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_domain_local_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_domain_local_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_domain_local_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_universal_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_universal_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_primary_universal_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_remove_transitive_domain_local_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_remove_transitive_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_remove_transitive_domain_local_groups_to_service_uncompressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_removed_special_sids_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_removed_special_sids_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_universal_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_universal_groups_to_service.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_user_from_trust_domain_local_groups_to_krbtgt.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_user_from_trust_domain_local_groups_to_service_compressed.ad_dc +^samba.tests.krb5.device_tests.samba.tests.krb5.device_tests.DeviceTests.test_device_info_user_from_trust_domain_local_groups_to_service_uncompressed.ad_dc diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index a325eb528b0..8924e22ee1d 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1778,6 +1778,10 @@ planoldpythontestsuite( 'ad_dc', 'samba.tests.krb5.claims_tests', environ=krb5_environ) +planoldpythontestsuite( + 'ad_dc', + 'samba.tests.krb5.device_tests', + environ=krb5_environ) planoldpythontestsuite( 'ad_dc:local', 'samba.tests.krb5.lockout_tests',