tests/krb5: Check buffer types in PAC with STRICT_CHECKING=1
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Wed, 29 Sep 2021 03:15:26 +0000 (16:15 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 14 Oct 2021 18:59:31 +0000 (18:59 +0000)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14642

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
librpc/idl/krb5pac.idl
python/samba/tests/krb5/raw_testcase.py

index 3239d7656b61ddb5d5712fe1631a71c6ef0d095b..515150ab9cdf47cae9fee1ac8961402e7ede920b 100644 (file)
@@ -113,6 +113,9 @@ interface krb5pac
                PAC_TYPE_LOGON_NAME = 10,
                PAC_TYPE_CONSTRAINED_DELEGATION = 11,
                PAC_TYPE_UPN_DNS_INFO = 12,
+               PAC_TYPE_CLIENT_CLAIMS_INFO = 13,
+               PAC_TYPE_DEVICE_INFO = 14,
+               PAC_TYPE_DEVICE_CLAIMS_INFO = 15,
                PAC_TYPE_TICKET_CHECKSUM = 16
        } PAC_TYPE;
 
index 0415f1ff6e6754932f292cb0a1bfba5fafa286dc..320de0a4dbe2e56aaafa3992e096d74e06ae3916 100644 (file)
@@ -2340,6 +2340,13 @@ class RawKerberosTest(TestCaseInTempDir):
             self.assertElementPresent(ticket_private, 'authorization-data',
                                       expect_empty=not expect_pac)
 
+            if expect_pac:
+                authorization_data = self.getElementValue(ticket_private,
+                                                          'authorization-data')
+                pac_data = self.get_pac(authorization_data)
+
+                self.check_pac_buffers(pac_data, kdc_exchange_dict)
+
         encpart_session_key = None
         if encpart_private is not None:
             self.assertElementPresent(encpart_private, 'key')
@@ -2446,6 +2453,47 @@ class RawKerberosTest(TestCaseInTempDir):
 
         kdc_exchange_dict['rep_ticket_creds'] = ticket_creds
 
+    def check_pac_buffers(self, pac_data, kdc_exchange_dict):
+        pac = ndr_unpack(krb5pac.PAC_DATA, pac_data)
+
+        rep_msg_type = kdc_exchange_dict['rep_msg_type']
+        armor_tgt = kdc_exchange_dict['armor_tgt']
+
+        expected_sname = kdc_exchange_dict['expected_sname']
+        expect_claims = kdc_exchange_dict['expect_claims']
+
+        expected_types = [krb5pac.PAC_TYPE_LOGON_INFO,
+                          krb5pac.PAC_TYPE_SRV_CHECKSUM,
+                          krb5pac.PAC_TYPE_KDC_CHECKSUM,
+                          krb5pac.PAC_TYPE_LOGON_NAME,
+                          krb5pac.PAC_TYPE_UPN_DNS_INFO]
+
+        kdc_options = kdc_exchange_dict['kdc_options']
+        pos = len(tuple(krb5_asn1.KDCOptions('cname-in-addl-tkt'))) - 1
+        constrained_delegation = (pos < len(kdc_options)
+                                  and kdc_options[pos] == '1')
+        if constrained_delegation:
+            expected_types.append(krb5pac.PAC_TYPE_CONSTRAINED_DELEGATION)
+
+        if self.kdc_fast_support:
+            if expect_claims:
+                expected_types.append(krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO)
+
+            if (rep_msg_type == KRB_TGS_REP
+                    and armor_tgt is not None):
+                expected_types.append(krb5pac.PAC_TYPE_DEVICE_INFO)
+                expected_types.append(krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO)
+
+        if not self.is_tgs(expected_sname):
+            expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
+
+        if self.strict_checking:
+            buffer_types = [pac_buffer.type
+                            for pac_buffer in pac.buffers]
+            self.assertCountEqual(expected_types, buffer_types,
+                                  f'expected: {expected_types} '
+                                  f'got: {buffer_types}')
+
     def generic_check_kdc_error(self,
                                 kdc_exchange_dict,
                                 callback_dict,
@@ -3397,6 +3445,10 @@ class RawKerberosTest(TestCaseInTempDir):
 
         return new_auth_data, old_pac
 
+    def get_pac(self, auth_data, expect_pac=True):
+        _, pac = self.replace_pac(auth_data, None, expect_pac)
+        return pac
+
     def get_krbtgt_checksum_key(self):
         krbtgt_creds = self.get_krbtgt_creds()
         krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)