From 429edcfb72674d113edddddc448e80a390210311 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mon, 16 Jul 2012 10:40:12 -0400 Subject: Support per-principal sessions and handle session update failures User had a system that refused to store keys into the kernel keyring. Any operation at all on the keyring would return "Key has been revoked". Wrap the operations in a try/except so we can ignore keyring failures. This also adds per-principal sessions. The principal name is stored in the session key so switching principals in the ccache doesn't require clearing the keyring. https://fedorahosted.org/freeipa/ticket/2880 --- ipalib/rpc.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) (limited to 'ipalib') diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 6518cb27d..8a6a51088 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -46,6 +46,7 @@ from ipalib.backend import Connectible from ipalib.errors import public_errors, PublicError, UnknownError, NetworkError, KerberosError, XMLRPCMarshallError from ipalib import errors from ipalib.request import context, Connection +from ipalib.util import get_current_principal from ipapython import ipautil from ipapython import kernel_keyring @@ -57,6 +58,8 @@ from urllib2 import urlparse from ipalib.krb_utils import KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, KRB5KRB_AP_ERR_TKT_EXPIRED, \ KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, KRB5_REALM_CANT_RESOLVE +COOKIE_NAME = 'ipa_session_cookie:%s' + def xml_wrap(value): """ Wrap all ``str`` in ``xmlrpclib.Binary``. @@ -258,12 +261,6 @@ class SSLTransport(LanguageAwareTransport): conn.connect() return conn - def parse_response(self, response): - session_cookie = response.getheader('Set-Cookie') - if session_cookie: - kernel_keyring.update_key('ipa_session_cookie', session_cookie) - return LanguageAwareTransport.parse_response(self, response) - class KerbTransport(SSLTransport): """ @@ -327,6 +324,18 @@ class KerbTransport(SSLTransport): return (host, extra_headers, x509) + def parse_response(self, response): + session_cookie = response.getheader('Set-Cookie') + if session_cookie: + principal = getattr(context, 'principal', None) + try: + kernel_keyring.update_key(COOKIE_NAME % principal, session_cookie) + except ValueError, e: + # Not fatal, we just can't use the session cookie we were + # sent. + pass + return SSLTransport.parse_response(self, response) + class DelegatedKerbTransport(KerbTransport): """ @@ -400,10 +409,12 @@ class xmlclient(Connectible): session = False session_data = None xmlrpc_uri = self.env.xmlrpc_uri + principal = get_current_principal() + setattr(context, 'principal', principal) # We have a session cookie, try using the session URI to see if it # is still valid if not delegate: - session_data = kernel_keyring.read_key('ipa_session_cookie') + session_data = kernel_keyring.read_key(COOKIE_NAME % principal) setattr(context, 'session_data', session_data) (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(self.env.xmlrpc_uri) xmlrpc_uri = urlparse.urlunparse((scheme, netloc, '/ipa/session/xml', params, query, fragment)) @@ -453,9 +464,9 @@ class xmlclient(Connectible): except ProtocolError, e: if session_data and e.errcode == 401: # Unauthorized. Remove the session and try again. + delattr(context, 'session_data') try: - kernel_keyring.del_key('ipa_session_cookie') - delattr(context, 'session_data') + kernel_keyring.del_key(COOKIE_NAME % principal) except ValueError: # This shouldn't happen if we have a session but # it isn't fatal. @@ -519,9 +530,10 @@ class xmlclient(Connectible): session_data = getattr(context, 'session_data', None) if session_data and e.errcode == 401: # Unauthorized. Remove the session and try again. + delattr(context, 'session_data') try: - kernel_keyring.del_key('ipa_session_cookie') - delattr(context, 'session_data') + principal = getattr(context, 'principal', None) + kernel_keyring.del_key(COOKIE_NAME % principal) except ValueError: # This shouldn't happen if we have a session but # it isn't fatal. -- cgit