From 176ea9c5c661c4326e7932fce81353a2a18f4e4d Mon Sep 17 00:00:00 2001 From: skelsec Date: Fri, 16 Apr 2021 23:41:46 +0200 Subject: [PATCH] support for kirbi, laxing spn checks --- minikerberos/aioclient.py | 37 ++++++++++++++++++++++++++--------- minikerberos/common/ccache.py | 11 ++++++++++- minikerberos/common/creds.py | 12 ++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/minikerberos/aioclient.py b/minikerberos/aioclient.py index 4954fc2..6febb81 100644 --- a/minikerberos/aioclient.py +++ b/minikerberos/aioclient.py @@ -128,18 +128,26 @@ def tgt_from_ccache(self, override_etype = None): our_user = str(self.usercreds.username) + '@' + self.usercreds.domain for tgt, keystruct in self.ccache.get_all_tgt(): - ticket_for = tgt['cname']['name-string'][0] + '@' + tgt['crealm'] - if ticket_for.upper() == our_user.upper(): - logger.debug('Found TGT for user %s' % our_user) + if self.usercreds.ccache_spn_strict_check is True: + ticket_for = tgt['cname']['name-string'][0] + '@' + tgt['crealm'] + if ticket_for.upper() == our_user.upper(): + logger.debug('Found TGT for user %s' % our_user) + self.kerberos_TGT = tgt + self.kerberos_TGT_encpart = tgt['enc-part'] + self.kerberos_session_key = Key(keystruct['keytype'], keystruct['keyvalue']) + self.kerberos_cipher = _enctype_table[keystruct['keytype']] + self.kerberos_cipher_type = keystruct['keytype'] + + return True, None + + else: self.kerberos_TGT = tgt self.kerberos_TGT_encpart = tgt['enc-part'] self.kerberos_session_key = Key(keystruct['keytype'], keystruct['keyvalue']) self.kerberos_cipher = _enctype_table[keystruct['keytype']] self.kerberos_cipher_type = keystruct['keytype'] - - return True, None - + logger.debug('No TGT found for user %s' % our_user) raise Exception('No TGT found for user %s' % our_user) @@ -241,9 +249,14 @@ def tgs_from_ccache(self, spn_user, override_etype): for tgs, keystruct in self.ccache.get_all_tgs(): ticket_for = ('/'.join(tgs['ticket']['sname']['name-string'])) + '@' + tgs['ticket']['realm'] - - if ticket_for.upper() == str(spn_user).upper(): - logger.debug('Found TGS for user %s' % ticket_for) + if self.usercreds.ccache_spn_strict_check is True: + if ticket_for.upper() == str(spn_user).upper(): + logger.debug('Found TGS for user %s' % ticket_for) + key = Key(keystruct['keytype'], keystruct['keyvalue']) + tgs = TGS_REP(tgs).native + return tgs, tgs['enc-part'], key, None + else: + # I hope you know what you are doing at this point... key = Key(keystruct['keytype'], keystruct['keyvalue']) tgs = TGS_REP(tgs).native return tgs, tgs['enc-part'], key, None @@ -270,6 +283,12 @@ async def get_TGS(self, spn_user, override_etype = None, is_linux = False): return tgs, encTGSRepPart, key + if self.kerberos_TGT is None: + #let's check if CCACHE has a TGT for us + _, err = self.tgt_from_ccache(override_etype=override_etype) + if err is not None: + raise Exception('No TGT found in CCACHE!') + #nope, we need to contact the server logger.debug('Constructing TGS request for user %s' % spn_user.get_formatted_pname()) now = datetime.datetime.now(datetime.timezone.utc) diff --git a/minikerberos/common/ccache.py b/minikerberos/common/ccache.py index b8b269f..7931ad8 100644 --- a/minikerberos/common/ccache.py +++ b/minikerberos/common/ccache.py @@ -395,7 +395,10 @@ def to_string(self, separator = '-'): def to_asn1(self): t = {'name-type': self.name_type, 'name-string': [name.to_string() for name in self.components]} - return t, self.realm.to_string() + return t, self.realm.to_string() + + def to_spn(self): + return '/'.join([name.to_string() for name in self.components]) + '@' + self.realm.to_string() @staticmethod def parse(reader): @@ -717,6 +720,12 @@ def to_kirbidir(self, directory_path): filepath = os.path.join(kf_abs, filename) with open(filepath, 'wb') as o: o.write(kirbi.dump()) + + def list_targets(self): + for cred in self.credentials: + target = cred.server + yield target.to_spn() + @staticmethod def from_file(filename): diff --git a/minikerberos/common/creds.py b/minikerberos/common/creds.py index e82e204..cefe1d7 100644 --- a/minikerberos/common/creds.py +++ b/minikerberos/common/creds.py @@ -29,6 +29,7 @@ def __init__(self): self.kerberos_key_rc4 = None self.kerberos_key_des3 = None self.ccache = None + self.ccache_spn_strict_check = True def get_preferred_enctype(self, server_enctypes): client_enctypes = self.get_supported_enctypes(as_int=False) @@ -123,6 +124,17 @@ def get_supported_enctypes(self, as_int = True): if as_int == True: return [etype.value for etype in supp_enctypes] return [etype for etype in supp_enctypes] + + @staticmethod + def from_krbcred(keytab_file_path: str): + return KerberosCredential.from_kirbi(keytab_file_path) + + @staticmethod + def from_kirbi(keytab_file_path: str): + cred = KerberosCredential() + cred.ccache = CCACHE.from_kirbifile(keytab_file_path) + cred.ccache_spn_strict_check = False + return cred @staticmethod def from_keytab(keytab_file_path: str, principal: str, realm: str):