python/samba/tests/krb5/raw_testcase.py move _test_as_exchange to generic
authorStefan Metzmacher <metze@samba.org>
Tue, 21 Apr 2020 09:07:45 +0000 (11:07 +0200)
committerStefan Metzmacher <metze@samba.org>
Mon, 14 Sep 2020 13:19:22 +0000 (15:19 +0200)
python/samba/tests/krb5/as_req_tests.py
python/samba/tests/krb5/raw_testcase.py

index e6a91f4a684aa8730aac2631e4994b6aa0d5a9ec..bba0ec7faf36e2f25a14a9d2fc4cf39fc4302cb4 100755 (executable)
@@ -46,283 +46,6 @@ class AsReqKerberosTests(RawKerberosTest):
         self.do_asn1_print = global_asn1_print
         self.do_hexdump = global_hexdump
 
-    def _test_as_exchange(self,
-                          cname,
-                          realm,
-                          sname,
-                          till,
-                          client_as_etypes,
-                          expected_error_mode,
-                          expected_crealm,
-                          expected_cname,
-                          expected_srealm,
-                          expected_sname,
-                          expected_salt,
-                          etypes,
-                          padata,
-                          kdc_options):
-
-        if till is None:
-            till = self.get_KerberosTime(offset=36000)
-
-        req = self.AS_REQ_create(padata=padata,
-                                 kdc_options=str(kdc_options),
-                                 cname=cname,
-                                 realm=realm,
-                                 sname=sname,
-                                 from_time=None,
-                                 till_time=till,
-                                 renew_time=None,
-                                 nonce=0x7fffffff,
-                                 etypes=etypes,
-                                 addresses=None,
-                                 EncAuthorizationData=None,
-                                 EncAuthorizationData_key=None,
-                                 additional_tickets=None)
-        rep = self.send_recv_transaction(req)
-        self.assertIsNotNone(rep)
-
-        msg_type = self.getElementValue(rep, 'msg-type')
-        self.assertIsNotNone(msg_type)
-
-        allowed_msg_types = (30,) # KRB-ERROR
-        if expected_error_mode == 0: # AS-REP
-            allowed_msg_types += (11,) # AS-REP
-        self.assertIn(msg_type, allowed_msg_types)
-
-        if msg_type == 11: # AS-REP
-            return self._test_as_rep_check(rep,
-                                           expected_crealm,
-                                           expected_cname,
-                                           expected_srealm,
-                                           expected_sname)
-
-        return self._test_as_error_check(rep,
-                                         client_as_etypes,
-                                         etypes,
-                                         expected_error_mode,
-                                         expected_srealm,
-                                         expected_sname,
-                                         expected_salt)
-
-    def _test_as_error_check(self,
-                             rep,
-                             client_as_etypes,
-                             proposed_etypes,
-                             expected_error_mode,
-                             expected_srealm,
-                             expected_sname,
-                             expected_salt):
-
-        expect_etype_info2 = ()
-        expect_etype_info = False
-        unexpect_etype_info = True
-        expected_aes_type = 0
-        expected_rc4_type = 0
-        if 23 in proposed_etypes:
-            expect_etype_info = True
-        for etype in proposed_etypes:
-            if etype in (18,17):
-                expect_etype_info = False
-            if etype not in client_as_etypes:
-                continue
-            if etype in (18,17):
-                if etype > expected_aes_type:
-                    expected_aes_type = etype
-            if etype in (23,):
-                unexpect_etype_info = False
-                if etype > expected_rc4_type:
-                    expected_rc4_type = etype
-
-        if expected_aes_type != 0:
-            expect_etype_info2 += (expected_aes_type,)
-        if expected_rc4_type != 0:
-            expect_etype_info2 += (expected_rc4_type,)
-
-        expected_error = 14 # ETYPE_NOSUPP
-        expected_patypes = ()
-        if expect_etype_info:
-            self.assertGreater(len(expect_etype_info2), 0)
-            expected_patypes += (11,) # PA-ETYPE-INFO
-        if len(expect_etype_info2) != 0:
-            expected_error = 25 # PREAUTH_REQUIRED
-            expected_patypes += (19,) # PA-ETYPE-INFO2
-
-        expected_patypes += (2,)  # PA-ENC-TIMESTAMP
-        expected_patypes += (16,) # PA-PK-AS-REQ
-        expected_patypes += (15,) # PA-PK-AS-REQ-19
-
-        self.assertElementEqual(rep, 'msg-type', 30) # KRB-ERROR
-        self.assertElementEqual(rep, 'error-code', expected_error)
-        self.assertElementMissing(rep, 'ctime')
-        self.assertElementMissing(rep, 'cusec')
-        self.assertElementPresent(rep, 'stime')
-        self.assertElementPresent(rep, 'susec')
-        # error-code checked above
-        if self.strict_checking:
-            self.assertElementMissing(rep, 'crealm')
-            self.assertElementMissing(rep, 'cname')
-        self.assertElementEqualUTF8(rep, 'realm', expected_srealm)
-        self.assertElementEqualPrincipal(rep, 'sname', expected_sname)
-        if self.strict_checking:
-            self.assertElementMissing(rep, 'e-text')
-        if expected_error_mode != 25: # PREAUTH_REQUIRED
-            self.assertElementMissing(rep, 'e-data')
-            return None
-        edata = self.getElementValue(rep, 'e-data')
-        if self.strict_checking:
-            self.assertIsNotNone(edata)
-        if edata is not None:
-            rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA())
-            self.assertGreater(len(rep_padata), 0)
-        else:
-            rep_padata = []
-
-        if self.strict_checking:
-            for i in range(0, len(expected_patypes)):
-                self.assertElementEqual(rep_padata[i], 'padata-type', expected_patypes[i])
-            self.assertEqual(len(rep_padata), len(expected_patypes))
-
-        etype_info2 = None
-        etype_info = None
-        enc_timestamp = None
-        pk_as_req = None
-        pk_as_req19 = None
-        for pa in rep_padata:
-            patype = self.getElementValue(pa, 'padata-type')
-            pavalue = self.getElementValue(pa, 'padata-value')
-            if patype == 19: # PA-ETYPE-INFO2
-                self.assertIsNone(etype_info2)
-                etype_info2 = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO2())
-                continue
-            if patype == 11: # PA-ETYPE-INFO
-                self.assertIsNone(etype_info)
-                etype_info = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO())
-                continue
-            if patype == 2: # PA-ENC-TIMESTAMP
-                self.assertIsNone(enc_timestamp)
-                enc_timestamp = pavalue
-                self.assertEqual(len(enc_timestamp), 0)
-                continue
-            if patype == 16: # PA-PK-AS-REQ
-                self.assertIsNone(pk_as_req)
-                pk_as_req = pavalue
-                self.assertEqual(len(pk_as_req), 0)
-                continue
-            if patype == 15: # PA-PK-AS-REQ-19
-                self.assertIsNone(pk_as_req19)
-                pk_as_req19 = pavalue
-                self.assertEqual(len(pk_as_req19), 0)
-                continue
-
-        if expected_error == 14: # ETYPE_NOSUPP
-            self.assertIsNone(etype_info2)
-            self.assertIsNone(etype_info)
-            if self.strict_checking:
-                self.assertIsNotNone(enc_timestamp)
-                self.assertIsNotNone(pk_as_req)
-                self.assertIsNotNone(pk_as_req19)
-            return None
-
-        self.assertIsNotNone(etype_info2)
-        if expect_etype_info:
-            self.assertIsNotNone(etype_info)
-        else:
-            if self.strict_checking:
-                self.assertIsNone(etype_info)
-        if unexpect_etype_info:
-            self.assertIsNone(etype_info)
-
-        self.assertGreaterEqual(len(etype_info2), 1)
-        self.assertLessEqual(len(etype_info2), len(expect_etype_info2))
-        if self.strict_checking:
-            self.assertEqual(len(etype_info2), len(expect_etype_info2))
-        for i in range(0, len(etype_info2)):
-            e = self.getElementValue(etype_info2[i], 'etype')
-            self.assertEqual(e, expect_etype_info2[i])
-            salt = self.getElementValue(etype_info2[i], 'salt')
-            if e == 23:
-                self.assertIsNone(salt)
-            else:
-                self.assertIsNotNone(salt)
-                if expected_salt is not None:
-                    self.assertEqual(salt, expected_salt)
-            s2kparams = self.getElementValue(etype_info2[i], 's2kparams')
-            if self.strict_checking:
-                self.assertIsNone(s2kparams)
-        if etype_info is not None:
-            self.assertEqual(len(etype_info), 1)
-            e = self.getElementValue(etype_info[0], 'etype')
-            self.assertEqual(e, 23)
-            self.assertEqual(e, expect_etype_info2[0])
-            salt = self.getElementValue(etype_info[0], 'salt')
-            if self.strict_checking:
-                self.assertIsNotNone(salt)
-                self.assertEqual(len(salt), 0)
-
-        self.assertIsNotNone(enc_timestamp)
-        self.assertIsNotNone(pk_as_req)
-        self.assertIsNotNone(pk_as_req19)
-
-        return etype_info2
-
-    def _test_kdc_rep_check(self,
-                            rep,
-                            msg_type,
-                            expected_crealm,
-                            expected_cname,
-                            expected_srealm,
-                            expected_sname,
-                            check_padata_fn=None,
-                            check_padata_dict=None,
-                            ticket_key=None,
-                            check_ticket_fn=None,
-                            check_ticket_dict=None,
-                            encpart_key=None,
-                            check_encpart_asn1Spec=None,
-                            check_encpart_fn=None,
-                            check_encpart_dict=None):
-
-        self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP
-        padata = self.getElementValue(rep, 'padata')
-        if padata is not None:
-            self.assertGreater(len(padata), 0)
-        else:
-            padata = []
-        self.assertElementEqualUTF8(rep, 'crealm', expected_crealm)
-        self.assertElementEqualPrincipal(rep, 'cname', expected_cname)
-        self.assertElementPresent(rep, 'ticket')
-        ticket = self.getElementValue(rep, 'ticket')
-        if ticket is not None:
-            self.assertElementPresent(ticket, 'tkt-vno')
-            self.assertElementEqualUTF8(ticket, 'realm', expected_srealm)
-            self.assertElementEqualPrincipal(ticket, 'sname', expected_sname)
-            self.assertElementPresent(ticket, 'enc-part')
-            tencpart = self.getElementValue(ticket, 'enc-part')
-            if tencpart is not None:
-                self.assertElementPresent(tencpart, 'etype')
-                self.assertElementPresent(tencpart, 'cipher')
-        self.assertElementPresent(rep, 'enc-part')
-        encpart = self.getElementValue(rep, 'enc-part')
-        if encpart is not None:
-            self.assertElementPresent(encpart, 'etype')
-            self.assertElementPresent(encpart, 'cipher')
-
-        return rep
-
-    def _test_as_rep_check(self,
-                           rep,
-                           expected_crealm,
-                           expected_cname,
-                           expected_srealm,
-                           expected_sname):
-        return self._test_kdc_rep_check(rep,
-                                        11, # AS-REP
-                                        expected_crealm,
-                                        expected_cname,
-                                        expected_srealm,
-                                        expected_sname)
-
     def _test_as_req_nopreauth(self,
                                initial_etypes,
                                initial_padata=None,
index 7316552d97cc7e6d8b8f9635b579314c977ef988..0d69f3e750254d42e62e36a66a0e389d08ba896f 100644 (file)
@@ -1191,3 +1191,316 @@ class RawKerberosTest(TestCase):
         }
         pa_s4u2self = self.der_encode(PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self())
         return self.PA_DATA_create(129, pa_s4u2self)
+
+    def _test_as_exchange(self,
+                          cname,
+                          realm,
+                          sname,
+                          till,
+                          client_as_etypes,
+                          expected_error_mode,
+                          expected_crealm,
+                          expected_cname,
+                          expected_srealm,
+                          expected_sname,
+                          expected_salt,
+                          etypes,
+                          padata,
+                          kdc_options,
+                          ticket_decryption_key=None):
+
+        if till is None:
+            till = self.get_KerberosTime(offset=36000)
+
+        req = self.AS_REQ_create(padata=padata,
+                                 kdc_options=str(kdc_options),
+                                 cname=cname,
+                                 realm=realm,
+                                 sname=sname,
+                                 from_time=None,
+                                 till_time=till,
+                                 renew_time=None,
+                                 nonce=0x7fffffff,
+                                 etypes=etypes,
+                                 addresses=None,
+                                 EncAuthorizationData=None,
+                                 EncAuthorizationData_key=None,
+                                 additional_tickets=None)
+        rep = self.send_recv_transaction(req)
+        self.assertIsNotNone(rep)
+
+        msg_type = self.getElementValue(rep, 'msg-type')
+        self.assertIsNotNone(msg_type)
+
+        allowed_msg_types = (30,) # KRB-ERROR
+        if expected_error_mode == 0: # AS-REP
+            allowed_msg_types += (11,) # AS-REP
+        self.assertIn(msg_type, allowed_msg_types)
+
+        if msg_type == 11: # AS-REP
+            return self._test_as_rep_check(rep,
+                                           expected_crealm,
+                                           expected_cname,
+                                           expected_srealm,
+                                           expected_sname,
+                                           ticket_decryption_key=ticket_decryption_key)
+
+        return self._test_as_error_check(rep,
+                                         client_as_etypes,
+                                         etypes,
+                                         expected_error_mode,
+                                         expected_srealm,
+                                         expected_sname,
+                                         expected_salt)
+
+    def _test_as_error_check(self,
+                             rep,
+                             client_as_etypes,
+                             proposed_etypes,
+                             expected_error_mode,
+                             expected_srealm,
+                             expected_sname,
+                             expected_salt):
+
+        expect_etype_info2 = ()
+        expect_etype_info = False
+        unexpect_etype_info = True
+        expected_aes_type = 0
+        expected_rc4_type = 0
+        if 23 in proposed_etypes:
+            expect_etype_info = True
+        for etype in proposed_etypes:
+            if etype in (18,17):
+                expect_etype_info = False
+            if etype not in client_as_etypes:
+                continue
+            if etype in (18,17):
+                if etype > expected_aes_type:
+                    expected_aes_type = etype
+            if etype in (23,):
+                unexpect_etype_info = False
+                if etype > expected_rc4_type:
+                    expected_rc4_type = etype
+
+        if expected_aes_type != 0:
+            expect_etype_info2 += (expected_aes_type,)
+        if expected_rc4_type != 0:
+            expect_etype_info2 += (expected_rc4_type,)
+
+        expected_error = 14 # ETYPE_NOSUPP
+        expected_patypes = ()
+        if expect_etype_info:
+            self.assertGreater(len(expect_etype_info2), 0)
+            expected_patypes += (11,) # PA-ETYPE-INFO
+        if len(expect_etype_info2) != 0:
+            expected_error = 25 # PREAUTH_REQUIRED
+            expected_patypes += (19,) # PA-ETYPE-INFO2
+
+        expected_patypes += (2,)  # PA-ENC-TIMESTAMP
+        expected_patypes += (16,) # PA-PK-AS-REQ
+        expected_patypes += (15,) # PA-PK-AS-REQ-19
+
+        self.assertElementEqual(rep, 'msg-type', 30) # KRB-ERROR
+        self.assertElementEqual(rep, 'error-code', expected_error)
+        self.assertElementMissing(rep, 'ctime')
+        self.assertElementMissing(rep, 'cusec')
+        self.assertElementPresent(rep, 'stime')
+        self.assertElementPresent(rep, 'susec')
+        # error-code checked above
+        if self.strict_checking:
+            self.assertElementMissing(rep, 'crealm')
+            self.assertElementMissing(rep, 'cname')
+        self.assertElementEqualUTF8(rep, 'realm', expected_srealm)
+        self.assertElementEqualPrincipal(rep, 'sname', expected_sname)
+        if self.strict_checking:
+            self.assertElementMissing(rep, 'e-text')
+        if expected_error_mode != 25: # PREAUTH_REQUIRED
+            self.assertElementMissing(rep, 'e-data')
+            return None
+        edata = self.getElementValue(rep, 'e-data')
+        if self.strict_checking:
+            self.assertIsNotNone(edata)
+        if edata is not None:
+            rep_padata = self.der_decode(edata, asn1Spec=krb5_asn1.METHOD_DATA())
+            self.assertGreater(len(rep_padata), 0)
+        else:
+            rep_padata = []
+
+        if self.strict_checking:
+            for i in range(0, len(expected_patypes)):
+                self.assertElementEqual(rep_padata[i], 'padata-type', expected_patypes[i])
+            self.assertEqual(len(rep_padata), len(expected_patypes))
+
+        etype_info2 = None
+        etype_info = None
+        enc_timestamp = None
+        pk_as_req = None
+        pk_as_req19 = None
+        for pa in rep_padata:
+            patype = self.getElementValue(pa, 'padata-type')
+            pavalue = self.getElementValue(pa, 'padata-value')
+            if patype == 19: # PA-ETYPE-INFO2
+                self.assertIsNone(etype_info2)
+                etype_info2 = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO2())
+                continue
+            if patype == 11: # PA-ETYPE-INFO
+                self.assertIsNone(etype_info)
+                etype_info = self.der_decode(pavalue, asn1Spec=krb5_asn1.ETYPE_INFO())
+                continue
+            if patype == 2: # PA-ENC-TIMESTAMP
+                self.assertIsNone(enc_timestamp)
+                enc_timestamp = pavalue
+                self.assertEqual(len(enc_timestamp), 0)
+                continue
+            if patype == 16: # PA-PK-AS-REQ
+                self.assertIsNone(pk_as_req)
+                pk_as_req = pavalue
+                self.assertEqual(len(pk_as_req), 0)
+                continue
+            if patype == 15: # PA-PK-AS-REQ-19
+                self.assertIsNone(pk_as_req19)
+                pk_as_req19 = pavalue
+                self.assertEqual(len(pk_as_req19), 0)
+                continue
+
+        if expected_error == 14: # ETYPE_NOSUPP
+            self.assertIsNone(etype_info2)
+            self.assertIsNone(etype_info)
+            if self.strict_checking:
+                self.assertIsNotNone(enc_timestamp)
+                self.assertIsNotNone(pk_as_req)
+                self.assertIsNotNone(pk_as_req19)
+            return None
+
+        self.assertIsNotNone(etype_info2)
+        if expect_etype_info:
+            self.assertIsNotNone(etype_info)
+        else:
+            if self.strict_checking:
+                self.assertIsNone(etype_info)
+        if unexpect_etype_info:
+            self.assertIsNone(etype_info)
+
+        self.assertGreaterEqual(len(etype_info2), 1)
+        self.assertLessEqual(len(etype_info2), len(expect_etype_info2))
+        if self.strict_checking:
+            self.assertEqual(len(etype_info2), len(expect_etype_info2))
+        for i in range(0, len(etype_info2)):
+            e = self.getElementValue(etype_info2[i], 'etype')
+            self.assertEqual(e, expect_etype_info2[i])
+            salt = self.getElementValue(etype_info2[i], 'salt')
+            if e == 23:
+                self.assertIsNone(salt)
+            else:
+                self.assertIsNotNone(salt)
+                if expected_salt is not None:
+                    self.assertEqual(salt, expected_salt)
+            s2kparams = self.getElementValue(etype_info2[i], 's2kparams')
+            if self.strict_checking:
+                self.assertIsNone(s2kparams)
+        if etype_info is not None:
+            self.assertEqual(len(etype_info), 1)
+            e = self.getElementValue(etype_info[0], 'etype')
+            self.assertEqual(e, 23)
+            self.assertEqual(e, expect_etype_info2[0])
+            salt = self.getElementValue(etype_info[0], 'salt')
+            if self.strict_checking:
+                self.assertIsNotNone(salt)
+                self.assertEqual(len(salt), 0)
+
+        self.assertIsNotNone(enc_timestamp)
+        self.assertIsNotNone(pk_as_req)
+        self.assertIsNotNone(pk_as_req19)
+
+        return etype_info2
+
+    def _test_kdc_rep_check(self,
+                            rep,
+                            msg_type,
+                            expected_crealm,
+                            expected_cname,
+                            expected_srealm,
+                            expected_sname,
+                            check_padata_fn=None,
+                            check_padata_dict=None,
+                            ticket_decryption_key=None,
+                            check_ticket_fn=None,
+                            check_ticket_dict=None,
+                            check_encpart_asn1Spec=None,
+                            check_encpart_fn=None,
+                            check_encpart_dict=None):
+
+        self.assertElementEqual(rep, 'msg-type', msg_type) # AS-REP | TGS-REP
+        padata = self.getElementValue(rep, 'padata')
+        if padata is not None:
+            self.assertGreater(len(padata), 0)
+        else:
+            padata = []
+        self.assertElementEqualUTF8(rep, 'crealm', expected_crealm)
+        self.assertElementEqualPrincipal(rep, 'cname', expected_cname)
+        self.assertElementPresent(rep, 'ticket')
+        ticket = self.getElementValue(rep, 'ticket')
+        ticket_encpart = None
+        ticket_cipher = None
+        if ticket is not None: # Never None, but gives indentation
+            self.assertElementPresent(ticket, 'tkt-vno')
+            self.assertElementEqualUTF8(ticket, 'realm', expected_srealm)
+            self.assertElementEqualPrincipal(ticket, 'sname', expected_sname)
+            self.assertElementPresent(ticket, 'enc-part')
+            ticket_encpart = self.getElementValue(ticket, 'enc-part')
+            if ticket_encpart is not None: # Never None, but gives indentation
+                self.assertElementPresent(ticket_encpart, 'etype')
+                # 0 means present, with any value != 0
+                self.assertElementKVNO(ticket_encpart, 'kvno', 0)
+                self.assertElementPresent(ticket_encpart, 'cipher')
+                ticket_cipher = self.getElementValue(ticket_encpart, 'cipher')
+        self.assertElementPresent(rep, 'enc-part')
+        encpart = self.getElementValue(rep, 'enc-part')
+        encpart_cipher = None
+        if encpart is not None: # Never None, but gives indentation
+            self.assertElementPresent(encpart, 'etype')
+            self.assertElementKVNO(ticket_encpart, 'kvno', 'autodetect')
+            self.assertElementPresent(encpart, 'cipher')
+            encpart_cipher = self.getElementValue(encpart, 'cipher')
+
+        encpart_decryption_key = None
+        if check_padata_fn is not None:
+            # See if get the decryption key from the preauth phase
+            encpart_decryption_key,encpart_decryption_usage = \
+                    check_padata_fn(req, padata, check_padata_dict)
+
+        ticket_private = None
+        if ticket_decryption_key is not None:
+            self.assertElementKVNO(ticket_encpart, 'kvno', ticket_decryption_key.kvno)
+            ticket_usage = 2
+            ticket_decpart = ticket_decryption_key.decrypt(ticket_usage, ticket_cipher)
+            ticket_private = self.der_decode(ticket_decpart, asn1Spec=krb5_asn1.EncTicketPart())
+
+        rep_private = None
+        if encpart_decryption_key is not None:
+            self.assertElementKVNO(encpart, 'kvno', encpart_decryption_key.kvno)
+            rep_decpart = encpart_decryption_key.decrypt(encpart_decryption_usage, encpart_cipher)
+            rep_private = self.der_decode(rep_decpart, asn1Spec=check_encpart_asn1Spec)
+
+        if check_ticket_fn is not None and ticket_private is not None:
+            check_ticket_fn(rep, ticket, ticket_private, check_ticket_dict)
+
+        if check_encpart_fn is not None and rep_private is not None:
+            check_encpart_fn(rep, rep_private, check_encpart_dict)
+
+        return rep
+
+    def _test_as_rep_check(self,
+                           rep,
+                           expected_crealm,
+                           expected_cname,
+                           expected_srealm,
+                           expected_sname,
+                           ticket_decryption_key=None):
+        return self._test_kdc_rep_check(rep,
+                                        11, # AS-REP
+                                        expected_crealm,
+                                        expected_cname,
+                                        expected_srealm,
+                                        expected_sname,
+                                        ticket_decryption_key=ticket_decryption_key)