From dddf6c413200044e8ebca1952e0a290920e6c5ca Mon Sep 17 00:00:00 2001 From: bdauvergne Date: Tue, 29 Sep 2009 09:25:06 +0000 Subject: [PATCH] Fix logout one more time - larpe/sessions.py: when expiring a session, remove all data indexed by the providerId - larpe/site_authentication.py: allows to give directly the list of cookies to local_logout(), bypass the fact that cookies are stored in Federation object that are by identity and by session objects (but cookies are by session). The result is that if the user clean its cookies, re-login on the same larpe SP, at next logout, the first session will not be logged out, but larpe could perfectly terminate it if the cookies had been kept somewhere. - larpe/saml2.ptl: do not kill session during logout, you never know if they are not shared with another service provider (they are used by all site behind larpe ;( ). instead clean up data indexed by provider Id, and ask for local_logout() and expire_session() to run. git-svn-id: svn+ssh://labs.libre-entreprise.org/svnroot/larpe@481 3ed937ae-f919-0410-9a43-8e6f19e4ba6e --- larpe/trunk/larpe/saml2.ptl | 57 +++++++++++++++-------- larpe/trunk/larpe/sessions.py | 4 ++ larpe/trunk/larpe/site_authentication.ptl | 8 ++-- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/larpe/trunk/larpe/saml2.ptl b/larpe/trunk/larpe/saml2.ptl index 6ee26b0..94a2648 100644 --- a/larpe/trunk/larpe/saml2.ptl +++ b/larpe/trunk/larpe/saml2.ptl @@ -279,10 +279,10 @@ class Saml2(Saml2Directory): get_logger().warn('Request Denied') elif error[0] == lasso.LOGOUT_ERROR_UNKNOWN_PRINCIPAL: get_logger().warn('Unknown principal on logout, probably session stopped already on IdP') - # XXX: wouldn't work when logged on two IdP - del session.lasso_session_dumps[logout.server.providerId] else: - raise + get_logger().error('Unknown Lasso exception on logout return: ' + repr(error)) + except Exception, exception: + get_logger().error('Unknown exception on logout return: ' + repr(exception)) get_session_manager().expire_session(logout.server.providerId) @@ -314,7 +314,8 @@ class Saml2(Saml2Directory): request_name_identifier = logout.nameIdentifier.content request_session_index = logout.request.sessionIndex if request_name_identifier == name_identifier and \ - (not session_index or request_session_index == session_index): + (not session_index or request_session_index == session_index) \ + and session.lasso_session_dump.get(providerId): get_logger().info('SLO/SOAP from %s' % logout.remoteProviderId) break else: @@ -345,7 +346,8 @@ class Saml2(Saml2Directory): request_name_identifier = logout.nameIdentifier.content request_session_index = logout.request.sessionIndex if request_name_identifier == name_identifier and \ - (not session_index or request_session_index == session_index): + (not session_index or request_session_index == session_index) \ + and session.lasso_session_dump.get(providerId): get_logger().info('SLO/SOAP from %s' % logout.remoteProviderId) break else: @@ -384,25 +386,42 @@ class Saml2(Saml2Directory): pass elif error[0] == lasso.PROFILE_ERROR_MISSING_ASSERTION: pass + elif error[0] == lasso.SERVER_ERROR_PROVIDER_NOT_FOUND: + pass + elif error[0] == lasso.NAME_IDENTIFIER_NOT_FOUND: + pass else: raise else: + try: + providerId = logout.server.providerId + session_index = logout.request.sessionIndex + name_identifier = logout.nameIdentifier.content + # Remove reference to local authentication on this SP in the session + # if a user is present, try a local logout + for session2 in get_session_manager().values(): + if session2.lasso_session_name_identifiers.get(providerId) == name_identifier \ + and ( not session_index + or session2.lasso_session_indexes.get(providerId) == session_index): + if session2.users.has_key(provider_id): + # try a local logout + try: + site_authentication.get_site_authentication(Host.get_host_from_url()).local_logout(user=session2.users[provider_id], cookies=getattr(session2,'cookies')) + except: + pass + del session2.users[provider_id] + if session2.lasso_session_dumps.has_key(provider_id): + del session2.lasso_session_dumps[provider_id] + if session2.lasso_session_indexes.has_key(provider_id): + del session2.lasso_session_indexes[provider_id] + if session2.lasso_session_name_identifiers.has_key(provider_id): + del session2.lasso_session_name_identifiers[provider_id] + session2.store() + except: + # killing all session failed, ignoring silently + pass get_session_manager().expire_session(logout.server.providerId) - try: - providerId = logout.server.providerId - session_index = logout.request.sessionIndex - name_identifier = logout.nameIdentifier.content - # Remove all session for this name_identifier and if present for this session index - for session2 in get_session_manager().values(): - if session2.lasso_session_name_identifiers.get(providerId) == name_identifier \ - and ( not session_index - or session2.lasso_session_indexes.get(providerId) == session_index): - del get_session_manager()[session2.id] - except: - # killing all session failed, ignoring silently - pass - logout.buildResponseMsg() if logout.msgBody: # soap answer return logout.msgBody diff --git a/larpe/trunk/larpe/sessions.py b/larpe/trunk/larpe/sessions.py index 465df16..aaa3a1d 100644 --- a/larpe/trunk/larpe/sessions.py +++ b/larpe/trunk/larpe/sessions.py @@ -81,6 +81,10 @@ class StorageSessionManager(SessionManager): del session.users[provider_id] if session.lasso_session_dumps.has_key(provider_id): del session.lasso_session_dumps[provider_id] + if session.lasso_session_indexes.has_key(provider_id): + del session.lasso_session_indexes[provider_id] + if session.lasso_session_name_identifiers.has_key(provider_id): + del session.lasso_session_name_identifiers[provider_id] session.store() if not session.users: SessionManager.expire_session(self) diff --git a/larpe/trunk/larpe/site_authentication.ptl b/larpe/trunk/larpe/site_authentication.ptl index 68f54aa..49cb8ee 100644 --- a/larpe/trunk/larpe/site_authentication.ptl +++ b/larpe/trunk/larpe/site_authentication.ptl @@ -290,15 +290,15 @@ class SiteAuthentication: return success, return_content - def local_logout(self, federation=None, user=None): - if federation is None and user is not None: + def local_logout(self, federation=None, user=None, cookies=None): + if cookies is None and federation is None and user is not None: federations = Federation.select(lambda x: user.name_identifiers[0] in x.name_identifiers) if federations: - federation = federations[0] + cookies = federations[0].cookies # Logout request to the site url = self.host.logout_url - if url is not None and federation is not None and federation.cookies is not None: + if url is not None and cookies is not None: try: http_get_page(url, {'Cookie': federation.cookies}) except: