diff options
-rw-r--r-- | ipalib/errors.py | 6 | ||||
-rw-r--r-- | ipaserver/rpcserver.py | 40 |
2 files changed, 15 insertions, 31 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py index d69e33062..09b7779e9 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -584,6 +584,12 @@ class InvalidSessionPassword(SessionError): errno = 1201 format= _('Principal %(principal)s cannot be authenticated: %(message)s') +class PasswordExpired(InvalidSessionPassword): + """ + **1202** Raised when we cannot obtain a TGT for a principal because the password is expired. + """ + errno = 1202 + ############################################################################## # 2000 - 2999: Authorization errors class AuthorizationError(PublicError): diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py index 454a53451..18de23d3a 100644 --- a/ipaserver/rpcserver.py +++ b/ipaserver/rpcserver.py @@ -39,7 +39,7 @@ from ipalib.capabilities import VERSION_WITHOUT_CAPABILITIES from ipalib.backend import Executioner from ipalib.errors import (PublicError, InternalError, CommandError, JSONError, CCacheError, RefererError, InvalidSessionPassword, NotFound, ACIError, - ExecutionError) + ExecutionError, PasswordExpired) from ipalib.request import context, destroy_context from ipalib.rpc import (xml_dumps, xml_loads, json_encode_binary, json_decode_binary) @@ -944,37 +944,12 @@ class login_password(Backend, KerberosSession, HTTP_Status): # Get the ccache we'll use and attempt to get credentials in it with user,password ipa_ccache_name = get_ipa_ccache_name() - reason = 'invalid-password' try: self.kinit(user, self.api.env.realm, password, ipa_ccache_name) - except InvalidSessionPassword, e: - # Ok, now why is this bad. Is the password simply bad or is the - # password expired? - try: - dn = DN(('uid', user), - self.api.env.container_user, - self.api.env.basedn) - conn = ldap2(shared_instance=False, - ldap_uri=self.api.env.ldap_uri) - conn.connect(bind_dn=dn, bind_pw=password) - - # password is ok, must be expired, lets double-check - entry_attrs = conn.get_entry(dn, - ['krbpasswordexpiration']) - if 'krbpasswordexpiration' in entry_attrs: - expiration = entry_attrs['krbpasswordexpiration'][0] - if expiration <= datetime.datetime.utcnow(): - reason = 'password-expired' - - except Exception: - # It doesn't really matter how we got here but the user's - # password is not accepted or the user is unknown. - pass - finally: - if conn.isconnected(): - conn.destroy_connection() - - return self.unauthorized(environ, start_response, str(e), reason) + except PasswordExpired as e: + return self.unauthorized(environ, start_response, str(e), 'password-expired') + except InvalidSessionPassword as e: + return self.unauthorized(environ, start_response, str(e), 'invalid-password') return self.finalize_kerberos_acquisition('login_password', ipa_ccache_name, environ, start_response) @@ -1001,7 +976,8 @@ class login_password(Backend, KerberosSession, HTTP_Status): (stdout, stderr, returncode) = ipautil.run( [paths.KINIT, principal, '-T', armor_path], - env={'KRB5CCNAME': ccache_name}, stdin=password, raiseonerr=False) + env={'KRB5CCNAME': ccache_name, 'LC_ALL': 'C'}, + stdin=password, raiseonerr=False) self.debug('kinit: principal=%s returncode=%s, stderr="%s"', principal, returncode, stderr) @@ -1013,6 +989,8 @@ class login_password(Backend, KerberosSession, HTTP_Status): raiseonerr=False) if returncode != 0: + if stderr.strip() == 'kinit: Cannot read password while getting initial credentials': + raise PasswordExpired(principal=principal, message=unicode(stderr)) raise InvalidSessionPassword(principal=principal, message=unicode(stderr)) class change_password(Backend, HTTP_Status): |