CVE-2022-37966 tests/krb5: Check encrypted-pa-data if present
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Mon, 29 Nov 2021 20:45:13 +0000 (09:45 +1300)
committerStefan Metzmacher <metze@samba.org>
Tue, 13 Dec 2022 23:48:48 +0000 (00:48 +0100)
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
(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]

python/samba/tests/krb5/raw_testcase.py
python/samba/tests/krb5/rfc4120_constants.py
selftest/knownfail_mit_kdc

index 4a78a8eadf3614a518718d04a991d8285696376e..2dedccf6188564b3d10ab15a135c12fd70fff935 100644 (file)
@@ -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)
 
index 7f0f44500c7489cf1ac2276ab87ffdc2cd84f3a6..2af43557ad7590ea2d71ce89a08bc58431a95c8e 100644 (file)
@@ -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
index 6cad47701aedbdfccab97bdfad394f68c896cddd..680c637fbc5621d5e5ffdebfde85d5d2a034464e 100644 (file)
@@ -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