248 lines
9.6 KiB
Diff
248 lines
9.6 KiB
Diff
|
From 33638de180a8157e369ad6c61f9e3406d9e85404 Mon Sep 17 00:00:00 2001
|
||
|
From: Stanislav Levin <slev@altlinux.org>
|
||
|
Date: Tue, 23 Jan 2024 19:12:53 +0300
|
||
|
Subject: [PATCH 1/3] ipapython: Clean up krb5_error
|
||
|
|
||
|
`krb5_error` has different definition in MIT krb.
|
||
|
https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/types/krb5_error.html
|
||
|
|
||
|
> Error message structure.
|
||
|
>
|
||
|
> Declaration:
|
||
|
> typedef struct _krb5_error krb5_error
|
||
|
|
||
|
While `krb5_error_code`
|
||
|
https://web.mit.edu/kerberos/www/krb5-latest/doc/appdev/refs/types/krb5_error_code.html#c.krb5_error_code
|
||
|
|
||
|
> krb5_error_code
|
||
|
> Used to convey an operation status.
|
||
|
>
|
||
|
> The value 0 indicates success; any other values are com_err codes. Use krb5_get_error_message() to obtain a string describing the error.
|
||
|
>
|
||
|
> Declaration
|
||
|
> typedef krb5_int32 krb5_error_code
|
||
|
|
||
|
And this is what was actually used.
|
||
|
|
||
|
To prevent confusion of types `krb5_error` was replaced with
|
||
|
`krb5_error_code`.
|
||
|
|
||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||
|
---
|
||
|
ipapython/session_storage.py | 25 ++++++++++++-------------
|
||
|
1 file changed, 12 insertions(+), 13 deletions(-)
|
||
|
|
||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||
|
index c43ef7d4e..371cf1524 100644
|
||
|
--- a/ipapython/session_storage.py
|
||
|
+++ b/ipapython/session_storage.py
|
||
|
@@ -111,7 +111,7 @@ class KRB5Error(Exception):
|
||
|
|
||
|
|
||
|
def krb5_errcheck(result, func, arguments):
|
||
|
- """Error checker for krb5_error return value"""
|
||
|
+ """Error checker for krb5_error_code return value"""
|
||
|
if result != 0:
|
||
|
raise KRB5Error(result, func.__name__, arguments)
|
||
|
|
||
|
@@ -119,14 +119,13 @@ def krb5_errcheck(result, func, arguments):
|
||
|
krb5_context = ctypes.POINTER(_krb5_context)
|
||
|
krb5_ccache = ctypes.POINTER(_krb5_ccache)
|
||
|
krb5_data_p = ctypes.POINTER(_krb5_data)
|
||
|
-krb5_error = ctypes.c_int32
|
||
|
krb5_creds = _krb5_creds
|
||
|
krb5_pointer = ctypes.c_void_p
|
||
|
krb5_cc_cursor = krb5_pointer
|
||
|
|
||
|
krb5_init_context = LIBKRB5.krb5_init_context
|
||
|
krb5_init_context.argtypes = (ctypes.POINTER(krb5_context), )
|
||
|
-krb5_init_context.restype = krb5_error
|
||
|
+krb5_init_context.restype = krb5_error_code
|
||
|
krb5_init_context.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_free_context = LIBKRB5.krb5_free_context
|
||
|
@@ -143,30 +142,30 @@ krb5_free_data_contents.restype = None
|
||
|
|
||
|
krb5_cc_default = LIBKRB5.krb5_cc_default
|
||
|
krb5_cc_default.argtypes = (krb5_context, ctypes.POINTER(krb5_ccache), )
|
||
|
-krb5_cc_default.restype = krb5_error
|
||
|
+krb5_cc_default.restype = krb5_error_code
|
||
|
krb5_cc_default.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_close = LIBKRB5.krb5_cc_close
|
||
|
krb5_cc_close.argtypes = (krb5_context, krb5_ccache, )
|
||
|
-krb5_cc_close.restype = krb5_error
|
||
|
+krb5_cc_close.restype = krb5_error_code
|
||
|
krb5_cc_close.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_parse_name = LIBKRB5.krb5_parse_name
|
||
|
krb5_parse_name.argtypes = (krb5_context, ctypes.c_char_p,
|
||
|
ctypes.POINTER(krb5_principal), )
|
||
|
-krb5_parse_name.restype = krb5_error
|
||
|
+krb5_parse_name.restype = krb5_error_code
|
||
|
krb5_parse_name.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_set_config = LIBKRB5.krb5_cc_set_config
|
||
|
krb5_cc_set_config.argtypes = (krb5_context, krb5_ccache, krb5_principal,
|
||
|
ctypes.c_char_p, krb5_data_p, )
|
||
|
-krb5_cc_set_config.restype = krb5_error
|
||
|
+krb5_cc_set_config.restype = krb5_error_code
|
||
|
krb5_cc_set_config.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_get_principal = LIBKRB5.krb5_cc_get_principal
|
||
|
krb5_cc_get_principal.argtypes = (krb5_context, krb5_ccache,
|
||
|
ctypes.POINTER(krb5_principal), )
|
||
|
-krb5_cc_get_principal.restype = krb5_error
|
||
|
+krb5_cc_get_principal.restype = krb5_error_code
|
||
|
krb5_cc_get_principal.errcheck = krb5_errcheck
|
||
|
|
||
|
# krb5_build_principal is a variadic function but that can't be expressed
|
||
|
@@ -177,26 +176,26 @@ krb5_build_principal.argtypes = (krb5_context, ctypes.POINTER(krb5_principal),
|
||
|
ctypes.c_uint, ctypes.c_char_p,
|
||
|
ctypes.c_char_p, ctypes.c_char_p,
|
||
|
ctypes.c_char_p, ctypes.c_char_p, )
|
||
|
-krb5_build_principal.restype = krb5_error
|
||
|
+krb5_build_principal.restype = krb5_error_code
|
||
|
krb5_build_principal.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_start_seq_get = LIBKRB5.krb5_cc_start_seq_get
|
||
|
krb5_cc_start_seq_get.argtypes = (krb5_context, krb5_ccache,
|
||
|
ctypes.POINTER(krb5_cc_cursor), )
|
||
|
-krb5_cc_start_seq_get.restype = krb5_error
|
||
|
+krb5_cc_start_seq_get.restype = krb5_error_code
|
||
|
krb5_cc_start_seq_get.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_next_cred = LIBKRB5.krb5_cc_next_cred
|
||
|
krb5_cc_next_cred.argtypes = (krb5_context, krb5_ccache,
|
||
|
ctypes.POINTER(krb5_cc_cursor),
|
||
|
ctypes.POINTER(krb5_creds), )
|
||
|
-krb5_cc_next_cred.restype = krb5_error
|
||
|
+krb5_cc_next_cred.restype = krb5_error_code
|
||
|
krb5_cc_next_cred.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_cc_end_seq_get = LIBKRB5.krb5_cc_end_seq_get
|
||
|
krb5_cc_end_seq_get.argtypes = (krb5_context, krb5_ccache,
|
||
|
ctypes.POINTER(krb5_cc_cursor), )
|
||
|
-krb5_cc_end_seq_get.restype = krb5_error
|
||
|
+krb5_cc_end_seq_get.restype = krb5_error_code
|
||
|
krb5_cc_end_seq_get.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents
|
||
|
@@ -212,7 +211,7 @@ krb5_principal_compare.restype = krb5_boolean
|
||
|
krb5_unparse_name = LIBKRB5.krb5_unparse_name
|
||
|
krb5_unparse_name.argtypes = (krb5_context, krb5_principal,
|
||
|
ctypes.POINTER(ctypes.c_char_p), )
|
||
|
-krb5_unparse_name.restype = krb5_error
|
||
|
+krb5_unparse_name.restype = krb5_error_code
|
||
|
krb5_unparse_name.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_free_unparsed_name = LIBKRB5.krb5_free_unparsed_name
|
||
|
--
|
||
|
2.43.0
|
||
|
|
||
|
|
||
|
From f8a616dc6196324145372713da772fe9b2352e53 Mon Sep 17 00:00:00 2001
|
||
|
From: Stanislav Levin <slev@altlinux.org>
|
||
|
Date: Tue, 23 Jan 2024 19:19:43 +0300
|
||
|
Subject: [PATCH 2/3] ipapython: Correct return type of krb5_free_cred_contents
|
||
|
|
||
|
According to https://web.mit.edu/kerberos/krb5-latest/doc/appdev/refs/api/krb5_free_cred_contents.html
|
||
|
|
||
|
> krb5_free_cred_contents - Free the contents of a krb5_creds structure.
|
||
|
>
|
||
|
> void krb5_free_cred_contents(krb5_context context, krb5_creds * val)
|
||
|
> param:
|
||
|
> [in] context - Library context
|
||
|
>
|
||
|
> [in] val - Credential structure to free contents of
|
||
|
>
|
||
|
> This function frees the contents of val , but not the structure itself.
|
||
|
|
||
|
https://github.com/krb5/krb5/blob/5b00197227231943bd2305328c8260dd0b0dbcf0/src/lib/krb5/krb/kfree.c#L166
|
||
|
|
||
|
This leads to undefined behavior and `krb5_free_cred_contents` can
|
||
|
raise KRB5Error (because of garbage data) while actually its foreign
|
||
|
function doesn't.
|
||
|
|
||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||
|
---
|
||
|
ipapython/session_storage.py | 3 +--
|
||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||
|
|
||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||
|
index 371cf1524..dc36f5493 100644
|
||
|
--- a/ipapython/session_storage.py
|
||
|
+++ b/ipapython/session_storage.py
|
||
|
@@ -200,8 +200,7 @@ krb5_cc_end_seq_get.errcheck = krb5_errcheck
|
||
|
|
||
|
krb5_free_cred_contents = LIBKRB5.krb5_free_cred_contents
|
||
|
krb5_free_cred_contents.argtypes = (krb5_context, ctypes.POINTER(krb5_creds))
|
||
|
-krb5_free_cred_contents.restype = krb5_error
|
||
|
-krb5_free_cred_contents.errcheck = krb5_errcheck
|
||
|
+krb5_free_cred_contents.restype = None
|
||
|
|
||
|
krb5_principal_compare = LIBKRB5.krb5_principal_compare
|
||
|
krb5_principal_compare.argtypes = (krb5_context, krb5_principal,
|
||
|
--
|
||
|
2.43.0
|
||
|
|
||
|
|
||
|
From 59b8a9fb7169561c7ba9168fe84f47ae94e5ce23 Mon Sep 17 00:00:00 2001
|
||
|
From: Stanislav Levin <slev@altlinux.org>
|
||
|
Date: Tue, 23 Jan 2024 19:52:34 +0300
|
||
|
Subject: [PATCH 3/3] ipapython: Propagate KRB5Error exceptions on iterating
|
||
|
ccache
|
||
|
|
||
|
`ipapython.session_storage.get_data` iterates over
|
||
|
credentials in a credential cache till `krb5_cc_next_cred` returns
|
||
|
an error. This function doesn't expect any error on calling
|
||
|
other kerberos foreign functions during iteration. But that can
|
||
|
actually happen and KRB5Error exceptions stop an iteration while
|
||
|
they should be propagated.
|
||
|
|
||
|
With this change iteration will exactly stop on `krb5_cc_next_cred`
|
||
|
error as it was supposed to be.
|
||
|
|
||
|
Fixes: https://pagure.io/freeipa/issue/9519
|
||
|
Signed-off-by: Stanislav Levin <slev@altlinux.org>
|
||
|
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
|
||
|
---
|
||
|
ipapython/session_storage.py | 10 ++++++----
|
||
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py
|
||
|
index dc36f5493..e890dc9b1 100644
|
||
|
--- a/ipapython/session_storage.py
|
||
|
+++ b/ipapython/session_storage.py
|
||
|
@@ -312,8 +312,12 @@ def get_data(princ_name, key):
|
||
|
checkcreds = krb5_creds()
|
||
|
# the next function will throw an error and break out of the
|
||
|
# while loop when we try to access past the last cred
|
||
|
- krb5_cc_next_cred(context, ccache, ctypes.byref(cursor),
|
||
|
- ctypes.byref(checkcreds))
|
||
|
+ try:
|
||
|
+ krb5_cc_next_cred(context, ccache, ctypes.byref(cursor),
|
||
|
+ ctypes.byref(checkcreds))
|
||
|
+ except KRB5Error:
|
||
|
+ break
|
||
|
+
|
||
|
if (krb5_principal_compare(context, principal,
|
||
|
checkcreds.client) == 1 and
|
||
|
krb5_principal_compare(context, srv_princ,
|
||
|
@@ -328,8 +332,6 @@ def get_data(princ_name, key):
|
||
|
else:
|
||
|
krb5_free_cred_contents(context,
|
||
|
ctypes.byref(checkcreds))
|
||
|
- except KRB5Error:
|
||
|
- pass
|
||
|
finally:
|
||
|
krb5_cc_end_seq_get(context, ccache, ctypes.byref(cursor))
|
||
|
|
||
|
--
|
||
|
2.43.0
|
||
|
|