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,
}
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)