The branch, master has been updated via 612eeff2704 tests/krb5: Add tests of PAC group handling via 53f9ac4b6fc tests/krb5: Allow checking domain SID in PAC via 8556576d8df tests/krb5: Overhaul PAC logon info group checking via 5a613db6f51 tests/krb5: Add (un)expected group parameters to get_service_ticket() and get_tgt() via f59f6968003 tests/krb5: Allow creating accounts without Resource SID compression support via 29723765b31 tests/krb5: Allow adding multiple members to a group via 3a13e3b6667 tests/krb5: Allow creating groups with a specified type via 6674f67537d tests/krb5: Fix bits_to_etypes() to not fail on Resource SID compression bit via 90f39b69591 tests/krb5: Remember to pass in expected_groups parameter via 0161d375746 tests/krb5: Remove unused copy-and-paste remnant via bdbe5c5a324 s4:kdc: add initial support for compound claims via f96fbe6eb1f s4:kdc: fetch client_claims_blob from samba_kdc_get_pac_blobs() via 03250eefaaf s4:kdc: pass client_claims, device_info, device_claims into samba_make_krb5_pac() via aa62775eb4f s4-auth: Make PAC parameters const via 7d3416e8cb6 krb5: Detect support for krb5_const_pac type via 6fe6992258d wafsamba: Have CHECK_C_PROTOTYPE() pass through 'lib' into CHECK_CODE() via a3ee0ce255c wscript: Correctly determine dependencies for system Heimdal build via 77bb72d6720 build: Remove unused dependencies from be1431a8930 smbd: Don't hide directories with "hide new files timeout"
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 612eeff2704bf6705b2ccce4006f7d9c6f0ee06a Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:49:17 2022 +1300 tests/krb5: Add tests of PAC group handling In which we make AS and TGS requests and verify the SIDs we expect are returned in the PAC. Example command to test against Windows Server 2019 functional level 2016 with FAST enabled: ADMIN_USERNAME=Administrator ADMIN_PASSWORD=locDCpass1 \ CLAIMS_SUPPORT=1 COMPOUND_ID_SUPPORT=1 DC_SERVER=ADDC.EXAMPLE.COM \ DOMAIN=EXAMPLE EXPECT_PAC=1 FAST_SUPPORT=1 KRB5_CONFIG=krb5.conf \ PYTHONPATH=bin/python REALM=EXAMPLE.COM SERVER=ADDC.EXAMPLE.COM \ SKIP_INVALID=1 SMB_CONF_PATH=smb.conf STRICT_CHECKING=1 \ TKT_SIG_SUPPORT=1 python3 python/samba/tests/krb5/group_tests.py Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Nov 8 03:37:37 UTC 2022 on sn-devel-184 commit 53f9ac4b6fc41cef4966b1f5eca0485be621f786 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:55:36 2022 +1300 tests/krb5: Allow checking domain SID in PAC Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8556576d8df47710757ff4e32b04668fa5045daf Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:54:23 2022 +1300 tests/krb5: Overhaul PAC logon info group checking We can now verify attributes of SIDs and the PAC locations in which SIDs are placed. We also gain the ability to assert that no SIDs are present in the PAC other than the ones we expect. We lighten somewhat the requirement that no duplicates are present among the SIDs, as such a situation may arise even with Windows, especially if group types are changed. For example, if a Universal group containing a user is changed to a Domain-Local group in between an AS-REQ and a TGS-REQ, the group's SID will be added to the PAC once for each request. We only verify that there are no exact duplicates (SID, attributes, and PAC location all being identical). Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5a613db6f511cfe3739cfe04cefa84e4f6681c99 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:51:26 2022 +1300 tests/krb5: Add (un)expected group parameters to get_service_ticket() and get_tgt() Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f59f6968003a3b314fb21ca84548806c03ae0b0a Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:48:09 2022 +1300 tests/krb5: Allow creating accounts without Resource SID compression support Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 29723765b31866524b7db5c37600b8f6c9c0a2e7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:47:51 2022 +1300 tests/krb5: Allow adding multiple members to a group As well as passing in a single 'str', we can now choose to pass a collection of member DN strings. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3a13e3b6667909fbdafaf95be88106d138013f9c Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:46:53 2022 +1300 tests/krb5: Allow creating groups with a specified type This will be useful for testing the handling of Domain-Local groups. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6674f67537d0cac81e40c2b88e882944cb368ad7 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:46:38 2022 +1300 tests/krb5: Fix bits_to_etypes() to not fail on Resource SID compression bit It's not an encryption type bit, so we should ignore it here. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 90f39b695916bb99c7a8d3cb5d6a1153b61b1dec Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Nov 2 17:27:12 2022 +1300 tests/krb5: Remember to pass in expected_groups parameter Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0161d375746a1f5e145147d3ea4eb35f163bb5ec Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 14:48:48 2022 +1300 tests/krb5: Remove unused copy-and-paste remnant Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit bdbe5c5a3241488ff638350aaf6e74d157490bb9 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 25 00:28:01 2022 +0100 s4:kdc: add initial support for compound claims Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f96fbe6eb1f1f0fcf6ce2d72df5cc631f427bcf1 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 25 00:19:06 2022 +0100 s4:kdc: fetch client_claims_blob from samba_kdc_get_pac_blobs() The blob will be empty until we properly support claims. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 03250eefaaf21e819e8e855fc0db6ae25da6a9ee Author: Stefan Metzmacher <me...@samba.org> Date: Thu Feb 24 23:57:31 2022 +0100 s4:kdc: pass client_claims, device_info, device_claims into samba_make_krb5_pac() This allows us to add claims blobs to the PAC once we have the ability to create them. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit aa62775eb4ff6e4cd50d8ef932a2c299509c39d9 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Tue Nov 1 19:01:15 2022 +1300 s4-auth: Make PAC parameters const These functions have no need to modify the PACs passed in, and this change permits us to operate on const PACs in the KDC. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7d3416e8cb686453ecbedbc085073af95835001e Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Nov 2 14:56:34 2022 +1300 krb5: Detect support for krb5_const_pac type We can't unconditionally assume (as we did in third_party/heimdal_build/wscript_configure) that Heimdal has this type, since we may have an older system Heimdal that lacks it. We must also check whether krb5_pac_get_buffer() is usable with krb5_const_pac, and declare krb5_const_pac as a non-const typedef if not. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6fe6992258d2c59dfc8cb979deb25ba6020a1c06 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 17:35:58 2022 +1300 wafsamba: Have CHECK_C_PROTOTYPE() pass through 'lib' into CHECK_CODE() Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a3ee0ce255c7acb7abf58e70b75025b5fefdb275 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 17:35:35 2022 +1300 wscript: Correctly determine dependencies for system Heimdal build Previously, the call to CHECK_BUNDLED_SYSTEM() in check_system_heimdal_lib() could have us pick up MIT Kerberos headers when we should only be using system Heimdal headers. Now, we just perform an explicit check for the functions we require, which should avoid any use of the MIT libraries. We also remove some library checks for Heimdal components that we don't use directly, restricting the checks to only the functions we need. Finally, we no longer need to recurse into third_party/heimdal_build when performing a system Heimdal build. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 77bb72d67204b58d0ae7a183e2a8988597faf15c Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Thu Nov 3 17:31:20 2022 +1300 build: Remove unused dependencies We don't need to include these any more, and removing them allows us to simplify the build system for system Heimdal builds. Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: auth/kerberos/wscript_build | 2 +- buildtools/wafsamba/samba_conftests.py | 5 +- lib/krb5_wrap/krb5_samba.h | 13 +- lib/krb5_wrap/wscript_configure | 18 + python/samba/tests/krb5/group_tests.py | 1203 ++++++++++++++++++++++ python/samba/tests/krb5/kdc_base_test.py | 40 +- python/samba/tests/krb5/protected_users_tests.py | 6 - python/samba/tests/krb5/raw_testcase.py | 152 ++- python/samba/tests/krb5/s4u_tests.py | 41 +- python/samba/tests/usage.py | 1 + selftest/knownfail_heimdal_kdc | 21 + selftest/knownfail_mit_kdc | 35 + source4/auth/kerberos/kerberos_pac.c | 4 +- source4/auth/kerberos/wscript_build | 2 +- source4/kdc/mit_samba.c | 6 +- source4/kdc/pac-glue.c | 75 +- source4/kdc/pac-glue.h | 10 +- source4/kdc/wdc-samba4.c | 84 +- source4/libcli/wscript_build | 1 - source4/selftest/tests.py | 4 + third_party/heimdal_build/wscript_configure | 3 +- wscript | 1 + wscript_build_system_heimdal | 8 +- wscript_configure_system_heimdal | 41 +- 24 files changed, 1668 insertions(+), 108 deletions(-) create mode 100644 lib/krb5_wrap/wscript_configure create mode 100755 python/samba/tests/krb5/group_tests.py Changeset truncated at 500 lines: diff --git a/auth/kerberos/wscript_build b/auth/kerberos/wscript_build index 1fa1b51138d..bf8b05c5364 100644 --- a/auth/kerberos/wscript_build +++ b/auth/kerberos/wscript_build @@ -1,4 +1,4 @@ #!/usr/bin/env python bld.SAMBA_SUBSYSTEM('KRB5_PAC', source='gssapi_pac.c kerberos_pac.c gssapi_helper.c', - deps='gssapi_krb5 ndr-krb5pac krb5samba') + deps='gssapi ndr-krb5pac krb5samba') diff --git a/buildtools/wafsamba/samba_conftests.py b/buildtools/wafsamba/samba_conftests.py index ef632ba9033..2c3149c0fa2 100644 --- a/buildtools/wafsamba/samba_conftests.py +++ b/buildtools/wafsamba/samba_conftests.py @@ -126,7 +126,7 @@ def CHECK_LARGEFILE(conf, define='HAVE_LARGEFILE'): @conf -def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None, msg=None): +def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None, msg=None, lib=None): '''verify that a C prototype matches the one on the current system''' if not conf.CHECK_DECLS(function, headers=headers): return False @@ -138,7 +138,8 @@ def CHECK_C_PROTOTYPE(conf, function, prototype, define, headers=None, msg=None) headers=headers, link=False, execute=False, - msg=msg) + msg=msg, + lib=lib) @conf diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h index 93a010323bf..79178ac8008 100644 --- a/lib/krb5_wrap/krb5_samba.h +++ b/lib/krb5_wrap/krb5_samba.h @@ -135,7 +135,18 @@ typedef struct { #endif /* HAVE_E_DATA_POINTER_IN_KRB5_ERROR */ #ifndef HAVE_KRB5_CONST_PAC -typedef krb5_pac krb5_const_pac; +#ifdef KRB5_CONST_PAC_GET_BUFFER +typedef const struct krb5_pac_data *krb5_const_pac; +#else +/* + * Certain Heimdal versions include a version of krb5_pac_get_buffer() that is + * unusable in certain cases, taking a krb5_pac when a krb5_const_pac may be all + * that we can supply. Furthermore, MIT Kerberos doesn't declare krb5_const_pac + * at all. In such cases, we must declare krb5_const_pac as a non-const typedef + * so that the build can succeed. + */ +typedef struct krb5_pac_data *krb5_const_pac; +#endif #endif krb5_error_code smb_krb5_parse_name(krb5_context context, diff --git a/lib/krb5_wrap/wscript_configure b/lib/krb5_wrap/wscript_configure new file mode 100644 index 00000000000..b595eef679c --- /dev/null +++ b/lib/krb5_wrap/wscript_configure @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# Check whether we have the krb5_const_pac type, if we aren't sure already. +if conf.CONFIG_SET('HAVE_KRB5_CONST_PAC') or ( + conf.CHECK_TYPE('krb5_const_pac', + headers='krb5.h', + lib='krb5')): + # If the type is available, check whether krb5_pac_get_buffer() accepts it + # as its second parameter, or whether it takes krb5_pac instead. + conf.CHECK_C_PROTOTYPE('krb5_pac_get_buffer', + 'krb5_error_code krb5_pac_get_buffer(' + ' krb5_context context,' + ' krb5_const_pac p,' + ' uint32_t type,' + ' krb5_data *data)', + define='KRB5_CONST_PAC_GET_BUFFER', + headers='krb5.h', + lib='krb5') diff --git a/python/samba/tests/krb5/group_tests.py b/python/samba/tests/krb5/group_tests.py new file mode 100755 index 00000000000..471b06e6cbb --- /dev/null +++ b/python/samba/tests/krb5/group_tests.py @@ -0,0 +1,1203 @@ +#!/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 <http://www.gnu.org/licenses/>. +# + +import os +import re +import sys + +from enum import Enum +from functools import partial + +import ldb + +from samba.dcerpc import krb5pac, netlogon, samr, security +from samba.dsdb import ( + GTYPE_SECURITY_DOMAIN_LOCAL_GROUP, + GTYPE_SECURITY_GLOBAL_GROUP, + GTYPE_SECURITY_UNIVERSAL_GROUP, +) +from samba.tests import DynamicTestCase, env_get_var_value +from samba.tests.krb5 import kcrypto +from samba.tests.krb5.kdc_base_test import KDCBaseTest +from samba.tests.krb5.raw_testcase import RawKerberosTest +from samba.tests.krb5.rfc4120_constants import ( + KRB_TGS_REP, + NT_PRINCIPAL, +) + +SidType = RawKerberosTest.SidType + +sys.path.insert(0, 'bin/python') +os.environ['PYTHONUNBUFFERED'] = '1' + +global_asn1_print = False +global_hexdump = False + + +class GroupType(Enum): + GLOBAL = GTYPE_SECURITY_GLOBAL_GROUP + DOMAIN_LOCAL = GTYPE_SECURITY_DOMAIN_LOCAL_GROUP + UNIVERSAL = GTYPE_SECURITY_UNIVERSAL_GROUP + + +# This simple class encapsulates the DN and SID of a Principal. +class Principal: + def __init__(self, dn, sid): + if not isinstance(dn, ldb.Dn): + raise AssertionError(f'expected {dn} to be an ldb.Dn') + + self.dn = dn + self.sid = sid + + +@DynamicTestCase +class GroupTests(KDCBaseTest): + # A placeholder object that represents the user account undergoing testing. + user = object() + + # Constants for group SID attributes. + default_attrs = (security.SE_GROUP_MANDATORY | + security.SE_GROUP_ENABLED_BY_DEFAULT | + security.SE_GROUP_ENABLED) + resource_attrs = default_attrs | security.SE_GROUP_RESOURCE + + asserted_identity = security.SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY + + def setUp(self): + super().setUp() + self.do_asn1_print = global_asn1_print + self.do_hexdump = global_hexdump + + @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_group', name, + dict(case)) + + # Enable or disable resource SID compression on the krbtgt + # account. Depending on how the KDC chooses to handle SID compression, this + # may or may not have any real effect. + def set_krbtgt_sid_compression(self, compression): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_dn = krbtgt_creds.get_dn() + + samdb = self.get_samdb() + + # Get the current supported encryption types of the krbtgt account. + res = samdb.search(krbtgt_dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-SupportedEncryptionTypes']) + orig_msg = res[0] + krbtgt_enctypes = orig_msg.get( + 'msDS-SupportedEncryptionTypes', idx=0) + if krbtgt_enctypes is None: + # Setting the enctypes isn't likely to accomplish anything. + return + + krbtgt_enctypes = int(krbtgt_enctypes) + + # Enable or disable the compression bit. + if compression: + set_krbtgt_enctypes = krbtgt_enctypes | ( + security.KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED) + else: + set_krbtgt_enctypes = krbtgt_enctypes & ~( + security.KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED) + + if krbtgt_enctypes == set_krbtgt_enctypes: + # Nothing to do. + return + + msg = ldb.Message(krbtgt_dn) + msg['msDS-SupportedEncryptionTypes'] = ldb.MessageElement( + str(set_krbtgt_enctypes), + ldb.FLAG_MOD_REPLACE, + 'msDS-SupportedEncryptionTypes') + + # Clean up the change afterwards. + diff = samdb.msg_diff(msg, orig_msg) + self.addCleanup(samdb.modify, diff) + + samdb.modify(msg) + + # Make sure the value remains as we set it. + res = samdb.search(krbtgt_dn, + scope=ldb.SCOPE_BASE, + attrs=['msDS-SupportedEncryptionTypes']) + new_krbtgt_enctypes = res[0].get( + 'msDS-SupportedEncryptionTypes', idx=0) + self.assertIsNotNone(new_krbtgt_enctypes) + new_krbtgt_enctypes = int(new_krbtgt_enctypes) + self.assertEqual(set_krbtgt_enctypes, new_krbtgt_enctypes, + 'failed to set krbtgt supported enctypes') + + # Get a ticket with the SIDs in the PAC replaced with ones we specify. This + # is useful for creating arbitrary tickets that can be used to perform a + # TGS-REQ. + def ticket_with_sids(self, ticket, new_sids, domain_sid): + krbtgt_creds = self.get_krbtgt_creds() + krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds) + + checksum_keys = { + krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key + } + + modify_pac_fn = partial(self.set_pac_sids, + new_sids=new_sids, + domain_sid=domain_sid) + + return self.modified_ticket(ticket, + modify_pac_fn=modify_pac_fn, + checksum_keys=checksum_keys) + + # Replace the SIDs in a PAC with 'new_sids'. + def set_pac_sids(self, pac, new_sids, domain_sid): + base_sids = [] + extra_sids = [] + resource_sids = [] + + resource_domain = None + + # Filter our SIDs into three arrays depending on their ultimate + # location in the PAC. + for sid, sid_type, attrs in new_sids: + if sid_type is self.SidType.BASE_SID: + domain, rid = sid.rsplit('-', 1) + self.assertEqual(domain_sid, domain, + 'base SIDs must be in our domain') + + base_sid = samr.RidWithAttribute() + base_sid.rid = int(rid) + base_sid.attributes = attrs + + base_sids.append(base_sid) + elif sid_type is self.SidType.EXTRA_SID: + extra_sid = netlogon.netr_SidAttr() + extra_sid.sid = security.dom_sid(sid) + extra_sid.attributes = attrs + + extra_sids.append(extra_sid) + elif sid_type is self.SidType.RESOURCE_SID: + domain, rid = sid.rsplit('-', 1) + if resource_domain is None: + resource_domain = domain + else: + self.assertEqual(resource_domain, domain, + 'resource SIDs must share the same ' + 'domain') + + resource_sid = samr.RidWithAttribute() + resource_sid.rid = int(rid) + resource_sid.attributes = attrs + + resource_sids.append(resource_sid) + else: + self.fail(f'invalid SID type {sid_type}') + + pac_buffers = pac.buffers + for pac_buffer in pac_buffers: + # Find the LOGON_INFO PAC buffer. + if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_INFO: + logon_info = pac_buffer.info.info + + # Add Extra SIDs and set the EXTRA_SIDS flag as needed. + logon_info.info3.sidcount = len(extra_sids) + if extra_sids: + logon_info.info3.sids = extra_sids + logon_info.info3.base.user_flags |= ( + netlogon.NETLOGON_EXTRA_SIDS) + else: + logon_info.info3.sids = None + logon_info.info3.base.user_flags &= ~( + netlogon.NETLOGON_EXTRA_SIDS) + + # Add Base SIDs. + logon_info.info3.base.groups.count = len(base_sids) + if base_sids: + logon_info.info3.base.groups.rids = base_sids + else: + logon_info.info3.base.groups.rids = None + + # Add Resource SIDs and set the RESOURCE_GROUPS flag as needed. + logon_info.resource_groups.groups.count = len(resource_sids) + if resource_sids: + resource_domain = security.dom_sid(resource_domain) + logon_info.resource_groups.domain_sid = resource_domain + logon_info.resource_groups.groups.rids = resource_sids + logon_info.info3.base.user_flags |= ( + netlogon.NETLOGON_RESOURCE_GROUPS) + else: + logon_info.resource_groups.domain_sid = None + logon_info.resource_groups.groups.rids = None + logon_info.info3.base.user_flags &= ~( + netlogon.NETLOGON_RESOURCE_GROUPS) + + break + else: + self.fail('no LOGON_INFO PAC buffer') + + pac.buffers = pac_buffers + + return pac + + # A list of test cases. + cases = [ + # AS-REQ tests. + { + 'test': 'universal; as-req to krbtgt', + 'groups': { + # A Universal group containing the user. + 'foo': (GroupType.UNIVERSAL, {user}), + }, + # Make an AS-REQ to the krbtgt with the user's account. + 'as:to_krbtgt': True, + 'as:expected': { + # Ignoring the user ID, or base RID, expect the PAC to contain + # precisely the following SIDS in any order: + ('foo', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'universal; as-req to service', + 'groups': { + 'foo': (GroupType.UNIVERSAL, {user}), + }, + # The same again, but this time perform the AS-REQ to a service. + 'as:to_krbtgt': False, + 'as:expected': { + ('foo', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'global; as-req to krbtgt', + 'groups': { + # The behaviour should be the same with a Global group. + 'foo': (GroupType.GLOBAL, {user}), + }, + 'as:to_krbtgt': True, + 'as:expected': { + ('foo', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'global; as-req to service', + 'groups': { + 'foo': (GroupType.GLOBAL, {user}), + }, + 'as:to_krbtgt': False, + 'as:expected': { + ('foo', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'domain-local; as-req to krbtgt', + 'groups': { + # A Domain-local group containing the user. + 'foo': (GroupType.DOMAIN_LOCAL, {user}), + }, + 'as:to_krbtgt': True, + 'as:expected': { + # A TGT will not contain domain-local groups the user belongs + # to. + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'domain-local; compression; as-req to service', + 'groups': { + 'foo': (GroupType.DOMAIN_LOCAL, {user}), + }, + 'as:to_krbtgt': False, + 'as:expected': { + # However, a service ticket will include domain-local + # groups. The account supports SID compression, so they are + # added as resource SIDs. + ('foo', SidType.RESOURCE_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'domain-local; no compression; as-req to service', + 'groups': { + 'foo': (GroupType.DOMAIN_LOCAL, {user}), + }, + 'as:to_krbtgt': False, + # This time, the target account disclaims support for SID + # compression. + 'as:compression': False, + 'as:expected': { + # The SIDs in the PAC are the same, except the group SID is + # placed in Extra SIDs, not Resource SIDs. + ('foo', SidType.EXTRA_SID, resource_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'nested domain-local; as-req to krbtgt', + 'groups': { + # A Universal group containing a Domain-local group containing + # the user. + 'universal': (GroupType.UNIVERSAL, {'dom-local'}), + 'dom-local': (GroupType.DOMAIN_LOCAL, {user}), + }, + # It is not possible in Windows for a Universal group to contain a + # Domain-local group without exploiting bugs. This flag provides a + # convenient means by which these tests can be skipped. + 'configuration_invalid': True, + 'as:to_krbtgt': True, + 'as:expected': { + # While Windows would exclude the universal group from the PAC, + # expecting its inclusion is more sensible on the whole. + ('universal', SidType.BASE_SID, default_attrs), + (asserted_identity, SidType.EXTRA_SID, default_attrs), + (security.DOMAIN_RID_USERS, SidType.BASE_SID, default_attrs), + (security.SID_CLAIMS_VALID, SidType.EXTRA_SID, default_attrs), + }, + }, + { + 'test': 'nested domain-local; compression; as-req to service', + 'groups': { + 'universal': (GroupType.UNIVERSAL, {'dom-local'}), + 'dom-local': (GroupType.DOMAIN_LOCAL, {user}), + }, + 'configuration_invalid': True, + 'as:to_krbtgt': False, + 'as:expected': { + # A service ticket is expected to include both SIDs. -- Samba Shared Repository