def test_mit_EncASRepPart_FAST_support(self): creds = self.get_user_creds() (enc, _) = self.as_req(creds) self.assertEqual(MIT_ENC_AS_REP_PART_TYPE_TAG, enc[0]) as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncTGSRepPart()) flags = int(as_rep['flags'], base=2) # MIT sets enc-pa-rep, flag bit 15 # RFC 6806 11. Negotiation of FAST and Detecting Modified Requests self.assertTrue(ENC_PA_REP_FLAG & flags)
def get_as_rep_enc_data(self, key, rep): ''' Decrypt and Decode the encrypted data in an AS-REP ''' enc_part = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with # application tag 26 try: enc_part = self.der_decode(enc_part, asn1Spec=krb5_asn1.EncASRepPart()) except Exception: enc_part = self.der_decode(enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) return enc_part
def tgs_req(self, cname, sname, realm, ticket, key, etypes): '''Send a TGS-REQ, returns the response and the decrypted and decoded enc-part ''' kdc_options = "0" till = self.get_KerberosTime(offset=36000) padata = [] subkey = self.RandomKey(key.etype) (ctime, cusec) = self.get_KerberosTimeWithUsec() req = self.TGS_REQ_create(padata=padata, cusec=cusec, ctime=ctime, ticket=ticket, kdc_options=str(kdc_options), cname=cname, realm=realm, sname=sname, from_time=None, till_time=till, renew_time=None, nonce=0x7ffffffe, etypes=etypes, addresses=None, EncAuthorizationData=None, EncAuthorizationData_key=None, additional_tickets=None, ticket_session_key=key, authenticator_subkey=subkey) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) msg_type = rep['msg-type'] enc_part = None if msg_type == KRB_TGS_REP: enc_part = subkey.decrypt(KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part = self.der_decode(enc_part, asn1Spec=krb5_asn1.EncTGSRepPart()) return (rep, enc_part)
def test_simple(self): user_creds = self.get_user_creds() user = user_creds.get_username() realm = user_creds.get_realm() cname = self.PrincipalName_create(name_type=1, names=[user]) sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) till = self.get_KerberosTime(offset=36000) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None etypes = (18, 17, 23) 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) self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) rep_padata = self.der_decode( rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break etype_info2 = self.der_decode( etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) (patime, pausec) = self.get_KerberosTimeWithUsec() pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = [pa_ts] 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 = rep['msg-type'] self.assertEqual(msg_type, 11) enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with # application tag 26 try: enc_part2 = self.der_decode( enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) except Exception: enc_part2 = self.der_decode( enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # TGS Request service_creds = self.get_service_creds(allow_missing_password=True) service_name = service_creds.get_username() sname = self.PrincipalName_create( name_type=2, names=["host", service_name]) kdc_options = krb5_asn1.KDCOptions('forwardable') till = self.get_KerberosTime(offset=36000) ticket = rep['ticket'] ticket_session_key = self.EncryptionKey_import(enc_part2['key']) padata = [] subkey = self.RandomKey(ticket_session_key.etype) (ctime, cusec) = self.get_KerberosTimeWithUsec() req = self.TGS_REQ_create(padata=padata, cusec=cusec, ctime=ctime, ticket=ticket, kdc_options=str(kdc_options), cname=cname, realm=realm, sname=sname, from_time=None, till_time=till, renew_time=None, nonce=0x7ffffffe, etypes=etypes, addresses=None, EncAuthorizationData=None, EncAuthorizationData_key=None, additional_tickets=None, ticket_session_key=ticket_session_key, authenticator_subkey=subkey) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) msg_type = rep['msg-type'] self.assertEqual(msg_type, 13) enc_part2 = subkey.decrypt( KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part2 = self.der_decode( enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return
def as_req(self, data): user_creds = data.user_creds realm = data.realm cname = data.cname sname = data.sname till = self.get_KerberosTime(offset=36000) kdc_options = "0" if data.canonicalize: kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) padata = None # Set the allowable encryption types etypes = (AES256_CTS_HMAC_SHA1_96, AES128_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5) req = self.AS_REQ_create(padata=padata, kdc_options=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) # # Check the protocol version, should be 5 self.assertEqual(rep['pvno'], 5, "Data {0}".format(str(data))) self.assertEqual(rep['msg-type'], KRB_ERROR, "Data {0}".format(str(data))) self.assertEqual( rep['error-code'], KDC_ERR_PREAUTH_REQUIRED, "Error code {0}, Data {1}".format(rep['error-code'], str(data))) rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) (patime, pausec) = self.get_KerberosTimeWithUsec() pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) enc_pa_ts_usage = 1 pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(PADATA_ENC_TIMESTAMP, pa_ts) kdc_options = "0" if data.canonicalize: kdc_options = str(krb5_asn1.KDCOptions('canonicalize')) padata = [pa_ts] req = self.AS_REQ_create(padata=padata, kdc_options=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) # # Check the protocol version, should be 5 self.assertEqual(rep['pvno'], 5, "Data {0}".format(str(data))) msg_type = rep['msg-type'] # Should not have got an error. # If we did, fail and print the error code to help debugging self.assertNotEqual( msg_type, KRB_ERROR, "Error code {0}, Data {1}".format(rep.get('error-code', ''), str(data))) self.assertEqual(msg_type, KRB_AS_REP, "Data {0}".format(str(data))) # Decrypt and decode the EncKdcRepPart enc = key.decrypt(3, rep['enc-part']['cipher']) if enc[0] == 0x7A: # MIT Kerberos Tags the EncASRepPart as a EncKDCRepPart # i.e. tag number 26 instead of tag number 25 as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncTGSRepPart()) else: as_rep = self.der_decode(enc, asn1Spec=krb5_asn1.EncASRepPart()) return (rep, as_rep)
def test_xrealm(self): user_creds = self.get_user_creds() user = user_creds.get_username() realm = user_creds.get_realm() cname = self.PrincipalName_create(name_type=1, names=[user]) sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) till = self.get_KerberosTime(offset=36000) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None etypes=(18,17,23) 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) self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(user_creds, etype_info2[0]) (patime, pausec) = self.get_KerberosTimeWithUsec() pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) enc_pa_ts_usage = 1 pa_ts = self.EncryptedData_create(key, enc_pa_ts_usage, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = [pa_ts] 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 = rep['msg-type'] self.assertEqual(msg_type, 11) usage = 3 enc_part2 = key.decrypt(usage, rep['enc-part']['cipher']) # MIT KDC encodes both EncASRepPart and EncTGSRepPart with application tag 26 try: enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) except Exception: enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # TGS Request (for cross-realm TGT) trust_realm = samba.tests.env_get_var_value('TRUST_REALM') sname = self.PrincipalName_create(name_type=2, names=["krbtgt", trust_realm]) kdc_options = krb5_asn1.KDCOptions('forwardable') till = self.get_KerberosTime(offset=36000) ticket = rep['ticket'] ticket_session_key = self.EncryptionKey_import(enc_part2['key']) padata = [] subkey = self.RandomKey(ticket_session_key.etype) subkey_usage = 9 (ctime, cusec) = self.get_KerberosTimeWithUsec() req = self.TGS_REQ_create(padata=padata, cusec=cusec, ctime=ctime, ticket=ticket, kdc_options=str(kdc_options), cname=cname, realm=realm, sname=sname, from_time=None, till_time=till, renew_time=None, nonce=0x7ffffffe, etypes=etypes, addresses=None, EncAuthorizationData=None, EncAuthorizationData_key=None, additional_tickets=None, ticket_session_key=ticket_session_key, authenticator_subkey=subkey) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) msg_type = rep['msg-type'] self.assertEqual(msg_type, 13) enc_part2 = subkey.decrypt(subkey_usage, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) # Check the forwardable flag fwd_pos = len(tuple(krb5_asn1.TicketFlags('forwardable'))) -1 assert(krb5_asn1.TicketFlags(enc_part2['flags'])[fwd_pos]) return
def _test_s4u2self(self, pa_s4u2self_ctype=None): service_creds = self.get_service_creds() service = service_creds.get_username() realm = service_creds.get_realm() cname = self.PrincipalName_create(name_type=1, names=[service]) sname = self.PrincipalName_create(name_type=2, names=["krbtgt", realm]) till = self.get_KerberosTime(offset=36000) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = None etypes = (18, 17, 23) 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) self.assertEqual(rep['msg-type'], 30) self.assertEqual(rep['error-code'], 25) rep_padata = self.der_decode(rep['e-data'], asn1Spec=krb5_asn1.METHOD_DATA()) for pa in rep_padata: if pa['padata-type'] == 19: etype_info2 = pa['padata-value'] break etype_info2 = self.der_decode(etype_info2, asn1Spec=krb5_asn1.ETYPE_INFO2()) key = self.PasswordKey_from_etype_info2(service_creds, etype_info2[0]) (patime, pausec) = self.get_KerberosTimeWithUsec() pa_ts = self.PA_ENC_TS_ENC_create(patime, pausec) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.PA_ENC_TS_ENC()) pa_ts = self.EncryptedData_create(key, KU_PA_ENC_TIMESTAMP, pa_ts) pa_ts = self.der_encode(pa_ts, asn1Spec=krb5_asn1.EncryptedData()) pa_ts = self.PA_DATA_create(2, pa_ts) kdc_options = krb5_asn1.KDCOptions('forwardable') padata = [pa_ts] 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 = rep['msg-type'] self.assertEqual(msg_type, 11) enc_part2 = key.decrypt(KU_AS_REP_ENC_PART, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncASRepPart()) # S4U2Self Request sname = cname for_user_name = env_get_var_value('FOR_USER') uname = self.PrincipalName_create(name_type=1, names=[for_user_name]) kdc_options = krb5_asn1.KDCOptions('forwardable') till = self.get_KerberosTime(offset=36000) ticket = rep['ticket'] ticket_session_key = self.EncryptionKey_import(enc_part2['key']) pa_s4u = self.PA_S4U2Self_create(name=uname, realm=realm, tgt_session_key=ticket_session_key, ctype=pa_s4u2self_ctype) padata = [pa_s4u] subkey = self.RandomKey(ticket_session_key.etype) (ctime, cusec) = self.get_KerberosTimeWithUsec() req = self.TGS_REQ_create(padata=padata, cusec=cusec, ctime=ctime, ticket=ticket, kdc_options=str(kdc_options), cname=cname, realm=realm, sname=sname, from_time=None, till_time=till, renew_time=None, nonce=0x7ffffffe, etypes=etypes, addresses=None, EncAuthorizationData=None, EncAuthorizationData_key=None, additional_tickets=None, ticket_session_key=ticket_session_key, authenticator_subkey=subkey) rep = self.send_recv_transaction(req) self.assertIsNotNone(rep) msg_type = rep['msg-type'] if msg_type == 13: enc_part2 = subkey.decrypt(KU_TGS_REP_ENC_PART_SUB_KEY, rep['enc-part']['cipher']) enc_part2 = self.der_decode(enc_part2, asn1Spec=krb5_asn1.EncTGSRepPart()) return msg_type