diff options
author | Simo Sorce <simo@redhat.com> | 2017-03-22 18:38:22 -0400 |
---|---|---|
committer | Tomas Krizek <tkrizek@redhat.com> | 2017-03-28 13:36:30 +0200 |
commit | fbbeb132bf37f8a03ef2f2184adb11796ab13d8b (patch) | |
tree | 00d007002e5b5bf782d55171b4c7e0a27743ac9e /ipalib | |
parent | 9a6ac74eb4421b9ffa831dc6fed067d2ddc0618e (diff) | |
download | freeipa-fbbeb132bf37f8a03ef2f2184adb11796ab13d8b.tar.gz freeipa-fbbeb132bf37f8a03ef2f2184adb11796ab13d8b.tar.xz freeipa-fbbeb132bf37f8a03ef2f2184adb11796ab13d8b.zip |
Handle failed authentication via cookie
If cookie authentication fails and we get back a 401 see if we
tried a SPNEGO auth by checking if we had a GSSAPI context. If not
it means our session cookie was invalid or expired or some other
error happened on the server that requires us to try a full SPNEGO
handshake, so go ahead and try it.
Fixes https://pagure.io/freeipa/issue/6775
Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-By: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/rpc.py | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 303b22a8a..f597ce0b7 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -586,22 +586,33 @@ class KerbTransport(SSLTransport): else: raise errors.KerberosError(message=unicode(e)) - def get_host_info(self, host): + def _get_host(self): + return self._connection[0] + + def _remove_extra_header(self, name): + for (h, v) in self._extra_headers: + if h == name: + self._extra_headers.remove((h, v)) + break + + def get_auth_info(self, use_cookie=True): """ Two things can happen here. If we have a session we will add a cookie for that. If not we will set an Authorization header. """ - (host, extra_headers, x509) = SSLTransport.get_host_info(self, host) - - if not isinstance(extra_headers, list): - extra_headers = [] + if not isinstance(self._extra_headers, list): + self._extra_headers = [] - session_cookie = getattr(context, 'session_cookie', None) - if session_cookie: - extra_headers.append(('Cookie', session_cookie)) - return (host, extra_headers, x509) + # Remove any existing Cookie first + self._remove_extra_header('Cookie') + if use_cookie: + session_cookie = getattr(context, 'session_cookie', None) + if session_cookie: + self._extra_headers.append(('Cookie', session_cookie)) + return # Set the remote host principal + host = self._get_host() service = self.service + "@" + host.split(':')[0] try: @@ -616,18 +627,14 @@ class KerbTransport(SSLTransport): except gssapi.exceptions.GSSError as e: self._handle_exception(e, service=service) - self._set_auth_header(extra_headers, response) - - return (host, extra_headers, x509) + self._set_auth_header(response) - def _set_auth_header(self, extra_headers, token): - for (h, v) in extra_headers: - if h == 'Authorization': - extra_headers.remove((h, v)) - break + def _set_auth_header(self, token): + # Remove any existing authorization header first + self._remove_extra_header('Authorization') if token: - extra_headers.append( + self._extra_headers.append( ('Authorization', 'negotiate %s' % base64.b64encode(token).decode('ascii')) ) @@ -651,18 +658,23 @@ class KerbTransport(SSLTransport): if self._sec_context.complete: self._sec_context = None return True - self._set_auth_header(self._extra_headers, token) + self._set_auth_header(token) + return False + elif response.status == 401: + self.get_auth_info(use_cookie=False) return False return True def single_request(self, host, handler, request_body, verbose=0): # Based on Python 2.7's xmllib.Transport.single_request try: - h = SSLTransport.make_connection(self, host) + h = self.make_connection(host) if verbose: h.set_debuglevel(1) + self.get_auth_info() + while True: if six.PY2: # pylint: disable=no-value-for-parameter |