示例#1
0
def check_config(oper, args):
    """
    Context: VerifyConfiguration
    Action:
    Example:
        "check_config": {
          "login_hint": null
        }

    :param args: Dictionary with parameters and values that MUST be in the
    tool configuration
    """

    _cnf = oper.conv.tool_config
    for key, val in args.items():
        if key in _cnf:
            if val and val != _cnf[key]:
                _msg = "{}={} not OK, should have been {}".format(
                    key, val, _cnf[key])
                oper.conv.events.store(
                    EV_CONDITION,
                    State("Check support", status=ERROR, message=_msg))
                oper.unsupported = _msg
        else:
            _msg = "No {} in the configuration".format(key)
            oper.conv.events.store(
                EV_CONDITION, State("Check support",
                                    status=ERROR,
                                    message=_msg))

            oper.unsupported = _msg
示例#2
0
def webfinger(environ, events):
    query = parse_qs(environ["QUERY_STRING"])
    _op = environ["oic.op"]

    try:
        if query["rel"] != [OIC_ISSUER]:
            events.store(
                EV_CONDITION,
                State('webfinger_parameters',
                      ERROR,
                      message='parameter rel wrong value: {}'.format(
                          query['rel'])))
            return BadRequest('Parameter value error')
        else:
            resource = query["resource"][0]
    except KeyError as err:
        events.store(
            EV_CONDITION,
            State('webfinger_parameters',
                  ERROR,
                  message='parameter {} missing'.format(err)))
        resp = BadRequest("Missing parameter in request")
    else:
        wf = WebFinger()
        resp = Response(wf.response(subject=resource, base=_op.baseurl))
    return resp
示例#3
0
    def session_change(self, **kwargs):
        try:
            _state = kwargs['state']
        except KeyError:
            pass
        else:
            logger.debug('Session state: {}'.format(kwargs))
            self.tester.conv.events.store(
                'SessionState',
                'Session check returned: {}'.format(_state))

            if _state == 'changed':
                self.tester.conv.events.store(EV_CONDITION,
                                              State('Done', status=OK))
                self.tester.store_result()
                self.opresult()
            else:  # display after_logout.html again
                self.session_checks['changed'] += 1
                logger.debug('{} session check'.format(self.session_checks[
                                                           'changed']))
                self.tester.conv.events.store(
                    'SessionState',
                    'Session check {} returned: {}'.format(
                        self.session_checks['unchanged'], _state))

                if self.session_checks['changed'] >= self.max_checks:
                    self.tester.conv.events.store(EV_FAULT,
                                                  'Session state not changed')
                    return self.main_page()
                else:
                    _msg = self.tester.inut.pre_html['after_logout.html']
                    _csi = self.tester.conv.entity.provider_info[
                        'check_session_iframe']
                    _mod_msg = _msg.replace("{check_session_iframe}", _csi)
                    return as_bytes(_mod_msg)
示例#4
0
    def log_fault(self, session, err, where, err_type=0):
        if err_type == 0:
            err_type = self.get_err_type(session)

        if "conv" in session:
            if err:
                session["conv"].events.store(EV_CONDITION,
                                             State("Fault", status=ERROR,
                                                   name=err_type,
                                                   message="{}".format(err)))
            else:
                session["conv"].events.store(
                    EV_CONDITION, State(
                        "Fault", status=ERROR,
                        name=err_type,
                        message="Error in %s" % where))
示例#5
0
def check_support(oper, args):
    """
    Context:
        AsyncAuthn
    Action:
        Verify that the needed support is supported by the OP
    Args:
        A dictionary of dictionaries. {level: {item: value}}
    Example:
        "check_support": {
          WARNING: {"scopes_supported": ["phone"]}
        }

        "check_support": {
          ERROR: {"id_token_signing_alg_values_supported": null}
        }

    """
    # args = { level : kwargs }
    for level, kwargs in list(args.items()):
        for key, val in list(kwargs.items()):
            # type of value: boolean, int, string, list, ...
            typ = oper.conv.entity.provider_info.__class__.c_param[key][0]
            try:
                pinfo = oper.conv.entity.provider_info[key]
            except KeyError:
                pass
            else:
                missing = []
                if isinstance(val, list):
                    for v in val:
                        if isinstance(typ, list) and issubclass(
                                typ[0], (six.string_types, basestring)):
                            if v not in pinfo:
                                missing.append(v)
                        elif issubclass(
                                typ,
                            (bool, int, six.string_types, basestring)):
                            if v != pinfo:
                                missing.append(v)
                else:
                    if isinstance(typ, list) and issubclass(
                            typ[0], (six.string_types, basestring)):
                        if val not in pinfo:
                            missing = val
                    elif issubclass(typ,
                                    (bool, int, six.string_types, basestring)):
                        if val != pinfo:
                            missing = val

                if missing:
                    oper.conv.events.store(
                        EV_CONDITION,
                        State(status=STATUSCODE_TRANSL[level],
                              test_id="Check support",
                              message="No support for: {}={}".format(
                                  key, missing)))
                    if level == 'ERROR':
                        oper.fail = True
示例#6
0
def check_endpoint(oper, args):
    try:
        _ = oper.conv.entity.provider_info[args]
    except KeyError:
        oper.conv.events.store(
            EV_CONDITION,
            State(test_id="check_endpoint", status=ERROR,
                  message="{} not in provider configuration".format(args)))
        oper.skip = True
示例#7
0
    def do_next(self, req, filename, path='', **kwargs):
        sh = self.sh

        self.conv = sh['conv']
        cls, funcs = self.get_cls_and_func(self.conv.index + 1)
        if cls.endpoint != path:
            if path == 'authorization':  # Jumping the gun here
                areq = AuthorizationRequest().from_urlencoded(req)
                # send an error back to the redirect_uri
                msg = AuthorizationErrorResponse(error='access_denied',
                                                 state=areq['state'])
                _entity = self.conv.entity
                redirect_uri = _entity.get_redirect_uri(areq)
                _req_loc = msg.request(redirect_uri)
                resp = _entity.server.http_request(_req_loc, 'GET')
                ret = Response('Client need to reregister')
                return ret

        self.handle_request(req, path=path)
        self.store_result()

        self.conv.index += 1

        try:
            resp = self.run_item(self.conv.test_id,
                                 index=self.conv.index,
                                 **kwargs)
        except Exception as err:
            raise

        if isinstance(resp, Response):
            self.store_result()
            return resp

        _done = False
        for _cond in self.conv.events.get_data(EV_CONDITION):
            if _cond.test_id == 'Done' and _cond.status == OK:
                _done = True
                break

        if not _done:
            self.conv.events.store(EV_CONDITION,
                                   State('Done', OK),
                                   sender='do_next')

            if 'assert' in self.conv.flow:
                _ver = Verify(self.chk_factory, self.conv)
                _ver.test_sequence(self.conv.flow["assert"])

            self.store_result()

        return self.inut.flow_list()
示例#8
0
    def post_op(self, oper, res, test_id):
        """
        should be done as late as possible, so all processing has been
        :param oper:
        :return:
        """
        try:
            oper.post_tests()
        except ConditionError:
            pass

        self.conv.events.store(EV_CONDITION, State('Done', OK))
        self.store_result(res)
示例#9
0
def check_support(oper, args):
    # args = { level : kwargs }
    for level, kwargs in list(args.items()):
        for key, val in list(kwargs.items()):
            typ = oper.conv.entity.provider_info.__class__.c_param[key][0]
            try:
                pinfo = oper.conv.entity.provider_info[key]
            except KeyError:
                pass
            else:
                missing = []
                if isinstance(val, list):
                    for v in val:
                        if typ == bool or typ == basestring or typ == int:
                            if v != pinfo:
                                missing.append(v)
                        elif typ == [basestring]:
                            if v not in pinfo:
                                missing.append(v)
                else:
                    if typ == bool or typ == basestring or typ == int:
                        if val != pinfo:
                            missing = val
                    elif typ == [basestring]:
                        if val not in pinfo:
                            missing = val

                if missing:
                    oper.conv.events.store(
                        EV_CONDITION,
                        State(status=STATUSCODE_TRANSL[level],
                              test_id="Check support",
                              message="No support for: {}={}".format(key,
                                                                     missing)))
                    if level == 'ERROR':
                        oper.fail = True
示例#10
0
    def run_flow(self, test_id, index=0, profiles=None, **kwargs):
        logger.info("<=<=<=<=< %s >=>=>=>=>" % test_id)
        _ss = self.sh
        _ss.test_flows.complete[test_id] = False

        self.conv.test_id = test_id
        res = Result(self.sh, self.kwargs['profile_handler'])

        if index >= len(self.conv.sequence):
            return CRITICAL

        _oper = None
        for item in self.conv.sequence[index:]:
            if isinstance(item, tuple):
                cls, funcs = item
            else:
                cls = item
                funcs = {}

            logger.info("<--<-- {} --- {} -->-->".format(index, cls))
            self.conv.events.store('operation', cls, sender='run_flow')
            try:
                _oper = cls(conv=self.conv,
                            inut=self.inut,
                            sh=self.sh,
                            profile=self.profile,
                            test_id=test_id,
                            funcs=funcs,
                            check_factory=self.check_factory,
                            cache=self.cache)
                # self.conv.operation = _oper
                if profiles:
                    profile_map = profiles.PROFILEMAP
                else:
                    profile_map = None
                _oper.setup(profile_map)
                resp = _oper()
            except ConditionError:
                self.store_result(res)
                return ERROR
            except Exception as err:
                exception_trace('run_flow', err)
                self.conv.events.store(EV_FAULT, err)
                #self.sh["index"] = index
                self.store_result(res)
                return CRITICAL
            else:
                if isinstance(resp, self.response_cls):
                    return resp

                if resp:
                    if self.com_handler:
                        resp = self.com_handler(resp)

                    resp = _oper.handle_response(self.get_response(resp))

                    if resp:
                        return self.inut.respond(resp)

            # should be done as late as possible, so all processing has been
            # done
            try:
                _oper.post_tests()
            except ConditionError:
                tinfo = self.store_result(res)
                return tinfo['state']

            index += 1

        _ss['index'] = self.conv.index = index

        try:
            if self.conv.flow["assert"]:
                _ver = Verify(self.check_factory, self.conv)
                _ver.test_sequence(self.conv.flow["assert"])
        except KeyError:
            pass
        except Exception as err:
            logger.error(err)
            raise

        if isinstance(_oper, Done):
            self.conv.events.store(EV_CONDITION,
                                   State('Done', OK),
                                   sender='run_flow')

        tinfo = self.store_result(res)

        return tinfo['state']
示例#11
0
    def parse_response(self, path, inut, message_factory, response=None):
        _ctype = self.response_type
        _conv = self.conv

        if self.csi is None:
            url, body, ht_args, csi = _conv.entity.request_info(
                self.request,
                method=self.method,
                request_args=self.req_args,
                **self.op_args)

            self.csi = csi

        try:
            response_mode = self.csi["response_mode"]
        except KeyError:
            response_mode = None

        if self.request_cls == "AuthorizationRequest":
            try:
                _rt = self.csi["response_type"]
            except KeyError:
                response_where = ""
            else:
                if _rt == ["code"]:
                    response_where = "url"
                elif _rt == [""]:
                    response_where = ""
                else:
                    response_where = "fragment"
        else:
            response_where = self.response_where

        # parse the response
        if response_mode == "form_post":
            info = response
            _ctype = "dict"
        elif response_where in ["url", ""]:
            info = response
            _ctype = "dict"
        elif response_where == "fragment":
            try:
                info = response["fragment"]
            except KeyError:
                return inut.sorry_response(inut.base_url,
                                           "missing fragment ?!")
        else:  # resp_c.where == "body"
            info = response

        logger.info("Response: %s" % info)

        ev_index = _conv.events.store(EV_RESPONSE,
                                      info,
                                      sender=self.__class__.__name__)

        resp_cls = message_factory(self.response_cls)
        #  algs = _conv.entity.sign_enc_algs("id_token")
        try:
            response = _conv.entity.parse_response(
                resp_cls,
                info,
                _ctype,
                self.csi["state"],
                keyjar=_conv.entity.keyjar  # , algs=algs
            )
        except ResponseError as err:
            _conv.events.store(
                EV_FAULT,
                State(_conv.test_id,
                      ERROR,
                      message=err,
                      context='parse_response'))
            return inut.err_response("run_sequence", err)
        except (VerificationError, MissingRequiredAttribute) as err:
            self.conv.events.store(EV_FAULT, err)
            inut.err_response("run_sequence", err)
            return None
        except Exception as err:
            return inut.err_response("run_sequence", err)

        logger.info("Parsed response: %s" % response.to_dict())

        _conv.events.store(EV_PROTOCOL_RESPONSE,
                           response,
                           ref=ev_index,
                           sender=self.__class__.__name__)

        if "id_token" in response:
            try:
                self.conv.entity.smid2sid[response['id_token']
                                          ['sid']] = response['state']
            except KeyError:
                pass

        display_jwx_headers(response, _conv)

        if self.expect_error:
            self.expected_error_response(response)
        else:
            if isinstance(response, ErrorResponse):
                raise Break("Unexpected error response")
示例#12
0
    def run_flow(self, test_id, index=0, profiles=None, conf=None):
        logger.info("<=<=<=<=< %s >=>=>=>=>" % test_id)
        self.flows.complete[test_id] = False
        self.conv.test_id = test_id
        self.conv.conf = conf

        if index >= len(self.conv.sequence):
            return CRITICAL

        res = Result(self.sh, self.kwargs['profile_handler'])

        _oper = None
        for item in self.conv.sequence[index:]:
            self.sh["index"] = index
            if isinstance(item, tuple):
                cls, funcs = item
            else:
                cls = item
                funcs = {}

            _name = cls.__name__
            _line = "<--<-- {} --- {} -->-->".format(index, _name)
            logger.info(_line)
            self.conv.events.store(EV_OPERATION, _line)
            try:
                _oper = cls(conv=self.conv,
                            inut=self.inut,
                            sh=self.sh,
                            profile=self.sh.profile,
                            test_id=test_id,
                            conf=conf,
                            funcs=funcs,
                            check_factory=self.check_factory,
                            cache=self.cache,
                            tool_conf=self.kwargs['tool_conf'])
                self.conv.operation = _oper
                _oper.setup(self.profiles.PROFILEMAP)
                if _oper.fail:
                    break
                resp = _oper()
            except Break:
                break
            except cherrypy.HTTPError:
                raise
            except Exception as err:
                self.conv.events.store(
                    EV_CONDITION,
                    State(test_id=test_id,
                          status=ERROR,
                          message=err,
                          context=cls.__name__))
                _trace = exception_trace(cls.__name__, err, logger)
                self.sh["index"] = index
                self.store_result(res)
                return {'exception_trace': _trace}
            else:
                rsp = self.handle_response(resp, index)
                if rsp:
                    self.store_result(res)
                    return self.inut.respond(rsp)

            index += 1
            if index == len(self.conv.sequence):
                break

        if isinstance(_oper, Done):
            try:
                if self.conv.flow["assert"]:
                    _ver = Verify(self.check_factory, self.conv)
                    _ver.test_sequence(self.conv.flow["assert"])
            except (KeyError, Break):
                self.conv.events.store(EV_CONDITION, State('Done', status=OK))
            except ConditionError:
                pass
            except Exception as err:
                raise
            else:
                self.conv.events.store(EV_CONDITION, State('Done', status=OK))

        tinfo = self.store_result(res)
        return tinfo['state']