Example #1
0
 def err_check(self, test, err=None, bryt=True):
     if err:
         self.exception = err
     chk = self.check_factory(test)()
     chk(self, self.test_output)
     if bryt:
         e = FatalError("%s" % err)
         e.trace = "".join(traceback.format_exception(*sys.exc_info()))
         raise e
Example #2
0
 def err_check(self, test, err=None, bryt=True):
     if err:
         self.exception = err
     chk = self.check_factory(test)()
     chk(self, self.test_output)
     if bryt:
         e = FatalError("%s" % err)
         e.trace = "".join(traceback.format_exception(*sys.exc_info()))
         raise e
Example #3
0
    def intermit(self, response):
        if response.status_code >= 400:
            done = True
        else:
            done = False

        rdseq = []
        while not done:
            url = response.url

            while response.status_code in [302, 301, 303]:
                url = response.headers["location"]
                if url in rdseq:
                    raise FatalError("Loop detected in redirects")
                else:
                    rdseq.append(url)
                    if len(rdseq) > 8:
                        raise FatalError("Too long sequence of redirects: %s" %
                                         rdseq)

                self.trace.reply("REDIRECT TO: %s" % url)

                # If back to me
                if self.for_me(url):
                    done = True
                    self.response.append(response)
                    break
                else:
                    try:
                        response = self.client.send(
                            url, "GET", headers={"Referer": self.last_url})
                    except Exception, err:
                        raise FatalError("%s" % err)

                    content = response.text
                    self.trace.reply("CONTENT: %s" % content)
                    self.response.append(response)

                    if response.status_code >= 400:
                        done = True
                        break

            if done or url is None:
                break

            if response.status_code < 300 or response.status_code >= 400:
                break
Example #4
0
    def check_severity(self, stat):
        if stat["status"] >= 4:
            self.trace.error("WHERE: %s" % stat["id"])
            self.trace.error("STATUS:%s" % STATUSCODE[stat["status"]])
            try:
                self.trace.error("HTTP STATUS: %s" % stat["http_status"])
            except KeyError:
                pass
            try:
                self.trace.error("INFO: %s" % (stat["message"], ))
            except KeyError:
                pass

            if not stat["mti"]:
                raise Break(stat["message"])
            else:
                raise FatalError(stat["message"])
Example #5
0
    def handle_result(self):
        try:
            self.response_spec = resp = self.cresp()
        except TypeError:
            self.response_spec = None
            return True

        self.info = None
        self.response_message = None

        response = self.last_response
        resp_type = resp.ctype
        if response:
            try:
                ctype = response.headers["content-type"]
                if ctype == "application/jwt":
                    resp_type = "jwt"
            except (AttributeError, TypeError):
                pass

        if response.status_code >= 400:
            pass
        elif not self.position:
            if isinstance(self.last_content, Message):
                self.response_message = self.last_content
            elif response.status_code == 200:
                self.info = self.last_content
        elif resp.where == "url" or response.status_code == 302:
            try:
                self.info = response.headers["location"]
                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")
            self.info = self.last_content

        if self.info and resp.response:
            if isinstance(resp.response, basestring):
                response = self.msg_factory(resp.response)
            else:
                response = resp.response

            self.response_type = response.__name__
            try:
                _cli = self.client
                _qresp = self.client.parse_response(
                    response,
                    self.info,
                    resp_type,
                    _cli.state,
                    keyjar=_cli.keyjar,
                    client_id=_cli.client_id,
                    scope="openid",
                    opponent_id=_cli.provider_info.keys()[0])
                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

            if err:
                if self.accept_exception:
                    if isinstance(err, self.accept_exception):
                        self.trace.info("Got expected exception: %s [%s]" %
                                        (err, err.__class__.__name__))
                    else:
                        raise
                else:
                    raise FatalError(_errtxt)
            elif self.response_message:
                self.do_check("response-parse")
Example #6
0
    def intermit(self):
        _response = self.last_response
        if _response.status_code >= 400:
            done = True
        else:
            done = False

        rdseq = []
        while not done:
            url = _response.url
            content = _response.text

            while _response.status_code in [302, 301, 303]:
                url = _response.headers["location"]
                if url in rdseq:
                    raise FatalError("Loop detected in redirects")
                else:
                    rdseq.append(url)
                    if len(rdseq) > 8:
                        raise FatalError("Too long sequence of redirects: %s" %
                                         rdseq)

                self.trace.reply("REDIRECT TO: %s" % url)

                # If back to me
                if self.for_me(_response):
                    self.client.cookiejar = self.cjar["rp"]
                    done = True
                    break
                else:
                    try:
                        _response = self.client.send(url, "GET")
                    except Exception, err:
                        raise FatalError("%s" % err)

                    content = _response.text
                    self.trace.reply("CONTENT: %s" % content)
                    self.position = url
                    self.last_content = content
                    self.response = _response

                    if _response.status_code >= 400:
                        done = True
                        break

            if done or url is None:
                break

            _base = url.split("?")[0]

            try:
                _spec = self.interaction[self.role].pick_interaction(
                    _base, content)
                #if _spec in self.interact_done:
                #    self.trace.error("Same interaction a second time")
                #    raise InteractionNeeded("Same interaction twice")
                #self.interact_done.append(_spec)
            except InteractionNeeded:
                self.position = url
                self.trace.error("Page Content: %s" % content)
                raise
            except KeyError:
                self.position = url
                self.trace.error("Page Content: %s" % content)
                self.err_check("interaction-needed")

            if len(_spec) > 2:
                self.trace.info(">> %s <<" % _spec["page-type"])
                if _spec["page-type"] == "login":
                    self.login_page = content

            _op = Action(_spec["control"])

            try:
                _response = _op(self.client, self, self.trace, url, _response,
                                content, self.features)
                if isinstance(_response, dict):
                    self.last_response = _response
                    self.last_content = _response
                    return _response
                content = _response.text
                self.position = url
                self.last_content = content
                self.response = _response

                if _response.status_code >= 400:
                    break
            except (FatalError, InteractionNeeded):
                raise
            except Exception, err:
                self.err_check("exception", err, False)
Example #7
0
class Response(Conversation):
    def __init__(self,
                 phase,
                 client,
                 config,
                 trace,
                 session,
                 verbose=False,
                 keyjar=None,
                 accept_exception=False,
                 last_response=None,
                 last_content=""):
        Conversation.__init__(self, client, config, trace)
        self.session = session
        self.creq, self.cresp = phase
        self.test_output = []
        self.protocol_response = []
        self.verbose = verbose
        self.keyjar = keyjar
        self.accept_exception = accept_exception

        self.last_response = last_response
        self.last_content = last_content
        self.position = 0
        self.response_type = ""

    def post_process(self, resp):
        _msg = self.response_message
        if _msg:
            try:
                self.test_sequence(resp.tests["post"])
            except KeyError:
                pass

            if isinstance(_msg, RegistrationResponse):
                self.client.registration_response = _msg
                for key in [
                        "client_id", "client_secret",
                        "registration_access_token", "registration_client_uri"
                ]:
                    try:
                        setattr(self.client, key, _msg[key])
                    except KeyError:
                        pass
            elif isinstance(_msg, ProviderConfigurationResponse):
                _issuer = self.session["srv_discovery_url"]
                _op_conf = self.session["op_conf"]
                if _op_conf:
                    for key, val in _op_conf["provider"].items():
                        if key == "dynamic":
                            continue
                        else:
                            _msg[key] = val
                self.client.handle_provider_config(_msg, _issuer)
                self.client.provider_info = _msg

            resp(self, self.response_message)

            return True
        else:
            return False

    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

        if err:
            if self.accept_exception:
                if isinstance(err, self.accept_exception):
                    self.trace.info("Got expected exception: %s [%s]" %
                                    (err, err.__class__.__name__))
                else:
                    raise
            else:
                raise FatalError(_errtxt)
        elif self.response_message:
            self.do_check("response-parse")

        return self.post_process(resp)
Example #8
0
class Conversation(tool.Conversation):
    def __init__(self,
                 client,
                 config,
                 trace,
                 interaction,
                 msg_factory,
                 check_factory,
                 features=None,
                 verbose=False,
                 expect_exception=False,
                 **extra_args):
        tool.Conversation.__init__(self, client, config, trace, interaction,
                                   check_factory, msg_factory, features,
                                   verbose, expect_exception, **extra_args)
        self.cis = []
        # self.item = []
        self.keyjar = self.client.keyjar
        self.position = ""
        self.last_response = None
        self.last_content = None
        self.accept_exception = False
        self.creq = None
        self.cresp = None
        self.msg_factory = msg_factory
        self.login_page = None
        self.response_message = None
        self.info = None
        self.AuthorizationRequest = None
        self.etag = {}
        self.timestamp = []

    def my_endpoints(self):
        return self.client.redirect_uris

    def handle_result(self):
        try:
            self.response_spec = resp = self.cresp()
        except TypeError:
            self.response_spec = None
            return True

        self.info = None
        self.response_message = None

        response = self.last_response
        resp_type = resp.ctype

        err = None
        _errtxt = ""
        if isinstance(response, dict):
            _cli = self.client
            _resp = self.msg_factory(resp.response)
            _qresp = self.client.parse_response(
                _resp,
                response,
                "dict",
                self.state,
                keyjar=self.keyjar,
                client_id=_cli.client_id,
                scope="openid",
                opponent_id=_cli.provider_info["issuer"])
            self.response_message = _qresp
            self.protocol_response.append((_qresp, self.info))
        else:
            try:
                ctype = response.headers["content-type"]
                if "application/jwt" in ctype:
                    resp_type = "jwt"
            except (AttributeError, TypeError, KeyError):
                pass

            if response.status_code >= 400:
                pass
            elif not self.position:
                if isinstance(self.last_content, Message):
                    self.response_message = self.last_content
                elif response.status_code == 200:
                    self.info = self.last_content
            elif resp.where == "url" or response.status_code == 302:
                try:
                    self.info = response.headers["location"]
                    resp_type = "urlencoded"
                except KeyError:
                    try:
                        _check = getattr(self.creq, "interaction_check", None)
                    except AttributeError:
                        _check = None

                    if _check:
                        return False
                    else:
                        self.do_check("missing-redirect")
            else:
                self.do_check("check_content_type_header")
                self.info = self.last_content

            if self.info and resp.response:
                if isinstance(resp.response, basestring):
                    response = self.msg_factory(resp.response)
                else:
                    response = resp.response

                self.response_type = response.__name__
                try:
                    _cli = self.client
                    _qresp = self.client.parse_response(
                        response,
                        self.info,
                        resp_type,
                        self.state,
                        keyjar=self.keyjar,
                        client_id=_cli.client_id,
                        scope="openid",
                        opponent_id=_cli.provider_info["issuer"])
                    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
                    self.test_output.append({
                        "status": 4,
                        "id": "OIDC error",
                        "message": "%s" % err
                    })
                    raise FatalError

        if err:
            if self.accept_exception:
                if isinstance(err, self.accept_exception):
                    self.trace.info("Got expected exception: %s [%s]" %
                                    (err, err.__class__.__name__))
                else:
                    raise
            else:
                raise FatalError(_errtxt)
        elif self.response_message:
            self.do_check("response-parse")

        return self.post_process(resp)