예제 #1
0
 def test_04_get_rand_digit_str(self):
     self.assertRaises(ValueError, get_rand_digit_str, 1)
     r = get_rand_digit_str(2)
     self.assertTrue(len(r) == 2, r)
     r = get_rand_digit_str(1001)
     self.assertTrue(len(r) == 1001, r)
     r = get_rand_digit_str(19182)
     self.assertTrue(len(r) == 19182)
예제 #2
0
 def test_04_get_rand_digit_str(self):
     self.assertRaises(ValueError, get_rand_digit_str, 1)
     r = get_rand_digit_str(2)
     self.assertTrue(len(r) == 2, r)
     r = get_rand_digit_str(1001)
     self.assertTrue(len(r) == 1001, r)
     r = get_rand_digit_str(19182)
     self.assertTrue(len(r) == 19182)
예제 #3
0
    def create_challenge(self):
        """
        Depending on the self.challenge_type and the self.challenge_length
        we create a challenge
        :return: a challenge string
        """
        ret = None
        if self.challenge_type == "QH":
            ret = geturandom(length=self.challenge_length, hex=True)
        elif self.challenge_type == "QA":
            ret = get_alphanum_str(self.challenge_length)
        elif self.challenge_type == "QN":
            ret = get_rand_digit_str(length=self.challenge_length)

        if not ret:  # pragma: no cover
            raise Exception("OCRA.create_challenge failed. Obviously no good "
                            "challenge_type!")

        return ret
예제 #4
0
파일: ocra.py 프로젝트: STRML/privacyidea
    def create_challenge(self):
        """
        Depending on the self.challenge_type and the self.challenge_length
        we create a challenge
        :return: a challenge string
        """
        ret = None
        if self.challenge_type == "QH":
            ret = geturandom(length=self.challenge_length, hex=True)
        elif self.challenge_type == "QA":
            ret = get_alphanum_str(self.challenge_length)
        elif self.challenge_type == "QN":
            ret = get_rand_digit_str(length=self.challenge_length)

        if not ret:  # pragma: no cover
            raise Exception("OCRA.create_challenge failed. Obviously no good "
                            "challenge_type!")

        return ret
예제 #5
0
 def createTransactionId(cls, length=20):
     return get_rand_digit_str(length)
예제 #6
0
def generic_challenge_response_reset_pin(wrapped_function, *args, **kwds):
    """
    Check if the authentication was successful, but if the token needs to reset
    its PIN.

    Conditions: To do so we check for "next_pin_change" in the tokeninfo data. This
    is however easily done using token.is_pin_change().

    Policies: A policy defines, if this PIN reset functionality should be active
    at all. scope=AUTH, action=CHANGE_PIN_VIA_VALIDATE

    args are:
    :param tokenobject_list: The list of all the tokens of the user, that will be checked
    :param passw: The password presented in the authentication. We need this for the PIN reset.

    kwds are:
    :param options: options dictionary containing g
    :param user: The user_obj
    """

    # Before we call the wrapped function, we need to check, if we have a generic challenge
    # for the given transaction_id and if the token serial matches a given token
    options = kwds.get("options") or {}
    user_obj = kwds.get("user")
    transaction_id = options.get("transaction_id") or options.get("state")
    if transaction_id:
        challenges = get_challenges(transaction_id=transaction_id,
                                    challenge=CHALLENGE_TYPE.PIN_RESET)
        if len(challenges) == 1:
            challenge = challenges[0]
            # check if challenge matches a token and if it is valid
            token_obj = next(t for t in args[0]
                             if t.token.serial == challenge.serial)
            if token_obj:
                # Then either verify the PIN or set the PIN the first time. The
                # PIN from the 1st response is stored in challenge.data
                if challenge.data:
                    # Verify the password
                    if verify_pass_hash(args[1], challenge.data):
                        g = options.get("g")
                        challenge.set_otp_status(True)
                        token_obj.challenge_janitor()
                        # Success, set new PIN and return success
                        token_obj.set_pin(args[1])
                        pinpol = Match.token(
                            g,
                            scope=SCOPE.ENROLL,
                            action=ACTION.CHANGE_PIN_EVERY,
                            token_obj=token_obj).action_values(unique=True)
                        # Set a new next_pin_change
                        if pinpol:
                            # Set a new next pin change
                            token_obj.set_next_pin_change(diff=list(pinpol)[0])
                        else:
                            # Obviously the admin removed the policy for changing pins,
                            # so we will not require to change the PIN again
                            token_obj.del_tokeninfo("next_pin_change")
                        return True, {
                            "message": "PIN successfully set.",
                            "serial": token_obj.token.serial
                        }
                    else:
                        return False, {
                            "serial": token_obj.token.serial,
                            "message": "PINs do not match"
                        }
                else:
                    # The PIN is presented the first time.
                    # Verify if the PIN adheres to the PIN policies. This is always in the normal user context
                    g = options.get("g")
                    g.logged_in_user = {"role": SCOPE.USER}
                    if user_obj:
                        # check_pin below originally works for logged in users, since only logged in users
                        # are allowed to change the pin. So we need to construct a logged_in_user object, otherwise
                        # check_pin would fail.
                        g.logged_in_user["username"] = user_obj.login
                        g.logged_in_user["realm"] = user_obj.realm
                    check_pin(g, args[1], token_obj.token.tokentype, user_obj)
                    # We need to ask for a 2nd time
                    challenge.set_otp_status(True)
                    seed = get_rand_digit_str(SEED_LENGTH)
                    reply_dict = _create_pin_reset_challenge(
                        token_obj, _("Please enter the new PIN again"),
                        pass_hash(args[1]))
                    return False, reply_dict

    success, reply_dict = wrapped_function(*args, **kwds)

    # After a successful authentication, we might start the PIN change process
    if success and reply_dict.get("pin_change"):
        g = options.get("g")
        # Determine the realm by the serial
        serial = reply_dict.get("serial")
        # The tokenlist can contain more than one token. So we get the matching token object
        token_obj = next(t for t in args[0] if t.token.serial == serial)
        if g and Match.token(g,
                             scope=SCOPE.AUTH,
                             action=ACTION.CHANGE_PIN_VIA_VALIDATE,
                             token_obj=token_obj).any():
            reply_dict = _create_pin_reset_challenge(
                token_obj, _("Please enter a new PIN"))
            return False, reply_dict

    return success, reply_dict