New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session cookie storage and handling fixes #649
Conversation
Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce <simo@redhat.com>
If cookie authentication fails and we get back a 401 see if we tried a SPNEGO auth by checking if we had a GSSAPI context. If not it means our session cookie was invalid or expired or some other error happened on the server that requires us to try a full SPNEGO handshake, so go ahead and try it. Fixes https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce <simo@redhat.com>
|
Note I am still running tests, but I think the patchset is good for review already. |
|
The FILE ccache is still growing because we keep getting updated cookies (where the only thing that changes is the expiration date. |
|
I aded a 4th patch to address the FILE ccache growth issue. |
|
I tested the whole patchset. It worked for me first time I've got cookie expired. However, it broke in ~10 minutes afterwards -- apparently, keyring ccache was empty, according to I suspect we created something that MIT Kerberos library does not really understand. ... some time later, in a different execution of ipa user-show ... .... some time afterwards, without running kinit .... .... and running ipa user-show now succeeds in retrieving old cookie, invalidating it, negotiating a new one, and storing it .... |
|
@simo5, I think I found why it happened -- I actually had krbMaxTicketLife set for HTTP/... principal to 300 seconds. So I think your patches are good. I'd like you to fix fourth patch according to inline comments I left but that's it. |
ipapython/session_storage.py
Outdated
| class _krb5_keyblock(ctypes.Structure): # noqa | ||
| """krb5/krb5.h struct _krb5_keyblock""" | ||
| _fields_ = [ | ||
| ("magic", ctypes.c_int32), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are resolving typedefs all the way down. When I write ctypes code, I usually try to stick to original typedefs as close as possible. Your approach is also fine, just a bit harder to review.
krb5_int32 = ctypes.c_int32
krb5_enctype = krb5_int32
krb5_kvno = ctypes.c_uint
krb5_error_code = krb5_int32
krb5_magic = krb5_error_code
...
("magic", krb5_magic),
...
ipapython/session_storage.py
Outdated
| krb5_cc_get_principal.errcheck = krb5_errcheck | ||
|
|
||
| krb5_build_principal = LIBKRB5.krb5_build_principal | ||
| krb5_build_principal.argtypes = (krb5_context, ctypes.POINTER(krb5_principal), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment that this function is a variadic function and could take more arguments.
| krb5_free_cred_contents(context, | ||
| ctypes.byref(checkcreds)) | ||
| except KRB5Error: | ||
| pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first I though that the loop could leak checkcred in case krb5_principal_compare fails. Then I noticed that the comparison function only returns true/false. Please add a comment.
ipapython/session_storage.py
Outdated
| try: | ||
| while True: | ||
| checkcreds = krb5_creds() | ||
| krb5_cc_next_cred(context, ccache, ctypes.byref(cursor), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The while True loop contains neither break nor return. Please add a comment that explains the loop is terminated when krb5_cc_next_cred() raises an exception when it ha reached the end of the list.
|
@simo5 I left some comments. |
|
I should have addressed all comments. I did not comment on krb5_principal_compare() because I think that is obvious and the function definition also does not define an errcheck argument for it so it should be clear enough. |
Unfortunately the MIT krb5 library has a severe limitation with FILE ccaches when retrieving config data. It will always only search until the first entry is found and return that one. For FILE caches MIT krb5 does not support removing old entries when a new one is stored, and storage happens only in append mode, so the end result is that even if an update is stored it is never returned with the standard krb5_cc_get_config() call. To work around this issue we simply implement what krb5_cc_get_config() does under the hood with the difference that we do not stop at the first match but keep going until all ccache entries have been checked. Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce <simo@redhat.com>
We slice down the received cookie so that just the content that matter is preserved. Thi is ok because servers can't trust anything else anyway and will accept a cookie with the ancillary data missing. By removing variable parts like the expiry component added by mod_session or the Expiration or Max-Age metadata we keep only the part of the cookie that changes only when a new session is generated. This way when storing the cookie we actually add a new entry in the ccache only when the session actually changes, and this prevents churn on FILE based ccaches. Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce <simo@redhat.com>
|
LGTM to me. @simo5 explained that |
|
@simo5 Please rebase for |
|
Should I make a new PR for 4.5 ? |
|
Yes please |
This patchset improves the behavior of the client in various ways.