Tweak the session auth to reflect developer consensus.

* Increase the session ID from 48 random bits to 128.

* Implement the sesison_logout RPC command. It permits the UI to send
  a command that destroys the users credentials in the current
  session.

* Restores the original web URL's and their authentication
  protections. Adds a new URL for sessions /ipa/session/json. Restores
  the original Kerberos auth which was for /ipa and everything
  below. New /ipa/session/json URL is treated as an exception and
  turns all authenticaion off. Similar to how /ipa/ui is handled.

* Refactor the RPC handlers in rpcserver.py such that there is one
  handler per URL, specifically one handler per RPC and AuthMechanism
  combination.

* Reworked how the URL names are used to map a URL to a
  handler. Previously it only permitted one level in the URL path
  hierarchy. We now dispatch on more that one URL path component.

* Renames the api.Backend.session object to wsgi_dispatch. The use of
  the name session was historical and is now confusing since we've
  implemented sessions in a different location than the
  api.Backend.session object, which is really a WSGI dispatcher, hence
  the new name wsgi_dispatch.

* Bullet-proof the setting of the KRB5CCNAME environment
  variable. ldap2.connect already sets it via the create_context()
  call but just in case that's not called or not called early enough
  (we now have other things besides ldap which need the ccache) we
  explicitly set it early as soon as we know it.

* Rework how we test for credential validity and expiration. The
  previous code did not work with s4u2proxy because it assumed the
  existance of a TGT. Now we first try ldap credentials and if we
  can't find those fallback to the TGT. This logic was moved to the
  KRB5_CCache object, it's an imperfect location for it but it's the
  only location that makes sense at the moment given some of the
  current code limitations. The new methods are KRB5_CCache.valid()
  and KRB5_CCache.endtime().

* Add two new classes to session.py AuthManager and
  SessionAuthManager. Their purpose is to emit authication events to
  interested listeners. At the moment the logout event is the only
  event, but the framework should support other events as they arise.

* Add BuildRequires python-memcached to freeipa.spec.in

* Removed the marshaled_dispatch method, it was cruft, no longer
  referenced.

https://fedorahosted.org/freeipa/ticket/2362
This commit is contained in:
John Dennis
2012-02-15 10:26:42 -05:00
committed by Rob Crittenden
parent 7d7322de2e
commit 9753fd4230
12 changed files with 376 additions and 126 deletions

View File

@@ -158,7 +158,6 @@ class KRB5_CCache(object):
self.ccache = None
self.principal = None
self.debug('opening ccache file "%s"', ccache)
try:
self.context = krbV.default_context()
self.scheme, self.name = krb5_parse_ccache(ccache)
@@ -228,8 +227,6 @@ class KRB5_CCache(object):
except krbV.Krb5Error, e:
error_code = e.args[0]
if error_code == KRB5_CC_NOTFOUND:
self.debug('"%s" credential not found in "%s" ccache',
krbV_principal.name, self.ccache_str()) #pylint: disable=E1103
raise KeyError('"%s" credential not found in "%s" ccache' % \
(krbV_principal.name, self.ccache_str())) #pylint: disable=E1103
raise e
@@ -281,7 +278,7 @@ class KRB5_CCache(object):
cred = self.get_credentials(krbV_principal)
authtime, starttime, endtime, renew_till = cred[3]
self.debug('principal=%s, authtime=%s, starttime=%s, endtime=%s, renew_till=%s',
self.debug('get_credential_times: principal=%s, authtime=%s, starttime=%s, endtime=%s, renew_till=%s',
krbV_principal.name, #pylint: disable=E1103
krb5_format_time(authtime), krb5_format_time(starttime),
krb5_format_time(endtime), krb5_format_time(renew_till))
@@ -327,3 +324,69 @@ class KRB5_CCache(object):
if endtime < now:
return False
return True
def valid(self, host, realm):
'''
Test to see if ldap service ticket or the TGT is valid.
:parameters:
host
ldap server
realm
kerberos realm
:returns:
True if either the ldap service ticket or the TGT is valid,
False otherwise.
'''
try:
principal = krb5_format_service_principal_name('ldap', host, realm)
valid = self.credential_is_valid(principal)
if valid:
return True
except KeyError:
pass
try:
principal = krb5_format_tgt_principal_name(realm)
valid = self.credential_is_valid(principal)
return valid
except KeyError:
return False
def endtime(self, host, realm):
'''
Returns the minimum endtime for tickets of interest (ldap service or TGT).
:parameters:
host
ldap server
realm
kerberos realm
:returns:
UNIX timestamp value.
'''
result = 0
try:
principal = krb5_format_service_principal_name('ldap', host, realm)
authtime, starttime, endtime, renew_till = self.get_credential_times(principal)
if result:
result = min(result, endtime)
else:
result = endtime
except KeyError:
pass
try:
principal = krb5_format_tgt_principal_name(realm)
authtime, starttime, endtime, renew_till = self.get_credential_times(principal)
if result:
result = min(result, endtime)
else:
result = endtime
except KeyError:
pass
self.debug('"%s" ccache endtime=%s', self.ccache_str(), krb5_format_time(result))
return result