Пример #1
0
    def parse_response(self, environ):
        try:
            self.response_spec = resp = self.cresp()
        except TypeError:
            self.response_spec = None
            return True

        self.info = None
        self.response_message = None
        self.response_type = resp.response
        resp_type = resp.ctype

        _info = ""
        if resp.where == "url":
            try:
                if environ:
                    _info = environ["QUERY_STRING"]
                    self.trace.reply("RESPONSE: %s" % _info)
                else:
                    _info = self.last_response
                resp_type = "urlencoded"
            except KeyError:
                try:
                    _check = getattr(self.creq, "interaction_check", None)
                except AttributeError:
                    _check = None

                if _check:
                    self.err_check("interaction-check")
                else:
                    self.do_check("missing-redirect")
        else:
            self.do_check("check_content_type_header")
            if environ:
                _info = get_body(environ)
                self.trace.reply("RESPONSE: %s" % _info)
            else:
                _info = self.last_content

        if isinstance(resp.response, basestring):
            response = message_factory(resp.response)
        else:
            response = resp.response

        #self.response_type = response.__name__
        try:
            _cli = self.client

            if _cli.provider_info:
                kwargs = {"opponent_id": _cli.provider_info["issuer"]}
            else:
                kwargs = {}

            _qresp = _cli.parse_response(
                response, _info, resp_type, _cli.state,
                keyjar=_cli.keyjar, client_id=_cli.client_id,
                scope="openid", **kwargs)
            if _qresp:
                self.trace.info("[%s]: %s" % (_qresp.type(),
                                              _qresp.to_dict()))
                if _qresp.extra():
                    self.trace.info("### extra claims: %s" % _qresp.extra())
                self.response_message = _qresp
                self.protocol_response.append((_qresp, self.info))
            else:
                self.response_message = None
            err = None
            _errtxt = ""
        except Exception, err:
            _errtxt = "%s" % err
            self.trace.error(_errtxt)
            self.exception = _errtxt
Пример #2
0
def run_sequence(sequence_info, session, conv, ots, environ, start_response,
                 trace, index):
    while index < len(sequence_info["sequence"]):
        session["index"] = index
        try:
            req_c, resp_c = sequence_info["sequence"][index]
        except (ValueError, TypeError):  # Not a tuple
            ret = none_request_response(sequence_info, index, session, conv,
                                        environ, start_response)
            if ret:
                return ret
        else:
            req = req_c(conv)
            try:
                if req.tests["pre"]:
                    conv.test_output.append((req.request, "pre"))
                    conv.test_sequence(req.tests["pre"])
            except KeyError:
                pass
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "pre-test", err)

            conv.request_spec = req

            if req_c == TEST_FLOWS.Discover:
                # Special since it's just a GET on a URL
                _r = req.discover(
                    ots.client, issuer=ots.config.CLIENT["srv_discovery_url"])
                conv.position, conv.last_response, conv.last_content = _r
                logging.debug("Provider info: %s" % conv.last_content._dict)
                verify_support(conv, ots, session["graph"])
            else:
                LOGGER.info("request: %s" % req.request)
                if req.request == "AuthorizationRequest":
                    # New state for each request
                    kwargs = {"request_args": {"state": rndstr()}}
                elif req.request in [
                        "AccessTokenRequest", "UserInfoRequest",
                        "RefreshAccessTokenRequest"
                ]:
                    kwargs = {"state": conv.AuthorizationRequest["state"]}
                else:
                    kwargs = {}

                # Extra arguments outside the OIDC spec
                try:
                    _extra = ots.config.CLIENT["extra"][req.request]
                except KeyError:
                    pass
                except Exception as err:
                    return err_response(environ, start_response, session,
                                        "config_exta", err)
                else:
                    try:
                        kwargs["request_args"].update(_extra)
                    except KeyError:
                        kwargs["request_args"] = _extra

                req.call_setup()
                try:
                    url, body, ht_args = req.construct_request(
                        ots.client, **kwargs)
                except PyoidcError as err:  # A OIDC specific error
                    return err_response(environ, start_response, session,
                                        "construct_request", err)

                if req.request == "AuthorizationRequest":
                    session["response_type"] = req.request_args[
                        "response_type"]
                    LOGGER.info("redirect.url: %s" % url)
                    LOGGER.info("redirect.header: %s" % ht_args)
                    resp = Redirect(str(url))
                    return resp(environ, start_response)
                else:
                    _kwargs = {"http_args": ht_args}
                    try:
                        _kwargs["state"] = conv.AuthorizationRequest["state"]
                    except AttributeError:
                        pass

                    try:
                        response = request_and_return(
                            conv, url, message_factory(resp_c.response),
                            req.method, body, resp_c.ctype, **_kwargs)
                    except PyoidcError as err:
                        return err_response(environ, start_response, session,
                                            "request_and_return", err)

                    trace.info(response.to_dict())
                    LOGGER.info(response.to_dict())
                    if resp_c.response == "RegistrationResponse" and \
                            isinstance(response, RegistrationResponse):
                        ots.client.store_registration_info(response)
                    else:  # must be an ErrorResponse
                        conv.test_output.append({
                            'status':
                            4,
                            "id":
                            "*",
                            'message':
                            'Error response: %s' % (response.to_dict(), )
                        })
                        return opresult(environ, start_response, conv, session)

            try:
                post_tests(conv, req_c, resp_c)
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "post_test", err)

        index += 1
        _tid = session["testid"]
        session["test_info"][_tid] = {
            "trace": conv.trace,
            "test_output": conv.test_output
        }

    # wrap it up
    # Any after the fact tests ?
    try:
        if sequence_info["tests"]:
            conv.test_output.append(("After completing the test", ""))
            conv.test_sequence(sequence_info["tests"])
    except KeyError:
        pass
    except Exception as err:
        return err_response(environ, start_response, session, "post_test", err)

    _tid = session["testid"]
    session["test_info"][_tid] = {
        "trace": conv.trace,
        "test_output": conv.test_output
    }
    session["node"].complete = True

    resp = Redirect("%sopresult#%s" % (CONF.BASE, _tid[3]))
    return resp(environ, start_response)
Пример #3
0
    def parse_response(self, environ):
        try:
            self.response_spec = resp = self.cresp()
        except TypeError:
            self.response_spec = None
            return True

        self.info = None
        self.response_message = None
        self.response_type = resp.response
        resp_type = resp.ctype

        _info = ""
        if resp.where == "url":
            try:
                if environ:
                    _info = environ["QUERY_STRING"]
                    self.trace.reply("RESPONSE: %s" % _info)
                else:
                    _info = self.last_response
                resp_type = "urlencoded"
            except KeyError:
                try:
                    _check = getattr(self.creq, "interaction_check", None)
                except AttributeError:
                    _check = None

                if _check:
                    self.err_check("interaction-check")
                else:
                    self.do_check("missing-redirect")
        else:
            self.do_check("check_content_type_header")
            if environ:
                _info = get_body(environ)
                self.trace.reply("RESPONSE: %s" % _info)
            else:
                _info = self.last_content

        if isinstance(resp.response, basestring):
            response = message_factory(resp.response)
        else:
            response = resp.response

        #self.response_type = response.__name__
        try:
            _cli = self.client

            if _cli.provider_info:
                kwargs = {"opponent_id": _cli.provider_info["issuer"]}
            else:
                kwargs = {}

            _qresp = _cli.parse_response(response,
                                         _info,
                                         resp_type,
                                         _cli.state,
                                         keyjar=_cli.keyjar,
                                         client_id=_cli.client_id,
                                         scope="openid",
                                         **kwargs)
            if _qresp:
                self.trace.info("[%s]: %s" % (_qresp.type(), _qresp.to_dict()))
                if _qresp.extra():
                    self.trace.info("### extra claims: %s" % _qresp.extra())
                self.response_message = _qresp
                self.protocol_response.append((_qresp, self.info))
            else:
                self.response_message = None
            err = None
            _errtxt = ""
        except Exception, err:
            _errtxt = "%s" % err
            self.trace.error(_errtxt)
            self.exception = _errtxt
Пример #4
0
    def run_sequence(self, sequence_info, session, conv, ots, trace, index):
        while index < len(sequence_info["sequence"]):
            logger.info("###{i}### {f} ###{i}###".format(f=session["testid"],
                                                         i=index))
            session["index"] = index
            try:
                (req_c, resp_c), _kwa = sequence_info["sequence"][index]
            except (ValueError, TypeError):  # Not a tuple
                ret = self.none_request_response(sequence_info, index, session,
                                                 conv)
                self.dump_log(session)
                if isinstance(ret, basestring):
                    session["ckey"] = ret
                elif ret:
                    return ret
            else:
                if conv.protocol_response:
                    # If last response was an error response, bail out.
                    inst, txt = conv.protocol_response[-1]
                    try:
                        session["expect_error"]
                    except KeyError:
                        if isinstance(inst, ErrorResponse):
                            return self.err_response(session, "", inst)
                try:
                    kwargs = setup(_kwa, conv)
                except NotSupported:
                    self.store_test_info(session)
                    return self.opresult(conv, session)
                except Exception as err:
                    return self.err_response(session, "function()", err)

                try:
                    expect_error = _kwa["expect_error"]
                except KeyError:
                    expect_error = None
                else:
                    del _kwa["expect_error"]

                req = req_c(conv)
                try:
                    _pt = req.tests["pre"]
                except KeyError:
                    pass
                else:
                    if _pt:
                        try:
                            conv.test_output.append((req.request, "pre"))
                            conv.test_sequence(_pt)
                        except Exception as err:
                            return self.err_response(session, "pre-test", err)

                conv.request_spec = req

                conv.trace.info("------------ %s ------------" % req_c.request)
                if req_c == Discover:
                    # Special since it's just a GET on a URL
                    try:
                        _r = req.discover(
                            ots.client,
                            issuer=ots.config.CLIENT["srv_discovery_url"])
                    except ConnectionError:
                        self.log_fault(session, "Connection Error",
                                       "discover_request", ERROR)
                        conv.trace.info(END_TAG)
                        return self.fini(session, conv)

                    conv.position, conv.last_response, conv.last_content = _r

                    if conv.last_response.status >= 400:
                        return self.err_response(session, "discover",
                                                 conv.last_response.text)

                    for x in ots.client.keyjar[
                            ots.client.provider_info["issuer"]]:
                        try:
                            resp = ots.client.http_request(x.source)
                        except Exception as err:
                            return self.err_response(session, "jwks_fetch",
                                                     str(err))
                        else:
                            conv.last_response = resp
                            conv.last_content = resp.content
                            if resp.status_code < 300:
                                trace.info("JWKS: %s" %
                                           pprint_json(resp.content))
                            else:
                                return self.err_response(
                                    session, "jwks_fetch", resp.content)
                elif req_c == Webfinger:
                    try:
                        url = req.discover(**kwargs)
                    except ConnectionError:
                        self.log_fault(session, "Connection Error",
                                       "WebFinger_request", ERROR)
                        conv.trace.info(END_TAG)
                        return self.fini(session, conv)

                    if url:
                        conv.trace.request(url)
                        conv.test_output.append({
                            "id":
                            "-",
                            "status":
                            OK,
                            "message":
                            "Found discovery URL: %s" % url
                        })
                    else:
                        conv.test_output.append({
                            "id":
                            "-",
                            "status":
                            ERROR,
                            "message":
                            "Failed to find discovery URL"
                        })
                else:
                    try:
                        endp = req.endpoint
                    except AttributeError:
                        pass
                    else:
                        if not endpoint_support(conv.client, endp):
                            conv.test_output.append({
                                "id":
                                "-",
                                "status":
                                ERROR,
                                "message":
                                "%s not supported" % req.endpoint
                            })
                            return self.opresult(conv, session)

                    logger.info("request: %s" % req.request)
                    if req.request == "AuthorizationRequest":
                        # New state for each request
                        kwargs["request_args"].update({"state": rndstr()})
                        if not ots.client.provider_info:
                            return self.err_response(session, req.request,
                                                     "No provider info")
                    elif req.request in [
                            "AccessTokenRequest", "UserInfoRequest",
                            "RefreshAccessTokenRequest"
                    ]:
                        kwargs.update(
                            {"state": conv.AuthorizationRequest["state"]})
                        if not ots.client.provider_info:
                            return self.err_response(session, req.request,
                                                     "No provider info")

                    req.rm_nonstandard_args(message_factory)

                    # Extra arguments outside the OIDC spec
                    try:
                        _extra = ots.config.CLIENT["extra"][req.request]
                    except KeyError:
                        pass
                    except Exception as err:
                        return self.err_response(session, "config_extra", err)
                    else:
                        try:
                            kwargs["request_args"].update(_extra)
                        except KeyError:
                            kwargs["request_args"] = _extra

                    req.call_setup()

                    try:
                        url, body, ht_args = req.construct_request(
                            ots.client, **kwargs)
                    except PyoidcError as err:  # A OIDC specific error
                        return self.err_response(session, "construct_request",
                                                 err)

                    if req.request == "AuthorizationRequest":
                        session["response_type"] = kwargs["request_args"][
                            "response_type"]
                        logger.info("redirect.url: %s" % url)
                        logger.info("redirect.header: %s" % ht_args)
                        conv.timestamp.append((url, utc_time_sans_frac()))
                        resp = Redirect(str(url))
                        return resp(self.environ, self.start_response)
                    else:
                        _kwargs = {"http_args": ht_args}

                        if conv.AuthorizationRequest:
                            _kwargs["state"] = conv.AuthorizationRequest[
                                "state"]

                        try:
                            _method = kwargs["method"]
                        except KeyError:
                            _method = req.method
                        try:
                            _ctype = kwargs["ctype"]
                        except KeyError:
                            _ctype = resp_c.ctype

                        self.dump_log(session, session["testid"])

                        try:
                            response = request_and_return(
                                conv, url, trace,
                                message_factory(resp_c.response), _method,
                                body, _ctype, **_kwargs)
                        except MissingErrorResponse:
                            self.log_fault(session, "Missing Error Response",
                                           "request_response",
                                           self.get_err_type(session))
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                        except PyoidcError as err:
                            return self.err_response(session,
                                                     "request_and_return", err)
                        except JWKESTException as err:
                            return self.err_response(session,
                                                     "request_and_return", err)
                        except ConnectionError:
                            self.log_fault(session,
                                           "Connection Error", "request",
                                           self.get_err_type(session))
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                        if response is None:  # bail out
                            self.log_fault(session, "Empty response",
                                           "request_response",
                                           self.get_err_type(session))
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                        trace.response(response)
                        logger.info(response.to_dict())

                        if expect_error:
                            session["expect_error"] = True
                            if isinstance(response, ErrorResponse):
                                if expect_error["stop"]:
                                    index = len(sequence_info["sequence"])
                                    session["index"] = index
                                    continue
                            else:
                                trace.error("Expected error, didn't get it")
                                return self.err_response(
                                    session, "expected error", None)
                        else:
                            if resp_c.response == "RegistrationResponse":
                                if isinstance(response, RegistrationResponse):
                                    ots.client.store_registration_info(
                                        response)
                            elif resp_c.response == "AccessTokenResponse":
                                if "error" not in response:
                                    areq = conv.AuthorizationRequest.to_dict()
                                    try:
                                        del areq["acr_values"]
                                    except KeyError:
                                        pass

                try:
                    post_tests(conv, req_c, resp_c)
                except Exception as err:
                    return self.err_response(session, "post_test", err)

            index += 1
            _tid = session["testid"]
            self.dump_log(session, _tid)
            self.store_test_info(session)

        # wrap it up
        # Any after the fact tests ?
        try:
            if sequence_info["tests"]:
                conv.test_output.append(("After completing the test flow", ""))
                conv.test_sequence(sequence_info["tests"])
        except KeyError:
            pass
        except Exception as err:
            return self.err_response(session, "post_test", err)

        return self.fini(session, conv)
Пример #5
0
        if resp_c:  # None in cases where no OIDC response is expected
            _ctype = resp_c.ctype
            # parse the response
            if path == "authz_post":
                query = parse_qs(get_post(environ))
                info = query["fragment"][0]
                _ctype = "urlencoded"
            elif resp_c.where == "url":
                info = environ["QUERY_STRING"]
                _ctype = "urlencoded"
            else:  # resp_c.where == "body"
                info = get_post(environ)

            LOGGER.info("Response: %s" % info)
            resp_cls = message_factory(resp_c.response)
            try:
                response = ots.client.parse_response(
                    resp_cls,
                    info,
                    _ctype,
                    conv.AuthorizationRequest["state"],
                    keyjar=ots.client.keyjar)
            except ResponseError as err:
                return err_response(environ, start_response, session,
                                    "run_sequence", err)
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "run_sequence", err)

            LOGGER.info("Parsed response: %s" % response.to_dict())
Пример #6
0
    def run_sequence(self, sequence_info, session, conv, ots, trace, index):
        while index < len(sequence_info["sequence"]):
            logger.info("###{i}### {f} ###{i}###".format(
                f=session["testid"], i=index))
            session["index"] = index
            try:
                (req_c, resp_c), _kwa = sequence_info["sequence"][index]
            except (ValueError, TypeError):  # Not a tuple
                ret = self.none_request_response(sequence_info, index, session,
                                                 conv)
                self.dump_log(session)
                if isinstance(ret, basestring):
                    session["ckey"] = ret
                elif ret:
                    return ret
            else:
                if conv.protocol_response:
                    # If last response was an error response, bail out.
                    inst, txt = conv.protocol_response[-1]
                    try:
                        session["expect_error"]
                    except KeyError:
                        if isinstance(inst, ErrorResponse):
                            return self.err_response(session,"", inst)
                try:
                    kwargs = setup(_kwa, conv)
                except NotSupported:
                    self.store_test_info(session)
                    return self.opresult(conv, session)
                except Exception as err:
                    return self.err_response(session, "function()", err)

                try:
                    expect_error = _kwa["expect_error"]
                except KeyError:
                    expect_error = None
                else:
                    del _kwa["expect_error"]

                req = req_c(conv)
                try:
                    _pt = req.tests["pre"]
                except KeyError:
                    pass
                else:
                    if _pt:
                        try:
                            conv.test_output.append((req.request, "pre"))
                            conv.test_sequence(_pt)
                        except Exception as err:
                            return self.err_response(session, "pre-test", err)

                conv.request_spec = req

                conv.trace.info("------------ %s ------------" % req_c.request)
                if req_c == Discover:
                    # Special since it's just a GET on a URL
                    try:
                        _r = req.discover(
                            ots.client,
                            issuer=ots.config.CLIENT["srv_discovery_url"])
                    except ConnectionError:
                            self.log_fault(session, "Connection Error",
                                           "discover_request", ERROR)
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                    conv.position, conv.last_response, conv.last_content = _r

                    if conv.last_response.status >= 400:
                        return self.err_response(session, "discover",
                                                 conv.last_response.text)

                    for x in ots.client.keyjar[
                            ots.client.provider_info["issuer"]]:
                        try:
                            resp = ots.client.http_request(x.source)
                        except Exception as err:
                            return self.err_response(session, "jwks_fetch",
                                                     str(err))
                        else:
                            conv.last_response = resp
                            conv.last_content = resp.content
                            if resp.status_code < 300:
                                trace.info(
                                    "JWKS: %s" % pprint_json(resp.content))
                            else:
                                return self.err_response(session, "jwks_fetch",
                                                         resp.content)
                elif req_c == Webfinger:
                    try:
                        url = req.discover(**kwargs)
                    except ConnectionError:
                            self.log_fault(session, "Connection Error",
                                           "WebFinger_request", ERROR)
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                    if url:
                        conv.trace.request(url)
                        conv.test_output.append(
                            {"id": "-", "status": OK,
                             "message": "Found discovery URL: %s" % url})
                    else:
                        conv.test_output.append(
                            {"id": "-", "status": ERROR,
                             "message": "Failed to find discovery URL"})
                else:
                    try:
                        endp = req.endpoint
                    except AttributeError:
                        pass
                    else:
                        if not endpoint_support(conv.client, endp):
                            conv.test_output.append(
                                {"id": "-", "status": ERROR,
                                 "message": "%s not supported" % req.endpoint})
                            return self.opresult(conv, session)

                    logger.info("request: %s" % req.request)
                    if req.request == "AuthorizationRequest":
                        # New state for each request
                        kwargs["request_args"].update({"state": rndstr()})
                        if not ots.client.provider_info:
                            return self.err_response(session, req.request,
                                                     "No provider info")
                    elif req.request in ["AccessTokenRequest",
                                         "UserInfoRequest",
                                         "RefreshAccessTokenRequest"]:
                        kwargs.update(
                            {"state": conv.AuthorizationRequest["state"]})
                        if not ots.client.provider_info:
                            return self.err_response(session, req.request,
                                                     "No provider info")

                    req.rm_nonstandard_args(message_factory)

                    # Extra arguments outside the OIDC spec
                    try:
                        _extra = ots.config.CLIENT["extra"][req.request]
                    except KeyError:
                        pass
                    except Exception as err:
                        return self.err_response(session, "config_extra", err)
                    else:
                        try:
                            kwargs["request_args"].update(_extra)
                        except KeyError:
                            kwargs["request_args"] = _extra

                    req.call_setup()

                    try:
                        url, body, ht_args = req.construct_request(ots.client,
                                                                   **kwargs)
                    except PyoidcError as err:  # A OIDC specific error
                        return self.err_response(session, "construct_request",
                                                 err)

                    if req.request == "AuthorizationRequest":
                        session["response_type"] = kwargs["request_args"][
                            "response_type"]
                        logger.info("redirect.url: %s" % url)
                        logger.info("redirect.header: %s" % ht_args)
                        conv.timestamp.append((url, utc_time_sans_frac()))
                        resp = Redirect(str(url))
                        return resp(self.environ, self.start_response)
                    else:
                        _kwargs = {"http_args": ht_args}

                        if conv.AuthorizationRequest:
                            _kwargs["state"] = conv.AuthorizationRequest[
                                "state"]

                        try:
                            _method = kwargs["method"]
                        except KeyError:
                            _method = req.method
                        try:
                            _ctype = kwargs["ctype"]
                        except KeyError:
                            _ctype = resp_c.ctype

                        self.dump_log(session, session["testid"])

                        try:
                            response = request_and_return(
                                conv, url, trace, message_factory(
                                    resp_c.response), _method, body, _ctype,
                                **_kwargs)
                        except MissingErrorResponse:
                            self.log_fault(session, "Missing Error Response",
                                           "request_response",
                                           self.get_err_type(session))
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                        except PyoidcError as err:
                            return self.err_response(session,
                                                     "request_and_return", err)
                        except JWKESTException as err:
                            return self.err_response(session,
                                                     "request_and_return", err)
                        except ConnectionError:
                                self.log_fault(session, "Connection Error",
                                               "request",
                                               self.get_err_type(session))
                                conv.trace.info(END_TAG)
                                return self.fini(session, conv)

                        if response is None:  # bail out
                            self.log_fault(session, "Empty response",
                                           "request_response",
                                           self.get_err_type(session))
                            conv.trace.info(END_TAG)
                            return self.fini(session, conv)

                        trace.response(response)
                        logger.info(response.to_dict())

                        if expect_error:
                            session["expect_error"] = True
                            if isinstance(response, ErrorResponse):
                                if expect_error["stop"]:
                                    index = len(sequence_info["sequence"])
                                    session["index"] = index
                                    continue
                            else:
                                trace.error("Expected error, didn't get it")
                                return self.err_response(session,
                                                         "expected error", None)
                        else:
                            if resp_c.response == "RegistrationResponse":
                                if isinstance(response, RegistrationResponse):
                                    ots.client.store_registration_info(response)
                            elif resp_c.response == "AccessTokenResponse":
                                if "error" not in response:
                                    areq = conv.AuthorizationRequest.to_dict()
                                    try:
                                        del areq["acr_values"]
                                    except KeyError:
                                        pass

                try:
                    post_tests(conv, req_c, resp_c)
                except Exception as err:
                    return self.err_response(session, "post_test", err)

            index += 1
            _tid = session["testid"]
            self.dump_log(session, _tid)
            self.store_test_info(session)

        # wrap it up
        # Any after the fact tests ?
        try:
            if sequence_info["tests"]:
                conv.test_output.append(("After completing the test flow", ""))
                conv.test_sequence(sequence_info["tests"])
        except KeyError:
            pass
        except Exception as err:
            return self.err_response(session, "post_test", err)

        return self.fini(session, conv)
Пример #7
0
def application(environ, start_response):
    LOGGER.info("Connection from: %s" % environ["REMOTE_ADDR"])
    session = environ['beaker.session']

    path = environ.get('PATH_INFO', '').lstrip('/')
    LOGGER.info("path: %s" % path)

    oprp = OPRP(**RP_ARGS)
    oprp.environ = environ
    oprp.start_response = start_response

    if path == "robots.txt":
        return oprp.static("static/robots.txt")
    elif path == "favicon.ico":
        return oprp.static("static/favicon.ico")
    elif path.startswith("static/"):
        return oprp.static(path)
    elif path.startswith("export/"):
        return oprp.static(path)

    if path == "":  # list
        try:
            if oprp.session_init(session):
                return oprp.flow_list(session)
            else:
                try:
                    resp = Redirect("%sopresult#%s" %
                                    (oprp.conf.BASE, session["testid"][0]))
                except KeyError:
                    return oprp.flow_list(session)
                else:
                    return resp(environ, start_response)
        except Exception as err:
            return oprp.err_response(session, "session_setup", err)
    elif path == "logs":
        return oprp.display_log("log", issuer="", profile="", testid="")
    elif path.startswith("log"):
        if path == "log" or path == "log/":
            _cc = oprp.conf.CLIENT
            try:
                _iss = _cc["srv_discovery_url"]
            except KeyError:
                _iss = _cc["provider_info"]["issuer"]
            parts = [quote_plus(_iss)]
        else:
            parts = []
            while path != "log":
                head, tail = os.path.split(path)
                # tail = tail.replace(":", "%3A")
                # if tail.endswith("%2F"):
                #     tail = tail[:-3]
                parts.insert(0, tail)
                path = head

        return oprp.display_log("log", *parts)
    elif path.startswith("tar"):
        path = path.replace(":", "%3A")
        return oprp.static(path)
    elif "flow_names" not in session:
        oprp.session_init(session)

    if path == "reset":
        oprp.reset_session(session)
        return oprp.flow_list(session)
    elif path == "pedit":
        try:
            return oprp.profile_edit(session)
        except Exception as err:
            return oprp.err_response(session, "pedit", err)
    elif path == "profile":
        info = parse_qs(get_post(environ))
        try:
            cp = session["profile"].split(".")
            cp[0] = info["rtype"][0]

            crsu = []
            for name, cs in list(CRYPTSUPPORT.items()):
                try:
                    if info[name] == ["on"]:
                        crsu.append(cs)
                except KeyError:
                    pass

            if len(cp) == 3:
                if len(crsu) == 3:
                    pass
                else:
                    cp.append("".join(crsu))
            else:  # len >= 4
                cp[3] = "".join(crsu)

            try:
                if info["extra"] == ['on']:
                    if len(cp) == 3:
                        cp.extend(["", "+"])
                    elif len(cp) == 4:
                        cp.append("+")
                    elif len(cp) == 5:
                        cp[4] = "+"
                else:
                    if len(cp) == 5:
                        cp = cp[:-1]
            except KeyError:
                if len(cp) == 5:
                    cp = cp[:-1]

            # reset all test flows
            RP_ARGS["test_profile"] = ".".join(cp)
            oprp.reset_session(session, ".".join(cp))
            return oprp.flow_list(session)
        except Exception as err:
            return oprp.err_response(session, "profile", err)
    elif path.startswith("test_info"):
        p = path.split("/")
        try:
            return oprp.test_info(p[1], session)
        except KeyError:
            return oprp.not_found()
    elif path == "continue":
        try:
            sequence_info = session["seq_info"]
        except KeyError:  # Cookie delete broke session
            query = parse_qs(environ["QUERY_STRING"])
            path = query["path"][0]
            index = int(query["index"][0])
            conv, sequence_info, ots, trace, index = oprp.session_setup(
                session, path, index)

            try:
                conv = RP_ARGS["cache"][query["ckey"][0]]
            except KeyError:
                pass
            else:
                ots.client = conv.client
                session["conv"] = conv
        except Exception as err:
            return oprp.err_response(session, "session_setup", err)
        else:
            index = session["index"]
            ots = session["ots"]
            conv = session["conv"]

        index += 1
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots,
                                     conv.trace, index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    elif path == "opresult":

        try:
            conv = session["conv"]
        except KeyError as err:
            homepage = ""
            return oprp.sorry_response(homepage, err)

        return oprp.opresult(conv, session)
    # expected path format: /<testid>[/<endpoint>]
    elif path in session["flow_names"]:
        LOGGER.info("<=<=<=<=< %s >=>=>=>=>" % path)
        conv, sequence_info, ots, trace, index = oprp.session_setup(
            session, path)
        session["node"].complete = False
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots, trace,
                                     index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    elif path in ["authz_cb", "authz_post"]:
        try:
            sequence_info = session["seq_info"]
            index = session["index"]
            ots = session["ots"]
            conv = session["conv"]
        except KeyError as err:
            # Todo: find out which port I'm listening on
            return oprp.sorry_response(oprp.conf.BASE, err)
        (req_c, resp_c), _ = sequence_info["sequence"][index]
        try:
            response_mode = conv.AuthorizationRequest["response_mode"]
        except KeyError:
            response_mode = None

        if path == "authz_cb":
            if response_mode == "form_post":
                pass
            elif session["response_type"] and not \
                    session["response_type"] == ["code"]:
                # but what if it's all returned as a query ?
                try:
                    qs = environ["QUERY_STRING"]
                except KeyError:
                    pass
                else:
                    session["conv"].trace.response("QUERY_STRING:%s" % qs)
                    session["conv"].query_component = qs

                return oprp.opresult_fragment()

        if resp_c:  # None in cases where no OIDC response is expected
            _ctype = resp_c.ctype

            # parse the response
            if response_mode == "form_post":
                info = parse_qs(get_post(environ))
                _ctype = "dict"
            elif path == "authz_post":
                query = parse_qs(get_post(environ))
                try:
                    info = query["fragment"][0]
                except KeyError:
                    return oprp.sorry_response(oprp.conf.BASE,
                                               "missing fragment ?!")
                _ctype = "urlencoded"
            elif resp_c.where == "url":
                info = environ["QUERY_STRING"]
                _ctype = "urlencoded"
            else:  # resp_c.where == "body"
                info = get_post(environ)

            LOGGER.info("Response: %s" % info)
            conv.trace.reply(info)
            resp_cls = message_factory(resp_c.response)

            kwargs = {
                "algs": ots.client.sign_enc_algs("id_token"),
                "keyjar": ots.client.keyjar
            }
            if "issuer_mismatch" in ots.client.allow:
                kwargs["sender"] = ots.client.provider_info["issuer"]

            try:
                response = ots.client.parse_response(
                    resp_cls, info, _ctype, conv.AuthorizationRequest["state"],
                    **kwargs)
            except ResponseError as err:
                return oprp.err_response(session, "run_sequence", err)
            except Exception as err:
                return oprp.err_response(session, "run_sequence", err)

            LOGGER.info("Parsed response: %s" % response.to_dict())
            conv.protocol_response.append((response, info))
            conv.trace.response(response)

        try:
            post_tests(conv, req_c, resp_c)
        except Exception as err:
            return oprp.err_response(session, "post_test", err)

        index += 1
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots,
                                     conv.trace, index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    else:
        resp = BadRequest()
        return resp(environ, start_response)
Пример #8
0
def application(environ, start_response):
    LOGGER.info("Connection from: %s" % environ["REMOTE_ADDR"])
    session = environ['beaker.session']

    path = environ.get('PATH_INFO', '').lstrip('/')
    LOGGER.info("path: %s" % path)

    oprp = OPRP(**RP_ARGS)
    oprp.environ = environ
    oprp.start_response = start_response

    if path == "robots.txt":
        return oprp.static("static/robots.txt")
    elif path == "favicon.ico":
        return oprp.static("static/favicon.ico")
    elif path.startswith("static/"):
        return oprp.static(path)
    elif path.startswith("export/"):
        return oprp.static(path)

    if path == "":  # list
        try:
            if oprp.session_init(session):
                return oprp.flow_list(session)
            else:
                try:
                    resp = Redirect("%sopresult#%s" % (
                        oprp.conf.BASE, session["testid"][0]))
                except KeyError:
                    return oprp.flow_list(session)
                else:
                    return resp(environ, start_response)
        except Exception as err:
            return oprp.err_response(session, "session_setup", err)
    elif path == "logs":
        return oprp.display_log("log", issuer="", profile="", testid="")
    elif path.startswith("log"):
        if path == "log" or path == "log/":
            _cc = oprp.conf.CLIENT
            try:
                _iss = _cc["srv_discovery_url"]
            except KeyError:
                _iss = _cc["provider_info"]["issuer"]
            parts = [quote_plus(_iss)]
        else:
            parts = []
            while path != "log":
                head, tail = os.path.split(path)
                # tail = tail.replace(":", "%3A")
                # if tail.endswith("%2F"):
                #     tail = tail[:-3]
                parts.insert(0, tail)
                path = head

        return oprp.display_log("log", *parts)
    elif path.startswith("tar"):
        path = path.replace(":", "%3A")
        return oprp.static(path)
    elif "flow_names" not in session:
        oprp.session_init(session)

    if path == "reset":
        oprp.reset_session(session)
        return oprp.flow_list(session)
    elif path == "pedit":
        try:
            return oprp.profile_edit(session)
        except Exception as err:
            return oprp.err_response(session, "pedit", err)
    elif path == "profile":
        info = parse_qs(get_post(environ))
        try:
            cp = session["profile"].split(".")
            cp[0] = info["rtype"][0]

            crsu = []
            for name, cs in list(CRYPTSUPPORT.items()):
                try:
                    if info[name] == ["on"]:
                        crsu.append(cs)
                except KeyError:
                    pass

            if len(cp) == 3:
                if len(crsu) == 3:
                    pass
                else:
                    cp.append("".join(crsu))
            else:  # len >= 4
                cp[3] = "".join(crsu)

            try:
                if info["extra"] == ['on']:
                    if len(cp) == 3:
                        cp.extend(["", "+"])
                    elif len(cp) == 4:
                        cp.append("+")
                    elif len(cp) == 5:
                        cp[4] = "+"
                else:
                    if len(cp) == 5:
                        cp = cp[:-1]
            except KeyError:
                if len(cp) == 5:
                    cp = cp[:-1]

            # reset all test flows
            oprp.reset_session(session, ".".join(cp))
            return oprp.flow_list(session)
        except Exception as err:
            return oprp.err_response(session, "profile", err)
    elif path.startswith("test_info"):
        p = path.split("/")
        try:
            return oprp.test_info(p[1], session)
        except KeyError:
            return oprp.not_found()
    elif path == "continue":
        try:
            sequence_info = session["seq_info"]
        except KeyError:  # Cookie delete broke session
            query = parse_qs(environ["QUERY_STRING"])
            path = query["path"][0]
            index = int(query["index"][0])
            conv, sequence_info, ots, trace, index = oprp.session_setup(
                session, path, index)

            try:
                conv = RP_ARGS["cache"][query["ckey"][0]]
            except KeyError:
                pass
            else:
                ots.client = conv.client
                session["conv"] = conv
        except Exception as err:
            return oprp.err_response(session, "session_setup", err)
        else:
            index = session["index"]
            ots = session["ots"]
            conv = session["conv"]

        index += 1
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots,
                                     conv.trace, index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    elif path == "opresult":

        try:
            conv = session["conv"]
        except KeyError as err:
            homepage = ""
            return oprp.sorry_response(homepage, err)

        return oprp.opresult(conv, session)
    # expected path format: /<testid>[/<endpoint>]
    elif path in session["flow_names"]:
        LOGGER.info("<=<=<=<=< %s >=>=>=>=>" % path)
        conv, sequence_info, ots, trace, index = oprp.session_setup(session,
                                                                    path)
        session["node"].complete = False
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots,
                                     trace, index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    elif path in ["authz_cb", "authz_post"]:
        try:
            sequence_info = session["seq_info"]
            index = session["index"]
            ots = session["ots"]
            conv = session["conv"]
        except KeyError as err:
            # Todo: find out which port I'm listening on
            return oprp.sorry_response(oprp.conf.BASE, err)
        (req_c, resp_c), _ = sequence_info["sequence"][index]
        try:
            response_mode = conv.AuthorizationRequest["response_mode"]
        except KeyError:
            response_mode = None

        if path == "authz_cb":
            if response_mode == "form_post":
                pass
            elif session["response_type"] and not \
                    session["response_type"] == ["code"]:
                # but what if it's all returned as a query ?
                try:
                    qs = environ["QUERY_STRING"]
                except KeyError:
                    pass
                else:
                    session["conv"].trace.response("QUERY_STRING:%s" % qs)
                    session["conv"].query_component = qs

                return oprp.opresult_fragment()

        if resp_c:  # None in cases where no OIDC response is expected
            _ctype = resp_c.ctype

            # parse the response
            if response_mode == "form_post":
                info = parse_qs(get_post(environ))
                _ctype = "dict"
            elif path == "authz_post":
                query = parse_qs(get_post(environ))
                try:
                    info = query["fragment"][0]
                except KeyError:
                    return oprp.sorry_response(oprp.conf.BASE,
                                               "missing fragment ?!")
                _ctype = "urlencoded"
            elif resp_c.where == "url":
                info = environ["QUERY_STRING"]
                _ctype = "urlencoded"
            else:  # resp_c.where == "body"
                info = get_post(environ)

            LOGGER.info("Response: %s" % info)
            conv.trace.reply(info)
            resp_cls = message_factory(resp_c.response)
            algs = ots.client.sign_enc_algs("id_token")
            try:
                response = ots.client.parse_response(
                    resp_cls, info, _ctype,
                    conv.AuthorizationRequest["state"],
                    keyjar=ots.client.keyjar, algs=algs)
            except ResponseError as err:
                return oprp.err_response(session, "run_sequence", err)
            except Exception as err:
                return oprp.err_response(session, "run_sequence", err)

            LOGGER.info("Parsed response: %s" % response.to_dict())
            conv.protocol_response.append((response, info))
            conv.trace.response(response)

        try:
            post_tests(conv, req_c, resp_c)
        except Exception as err:
            return oprp.err_response(session, "post_test", err)

        index += 1
        try:
            return oprp.run_sequence(sequence_info, session, conv, ots,
                                     conv.trace, index)
        except Exception as err:
            return oprp.err_response(session, "run_sequence", err)
    else:
        resp = BadRequest()
        return resp(environ, start_response)
Пример #9
0
def run_sequence(sequence_info, session, conv, ots, environ, start_response,
                 trace, index):
    while index < len(sequence_info["sequence"]):
        session["index"] = index
        try:
            req_c, resp_c = sequence_info["sequence"][index]
        except (ValueError, TypeError):  # Not a tuple
            ret = none_request_response(sequence_info, index, session, conv,
                                        environ, start_response)
            if ret:
                return ret
        else:
            req = req_c(conv)
            try:
                if req.tests["pre"]:
                    conv.test_output.append((req.request, "pre"))
                    conv.test_sequence(req.tests["pre"])
            except KeyError:
                pass
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "pre-test", err)

            conv.request_spec = req

            if req_c == TEST_FLOWS.Discover:
                # Special since it's just a GET on a URL
                _r = req.discover(
                    ots.client, issuer=ots.config.CLIENT["srv_discovery_url"])
                conv.position, conv.last_response, conv.last_content = _r
                logging.debug("Provider info: %s" % conv.last_content._dict)
                verify_support(conv, ots, session["graph"])
            else:
                LOGGER.info("request: %s" % req.request)
                if req.request == "AuthorizationRequest":
                    # New state for each request
                    kwargs = {"request_args": {"state": rndstr()}}
                elif req.request in ["AccessTokenRequest", "UserInfoRequest",
                                     "RefreshAccessTokenRequest"]:
                    kwargs = {"state": conv.AuthorizationRequest["state"]}
                else:
                    kwargs = {}

                # Extra arguments outside the OIDC spec
                try:
                    _extra = ots.config.CLIENT["extra"][req.request]
                except KeyError:
                    pass
                except Exception as err:
                    return err_response(environ, start_response, session,
                                        "config_exta", err)
                else:
                    try:
                        kwargs["request_args"].update(_extra)
                    except KeyError:
                        kwargs["request_args"] = _extra

                req.call_setup()
                try:
                    url, body, ht_args = req.construct_request(ots.client,
                                                               **kwargs)
                except PyoidcError as err:  # A OIDC specific error
                    return err_response(environ, start_response, session,
                                        "construct_request", err)

                if req.request == "AuthorizationRequest":
                    session["response_type"] = req.request_args["response_type"]
                    LOGGER.info("redirect.url: %s" % url)
                    LOGGER.info("redirect.header: %s" % ht_args)
                    resp = Redirect(str(url))
                    return resp(environ, start_response)
                else:
                    _kwargs = {"http_args": ht_args}
                    try:
                        _kwargs["state"] = conv.AuthorizationRequest["state"]
                    except AttributeError:
                        pass

                    try:
                        response = request_and_return(
                            conv, url, message_factory(resp_c.response),
                            req.method, body, resp_c.ctype, **_kwargs)
                    except PyoidcError as err:
                        return err_response(environ, start_response, session,
                                            "request_and_return", err)

                    trace.info(response.to_dict())
                    LOGGER.info(response.to_dict())
                    if resp_c.response == "RegistrationResponse" and \
                            isinstance(response, RegistrationResponse):
                        ots.client.store_registration_info(response)
                    else:  # must be an ErrorResponse
                        conv.test_output.append(
                            {'status': 4, "id": "*",
                             'message':
                                 'Error response: %s' % (response.to_dict(),)})
                        return opresult(environ, start_response, conv, session)

            try:
                post_tests(conv, req_c, resp_c)
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "post_test", err)

        index += 1
        _tid = session["testid"]
        session["test_info"][_tid] = {"trace": conv.trace,
                                      "test_output": conv.test_output}

    # wrap it up
    # Any after the fact tests ?
    try:
        if sequence_info["tests"]:
            conv.test_output.append(("After completing the test", ""))
            conv.test_sequence(sequence_info["tests"])
    except KeyError:
        pass
    except Exception as err:
        return err_response(environ, start_response, session, "post_test", err)

    _tid = session["testid"]
    session["test_info"][_tid] = {"trace": conv.trace,
                                  "test_output": conv.test_output}
    session["node"].complete = True

    resp = Redirect("%sopresult#%s" % (CONF.BASE, _tid[3]))
    return resp(environ, start_response)
Пример #10
0
        if resp_c:  # None in cases where no OIDC response is expected
            _ctype = resp_c.ctype
            # parse the response
            if path == "authz_post":
                query = parse_qs(get_post(environ))
                info = query["fragment"][0]
                _ctype = "urlencoded"
            elif resp_c.where == "url":
                info = environ["QUERY_STRING"]
                _ctype = "urlencoded"
            else:  # resp_c.where == "body"
                info = get_post(environ)

            LOGGER.info("Response: %s" % info)
            resp_cls = message_factory(resp_c.response)
            try:
                response = ots.client.parse_response(
                    resp_cls, info, _ctype,
                    conv.AuthorizationRequest["state"],
                    keyjar=ots.client.keyjar)
            except ResponseError as err:
                return err_response(environ, start_response, session,
                                    "run_sequence", err)
            except Exception as err:
                return err_response(environ, start_response, session,
                                    "run_sequence", err)

            LOGGER.info("Parsed response: %s" % response.to_dict())
            conv.protocol_response.append((response, info))