diff options
author | John Dennis <jdennis@redhat.com> | 2012-02-25 13:39:19 -0500 |
---|---|---|
committer | Rob Crittenden <rcritten@redhat.com> | 2012-02-27 05:57:43 -0500 |
commit | ee780df13c99a5465cd6df965772260c297a5eb2 (patch) | |
tree | 8f215388e7642ca590aa7d0c432f7591653843df /ipalib | |
parent | 059a90702e454b99490031bd37541304e65d35d2 (diff) | |
download | freeipa-ee780df13c99a5465cd6df965772260c297a5eb2.tar.gz freeipa-ee780df13c99a5465cd6df965772260c297a5eb2.tar.xz freeipa-ee780df13c99a5465cd6df965772260c297a5eb2.zip |
Implement password based session login
* Adjust URL's
- rename /ipa/login -> /ipa/session/login_kerberos
- add /ipa/session/login_password
* Adjust Kerberos protection on URL's in ipa.conf
* Bump VERSION in httpd ipa.conf to pick up session changes.
* Adjust login URL in ipa.js
* Add InvalidSessionPassword to errors.py
* Rename krblogin class to login_kerberos for consistency with
new login_password class
* Implement login_password.kinit() method which invokes
/usr/bin/kinit as a subprocess
* Add login_password class for WSGI dispatch, accepts POST
application/x-www-form-urlencoded user & password
parameters. We form the Kerberos principal from the server's
realm.
* Add function krb5_unparse_ccache()
* Refactor code to share common code
* Clean up use of ccache names, be consistent
* Replace read_krbccache_file(), store_krbccache_file(), delete_krbccache_file()
with load_ccache_data(), bind_ipa_ccache(), release_ipa_ccache().
bind_ipa_ccache() now sets environment KRB5CCNAME variable.
release_ipa_ccache() now clears environment KRB5CCNAME variable.
* ccache names should now support any ccache storage scheme,
not just FILE based ccaches
* Add utilies to return HTTP status from wsgi handlers,
use constants for HTTP status code for consistency.
Use utilies for returning from wsgi handlers rather than
duplicated code.
* Add KerberosSession.finalize_kerberos_acquisition() method
so different login handlers can share common code.
* add Requires: krb5-workstation to server (server now calls kinit)
* Fix test_rpcserver.py to use new dispatch inside route() method
https://fedorahosted.org/freeipa/ticket/2095
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/errors.py | 7 | ||||
-rw-r--r-- | ipalib/krb_utils.py | 13 | ||||
-rw-r--r-- | ipalib/session.py | 89 |
3 files changed, 78 insertions, 31 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py index bdc4a5e73..df4ab4167 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -612,6 +612,13 @@ class SessionError(AuthenticationError): format= _('Session error') +class InvalidSessionPassword(SessionError): + """ + **1201** Raised when we cannot obtain a TGT for a principal. + """ + errno = 1201 + format= _('Principal %(principal)s cannot be authenticated: %(message)s') + ############################################################################## # 2000 - 2999: Authorization errors class AuthorizationError(PublicError): diff --git a/ipalib/krb_utils.py b/ipalib/krb_utils.py index 7e68bf67b..a8f7751dd 100644 --- a/ipalib/krb_utils.py +++ b/ipalib/krb_utils.py @@ -42,7 +42,7 @@ ccache_name_re = re.compile(r'^((\w+):)?(.+)') #------------------------------------------------------------------------------- -def krb5_parse_ccache(name): +def krb5_parse_ccache(ccache_name): ''' Given a Kerberos ccache name parse it into it's scheme and location components. Currently valid values for the scheme @@ -55,12 +55,12 @@ def krb5_parse_ccache(name): does not exist it defaults to FILE. :parameters: - name + ccache_name The name of the Kerberos ccache. :returns: A two-tuple of (scheme, ccache) ''' - match = ccache_name_re.search(name) + match = ccache_name_re.search(ccache_name) if match: scheme = match.group(2) location = match.group(3) @@ -71,7 +71,10 @@ def krb5_parse_ccache(name): return scheme, location else: - raise ValueError('Invalid ccache name = "%s"' % name) + raise ValueError('Invalid ccache name = "%s"' % ccache_name) + +def krb5_unparse_ccache(scheme, name): + return '%s:%s' % (scheme.upper(), name) def krb5_format_principal_name(user, realm): ''' @@ -388,5 +391,5 @@ class KRB5_CCache(object): except KeyError: pass - self.debug('"%s" ccache endtime=%s (%s)', self.ccache_str(), result, krb5_format_time(result)) + self.debug('KRB5_CCache %s endtime=%s (%s)', self.ccache_str(), result, krb5_format_time(result)) return result diff --git a/ipalib/session.py b/ipalib/session.py index 5c71a92b6..4b783bbcb 100644 --- a/ipalib/session.py +++ b/ipalib/session.py @@ -1197,34 +1197,71 @@ class MemcacheSessionManager(SessionManager): krbccache_dir ='/var/run/ipa_memcached' krbccache_prefix = 'krbcc_' -def get_krbccache_pathname(): +def _get_krbccache_pathname(): return os.path.join(krbccache_dir, '%s%s' % (krbccache_prefix, os.getpid())) -def read_krbccache_file(krbccache_pathname): - root_logger.debug('reading krbccache data from "%s"', krbccache_pathname) - src = open(krbccache_pathname) - ccache_data = src.read() - src.close() - return ccache_data - -def store_krbccache_file(ccache_data): - krbccache_pathname = get_krbccache_pathname() - root_logger.debug('storing krbccache data into "%s"', krbccache_pathname) - dst = open(krbccache_pathname, 'w') - dst.write(ccache_data) - dst.close() - - return krbccache_pathname - -def delete_krbccache_file(krbccache_pathname=None): - if krbccache_pathname is None: - krbccache_pathname = get_krbccache_pathname() - - try: - os.unlink(krbccache_pathname) - except Exception, e: - root_logger.error('unable to delete session krbccache file "%s", %s', - krbccache_pathname, e) +def get_ipa_ccache_name(scheme='FILE'): + if scheme == 'FILE': + name = os.path.join(krbccache_dir, '%s%s' % (krbccache_prefix, os.getpid())) + else: + raise ValueError('ccache scheme "%s" unsupported', scheme) + + ccache_name = krb5_unparse_ccache(scheme, name) + return ccache_name + + +def load_ccache_data(ccache_name): + scheme, name = krb5_parse_ccache(ccache_name) + if scheme == 'FILE': + root_logger.debug('reading ccache data from file "%s"', name) + src = open(name) + ccache_data = src.read() + src.close() + return ccache_data + else: + raise ValueError('ccache scheme "%s" unsupported (%s)', scheme, ccache_name) + +def bind_ipa_ccache(ccache_data, scheme='FILE'): + if scheme == 'FILE': + name = _get_krbccache_pathname() + root_logger.debug('storing ccache data into file "%s"', name) + dst = open(name, 'w') + dst.write(ccache_data) + dst.close() + else: + raise ValueError('ccache scheme "%s" unsupported', scheme) + + ccache_name = krb5_unparse_ccache(scheme, name) + os.environ['KRB5CCNAME'] = ccache_name + return ccache_name + +def release_ipa_ccache(ccache_name): + ''' + Stop using the current request's ccache. + * Remove KRB5CCNAME from the enviroment + * Remove the ccache file from the file system + + Note, we do not demand any of these elements exist, but if they + do we'll remove them. + ''' + + if os.environ.has_key('KRB5CCNAME'): + if ccache_name != os.environ['KRB5CCNAME']: + root_logger.error('release_ipa_ccache: ccache_name (%s) != KRB5CCNAME environment variable (%s)', + ccache_name, os.environ['KRB5CCNAME']) + del os.environ['KRB5CCNAME'] + else: + root_logger.debug('release_ipa_ccache: KRB5CCNAME environment variable not set') + + scheme, name = krb5_parse_ccache(ccache_name) + if scheme == 'FILE': + if os.path.exists(name): + try: + os.unlink(name) + except Exception, e: + root_logger.error('unable to delete session ccache file "%s", %s', name, e) + else: + raise ValueError('ccache scheme "%s" unsupported (%s)', scheme, ccache_name) #------------------------------------------------------------------------------- |