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
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
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"])
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")
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)
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)
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)