From: Joseph Sutton Date: Mon, 29 Nov 2021 20:45:13 +0000 (+1300) Subject: CVE-2022-37966 tests/krb5: Check encrypted-pa-data if present X-Git-Tag: samba-4.15.13~65 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=900c6e2268dbd2625e679af1550d4874247cd1b1;p=thirdparty%2Fsamba.git CVE-2022-37966 tests/krb5: Check encrypted-pa-data if present Signed-off-by: Joseph Sutton Reviewed-by: Stefan Metzmacher (cherry picked from commit f94bdb41fccdb085d8f8f5a1a5e4a56581839e8e) BUG: https://bugzilla.samba.org/show_bug.cgi?id=15237 [jsutton@samba.org Fixed MIT knownfail conflict; added import of PADATA_REQ_ENC_PA_REP constant] --- diff --git a/python/samba/tests/krb5/raw_testcase.py b/python/samba/tests/krb5/raw_testcase.py index 4a78a8eadf3..2dedccf6188 100644 --- a/python/samba/tests/krb5/raw_testcase.py +++ b/python/samba/tests/krb5/raw_testcase.py @@ -65,6 +65,7 @@ from samba.tests.krb5.rfc4120_constants import ( KU_AP_REQ_AUTH, KU_AS_REP_ENC_PART, KU_AP_REQ_ENC_PART, + KU_AS_REQ, KU_ENC_CHALLENGE_KDC, KU_FAST_ENC, KU_FAST_FINISHED, @@ -95,6 +96,7 @@ from samba.tests.krb5.rfc4120_constants import ( PADATA_PAC_REQUEST, PADATA_PK_AS_REQ, PADATA_PK_AS_REP_19, + PADATA_REQ_ENC_PA_REP, PADATA_SUPPORTED_ETYPES ) import samba.tests.krb5.kcrypto as kcrypto @@ -2306,6 +2308,8 @@ class RawKerberosTest(TestCaseInTempDir): req_body=req_body, asn1Spec=req_asn1Spec()) + kdc_exchange_dict['req_obj'] = req_obj + to_rodc = kdc_exchange_dict['to_rodc'] rep = self.send_recv_transaction(req_decoded, to_rodc=to_rodc) @@ -2689,6 +2693,8 @@ class RawKerberosTest(TestCaseInTempDir): rep_decpart, asn1Spec=krb5_asn1.EncTGSRepPart()) + kdc_exchange_dict['reply_key'] = encpart_decryption_key + self.assertIsNotNone(check_kdc_private_fn) if check_kdc_private_fn is not None: check_kdc_private_fn(kdc_exchange_dict, callback_dict, @@ -2855,15 +2861,35 @@ class RawKerberosTest(TestCaseInTempDir): sent_pac_options = self.get_sent_pac_options(kdc_exchange_dict) - if self.strict_checking: - if canonicalize or '1' in sent_pac_options: - self.assertElementPresent(encpart_private, + sent_enc_pa_rep = self.sent_enc_pa_rep(kdc_exchange_dict) + + enc_padata = self.getElementValue(encpart_private, 'encrypted-pa-data') - enc_pa_dict = self.get_pa_dict( - encpart_private['encrypted-pa-data']) - if canonicalize: - self.assertIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) + if (canonicalize or '1' in sent_pac_options or ( + rep_msg_type == KRB_AS_REP and sent_enc_pa_rep)): + if self.strict_checking: + self.assertIsNotNone(enc_padata) + if enc_padata is not None: + enc_pa_dict = self.get_pa_dict(enc_padata) + if self.strict_checking: + if canonicalize: + self.assertIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) + else: + self.assertNotIn(PADATA_SUPPORTED_ETYPES, + enc_pa_dict) + + if '1' in sent_pac_options: + self.assertIn(PADATA_PAC_OPTIONS, enc_pa_dict) + else: + self.assertNotIn(PADATA_PAC_OPTIONS, enc_pa_dict) + + if rep_msg_type == KRB_AS_REP and sent_enc_pa_rep: + self.assertIn(PADATA_REQ_ENC_PA_REP, enc_pa_dict) + else: + self.assertNotIn(PADATA_REQ_ENC_PA_REP, enc_pa_dict) + + if PADATA_SUPPORTED_ETYPES in enc_pa_dict: expected_supported_etypes = kdc_exchange_dict[ 'expected_supported_etypes'] expected_supported_etypes |= ( @@ -2877,24 +2903,39 @@ class RawKerberosTest(TestCaseInTempDir): self.assertEqual(supported_etypes, expected_supported_etypes) - else: - self.assertNotIn(PADATA_SUPPORTED_ETYPES, enc_pa_dict) - - if '1' in sent_pac_options: - self.assertIn(PADATA_PAC_OPTIONS, enc_pa_dict) + if PADATA_PAC_OPTIONS in enc_pa_dict: pac_options = self.der_decode( enc_pa_dict[PADATA_PAC_OPTIONS], asn1Spec=krb5_asn1.PA_PAC_OPTIONS()) self.assertElementEqual(pac_options, 'options', sent_pac_options) - else: - self.assertNotIn(PADATA_PAC_OPTIONS, enc_pa_dict) - else: - self.assertElementEqual(encpart_private, - 'encrypted-pa-data', - []) + + if PADATA_REQ_ENC_PA_REP in enc_pa_dict: + enc_pa_rep = enc_pa_dict[PADATA_REQ_ENC_PA_REP] + + enc_pa_rep = self.der_decode( + enc_pa_rep, + asn1Spec=krb5_asn1.Checksum()) + + reply_key = kdc_exchange_dict['reply_key'] + req_obj = kdc_exchange_dict['req_obj'] + req_asn1Spec = kdc_exchange_dict['req_asn1Spec'] + + req_obj = self.der_encode(req_obj, + asn1Spec=req_asn1Spec()) + + checksum = enc_pa_rep['checksum'] + ctype = enc_pa_rep['cksumtype'] + + reply_key.verify_checksum(KU_AS_REQ, + req_obj, + ctype, + checksum) + else: + if enc_padata is not None: + self.assertEqual(enc_padata, []) if ticket_session_key is not None and encpart_session_key is not None: self.assertEqual(ticket_session_key.etype, @@ -4052,6 +4093,11 @@ class RawKerberosTest(TestCaseInTempDir): return PADATA_ENCRYPTED_CHALLENGE in fast_pa_dict + def sent_enc_pa_rep(self, kdc_exchange_dict): + fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict) + + return PADATA_REQ_ENC_PA_REP in fast_pa_dict + def get_sent_pac_options(self, kdc_exchange_dict): fast_pa_dict = self.get_fast_pa_dict(kdc_exchange_dict) diff --git a/python/samba/tests/krb5/rfc4120_constants.py b/python/samba/tests/krb5/rfc4120_constants.py index 7f0f44500c7..2af43557ad7 100644 --- a/python/samba/tests/krb5/rfc4120_constants.py +++ b/python/samba/tests/krb5/rfc4120_constants.py @@ -66,6 +66,8 @@ PADATA_PW_SALT = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-PW-SALT')) PADATA_SUPPORTED_ETYPES = int( krb5_asn1.PADataTypeValues('kRB5-PADATA-SUPPORTED-ETYPES')) +PADATA_REQ_ENC_PA_REP = int( + krb5_asn1.PADataTypeValues('kRB5-PADATA-REQ-ENC-PA-REP')) # Error codes KDC_ERR_C_PRINCIPAL_UNKNOWN = 6 @@ -194,6 +196,7 @@ KU_FAST_REP = 52 KU_FAST_FINISHED = 53 KU_ENC_CHALLENGE_CLIENT = 54 KU_ENC_CHALLENGE_KDC = 55 +KU_AS_REQ = 56 # Armor types FX_FAST_ARMOR_AP_REQUEST = 1 diff --git a/selftest/knownfail_mit_kdc b/selftest/knownfail_mit_kdc index 6cad47701ae..680c637fbc5 100644 --- a/selftest/knownfail_mit_kdc +++ b/selftest/knownfail_mit_kdc @@ -347,9 +347,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_ ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_outer_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_enc_pa_rep.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_fast_no_etypes.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_no_sname.ad_dc +^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_enc_pa_rep.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_simple_tgs_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_inner_no_sname.ad_dc ^samba.tests.krb5.fast_tests.samba.tests.krb5.fast_tests.FAST_Tests.test_fast_tgs_inner_no_sname.ad_dc