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 try: otplen = int(self.token.LinOtpOtpLen) except ValueError as ex: log.debug("[resync] otplen ValueError: %r ret: %r ", ex, ret) raise self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") secObj = self._get_secret_object() counter = self.token.getOtpCounter() syncWindow = self.token.getSyncWindow() # log.debug("serial: %s",serialNum) hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) counter = hmac2Otp.checkOtp(otp1, syncWindow) if counter == -1: log.debug("[resync] exit. First counter (-1) not found ret: %r", ret) return ret nextOtp = hmac2Otp.generate(counter + 1) if nextOtp != otp2: log.debug( "[resync] exit. Failed to verify second otp: nextOtp:" " %r != otp2: %r ret: %r", nextOtp, otp2, ret, ) return ret ret = True self.incOtpCounter(counter + 1, True) log.debug("Resync was successful") return ret
def resync(self, otp1, otp2, options=None, pin=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 ''' log.debug( "[resync] .begin. Resync the token based on: %r, anOtpVal: %r, options: %r" % (otp1, otp2, options)) ret = False try: otplen = int(self.token.LinOtpOtpLen) except ValueError as ex: log.debug("[resync] otplen ValueError: %r ret: %r " % (ex, ret)) raise Exception(ex) self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') secretHOtp = self.token.getHOtpKey(pin) counter = self.token.getOtpCounter() syncWindow = self.token.getSyncWindow() #log.debug("serial: %s",serialNum) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) counter = hmac2Otp.checkOtp(otp1, syncWindow) if counter == -1: log.debug("[resync] exit. First counter (-1) not found ret: %r" % (ret)) return ret nextOtp = hmac2Otp.generate(counter + 1) if nextOtp != otp2: log.debug( "[resync] exit. Failed to verify second otp: nextOtp: %r != otp2: %r ret: %r" % (nextOtp, otp2, ret)) return ret ret = True self.incOtpCounter(counter + 1, True) log.debug("[resync] end. resync was successful: ret: %r" % (ret)) return ret
def checkOtp(self, anOtpVal, counter, window, options=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' log.debug( "[checkOtp] begin. Validate the token otp: anOtpVal: %r ,counter: %r,window: %r, options: %r " % (anOtpVal, counter, window, options)) res = -1 try: otplen = int(self.getOtpLen()) except ValueError as ex: log.exception( '[checkOtp] failed to initialize otplen: ValueError %r %r' % (ex, self.token.LinOtpOtpLen)) raise Exception(ex) try: self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') except Exception as ex: log.exception('[checkOtp] failed to initialize hashlibStr: %r' % (ex)) raise Exception(ex) secretHOtp = self.token.getHOtpKey() #serialNum = self.token.LinOtpTokenSerialnumber #log.debug("serial: %s",serialNum) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(anOtpVal, window) if -1 == res: res = self.autosync(hmac2Otp, anOtpVal) log.debug("[checkOtp] end. otp verification result was: res %r" % (res)) return res
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 ''' log.debug("[resync] .begin. Resync the token based on: %r, anOtpVal: %r, options: %r" % (otp1, otp2, options)) ret = False try: otplen = int(self.token.LinOtpOtpLen) except ValueError as ex: log.debug("[resync] otplen ValueError: %r ret: %r " % (ex, ret)) raise Exception(ex) self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') secretHOtp = self.token.getHOtpKey() counter = self.token.getOtpCounter() syncWindow = self.token.getSyncWindow() #log.debug("serial: %s",serialNum) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) counter = hmac2Otp.checkOtp(otp1, syncWindow) if counter == -1: log.debug("[resync] exit. First counter (-1) not found ret: %r" % (ret)) return ret nextOtp = hmac2Otp.generate(counter + 1) if nextOtp != otp2: log.debug("[resync] exit. Failed to verify second otp: nextOtp: %r != otp2: %r ret: %r" % (nextOtp, otp2, ret)) return ret ret = True self.incOtpCounter(counter + 1, True) log.debug("[resync] end. resync was successful: ret: %r" % (ret)) return ret
def check_otp_exist(self, otp, window=10, user=None, autoassign=False): """ checks if the given OTP value is/are values of this very token. This is used to autoassign and to determine the serial number of a token. :param otp: the to be verified otp value :type otp: string :param window: the lookahead window for the counter :type window: int :return: counter or -1 if otp does not exist :rtype: int """ res = -1 try: otplen = int(self.token.LinOtpOtpLen) counter = int(self.token.LinOtpCount) except ValueError as ex: log.warning( "[check_otp_exist] a value error occurred while converting: " "otplen %r, counter %r : ValueError: %r ret: %r ", self.token.LinOtpOtpLen, self.token.LinOtpCount, ex, res, ) return res self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") secObj = self._get_secret_object() hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(otp, window) if res >= 0: # As usually the counter is increased in auth.validate.checkUserPass, we # need to do this manually here: self.incOtpCounter(res) if res == -1: msg = "otp counter %r was not found" % otp else: msg = "otp counter %r was found" % otp return res
def checkOtp(self, anOtpVal, counter, window, options=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' log.debug("[checkOtp] begin. Validate the token otp: anOtpVal: %r ,counter: %r,window: %r, options: %r " % (anOtpVal, counter, window, options)) res = -1 try: otplen = int(self.getOtpLen()) except ValueError as ex: log.exception('[checkOtp] failed to initialize otplen: ValueError %r %r' % (ex, self.token.LinOtpOtpLen)) raise Exception(ex) try: self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') except Exception as ex: log.exception('[checkOtp] failed to initialize hashlibStr: %r' % (ex)) raise Exception(ex) secretHOtp = self.token.getHOtpKey() #serialNum = self.token.LinOtpTokenSerialnumber #log.debug("serial: %s",serialNum) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(anOtpVal, window) if -1 == res: res = self.autosync(hmac2Otp, anOtpVal) log.debug("[checkOtp] end. otp verification result was: res %r" % (res)) return res
def checkOtp(self, anOtpVal, counter, window, options=None): """ checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int """ res = -1 try: otplen = int(self.getOtpLen()) except ValueError as ex: log.error( "[checkOtp] failed to initialize otplen: ValueError %r %r", ex, self.token.LinOtpOtpLen, ) raise try: self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") except Exception as ex: log.error("[checkOtp] failed to initialize hashlibStr: %r", ex) raise secObj = self._get_secret_object() hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(anOtpVal, window) if -1 == res: res = self.autosync(hmac2Otp, anOtpVal) return res
def check_otp_exist(self, otp, window=10): ''' checks if the given OTP value is/are values of this very token. This is used to autoassign and to determine the serial number of a token. :param otp: the to be verified otp value :type otp: string :param window: the lookahead window for the counter :type window: int :return: counter or -1 if otp does not exist :rtype: int ''' log.debug( "[check_otp_exist] begin. checks if the given OTP value exists: otp %r, window %r " % (otp, window)) res = -1 try: otplen = int(self.token.LinOtpOtpLen) counter = int(self.token.LinOtpCount) except ValueError as ex: log.warning( "[check_otp_exist] a value error occurred while converting: otplen %r, counter %r : ValueError: %r ret: %r " % (self.token.LinOtpOtpLen, self.token.LinOtpCount, ex, res)) return res self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") secretHOtp = self.token.getHOtpKey() hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(otp, window) if res >= 0: # As usually the counter is increased in lib.token.checkUserPass, we # need to do this manually here: self.incOtpCounter(res) if res == -1: msg = "otp counter %r was not found" % otp else: msg = "otp counter %r was found" % otp log.debug("[check_otp_exist] end. %r: res %r" % (msg, res)) return res
def check_otp_exist(self, otp, window=10, user=None, autoassign=False): ''' checks if the given OTP value is/are values of this very token. This is used to autoassign and to determine the serial number of a token. :param otp: the to be verified otp value :type otp: string :param window: the lookahead window for the counter :type window: int :return: counter or -1 if otp does not exist :rtype: int ''' log.debug("[check_otp_exist] begin. checks if the given OTP value exists: otp %r, window %r " % (otp, window)) res = -1 try: otplen = int(self.token.LinOtpOtpLen) counter = int(self.token.LinOtpCount) except ValueError as ex: log.warning("[check_otp_exist] a value error occurred while converting: otplen %r, counter %r : ValueError: %r ret: %r " % (self.token.LinOtpOtpLen, self.token.LinOtpCount, ex, res)) return res self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") secObj = self._get_secret_object() hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(otp, window) if res >= 0: # As usually the counter is increased in auth.validate.checkUserPass, we # need to do this manually here: self.incOtpCounter(res) if res == -1: msg = "otp counter %r was not found" % otp else: msg = "otp counter %r was found" % otp log.debug("[check_otp_exist] end. %r: res %r" % (msg, res)) return res
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 try: otplen = int(self.token.LinOtpOtpLen) except ValueError: return ret secObj = self._get_secret_object() self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') timeStepping = int(self.getFromTokenInfo("timeStep", 30)) shift = int(self.getFromTokenInfo("timeShift", 0)) try: window = int(self.token.LinOtpSyncWindow) * timeStepping except: window = 10 * timeStepping log.debug("[resync] timestep: %r, syncWindow: %r, timeShift: %r" % (timeStepping, window, shift)) T0 = time.time() + shift log.debug("[resync] T0 : %i" % T0) counter = int((T0 / timeStepping) + 0.5) # T = (Current Unix time - T0) / timeStepping log.debug("[resync] counter (current time): %i" % counter) oCount = self.getOtpCount() log.debug("[resync] tokenCounter: %r" % oCount) log.debug("[resync] now checking window %s, timeStepping %s" % (window, timeStepping)) # check 2nd value hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) log.debug("[resync] %s in otpkey: %s " % (otp2, secObj)) res2 = hmac2Otp.checkOtp(otp2, int(window / timeStepping), symetric=True) #TEST -remove the 10 log.debug("[resync] res 2: %r" % res2) # check 1st value hmac2Otp = HmacOtp(secObj, counter - 1, otplen, self.getHashlib(self.hashlibStr)) log.debug("[resync] %s in otpkey: %s " % (otp1, secObj)) res1 = hmac2Otp.checkOtp(otp1, int(window / timeStepping), symetric=True) #TEST -remove the 10 log.debug("[resync] res 1: %r" % res1) if res1 < oCount: # A previous OTP value was used again! log.warning( "[resync] 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) * timeStepping currenttime = T0 - shift new_shift = (tokentime - currenttime) log.debug( "[resync] the counters %r and %r matched. New shift: %r" % (res1, res2, new_shift)) self.addToTokenInfo('timeShift', new_shift) # The OTP value that was used for resync must not be used again! self.setOtpCount(res2 + 1) ret = True if ret is True: msg = "resync was successful" else: msg = "resync was not successful" log.debug(msg) return ret
def checkOtp(self, anOtpVal, counter, window, options=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' try: otplen = int(self.token.LinOtpOtpLen) except ValueError as e: raise e secObj = self._get_secret_object() self.hashlibStr = self.getFromTokenInfo("hashlib", self.hashlibStr) or 'sha1' timeStepping = int( self.getFromTokenInfo("timeStep", self.timeStep) or 30) window = int( self.getFromTokenInfo("timeWindow", self.timeWindow) or 180) shift = int(self.getFromTokenInfo("timeShift", self.timeShift) or 0) ## oldCounter we have to remove one, as the normal otp handling will increment oCount = self.getOtpCount() - 1 initTime = -1 if options is not None and type(options) == dict: initTime = int(options.get('initTime', -1)) if oCount < 0: oCount = 0 log.debug("[checkOTP] timestep: %i, timeWindow: %i, timeShift: %i" % (timeStepping, window, shift)) inow = int(time.time()) T0 = time.time() + shift if initTime != -1: T0 = int(initTime) counter = self._time2counter_(T0, timeStepping=timeStepping) hmac2Otp = HmacOtp(secObj, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(anOtpVal, int(window / timeStepping), symetric=True) if res != -1 and oCount != 0 and res <= oCount: if initTime == -1: log.warning( "[checkOTP] a previous OTP value was used again!\n 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.setOtpCount(counter) # # here we calculate the new drift/shift between the server time and the tokentime # tokentime = self._counter2time_(res, timeStepping) tokenDt = datetime.datetime.fromtimestamp(tokentime / 1.0) nowDt = datetime.datetime.fromtimestamp(inow / 1.0) # reverse time mapping: # from time to counter to timeStepping mapped timeslot lastauth = self._counter2time_(oCount, timeStepping) lastauthDt = datetime.datetime.fromtimestamp(lastauth / 1.0) log.debug("[checkOTP] last auth : %r" % (lastauthDt)) log.debug("[checkOTP] tokentime : %r" % (tokenDt)) log.debug("[checkOTP] now : %r" % (nowDt)) log.debug("[checkOTP] delta : %r" % (tokentime - inow)) inow_counter = self._time2counter_(inow, timeStepping) inow_token_time = self._counter2time_(inow_counter, timeStepping) new_shift = (tokentime - inow_token_time) log.debug("[checkOTP] the counter %r matched. New shift: %r" % (res, new_shift)) self.addToTokenInfo('timeShift', new_shift) log.debug("[checkOtp] end. otp verification result was: res %r" % (res)) return res
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 ''' log.debug("[resync] .begin. Resync the token based on: %r, anOtpVal: %r, options: %r" % (otp1, otp2, options)) ret = False try: otplen = int(self.token.LinOtpOtpLen) except ValueError: return ret secretHOtp = self.token.getHOtpKey() self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1') timeStepping = int(self.getFromTokenInfo("timeStep", 30)) shift = int(self.getFromTokenInfo("timeShift", 0)) try: window = int(self.token.LinOtpSyncWindow) * timeStepping except: window = 10 * timeStepping log.debug("[resync] timestep: %r, syncWindow: %r, timeShift: %r" % (timeStepping, window, shift)) T0 = time.time() + shift log.debug("[resync] T0 : %i" % T0) counter = int((T0 / timeStepping) + 0.5) # T = (Current Unix time - T0) / timeStepping log.debug("[resync] counter (current time): %i" % counter) oCount = self.getOtpCount() log.debug("[resync] tokenCounter: %r" % oCount) log.debug("[resync] now checking window %s, timeStepping %s" % (window, timeStepping)) # check 2nd value hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) log.debug("[resync] %s in otpkey: %s " % (otp2, secretHOtp)) res2 = hmac2Otp.checkOtp(otp2, int (window / timeStepping), symetric=True) #TEST -remove the 10 log.debug("[resync] res 2: %r" % res2) # check 1st value hmac2Otp = HmacOtp(secretHOtp, counter - 1, otplen, self.getHashlib(self.hashlibStr)) log.debug("[resync] %s in otpkey: %s " % (otp1, secretHOtp)) res1 = hmac2Otp.checkOtp(otp1, int (window / timeStepping), symetric=True) #TEST -remove the 10 log.debug("[resync] res 1: %r" % res1) if res1 < oCount: # A previous OTP value was used again! log.warning("[resync] 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) * timeStepping currenttime = T0 - shift new_shift = (tokentime - currenttime) log.debug("[resync] the counters %r and %r matched. New shift: %r" % (res1, res2, new_shift)) self.addToTokenInfo('timeShift', new_shift) # The OTP value that was used for resync must not be used again! self.setOtpCount(res2 + 1) ret = True if ret == True: msg = "resync was successful" else: msg = "resync was not successful" log.debug("[resync] end. %s: ret: %r" % (msg, ret)) return ret
def checkOtp(self, anOtpVal, counter, window, options=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' log.debug("[checkOtp] begin. Validate the token otp: anOtpVal: %r ,\ counter: %r,window: %r, options: %r " % (anOtpVal, counter, window, options)) try: otplen = int(self.token.LinOtpOtpLen) except ValueError as e: raise e secretHOtp = self.token.getHOtpKey() self.hashlibStr = self.getFromTokenInfo("hashlib", self.hashlibStr) timeStepping = int(self.getFromTokenInfo("timeStep", self.timeStep)) window = int(self.getFromTokenInfo("timeWindow", self.timeWindow)) shift = int(self.getFromTokenInfo("timeShift", self.timeShift)) ## oldCounter we have to remove one, as the normal otp handling will increment oCount = self.getOtpCount() - 1 initTime = -1 if options != None and type(options) == dict: initTime = int(options.get('initTime', -1)) if oCount < 0: oCount = 0 log.debug("[checkOTP] timestep: %i, timeWindow: %i, timeShift: %i" % (timeStepping, window, shift)) inow = int(time.time()) T0 = time.time() + shift if initTime != -1: T0 = int(initTime) log.debug("[checkOTP] T0 : %i" % T0) counter = self._time2counter_(T0, timeStepping=timeStepping) otime = self._getTimeFromCounter(oCount, timeStepping=timeStepping) ttime = self._getTimeFromCounter(counter, timeStepping=timeStepping) log.debug("[checkOTP] last log: %r :: %r" % (oCount, otime)) log.debug("[checkOTP] counter : %r :: %r <==> %r" % (counter, ttime, datetime.datetime.now())) log.debug("[checkOTP] shift : %r " % (shift)) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) res = hmac2Otp.checkOtp(anOtpVal, int (window / timeStepping), symetric=True) log.debug("[checkOTP] comparing the result %i to the old counter %i." % (res, oCount)) if res != -1 and oCount != 0 and res <= oCount: if initTime == -1: log.warning("[checkOTP] a previous OTP value was used again!\n 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.setOtpCount(counter) # # here we calculate the new drift/shift between the server time and the tokentime # tokentime = self._counter2time_(res, timeStepping) tokenDt = datetime.datetime.fromtimestamp(tokentime / 1.0) nowDt = datetime.datetime.fromtimestamp(inow / 1.0) lastauth = self._counter2time_(oCount, timeStepping) lastauthDt = datetime.datetime.fromtimestamp(lastauth / 1.0) log.debug("[checkOTP] last auth : %r" % (lastauthDt)) log.debug("[checkOTP] tokentime : %r" % (tokenDt)) log.debug("[checkOTP] now : %r" % (nowDt)) log.debug("[checkOTP] delta : %r" % (tokentime - inow)) new_shift = (tokentime - inow) log.debug("[checkOTP] the counter %r matched. New shift: %r" % (res, new_shift)) self.addToTokenInfo('timeShift', new_shift) log.debug("[checkOtp] end. otp verification result was: res %r" % (res)) return res
def get_otp_detail(self, otp, window='24h'): """ provide information belonging to one otp :param otp: the otp for which the timestamp is searched :param window: string, in human readable '2h' or iso8601 format 'PT2H' """ from linotp.lib.type_utils import parse_duration window = parse_duration(window).total_seconds() # ------------------------------------------------------------------ -- time_step = self.timeStepping T0 = time.time() + self.shift counter = time2counter(T0, timeStepping=time_step) # ------------------------------------------------------------------ -- # prepare the hmac operation secObj = self._get_secret_object() hmac2Otp = HmacOtp( secObj, counter, self.otplen, self.getHashlib(self.hashlibStr)) matching_counter = hmac2Otp.checkOtp( otp, int(window // time_step), symetric=True) # ------------------------------------------------------------------ -- # matching_counter =-1 : no otp found in the current time frame if matching_counter == -1: log.info('no matching otp found in window: %r', window) return False, None # ------------------------------------------------------------------ -- # do not provide information of otps in the future if matching_counter >= counter: log.info('otp is in future - no info for future otps') return False, None # ------------------------------------------------------------------ -- # all fine - now return the time stamp and the utc time format time_stamp = counter2time( matching_counter, timeStepping=time_step) time_info = datetime.datetime.utcfromtimestamp(time_stamp) return True, { 'serial' : self.getSerial(), 'otp': otp, 'counter': matching_counter, 'time': time_info.isoformat(), 'seconds': int(time_stamp), 'span': time_step, }
def checkOtp(self, anOtpVal, counter, window, options=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' # convert the window counter into seconds totp_window = window * self.timeStepping T0 = time.time() + self.shift counter = time2counter(T0, timeStepping=self.timeStepping) # ------------------------------------------------------------------ -- # setup the hmac object, which encapsulates the secret context secObj = self._get_secret_object() hmac2Otp = HmacOtp( secObj, counter, self.otplen, self.getHashlib(self.hashlibStr)) # ------------------------------------------------------------------ -- otp_match_counter = hmac2Otp.checkOtp( anOtpVal, int(totp_window // self.timeStepping), symetric=True) # ------------------------------------------------------------------ -- # protect against a replay # if the counter belonging to the provided otp is lower than the # stored counter (which is the next expected counter), then we deny # as it might be replay if otp_match_counter != -1 and otp_match_counter < self.getOtpCount(): log.warning("a previous OTP value was used again!") return -1 # ------------------------------------------------------------------ -- # the otp might be out of the test window so we try to autosync: # look if two consecutive otps has been provided if otp_match_counter == -1: otp_match_counter = self.autosync(hmac2Otp, anOtpVal) if otp_match_counter == -1: log.debug("otp verification failed!") return -1 # ------------------------------------------------------------------ -- # on success, we have to save the timeshift and matching otp counter self.set_new_timeshift(otp_match_counter) # and the matching otp counter self.setOtpCount(otp_match_counter) log.debug("otp verification result was: res %r", otp_match_counter) return otp_match_counter
def checkOtp(self, anOtpVal, counter, window, options=None, pin=None): ''' checkOtp - 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 :type counter: int :param window: the counter +window, which should be checked :type window: int :param options: the dict, which could contain token specific info :type options: dict :return: the counter state or -1 :rtype: int ''' log.debug("[checkOtp] begin. Validate the token otp: anOtpVal: %r ,\ counter: %r,window: %r, options: %r " % (anOtpVal, counter, window, options)) try: otplen = int(self.token.LinOtpOtpLen) except ValueError as e: raise e secretHOtp = self.token.getHOtpKey(pin) self.hashlibStr = self.getFromTokenInfo("hashlib", self.hashlibStr) timeStepping = int(self.getFromTokenInfo("timeStep", self.timeStep)) window = int(self.getFromTokenInfo("timeWindow", self.timeWindow)) shift = int(self.getFromTokenInfo("timeShift", self.timeShift)) ## oldCounter we have to remove one, as the normal otp handling will increment oCount = self.getOtpCount() - 1 initTime = -1 if options != None and type(options) == dict: initTime = int(options.get('initTime', -1)) if oCount < 0: oCount = 0 log.debug("[checkOTP] timestep: %i, timeWindow: %i, timeShift: %i" % (timeStepping, window, shift)) inow = int(time.time()) T0 = time.time() + shift if initTime != -1: T0 = int(initTime) log.debug("[checkOTP] T0 : %i" % T0) counter = self._time2counter_(T0, timeStepping=timeStepping) otime = self._getTimeFromCounter(oCount, timeStepping=timeStepping) ttime = self._getTimeFromCounter(counter, timeStepping=timeStepping) log.debug("[checkOTP] last log: %r :: %r" % (oCount, otime)) log.debug("[checkOTP] counter : %r :: %r <==> %r" % (counter, ttime, datetime.datetime.now())) log.debug("[checkOTP] shift : %r " % (shift)) hmac2Otp = HmacOtp(secretHOtp, counter, otplen, self.getHashlib(self.hashlibStr)) log.debug("got hmac") res = hmac2Otp.checkOtp(anOtpVal, int(window / timeStepping), symetric=True) log.warning( "[checkOTP] comparing the result %i to the old counter %i." % (res, oCount)) if res != -1 and oCount != 0 and res <= oCount: if initTime == -1: log.warning( "[checkOTP] a previous OTP value was used again!\n former tokencounter: %i, presented counter %i" % (oCount, res)) res = -2 # return something different so we can tell them their code is being reused 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.setOtpCount(counter) # # here we calculate the new drift/shift between the server time and the tokentime # tokentime = self._counter2time_(res, timeStepping) tokenDt = datetime.datetime.fromtimestamp(tokentime / 1.0) nowDt = datetime.datetime.fromtimestamp(inow / 1.0) lastauth = self._counter2time_(oCount, timeStepping) lastauthDt = datetime.datetime.fromtimestamp(lastauth / 1.0) log.debug("[checkOTP] last auth : %r" % (lastauthDt)) log.debug("[checkOTP] tokentime : %r" % (tokenDt)) log.debug("[checkOTP] now : %r" % (nowDt)) log.debug("[checkOTP] delta : %r" % (tokentime - inow)) new_shift = (tokentime - inow) log.debug("[checkOTP] the counter %r matched. New shift: %r" % (res, new_shift)) self.addToTokenInfo('timeShift', new_shift) log.debug("[checkOtp] end. otp verification result was: res %r" % (res)) return res