URL: https://github.com/freeipa/freeipa/pull/638 Author: abbra Title: #638: ipalib/rpc.py: Fix session handling for KEYRING: ccaches Action: opened
PR body: """ MIT Kerberos allows to store configuration entries in the ccache. Unfortunately, there are big differences between ccache types in how these entries behave: - MIT Kerberos FILE: ccache code does always append entries, so we end up with ever growing ccache files. In KEYRING: case we are lucky that add_key syscall actually updates the key with the same name. - MIT Kerberos FILE: and KEYRING: ccache code does not allow to remove cred from ccache. Corresponding functions simply return KRB5_CC_NOSUPP; As result, using FILE: ccache type does not allow us to override our session cookie stored as a config entry in the ccache. Successive runs of ipa CLI create new entries in the ccache and only return the original one. Once we put a cookie in the FILE: ccache, it cannot be removed from there and cannot be replaced. Also, as retrieval code in krb5_cc_get_conf() ends up calling krb5_cc_retrieve_cred() with 0 flags and only has a cred principal name constructed out of a our conf key (X-IPA-Session_Cookie), none of the matching logic for "most recent ticket" could be applied. This commit attempts to improve situation for KEYRING: ccache type by setting the cookie to a predefined 'empty' value when deleting config entry. This avoids non-working 'remove cred' code path in ccache processing in MIT Kerberos. Additionally, when server side denies our cookie, it sends us empty Negotiate value. We errorneously treat it as invalid token. We also must use proper method to initialize our connection, SSLTransport.make_connection knows nothing about setting up GSSAPI client context, KrbTransport does. Unfortunately, with non-removable session cookie the code to initialize session context never triggered properly after expire. Fixes https://pagure.io/freeipa/issue/6775 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/638/head:pr638 git checkout pr638
From de6d317bfb0f024847a212aab0e6c1026bc84d5c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy <aboko...@redhat.com> Date: Wed, 22 Mar 2017 12:23:02 +0200 Subject: [PATCH] ipalib/rpc.py: Fix session handling for KEYRING: ccaches MIT Kerberos allows to store configuration entries in the ccache. Unfortunately, there are big differences between ccache types in how these entries behave: - MIT Kerberos FILE: ccache code does always append entries, so we end up with ever growing ccache files. In KEYRING: case we are lucky that add_key syscall actually updates the key with the same name. - MIT Kerberos FILE: and KEYRING: ccache code does not allow to remove cred from ccache. Corresponding functions simply return KRB5_CC_NOSUPP; As result, using FILE: ccache type does not allow us to override our session cookie stored as a config entry in the ccache. Successive runs of ipa CLI create new entries in the ccache and only return the original one. Once we put a cookie in the FILE: ccache, it cannot be removed from there and cannot be replaced. Also, as retrieval code in krb5_cc_get_conf() ends up calling krb5_cc_retrieve_cred() with 0 flags and only has a cred principal name constructed out of a our conf key (X-IPA-Session_Cookie), none of the matching logic for "most recent ticket" could be applied. This commit attempts to improve situation for KEYRING: ccache type by setting the cookie to a predefined 'empty' value when deleting config entry. This avoids non-working 'remove cred' code path in ccache processing in MIT Kerberos. Additionally, when server side denies our cookie, it sends us empty Negotiate value. We errorneously treat it as invalid token. We also must use proper method to initialize our connection, SSLTransport.make_connection knows nothing about setting up GSSAPI client context, KrbTransport does. Unfortunately, with non-removable session cookie the code to initialize session context never triggered properly after expire. Fixes https://pagure.io/freeipa/issue/6775 --- ipalib/rpc.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 303b22a..50b010d 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -92,6 +92,7 @@ COOKIE_NAME = 'ipa_session' CCACHE_COOKIE_KEY = 'X-IPA-Session-Cookie' +CCACHE_COOKIE_EMPTY_VALUE = 'X-IPA-Session-Cookie-Empty' errors_by_code = dict((e.errno, e) for e in public_errors) @@ -118,7 +119,10 @@ def read_persistent_client_session_data(principal): ''' try: - return session_storage.get_data(principal, CCACHE_COOKIE_KEY) + value = session_storage.get_data(principal, CCACHE_COOKIE_KEY) + if value == CCACHE_COOKIE_EMPTY_VALUE: + raise ValueError(CCACHE_COOKIE_EMPTY_VALUE) + return value except Exception as e: raise ValueError(str(e)) @@ -127,11 +131,17 @@ def delete_persistent_client_session_data(principal): Given a principal remove the session data for that principal from the persistent secure storage. + The code first overrides the session data with a value of + the constant CCACHE_COOKIE_EMPTY_VALUE as most ccache + types in MIT Kerberos do not support removal of creds. + Raises ValueError if unable to perform the action for any reason. ''' try: - session_storage.remove_data(principal, CCACHE_COOKIE_KEY) + session_storage.store_data(principal, CCACHE_COOKIE_KEY, + CCACHE_COOKIE_EMPTY_VALUE) + #session_storage.remove_data(principal, CCACHE_COOKIE_KEY) except Exception as e: raise ValueError(str(e)) @@ -644,7 +654,7 @@ def _auth_complete(self, response): # b64decode raises TypeError on invalid input except (TypeError, UnicodeError): pass - if not token: + if token is None: raise KerberosError( message=u"No valid Negotiate header in server response") token = self._sec_context.step(token=token) @@ -658,7 +668,7 @@ def _auth_complete(self, response): def single_request(self, host, handler, request_body, verbose=0): # Based on Python 2.7's xmllib.Transport.single_request try: - h = SSLTransport.make_connection(self, host) + h = self.make_connection(host) if verbose: h.set_debuglevel(1) @@ -1021,7 +1031,7 @@ def create_connection(self, ccache=None, verbose=None, fallback=None, except Exception as e: # This shouldn't happen if we have a session but it isn't fatal. pass - return self.create_connection(ccache, verbose, fallback, delegate) + return self.create_connection(ccache, verbose, fallback, delegate, ca_cerfile) if not fallback: raise serverproxy = None
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code