Exemple #1
0
    def checkResponse4Challenge(self, user, passw, options=None, challenges=None):
        '''
        verify the response of a previous challenge

        :param user:     the requesting user
        :param passw:    the to be checked pass (pin+otp)
        :param options:  options an additional argument, which could be token
                          specific
        :param challenges: the list of challenges, where each challenge is
                            described as dict
        :return: tuple of (otpcounter and the list of matching challenges)

        '''
        otp_counter = -1
        transid = None
        matching = None
        matchin_challenges = []

        if 'transactionid' in options or 'state' in options:
            ## fetch the transactionid
            transid = options.get('transactionid', options.get('state', None))

        # check if the transactionid is in the list of challenges
        if transid is not None:
            for challenge in challenges:
                if is_same_transaction(challenge, transid):
                    matching = challenge
                    break
            if matching is not None:
                otp_counter = check_otp(self, passw, options=options)
                if otp_counter >= 0:
                    matchin_challenges.append(matching)

        return (otp_counter, matchin_challenges)
Exemple #2
0
    def checkResponse4Challenge(self,
                                user,
                                passw,
                                options=None,
                                challenges=None):
        """
        This method verifies if the given ``passw`` matches any existing ``challenge``
        of the token.

        It then returns the new otp_counter of the token and the
        list of the matching challenges.

        In case of success the otp_counter needs to be > 0.
        The matching_challenges is passed to the method
        :py:meth:`~linotp.lib.tokenclass.TokenClass.challenge_janitor`
        to clean up challenges.

        :param user: the requesting user
        :type user: User object
        :param passw: the password (pin+otp)
        :type passw: string
        :param options:  additional arguments from the request, which could be token specific
        :type options: dict
        :param challenges: A sorted list of valid challenges for this token.
        :type challenges: list
        :return: tuple of (otpcounter and the list of matching challenges)
        """
        otp_counter = -1
        transid = None
        matching = None
        matching_challenges = []

        # fetch the transactionid
        if 'transactionid' in options:
            transid = options.get('transactionid', None)

        # check if the transactionid is in the list of challenges
        if transid is not None:
            for challenge in challenges:
                if is_same_transaction(challenge, transid):
                    matching = challenge
                    break
            if matching is not None:
                # Split pin from otp and check the resulting pin and otpval
                (res, pin, otpval) = self.splitPinPass(passw)
                if not check_pin(self, pin, user=user, options=options):
                    otpval = passw
                # The U2F checkOtp functions needs to know the saved challenge
                # to compare the received challenge value to the saved one,
                # thus we add the transactionid to the options
                options['transactionid'] = transid
                options['challenges'] = challenges
                otp_counter = check_otp(self, otpval, options=options)
                if otp_counter >= 0:
                    matching_challenges.append(matching)

        return (otp_counter, matching_challenges)
Exemple #3
0
    def checkResponse4Challenge(self, user, passw, options=None, challenges=None):
        """
        This method verifies if the given ``passw`` matches any existing ``challenge``
        of the token.

        It then returns the new otp_counter of the token and the
        list of the matching challenges.

        In case of success the otp_counter needs to be > 0.
        The matching_challenges is passed to the method
        :py:meth:`~linotp.lib.tokenclass.TokenClass.challenge_janitor`
        to clean up challenges.

        :param user: the requesting user
        :type user: User object
        :param passw: the password (pin+otp)
        :type passw: string
        :param options:  additional arguments from the request, which could be token specific
        :type options: dict
        :param challenges: A sorted list of valid challenges for this token.
        :type challenges: list
        :return: tuple of (otpcounter and the list of matching challenges)
        """
        otp_counter = -1
        transid = None
        matching = None
        matching_challenges = []

        # fetch the transactionid
        if 'transactionid' in options:
            transid = options.get('transactionid', None)

        # check if the transactionid is in the list of challenges
        if transid is not None:
            for challenge in challenges:
                if is_same_transaction(challenge, transid):
                    matching = challenge
                    break
            if matching is not None:
                # Split pin from otp and check the resulting pin and otpval
                (res, pin, otpval) = self.splitPinPass(passw)
                if not check_pin(self, pin, user=user, options=options):
                    otpval = passw
                # The U2F checkOtp functions needs to know the saved challenge
                # to compare the received challenge value to the saved one,
                # thus we add the transactionid to the options
                options['transactionid'] = transid
                options['challenges'] = challenges
                otp_counter = check_otp(self, otpval, options=options)
                if otp_counter >= 0:
                    matching_challenges.append(matching)

        return (otp_counter, matching_challenges)
Exemple #4
0
    def checkResponse4Challenge(self,
                                user,
                                passw,
                                options=None,
                                challenges=None):
        '''
        verify the response of a previous challenge

        :param user:     the requesting user
        :param passw:    the to be checked pass (pin+otp)
        :param options:  options an additional argument, which could be token
                          specific
        :param challenges: the list of challenges, where each challenge is
                            described as dict
        :return: tuple of (otpcounter and the list of matching challenges)

        '''
        otp_counter = -1
        transid = None
        matching = None
        matchin_challenges = []

        if 'transactionid' in options or 'state' in options:
            ## fetch the transactionid
            transid = options.get('transactionid', options.get('state', None))

        # check if the transactionid is in the list of challenges
        if transid is not None:
            for challenge in challenges:
                if is_same_transaction(challenge, transid):
                    matching = challenge
                    break
            if matching is not None:
                otp_counter = check_otp(self, passw, options=options)
                if otp_counter >= 0:
                    matchin_challenges.append(matching)

        return (otp_counter, matchin_challenges)
Exemple #5
0
    def checkResponse4Challenge(self,
                                user,
                                passw,
                                options=None,
                                challenges=None):
        """
        verify the response of a previous challenge

        There are two possible cases:

        1) The 'transaction_id' (also know as 'state', which has the same
           value) is available in options
        2) No 'transaction_id'

        In the first case we can safely assume that the passw only contains the OTP (no pin).
        In the second case passw will contain both and we split to get the OTP.

        :param user:     the requesting user
        :param passw:    the to be checked pass (pin+otp)
        :param options:  options an additional argument, which could be token
                          specific
        :param challenges: the list of challenges, where each challenge is
                            described as dict
        :return: tuple of (otpcounter and the list of matching challenges)

        """
        transaction_id = None
        otp_counter = -1
        matching_challenges = []

        if challenges is None or len(challenges) == 0:
            # There are no challenges for this token
            return -1, []

        if options and ('transactionid' in options or 'state' in options):
            ## fetch the transactionid
            transaction_id = options.get('transactionid', None)
            if transaction_id is None:
                transaction_id = options.get('state', None)

        if transaction_id:
            otp = passw
            # if the transaction_id is set we can assume that we have only received a single
            # challenge with that transaction_id thanks to
            # linotp.lib.validate.ValidateToken.get_challenges()
            assert (len(challenges) == 1)
            assert (is_same_transaction(challenges[0], transaction_id))
        else:
            # If no transaction_id is set the request came through the WebUI and
            # we have to check all challenges
            split_status, _, otp = split_pin_otp(self, passw, user, options)
            if split_status < 0:
                raise Exception("Could not split passw")

        window = self.getOtpCountWindow()

        for challenge in challenges:
            challenge_data = challenge.getData()
            stored_counter = challenge_data.get("counter_value")
            temp_otp_counter = self.checkOtp(otp, int(stored_counter), window,
                                             options)
            if temp_otp_counter > 0:
                otp_counter = temp_otp_counter
                matching_challenges = [challenge]
                break

        # The matching_challenges list will either contain a single challenge or will be empty.
        # Returning multiple challenges is not useful in this case because all older challenges are
        # cleaned up anyway.
        return otp_counter, matching_challenges
Exemple #6
0
    def checkResponse4Challenge(self, user, passw, options=None, challenges=None):
        """
        verify the response of a previous challenge

        There are two possible cases:

        1) The 'transaction_id' (also know as 'state', which has the same
           value) is available in options
        2) No 'transaction_id'

        In the first case we can safely assume that the passw only contains the OTP (no pin).
        In the second case passw will contain both and we split to get the OTP.

        :param user:     the requesting user
        :param passw:    the to be checked pass (pin+otp)
        :param options:  options an additional argument, which could be token
                          specific
        :param challenges: the list of challenges, where each challenge is
                            described as dict
        :return: tuple of (otpcounter and the list of matching challenges)

        """
        transaction_id = None
        otp_counter = -1
        matching_challenges = []

        if challenges is None or len(challenges) == 0:
            # There are no challenges for this token
            return -1, []

        if options and ('transactionid' in options or 'state' in options):
            ## fetch the transactionid
            transaction_id = options.get('transactionid', None)
            if transaction_id is None:
                transaction_id = options.get('state', None)

        if transaction_id:
            otp = passw
            # if the transaction_id is set we can assume that we have only received a single
            # challenge with that transaction_id thanks to
            # linotp.lib.validate.ValidateToken.get_challenges()
            assert(len(challenges) == 1)
            assert(is_same_transaction(challenges[0], transaction_id))
        else:
            # If no transaction_id is set the request came through the WebUI and
            # we have to check all challenges
            split_status, _, otp = split_pin_otp(self, passw, user, options)
            if split_status < 0:
                raise Exception("Could not split passw")

        window = self.getOtpCountWindow()

        for challenge in challenges:
            challenge_data = challenge.getData()
            stored_counter = challenge_data.get("counter_value")
            temp_otp_counter = self.checkOtp(otp, int(stored_counter), window, options)
            if temp_otp_counter > 0:
                otp_counter = temp_otp_counter
                matching_challenges = [challenge]
                break

        # The matching_challenges list will either contain a single challenge or will be empty.
        # Returning multiple challenges is not useful in this case because all older challenges are
        # cleaned up anyway.
        return otp_counter, matching_challenges