summaryrefslogtreecommitdiffstats
path: root/ipalib/rpc.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2012-07-16 10:40:12 -0400
committerRob Crittenden <rcritten@redhat.com>2012-07-18 16:05:08 -0400
commit429edcfb72674d113edddddc448e80a390210311 (patch)
treec8527a1f784677e74dc24b9adf5cb2b3743ba22e /ipalib/rpc.py
parent32c1aa45b3d41e15adb2ca8f8713e774046bc340 (diff)
downloadfreeipa-429edcfb72674d113edddddc448e80a390210311.tar.gz
freeipa-429edcfb72674d113edddddc448e80a390210311.tar.xz
freeipa-429edcfb72674d113edddddc448e80a390210311.zip
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
Diffstat (limited to 'ipalib/rpc.py')
-rw-r--r--ipalib/rpc.py34
1 files changed, 23 insertions, 11 deletions
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.