From f51bf86032f9772989985c653d2e47322ac7b74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Kie=C3=9F?= Date: Thu, 15 Dec 2022 12:56:18 +0100 Subject: [PATCH] Add krb5_cc_retrieve_cred() and krb5_cc_remove_cred() --- src/krb5/__init__.py | 6 ++++ src/krb5/_ccache.pyi | 39 +++++++++++++++++++++ src/krb5/_ccache.pyx | 77 ++++++++++++++++++++++++++++++++++++++++++ src/krb5/python_krb5.h | 5 +++ 4 files changed, 127 insertions(+) diff --git a/src/krb5/__init__.py b/src/krb5/__init__.py index a3f87f1..112e892 100644 --- a/src/krb5/__init__.py +++ b/src/krb5/__init__.py @@ -3,6 +3,7 @@ from krb5._ccache import ( CCache, + CredentialsRetrieveFlags, cc_default, cc_default_name, cc_destroy, @@ -11,7 +12,9 @@ cc_get_type, cc_initialize, cc_new_unique, + cc_remove_cred, cc_resolve, + cc_retrieve_cred, cc_set_default_name, cc_store_cred, cc_switch, @@ -70,6 +73,7 @@ __all__ = [ "CCache", "Context", + "CredentialsRetrieveFlags", "Creds", "GetInitCredsOpt", "InitCredsContext", @@ -89,7 +93,9 @@ "cc_get_type", "cc_initialize", "cc_new_unique", + "cc_remove_cred", "cc_resolve", + "cc_retrieve_cred", "cc_set_default_name", "cc_store_cred", "cc_switch", diff --git a/src/krb5/_ccache.pyi b/src/krb5/_ccache.pyi index 2d87143..742e722 100644 --- a/src/krb5/_ccache.pyi +++ b/src/krb5/_ccache.pyi @@ -158,6 +158,24 @@ def cc_new_unique( CCache: The created credential cache. """ +def cc_remove_cred( + context: Context, + cache: CCache, + flags: typing.Union[int, CredentialsRetrieveFlags], + creds: Creds, +) -> None: + """Remove matching credentials from a credential cache. + + Remove all credential which match creds according to flags from the + credential cache. + + Args: + context: Krb5 context. + cache: The credential cache to store the creds into. + flags: The flags describing how to perform the matching. + creds: The credentials to match against. + """ + def cc_resolve( context: Context, name: bytes, @@ -177,6 +195,27 @@ def cc_resolve( CCache: The credential cache that was resolved. """ +def cc_retrieve_cred( + context: Context, + cache: CCache, + flags: typing.Union[int, CredentialsRetrieveFlags], + mcreds: Creds, +) -> Creds: + """Retrieve matching credentials from a credential cache. + + Retrieve all credential which match creds according to flags from the + credential cache. + + Args: + context: Krb5 context. + cache: The credential cache to store the creds into. + flags: The flags describing how to perform the matching. + mcreds: The credentials to match against. + + Returns: + Creds: The matching credentials. + """ + def cc_set_default_name( context: Context, name: typing.Optional[bytes], diff --git a/src/krb5/_ccache.pyx b/src/krb5/_ccache.pyx index e2669a8..dca0a30 100644 --- a/src/krb5/_ccache.pyx +++ b/src/krb5/_ccache.pyx @@ -1,6 +1,7 @@ # Copyright: (c) 2021 Jordan Borean (@jborean93) # MIT License (see LICENSE or https://opensource.org/licenses/MIT) +import enum import typing from libc.stdint cimport uintptr_t @@ -76,12 +77,27 @@ cdef extern from "python_krb5.h": krb5_creds *cred, ) nogil + krb5_error_code krb5_cc_remove_cred( + krb5_context context, + krb5_ccache cache, + int flags, + krb5_creds *creds, + ) nogil + krb5_error_code krb5_cc_resolve( krb5_context context, const char *name, krb5_ccache *cache, ) nogil + krb5_error_code krb5_cc_retrieve_cred( + krb5_context context, + krb5_ccache cache, + int flags, + krb5_creds *mcreds, + krb5_creds *creds, + ) nogil + krb5_error_code krb5_cc_set_default_name( krb5_context context, const char *name, @@ -104,6 +120,38 @@ cdef extern from "python_krb5.h": krb5_ccache cache, ) nogil + int32_t KRB5_TC_MATCH_TIMES + int32_t KRB5_TC_MATCH_IS_SKEY + int32_t KRB5_TC_MATCH_FLAGS + int32_t KRB5_TC_MATCH_TIMES_EXACT + int32_t KRB5_TC_MATCH_FLAGS_EXACT + int32_t KRB5_TC_MATCH_AUTHDATA + int32_t KRB5_TC_MATCH_SRV_NAMEONLY + int32_t KRB5_TC_MATCH_2ND_TKT + int32_t KRB5_TC_MATCH_KTYPE + int32_t KRB5_TC_SUPPORTED_KTYPES + + +_CredentialsRetrieveFlags_members = [ + ('none', 0), + ('match_times', KRB5_TC_MATCH_TIMES), + ('match_is_skey', KRB5_TC_MATCH_IS_SKEY), + ('match_flags', KRB5_TC_MATCH_FLAGS), + ('match_times_exact', KRB5_TC_MATCH_TIMES_EXACT), + ('match_flags_exact', KRB5_TC_MATCH_FLAGS_EXACT), + ('match_authdata', KRB5_TC_MATCH_AUTHDATA), + ('match_srv_nameonly', KRB5_TC_MATCH_SRV_NAMEONLY), + ('match_2nd_tkt', KRB5_TC_MATCH_2ND_TKT), + ('match_keytype', KRB5_TC_MATCH_KTYPE), +] +# If KRB5_TC_SUPPORTED_KTYPES is not available it will be set to 0 in +# python_krb5.h +if KRB5_TC_SUPPORTED_KTYPES != 0: + _CredentialsRetrieveFlags_members += [ + ('supported_ktypes', KRB5_TC_SUPPORTED_KTYPES), + ] +CredentialsRetrieveFlags = enum.IntEnum('CredentialsRetrieveFlags', _CredentialsRetrieveFlags_members) + cdef class CCache: # cdef Context ctx @@ -278,6 +326,19 @@ def cc_new_unique( return ccache +def cc_remove_cred( + Context context not None, + CCache cache not None, + int flags, + Creds creds not None, +) -> None: + cdef krb5_error_code err = 0 + + err = krb5_cc_remove_cred(context.raw, cache.raw, flags, &creds.raw) + if err: + raise Krb5Error(context, err) + + def cc_resolve( Context context not None, const unsigned char[:] name not None, @@ -298,6 +359,22 @@ def cc_resolve( return ccache +def cc_retrieve_cred( + Context context not None, + CCache cache not None, + int flags, + Creds mcreds not None, +) -> Creds: + creds = Creds(context) + cdef krb5_error_code err = 0 + + err = krb5_cc_retrieve_cred(context.raw, cache.raw, flags, &mcreds.raw, &creds.raw) + if err: + raise Krb5Error(context, err) + + return creds + + def cc_set_default_name( Context context not None, const unsigned char[:] name, diff --git a/src/krb5/python_krb5.h b/src/krb5/python_krb5.h index 6b4ea01..dbe335e 100644 --- a/src/krb5/python_krb5.h +++ b/src/krb5/python_krb5.h @@ -9,3 +9,8 @@ #ifndef KRB5_KT_PREFIX_MAX_LEN #define KRB5_KT_PREFIX_MAX_LEN -1 #endif + +// Heimdal does not define this +#ifndef KRB5_TC_SUPPORTED_KTYPES +#define KRB5_TC_SUPPORTED_KTYPES 0 +#endif