[Freeipa-devel] [freeipa PR#649][synchronized] Session cookie storage and handling fixes
URL: https://github.com/freeipa/freeipa/pull/649 Author: simo5 Title: #649: Session cookie storage and handling fixes Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/649/head:pr649 git checkout pr649 From 9fd0b4ce68daac2edbc38ccc743d4b7c1fafdf9d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:25:38 -0400 Subject: [PATCH 1/4] Avoid growing FILE ccaches unnecessarily Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce --- ipapython/session_storage.py | 6 ++ 1 file changed, 6 insertions(+) diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py index bcf0947..f208827 100644 --- a/ipapython/session_storage.py +++ b/ipapython/session_storage.py @@ -111,6 +111,12 @@ def store_data(princ_name, key, value): if not isinstance(value, bytes): value = value.encode('utf-8') +# FILE ccaches grow every time an entry is stored, so we need +# to avoid storing the same entry multiple times. +oldvalue = get_data(princ_name, key) +if oldvalue == value: +return + context = krb5_context() principal = krb5_principal() ccache = krb5_ccache() From 7653192d67de8d6b19259ece49f6c1d31f788665 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:38:22 -0400 Subject: [PATCH 2/4] 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 --- ipalib/rpc.py | 52 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 303b22a..f597ce0 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -586,22 +586,33 @@ def _handle_exception(self, e, service=None): 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 @@ def get_host_info(self, host): 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 @@ def _auth_complete(self, response): 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):
[Freeipa-devel] [freeipa PR#649][synchronized] Session cookie storage and handling fixes
URL: https://github.com/freeipa/freeipa/pull/649 Author: simo5 Title: #649: Session cookie storage and handling fixes Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/649/head:pr649 git checkout pr649 From 9fd0b4ce68daac2edbc38ccc743d4b7c1fafdf9d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:25:38 -0400 Subject: [PATCH 1/4] Avoid growing FILE ccaches unnecessarily Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce --- ipapython/session_storage.py | 6 ++ 1 file changed, 6 insertions(+) diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py index bcf0947..f208827 100644 --- a/ipapython/session_storage.py +++ b/ipapython/session_storage.py @@ -111,6 +111,12 @@ def store_data(princ_name, key, value): if not isinstance(value, bytes): value = value.encode('utf-8') +# FILE ccaches grow every time an entry is stored, so we need +# to avoid storing the same entry multiple times. +oldvalue = get_data(princ_name, key) +if oldvalue == value: +return + context = krb5_context() principal = krb5_principal() ccache = krb5_ccache() From 7653192d67de8d6b19259ece49f6c1d31f788665 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:38:22 -0400 Subject: [PATCH 2/4] 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 --- ipalib/rpc.py | 52 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 303b22a..f597ce0 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -586,22 +586,33 @@ def _handle_exception(self, e, service=None): 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 @@ def get_host_info(self, host): 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 @@ def _auth_complete(self, response): 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):
[Freeipa-devel] [freeipa PR#649][synchronized] Session cookie storage and handling fixes
URL: https://github.com/freeipa/freeipa/pull/649 Author: simo5 Title: #649: Session cookie storage and handling fixes Action: synchronized To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/649/head:pr649 git checkout pr649 From 9fd0b4ce68daac2edbc38ccc743d4b7c1fafdf9d Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:25:38 -0400 Subject: [PATCH 1/4] Avoid growing FILE ccaches unnecessarily Related https://pagure.io/freeipa/issue/6775 Signed-off-by: Simo Sorce --- ipapython/session_storage.py | 6 ++ 1 file changed, 6 insertions(+) diff --git a/ipapython/session_storage.py b/ipapython/session_storage.py index bcf0947..f208827 100644 --- a/ipapython/session_storage.py +++ b/ipapython/session_storage.py @@ -111,6 +111,12 @@ def store_data(princ_name, key, value): if not isinstance(value, bytes): value = value.encode('utf-8') +# FILE ccaches grow every time an entry is stored, so we need +# to avoid storing the same entry multiple times. +oldvalue = get_data(princ_name, key) +if oldvalue == value: +return + context = krb5_context() principal = krb5_principal() ccache = krb5_ccache() From 7653192d67de8d6b19259ece49f6c1d31f788665 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 22 Mar 2017 18:38:22 -0400 Subject: [PATCH 2/4] 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 --- ipalib/rpc.py | 52 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/ipalib/rpc.py b/ipalib/rpc.py index 303b22a..f597ce0 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -586,22 +586,33 @@ def _handle_exception(self, e, service=None): 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 @@ def get_host_info(self, host): 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 @@ def _auth_complete(self, response): 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):