Exemplo n.º 1
0
    def operation(self, saml_msg, binding):
        logger.debug("_operation: %s", saml_msg)
        if not (saml_msg and "SAMLRequest" in saml_msg):
            resp = BadRequest("Error parsing request or no request")
            return resp(self.environ, self.start_response)
        else:
            # saml_msg may also contain Signature and SigAlg
            if "Signature" in saml_msg:
                try:
                    kwargs = {
                        "signature": saml_msg["Signature"],
                        "sigalg": saml_msg["SigAlg"],
                    }
                except KeyError:
                    resp = BadRequest("Signature Algorithm specification is missing")
                    return resp(self.environ, self.start_response)
            else:
                kwargs = {}

            try:
                kwargs["encrypt_cert"] = encrypt_cert_from_item(
                    saml_msg["req_info"].message
                )
            except KeyError:
                pass

            try:
                kwargs["relay_state"] = saml_msg["RelayState"]
            except KeyError:
                pass

            return self.do(saml_msg["SAMLRequest"], binding, **kwargs)
Exemplo n.º 2
0
    def do(self, query, binding, relay_state=""):
        req = IDP.parse_name_id_mapping_request(query, binding)
        request = req.message
        # Do the necessary stuff
        try:
            name_id = IDP.ident.handle_name_id_mapping_request(
                request.name_id, request.name_id_policy)
        except Unknown:
            resp = BadRequest("Unknown entity")
            return resp(self.environ, self.start_response)
        except PolicyError:
            resp = BadRequest("Unknown entity")
            return resp(self.environ, self.start_response)

        info = IDP.response_args(request)
        _resp = IDP.create_name_id_mapping_response(name_id, **info)

        # Only SOAP
        hinfo = IDP.apply_binding(BINDING_SOAP,
                                  "%s" % _resp,
                                  "",
                                  "",
                                  response=True)

        resp = Response(hinfo["data"], headers=hinfo["headers"])
        return resp(self.environ, self.start_response)
Exemplo n.º 3
0
    def redirect(self):
        """ This is the HTTP-redirect endpoint """

        logger.info("--- In SSO Redirect ---")
        saml_msg = self.unpack_redirect()

        try:
            _key = saml_msg["key"]
            saml_msg = IDP.ticket[_key]
            self.req_info = saml_msg["req_info"]
            del IDP.ticket[_key]
        except KeyError:
            try:
                self.req_info = IDP.parse_authn_request(
                    saml_msg["SAMLRequest"], BINDING_HTTP_REDIRECT
                )
            except KeyError:
                resp = BadRequest("Message signature verification failure")
                return resp(self.environ, self.start_response)

            if not self.req_info:
                resp = BadRequest("Message parsing failed")
                return resp(self.environ, self.start_response)

            _req = self.req_info.message

            if "SigAlg" in saml_msg and "Signature" in saml_msg:
                # Signed request
                issuer = _req.issuer.text
                _certs = IDP.metadata.certs(issuer, "any", "signing")
                verified_ok = False
                for cert in _certs:
                    if verify_redirect_signature(saml_msg, IDP.sec.sec_backend, cert):
                        verified_ok = True
                        break
                if not verified_ok:
                    resp = BadRequest("Message signature verification failure")
                    return resp(self.environ, self.start_response)

            if self.user:
                saml_msg["req_info"] = self.req_info
                if _req.force_authn is not None and _req.force_authn.lower() == "true":
                    key = self._store_request(saml_msg)
                    return self.not_authn(key, _req.requested_authn_context)
                else:
                    return self.operation(saml_msg, BINDING_HTTP_REDIRECT)
            else:
                saml_msg["req_info"] = self.req_info
                key = self._store_request(saml_msg)
                return self.not_authn(key, _req.requested_authn_context)
        else:
            return self.operation(saml_msg, BINDING_HTTP_REDIRECT)
Exemplo n.º 4
0
    def operation(self, _dict, binding, **kwargs):
        logger.debug("_operation: %s", _dict)
        if not _dict or "ID" not in _dict:
            resp = BadRequest("Error parsing request or no request")
            return resp(self.environ, self.start_response)

        return self.do(_dict["ID"], binding, **kwargs)
Exemplo n.º 5
0
 def artifact_operation(self, _dict):
     if not _dict:
         resp = BadRequest("Missing query")
         return resp(self.environ, self.start_response)
     else:
         # exchange artifact for response
         request = self.sp.artifact2message(_dict["SAMLart"], "spsso")
         return self.do(request, BINDING_HTTP_ARTIFACT, _dict["RelayState"])
Exemplo n.º 6
0
 def artifact_operation(self, saml_msg):
     if not saml_msg:
         resp = BadRequest("Missing query")
         return resp(self.environ, self.start_response)
     else:
         # exchange artifact for request
         request = IDP.artifact2message(saml_msg["SAMLart"], "spsso")
         try:
             return self.do(request, BINDING_HTTP_ARTIFACT, saml_msg["RelayState"])
         except KeyError:
             return self.do(request, BINDING_HTTP_ARTIFACT)
Exemplo n.º 7
0
 def operation(self, _dict, binding):
     logger.debug("_operation: %s", _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:
         try:
             return self.do(_dict["SAMLRequest"], binding,
                            _dict["RelayState"])
         except KeyError:
             # Can live with no relay state
             return self.do(_dict["SAMLRequest"], binding)
Exemplo n.º 8
0
 def operation(self, saml_msg, binding):
     logger.debug("_operation: %s", saml_msg)
     if not saml_msg or not 'SAMLRequest' in saml_msg:
         resp = BadRequest('Error parsing request or no request')
         return resp(self.environ, self.start_response)
     else:
         try:
             _encrypt_cert = encrypt_cert_from_item(
                 saml_msg["req_info"].message)
             return self.do(saml_msg["SAMLRequest"],
                            binding,
                            saml_msg["RelayState"],
                            encrypt_cert=_encrypt_cert)
         except KeyError:
             # Can live with no relay state
             return self.do(saml_msg["SAMLRequest"], binding)
Exemplo n.º 9
0
    def do(self, request, binding, relay_state=""):
        logger.info("--- Single Log Out Service ---")
        try:
            _, body = request.split("\n")
            logger.debug("req: '%s'", body)
            req_info = IDP.parse_logout_request(body, binding)
        except Exception as exc:
            logger.error("Bad request: %s", exc)
            resp = BadRequest("%s" % exc)
            return resp(self.environ, self.start_response)

        msg = req_info.message
        if msg.name_id:
            lid = IDP.ident.find_local_id(msg.name_id)
            logger.info("local identifier: %s", 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)
            except KeyError as exc:
                logger.error("ServiceError: %s", exc)
                resp = ServiceError("%s" % exc)
                return resp(self.environ, self.start_response)

        resp = IDP.create_logout_response(msg, [binding])

        try:
            hinfo = IDP.apply_binding(binding, "%s" % resp, "", relay_state)
        except Exception as exc:
            logger.error("ServiceError: %s", exc)
            resp = ServiceError("%s" % exc)
            return resp(self.environ, self.start_response)

        #_tlh = dict2list_of_tuples(hinfo["headers"])
        delco = delete_cookie(self.environ, "idpauthn")
        if delco:
            hinfo["headers"].append(delco)
        logger.info("Header: %s", hinfo["headers"])
        resp = Response(hinfo["data"], headers=hinfo["headers"])
        return resp(self.environ, self.start_response)
Exemplo n.º 10
0
def application(environ, start_response):
    """
    The main WSGI application. Dispatch the current request to
    the functions from above.

    If nothing matches, call the `not_found` function.

    :param environ: The HTTP application environment
    :param start_response: The application to run when the handling of the
        request is done
    :return: The response as a list of lines
    """
    path = environ.get("PATH_INFO", "").lstrip("/")
    logger.debug("<application> PATH: '%s'", path)

    if path == "metadata":
        return metadata(environ, start_response)

    logger.debug("Finding callback to run")
    try:
        for regex, spec in urls:
            match = re.search(regex, path)
            if match is not None:
                if isinstance(spec, tuple):
                    callback, func_name, _sp = spec
                    cls = callback(_sp, environ, start_response, cache=CACHE)
                    func = getattr(cls, func_name)
                    return func()
                else:
                    return spec(environ, start_response, SP)
        if re.match(".*static/.*", path):
            return handle_static(environ, start_response, path)
        return not_found(environ, start_response)
    except StatusError as err:
        logging.error("StatusError: %s" % err)
        resp = BadRequest("%s" % err)
        return resp(environ, start_response)
    except Exception as err:
        # _err = exception_trace("RUN", err)
        # logging.error(exception_trace("RUN", _err))
        print(err, file=sys.stderr)
        resp = ServiceError("%s" % err)
        return resp(environ, start_response)
Exemplo n.º 11
0
 def operation(self, _dict, binding):
     logger.debug("_operation: %s", _dict)
     if not _dict:
         resp = BadRequest("Error parsing request or no request")
         return resp(self.environ, self.start_response)
     else:
         try:
             _relay_state = _dict["RelayState"]
         except KeyError:
             _relay_state = ""
         if "SAMLResponse" in _dict:
             return self.do(_dict["SAMLResponse"],
                            binding,
                            _relay_state,
                            mtype="response")
         elif "SAMLRequest" in _dict:
             return self.do(_dict["SAMLRequest"],
                            binding,
                            _relay_state,
                            mtype="request")
Exemplo n.º 12
0
    def do(self, request, binding, relay_state="", encrypt_cert=None, **kwargs):

        logger.info("--- Single Log Out Service ---")
        try:
            logger.debug("req: '%s'", request)
            req_info = IDP.parse_logout_request(request, binding)
        except Exception as exc:
            logger.error("Bad request: %s", exc)
            resp = BadRequest("%s" % exc)
            return resp(self.environ, self.start_response)

        msg = req_info.message
        if msg.name_id:
            lid = IDP.ident.find_local_id(msg.name_id)
            logger.info("local identifier: %s", 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)
            except KeyError as exc:
                logger.error("Unknown session: %s", exc)
                resp = ServiceError("Unknown session: %s", exc)
                return resp(self.environ, self.start_response)

        resp = IDP.create_logout_response(msg, [binding])

        if binding == BINDING_SOAP:
            destination = ""
            response = False
        else:
            binding, destination = IDP.pick_binding(
                "single_logout_service", [binding], "spsso", req_info
            )
            response = True

        try:
            hinfo = IDP.apply_binding(
                binding, "%s" % resp, destination, relay_state, response=response
            )
        except Exception as exc:
            logger.error("ServiceError: %s", exc)
            resp = ServiceError("%s" % exc)
            return resp(self.environ, self.start_response)

        # _tlh = dict2list_of_tuples(hinfo["headers"])
        delco = delete_cookie(self.environ, "idpauthn")
        if delco:
            hinfo["headers"].append(delco)
        logger.info("Header: %s", (hinfo["headers"],))

        if binding == BINDING_HTTP_REDIRECT:
            for key, value in hinfo["headers"]:
                if key.lower() == "location":
                    resp = Redirect(value, headers=hinfo["headers"])
                    return resp(self.environ, self.start_response)

            resp = ServiceError("missing Location header")
            return resp(self.environ, self.start_response)
        else:
            resp = Response(hinfo["data"], headers=hinfo["headers"])
            return resp(self.environ, self.start_response)