示例#1
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        check the otpval of a token against a given counter
        and the window

        :param passw: the to be verified passw/pin
        :type passw: string

        :return: counter if found, -1 if not found
        :rtype: int
        """
        options = options or {}
        ret = HotpTokenClass.check_otp(self, anOtpVal, counter, window,
                                       options)
        if ret < 0 and is_true(get_from_config("sms.concurrent_challenges")):
            if safe_compare(options.get("data"), anOtpVal):
                # We authenticate from the saved challenge
                ret = 1
        if ret >= 0 and self._get_auto_sms(options):
            # get message template from user specific policies
            message = self._get_sms_text(options)
            self.inc_otp_counter(ret, reset=False)
            success, message = self._send_sms(message=message, options=options)
            log.debug("AutoSMS: send new SMS: {0!s}".format(success))
            log.debug("AutoSMS: {0!r}".format(message))
        return ret
示例#2
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        check the otpval of a token against a given counter
        and the window

        :param passw: the to be verified passw/pin
        :type passw: string

        :return: counter if found, -1 if not found
        :rtype: int
        """
        options = options or {}
        ret = HotpTokenClass.check_otp(self, anOtpVal, counter, window,
                                       options)
        if ret < 0 and is_true(get_from_config("email.concurrent_challenges")):
            if safe_compare(options.get("data"), anOtpVal):
                # We authenticate from the saved challenge
                ret = 1
        if ret >= 0 and self._get_auto_email(options):
            message, mimetype = self._get_email_text_or_subject(options)
            subject, _ = self._get_email_text_or_subject(
                options, action=EMAILACTION.EMAILSUBJECT, default="Your OTP")
            self.inc_otp_counter(ret, reset=False)
            success, message = self._compose_email(message=message,
                                                   subject=subject,
                                                   mimetype=mimetype)
            log.debug("AutoEmail: send new SMS: {0!s}".format(success))
            log.debug("AutoEmail: {0!r}".format(message))
        return ret
示例#3
0
    def checkOtp(self, anOtpVal, window, symetric=False):
        """

        :param anOtpVal: The OTP value to check
        :type anOtpVal: str
        :param window:
        :param symetric:
        :return: -1 if the OTP doesn't match or the current counter
        :rtype: int
        """
        res = -1
        start = self.counter
        end = self.counter + window
        if symetric is True:
            # changed window/2 to window for TOTP
            start = self.counter - (window)
            start = 0 if (start < 0) else start
            end = self.counter + (window)

        log.debug("OTP range counter: {0!r} - {1!r}".format(start, end))
        for c in range(start, end):
            otpval = self.generate(c)
            #log.debug("calculating counter {0!r}".format(c))

            if safe_compare(otpval, anOtpVal):
                res = c
                break
        # return -1 or the counter
        return res
示例#4
0
    def checkOtp(self, anOtpVal, window=10, options=None):
        '''
        check a provided otp value

        :param anOtpVal: the to be tested otp value
        :type anOtpVal: str
        :param window: the +/- window around the test time
        :param options: generic container for additional values \
                        here only used for seltest: setting the initTime

        :return: -1 for fail else the identified counter/time 
        '''
        res = -1
        window = window * 2

        initTime = 0
        if options is not None and type(options) == dict:
            initTime = int(options.get('initTime', 0))

        if initTime == 0:
            otime = int(time.time() // 10)
        else:
            otime = initTime

        if self.secretObject is None:
            key = self.key
            pin = self.pin
        else:
            key = self.secretObject.getKey()
            pin = self.secPin.getKey()

        for i in range(otime - window, otime + window):
            otp = self.calcOtp(i, to_unicode(key), to_unicode(pin))
            if safe_compare(anOtpVal, otp):
                res = i
                log.debug("otpvalue {0!r} found at: {1!r}".format(
                    anOtpVal, res))
                break

        if self.secretObject is not None:
            zerome(key)
            zerome(pin)
            del key
            del pin

        ## prevent access twice with last motp
        if res <= self.oldtime:
            log.warning(
                "otpvalue {0!s} checked once before ({1!r}<={2!r})".format(
                    anOtpVal, res, self.oldtime))
            res = -1
        if res == -1:
            msg = 'checking motp failed'
        else:
            msg = 'checking motp sucess'

        log.debug("end. {0!s} : returning result: {1!r}, ".format(msg, res))
        return res
示例#5
0
        def check_password(self, password):
            """

            :param password:
            :type password: str
            :return: result of password check: 0 if success, -1 if failed
            :rtype: int
            """
            res = -1

            key = self.secretObject.getKey()
            # getKey() returns bytes and since we can not assume, that the
            # password only contains printable characters, we need to compare
            # bytes strings here. This also avoids making another copy of 'key'.
            if safe_compare(key, password):
                res = 0

            zerome(key)
            del key

            return res
示例#6
0
    def check_answer(self, given_answer, challenge_object):
        """
        Check if the given answer is the answer to the sent question.
        The question for this challenge response was stored in the
        challenge_object.

        Then we get the answer from the tokeninfo.

        :param given_answer: The answer given by the user
        :param challenge_object: The challenge object as stored in the database
        :return: in case of success: 1
        """
        res = -1
        question = challenge_object.challenge
        answer = self.get_tokeninfo(question)
        # We need to compare two unicode strings
        if safe_compare(answer, given_answer):
            res = 1
        else:
            log.debug("The answer for token {0!s} does not match.".format(
                self.get_serial()))
        return res
    def check_challenge_response(self, user=None, passw=None, options=None):
        """
        This method verifies if there is a matching challenge for the given
        passw and also verifies if the response is correct.

        It then returns 1 in case of success
        In case of failure it returns -1

        :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. Usually "transactionid"
        :type options: dict
        :return: return success
        :rtype: int
        """
        options = options or {}
        r_success = -1

        # fetch the transaction_id
        transaction_id = options.get('transaction_id')
        if transaction_id is None:
            transaction_id = options.get('state')

        # get the challenges for this transaction ID
        if transaction_id is not None:
            challengeobject_list = get_challenges(
                serial=self.token.serial, transaction_id=transaction_id)

            for challengeobject in challengeobject_list:

                if challengeobject.is_valid():
                    # challenge is still valid
                    # Add the challenge to the options for check_otp
                    options["challenge"] = challengeobject.challenge
                    options["data"] = [
                        int(c) for c in challengeobject.data.split(",")
                    ]
                    # Now see if the answer is the right indexes
                    secret_string = to_unicode(
                        self.token.get_otpkey().getKey())
                    if len(options["data"]) == len(passw):
                        expected_answer = "".join(
                            [secret_string[x - 1] for x in options["data"]])
                        if safe_compare(passw, expected_answer):
                            r_success = 1
                            # Set valid OTP to true. We must not delete the challenge now,
                            # Since we need it for further mutlichallenges
                            challengeobject.set_otp_status(True)
                            log.debug("The presented answer was correct.")
                            break
                        else:
                            log.debug("The presented answer was wrong.")
                            # increase the received_count
                            challengeobject.set_otp_status()
                    else:
                        log.debug(
                            "Length of password does not match the requested number of positions."
                        )
                        # increase the received_count
                        challengeobject.set_otp_status()

        self.challenge_janitor()
        return r_success