summaryrefslogtreecommitdiff
path: root/python/samba/tests/krb5/raw_testcase.py
diff options
context:
space:
mode:
authorJoseph Sutton <josephsutton@catalyst.net.nz>2022-11-09 13:45:13 +1300
committerStefan Metzmacher <metze@samba.org>2022-12-13 13:07:29 +0000
commita50a2be622afaa7a280312ea12f5eb9c9a0c41da (patch)
treecdc51bdbc2effdc4a65fe0af39ab5777cb5805e1 /python/samba/tests/krb5/raw_testcase.py
parent538315a2aa6d03b7639b49eb1576efa8755fefec (diff)
downloadsamba-a50a2be622afaa7a280312ea12f5eb9c9a0c41da.tar.gz
CVE-2022-37967 Add new PAC checksum
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15231 Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org> Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'python/samba/tests/krb5/raw_testcase.py')
-rw-r--r--python/samba/tests/krb5/raw_testcase.py78
1 files changed, 73 insertions, 5 deletions
diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py
index 4f683a9631b..4fb2b7bf181 100644
--- a/python/samba/tests/krb5/raw_testcase.py
+++ b/python/samba/tests/krb5/raw_testcase.py
@@ -557,7 +557,8 @@ class RawKerberosTest(TestCaseInTempDir):
pac_checksum_types = {krb5pac.PAC_TYPE_SRV_CHECKSUM,
krb5pac.PAC_TYPE_KDC_CHECKSUM,
- krb5pac.PAC_TYPE_TICKET_CHECKSUM}
+ krb5pac.PAC_TYPE_TICKET_CHECKSUM,
+ krb5pac.PAC_TYPE_FULL_CHECKSUM}
etypes_to_test = (
{"value": -1111, "name": "dummy", },
@@ -651,6 +652,12 @@ class RawKerberosTest(TestCaseInTempDir):
tkt_sig_support = '0'
cls.tkt_sig_support = bool(int(tkt_sig_support))
+ full_sig_support = samba.tests.env_get_var_value('FULL_SIG_SUPPORT',
+ allow_missing=True)
+ if full_sig_support is None:
+ full_sig_support = '0'
+ cls.full_sig_support = bool(int(full_sig_support))
+
gnutls_pbkdf2_support = samba.tests.env_get_var_value(
'GNUTLS_PBKDF2_SUPPORT',
allow_missing=True)
@@ -2434,6 +2441,7 @@ class RawKerberosTest(TestCaseInTempDir):
unexpected_flags=None,
ticket_decryption_key=None,
expect_ticket_checksum=None,
+ expect_full_checksum=None,
generate_fast_fn=None,
generate_fast_armor_fn=None,
generate_fast_padata_fn=None,
@@ -2503,6 +2511,7 @@ class RawKerberosTest(TestCaseInTempDir):
'unexpected_flags': unexpected_flags,
'ticket_decryption_key': ticket_decryption_key,
'expect_ticket_checksum': expect_ticket_checksum,
+ 'expect_full_checksum': expect_full_checksum,
'generate_fast_fn': generate_fast_fn,
'generate_fast_armor_fn': generate_fast_armor_fn,
'generate_fast_padata_fn': generate_fast_padata_fn,
@@ -2568,6 +2577,7 @@ class RawKerberosTest(TestCaseInTempDir):
unexpected_flags=None,
ticket_decryption_key=None,
expect_ticket_checksum=None,
+ expect_full_checksum=None,
generate_fast_fn=None,
generate_fast_armor_fn=None,
generate_fast_padata_fn=None,
@@ -2638,6 +2648,7 @@ class RawKerberosTest(TestCaseInTempDir):
'unexpected_flags': unexpected_flags,
'ticket_decryption_key': ticket_decryption_key,
'expect_ticket_checksum': expect_ticket_checksum,
+ 'expect_full_checksum': expect_full_checksum,
'generate_fast_fn': generate_fast_fn,
'generate_fast_armor_fn': generate_fast_armor_fn,
'generate_fast_padata_fn': generate_fast_padata_fn,
@@ -3120,7 +3131,8 @@ class RawKerberosTest(TestCaseInTempDir):
self.check_pac_buffers(pac_data, kdc_exchange_dict)
expect_ticket_checksum = kdc_exchange_dict['expect_ticket_checksum']
- if expect_ticket_checksum:
+ expect_full_checksum = kdc_exchange_dict['expect_full_checksum']
+ if expect_ticket_checksum or expect_full_checksum:
self.assertIsNotNone(ticket_decryption_key)
if ticket_decryption_key is not None:
@@ -3130,7 +3142,9 @@ class RawKerberosTest(TestCaseInTempDir):
service_ticket=service_ticket,
expect_pac=expect_pac,
expect_ticket_checksum=expect_ticket_checksum
- or self.tkt_sig_support)
+ or self.tkt_sig_support,
+ expect_full_checksum=expect_full_checksum
+ or self.full_sig_support)
kdc_exchange_dict['rep_ticket_creds'] = ticket_creds
@@ -3267,6 +3281,8 @@ class RawKerberosTest(TestCaseInTempDir):
unchecked = set()
if not self.tkt_sig_support:
require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
+ if not self.full_sig_support:
+ require_strict.add(krb5pac.PAC_TYPE_FULL_CHECKSUM)
expected_client_claims = kdc_exchange_dict['expected_client_claims']
unexpected_client_claims = kdc_exchange_dict[
@@ -3323,6 +3339,7 @@ class RawKerberosTest(TestCaseInTempDir):
if rep_msg_type == KRB_TGS_REP:
if not self.is_tgs_principal(expected_sname):
expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
+ expected_types.append(krb5pac.PAC_TYPE_FULL_CHECKSUM)
expect_extra_pac_buffers = self.is_tgs(expected_sname)
@@ -4194,7 +4211,8 @@ class RawKerberosTest(TestCaseInTempDir):
def verify_ticket(self, ticket, krbtgt_keys, service_ticket,
expect_pac=True,
- expect_ticket_checksum=True):
+ expect_ticket_checksum=True,
+ expect_full_checksum=None):
# Decrypt the ticket.
key = ticket.decryption_key
@@ -4239,6 +4257,8 @@ class RawKerberosTest(TestCaseInTempDir):
checksums = {}
+ full_checksum_buffer = None
+
for pac_buffer, raw_pac_buffer in zip(pac.buffers, raw_pac.buffers):
buffer_type = pac_buffer.type
if buffer_type in self.pac_checksum_types:
@@ -4253,7 +4273,9 @@ class RawKerberosTest(TestCaseInTempDir):
checksums[buffer_type] = checksum, ctype
- if buffer_type != krb5pac.PAC_TYPE_TICKET_CHECKSUM:
+ if buffer_type == krb5pac.PAC_TYPE_FULL_CHECKSUM:
+ full_checksum_buffer = raw_pac_buffer
+ elif buffer_type != krb5pac.PAC_TYPE_TICKET_CHECKSUM:
# Zero the checksum field so that we can later verify the
# checksums. The ticket checksum field is not zeroed.
@@ -4267,6 +4289,17 @@ class RawKerberosTest(TestCaseInTempDir):
# Re-encode the PAC.
pac_data = ndr_pack(raw_pac)
+ if full_checksum_buffer is not None:
+ signature = ndr_unpack(
+ krb5pac.PAC_SIGNATURE_DATA,
+ full_checksum_buffer.info.remaining)
+ signature.signature = bytes(len(checksum))
+ full_checksum_buffer.info.remaining = ndr_pack(
+ signature)
+
+ # Re-encode the PAC.
+ full_pac_data = ndr_pack(raw_pac)
+
# Verify the signatures.
server_checksum, server_ctype = checksums[
@@ -4295,6 +4328,7 @@ class RawKerberosTest(TestCaseInTempDir):
if not service_ticket:
self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums)
+ self.assertNotIn(krb5pac.PAC_TYPE_FULL_CHECKSUM, checksums)
else:
ticket_checksum, ticket_ctype = checksums.get(
krb5pac.PAC_TYPE_TICKET_CHECKSUM,
@@ -4313,6 +4347,19 @@ class RawKerberosTest(TestCaseInTempDir):
ticket_ctype,
ticket_checksum)
+ full_checksum, full_ctype = checksums.get(
+ krb5pac.PAC_TYPE_FULL_CHECKSUM,
+ (None, None))
+ if expect_full_checksum:
+ self.assertIsNotNone(full_checksum)
+ elif expect_full_checksum is False:
+ self.assertIsNone(full_checksum)
+ if full_checksum is not None:
+ krbtgt_key.verify_rodc_checksum(KU_NON_KERB_CKSUM_SALT,
+ full_pac_data,
+ full_ctype,
+ full_checksum)
+
def modified_ticket(self,
ticket, *,
new_ticket_key=None,
@@ -4370,6 +4417,14 @@ class RawKerberosTest(TestCaseInTempDir):
checksum_keys[krb5pac.PAC_TYPE_TICKET_CHECKSUM] = (
kdc_checksum_key)
+ if krb5pac.PAC_TYPE_FULL_CHECKSUM not in checksum_keys:
+ # If the full signature key is not present, fall back to the key
+ # used for the KDC signature.
+ kdc_checksum_key = checksum_keys.get(krb5pac.PAC_TYPE_KDC_CHECKSUM)
+ if kdc_checksum_key is not None:
+ checksum_keys[krb5pac.PAC_TYPE_FULL_CHECKSUM] = (
+ kdc_checksum_key)
+
# Decrypt the ticket.
enc_part = ticket.ticket['enc-part']
@@ -4522,6 +4577,19 @@ class RawKerberosTest(TestCaseInTempDir):
# Add the new checksum buffers to the PAC.
pac.buffers = pac_buffers
+ # Calculate the full checksum and insert it into the PAC.
+ full_checksum_buffer = checksum_buffers.get(
+ krb5pac.PAC_TYPE_FULL_CHECKSUM)
+ if full_checksum_buffer is not None:
+ full_checksum_key = checksum_keys[krb5pac.PAC_TYPE_FULL_CHECKSUM]
+
+ pac_data = ndr_pack(pac)
+ full_checksum = full_checksum_key.make_checksum(
+ KU_NON_KERB_CKSUM_SALT,
+ pac_data)
+
+ full_checksum_buffer.info.signature = full_checksum
+
# Calculate the server and KDC checksums and insert them into the PAC.
server_checksum_buffer = checksum_buffers.get(