def test_13_parse_time_offset_from_now(self):
        td = parse_timedelta("+5s")
        self.assertEqual(td, timedelta(seconds=5))
        td = parse_timedelta("-12m")
        self.assertEqual(td, timedelta(minutes=-12))
        td = parse_timedelta("+123h")
        self.assertEqual(td, timedelta(hours=123))
        td = parse_timedelta("+2d")
        self.assertEqual(td, timedelta(days=2))

        # It is allowed to start without a +/- which would mean a +
        td = parse_timedelta("12d")
        self.assertEqual(td, timedelta(days=12))

        # Does not contains numbers
        self.assertRaises(Exception, parse_timedelta, "+twod")

        s, td = parse_time_offset_from_now("Hello {now}+5d with 5 days.")
        self.assertEqual(s, "Hello {now} with 5 days.")
        self.assertEqual(td, timedelta(days=5))

        s, td = parse_time_offset_from_now("Hello {current_time}+5m!")
        self.assertEqual(s, "Hello {current_time}!")
        self.assertEqual(td, timedelta(minutes=5))

        s, td = parse_time_offset_from_now("Hello {current_time}-3habc")
        self.assertEqual(s, "Hello {current_time}abc")
        self.assertEqual(td, timedelta(hours=-3))
    def test_13_parse_time_offset_from_now(self):
        td = parse_timedelta("+5s")
        self.assertEqual(td, timedelta(seconds=5))
        td = parse_timedelta("-12m")
        self.assertEqual(td, timedelta(minutes=-12))
        td = parse_timedelta("+123h")
        self.assertEqual(td, timedelta(hours=123))
        td = parse_timedelta("+2d")
        self.assertEqual(td, timedelta(days=2))

        # It is allowed to start without a +/- which would mean a +
        td = parse_timedelta("12d")
        self.assertEqual(td, timedelta(days=12))

        # Does not contains numbers
        self.assertRaises(Exception, parse_timedelta, "+twod")

        s, td = parse_time_offset_from_now("Hello {now}+5d with 5 days.")
        self.assertEqual(s, "Hello {now} with 5 days.")
        self.assertEqual(td, timedelta(days=5))

        s, td = parse_time_offset_from_now("Hello {current_time}+5m!")
        self.assertEqual(s, "Hello {current_time}!")
        self.assertEqual(td, timedelta(minutes=5))

        s, td = parse_time_offset_from_now("Hello {current_time}-3habc")
        self.assertEqual(s, "Hello {current_time}abc")
        self.assertEqual(td, timedelta(hours=-3))
Exemple #3
0
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = self._get_response_content(response)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial") or \
                 g.audit_object.audit_data.get("serial")

        if action.lower() in [ACTION_TYPE.SET_TOKENREALM,
                              ACTION_TYPE.SET_DESCRIPTION,
                              ACTION_TYPE.DELETE, ACTION_TYPE.DISABLE,
                              ACTION_TYPE.ENABLE, ACTION_TYPE.UNASSIGN,
                              ACTION_TYPE.SET_VALIDITY,
                              ACTION_TYPE.SET_COUNTWINDOW,
                              ACTION_TYPE.SET_TOKENINFO,
                              ACTION_TYPE.SET_FAILCOUNTER,
                              ACTION_TYPE.CHANGE_FAILCOUNTER,
                              ACTION_TYPE.SET_RANDOM_PIN,
                              ACTION_TYPE.DELETE_TOKENINFO]:
            if serial:
                log.info("{0!s} for token {1!s}".format(action, serial))
                if action.lower() == ACTION_TYPE.SET_TOKENREALM:
                    realm = handler_options.get("realm")
                    only_realm = is_true(handler_options.get("only_realm"))
                    # Set the realm..
                    log.info("Setting realm of token {0!s} to {1!s}".format(
                        serial, realm))
                    # Add the token realm
                    set_realms(serial, [realm], add=not only_realm)
                elif action.lower() == ACTION_TYPE.SET_RANDOM_PIN:
                    # If for any reason we have no value, we default to 6
                    length = int(handler_options.get("length") or 6)
                    pin = generate_password(size=length)
                    if set_pin(serial, pin):
                        content.setdefault("detail", {})["pin"] = pin
                        options.get("response").data = json.dumps(content)
                elif action.lower() == ACTION_TYPE.DELETE:
                    remove_token(serial=serial)
                elif action.lower() == ACTION_TYPE.DISABLE:
                    enable_token(serial, enable=False)
                elif action.lower() == ACTION_TYPE.ENABLE:
                    enable_token(serial, enable=True)
                elif action.lower() == ACTION_TYPE.UNASSIGN:
                    unassign_token(serial)
                elif action.lower() == ACTION_TYPE.SET_DESCRIPTION:
                    description = handler_options.get("description") or ""
                    description, td = parse_time_offset_from_now(description)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    set_description(serial,
                                    description.format(
                                        current_time=s_now,
                                        now=s_now,
                                        client_ip=g.client_ip,
                                        ua_browser=request.user_agent.browser,
                                        ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.SET_COUNTWINDOW:
                    set_count_window(serial,
                                     int(handler_options.get("count window",
                                                             50)))
                elif action.lower() == ACTION_TYPE.SET_TOKENINFO:
                    tokeninfo = handler_options.get("value") or ""
                    tokeninfo, td = parse_time_offset_from_now(tokeninfo)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    try:
                        username = request.User.loginname
                        realm = request.User.realm
                    except Exception:
                        username = "******"
                        realm = "N/A"
                    add_tokeninfo(serial, handler_options.get("key"),
                                  tokeninfo.format(
                                      current_time=s_now,
                                      now=s_now,
                                      client_ip=g.client_ip,
                                      username=username,
                                      realm=realm,
                                      ua_browser=request.user_agent.browser,
                                      ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.DELETE_TOKENINFO:
                    delete_tokeninfo(serial, handler_options.get("key"))
                elif action.lower() == ACTION_TYPE.SET_VALIDITY:
                    start_date = handler_options.get(VALIDITY.START)
                    end_date = handler_options.get(VALIDITY.END)
                    if start_date:
                         d = parse_date(start_date)
                         set_validity_period_start(serial, None,
                                                   d.strftime(DATE_FORMAT))
                    if end_date:
                        d = parse_date(end_date)
                        set_validity_period_end(serial, None,
                                                d.strftime(DATE_FORMAT))
                elif action.lower() == ACTION_TYPE.SET_FAILCOUNTER:
                    try:
                        set_failcounter(serial,
                                        int(handler_options.get("fail counter")))
                    except Exception as exx:
                        log.warning("Misconfiguration: Failed to set fail "
                                    "counter!")
                elif action.lower() == ACTION_TYPE.CHANGE_FAILCOUNTER:
                    try:
                        token_obj = get_one_token(serial=serial)
                        token_obj.set_failcount(
                            token_obj.token.failcount + int(handler_options.get("change fail counter")))
                    except Exception as exx:
                        log.warning("Misconfiguration: Failed to increase or decrease fail "
                                    "counter!")
            else:
                log.info("Action {0!s} requires serial number. But no serial "
                         "number could be found in request.")

        if action.lower() == ACTION_TYPE.INIT:
            log.info("Initializing new token")
            init_param = {"type": handler_options.get("tokentype"),
                          "genkey": 1,
                          "realm": handler_options.get("realm", "")}
            user = None
            if is_true(handler_options.get("user")):
                user = self._get_tokenowner(request)
                tokentype = handler_options.get("tokentype")
                # Some tokentypes need additional parameters
                if handler_options.get("additional_params"):
                    add_params = yaml.safe_load(handler_options.get("additional_params"))
                    if type(add_params) == dict:
                        init_param.update(add_params)

                if tokentype == "sms":
                    if handler_options.get("dynamic_phone"):
                        init_param["dynamic_phone"] = 1
                    else:
                        init_param['phone'] = user.get_user_phone(
                            phone_type='mobile', index=0)
                        if not init_param['phone']:
                            log.warning("Enrolling SMS token. But the user "
                                        "{0!r} has no mobile number!".format(user))
                    if handler_options.get("sms_identifier"):
                        init_param["sms.identifier"] = handler_options.get("sms_identifier")
                elif tokentype == "email":
                    if handler_options.get("dynamic_email"):
                        init_param["dynamic_email"] = 1
                    else:
                        init_param['email'] = user.info.get("email", "")
                        if not init_param['email']:
                            log.warning("Enrolling EMail token. But the user {0!s}"
                                        "has no email address!".format(user))
                    if handler_options.get("smtp_identifier"):
                        init_param["email.identifier"] = handler_options.get("smtp_identifier")
                elif tokentype == "motp":
                    init_param['motppin'] = handler_options.get("motppin")

            t = init_token(param=init_param, user=user)
            log.info("New token {0!s} enrolled.".format(t.token.serial))

        return ret
Exemple #4
0
    def check_condition(self, options):
        """
        Check if all conditions are met and if the action should be executed.
        The the conditions are met, we return "True"
        :return: True
        """
        res = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        e_handler_def = options.get("handler_def")
        if not response or not e_handler_def:
            # options is missing a response and the handler definition
            # We are probably in test mode.
            return True
        # conditions can be correspnding to the property conditions
        conditions = e_handler_def.get("conditions")
        content = json.loads(response.data)
        user = self._get_tokenowner(request)

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial")
        tokenrealms = []
        tokentype = None
        token_obj = None
        if serial:
            # We have determined the serial number from the request.
            token_obj_list = get_tokens(serial=serial)
        else:
            # We have to determine the token via the user object. But only if
            #  the user has only one token
            token_obj_list = get_tokens(user=user)
        if len(token_obj_list) == 1:
            token_obj = token_obj_list[0]
            tokenrealms = token_obj.get_realms()
            tokentype = token_obj.get_tokentype()

        if "realm" in conditions:
            res = user.realm == conditions.get("realm")

        if "logged_in_user" in conditions and res:
            # Determine the role of the user
            try:
                logged_in_user = g.logged_in_user
                user_role = logged_in_user.get("role")
            except Exception:
                # A non-logged-in-user is a User, not an admin
                user_role = ROLE.USER
            res = user_role == conditions.get("logged_in_user")

        # Check result_value only if the check condition is still True
        if "result_value" in conditions and res:
            condition_value = conditions.get("result_value")
            result_value = content.get("result", {}).get("value")
            res = condition_value == str(result_value)

        # checking of max-failcounter state of the token
        if "token_locked" in conditions and res:
            if token_obj:
                locked = token_obj.get_failcount() >= \
                         token_obj.get_max_failcount()
                res = (conditions.get("token_locked") in ["True", True]) == \
                      locked
            else:
                # check all tokens of the user, if any token is maxfail
                token_objects = get_tokens(user=user, maxfail=True)
                if not ','.join([tok.get_serial() for tok in token_objects]):
                    res = False

        if "tokenrealm" in conditions and res and tokenrealms:
            res = False
            for trealm in tokenrealms:
                if trealm in conditions.get("tokenrealm").split(","):
                    res = True
                    break

        if "serial" in conditions and res and serial:
            serial_match = conditions.get("serial")
            res = bool(re.match(serial_match, serial))

        if CONDITION.USER_TOKEN_NUMBER in conditions and res and user:
            num_tokens = get_tokens(user=user, count=True)
            res = num_tokens == int(conditions.get(
                CONDITION.USER_TOKEN_NUMBER))

        # Token specific conditions
        if token_obj:
            if CONDITION.TOKENTYPE in conditions and res:
                res = False
                if tokentype in conditions.get(CONDITION.TOKENTYPE).split(","):
                    res = True

            if CONDITION.TOKEN_HAS_OWNER in conditions and res:
                uid = token_obj.get_user_id()
                check = conditions.get(CONDITION.TOKEN_HAS_OWNER)
                if uid and check in ["True", True]:
                    res = True
                elif not uid and check in ["False", False]:
                    res = True
                else:
                    log.debug("Condition token_has_owner for token {0!r} "
                              "not fulfilled.".format(token_obj))
                    res = False

            if CONDITION.TOKEN_IS_ORPHANED in conditions and res:
                uid = token_obj.get_user_id()
                orphaned = uid and not user
                check = conditions.get(CONDITION.TOKEN_IS_ORPHANED)
                if orphaned and check in ["True", True]:
                    res = True
                elif not orphaned and check in ["False", False]:
                    res = True
                else:
                    log.debug(
                        "Condition token_is_orphaned for token {0!r} not "
                        "fulfilled.".format(token_obj))
                    res = False

            if CONDITION.TOKEN_VALIDITY_PERIOD in conditions and res:
                valid = token_obj.check_validity_period()
                res = (conditions.get(CONDITION.TOKEN_VALIDITY_PERIOD)
                       in ["True", True]) == valid

            if CONDITION.OTP_COUNTER in conditions and res:
                res = token_obj.token.count == \
                      int(conditions.get(CONDITION.OTP_COUNTER))

            if CONDITION.LAST_AUTH in conditions and res:
                res = not token_obj.check_last_auth_newer(
                    conditions.get(CONDITION.LAST_AUTH))

            if CONDITION.COUNT_AUTH in conditions and res:
                count = token_obj.get_count_auth()
                cond = conditions.get(CONDITION.COUNT_AUTH)
                res = compare_condition(cond, count)

            if CONDITION.COUNT_AUTH_SUCCESS in conditions and res:
                count = token_obj.get_count_auth_success()
                cond = conditions.get(CONDITION.COUNT_AUTH_SUCCESS)
                res = compare_condition(cond, count)

            if CONDITION.COUNT_AUTH_FAIL in conditions and res:
                count = token_obj.get_count_auth()
                c_success = token_obj.get_count_auth_success()
                c_fail = count - c_success
                cond = conditions.get(CONDITION.COUNT_AUTH_FAIL)
                res = compare_condition(cond, c_fail)
            if CONDITION.TOKENINFO in conditions and res:
                cond = conditions.get(CONDITION.TOKENINFO)
                # replace {now} in condition
                cond, td = parse_time_offset_from_now(cond)
                s_now = (datetime.datetime.now(tzlocal()) +
                         td).strftime(DATE_FORMAT)
                cond = cond.format(now=s_now)
                if len(cond.split("==")) == 2:
                    key, value = [x.strip() for x in cond.split("==")]
                    res = compare_value_value(token_obj.get_tokeninfo(key),
                                              "==", value)
                elif len(cond.split(">")) == 2:
                    key, value = [x.strip() for x in cond.split(">")]
                    res = compare_value_value(token_obj.get_tokeninfo(key),
                                              ">", value)
                elif len(cond.split("<")) == 2:
                    key, value = [x.strip() for x in cond.split("<")]
                    res = compare_value_value(token_obj.get_tokeninfo(key),
                                              "<", value)
                else:
                    # There is a condition, but we do not know it!
                    log.warning("Misconfiguration in your tokeninfo "
                                "condition: {0!s}".format(cond))
                    res = False

        return res
Exemple #5
0
    def check_condition(self, options):
        """
        Check if all conditions are met and if the action should be executed.
        The the conditions are met, we return "True"
        :return: True
        """
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        e_handler_def = options.get("handler_def")
        if not e_handler_def:
            # options is the handler definition
            return True
        # conditions can be corresponding to the property conditions
        conditions = e_handler_def.get("conditions")
        content = self._get_response_content(response)
        user = self._get_tokenowner(request)

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial")
        tokenrealms = []
        tokenresolvers = []
        tokentype = None
        token_obj = None
        if serial:
            # We have determined the serial number from the request.
            token_obj_list = get_tokens(serial=serial)
        else:
            # We have to determine the token via the user object. But only if
            #  the user has only one token
            token_obj_list = get_tokens(user=user)
        if len(token_obj_list) == 1:
            # There is a token involved, so we determine it's resolvers and realms
            token_obj = token_obj_list[0]
            tokenrealms = token_obj.get_realms()
            tokentype = token_obj.get_tokentype()

            all_realms = get_realms()
            for tokenrealm in tokenrealms:
                resolvers = all_realms.get(tokenrealm, {}).get("resolver", {})
                tokenresolvers.extend([r.get("name") for r in resolvers])
            tokenresolvers = list(set(tokenresolvers))

        if CONDITION.CLIENT_IP in conditions:
            if g and g.client_ip:
                ip_policy = [
                    ip.strip()
                    for ip in conditions.get(CONDITION.CLIENT_IP).split(",")
                ]
                found, excluded = check_ip_in_policy(g.client_ip, ip_policy)
                if not found or excluded:
                    return False

        if CONDITION.REALM in conditions:
            if user.realm != conditions.get(CONDITION.REALM):
                return False

        if CONDITION.RESOLVER in conditions:
            if user.resolver != conditions.get(CONDITION.RESOLVER):
                return False

        if "logged_in_user" in conditions:
            # Determine the role of the user
            try:
                logged_in_user = g.logged_in_user
                user_role = logged_in_user.get("role")
            except Exception:
                # A non-logged-in-user is a User, not an admin
                user_role = ROLE.USER
            if user_role != conditions.get("logged_in_user"):
                return False

        if CONDITION.RESULT_VALUE in conditions:
            condition_value = conditions.get(CONDITION.RESULT_VALUE)
            result_value = content.get("result", {}).get("value")
            if is_true(condition_value) != is_true(result_value):
                return False

        if CONDITION.RESULT_STATUS in conditions:
            condition_value = conditions.get(CONDITION.RESULT_STATUS)
            result_status = content.get("result", {}).get("status")
            if is_true(condition_value) != is_true(result_status):
                return False

        # checking of max-failcounter state of the token
        if "token_locked" in conditions:
            if token_obj:
                locked = token_obj.get_failcount() >= \
                         token_obj.get_max_failcount()
                if (conditions.get("token_locked") in ["True", True]) != \
                      locked:
                    return False
            else:
                # check all tokens of the user, if any token is maxfail
                token_objects = get_tokens(user=user, maxfail=True)
                if not ','.join([tok.get_serial() for tok in token_objects]):
                    return False

        if CONDITION.TOKENREALM in conditions and tokenrealms:
            res = False
            for trealm in tokenrealms:
                if trealm in conditions.get(CONDITION.TOKENREALM).split(","):
                    res = True
                    break
            if not res:
                return False

        if CONDITION.TOKENRESOLVER in conditions and tokenresolvers:
            res = False
            for tres in tokenresolvers:
                if tres in conditions.get(CONDITION.TOKENRESOLVER).split(","):
                    res = True
                    break
            if not res:
                return False

        if "serial" in conditions and serial:
            serial_match = conditions.get("serial")
            if not bool(re.match(serial_match, serial)):
                return False

        if CONDITION.USER_TOKEN_NUMBER in conditions and user:
            num_tokens = get_tokens(user=user, count=True)
            if num_tokens != int(conditions.get(CONDITION.USER_TOKEN_NUMBER)):
                return False

        if CONDITION.DETAIL_ERROR_MESSAGE in conditions:
            message = content.get("detail", {}).get("error", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_ERROR_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        if CONDITION.DETAIL_MESSAGE in conditions:
            message = content.get("detail", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        # Token specific conditions
        if token_obj:
            if CONDITION.TOKENTYPE in conditions:
                if tokentype not in conditions.get(
                        CONDITION.TOKENTYPE).split(","):
                    return False

            if CONDITION.TOKEN_HAS_OWNER in conditions:
                uid = token_obj.get_user_id()
                check = conditions.get(CONDITION.TOKEN_HAS_OWNER)
                if uid and check in ["True", True]:
                    res = True
                elif not uid and check in ["False", False]:
                    res = True
                else:
                    log.debug("Condition token_has_owner for token {0!r} "
                              "not fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_IS_ORPHANED in conditions:
                orphaned = token_obj.is_orphaned()
                check = conditions.get(CONDITION.TOKEN_IS_ORPHANED)
                if orphaned and check in ["True", True]:
                    res = True
                elif not orphaned and check in ["False", False]:
                    res = True
                else:
                    log.debug(
                        "Condition token_is_orphaned for token {0!r} not "
                        "fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_VALIDITY_PERIOD in conditions:
                valid = token_obj.check_validity_period()
                if (conditions.get(CONDITION.TOKEN_VALIDITY_PERIOD)
                        in ["True", True]) != valid:
                    return False

            if CONDITION.OTP_COUNTER in conditions:
                cond = conditions.get(CONDITION.OTP_COUNTER)
                if not compare_condition(cond, token_obj.token.count):
                    return False

            if CONDITION.LAST_AUTH in conditions:
                if token_obj.check_last_auth_newer(
                        conditions.get(CONDITION.LAST_AUTH)):
                    return False

            if CONDITION.COUNT_AUTH in conditions:
                count = token_obj.get_count_auth()
                cond = conditions.get(CONDITION.COUNT_AUTH)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_SUCCESS in conditions:
                count = token_obj.get_count_auth_success()
                cond = conditions.get(CONDITION.COUNT_AUTH_SUCCESS)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_FAIL in conditions:
                count = token_obj.get_count_auth()
                c_success = token_obj.get_count_auth_success()
                c_fail = count - c_success
                cond = conditions.get(CONDITION.COUNT_AUTH_FAIL)
                if not compare_condition(cond, c_fail):
                    return False

            if CONDITION.TOKENINFO in conditions:
                cond = conditions.get(CONDITION.TOKENINFO)
                # replace {now} in condition
                cond, td = parse_time_offset_from_now(cond)
                s_now = (datetime.datetime.now(tzlocal()) +
                         td).strftime(DATE_FORMAT)
                cond = cond.format(now=s_now)
                if len(cond.split("==")) == 2:
                    key, value = [x.strip() for x in cond.split("==")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               "==", value):
                        return False
                elif len(cond.split(">")) == 2:
                    key, value = [x.strip() for x in cond.split(">")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               ">", value):
                        return False
                elif len(cond.split("<")) == 2:
                    key, value = [x.strip() for x in cond.split("<")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                               "<", value):
                        return False
                else:
                    # There is a condition, but we do not know it!
                    log.warning("Misconfiguration in your tokeninfo "
                                "condition: {0!s}".format(cond))
                    return False

        return True
Exemple #6
0
    def check_condition(self, options):
        """
        Check if all conditions are met and if the action should be executed.
        The the conditions are met, we return "True"
        :return: True
        """
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        e_handler_def = options.get("handler_def")
        if not e_handler_def:
            # options is the handler definition
            return True
        # conditions can be corresponding to the property conditions
        conditions = e_handler_def.get("conditions")
        content = self._get_response_content(response)
        user = self._get_tokenowner(request)

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial")
        tokenrealms = []
        tokentype = None
        token_obj = None
        if serial:
            # We have determined the serial number from the request.
            token_obj_list = get_tokens(serial=serial)
        else:
            # We have to determine the token via the user object. But only if
            #  the user has only one token
            token_obj_list = get_tokens(user=user)
        if len(token_obj_list) == 1:
            token_obj = token_obj_list[0]
            tokenrealms = token_obj.get_realms()
            tokentype = token_obj.get_tokentype()

        if "realm" in conditions:
            if user.realm != conditions.get("realm"):
                return False

        if "logged_in_user" in conditions:
            # Determine the role of the user
            try:
                logged_in_user = g.logged_in_user
                user_role = logged_in_user.get("role")
            except Exception:
                # A non-logged-in-user is a User, not an admin
                user_role = ROLE.USER
            if user_role != conditions.get("logged_in_user"):
                return False

        if CONDITION.RESULT_VALUE in conditions:
            condition_value = conditions.get(CONDITION.RESULT_VALUE)
            result_value = content.get("result", {}).get("value")
            if is_true(condition_value) != is_true(result_value):
                return False

        if CONDITION.RESULT_STATUS in conditions:
            condition_value = conditions.get(CONDITION.RESULT_STATUS)
            result_status = content.get("result", {}).get("status")
            if is_true(condition_value) != is_true(result_status):
                return False

        # checking of max-failcounter state of the token
        if "token_locked" in conditions:
            if token_obj:
                locked = token_obj.get_failcount() >= \
                         token_obj.get_max_failcount()
                if (conditions.get("token_locked") in ["True", True]) != \
                      locked:
                    return False
            else:
                # check all tokens of the user, if any token is maxfail
                token_objects = get_tokens(user=user, maxfail=True)
                if not ','.join([tok.get_serial() for tok in token_objects]):
                    return False

        if "tokenrealm" in conditions and tokenrealms:
            res = False
            for trealm in tokenrealms:
                if trealm in conditions.get("tokenrealm").split(","):
                    res = True
                    break
            if not res:
                return False

        if "serial" in conditions and serial:
            serial_match = conditions.get("serial")
            if not bool(re.match(serial_match, serial)):
                return False

        if CONDITION.USER_TOKEN_NUMBER in conditions and user:
            num_tokens = get_tokens(user=user, count=True)
            if num_tokens != int(conditions.get(
                    CONDITION.USER_TOKEN_NUMBER)):
                return False

        if CONDITION.DETAIL_ERROR_MESSAGE in conditions:
            message = content.get("detail", {}).get("error", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_ERROR_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        if CONDITION.DETAIL_MESSAGE in conditions:
            message = content.get("detail", {}).get("message")
            search_exp = conditions.get(CONDITION.DETAIL_MESSAGE)
            m = re.search(search_exp, message)
            if not bool(m):
                return False

        # Token specific conditions
        if token_obj:
            if CONDITION.TOKENTYPE in conditions:
                if tokentype not in conditions.get(CONDITION.TOKENTYPE).split(
                        ","):
                    return False

            if CONDITION.TOKEN_HAS_OWNER in conditions:
                uid = token_obj.get_user_id()
                check = conditions.get(CONDITION.TOKEN_HAS_OWNER)
                if uid and check in ["True", True]:
                    res = True
                elif not uid and check in ["False", False]:
                    res = True
                else:
                    log.debug("Condition token_has_owner for token {0!r} "
                              "not fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_IS_ORPHANED in conditions:
                uid = token_obj.get_user_id()
                orphaned = uid and not user
                check = conditions.get(CONDITION.TOKEN_IS_ORPHANED)
                if orphaned and check in ["True", True]:
                    res = True
                elif not orphaned and check in ["False", False]:
                    res = True
                else:
                    log.debug("Condition token_is_orphaned for token {0!r} not "
                              "fulfilled.".format(token_obj))
                    return False

            if CONDITION.TOKEN_VALIDITY_PERIOD in conditions:
                valid = token_obj.check_validity_period()
                if (conditions.get(CONDITION.TOKEN_VALIDITY_PERIOD)
                       in ["True", True]) != valid:
                    return False

            if CONDITION.OTP_COUNTER in conditions:
                if token_obj.token.count != \
                      int(conditions.get(CONDITION.OTP_COUNTER)):
                    return False

            if CONDITION.LAST_AUTH in conditions:
                if token_obj.check_last_auth_newer(conditions.get(
                    CONDITION.LAST_AUTH)):
                    return False

            if CONDITION.COUNT_AUTH in conditions:
                count = token_obj.get_count_auth()
                cond = conditions.get(CONDITION.COUNT_AUTH)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_SUCCESS in conditions:
                count = token_obj.get_count_auth_success()
                cond = conditions.get(CONDITION.COUNT_AUTH_SUCCESS)
                if not compare_condition(cond, count):
                    return False

            if CONDITION.COUNT_AUTH_FAIL in conditions:
                count = token_obj.get_count_auth()
                c_success = token_obj.get_count_auth_success()
                c_fail = count - c_success
                cond = conditions.get(CONDITION.COUNT_AUTH_FAIL)
                if not compare_condition(cond, c_fail):
                    return False

            if CONDITION.TOKENINFO in conditions:
                cond = conditions.get(CONDITION.TOKENINFO)
                # replace {now} in condition
                cond, td = parse_time_offset_from_now(cond)
                s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                    DATE_FORMAT)
                cond = cond.format(now=s_now)
                if len(cond.split("==")) == 2:
                    key, value = [x.strip() for x in cond.split("==")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                              "==", value):
                        return False
                elif len(cond.split(">")) == 2:
                    key, value = [x.strip() for x in cond.split(">")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                              ">", value):
                        return False
                elif len(cond.split("<")) == 2:
                    key, value = [x.strip() for x in cond.split("<")]
                    if not compare_value_value(token_obj.get_tokeninfo(key),
                                              "<", value):
                        return False
                else:
                    # There is a condition, but we do not know it!
                    log.warning("Misconfiguration in your tokeninfo "
                                "condition: {0!s}".format(cond))
                    return False

        return True
    def do(self, action, options=None):
        """
        This method executes the defined action in the given event.

        :param action:
        :param options: Contains the flask parameters g, request, response
            and the handler_def configuration
        :type options: dict
        :return:
        """
        ret = True
        g = options.get("g")
        request = options.get("request")
        response = options.get("response")
        content = json.loads(response.data)
        handler_def = options.get("handler_def")
        handler_options = handler_def.get("options", {})

        serial = request.all_data.get("serial") or \
                 content.get("detail", {}).get("serial") or \
                 g.audit_object.audit_data.get("serial")

        if action.lower() in [ACTION_TYPE.SET_TOKENREALM,
                              ACTION_TYPE.SET_DESCRIPTION,
                              ACTION_TYPE.DELETE, ACTION_TYPE.DISABLE,
                              ACTION_TYPE.ENABLE, ACTION_TYPE.UNASSIGN,
                              ACTION_TYPE.SET_VALIDITY,
                              ACTION_TYPE.SET_COUNTWINDOW,
                              ACTION_TYPE.SET_TOKENINFO,
                              ACTION_TYPE.SET_FAILCOUNTER]:
            if serial:
                log.info("{0!s} for token {1!s}".format(action, serial))
                if action.lower() == ACTION_TYPE.SET_TOKENREALM:
                    realm = handler_options.get("realm")
                    only_realm = is_true(handler_options.get("only_realm"))
                    # Set the realm..
                    log.info("Setting realm of token {0!s} to {1!s}".format(
                        serial, realm))
                    # Add the token realm
                    set_realms(serial, [realm], add=not only_realm)
                elif action.lower() == ACTION_TYPE.DELETE:
                    remove_token(serial=serial)
                elif action.lower() == ACTION_TYPE.DISABLE:
                    enable_token(serial, enable=False)
                elif action.lower() == ACTION_TYPE.ENABLE:
                    enable_token(serial, enable=True)
                elif action.lower() == ACTION_TYPE.UNASSIGN:
                    unassign_token(serial)
                elif action.lower() == ACTION_TYPE.SET_DESCRIPTION:
                    description = handler_options.get("description") or ""
                    description, td = parse_time_offset_from_now(description)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    set_description(serial,
                                    description.format(
                                        current_time=s_now,
                                        now=s_now,
                                        client_ip=g.client_ip,
                                        ua_browser=request.user_agent.browser,
                                        ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.SET_COUNTWINDOW:
                    set_count_window(serial,
                                     int(handler_options.get("count window",
                                                             50)))
                elif action.lower() == ACTION_TYPE.SET_TOKENINFO:
                    tokeninfo = handler_options.get("value") or ""
                    tokeninfo, td = parse_time_offset_from_now(tokeninfo)
                    s_now = (datetime.datetime.now(tzlocal()) + td).strftime(
                        AUTH_DATE_FORMAT)
                    try:
                        username = request.User.loginname
                        realm = request.User.realm
                    except Exception:
                        username = "******"
                        realm = "N/A"
                    add_tokeninfo(serial, handler_options.get("key"),
                                  tokeninfo.format(
                                      current_time=s_now,
                                      now=s_now,
                                      client_ip=g.client_ip,
                                      username=username,
                                      realm=realm,
                                      ua_browser=request.user_agent.browser,
                                      ua_string=request.user_agent.string))
                elif action.lower() == ACTION_TYPE.SET_VALIDITY:
                    start_date = handler_options.get(VALIDITY.START)
                    end_date = handler_options.get(VALIDITY.END)
                    if start_date:
                         d = parse_date(start_date)
                         set_validity_period_start(serial, None,
                                                   d.strftime(DATE_FORMAT))
                    if end_date:
                        d = parse_date(end_date)
                        set_validity_period_end(serial, None,
                                                d.strftime(DATE_FORMAT))
                elif action.lower() == ACTION_TYPE.SET_FAILCOUNTER:
                    try:
                        set_failcounter(serial,
                                        int(handler_options.get("fail counter")))
                    except Exception as exx:
                        log.warning("Misconfiguration: Failed to set fail "
                                    "counter!")
            else:
                log.info("Action {0!s} requires serial number. But no serial "
                         "number could be found in request.")

        if action.lower() == ACTION_TYPE.INIT:
            log.info("Initializing new token")
            init_param = {"type": handler_options.get("tokentype"),
                          "genkey": 1,
                          "realm": handler_options.get("realm", "")}
            user = None
            if is_true(handler_options.get("user")):
                user = self._get_tokenowner(request)
                tokentype = handler_options.get("tokentype")
                # Some tokentypes need additional parameters or otherwise
                # will fail to enroll.
                # TODO: Other tokentypes will require additional parameters
                if tokentype == "sms":
                    if handler_options.get("dynamic_phone"):
                        init_param["dynamic_phone"] = 1
                    else:
                        init_param['phone'] = user.get_user_phone(
                            phone_type='mobile')
                        if not init_param['phone']:
                            log.warning("Enrolling SMS token. But the user "
                                        "{0!r} has no mobile number!".format(user))
                elif tokentype == "email":
                    init_param['email'] = user.info.get("email", "")
                    if not init_param['email']:
                        log.warning("Enrolling EMail token. But the user {0!s}"
                                    "has no email address!".format(user))
                elif tokentype == "motp":
                    init_param['motppin'] = handler_options.get("motppin")

            t = init_token(param=init_param, user=user)
            log.info("New token {0!s} enrolled.".format(t.token.serial))

        return ret