diff --git a/librpc/idl/security.idl b/librpc/idl/security.idl index 6b867595a284b4e324a7b037df0a81b0d42bdaf4..b8604741164a2051209cc22748130c523e45d665 100644 --- a/librpc/idl/security.idl +++ b/librpc/idl/security.idl @@ -298,7 +298,18 @@ interface security const string SID_NT_TRUSTED_INSTALLER = "S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464"; + /* + * This is added during the AS-REQ/AS-REP exchange after + * pre-authentication was successful. + */ const string SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY = "S-1-18-1"; + /* + * This is added during S4U2Self PAC creation. + * + * It won't replace a possible + * SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY + * during S4U2Proxy. + */ const string SID_SERVICE_ASSERTED_IDENTITY = "S-1-18-2"; const string SID_COMPOUNDED_AUTHENTICATION = "S-1-5-21-0-0-0-496"; diff --git a/python/samba/tests/krb5/kcrypto.py b/python/samba/tests/krb5/kcrypto.py index 4bf38d3c36bf98ec80671f9ca15035c0bacace71..79df0b58a3e3962f5840562d010aba28bcd191d3 100755 --- a/python/samba/tests/krb5/kcrypto.py +++ b/python/samba/tests/krb5/kcrypto.py @@ -51,7 +51,7 @@ os.environ["PYTHONUNBUFFERED"] = "1" from math import gcd from functools import reduce from struct import pack, unpack -from binascii import crc32 +from binascii import crc32, b2a_hex from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hmac from cryptography.hazmat.primitives.ciphers import algorithms as ciphers @@ -616,6 +616,9 @@ class Key(object): self.enctype = enctype self.contents = contents + def __str__(self): + return "enctype=%d contents=%s" % (self.enctype, + b2a_hex(self.contents).decode('ascii')) def seedsize(enctype): e = _get_enctype_profile(enctype) diff --git a/python/samba/tests/krb5/kdc_base_test.py b/python/samba/tests/krb5/kdc_base_test.py index 16e3f7a6a734e25f45f4648ae09c01063fb0e727..f680a6c3f672bbd7ee43fab336499372605cafb4 100644 --- a/python/samba/tests/krb5/kdc_base_test.py +++ b/python/samba/tests/krb5/kdc_base_test.py @@ -728,7 +728,7 @@ class KDCBaseTest(RawKerberosTest): 'revealed_to_rodc': False, 'revealed_to_mock_rodc': False, 'no_auth_data_required': False, - 'supported_enctypes': None, + 'supported_enctypes': 0x1C, 'not_delegated': False, 'delegation_to_spn': None, 'delegation_from_dn': None, diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 74d111d386b761151b7a73bece56c6686adc79ec..2ac4258802e5c90ca8e414cd87744177f8279fac 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -231,6 +231,10 @@ class Krb5EncryptionKey: self.ctype = EncTypeChecksum[self.etype] self.kvno = kvno + def __str__(self): + return "etype=%d ctype=%d kvno=%d key=%s" % ( + self.etype, self.ctype, self.kvno, self.key) + def encrypt(self, usage, plaintext): ciphertext = kcrypto.encrypt(self.key, usage, plaintext) return ciphertext @@ -1244,7 +1248,8 @@ class RawKerberosTest(TestCaseInTempDir): if etypes: etype = etypes[0] else: - etype = kcrypto.Enctype.RC4 + etype = kcrypto.Enctype.AES256 + #etype = kcrypto.Enctype.RC4 forced_key = creds.get_forced_key(etype) if forced_key is not None: @@ -1835,6 +1840,7 @@ class RawKerberosTest(TestCaseInTempDir): EncAuthorizationData_key=None, # optional EncAuthorizationData_usage=None): # optional + time.sleep(2) check_error_fn = kdc_exchange_dict['check_error_fn'] check_rep_fn = kdc_exchange_dict['check_rep_fn'] generate_fast_fn = kdc_exchange_dict['generate_fast_fn'] @@ -1859,7 +1865,12 @@ class RawKerberosTest(TestCaseInTempDir): outer_req = kdc_exchange_dict['outer_req'] if till_time is None: + till_time = self.get_KerberosTime(offset=3600) till_time = self.get_KerberosTime(offset=36000) + if req_msg_type == KRB_AS_REQ: + till_time = self.get_KerberosTime(offset=3600) + if req_msg_type == KRB_AS_REQ: + till_time = self.get_KerberosTime(offset=7200) if 'nonce' in kdc_exchange_dict: nonce = kdc_exchange_dict['nonce'] @@ -2045,6 +2056,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, expected_account_name=None, + expected_groups=None, + unexpected_groups=None, expected_upn_name=None, expected_sid=None, expected_supported_etypes=None, @@ -2105,6 +2118,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'expected_account_name': expected_account_name, + 'expected_groups': expected_groups, + 'unexpected_groups': unexpected_groups, 'expected_upn_name': expected_upn_name, 'expected_sid': expected_sid, 'expected_supported_etypes': expected_supported_etypes, @@ -2161,6 +2176,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=None, expected_sname=None, expected_account_name=None, + expected_groups=None, + unexpected_groups=None, expected_upn_name=None, expected_sid=None, expected_supported_etypes=None, @@ -2222,6 +2239,8 @@ class RawKerberosTest(TestCaseInTempDir): 'expected_srealm': expected_srealm, 'expected_sname': expected_sname, 'expected_account_name': expected_account_name, + 'expected_groups': expected_groups, + 'unexpected_groups': unexpected_groups, 'expected_upn_name': expected_upn_name, 'expected_sid': expected_sid, 'expected_supported_etypes': expected_supported_etypes, @@ -2796,6 +2815,8 @@ class RawKerberosTest(TestCaseInTempDir): require_strict=require_strict) expected_account_name = kdc_exchange_dict['expected_account_name'] + expected_groups = kdc_exchange_dict['expected_groups'] + unexpected_groups = kdc_exchange_dict['unexpected_groups'] expected_sid = kdc_exchange_dict['expected_sid'] expect_upn_dns_info_ex = kdc_exchange_dict['expect_upn_dns_info_ex'] @@ -2828,7 +2849,8 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(account_name, pac_buffer.info.account_name) elif pac_buffer.type == krb5pac.PAC_TYPE_LOGON_INFO: - logon_info = pac_buffer.info.info.info3.base + info3 = pac_buffer.info.info.info3 + logon_info = info3.base if expected_account_name is not None: self.assertEqual(expected_account_name, @@ -2838,6 +2860,30 @@ class RawKerberosTest(TestCaseInTempDir): expected_rid = int(expected_sid.rsplit('-', 1)[1]) self.assertEqual(expected_rid, logon_info.rid) + if expected_groups is not None: + self.assertIsNotNone(info3.sids) + got_sids = {str(sid_attr.sid) for sid_attr in info3.sids} + self.assertEqual(info3.sidcount, + len(got_sids), + 'Found duplicate SIDs') + + match_count = 0 + for g in expected_groups: + for sid_attr in info3.sids: + if g == str(sid_attr.sid): + match_count += 1 + self.assertEqual(match_count, len(expected_groups)) + + if unexpected_groups is not None: + match_count = 0 + + for g in unexpected_groups: + self.assertIsNotNone(info3.sids) + for sid_attr in info3.sids: + if g == str(sid_attr.sid): + match_count += 1 + self.assertEqual(match_count, 0) + elif pac_buffer.type == krb5pac.PAC_TYPE_UPN_DNS_INFO: upn_dns_info = pac_buffer.info upn_dns_info_ex = upn_dns_info.ex @@ -3939,6 +3985,8 @@ class RawKerberosTest(TestCaseInTempDir): kdc_options, renew_time=None, expected_account_name=None, + expected_groups=None, + unexpected_groups=None, expected_upn_name=None, expected_sid=None, expected_flags=None, @@ -3979,6 +4027,8 @@ class RawKerberosTest(TestCaseInTempDir): expected_srealm=expected_srealm, expected_sname=expected_sname, expected_account_name=expected_account_name, + expected_groups=expected_groups, + unexpected_groups=unexpected_groups, expected_upn_name=expected_upn_name, expected_sid=expected_sid, expected_supported_etypes=expected_supported_etypes, diff --git a/python/samba/tests/krb5/s4u_tests.py b/python/samba/tests/krb5/s4u_tests.py index 49dd89cd7640764ee6887656133f8a30cd519a84..25e4162ce8bca9547ce1daec21f48ac75af4799f 100755 --- a/python/samba/tests/krb5/s4u_tests.py +++ b/python/samba/tests/krb5/s4u_tests.py @@ -24,7 +24,7 @@ sys.path.insert(0, "bin/python") os.environ["PYTHONUNBUFFERED"] = "1" from samba import ntstatus -from samba.dcerpc import krb5pac, lsa +from samba.dcerpc import krb5pac, lsa, security from samba.tests import env_get_var_value from samba.tests.krb5.kcrypto import Cksumtype, Enctype @@ -35,6 +35,7 @@ from samba.tests.krb5.raw_testcase import ( ) from samba.tests.krb5.rfc4120_constants import ( AES256_CTS_HMAC_SHA1_96, + AD_IF_RELEVANT, ARCFOUR_HMAC_MD5, KDC_ERR_BADMATCH, KDC_ERR_BADOPTION, @@ -47,7 +48,9 @@ from samba.tests.krb5.rfc4120_constants import ( KU_PA_ENC_TIMESTAMP, KU_AS_REP_ENC_PART, KU_TGS_REP_ENC_PART_SUB_KEY, - NT_PRINCIPAL + KU_TGS_REQ_AUTH_DAT_SESSION, + KU_TGS_REQ_AUTH_DAT_SUBKEY, + NT_PRINCIPAL, ) import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1 @@ -199,24 +202,24 @@ class S4UKerberosTests(KDCBaseTest): # Using the checksum type from the tgt_session_key happens to work # everywhere - def test_s4u2self(self): + def _metze_test_s4u2self(self): msg_type = self._test_s4u2self() self.assertEqual(msg_type, 13) # Per spec, the checksum of PA-FOR-USER is HMAC_MD5, see [MS-SFU] 2.2.1 - def test_s4u2self_hmac_md5_checksum(self): + def _metze_test_s4u2self_hmac_md5_checksum(self): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.HMAC_MD5) self.assertEqual(msg_type, 13) - def test_s4u2self_md5_unkeyed_checksum(self): + def _metze_test_s4u2self_md5_unkeyed_checksum(self): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.MD5) self.assertEqual(msg_type, 30) - def test_s4u2self_sha1_unkeyed_checksum(self): + def _metze_test_s4u2self_sha1_unkeyed_checksum(self): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.SHA1) self.assertEqual(msg_type, 30) - def test_s4u2self_crc32_unkeyed_checksum(self): + def _metze_test_s4u2self_crc32_unkeyed_checksum(self): msg_type = self._test_s4u2self(pa_s4u2self_ctype=Cksumtype.CRC32) self.assertEqual(msg_type, 30) @@ -283,6 +286,8 @@ class S4UKerberosTests(KDCBaseTest): ARCFOUR_HMAC_MD5)) expect_edata = kdc_dict.pop('expect_edata', None) + expected_groups = kdc_dict.pop('expected_groups', None) + unexpected_groups = kdc_dict.pop('unexpected_groups', None) def generate_s4u2self_padata(_kdc_exchange_dict, _callback_dict, @@ -301,6 +306,7 @@ class S4UKerberosTests(KDCBaseTest): expected_srealm=realm, expected_sname=service_sname, expected_account_name=client_name, + unexpected_groups=unexpected_groups, expected_sid=sid, expected_flags=expected_flags, unexpected_flags=unexpected_flags, @@ -336,7 +342,7 @@ class S4UKerberosTests(KDCBaseTest): # Test performing an S4U2Self operation with a forwardable ticket. The # resulting ticket should have the 'forwardable' flag set. - def test_s4u2self_forwardable(self): + def _metze_test_s4u2self_forwardable(self): self._run_s4u2self_test( { 'client_opts': { @@ -350,7 +356,7 @@ class S4UKerberosTests(KDCBaseTest): # Test performing an S4U2Self operation with a forwardable ticket that does # not contain a PAC. The request should fail. - def test_s4u2self_no_pac(self): + def _metze_test_s4u2self_no_pac(self): def forwardable_no_pac(ticket): ticket = self.set_ticket_forwardable(ticket, flag=True) return self.remove_ticket_pac(ticket) @@ -369,7 +375,7 @@ class S4UKerberosTests(KDCBaseTest): # Test performing an S4U2Self operation without requesting a forwardable # ticket. The resulting ticket should not have the 'forwardable' flag set. - def test_s4u2self_without_forwardable(self): + def _metze_test_s4u2self_without_forwardable(self): self._run_s4u2self_test( { 'client_opts': { @@ -382,7 +388,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with a non-forwardable TGT. The 'forwardable' flag should # not be set on the ticket. - def test_s4u2self_not_forwardable(self): + def _metze_test_s4u2self_not_forwardable(self): self._run_s4u2self_test( { 'client_opts': { @@ -396,7 +402,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with the not_delegated flag set on the client. The # 'forwardable' flag should not be set on the ticket. - def test_s4u2self_client_not_delegated(self): + def _metze_test_s4u2self_client_not_delegated(self): self._run_s4u2self_test( { 'client_opts': { @@ -411,7 +417,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with a service not trusted to authenticate for delegation, # but having an empty msDS-AllowedToDelegateTo attribute. The 'forwardable' # flag should be set on the ticket. - def test_s4u2self_not_trusted_empty_allowed(self): + def _metze_test_s4u2self_not_trusted_empty_allowed(self): self._run_s4u2self_test( { 'client_opts': { @@ -430,7 +436,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with a service not trusted to authenticate for delegation # and having a non-empty msDS-AllowedToDelegateTo attribute. The # 'forwardable' flag should not be set on the ticket. - def test_s4u2self_not_trusted_nonempty_allowed(self): + def _metze_test_s4u2self_not_trusted_nonempty_allowed(self): self._run_s4u2self_test( { 'client_opts': { @@ -449,7 +455,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with a service trusted to authenticate for delegation and # having an empty msDS-AllowedToDelegateTo attribute. The 'forwardable' # flag should be set on the ticket. - def test_s4u2self_trusted_empty_allowed(self): + def _metze_test_s4u2self_trusted_empty_allowed(self): self._run_s4u2self_test( { 'client_opts': { @@ -468,7 +474,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with a service trusted to authenticate for delegation and # having a non-empty msDS-AllowedToDelegateTo attribute. The 'forwardable' # flag should be set on the ticket. - def test_s4u2self_trusted_nonempty_allowed(self): + def _metze_test_s4u2self_trusted_nonempty_allowed(self): self._run_s4u2self_test( { 'client_opts': { @@ -486,7 +492,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self with the sname in the request different to that of the # service. We expect an error. - def test_s4u2self_wrong_sname(self): + def _metze_test_s4u2self_wrong_sname(self): other_creds = self.get_cached_creds( account_type=self.AccountType.COMPUTER, opts={ @@ -513,7 +519,7 @@ class S4UKerberosTests(KDCBaseTest): # Do an S4U2Self where the service does not require authorization data. The # resulting ticket should still contain a PAC. - def test_s4u2self_no_auth_data_required(self): + def _metze_test_s4u2self_no_auth_data_required(self): self._run_s4u2self_test( { 'client_opts': { @@ -529,7 +535,21 @@ class S4UKerberosTests(KDCBaseTest): 'expected_flags': 'forwardable' }) + # Do an S4U2Self an check that the service asserted identity is part of + # the sids. + def _metze_test_s4u2self_asserted_identity(self): + self._run_s4u2self_test( + { + 'client_opts': { + 'not_delegated': False + }, + 'expected_groups': [security.SID_SERVICE_ASSERTED_IDENTITY], + 'unexpected_groups': [security.SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY] + }) + def _run_delegation_test(self, kdc_dict): + s4u2self = kdc_dict.pop('s4u2self', False) + client_opts = kdc_dict.pop('client_opts', None) client_creds = self.get_cached_creds( account_type=self.AccountType.USER, @@ -570,19 +590,88 @@ class S4UKerberosTests(KDCBaseTest): account_type=self.AccountType.COMPUTER, opts=service1_opts) + service1_tgt = self.get_tgt(service1_creds) + + client_username = client_creds.get_username() + client_realm = client_creds.get_realm() + client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, + names=[client_username]) + + service1_name = service1_creds.get_username()[:-1] + service1_realm = service1_creds.get_realm() + service1_service = 'host' + service1_sname = self.PrincipalName_create( + name_type=NT_PRINCIPAL, names=[service1_service, + service1_name]) + service1_decryption_key = self.TicketDecryptionKey_from_creds( + service1_creds) + + expect_pac = kdc_dict.pop('expect_pac', True) + + expected_groups = kdc_dict.pop('expected_groups', None) + unexpected_groups = kdc_dict.pop('unexpected_groups', None) + client_tkt_options = kdc_dict.pop('client_tkt_options', 'forwardable') expected_flags = krb5_asn1.TicketFlags(client_tkt_options) - client_tgt = self.get_tgt(client_creds, - kdc_options=client_tkt_options, - expected_flags=expected_flags) - client_service_tkt = self.get_service_ticket( - client_tgt, - service1_creds, - kdc_options=client_tkt_options, - expected_flags=expected_flags) + etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, + ARCFOUR_HMAC_MD5)) - service1_tgt = self.get_tgt(service1_creds) + if s4u2self: + def generate_s4u2self_padata(_kdc_exchange_dict, + _callback_dict, + req_body): + pa_s4u = self.PA_S4U2Self_create( + name=client_cname, + realm=client_realm, + tgt_session_key=service1_tgt.session_key, + ctype=None) + + return [pa_s4u], req_body + + s4u2self_expected_flags = krb5_asn1.TicketFlags('forwardable') + s4u2self_unexpected_flags = krb5_asn1.TicketFlags('0') + + s4u2self_kdc_options = krb5_asn1.KDCOptions('forwardable') + + s4u2self_authenticator_subkey = self.RandomKey(Enctype.AES256) + s4u2self_kdc_exchange_dict = self.tgs_exchange_dict( + expected_crealm=client_realm, + expected_cname=client_cname, + expected_srealm=service1_realm, + expected_sname=service1_sname, + expected_account_name=client_username, + expected_groups=expected_groups, + unexpected_groups=unexpected_groups, + expected_sid=sid, + expected_flags=s4u2self_expected_flags, + unexpected_flags=s4u2self_unexpected_flags, + ticket_decryption_key=service1_decryption_key, + generate_padata_fn=generate_s4u2self_padata, + check_rep_fn=self.generic_check_kdc_rep, + check_kdc_private_fn=self.generic_check_kdc_private, + tgt=service1_tgt, + authenticator_subkey=s4u2self_authenticator_subkey, + kdc_options=str(s4u2self_kdc_options), + expect_claims=False, + expect_edata=False) + + self._generic_kdc_exchange(s4u2self_kdc_exchange_dict, + cname=None, + realm=service1_realm, + sname=service1_sname, + etypes=etypes) + + client_service_tkt = s4u2self_kdc_exchange_dict['rep_ticket_creds'] + else: + client_tgt = self.get_tgt(client_creds, + kdc_options=client_tkt_options, + expected_flags=expected_flags) + client_service_tkt = self.get_service_ticket( + client_tgt, + service1_creds, + kdc_options=client_tkt_options, + expected_flags=expected_flags) modify_client_tkt_fn = kdc_dict.pop('modify_client_tkt_fn', None) if modify_client_tkt_fn is not None: @@ -598,14 +687,6 @@ class S4UKerberosTests(KDCBaseTest): if kdc_options is None: kdc_options = str(krb5_asn1.KDCOptions('cname-in-addl-tkt')) - client_username = client_creds.get_username() - client_realm = client_creds.get_realm() - client_cname = self.PrincipalName_create(name_type=NT_PRINCIPAL, - names=[client_username]) - - service1_name = service1_creds.get_username()[:-1] - service1_realm = service1_creds.get_realm() - service2_name = service2_creds.get_username()[:-1] service2_realm = service2_creds.get_realm() service2_service = 'host' @@ -633,10 +714,11 @@ class S4UKerberosTests(KDCBaseTest): pac_options = kdc_dict.pop('pac_options', None) - authenticator_subkey = self.RandomKey(Enctype.AES256) - - etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96, - ARCFOUR_HMAC_MD5)) + use_authenticator_subkey = kdc_dict.pop('use_authenticator_subkey', True) + if use_authenticator_subkey: + authenticator_subkey = self.RandomKey(Enctype.AES256) + else: + authenticator_subkey = None expected_proxy_target = service2_creds.get_spn() @@ -646,14 +728,14 @@ class S4UKerberosTests(KDCBaseTest): transited_service = f'host/{service1_name}@{service1_realm}' expected_transited_services.append(transited_service) - expect_pac = kdc_dict.pop('expect_pac', True) - kdc_exchange_dict = self.tgs_exchange_dict( expected_crealm=client_realm, expected_cname=client_cname, expected_srealm=service2_realm, expected_sname=service2_sname, expected_account_name=client_username, + expected_groups=expected_groups, + unexpected_groups=unexpected_groups, expected_sid=sid, expected_supported_etypes=service2_etypes, ticket_decryption_key=service2_decryption_key, @@ -672,12 +754,29 @@ class S4UKerberosTests(KDCBaseTest): expected_transited_services=expected_transited_services, expect_pac=expect_pac) + EncAuthorizationData = kdc_dict.pop('enc-authorization-data', None) + + if EncAuthorizationData is not None: + if authenticator_subkey is not None: + EncAuthorizationData_key = authenticator_subkey + EncAuthorizationData_usage = KU_TGS_REQ_AUTH_DAT_SUBKEY + else: + EncAuthorizationData_key = client_service_tkt.session_key + EncAuthorizationData_usage = KU_TGS_REQ_AUTH_DAT_SESSION + else: + EncAuthorizationData_key = None + EncAuthorizationData_usage = None + self._generic_kdc_exchange(kdc_exchange_dict, cname=None, realm=service2_realm, sname=service2_sname, etypes=etypes, - additional_tickets=additional_tickets) + till_time=self.get_KerberosTime(offset=72000), + additional_tickets=additional_tickets, + EncAuthorizationData=EncAuthorizationData, + EncAuthorizationData_key=EncAuthorizationData_key, + EncAuthorizationData_usage=EncAuthorizationData_usage) if not expected_error_mode: # Check whether the ticket contains a PAC. @@ -688,10 +787,18 @@ class S4UKerberosTests(KDCBaseTest): else: self.assertIsNone(pac) + if EncAuthorizationData is not None: + ticket_auth_data = ticket.ticket_private.get('authorization-data') + self.assertIsNotNone(ticket_auth_data) + print("EncAuthorizationData=%s" % type(EncAuthorizationData)) + print("EncAuthorizationData=%s" % EncAuthorizationData) + print("ticket_auth_data=%s" % type(ticket_auth_data)) + print("ticket_auth_data=%s" % ticket_auth_data) + # Ensure we used all the parameters given to us. self.assertEqual({}, kdc_dict) - def test_constrained_delegation(self): + def _metze_test_constrained_delegation(self): # Test constrained delegation. self._run_delegation_test( { @@ -699,7 +806,50 @@ class S4UKerberosTests(KDCBaseTest): 'allow_delegation': True }) - def test_constrained_delegation_no_auth_data_required(self): + def test_constrained_delegation_with_enc_auth_data_subkey(self): + # Test constrained delegation. + EncAuthorizationData = [] + relevant_elems = [] + auth_data999 = self.AuthorizationData_create(999, b'AuthorizationData999') + relevant_elems.append(auth_data999) + ad_relevant = self.der_encode(relevant_elems, asn1Spec=krb5_asn1.AD_IF_RELEVANT()) + ad_data = self.AuthorizationData_create(AD_IF_RELEVANT, ad_relevant) + EncAuthorizationData.append(ad_data) + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 'enc-authorization-data': EncAuthorizationData, + }) + + def _metze_test_constrained_delegation_authentication_asserted_identity(self): + # Test constrained delegation and check asserted identity is the + # authenticaten authority. Note that we should always find this + # SID for all the requests. Just S4U2Self will have a different SID. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 'expected_groups': [security.SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY], + 'unexpected_groups': [security.SID_SERVICE_ASSERTED_IDENTITY] + }) + + def _metze_test_constrained_delegation_service_asserted_identity(self): + # Test constrained delegation and check asserted identity is the + # service sid is there. This is a S4U2Proxy + S4U2Self test. + self._run_delegation_test( + { + 'expected_error_mode': 0, + 'allow_delegation': True, + 's4u2self': True, + 'service1_opts': { + 'trusted_to_auth_for_delegation': True, + }, + 'expected_groups': [security.SID_SERVICE_ASSERTED_IDENTITY], + 'unexpected_groups': [security.SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY] + }) + + def _metze_test_constrained_delegation_no_auth_data_required(self): # Test constrained delegation. self._run_delegation_test( { @@ -711,7 +861,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_pac': False }) - def test_constrained_delegation_existing_delegation_info(self): + def _metze_test_constrained_delegation_existing_delegation_info(self): # Test constrained delegation with an existing S4U_DELEGATION_INFO # structure in the PAC. @@ -726,7 +876,7 @@ class S4UKerberosTests(KDCBaseTest): 'expected_transited_services': services }) - def test_constrained_delegation_not_allowed(self): + def _metze_test_constrained_delegation_not_allowed(self): # Test constrained delegation when the delegating service does not # allow it. self._run_delegation_test( @@ -736,7 +886,7 @@ class S4UKerberosTests(KDCBaseTest): 'allow_delegation': False }) - def test_constrained_delegation_no_client_pac(self): + def _metze_test_constrained_delegation_no_client_pac(self): # Test constrained delegation when the client service ticket does not # contain a PAC. self._run_delegation_test( @@ -748,7 +898,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_no_service_pac(self): + def _metze_test_constrained_delegation_no_service_pac(self): # Test constrained delegation when the service TGT does not contain a # PAC. self._run_delegation_test( @@ -759,7 +909,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_no_client_pac_no_auth_data_required(self): + def _metze_test_constrained_delegation_no_client_pac_no_auth_data_required(self): # Test constrained delegation when the client service ticket does not # contain a PAC. self._run_delegation_test( @@ -774,7 +924,7 @@ class S4UKerberosTests(KDCBaseTest): } }) - def test_constrained_delegation_no_service_pac_no_auth_data_required(self): + def _metze_test_constrained_delegation_no_service_pac_no_auth_data_required(self): # Test constrained delegation when the service TGT does not contain a # PAC. self._run_delegation_test( @@ -789,7 +939,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_non_forwardable(self): + def _metze_test_constrained_delegation_non_forwardable(self): # Test constrained delegation with a non-forwardable ticket. self._run_delegation_test( { @@ -800,7 +950,7 @@ class S4UKerberosTests(KDCBaseTest): self.set_ticket_forwardable, flag=False) }) - def test_constrained_delegation_pac_options_rbcd(self): + def _metze_test_constrained_delegation_pac_options_rbcd(self): # Test constrained delegation, but with the RBCD bit set in the PAC # options. self._run_delegation_test( @@ -810,7 +960,7 @@ class S4UKerberosTests(KDCBaseTest): 'allow_delegation': True }) - def test_rbcd_no_auth_data_required(self): + def _metze_test_rbcd_no_auth_data_required(self): self._run_delegation_test( { 'expected_error_mode': 0, @@ -822,7 +972,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_pac': False }) - def test_rbcd_existing_delegation_info(self): + def _metze_test_rbcd_existing_delegation_info(self): # Test constrained delegation with an existing S4U_DELEGATION_INFO # structure in the PAC. @@ -838,7 +988,7 @@ class S4UKerberosTests(KDCBaseTest): 'expected_transited_services': services }) - def test_rbcd_not_allowed(self): + def _metze_test_rbcd_not_allowed(self): # Test resource-based constrained delegation when the target service # does not allow it. self._run_delegation_test( @@ -849,7 +999,7 @@ class S4UKerberosTests(KDCBaseTest): 'pac_options': '0001' # supports RBCD }) - def test_rbcd_no_client_pac_a(self): + def _metze_test_rbcd_no_client_pac_a(self): # Test constrained delegation when the client service ticket does not # contain a PAC, and an empty msDS-AllowedToDelegateTo attribute. self._run_delegation_test( @@ -861,7 +1011,7 @@ class S4UKerberosTests(KDCBaseTest): 'modify_client_tkt_fn': self.remove_ticket_pac }) - def test_rbcd_no_client_pac_b(self): + def _metze_test_rbcd_no_client_pac_b(self): # Test constrained delegation when the client service ticket does not # contain a PAC, and a non-empty msDS-AllowedToDelegateTo attribute. self._run_delegation_test( @@ -876,7 +1026,7 @@ class S4UKerberosTests(KDCBaseTest): } }) - def test_rbcd_no_service_pac(self): + def _metze_test_rbcd_no_service_pac(self): # Test constrained delegation when the service TGT does not contain a # PAC. self._run_delegation_test( @@ -888,7 +1038,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_rbcd_no_client_pac_no_auth_data_required_a(self): + def _metze_test_rbcd_no_client_pac_no_auth_data_required_a(self): # Test constrained delegation when the client service ticket does not # contain a PAC, and an empty msDS-AllowedToDelegateTo attribute. self._run_delegation_test( @@ -903,7 +1053,7 @@ class S4UKerberosTests(KDCBaseTest): } }) - def test_rbcd_no_client_pac_no_auth_data_required_b(self): + def _metze_test_rbcd_no_client_pac_no_auth_data_required_b(self): # Test constrained delegation when the client service ticket does not # contain a PAC, and a non-empty msDS-AllowedToDelegateTo attribute. self._run_delegation_test( @@ -921,7 +1071,7 @@ class S4UKerberosTests(KDCBaseTest): } }) - def test_rbcd_no_service_pac_no_auth_data_required(self): + def _metze_test_rbcd_no_service_pac_no_auth_data_required(self): # Test constrained delegation when the service TGT does not contain a # PAC. self._run_delegation_test( @@ -936,7 +1086,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_rbcd_non_forwardable(self): + def _metze_test_rbcd_non_forwardable(self): # Test resource-based constrained delegation with a non-forwardable # ticket. self._run_delegation_test( @@ -949,7 +1099,7 @@ class S4UKerberosTests(KDCBaseTest): self.set_ticket_forwardable, flag=False) }) - def test_rbcd_no_pac_options_a(self): + def _metze_test_rbcd_no_pac_options_a(self): # Test resource-based constrained delegation without the RBCD bit set # in the PAC options, and an empty msDS-AllowedToDelegateTo attribute. self._run_delegation_test( @@ -960,7 +1110,7 @@ class S4UKerberosTests(KDCBaseTest): 'pac_options': '1' # does not support RBCD }) - def test_rbcd_no_pac_options_b(self): + def _metze_test_rbcd_no_pac_options_b(self): # Test resource-based constrained delegation without the RBCD bit set # in the PAC options, and a non-empty msDS-AllowedToDelegateTo # attribute. @@ -975,7 +1125,7 @@ class S4UKerberosTests(KDCBaseTest): } }) - def test_bronze_bit_constrained_delegation_old_checksum(self): + def _metze_test_bronze_bit_constrained_delegation_old_checksum(self): # Attempt to modify the ticket without updating the PAC checksums. self._run_delegation_test( { @@ -989,7 +1139,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_bronze_bit_rbcd_old_checksum(self): + def _metze_test_bronze_bit_rbcd_old_checksum(self): # Attempt to modify the ticket without updating the PAC checksums. self._run_delegation_test( { @@ -1003,7 +1153,7 @@ class S4UKerberosTests(KDCBaseTest): flag=True, update_pac_checksums=False) }) - def test_constrained_delegation_missing_client_checksum(self): + def _metze_test_constrained_delegation_missing_client_checksum(self): # Present a user ticket without the required checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1022,7 +1172,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_missing_service_checksum(self): + def _metze_test_constrained_delegation_missing_service_checksum(self): # Present the service's ticket without the required checksums. for checksum in filter(lambda x: x != krb5pac.PAC_TYPE_TICKET_CHECKSUM, self.pac_checksum_types): @@ -1037,7 +1187,7 @@ class S4UKerberosTests(KDCBaseTest): self.remove_pac_checksum, checksum=checksum) }) - def test_rbcd_missing_client_checksum(self): + def _metze_test_rbcd_missing_client_checksum(self): # Present a user ticket without the required checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1057,7 +1207,7 @@ class S4UKerberosTests(KDCBaseTest): self.remove_pac_checksum, checksum=checksum) }) - def test_rbcd_missing_service_checksum(self): + def _metze_test_rbcd_missing_service_checksum(self): # Present the service's ticket without the required checksums. for checksum in filter(lambda x: x != krb5pac.PAC_TYPE_TICKET_CHECKSUM, self.pac_checksum_types): @@ -1073,7 +1223,7 @@ class S4UKerberosTests(KDCBaseTest): self.remove_pac_checksum, checksum=checksum) }) - def test_constrained_delegation_zeroed_client_checksum(self): + def _metze_test_constrained_delegation_zeroed_client_checksum(self): # Present a user ticket with invalid checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1087,7 +1237,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_zeroed_service_checksum(self): + def _metze_test_constrained_delegation_zeroed_service_checksum(self): # Present the service's ticket with invalid checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1108,7 +1258,7 @@ class S4UKerberosTests(KDCBaseTest): self.zeroed_pac_checksum, checksum=checksum) }) - def test_rbcd_zeroed_client_checksum(self): + def _metze_test_rbcd_zeroed_client_checksum(self): # Present a user ticket with invalid checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1123,7 +1273,7 @@ class S4UKerberosTests(KDCBaseTest): self.zeroed_pac_checksum, checksum=checksum) }) - def test_rbcd_zeroed_service_checksum(self): + def _metze_test_rbcd_zeroed_service_checksum(self): # Present the service's ticket with invalid checksums. for checksum in self.pac_checksum_types: with self.subTest(checksum=checksum): @@ -1146,7 +1296,7 @@ class S4UKerberosTests(KDCBaseTest): unkeyed_ctypes = {Cksumtype.MD5, Cksumtype.SHA1, Cksumtype.CRC32} - def test_constrained_delegation_unkeyed_client_checksum(self): + def _metze_test_constrained_delegation_unkeyed_client_checksum(self): # Present a user ticket with invalid checksums. for checksum in self.pac_checksum_types: for ctype in self.unkeyed_ctypes: @@ -1169,7 +1319,7 @@ class S4UKerberosTests(KDCBaseTest): 'expect_edata': False }) - def test_constrained_delegation_unkeyed_service_checksum(self): + def _metze_test_constrained_delegation_unkeyed_service_checksum(self): # Present the service's ticket with invalid checksums. for checksum in self.pac_checksum_types: for ctype in self.unkeyed_ctypes: @@ -1198,7 +1348,7 @@ class S4UKerberosTests(KDCBaseTest): checksum=checksum, ctype=ctype) }) - def test_rbcd_unkeyed_client_checksum(self): + def _metze_test_rbcd_unkeyed_client_checksum(self): # Present a user ticket with invalid checksums. for checksum in self.pac_checksum_types: for ctype in self.unkeyed_ctypes: @@ -1221,7 +1371,7 @@ class S4UKerberosTests(KDCBaseTest): checksum=checksum, ctype=ctype) }) - def test_rbcd_unkeyed_service_checksum(self): + def _metze_test_rbcd_unkeyed_service_checksum(self): # Present the service's ticket with invalid checksums. for checksum in self.pac_checksum_types: for ctype in self.unkeyed_ctypes: diff --git a/selftest/knownfail.d/asserted_identity b/selftest/knownfail.d/asserted_identity new file mode 100644 index 0000000000000000000000000000000000000000..013070735e2aba4d274f7b2f35d09547b1626bb5 --- /dev/null +++ b/selftest/knownfail.d/asserted_identity @@ -0,0 +1,3 @@ +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_authentication_asserted_identity +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_service_asserted_identity +^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_asserted_identity diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h index 767d04f5c8c9a18f5cabfc6b157572f27b91e710..bf9a0bc55e9c4e050d5d4b47e141f9463bfd06a4 100644 --- a/third_party/heimdal/kdc/kdc_locl.h +++ b/third_party/heimdal/kdc/kdc_locl.h @@ -168,6 +168,7 @@ struct astgs_request_desc { unsigned int rk_is_subkey : 1; unsigned int fast_asserted : 1; unsigned int explicit_armor_present : 1; + krb5_keyblock enc_ad_key; krb5_crypto armor_crypto; hdb_entry *armor_server; diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c index e95bdad0a640e9f93f9910aa124744a9229f4a01..473bb9d24bfc41380ec8be0b57ef5ba8c70c90e8 100644 --- a/third_party/heimdal/kdc/kerberos5.c +++ b/third_party/heimdal/kdc/kerberos5.c @@ -2800,6 +2800,7 @@ out: if (r->armor_server) _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server); krb5_free_keyblock_contents(r->context, &r->reply_key); + krb5_free_keyblock_contents(r->context, &r->enc_ad_key); krb5_free_keyblock_contents(r->context, &r->session_key); krb5_free_keyblock_contents(r->context, &r->strengthen_key); krb5_pac_free(r->context, r->pac); diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c index aab6806fbe12f06a56d5c02c59f4c0c8f2761204..e0af11a39586b750f242c4c0b4b5cdfadd3c7e8d 100644 --- a/third_party/heimdal/kdc/krb5tgs.c +++ b/third_party/heimdal/kdc/krb5tgs.c @@ -556,7 +556,8 @@ tgs_make_reply(astgs_request_t r, rep->pvno = 5; rep->msg_type = krb_tgs_rep; - et->authtime = tgt->authtime; + if (et->authtime == 0) + et->authtime = tgt->authtime; _kdc_fix_time(&b->till); et->endtime = min(tgt->endtime, *b->till); ALLOC(et->starttime); @@ -931,8 +932,7 @@ tgs_parse_request(astgs_request_t r, const char *from, const struct sockaddr *from_addr, time_t **csec, - int **cusec, - AuthorizationData **auth_data) + int **cusec) { krb5_kdc_configuration *config = r->config; KDC_REQ_BODY *b = &r->req.req_body; @@ -943,16 +943,13 @@ tgs_parse_request(astgs_request_t r, krb5_auth_context ac = NULL; krb5_flags ap_req_options; krb5_flags verify_ap_req_flags = 0; - krb5_crypto crypto; krb5uint32 krbtgt_kvno; /* kvno used for the PA-TGS-REQ AP-REQ Ticket */ krb5uint32 krbtgt_kvno_try; int kvno_search_tries = 4; /* number of kvnos to try when tkt_vno == 0 */ const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */ Key *tkey; krb5_keyblock *subkey = NULL; - unsigned usage; - *auth_data = NULL; *csec = NULL; *cusec = NULL; @@ -1134,7 +1131,6 @@ next_kvno: goto out; } - usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY; r->rk_is_subkey = 1; ret = krb5_auth_con_getremotesubkey(r->context, ac, &subkey); @@ -1146,7 +1142,6 @@ next_kvno: goto out; } if(subkey == NULL){ - usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION; r->rk_is_subkey = 0; ret = krb5_auth_con_getkey(r->context, ac, &subkey); @@ -1172,45 +1167,13 @@ next_kvno: if (ret) goto out; + krb5_free_keyblock_contents(r->context, &r->enc_ad_key); if (b->enc_authorization_data) { - krb5_data ad; - - ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto); - if (ret) { - const char *msg = krb5_get_error_message(r->context, ret); - krb5_auth_con_free(r->context, ac); - kdc_log(r->context, config, 4, "krb5_crypto_init failed: %s", msg); - krb5_free_error_message(r->context, msg); - goto out; - } - ret = krb5_decrypt_EncryptedData (r->context, - crypto, - usage, - b->enc_authorization_data, - &ad); - krb5_crypto_destroy(r->context, crypto); - if(ret){ - krb5_auth_con_free(r->context, ac); - kdc_log(r->context, config, 4, - "Failed to decrypt enc-authorization-data"); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ - goto out; - } - ALLOC(*auth_data); - if (*auth_data == NULL) { - krb5_auth_con_free(r->context, ac); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ - goto out; - } - ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL); - if(ret){ - krb5_auth_con_free(r->context, ac); - free(*auth_data); - *auth_data = NULL; - kdc_log(r->context, config, 4, "Failed to decode authorization data"); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + ret = krb5_copy_keyblock_contents(r->context, + &r->reply_key, + &r->enc_ad_key); + if (ret) goto out; - } } ret = validate_fast_ad(r, r->ticket->ticket.authorization_data); @@ -1368,7 +1331,6 @@ _kdc_db_fetch_client(krb5_context context, static krb5_error_code tgs_build_reply(astgs_request_t priv, krb5_enctype krbtgt_etype, - AuthorizationData **auth_data, const struct sockaddr *from_addr) { krb5_context context = priv->context; @@ -1398,6 +1360,7 @@ tgs_build_reply(astgs_request_t priv, krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1); char **capath = NULL; size_t num_capath = 0; + AuthorizationData *auth_data = NULL; HDB *krbtgt_outdb; hdb_entry *krbtgt_out = NULL; @@ -1929,6 +1892,60 @@ server_lookup: if (ret) goto out; + if (b->enc_authorization_data) { + unsigned auth_data_usage; + krb5_crypto crypto; + krb5_data ad; + + if (priv->rk_is_subkey != 0) { + auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY; + } else { + auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION; + } + + ret = krb5_crypto_init(context, &priv->enc_ad_key, 0, &crypto); + if (ret) { + const char *msg = krb5_get_error_message(context, ret); + kdc_audit_addreason((kdc_request_t)priv, + "krb5_crypto_init() failed for " + "enc_authorization_data"); + kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg); + krb5_free_error_message(context, msg); + goto out; + } + ret = krb5_decrypt_EncryptedData(context, + crypto, + auth_data_usage, + b->enc_authorization_data, + &ad); + krb5_crypto_destroy(context, crypto); + if(ret){ + kdc_audit_addreason((kdc_request_t)priv, + "Failed to decrypt enc-authorization-data"); + kdc_log(context, config, 4, + "Failed to decrypt enc-authorization-data"); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + ALLOC(auth_data); + if (auth_data == NULL) { + krb5_data_free(&ad); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL); + krb5_data_free(&ad); + if(ret){ + free(auth_data); + auth_data = NULL; + kdc_audit_addreason((kdc_request_t)priv, + "Failed to decode authorization data"); + kdc_log(context, config, 4, "Failed to decode authorization data"); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + } + /* * Check flags */ @@ -2040,7 +2057,7 @@ server_lookup: &tkey_sign->key, &sessionkey, kvno, - *auth_data, + auth_data, tgt_realm, rodc_id, add_ticket_sig); @@ -2060,6 +2077,11 @@ out: krb5_free_principal(context, krbtgt_out_principal); free(ref_realm); + if (auth_data) { + free_AuthorizationData(auth_data); + free(auth_data); + } + free_EncTicketPart(&adtkt); krb5_pac_free(context, user2user_pac); @@ -2080,7 +2102,6 @@ _kdc_tgs_rep(astgs_request_t r) const char *from = r->from; struct sockaddr *from_addr = r->addr; int datagram_reply = r->datagram_reply; - AuthorizationData *auth_data = NULL; krb5_error_code ret; int i = 0; const PA_DATA *tgs_req, *pa; @@ -2118,8 +2139,7 @@ _kdc_tgs_rep(astgs_request_t r) ret = tgs_parse_request(r, tgs_req, &krbtgt_etype, from, from_addr, - &csec, &cusec, - &auth_data); + &csec, &cusec); if (ret == HDB_ERR_NOT_FOUND_HERE) { /* kdc_log() is called in tgs_parse_request() */ goto out; @@ -2143,7 +2163,6 @@ _kdc_tgs_rep(astgs_request_t r) ret = tgs_build_reply(r, krbtgt_etype, - &auth_data, from_addr); if (ret) { kdc_log(r->context, config, 4, @@ -2220,6 +2239,7 @@ out: if (r->explicit_armor_pac) krb5_pac_free(r->context, r->explicit_armor_pac); krb5_free_keyblock_contents(r->context, &r->reply_key); + krb5_free_keyblock_contents(r->context, &r->enc_ad_key); krb5_free_keyblock_contents(r->context, &r->strengthen_key); if (r->ticket) @@ -2236,10 +2256,5 @@ out: _kdc_free_fast_state(&r->fast); krb5_pac_free(r->context, r->pac); - if (auth_data) { - free_AuthorizationData(auth_data); - free(auth_data); - } - return ret; } diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c index fda5a37b1c6e61d9984b1bf0ae5e64ddabcb7f58..9a0ee822dd642b026469ac493fe655e2937f7612 100644 --- a/third_party/heimdal/kdc/mssfu.c +++ b/third_party/heimdal/kdc/mssfu.c @@ -513,6 +513,15 @@ validate_constrained_delegation(astgs_request_t r) goto out; } + if (b->enc_authorization_data && r->rk_is_subkey == 0) { + krb5_free_keyblock_contents(r->context, &r->enc_ad_key); + ret = krb5_copy_keyblock_contents(r->context, + &evidence_tkt.key, + &r->enc_ad_key); + if (ret) + goto out; + } + kdc_log(r->context, r->config, 4, "constrained delegation for %s " "from %s (%s) to %s", s4ucname, r->cname, s4usname, r->sname); @@ -535,6 +544,8 @@ validate_constrained_delegation(astgs_request_t r) r->pac_attributes = s4u_pac_attributes; + r->et.authtime = evidence_tkt.authtime; + out: if (s4u_client) _kdc_free_ent(r->context, s4u_clientdb, s4u_client);