예제 #1
0
    def resync(self, otp1, otp2, options=None):
        """
        resync the token based on two otp values
        external method to do the resync of the token

        :param otp1: the first otp value
        :type otp1: string
        :param otp2: the second otp value
        :type otp2: string
        :param options: optional token specific parameters
        :type options:  dict or None
        :return: counter or -1 if otp does not exist
        :rtype:  int
        """
        ret = False
        options = options or {}
        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        log.debug("timestep: %r, syncWindow: %r, timeShift: %r"
                  % (self.timestep, self.timewindow, self.timeshift))

        initTime = int(options.get('initTime', -1))
        if initTime != -1:
            server_time = int(initTime)
        else:
            server_time = time.time() + self.timeshift

        counter = int((server_time / self.timestep) + 0.5)
        log.debug("counter (current time): %i" % counter)

        oCount = self.get_otp_count()

        log.debug("tokenCounter: %r" % oCount)
        log.debug("now checking window %s, timeStepping %s" %
                  (self.timewindow, self.timestep))
        # check 2nd value
        hmac2Otp = HmacOtp(secretHOtp,
                           counter,
                           otplen,
                           self.get_hashlib(self.hashlib))
        log.debug("%s in otpkey: %s " % (otp2, secretHOtp))
        res2 = hmac2Otp.checkOtp(otp2,
                                 int(self.timewindow / self.timestep),
                                 symetric=True)  # TEST -remove the 10
        log.debug("res 2: %r" % res2)
        # check 1st value
        hmac2Otp = HmacOtp(secretHOtp,
                           counter - 1,
                           otplen,
                           self.get_hashlib(self.hashlib))
        log.debug("%s in otpkey: %s " % (otp1, secretHOtp))
        res1 = hmac2Otp.checkOtp(otp1,
                                 int(self.timewindow / self.timestep),
                                 symetric=True)  # TEST -remove the 10
        log.debug("res 1: %r" % res1)

        if res1 < oCount:
            # A previous OTP value was used again!
            log.warning("a previous OTP value was used again! tokencounter: "
                        "%i, presented counter %i" %
                        (oCount, res1))
            res1 = -1

        if res1 != -1 and res1 + 1 == res2:
            # here we calculate the new drift/shift between the server time
            # and the tokentime
            tokentime = (res2 + 0.5) * self.timestep
            currenttime = server_time - self.timeshift
            new_shift = (tokentime - currenttime)
            log.debug("the counters %r and %r matched. New shift: %r"
                      % (res1, res2, new_shift))
            self.add_tokeninfo('timeShift', new_shift)

            # The OTP value that was used for resync must not be used again!
            self.set_otp_count(res2 + 1)

            ret = True

        if ret is True:
            msg = "resync was successful"
        else:
            msg = "resync was not successful"

        log.debug("end. %s: ret: %r" % (msg, ret))
        return ret
예제 #2
0
    def resync(self, otp1, otp2, options=None):
        """
        resync the token based on two otp values
        external method to do the resync of the token

        :param otp1: the first otp value
        :type otp1: string
        :param otp2: the second otp value
        :type otp2: string
        :param options: optional token specific parameters
        :type options:  dict or None
        :return: counter or -1 if otp does not exist
        :rtype:  int
        """
        ret = False
        options = options or {}
        otplen = int(self.token.otplen)
        secretHOtp = self.token.get_otpkey()

        log.debug(
            "timestep: {0!r}, syncWindow: {1!r}, timeShift: {2!r}".format(
                self.timestep, self.timewindow, self.timeshift))

        initTime = int(options.get('initTime', -1))
        if initTime != -1:
            server_time = int(initTime)
        else:
            server_time = time.time() + self.timeshift

        counter = int((server_time / self.timestep) + 0.5)
        log.debug("counter (current time): {0:d}".format(counter))

        oCount = self.get_otp_count()

        log.debug("tokenCounter: {0!r}".format(oCount))
        log.debug("now checking window {0!s}, timeStepping {1!s}".format(
            self.timewindow, self.timestep))
        # check 2nd value
        hmac2Otp = HmacOtp(secretHOtp, counter, otplen,
                           self.get_hashlib(self.hashlib))
        log.debug("{0!s} in otpkey: {1!s} ".format(otp2, secretHOtp))
        res2 = hmac2Otp.checkOtp(otp2,
                                 int(self.timewindow / self.timestep),
                                 symetric=True)  # TEST -remove the 10
        log.debug("res 2: {0!r}".format(res2))
        # check 1st value
        hmac2Otp = HmacOtp(secretHOtp, counter - 1, otplen,
                           self.get_hashlib(self.hashlib))
        log.debug("{0!s} in otpkey: {1!s} ".format(otp1, secretHOtp))
        res1 = hmac2Otp.checkOtp(otp1,
                                 int(self.timewindow / self.timestep),
                                 symetric=True)  # TEST -remove the 10
        log.debug("res 1: {0!r}".format(res1))

        if res1 < oCount:
            # A previous OTP value was used again!
            log.warning("a previous OTP value was used again! tokencounter: "
                        "%i, presented counter %i" % (oCount, res1))
            res1 = -1

        if res1 != -1 and res1 + 1 == res2:
            # here we calculate the new drift/shift between the server time
            # and the tokentime
            tokentime = (res2 + 0.5) * self.timestep
            currenttime = server_time - self.timeshift
            new_shift = (tokentime - currenttime)
            log.debug("the counters {0!r} and {1!r} matched. New shift: {2!r}".
                      format(res1, res2, new_shift))
            self.add_tokeninfo('timeShift', new_shift)

            # The OTP value that was used for resync must not be used again!
            self.set_otp_count(res2 + 1)

            ret = True

        if ret is True:
            msg = "resync was successful"
        else:
            msg = "resync was not successful"

        log.debug("end. {0!s}: ret: {1!r}".format(msg, ret))
        return ret
예제 #3
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        validate the token otp against a given otpvalue

        :param anOtpVal: the to be verified otpvalue
        :type anOtpVal:  string
        :param counter: the counter state, that should be verified. For TOTP
        this is the unix system time (seconds) divided by 30/60
        :type counter: int
        :param window: the counter +window (sec), which should be checked
        :type window: int
        :param options: the dict, which could contain token specific info
        :type options: dict
        :return: the counter or -1
        :rtype: int
        """
        otplen = int(self.token.otplen)
        options = options or {}
        secretHOtp = self.token.get_otpkey()
        # oldCounter we have to remove one, as the normal otp handling will
        # increment
        # TODO: Migration: Really?
        # oCount = self.get_otp_count() - 1
        oCount = self.get_otp_count()
        inow = int(time.time())
        window = window or self.timewindow

        initTime = int(options.get('initTime', -1))
        if initTime != -1:
            server_time = int(initTime)
        else:
            server_time = time.time() + self.timeshift

        # If we have a counter from the parameter list
        if not counter:
            # No counter, so we take the current token_time
            counter = self._time2counter(server_time,
                                         timeStepping=self.timestep)
        otime = self._getTimeFromCounter(oCount, timeStepping=self.timestep)
        ttime = self._getTimeFromCounter(counter, timeStepping=self.timestep)

        hmac2Otp = HmacOtp(secretHOtp,
                           counter,
                           otplen,
                           self.get_hashlib(self.hashlib))
        res = hmac2Otp.checkOtp(anOtpVal,
                                int(window / self.timestep),
                                symetric=True)

        if res != -1 and oCount != 0 and res <= oCount:
            log.warning("a previous OTP value was used again! former "
                        "tokencounter: %i, presented counter %i" %
                        (oCount, res))
            res = -1
            return res

        if -1 == res:
            # _autosync: test if two consecutive otps have been provided
            res = self._autosync(hmac2Otp, anOtpVal)

        if res != -1:
            # on success, we have to save the last attempt
            self.set_otp_count(res)
            # and we reset the fail counter
            self.reset()
            # We could also store it temporarily
            # self.auth_details["matched_otp_counter"] = res

            # here we calculate the new drift/shift between the server time
            # and the tokentime
            tokentime = self._counter2time(res, self.timestep)
            tokenDt = datetime.datetime.fromtimestamp(tokentime / 1.0)

            nowDt = datetime.datetime.fromtimestamp(inow / 1.0)

            lastauth = self._counter2time(oCount, self.timestep)
            lastauthDt = datetime.datetime.fromtimestamp(lastauth / 1.0)

            log.debug("last auth : %r" % lastauthDt)
            log.debug("tokentime : %r" % tokenDt)
            log.debug("now       : %r" % nowDt)
            log.debug("delta     : %r" % (tokentime - inow))

            new_shift = (tokentime - inow)
            log.debug("the counter %r matched. New shift: %r" %
                      (res, new_shift))
            self.add_tokeninfo('timeShift', new_shift)
        return res
예제 #4
0
    def check_otp(self, anOtpVal, counter=None, window=None, options=None):
        """
        validate the token otp against a given otpvalue

        :param anOtpVal: the to be verified otpvalue
        :type anOtpVal:  string
        :param counter: the counter state, that should be verified. For TOTP
        this is the unix system time (seconds) divided by 30/60
        :type counter: int
        :param window: the counter +window (sec), which should be checked
        :type window: int
        :param options: the dict, which could contain token specific info
        :type options: dict
        :return: the counter or -1
        :rtype: int
        """
        otplen = int(self.token.otplen)
        options = options or {}
        secretHOtp = self.token.get_otpkey()
        # oldCounter we have to remove one, as the normal otp handling will
        # increment
        # TODO: Migration: Really?
        # oCount = self.get_otp_count() - 1
        oCount = self.get_otp_count()
        inow = int(time.time())
        window = window or self.timewindow

        initTime = int(options.get('initTime', -1))
        if initTime != -1:
            server_time = int(initTime)
        else:
            server_time = time.time() + self.timeshift

        # If we have a counter from the parameter list
        if not counter:
            # No counter, so we take the current token_time
            counter = self._time2counter(server_time,
                                         timeStepping=self.timestep)
        otime = self._getTimeFromCounter(oCount, timeStepping=self.timestep)
        ttime = self._getTimeFromCounter(counter, timeStepping=self.timestep)

        hmac2Otp = HmacOtp(secretHOtp, counter, otplen,
                           self.get_hashlib(self.hashlib))
        res = hmac2Otp.checkOtp(anOtpVal,
                                int(window / self.timestep),
                                symetric=True)

        if res != -1 and oCount != 0 and res <= oCount:
            log.warning("a previous OTP value was used again! former "
                        "tokencounter: %i, presented counter %i" %
                        (oCount, res))
            res = -1
            return res

        if -1 == res:
            # _autosync: test if two consecutive otps have been provided
            res = self._autosync(hmac2Otp, anOtpVal)

        if res != -1:
            # on success, we have to save the last attempt
            self.set_otp_count(res)
            # We could also store it temporarily
            # self.auth_details["matched_otp_counter"] = res

            # here we calculate the new drift/shift between the server time
            # and the tokentime
            tokentime = self._counter2time(res, self.timestep)
            tokenDt = datetime.datetime.fromtimestamp(tokentime / 1.0)

            nowDt = datetime.datetime.fromtimestamp(inow / 1.0)

            lastauth = self._counter2time(oCount, self.timestep)
            lastauthDt = datetime.datetime.fromtimestamp(lastauth / 1.0)

            log.debug("last auth : {0!r}".format(lastauthDt))
            log.debug("tokentime : {0!r}".format(tokenDt))
            log.debug("now       : {0!r}".format(nowDt))
            log.debug("delta     : {0!r}".format((tokentime - inow)))

            new_shift = (tokentime - inow)
            log.debug("the counter {0!r} matched. New shift: {1!r}".format(
                res, new_shift))
            self.add_tokeninfo('timeShift', new_shift)
        return res