From 4a32aab3a1d04540c299b94ed5fa64f5c15cb55a Mon Sep 17 00:00:00 2001 From: Andreas Richter Date: Fri, 7 Mar 2014 08:22:08 -0500 Subject: [PATCH] IDP logout fix, add .gitignore Make IDP logout a little more resilient by double checking content in the cache. Added some .gitignore for generated and copied files in idp, sp and idp2 folders. Allow both sp and idp2 to be mounted using wsgi container. Add static handler for css and other files in idp2. --- example/.gitignore | 9 ++++ example/idp2/idp.py | 75 ++++++++++++++++++++++++-------- example/idp2/static/css/main.css | 2 + example/idp2/templates/root.mako | 2 +- example/sp/sp.py | 3 ++ 5 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 example/.gitignore create mode 100644 example/idp2/static/css/main.css diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..4fcc7ec --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,9 @@ +idp/idp_conf.py +idp2/idp.subject +idp2/idp_conf.py +sp/outstanding +sp/sp_conf.py +server.crt +server.csr +server.key +server.key.org diff --git a/example/idp2/idp.py b/example/idp2/idp.py index 2ab9374..7520b87 100755 --- a/example/idp2/idp.py +++ b/example/idp2/idp.py @@ -120,7 +120,7 @@ class Service(object): def operation(self, _dict, binding): logger.debug("_operation: %s" % _dict) - if not _dict: + if not _dict or not 'SAMLRequest' in _dict: resp = BadRequest('Error parsing request or no request') return resp(self.environ, self.start_response) else: @@ -335,8 +335,13 @@ class SSO(Service): self.req_info = _info["req_info"] del IDP.ticket[_key] except KeyError: - self.req_info = IDP.parse_authn_request(_info["SAMLRequest"], - BINDING_HTTP_REDIRECT) + try: + self.req_info = IDP.parse_authn_request(_info["SAMLRequest"], + BINDING_HTTP_REDIRECT) + except KeyError: + resp = BadRequest("Message signature verification failure") + return resp(self.environ, self.start_response) + _req = self.req_info.message if "SigAlg" in _info and "Signature" in _info: # Signed request @@ -547,8 +552,11 @@ class SLO(Service): if msg.name_id: lid = IDP.ident.find_local_id(msg.name_id) logger.info("local identifier: %s" % lid) - del IDP.cache.uid2user[IDP.cache.user2uid[lid]] - del IDP.cache.user2uid[lid] + if lid in IDP.cache.user2uid: + uid = IDP.cache.user2uid[lid] + if uid in IDP.cache.uid2user: + del IDP.cache.uid2user[uid] + del IDP.cache.user2uid[lid] # remove the authentication try: IDP.session_db.remove_authn_statements(msg.name_id) @@ -843,6 +851,19 @@ def metadata(environ, start_response): logger.error("An error occured while creating metadata:" + ex.message) return not_found(environ, start_response) +def staticfile(environ, start_response): + try: + path = args.path + if path is None or len(path) == 0: + path = os.path.dirname(os.path.abspath(__file__)) + if path[-1] != "/": + path += "/" + path += environ.get('PATH_INFO', '').lstrip('/') + start_response('200 OK', [('Content-Type', "text/xml")]) + return open(path, 'r').read() + except Exception as ex: + logger.error("An error occured while creating metadata:" + ex.message) + return not_found(environ, start_response) def application(environ, start_response): """ @@ -900,19 +921,40 @@ def application(environ, start_response): return func() return callback(environ, start_response, user) + if re.search(r'static/.*', path) is not None: + return staticfile(environ, start_response) return not_found(environ, start_response) # ---------------------------------------------------------------------------- +# allow uwsgi or gunicorn mount +# by moving some initialization out of __name__ == '__main__' section. +# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp + +args = type('Config', (object,), { }) +args.config = 'idp_conf' +args.mako_root = './' +args.path = None + +import socket +from idp_user import USERS +from idp_user import EXTRA +from mako.lookup import TemplateLookup + +AUTHN_BROKER = AuthnBroker() +AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), + username_password_authn, 10, + "http://%s" % socket.gethostname()) +AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), + "", 0, "http://%s" % socket.gethostname()) + +IDP = server.Server(args.config, cache=Cache()) +IDP.ticket = {} # ---------------------------------------------------------------------------- if __name__ == '__main__': - import socket - from idp_user import USERS - from idp_user import EXTRA from wsgiref.simple_server import make_server - from mako.lookup import TemplateLookup parser = argparse.ArgumentParser() parser.add_argument('-p', dest='path', help='Path to configuration file.') @@ -937,16 +979,11 @@ if __name__ == '__main__': PORT = 8088 - AUTHN_BROKER = AuthnBroker() - AUTHN_BROKER.add(authn_context_class_ref(PASSWORD), - username_password_authn, 10, - "http://%s" % socket.gethostname()) - AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), - "", 0, "http://%s" % socket.gethostname()) - - IDP = server.Server(args.config, cache=Cache()) - IDP.ticket = {} - SRV = make_server('', PORT, application) print "IdP listening on port: %s" % PORT SRV.serve_forever() +else: + _rot = args.mako_root + LOOKUP = TemplateLookup(directories=[_rot + 'templates', _rot + 'htdocs'], + module_directory=_rot + 'modules', + input_encoding='utf-8', output_encoding='utf-8') diff --git a/example/idp2/static/css/main.css b/example/idp2/static/css/main.css new file mode 100644 index 0000000..9b44f63 --- /dev/null +++ b/example/idp2/static/css/main.css @@ -0,0 +1,2 @@ +/* Sample css file */ + diff --git a/example/idp2/templates/root.mako b/example/idp2/templates/root.mako index 3d6e9a0..c27e954 100644 --- a/example/idp2/templates/root.mako +++ b/example/idp2/templates/root.mako @@ -6,7 +6,7 @@ <% self.seen_css.add(path) %> <%def name="css()" filter="trim"> - ${css_link('/css/main.css', 'screen')} + ${css_link('/static/css/main.css', 'screen')} <%def name="pre()" filter="trim">
diff --git a/example/sp/sp.py b/example/sp/sp.py index b0a3c61..40d8858 100755 --- a/example/sp/sp.py +++ b/example/sp/sp.py @@ -270,6 +270,9 @@ app_with_auth = make_middleware_with_config(application, {"here": "."}, # ---------------------------------------------------------------------------- PORT = 8087 +# allow uwsgi or gunicorn mount +# by moving some initialization out of __name__ == '__main__' section. +# uwsgi -s 0.0.0.0:8087 --protocol http --callable app_with_auth --module idp if __name__ == '__main__': #make_metadata arguments