async def authenticate(self, authData, flags=None, seq_number=0, is_rpc=False): try: if self.kc is None: _, err = await self.setup_kc() if err is not None: return None, None, err if self.iterations == 0: try: #check TGS first, maybe ccache already has what we need for target in self.ccred.ccache.list_targets(): # just printing this to debug... logger.debug('CCACHE target SPN record: %s' % target) tgs, encpart, self.session_key = await self.kc.get_TGS( self.spn) self.from_ccache = True except Exception as e: # this is normal when no credentials stored in ccache #tgt = await self.kc.get_TGT(override_etype=[18]) tgt = await self.kc.get_TGT() tgs, encpart, self.session_key = await self.kc.get_TGS( self.spn) ap_opts = [] if is_rpc == True: if self.iterations == 0: ap_opts.append('mutual-required') flags = ChecksumFlags.GSS_C_CONF_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG | ChecksumFlags.GSS_C_SEQUENCE_FLAG|\ ChecksumFlags.GSS_C_REPLAY_FLAG | ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_DCE_STYLE if self.from_ccache is False: apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=flags, seq_number=seq_number, ap_opts=ap_opts) else: apreq = self.kc.construct_apreq_from_ticket( Ticket(tgs['ticket']).dump(), self.session_key, tgs['crealm'], tgs['cname']['name-string'][0], flags=flags, seq_number=seq_number, ap_opts=ap_opts, cb_data=None) self.iterations += 1 return apreq, False, None else: #mutual authentication part here self.seq_number = seq_number aprep = AP_REP.load(authData).native cipher = _enctype_table[int(aprep['enc-part']['etype'])]() cipher_text = aprep['enc-part']['cipher'] temp = cipher.decrypt(self.session_key, 12, cipher_text) enc_part = EncAPRepPart.load(temp).native cipher = _enctype_table[int( enc_part['subkey']['keytype'])]() now = datetime.datetime.now(datetime.timezone.utc) apreppart_data = {} apreppart_data['cusec'] = now.microsecond apreppart_data['ctime'] = now.replace(microsecond=0) apreppart_data['seq-number'] = enc_part['seq-number'] #print('seq %s' % enc_part['seq-number']) apreppart_data_enc = cipher.encrypt( self.session_key, 12, EncAPRepPart(apreppart_data).dump(), None) #overriding current session key self.session_key = Key(cipher.enctype, enc_part['subkey']['keyvalue']) ap_rep = {} ap_rep['pvno'] = 5 ap_rep['msg-type'] = MESSAGE_TYPE.KRB_AP_REP.value ap_rep['enc-part'] = EncryptedData({ 'etype': self.session_key.enctype, 'cipher': apreppart_data_enc }) token = AP_REP(ap_rep).dump() self.gssapi = get_gssapi(self.session_key) self.iterations += 1 return token, False, None else: if self.from_ccache is False: apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=flags, seq_number=seq_number, ap_opts=ap_opts) else: apreq = self.kc.construct_apreq_from_ticket( Ticket(tgs['ticket']).dump(), self.session_key, tgs['crealm'], tgs['cname']['name-string'][0], flags=flags, seq_number=seq_number, ap_opts=ap_opts, cb_data=None) return apreq, False, None except Exception as e: return None, None, e
async def authenticate(self, authData, flags=None, seq_number=0, is_rpc=False): if self.iterations == 0: #tgt = await self.kc.get_TGT(override_etype=[18]) tgt = await self.kc.get_TGT() tgs, encpart, self.session_key = await self.kc.get_TGS(self.spn) ap_opts = [] if is_rpc == True: if self.iterations == 0: ap_opts.append('mutual-required') flags = ChecksumFlags.GSS_C_CONF_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG | ChecksumFlags.GSS_C_SEQUENCE_FLAG|\ ChecksumFlags.GSS_C_REPLAY_FLAG | ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_DCE_STYLE apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=flags, seq_number=seq_number, ap_opts=ap_opts) self.iterations += 1 return apreq, False else: #mutual authentication part here aprep = AP_REP.load(authData).native cipher = _enctype_table[int(aprep['enc-part']['etype'])]() cipher_text = aprep['enc-part']['cipher'] temp = cipher.decrypt(self.session_key, 12, cipher_text) enc_part = EncAPRepPart.load(temp).native cipher = _enctype_table[int(enc_part['subkey']['keytype'])]() now = datetime.datetime.now(datetime.timezone.utc) apreppart_data = {} apreppart_data['cusec'] = now.microsecond apreppart_data['ctime'] = now.replace(microsecond=0) apreppart_data['seq-number'] = enc_part['seq-number'] apreppart_data_enc = cipher.encrypt( self.session_key, 12, EncAPRepPart(apreppart_data).dump(), None) #overriding current session key self.session_key = Key(cipher.enctype, enc_part['subkey']['keyvalue']) ap_rep = {} ap_rep['pvno'] = 5 ap_rep['msg-type'] = MESSAGE_TYPE.KRB_AP_REP.value ap_rep['enc-part'] = EncryptedData({ 'etype': self.session_key.enctype, 'cipher': apreppart_data_enc }) token = AP_REP(ap_rep).dump() self.gssapi = get_gssapi(self.session_key) self.iterations += 1 return token, False else: apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=flags, seq_number=seq_number, ap_opts=ap_opts) return apreq, False
async def authenticate(self, authData, flags=None, seq_number=0, cb_data=None): """ This function is called (multiple times depending on the flags) to perform authentication. """ try: if self.kc is None: _, err = await self.setup_kc() if err is not None: return None, None, err if self.iterations == 0: self.seq_number = 0 #int.from_bytes(os.urandom(4), byteorder='big', signed=False) self.iterations += 1 #tgt = await self.kc.get_TGT() tgt = await self.kc.get_TGT( override_etype=self.preferred_etypes) tgs, encpart, self.session_key = await self.kc.get_TGS( self.spn) #, override_etype = self.preferred_etypes) #self.expected_server_seq_number = encpart.get('nonce', seq_number) ap_opts = [] if ChecksumFlags.GSS_C_MUTUAL_FLAG in self.flags or ChecksumFlags.GSS_C_DCE_STYLE in self.flags: if ChecksumFlags.GSS_C_MUTUAL_FLAG in self.flags: ap_opts.append('mutual-required') apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=self.flags, seq_number=self.seq_number, ap_opts=ap_opts, cb_data=cb_data) return apreq, True, None else: #no mutual or dce auth will take one step only apreq = self.kc.construct_apreq(tgs, encpart, self.session_key, flags=self.flags, seq_number=self.seq_number, ap_opts=[], cb_data=cb_data) self.gssapi = get_gssapi(self.session_key) return apreq, False, None else: self.iterations += 1 #raise Exception('Not implemented!') if ChecksumFlags.GSS_C_DCE_STYLE in self.flags: # adata = authData[16:] # if ChecksumFlags.GSS_C_DCE_STYLE in self.flags: # adata = authData raise Exception('DCE auth Not implemented!') # at this point we are dealing with mutual authentication # This means that the server sent back an AP-rep wrapped in a token # The APREP contains a new session key we'd need to update and a seq-number # that is expected the server will use for future communication. # For mutual auth we dont need to reply anything after this step, # but for DCE auth a reply is expected. TODO # converting the token to aprep token = KRB5_MECH_INDEP_TOKEN.from_bytes(authData) if token.data[:2] != b'\x02\x00': raise Exception('Unexpected token type! %s' % token.data[:2].hex()) aprep = AP_REP.load(token.data[2:]).native # decrypting aprep cipher = _enctype_table[int(aprep['enc-part']['etype'])]() cipher_text = aprep['enc-part']['cipher'] temp = cipher.decrypt(self.session_key, 12, cipher_text) enc_part = EncAPRepPart.load(temp).native #updating session key, gssapi self.session_key = Key(int(enc_part['subkey']['keytype']), enc_part['subkey']['keyvalue']) #self.seq_number = enc_part.get('seq-number', 0) self.gssapi = get_gssapi(self.session_key) return b'', False, None except Exception as e: return None, None, e
async def authenticate(self, authData, flags = None, seq_number = 0, is_rpc = False): if self.iteractions == 0: self.setup() self.iteractions += 1 #authdata should be 0 at this point if self.is_azure is True: # kerberos service is on the same ip asreq = self.pkinit.build_asreq(target = self.target.get_hostname_or_ip(), kdcopts = ['forwardable','renewable','proxiable', 'canonicalize']) else: if self.target.dc_ip is None: raise Exception('DC IP must be set for kerberos auth!') asreq = self.pkinit.build_asreq(kdcopts = ['forwardable','renewable','proxiable', 'canonicalize']) negodata = generate_init_nego(self._msgctr, self._convid) self._msgctr += 1 metadata = self.__get_metadata() self._msgctr += 1 ap_req, token_raw = generate_ap_req(self._msgctr, self._convid, asreq, PKU2U_TOKEN_TYPE.KRB_AS_REQ) self._krb_finished_data += token_raw # for the checksum calc... self._msgctr += 1 msg = negodata + metadata + ap_req self._msgs += msg return msg, True, None elif self.iteractions == 1: from minikerberos.protocol.encryption import Enctype, _checksum_table, _enctype_table, Key self.iteractions += 1 self._msgs += authData msgs = negoexts_parse_bytes(authData) self._msgctr += len(msgs) #print(msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native) as_rep = msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native self._krb_finished_data += msgs[MESSAGE_TYPE.CHALLENGE].exchange_data_raw # for the checksum calc... encasrep, session_key, cipher = self.pkinit.decrypt_asrep(as_rep) self.xxxxx = session_key self.session_key_data = {} self.session_key_data['keytype'] = Enctype.AES256 self.session_key_data['keyvalue'] = os.urandom(32) subkey_cipher = _enctype_table[self.session_key_data['keytype']] subkey_key = Key(subkey_cipher.enctype, self.session_key_data['keyvalue']) subkey_checksum = _checksum_table[16] # ChecksumTypes.hmac_sha1_96_aes256 ap_req = self.pkinit.build_apreq(as_rep, session_key, cipher, self.session_key_data, self._krb_finished_data) ap_req_msg, _ = generate_ap_req(self._msgctr, self._convid, ap_req, PKU2U_TOKEN_TYPE.KRB_AP_REQ) #print(ap_req_msg.hex()) self._msgctr += 1 checksum_final = subkey_checksum.checksum(subkey_key, 25, self._msgs + ap_req_msg ) verify_msg = generate_verify(self._msgctr, self._convid, checksum_final, 16) self._msgctr += 1 ret_msg = ap_req_msg + verify_msg self._msgs += ret_msg return ret_msg, True, None elif self.iteractions == 2: from minikerberos.protocol.encryption import Enctype, _checksum_table, _enctype_table, Key from minikerberos.protocol.asn1_structs import EncAPRepPart #input('aaaaaaaaaaaaaa') self.iteractions += 1 self._msgs += authData msgs = negoexts_parse_bytes(authData) self._msgctr += len(msgs) ap_rep = msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native #print(ap_rep) #self.xxxxx cipher = _enctype_table[int(ap_rep['enc-part']['etype'])]() cipher_text = ap_rep['enc-part']['cipher'] subkey_key = Key(cipher.enctype, self.xxxxx.contents) temp = cipher.decrypt(subkey_key, 12, cipher_text) enc_part = EncAPRepPart.load(temp).native #print(enc_part) cipher = _enctype_table[int(enc_part['subkey']['keytype'])]() self.session_key = Key(cipher.enctype, enc_part['subkey']['keyvalue']) self.gssapi = get_gssapi(self.session_key) return None, False, None