From 67d0db78f692cb9332ff4b94cf421e99ebbe9e25 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Dec 01 2015 15:13:17 +0000 Subject: Handle unknown SAML2 SP's when logging out In the case where a logout is in progress and an unknown SP is in the session list it is marked as logged out and logout continues (with logging). This is expected to be a fairly rare occurance as it involves adding an SP, having users log into it, then removing it and restarting Apache. In the case where a logout request or response is received from an unknown SP a 400 is raised. We might be able to find a user session but because we can't authenticate the SP there is no way to know if this is a request from that user or some sort of DoS attack so an error is raised. https://fedorahosted.org/ipsilon/ticket/187 Signed-off-by: Rob Crittenden Reviewed-by: Patrick Uiterwijk --- diff --git a/ipsilon/providers/saml2/logout.py b/ipsilon/providers/saml2/logout.py index f706c72..b34203f 100644 --- a/ipsilon/providers/saml2/logout.py +++ b/ipsilon/providers/saml2/logout.py @@ -240,11 +240,14 @@ class LogoutRequest(ProviderPageBase): saml_sessions = self.cfg.idp.sessionfactory + logout_type = None try: if lasso.SAML2_FIELD_REQUEST in message: + logout_type = "request" self._handle_logout_request(us, logout, saml_sessions, message) elif samlresponse: + logout_type = "response" self._handle_logout_response(us, logout, saml_sessions, message, samlresponse) else: @@ -252,6 +255,10 @@ class LogoutRequest(ProviderPageBase): 'logout request or response.') except InvalidRequest as e: raise cherrypy.HTTPError(400, 'Bad Request. %s' % e) + except UnknownProvider as e: + raise cherrypy.HTTPError( + 400, 'Invalid logout %s: %s' % (logout_type, e) + ) # Fall through to handle any remaining sessions. @@ -271,12 +278,22 @@ class LogoutRequest(ProviderPageBase): self.error('Failed to load session: %s' % e) raise cherrypy.HTTPRedirect(400, 'Failed to log out user: %s ' % e) - if logout_mech == lasso.SAML2_METADATA_BINDING_REDIRECT: - logout.initRequest(session.provider_id, - lasso.HTTP_METHOD_REDIRECT) - else: - logout.initRequest(session.provider_id, - lasso.HTTP_METHOD_SOAP) + try: + if logout_mech == lasso.SAML2_METADATA_BINDING_REDIRECT: + logout.initRequest(session.provider_id, + lasso.HTTP_METHOD_REDIRECT) + else: + logout.initRequest(session.provider_id, + lasso.HTTP_METHOD_SOAP) + except lasso.ServerProviderNotFoundError: + self.error( + 'Service Provider %s not found. Trying next session' % + session.provider_id + ) + saml_sessions.remove_session(session) + (logout_mech, session) = saml_sessions.get_next_logout( + logout_mechs=logout_order) + continue try: logout.buildRequestMsg() diff --git a/ipsilon/providers/saml2idp.py b/ipsilon/providers/saml2idp.py index f5854d8..a6137f8 100644 --- a/ipsilon/providers/saml2idp.py +++ b/ipsilon/providers/saml2idp.py @@ -416,7 +416,14 @@ Provides SAML 2.0 authentication infrastructure. """ logout = self.idp.get_logout_handler() logout.setSessionFromDump(session.login_session) - logout.initRequest(session.provider_id) + try: + logout.initRequest(session.provider_id) + except lasso.ServerProviderNotFoundError: + self.error( + 'Service Provider %s not found. Trying next session' % + session.provider_id + ) + return self.idp_initiated_logout() try: logout.buildRequestMsg() except lasso.Error, e: