Ejemplo n.º 1
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        '''
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        '''
        log.debug("[get_multi_otp] begin. Get a dictionary of multiple future OTP values for: count: %r, epoch_start: %r, epoch_end: %r, curTime: %r" %
                  (count, epoch_start, epoch_end, curTime))

        otp_dict = {"type" : "HMAC", "otp": {}}
        ret = False
        error = "No count specified"
        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error("[get_multi_otp]: Could not convert otplen - value error %r " % (ex))
            raise Exception(ex)

        secretHOtp = self.token.getHOtpKey()
        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen, self.getHashlib(self.hashlibStr))
        log.debug("[get_multi_otp] retrieving %i OTP values for token %s" % (count, hmac2Otp))

        if count > 0:
            for i in range(count):
                otpval = hmac2Otp.generate(self.getOtpCount() + i, inc_counter=False)
                otp_dict["otp"][i] = otpval
            ret = True

        log.debug("[get_multi_otp] end. dictionary of multiple future OTP is: otp_dict: %r - status: %r - error %r" % (ret, error, otp_dict))
        return (ret, error, otp_dict)
Ejemplo n.º 2
0
    def _calc_otp(self, input_data):
        """
        Calculates an otp by using an hmac algorithm with seed and
        input_data

        :param input_data: data used in hmac

        :return: otp value
        """

        # get otp length from stored token in database
        try:
            otp_length = int(self.token.LinOtpOtpLen)
        except ValueError as value_error_ex:
            log.exception('[getOTP]: Could not convert otplen - value error '
                          '%r' % (value_error_ex))
            raise value_error_ex

        # get otp for data using secret object and hotp algorithm
        secret_object = self._get_secret_object()
        hmac_otp_obj = HmacOtp(secret_object, input_data, otp_length,
                               self.getHashlib(self.hashlibStr))
        otp_value = hmac_otp_obj.generate(inc_counter=False)

        return otp_value
Ejemplo n.º 3
0
    def getNextOtp(self):
        '''
        access the nex validf otp

        :return: otpval
        :rtype: string
        '''
        log.debug("[getNextOtp] begin. starting to look for the next otp")

        try:
            ### TODO - replace tokenLen
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error("[getNextOtp] ValueError %r" % ex)
            raise Exception(ex)

        secret_obj = self.token.getHOtpKey()
        counter = self.token.getOtpCounter()

        #log.debug("serial: %s",serialNum)
        hmac2otp = HmacOtp(secret_obj, counter, otplen)
        nextotp = hmac2otp.generate(counter + 1)


        log.debug("[getNextOtp] end. got the next otp value: nextOtp %r"
                                                                    % nextotp)
        return nextotp
Ejemplo n.º 4
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''
        log.debug("[getOtp] begin. Get the next OTP value for: curTime: %r" %
                  (curTime))

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error("[getOtp]: Could not convert otplen - value error %r " %
                      (ex))
            raise Exception(ex)

        self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1')
        secretHOtp = self.token.getHOtpKey()

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))
        otpval = hmac2Otp.generate(inc_counter=False)

        pin = self.token.getPin()
        combined = "%s%s" % (otpval, pin)

        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        log.debug(
            "[getOtp]  end. Return opt is: (pin: %r, otpval: %r, combined: %r) "
            % (pin, otpval, combined))
        return (1, pin, otpval, combined)
Ejemplo n.º 5
0
    def _getNextOtp(self):
        """
        access the nex valid otp

        :return: otpval
        :rtype: string
        """
        LOG.debug("[getNextOtp] begin. starting to look for the next otp")

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            LOG.error("[getNextOtp] ValueError %r" % ex)
            raise Exception(ex)

        secret_obj = self.token.getHOtpKey()
        counter = self.token.getOtpCounter()

        #log.debug("serial: %s",serialNum)
        hmac2otp = HmacOtp(secret_obj, counter, otplen)
        nextotp = hmac2otp.generate(counter + 1)

        LOG.debug("[getNextOtp] end. got the next otp value: nextOtp %r" %
                  nextotp)
        return nextotp
Ejemplo n.º 6
0
    def _getNextOtp(self):
        """
        access the nex valid otp

        :return: otpval
        :rtype: string
        """
        LOG.debug("[getNextOtp] begin. starting to look for the next otp")

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            LOG.error("[getNextOtp] ValueError %r" % ex)
            raise Exception(ex)

        secObj = self._get_secret_object()
        counter = self.token.getOtpCounter()

        #log.debug("serial: %s",serialNum)
        hmac2otp = HmacOtp(secObj, counter, otplen)
        nextotp = hmac2otp.generate(counter + 1)

        LOG.debug("[getNextOtp] end. got the next otp value: nextOtp %r"
                  % nextotp)
        return nextotp
Ejemplo n.º 7
0
    def get_otp(self, counter):
        """
        Get next otp value with the given data used as counter for hotp
        algorithm

        :param counter: data to give as counter into the hotp algorithm
        :type counter: base64 encoded string

        :return: otp value
        """

        # get otp length from stored token in database
        try:
            otp_length = int(self.token.LinOtpOtpLen)
        except ValueError as value_error_ex:
            log.exception('[getOTP]: Could not convert otplen - value error '
                          '%r' % (value_error_ex))
            raise value_error_ex

        # get otp for data using secret object and hotp algorithm
        secret_object = self._get_secret_object()
        hmac_otp_obj = HmacOtp(secret_object, counter, otp_length,
                               self.getHashlib(self.hashlibStr))
        otp_value = hmac_otp_obj.generate(inc_counter=False)

        return otp_value
Ejemplo n.º 8
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        '''
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        '''

        otp_dict = {"type": "HMAC", "otp": {}}
        ret = False
        error = "No count specified"
        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.exception(
                "[get_multi_otp]: Could not convert otplen - value error %r " %
                (ex))
            raise Exception(ex)
        s_count = self.getOtpCount()
        secObj = self._get_secret_object()
        hmac2Otp = HmacOtp(secObj, s_count, otplen,
                           self.getHashlib(self.hashlibStr))

        if count > 0:
            for i in range(count):
                otpval = hmac2Otp.generate(s_count + i, inc_counter=False)
                otp_dict["otp"][s_count + i] = otpval
            ret = True

        return (ret, error, otp_dict)
Ejemplo n.º 9
0
    def getNextOtp(self):
        '''
        access the nex validf otp

        :return: otpval
        :rtype: string
        '''
        log.debug("[getNextOtp] begin. starting to look for the next otp")

        try:
            # ## TODO - replace tokenLen
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.exception("[getNextOtp] ValueError %r" % ex)
            raise Exception(ex)

        secObj = self._get_secret_object()
        counter = self.token.getOtpCounter()

        # log.debug("serial: %s",serialNum)
        hmac2otp = HmacOtp(secObj, counter, otplen)
        nextotp = hmac2otp.generate(counter + 1)

        log.debug("[getNextOtp] end. got the next otp value: nextOtp %r" %
                  nextotp)
        return nextotp
Ejemplo n.º 10
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.exception(
                "[getOtp]: Could not convert otplen - value error %r " % (ex))
            raise Exception(ex)

        self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1')
        secObj = self._get_secret_object()

        hmac2Otp = HmacOtp(secObj, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))
        otpval = hmac2Otp.generate(inc_counter=False)

        pin = self.getPin()
        combined = "%s%s" % (otpval, pin)

        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        return (1, pin, otpval, combined)
Ejemplo n.º 11
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''

        res = (-1, 0, 0, 0)

        otplen = int(self.token.LinOtpOtpLen)
        secObj = self._get_secret_object()

        self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") or 'sha1'
        timeStepping = int(self.getFromTokenInfo("timeStep", 30) or 30)
        shift = int(self.getFromTokenInfo("timeShift", 0) or 0)

        hmac2Otp = HmacOtp(secObj, self.getOtpCount(), otplen, self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))
        otpval = hmac2Otp.generate(counter=counter, inc_counter=False)

        pin = self.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        return (1, pin, otpval, combined)
Ejemplo n.º 12
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''

        res = (-1, 0, 0, 0)

        otplen = int(self.token.LinOtpOtpLen)
        secObj = self._get_secret_object()

        self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") or 'sha1'
        timeStepping = int(self.getFromTokenInfo("timeStep", 30) or 30)
        shift = int(self.getFromTokenInfo("timeShift", 0) or 0)

        hmac2Otp = HmacOtp(secObj, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))
        otpval = hmac2Otp.generate(counter=counter, inc_counter=False)

        pin = self.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        return (1, pin, otpval, combined)
Ejemplo n.º 13
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''
        log.debug("[getOtp] begin. Get the next OTP value for: curTime: %r" % (curTime))

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error("[getOtp]: Could not convert otplen - value error %r " % (ex))
            raise Exception(ex)

        self.hashlibStr = self.getFromTokenInfo("hashlib", 'sha1')
        secretHOtp = self.token.getHOtpKey()

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen, self.getHashlib(self.hashlibStr))
        otpval = hmac2Otp.generate(inc_counter=False)

        pin = self.token.getPin()
        combined = "%s%s" % (otpval, pin)

        if getFromConfig("PrependPin") == "True" :
            combined = "%s%s" % (pin, otpval)

        log.debug("[getOtp]  end. Return opt is: (pin: %r, otpval: %r, combined: %r) " %
                  (pin, otpval, combined))
        return (1, pin, otpval, combined)
Ejemplo n.º 14
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

        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
Ejemplo n.º 15
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        '''
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        '''
        log.debug(
            "[get_multi_otp] begin. Get a dictionary of multiple future OTP values for: count: %r, epoch_start: %r, epoch_end: %r, curTime: %r"
            % (count, epoch_start, epoch_end, curTime))

        otp_dict = {"type": "TOTP", "otp": {}}
        ret = False
        error = "No count specified"
        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))

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))

        otp_dict["shift"] = shift
        otp_dict["timeStepping"] = timeStepping

        if count > 0:
            for i in range(0, count):
                otpval = hmac2Otp.generate(counter=counter + i,
                                           inc_counter=False)
                timeCounter = ((counter + i) * timeStepping) + shift
                otp_dict["otp"][counter + i] = {
                    'otpval':
                    otpval,
                    'time':
                    datetime.datetime.fromtimestamp(timeCounter).strftime(
                        "%Y-%m-%d %H:%M:%S"),
                }
            ret = True

        log.debug(
            "[get_multi_otp] end. dictionary of multiple future OTP is: otp_dict: %r - status: %r - error %r"
            % (ret, error, otp_dict))
        return (ret, error, otp_dict)
Ejemplo n.º 16
0
    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
Ejemplo n.º 17
0
    def get_otp(self, counter: int) -> str:
        """
        calculate the otp from a given counter

        :param counter: a given counter
        :return: the otp string
        """
        hmac = HmacOtp(digits=self.otplen, hashfunc=self.hashlib)
        return hmac.generate(counter=counter,
                             key=binascii.unhexlify(self.otpkey))
Ejemplo n.º 18
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        """
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        """

        otp_dict = {"type": "TOTP", "otp": {}}
        ret = False
        error = "No count specified"
        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError:
            return ret

        secObj = self._get_secret_object()
        self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1") or "sha1"
        timeStepping = int(self.getFromTokenInfo("timeStep", 30) or 30)
        shift = int(self.getFromTokenInfo("timeShift", 0) or 0)

        hmac2Otp = HmacOtp(
            secObj,
            self.getOtpCount(),
            otplen,
            self.getHashlib(self.hashlibStr),
        )

        tCounter = self.time2float(datetime.datetime.utcnow())
        if curTime:
            tCounter = self.time2float(curTime)

        counter = int((tCounter - shift) // timeStepping)

        otp_dict["shift"] = shift
        otp_dict["timeStepping"] = timeStepping

        if count > 0:
            for i in range(0, count):
                otpval = hmac2Otp.generate(counter=counter + i,
                                           inc_counter=False)
                timeCounter = ((counter + i) * timeStepping) + shift
                otp_dict["otp"][counter + i] = {
                    "otpval":
                    otpval,
                    "time":
                    datetime.datetime.utcfromtimestamp(timeCounter).strftime(
                        "%Y-%m-%d %H:%M:%S"),
                }
            ret = True

        return (ret, error, otp_dict)
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        '''
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        '''
        log.debug("[get_multi_otp] begin. Get a dictionary of multiple future OTP values for: count: %r, epoch_start: %r, epoch_end: %r, curTime: %r" %
                  (count, epoch_start, epoch_end, curTime))

        otp_dict = {"type" : "TOTP", "otp": {}}
        ret = False
        error = "No count specified"
        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))

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(),
                           otplen, self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))


        otp_dict["shift"] = shift
        otp_dict["timeStepping"] = timeStepping

        if count > 0:
            for i in range(0, count):
                otpval = hmac2Otp.generate(counter=counter + i, inc_counter=False)
                timeCounter = ((counter + i) * timeStepping) + shift
                otp_dict["otp"][ counter + i] = {
                     'otpval' : otpval,
                     'time'  : datetime.datetime.fromtimestamp(timeCounter).strftime("%Y-%m-%d %H:%M:%S"),
                    }
            ret = True

        log.debug("[get_multi_otp] end. dictionary of multiple future OTP is: otp_dict: %r - status: %r - error %r" % (ret, error, otp_dict))
        return (ret, error, otp_dict)
Ejemplo n.º 21
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

        '''
        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
Ejemplo n.º 22
0
def get_otp(key, counter, digits=8, hashfunc=sha1):
    """
    calculate otp from a given counter

    :param key: the token seed in hexlified format
    :param counter: the given counter == time equivalent
    :param digits: number of digits in the otp
    :param hashfunc: the hash method used in the hmac calculation
    :return: otp value
    """
    hmac = LinHmacOTP(digits=digits, hashfunc=hashfunc)
    otp = hmac.generate(counter=counter, key=binascii.unhexlify(key))
    return otp
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
def calc_totp_OTP(key, digits=6, timestep=30):
    '''

    :param key: the otpkey secret
    :param digits: the number of to be returned digits
    :param timestep: the time stepping 60 or 30 sec

    :return: the otp value as string
    '''
    htoken = HmacOtp(digits=digits)
    counter = int((time.time() / timestep) + 0.5)
    otp = htoken.generate(counter=counter, key=binascii.unhexlify(key))

    return otp
Ejemplo n.º 25
0
def calc_totp_OTP(key, digits=6, timestep=30):
    '''

    :param key: the otpkey secret
    :param digits: the number of to be returned digits
    :param timestep: the time stepping 60 or 30 sec

    :return: the otp value as string
    '''
    htoken = HmacOtp(digits=digits)
    counter = int((time.time() / timestep) + 0.5)
    otp = htoken.generate(counter=counter, key=binascii.unhexlify(key))

    return otp
Ejemplo n.º 26
0
    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
Ejemplo n.º 27
0
    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
Ejemplo n.º 28
0
    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
Ejemplo n.º 29
0
    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
Ejemplo n.º 30
0
    def get_multi_otp(self, count=0, epoch_start=0, epoch_end=0, curTime=None):
        '''
        return a dictionary of multiple future OTP values of the HOTP/HMAC token

        :param count:   how many otp values should be returned
        :type count:    int

        :return:     tuple of status: boolean, error: text and the OTP dictionary

        '''
        log.debug(
            "[get_multi_otp] begin. Get a dictionary of multiple future OTP values for: count: %r, epoch_start: %r, epoch_end: %r, curTime: %r"
            % (count, epoch_start, epoch_end, curTime))

        otp_dict = {"type": "HMAC", "otp": {}}
        ret = False
        error = "No count specified"
        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error(
                "[get_multi_otp]: Could not convert otplen - value error %r " %
                (ex))
            raise Exception(ex)

        secretHOtp = self.token.getHOtpKey()
        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))
        log.debug("[get_multi_otp] retrieving %i OTP values for token %s" %
                  (count, hmac2Otp))

        if count > 0:
            for i in range(count):
                otpval = hmac2Otp.generate(self.getOtpCount() + i,
                                           inc_counter=False)
                otp_dict["otp"][i] = otpval
            ret = True

        log.debug(
            "[get_multi_otp] end. dictionary of multiple future OTP is: otp_dict: %r - status: %r - error %r"
            % (ret, error, otp_dict))
        return (ret, error, otp_dict)
Ejemplo n.º 31
0
def calcOTP(key, counter=0, digits=6, typ=None):
    '''
    as we have to use this method in a not class related function
    this function is extracted

    :param key: the otpkey secret
    :param counter: the related counter
    :param digits: the number of to be returned digits

    :return: the otp value as string
    '''
    htoken = HmacOtp(digits=digits)
    if typ == 'totp':
        log.debug("waiting for next time slot")
        timestep = 30
        time.sleep(timestep + 1)
        counter = int((time.time() / timestep) + 0.5)

    otp = htoken.generate(counter=counter, key=binascii.unhexlify(key))

    return otp
Ejemplo n.º 32
0
def calcOTP(key, counter=0, digits=6, typ=None):
    '''
    as we have to use this method in a not class related function
    this function is extracted

    :param key: the otpkey secret
    :param counter: the related counter
    :param digits: the number of to be returned digits

    :return: the otp value as string
    '''
    htoken = HmacOtp(digits=digits)
    if typ == 'totp':
        log.debug("waiting for next time slot")
        timestep = 30
        time.sleep(timestep + 1)
        counter = int((time.time() / timestep) + 0.5)

    otp = htoken.generate(counter=counter, key=binascii.unhexlify(key))

    return otp
Ejemplo n.º 33
0
    def test_compliance(self):
        """assure that the HamcOTP class is compilant"""

        for test_vector in TestVectors:

            key = test_vector["key"]
            hash_func = test_vector["hash"]
            step = test_vector["timeStep"]
            otps = test_vector["otps"]

            for test_set in otps:

                # ---------------------------------------------------------- --

                # tupple (59, '94287082', '1970-01-01 00:00:59')

                seconds, otpvalue, timestr = test_set

                # ---------------------------------------------------------- --

                # read the time format and conert it to seconds

                time = datetime.strptime(timestr, "%Y-%m-%d %H:%M:%S")
                time_delta = time - unix_start_time

                assert seconds == time_delta.total_seconds()

                # ---------------------------------------------------------- --

                # verify the otp for the given seconds / counter

                counter = int(seconds / step)

                hmac = LinHmacOtp(digits=len(otpvalue), hashfunc=hash_func)

                lin_otp = hmac.generate(
                    counter=counter, key=binascii.unhexlify(key)
                )

                assert otpvalue == lin_otp
Ejemplo n.º 34
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''
        log.debug("[getOtp] begin. Get the next OTP value for: curTime: %r" %
                  (curTime))

        res = (-1, 0, 0, 0)

        otplen = int(self.token.LinOtpOtpLen)
        secretHOtp = self.token.getHOtpKey()
        self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1")
        timeStepping = int(self.getFromTokenInfo("timeStep", 30))
        shift = int(self.getFromTokenInfo("timeShift", 0))

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen,
                           self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))
        otpval = hmac2Otp.generate(counter=counter, inc_counter=False)

        pin = self.token.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        log.debug(
            "[getOtp]  end. Return opt is: (pin: %r, otpval: %r, combined: %r) "
            % (pin, otpval, combined))

        return (1, pin, otpval, combined)
Ejemplo n.º 35
0
    def getNextOtp(self):
        """
        access the nex validf otp

        :return: otpval
        :rtype: string
        """

        try:
            # ## TODO - replace tokenLen
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError as ex:
            log.error("[getNextOtp] ValueError %r", ex)
            raise ex

        secObj = self._get_secret_object()
        counter = self.token.getOtpCounter()

        hmac2otp = HmacOtp(secObj, counter, otplen)
        nextotp = hmac2otp.generate(counter + 1)

        return nextotp
Ejemplo n.º 36
0
    def getOtp(self, curTime=None):
        '''
        get the next OTP value

        :return: next otp value
        :rtype: string
        '''
        log.debug("[getOtp] begin. Get the next OTP value for: curTime: %r" % (curTime))

        res = (-1, 0, 0, 0)


        otplen = int(self.token.LinOtpOtpLen)
        secretHOtp = self.token.getHOtpKey()
        self.hashlibStr = self.getFromTokenInfo("hashlib", "sha1")
        timeStepping = int(self.getFromTokenInfo("timeStep", 30))
        shift = int(self.getFromTokenInfo("timeShift", 0))

        hmac2Otp = HmacOtp(secretHOtp, self.getOtpCount(), otplen, self.getHashlib(self.hashlibStr))

        tCounter = self.time2float(datetime.datetime.now())
        if curTime:
            tCounter = self.time2float(curTime)

        ## we don't need to round here as we have alread float
        counter = int(((tCounter - shift) / timeStepping))
        otpval = hmac2Otp.generate(counter=counter, inc_counter=False)

        pin = self.token.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True" :
            combined = "%s%s" % (pin, otpval)

        log.debug("[getOtp]  end. Return opt is: (pin: %r, otpval: %r, combined: %r) " %
                  (pin, otpval, combined))

        return (1, pin, otpval, combined)
Ejemplo n.º 37
0
    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
Ejemplo n.º 38
0
    def test_scenario01(self):
        """Tests Scenario 01 (https://wally/projects/linotp/wiki/TestingTest_Szenario_01)"""

        driver = self.driver

        ### 1. UserIdResolver anlegen ###
        CA001_cert = \
"""-----BEGIN CERTIFICATE-----
MIIDcjCCAtugAwIBAgIQVSU6NwMTmKNI6t3WcjY6uTANBgkqhkiG9w0BAQUFADBC
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxGTAXBgoJkiaJk/IsZAEZFglsc2V4cGVy
dHMxDjAMBgNVBAMTBUNBMDAxMB4XDTA1MDQxMTE2NDgzOVoXDTQwMDQxMTE2NTY1
MFowQjEVMBMGCgmSJomT8ixkARkWBWxvY2FsMRkwFwYKCZImiZPyLGQBGRYJbHNl
eHBlcnRzMQ4wDAYDVQQDEwVDQTAwMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAqlWLfYK+dExjG+Qa/jpYjSo3EQnweQ7azacosa+xsrTMfDV5wLgMBSclCTX2
i/35VRg282Bh7hKCZifOBnAxjCBIHMpHQmW9c0T/GpeWSOQ1x0KeKrZ4PRj5oHEv
/uDJ7q2HlWXgRQo6NR75yDGLpsAWk64TyQ/I4f2vlC+AtjMCAyPS46OCAWcwggFj
MBMGCSsGAQQBgjcUAgQGHgQAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTAD
AQH/MB0GA1UdDgQWBBTCY8rVNcU/NGvgZxaPmO+Kz8bG4TCB/AYDVR0fBIH0MIHx
MIHuoIHroIHohoGwbGRhcDovLy9DTj1DQTAwMSxDTj1sc2V4czAxLENOPUNEUCxD
Tj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1
cmF0aW9uLERDPWxzZXhwZXJ0cyxEQz1sb2NhbD9jZXJ0aWZpY2F0ZVJldm9jYXRp
b25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGM2h0
dHA6Ly9sc2V4czAxLmxzZXhwZXJ0cy5sb2NhbC9DZXJ0RW5yb2xsL0NBMDAxLmNy
bDAQBgkrBgEEAYI3FQEEAwIBADANBgkqhkiG9w0BAQUFAAOBgQBa+RGoezCgJS5W
PFCPy9BWqZr7iRimfRGBDqHpYDCPDtgec2fKCZ+u4jfwuTisZ7UOoiM1iEvkw0hH
Z7R1pz4Yd6E074kS/fe6u7U+9L3dmSUjFvO3gkLKtHKbhQi0NA+EHMRrPsQQemLm
gYzNiYwtvAu74Q+eTC6R5Uf0hOlFig==
-----END CERTIFICATE-----"""

        # Create LDAP UserIdResolver
        ldap_name = "SE_scenario01_ldap"
        ldap_expected_users = ['bach', 'beethoven', 'berlioz', 'brahms', 'debussy', u'dvořák',
                               'haydn', 'mozart', u'حافظ', u'郎']
        ldap_num_expected_users = len(ldap_expected_users)
        ldap_id_resolver = LdapUserIdResolver(
            ldap_name,
            driver,
            self.base_url,
            uri="ldaps://blackdog",
            certificate=CA001_cert,
            basedn="ou=people,dc=blackdog,dc=office,dc=lsexperts,dc=de",
            # You may also use cn="Wolfgang Amadeus Mozart"
            binddn=u'cn="عبد الحليم حافظ",ou=people,dc=blackdog,dc=office,dc=lsexperts,dc=de',
            password="******",
            preset_ldap=True
        )
        time.sleep(1)

        # Create SQL UserIdResolver
        sql_name = "SE_scenario01_sql"
        sql_server = "blackdog"
        sql_database = "userdb"
        sql_user = "******"
        sql_password = "******"
        sql_table = "user"
        sql_limit = "500"
        sql_encoding = "latin1"
        sql_expected_users = ["corny", "kay", "eric", u"knöt"]
        sql_num_expected_users = len(sql_expected_users)
        sql_id_resolver = SqlUserIdResolver(sql_name, driver, self.base_url,
                                            sql_server, sql_database,
                                            sql_user, sql_password, sql_table,
                                            sql_limit, sql_encoding)
        time.sleep(1)

        # Create realm for all resolvers
        resolvers_realm1 = [ldap_id_resolver]
        realm_name1 = "SE_scenario01_realm1"
        realm1 = Realm(realm_name1, resolvers_realm1)
        realm1.create(driver, self.base_url)
        time.sleep(1)

        resolvers_realm2 = [sql_id_resolver]
        realm_name2 = "SE_scenario01_realm2"
        realm2 = Realm(realm_name2, resolvers_realm2)
        realm2.create(driver, self.base_url)
        time.sleep(1)

        ### 2. Im Management Webinterface testen, dass alle Benutzer sichtbar sind ###

        user_view = UserView(driver, self.base_url, realm_name1)
        self.assertEqual(ldap_num_expected_users, user_view.get_num_users(),
                         "Not the expected number of users")
        for user in ldap_expected_users:
            self.assertTrue(user_view.user_exists(user), "User '" + user +
                            "' should exist.")
        time.sleep(1)

        user_view = UserView(driver, self.base_url, realm_name2)
        self.assertEqual(sql_num_expected_users, user_view.get_num_users(),
                         "Not the expected number of users")
        for user in sql_expected_users:
            self.assertTrue(user_view.user_exists(user), "User '" + user +
                            "' should exist.")

        ### 3. eToken.xml ueber das Webinterface importieren  ###

        seed_oath137332 = "ff06df50017d3b981cfbc4ec4d374040164d8d19"
        seed_oath137332_bin = binascii.unhexlify(seed_oath137332)
        file_content = """<Tokens>
<Token serial="00040008CFA5">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123412354</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="00040008CFA52">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123456</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath137332">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb1}">
<Seed>""" + seed_oath137332 + """</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath12482B">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb2}">
<Seed>6ec1d0e9915a2bebf84745b318e39e481249c1eb</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
</Tokens>"""

        TokenImport(driver, self.base_url, "safenet", file_content, None)

        serial_token_bach = "oath137332"
        test1_realm = realm_name1.lower()

        ### 4. Im Management Webinterface nun eine Policy anlegen ###

        Policy(driver, self.base_url, "SE_scenario01", "selfservice",
               "enrollMOTP, setOTPPIN, setMOTPPIN, resync, disable ",
               test1_realm)

        ### 5. eToken zuweisen ###

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("bach")
        token_view = TokenView(driver, self.base_url)
        token_view.select_token(serial_token_bach)
        driver.find_element_by_id("button_assign").click()
        time.sleep(2)
        driver.find_element_by_id("pin1").clear()
        driver.find_element_by_id("pin1").send_keys("1234")
        driver.find_element_by_id("pin2").clear()
        driver.find_element_by_id("pin2").send_keys("1234")
        driver.find_element_by_id("button_setpin_setpin").click()
        time.sleep(1)

        ### 6. Remote Token zuweisen ###

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("debussy")
        remote_token = RemoteToken(driver=self.driver,
                                   base_url=self.base_url,
                                   url="https://billybones",
                                   remote_serial="LSSP0002F653",
                                   pin="1234",
                                   remote_otp_length=6,
                                   )
        serial_token_debussy = remote_token.serial
        remote_token_otp = "666666"
        time.sleep(1)

        ### 7. Spass-Token zuweisen ###

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("beethoven")
        spass_token = SpassToken(
            driver=self.driver,
            base_url=self.base_url,
            pin=u"beethovenspass#ñô",
            description="SPass Token enrolled with Selenium"
            )
        serial_token_beethoven = spass_token.serial
        time.sleep(1)

        ### 8. Selfservice mOTP ###

        motp_key = "1234123412341234"
        motp_pin = "1234"
        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("mozart@" + test1_realm)
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit() # Submits the form
        time.sleep(1)
        driver.find_element_by_id("motp_secret").clear()
        driver.find_element_by_id("motp_secret").send_keys(motp_key)
        driver.find_element_by_id("motp_s_pin1").clear()
        driver.find_element_by_id("motp_s_pin1").send_keys(motp_pin)
        driver.find_element_by_id("motp_s_pin2").clear()
        driver.find_element_by_id("motp_s_pin2").send_keys(motp_pin)
        driver.find_element_by_id("motp_self_desc").clear()
        driver.find_element_by_id("motp_self_desc").send_keys("Selenium self enrolled")
        driver.find_element_by_id("button_register_motp").click()
        time.sleep(1)
        alert_box_text = driver.find_element_by_id("alert_box_text").text
        m = re.match(
            r"""
                .*?
                Token\ enrolled\ successfully
                .*?
                [sS]erial(\ number)?:     # 'serial:' or 'Serial number:'
                \s*
                (?P<serial>\w+)           # For example: LSMO0001222C
                """,
            alert_box_text,
            re.DOTALL | re.VERBOSE
            )
        self.assertTrue(
            m is not None,
            "alert_box_text does not match regex. Possibly the token was not enrolled properly. %r" % alert_box_text
            )
        serial_token_mozart = m.group('serial')
        self.driver.find_element_by_xpath("//button[@type='button' and ancestor::div[@aria-describedby='alert_box']]").click()
        driver.find_element_by_link_text("Logout").click()

        ### 9. Alle 4 Benutzer melden sich im selfservice Portal an und setzen die PIN

        user_token_dict = {
            "bach": serial_token_bach,
            "debussy": serial_token_debussy,
            "mozart": serial_token_mozart,
            "beethoven": serial_token_beethoven
            }
        for user in user_token_dict:
            driver.get(self.base_url + "/account/login")
            driver.find_element_by_id("login").clear()
            driver.find_element_by_id("login").send_keys("%s@%s" % (user, test1_realm))
            driver.find_element_by_id("password").clear()
            driver.find_element_by_id("password").send_keys("Test123!")
            driver.find_element_by_id("password").submit()
            driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='set PIN']").click()
            time.sleep(1)
            # driver.find_element_by_css_selector('#tokenDiv > ul > li > a').click()
            driver.find_element_by_id('tokenDiv').find_element_by_partial_link_text(user_token_dict[user]).click()
            driver.find_element_by_id("pin1").clear()
            driver.find_element_by_id("pin1").send_keys(user + "newpin")
            driver.find_element_by_id("pin2").clear()
            driver.find_element_by_id("pin2").send_keys(user + "newpin")
            driver.find_element_by_id("button_setpin").click()
            time.sleep(1)
            self.assertEqual("PIN set successfully", self.close_alert_and_get_its_text())
            driver.find_element_by_link_text("Logout").click()

        ### 10. Authentisierung der 4 Benutzer ###
        validate = Validate(self.http_protocol,
                            self.http_host,
                            self.http_username,
                            self.http_password)

        # Validate HOTP Token - bach
        hotp = HmacOtp()
        for counter in range(0, 20):
            otp = "bachnewpin" + hotp.generate(counter=counter, key=seed_oath137332_bin)
            access_granted, _ = validate.validate(user="******" +
                                                test1_realm, password=otp)
            self.assertTrue(access_granted, "OTP: " + otp + " for user " +
                            "bach@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user bach")

        # Validate Remote token - debussy
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: " + remote_token_otp + " for user " +
                        "debussy@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user debussy")

        # Validate Spass token - beethoven
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertTrue(access_granted, "OTP: " + "beethovennewpin" + " for user " +
                        "beethoven@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: randominvalidpin should be False for user beethoven")

        # Validate mOTP token - mozart
        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertTrue(access_granted, "OTP: " + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")
        motp_otp = calculate_motp(
            epoch=current_epoch - 4000,
            key=motp_key,
            pin=motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertFalse(access_granted, "OTP: mozartnewpin%s should be False for user mozart" % motp_otp)

        ### 11. mOTP Pin im selfservice ändern ###

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("mozart", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='set mOTP PIN']").click()
        time.sleep(1)
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_mozart).click()
        driver.find_element_by_id("mpin1").clear()
        new_motp_pin = "5588"
        driver.find_element_by_id("mpin1").send_keys(new_motp_pin)
        driver.find_element_by_id("mpin2").clear()
        driver.find_element_by_id("mpin2").send_keys(new_motp_pin)
        driver.find_element_by_id("button_setmpin").click()
        time.sleep(1)
        self.assertEqual("mOTP PIN set successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        time.sleep(10) # otherwise next mOTP value might not be valid

        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=new_motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertTrue(access_granted, "OTP: mozartnewpin" + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")

        ### 12. Token Resynchronisierung ###

        # Bach 'presses' his token more than 10 times and fails to authenticate
        counter = 50 # was 19
        hotp = HmacOtp()
        otp = "bachnewpin" + hotp.generate(counter=counter, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertFalse(access_granted, "OTP: %s should be False for user bach" % otp)

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("bach", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='Resync Token']").click()
        time.sleep(1)
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_bach).click()
        otp1 = hotp.generate(counter=counter + 1, key=seed_oath137332_bin)
        otp2 = hotp.generate(counter=counter + 2, key=seed_oath137332_bin)
        driver.find_element_by_id("otp1").clear()
        driver.find_element_by_id("otp1").send_keys(otp1)
        driver.find_element_by_id("otp2").clear()
        driver.find_element_by_id("otp2").send_keys(otp2)
        driver.find_element_by_id("button_resync").click()
        time.sleep(1)
        self.assertEqual("Token resynced successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        # Should be able to authenticate again
        otp = "bachnewpin" + hotp.generate(counter=counter + 3, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertTrue(access_granted, "OTP: %s should be True for user bach" % otp)

        ### 13. Ein Benutzer debussy deaktiviert seinen Token im Selfservice portal und versucht sich anzumelden. ###

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("debussy", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='Disable Token']").click()
        time.sleep(1)
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_debussy).click()
        driver.find_element_by_id("button_disable").click()
        time.sleep(1)
        self.assertEqual("Token disabled successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        # debussy should be unable to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertFalse(access_granted, "OTP: debussynewpin" + remote_token_otp + "should be False for user debussy")

        ### 14. Der Admin entsperrt diesen Token, der Benutzer debussy kann sich wieder anmelden. ###

        driver.get(self.base_url + "/manage")
        time.sleep(1)
        token_view = TokenView(driver, self.base_url)
        token_view.select_token(serial_token_debussy)
        driver.find_element_by_id("button_enable").click()
        time.sleep(1)

        # debussy should be able to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: debussynewpin" + remote_token_otp + "should be True for user debussy")
Ejemplo n.º 39
0
    def test_otppin_3(self):
        """
        Test policy otppin=3 (ignore_pin) : TestRail C1910

        First we do some authentications with user a with
        otppin=3.

        Then we change the policy, that only users from
        a specific resolver (user B) get through with otppin=3.
        """

        # Define user A
        user_a = "bach"
        user_a_pw = "Test123!"
        user_a_realm = self.two_resolvers_realm_name
        user_a_token_pin = "1234"

        # Define user B
        user_b = "kay"
        user_b_pw = "test123!"
        user_b_realm = self.two_resolvers_realm_name
        user_b_token_pin = ""
        user_b_token_key = "3132333435363738393031323334353637383930"

        # Unhexlify for hotp.generate method
        user_b_token_seed_bin = binascii.unhexlify(user_b_token_key)

        # Create Token
        self.user_view.select_user(user_b)
        HotpToken(self.driver,
                  self.base_url,
                  pin=user_b_token_pin,
                  hmac_key=user_b_token_key)

        ###############################
        ##
        # First some tests with user A
        ##
        ###############################

        # Create policy
        Policy(self.manage_ui, "otppin3", "authentication",
               "otppin=3",
               "*",
               "*")  # user = "******"

        # Create event based HMAC token
        # Tokens were imported by self.import_tokens()
        self.user_view.select_realm(user_a_realm)
        self.user_view.select_user(user_a)

        # Unhexlify for hotp.generate method
        seed_oath137332_bin = binascii.unhexlify(self.seed_oath137332)

        # Assign token to user
        # Set a pin
        self.token_view.assign_token(self.serial_oath137332,
                                     user_a_token_pin)

        # authentication tests
        # - PIN+OTP -> successfully
        # - PW+OTP -> successfully
        # - nonsense+OTP -> successfully
        # - OTP -> successfully
        # - wront OTP -> fails

        hotp_a = HmacOtp()

        # PIN+OTP -> success
        otp = user_a_token_pin + \
            hotp_a.generate(counter=0,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " +
                        user_a + "@" + user_a_realm + " returned False")

        # PW+OTP -> success
        otp = user_a_pw + \
            hotp_a.generate(counter=1,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, PW+OTP: " + otp + " for user " +
                        user_a + "@" + user_a_realm + " returned False")

        # nonsense+OTP -> success
        otp = "nonsense" + \
            hotp_a.generate(counter=2,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, nonsense+OTP: " + otp + " for user " +
                        user_a + "@" + user_a_realm + " returned False")

        # OTP -> success
        otp = hotp_a.generate(counter=3,
                              key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, OTP: " + otp + " for user " +
                        user_a + "@" + user_a_realm + " returned False")

        # wrong OTP -> fails
        otp = "111111"

        access_denied, _ = self.validate.validate(user=user_a + "@" +
                                                  user_a_realm, password=otp)
        self.assertFalse(access_denied, "OTPPIN=3, wrong OTP: " + otp + " for user " +
                         user_a + "@" + user_a_realm + " returned True")

        ###########################
        #
        # Bring user B into game
        #
        # change policy
        #    user = resolverB:
        #
        # So the ignore_pin should
        # should only affect users
        # in resolverB
        #
        ###########################

        # Change policy
        Policy(self.manage_ui, "otppin3", "authentication",
               "otppin=3",
               "*",  # realm
               data.sql_resolver["name"] + ":")  # pick specific resolver

        hotp_b = HmacOtp()

        # PIN+OTP -> success
        otp = user_b_token_pin + \
            hotp_b.generate(counter=0,
                            key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " +
                        user_b + "@" + user_b_realm + " returned False")

        # PW+OTP -> success
        otp = user_b_pw + \
            hotp_b.generate(counter=1,
                            key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, PW+OTP: " + otp + " for user " +
                        user_b + "@" + user_b_realm + " returned False")

        # OTP -> success
        otp = hotp_b.generate(counter=2,
                              key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, OTP: " + otp + " for user " +
                        user_b + "@" + user_b_realm + " returned False")

        # wrong OTP -> fails
        otp = "111111"

        access_denied, _ = self.validate.validate(user=user_b + "@" +
                                                  user_b_realm, password=otp)
        self.assertFalse(access_denied, "OTPPIN=3, wrong OTP: " + otp + " for user " +
                         user_b + "@" + user_b_realm + " returned False")

        # Back to user A and try to authenticate
        # with changed policy!

        # OTP -> fails
        otp = hotp_a.generate(counter=4,
                              inc_counter=False,
                              key=seed_oath137332_bin)

        access_denied, _ = self.validate.validate(user=user_a + "@" +
                                                  user_a_realm, password=otp)
        self.assertFalse(access_denied, "OTPPIN=3, OTP: " + otp + " for user " +
                         user_a + "@" + user_a_realm + " returned True")

        # PIN+OTP -> success
        otp = user_a_token_pin + \
            hotp_a.generate(counter=4,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        self.assertTrue(access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " +
                        user_a + "@" + user_a_realm + " returned False")
Ejemplo n.º 40
0
def get_otp(key, counter=None, digits=8):

    hmac = HmacOtp(digits=digits, hashfunc=sha1)
    return hmac.generate(counter=counter, key=binascii.unhexlify(key))
Ejemplo n.º 41
0
    def test_scenario01(self):
        """
        Scenario01 (https://wally/projects/linotp/wiki/TestingTest_Szenario_01)
        """

        driver = self.driver

        token_view = self.manage_ui.token_view
        user_view = self.manage_ui.user_view

        selfservice = SelfService(self.driver, self.base_url)

        # reset all views
        self.reset_resolvers_and_realms()
        self.manage_ui.policy_view.clear_policies()
        token_view.delete_all_tokens()

        self._announce_test("1. UserIdResolver anlegen")
        # Create LDAP UserIdResolver
        ldap_data = data.musicians_ldap_resolver
        ldap_resolver = self.useridresolver_manager.create_resolver(ldap_data)

        # Create SQL UserIdResolver
        sql_data = data.sql_resolver

        sql_resolver = self.useridresolver_manager.create_resolver(sql_data)
        self.useridresolver_manager.close()

        # Create realm for all resolvers
        realm_name1 = "SE_scenario01_realm1"
        realm_name2 = "SE_scenario01_realm2"

        self.realm_manager.create(realm_name1, [ldap_resolver])
        self.realm_manager.create(realm_name2, [sql_resolver])
        self.realm_manager.close()

        self._announce_test(
            "2. In Management Webinterface, check that all users are visible")

        self.check_users(realm_name1, ldap_data)
        self.check_users(realm_name2, sql_data)

        self._announce_test("3. eToken.xml ueber das Webinterface importieren")

        token_import_aladdin = TokenImportAladdin(self.manage_ui)

        aladdin_xml_path = os.path.join(self.manage_ui.test_data_dir,
                                        'aladdin.xml')
        err_import = token_import_aladdin.do_import(file_content=None,
                                                    file_path=aladdin_xml_path)
        # There shouldn't raise an error
        self.assertFalse(err_import,
                         "Error during Aladdin token import!")

        token_import_aladdin = TokenImportAladdin(self.manage_ui)
        err_import = token_import_aladdin.do_import(
            file_path=os.path.join(self.manage_ui.test_data_dir,
                                   'wrong_token.xml'))
        # There shouldn't raise an error
        self.assertTrue(err_import,
                        "Successful import of wrong Aladdin token file!")

        serial_token_bach = "oath137332"
        test1_realm = realm_name1.lower()

        self._announce_test(
            "4. Im Management Webinterface nun eine Policy anlegen")

        Policy(self.manage_ui, "SE_scenario01", "selfservice",
               "enrollMOTP, setOTPPIN, setMOTPPIN, resync, disable ",
               test1_realm)

        self._announce_test("5. eToken zuweisen")

        user_view.select_realm(test1_realm)
        user_view.select_user("bach")

        token_view.assign_token(serial_token_bach, "1234")

        self._announce_test("6. Remote Token zuweisen")

        user_view.select_user("debussy")
        remote_token = RemoteToken(driver=self.driver,
                                   base_url=self.base_url,
                                   url="https://billybones",
                                   remote_serial="LSSP0002F653",
                                   pin="1234",
                                   remote_otp_length=6,
                                   )
        serial_token_debussy = remote_token.serial

        self._announce_test("7. Spass-Token zuweisen")

        user_view.select_user("beethoven")
        spass_token = SpassToken(
            driver=self.driver,
            base_url=self.base_url,
            pin=u"beethovenspass#ñô",
            description="SPass Token enrolled with Selenium"
        )
        serial_token_beethoven = spass_token.serial

        self._announce_test("8. Selfservice mOTP")

        motp_key = "1234123412341234"
        motp_pin = "1234"
        selfservice.login("mozart", "Test123!", test1_realm)
        driver.find_element_by_id("motp_secret").clear()
        driver.find_element_by_id("motp_secret").send_keys(motp_key)
        driver.find_element_by_id("motp_s_pin1").clear()
        driver.find_element_by_id("motp_s_pin1").send_keys(motp_pin)
        driver.find_element_by_id("motp_s_pin2").clear()
        driver.find_element_by_id("motp_s_pin2").send_keys(motp_pin)
        driver.find_element_by_id("motp_self_desc").clear()
        driver.find_element_by_id("motp_self_desc").send_keys(
            "Selenium self enrolled")
        driver.find_element_by_id("button_register_motp").click()
        alert_box_text = driver.find_element_by_id("alert_box_text").text
        m = re.match(
            r"""
                .*?
                Token\ enrolled\ successfully
                .*?
                [sS]erial(\ number)?:     # 'serial:' or 'Serial number:'
                \s*
                (?P<serial>\w+)           # For example: LSMO0001222C
                """,
            alert_box_text,
            re.DOTALL | re.VERBOSE
        )
        self.assertTrue(
            m is not None,
            "alert_box_text does not match regex. Possibly the token was not enrolled properly. %r" % alert_box_text
        )
        serial_token_mozart = m.group('serial')
        self.driver.find_element_by_xpath(
            "//button[@type='button' and ancestor::div[@aria-describedby='alert_box']]").click()
        driver.find_element_by_link_text("Logout").click()

        self._announce_test(
            "9. Alle 4 Benutzer melden sich im selfservice Portal an und setzen die PIN")

        user_token_dict = {
            "bach": serial_token_bach,
            "debussy": serial_token_debussy,
            "mozart": serial_token_mozart,
            "beethoven": serial_token_beethoven
        }

        for user, token in user_token_dict.iteritems():
            selfservice.login(user, "Test123!", test1_realm)
            selfservice.set_pin(token, user + "newpin")
            selfservice.logout()

        self._announce_test("10. Authentisierung der 4 Benutzer ###")
        validate = Validate(self.http_protocol,
                            self.http_host,
                            self.http_port,
                            self.http_username,
                            self.http_password)

        # seed is also set in testdata/aladdin.xml
        seed_oath137332 = "ff06df50017d3b981cfbc4ec4d374040164d8d19"
        seed_oath137332_bin = binascii.unhexlify(seed_oath137332)

        # Validate HOTP Token - bach
        hotp = HmacOtp()
        for counter in range(0, 20):
            otp = "bachnewpin" + \
                hotp.generate(counter=counter, key=seed_oath137332_bin)
            access_granted, _ = validate.validate(user="******" +
                                                  test1_realm, password=otp)
            self.assertTrue(access_granted, "OTP: " + otp + " for user " +
                            "bach@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(
            access_granted, "OTP: 1234111111 should be False for user bach")

        # Validate Remote token - debussy

        # deactivated remote token test while no remote linotp integration
        # server is available
        '''
        remote_token_otp = "666666"
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: " + remote_token_otp + " for user " +
                        "debussy@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user debussy")'''

        # Validate Spass token - beethoven
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertTrue(access_granted, "OTP: " + "beethovennewpin" + " for user " +
                        "beethoven@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(
            access_granted, "OTP: randominvalidpin should be False for user beethoven")

        # Validate mOTP token - mozart
        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=motp_pin
        )

        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" + motp_otp)
        time.sleep(1)
        self.assertTrue(access_granted, "OTP: " + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")
        motp_otp = calculate_motp(
            epoch=current_epoch - 4000,
            key=motp_key,
            pin=motp_pin
        )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" + motp_otp)
        self.assertFalse(
            access_granted, "OTP: mozartnewpin%s should be False for user mozart" % motp_otp)

        self._announce_test("11. mOTP Pin im selfservice ändern")

        new_motp_pin = "5588"

        selfservice.login("mozart", "Test123!", test1_realm)
        selfservice.set_motp_pin(token, new_motp_pin)
        selfservice.logout()

        time.sleep(10)  # otherwise next mOTP value might not be valid

        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=new_motp_pin
        )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" + motp_otp)
        self.assertTrue(access_granted, "OTP: mozartnewpin" + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")

        self._announce_test("12. Token Resynchronisierung")

        # Bach 'presses' his token more than 10 times and fails to authenticate
        counter = 50  # was 19
        hotp = HmacOtp()
        otp = "bachnewpin" + \
            hotp.generate(counter=counter, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertFalse(
            access_granted, "OTP: %s should be False for user bach" % otp)

        selfservice.login("bach", "Test123!", test1_realm)

        otp1 = hotp.generate(counter=counter + 1, key=seed_oath137332_bin)
        otp2 = hotp.generate(counter=counter + 2, key=seed_oath137332_bin)

        selfservice.resync_token(serial_token_bach, otp1, otp2)
        selfservice.logout()

        # Should be able to authenticate again
        otp = "bachnewpin" + \
            hotp.generate(counter=counter + 3, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertTrue(
            access_granted, "OTP: %s should be True for user bach" % otp)

        self._announce_test(
            "13. Benutzer beethoven deaktiviert seinen Token im Selfservice portal und versucht sich anzumelden.")

        selfservice.login("beethoven", "Test123!", test1_realm)
        selfservice.disable_token(serial_token_beethoven)
        selfservice.logout()

        # beethoven should be unable to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(
            access_granted, "OTP: beethovennewpin should be False for user beethoven")

        self._announce_test(
            "14. Der Admin entsperrt diesen Token, der Benutzer beethoven kann sich wieder anmelden.")

        token_view.open()
        token_view.select_token(serial_token_beethoven)
        driver.find_element_by_id("button_enable").click()

        time.sleep(1)
        # beethoven should be able to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertTrue(
            access_granted, "OTP: beethovennewpin should be able to authenticate after re-enabled token.")
Ejemplo n.º 42
0
    def test_scenario01(self):
        """Tests Scenario 01 (https://wally/projects/linotp/wiki/TestingTest_Szenario_01)"""

        driver = self.driver

        token_view = self.manage_ui.token_view
        user_view = self.manage_ui.user_view

        selfservice = SelfService(self.driver, self.base_url)

        # reset all views
        self.reset_resolvers_and_realms()
        self.manage_ui.policy_view.clear_policies()
        token_view.delete_all_tokens()

        self._announce_test("1. UserIdResolver anlegen")
        # Create LDAP UserIdResolver
        ldap_data = data.musicians_ldap_resolver
        ldap_resolver = self.useridresolver_manager.create_resolver(ldap_data)

        # Create SQL UserIdResolver
        sql_data = data.sql_resolver

        sql_resolver = self.useridresolver_manager.create_resolver(sql_data)
        self.useridresolver_manager.close()

        # Create realm for all resolvers
        realm_name1 = "SE_scenario01_realm1"
        realm_name2 = "SE_scenario01_realm2"

        self.realm_manager.create(realm_name1, [ldap_resolver])
        self.realm_manager.create(realm_name2, [sql_resolver])
        self.realm_manager.close()

        self._announce_test(
            "2. In Management Webinterface, check that all users are visible")

        self.check_users(realm_name1, ldap_data)
        self.check_users(realm_name2, sql_data)

        self._announce_test("3. eToken.xml ueber das Webinterface importieren")

        seed_oath137332 = "ff06df50017d3b981cfbc4ec4d374040164d8d19"
        seed_oath137332_bin = binascii.unhexlify(seed_oath137332)
        file_content = """<Tokens>
<Token serial="00040008CFA5">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123412354</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="00040008CFA52">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123456</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath137332">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb1}">
<Seed>""" + seed_oath137332 + """</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath12482B">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb2}">
<Seed>6ec1d0e9915a2bebf84745b318e39e481249c1eb</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
</Tokens>"""

        TokenImport(driver, self.base_url, "safenet", file_content, None)

        serial_token_bach = "oath137332"
        test1_realm = realm_name1.lower()

        self._announce_test(
            "4. Im Management Webinterface nun eine Policy anlegen")

        Policy(self.manage_ui, "SE_scenario01", "selfservice",
               "enrollMOTP, setOTPPIN, setMOTPPIN, resync, disable ",
               test1_realm)

        self._announce_test("5. eToken zuweisen")

        user_view.select_realm(test1_realm)
        user_view.select_user("bach")

        token_view.assign_token(serial_token_bach, "1234")

        self._announce_test("6. Remote Token zuweisen")

        user_view.select_user("debussy")
        remote_token = RemoteToken(
            driver=self.driver,
            base_url=self.base_url,
            url="https://billybones",
            remote_serial="LSSP0002F653",
            pin="1234",
            remote_otp_length=6,
        )
        serial_token_debussy = remote_token.serial

        self._announce_test("7. Spass-Token zuweisen")

        user_view.select_user("beethoven")
        spass_token = SpassToken(
            driver=self.driver,
            base_url=self.base_url,
            pin=u"beethovenspass#ñô",
            description="SPass Token enrolled with Selenium")
        serial_token_beethoven = spass_token.serial

        self._announce_test("8. Selfservice mOTP")

        motp_key = "1234123412341234"
        motp_pin = "1234"
        selfservice.login("mozart", "Test123!", test1_realm)
        driver.find_element_by_id("motp_secret").clear()
        driver.find_element_by_id("motp_secret").send_keys(motp_key)
        driver.find_element_by_id("motp_s_pin1").clear()
        driver.find_element_by_id("motp_s_pin1").send_keys(motp_pin)
        driver.find_element_by_id("motp_s_pin2").clear()
        driver.find_element_by_id("motp_s_pin2").send_keys(motp_pin)
        driver.find_element_by_id("motp_self_desc").clear()
        driver.find_element_by_id("motp_self_desc").send_keys(
            "Selenium self enrolled")
        driver.find_element_by_id("button_register_motp").click()
        alert_box_text = driver.find_element_by_id("alert_box_text").text
        m = re.match(
            r"""
                .*?
                Token\ enrolled\ successfully
                .*?
                [sS]erial(\ number)?:     # 'serial:' or 'Serial number:'
                \s*
                (?P<serial>\w+)           # For example: LSMO0001222C
                """, alert_box_text, re.DOTALL | re.VERBOSE)
        self.assertTrue(
            m is not None,
            "alert_box_text does not match regex. Possibly the token was not enrolled properly. %r"
            % alert_box_text)
        serial_token_mozart = m.group('serial')
        self.driver.find_element_by_xpath(
            "//button[@type='button' and ancestor::div[@aria-describedby='alert_box']]"
        ).click()
        driver.find_element_by_link_text("Logout").click()

        self._announce_test(
            "9. Alle 4 Benutzer melden sich im selfservice Portal an und setzen die PIN"
        )

        user_token_dict = {
            "bach": serial_token_bach,
            "debussy": serial_token_debussy,
            "mozart": serial_token_mozart,
            "beethoven": serial_token_beethoven
        }
        for user, token in user_token_dict.iteritems():
            selfservice.login(user, "Test123!", test1_realm)
            selfservice.set_pin(token, user + "newpin")
            selfservice.logout()

        self._announce_test("10. Authentisierung der 4 Benutzer ###")
        validate = Validate(self.http_protocol, self.http_host, self.http_port,
                            self.http_username, self.http_password)

        # Validate HOTP Token - bach
        hotp = HmacOtp()
        for counter in range(0, 20):
            otp = "bachnewpin" + \
                hotp.generate(counter=counter, key=seed_oath137332_bin)
            access_granted, _ = validate.validate(user="******" + test1_realm,
                                                  password=otp)
            self.assertTrue(
                access_granted, "OTP: " + otp + " for user " + "bach@" +
                test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(access_granted,
                         "OTP: 1234111111 should be False for user bach")

        # Validate Remote token - debussy

        # deactivated remote token test while no remote linotp integration
        # server is available
        '''
        remote_token_otp = "666666"
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: " + remote_token_otp + " for user " +
                        "debussy@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user debussy")'''

        # Validate Spass token - beethoven
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertTrue(
            access_granted, "OTP: " + "beethovennewpin" + " for user " +
            "beethoven@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(
            access_granted,
            "OTP: randominvalidpin should be False for user beethoven")

        # Validate mOTP token - mozart
        current_epoch = time.time()
        motp_otp = calculate_motp(epoch=current_epoch,
                                  key=motp_key,
                                  pin=motp_pin)

        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        time.sleep(1)
        self.assertTrue(
            access_granted, "OTP: " + motp_otp + " for user " + "mozart@" +
            test1_realm + " returned False")
        motp_otp = calculate_motp(epoch=current_epoch - 4000,
                                  key=motp_key,
                                  pin=motp_pin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        self.assertFalse(
            access_granted,
            "OTP: mozartnewpin%s should be False for user mozart" % motp_otp)

        self._announce_test("11. mOTP Pin im selfservice ändern")

        new_motp_pin = "5588"

        selfservice.login("mozart", "Test123!", test1_realm)
        selfservice.set_motp_pin(token, new_motp_pin)
        selfservice.logout()

        time.sleep(10)  # otherwise next mOTP value might not be valid

        current_epoch = time.time()
        motp_otp = calculate_motp(epoch=current_epoch,
                                  key=motp_key,
                                  pin=new_motp_pin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        self.assertTrue(
            access_granted, "OTP: mozartnewpin" + motp_otp + " for user " +
            "mozart@" + test1_realm + " returned False")

        self._announce_test("12. Token Resynchronisierung")

        # Bach 'presses' his token more than 10 times and fails to authenticate
        counter = 50  # was 19
        hotp = HmacOtp()
        otp = "bachnewpin" + \
            hotp.generate(counter=counter, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertFalse(access_granted,
                         "OTP: %s should be False for user bach" % otp)

        selfservice.login("bach", "Test123!", test1_realm)

        otp1 = hotp.generate(counter=counter + 1, key=seed_oath137332_bin)
        otp2 = hotp.generate(counter=counter + 2, key=seed_oath137332_bin)

        selfservice.resync_token(serial_token_bach, otp1, otp2)
        selfservice.logout()

        # Should be able to authenticate again
        otp = "bachnewpin" + \
            hotp.generate(counter=counter + 3, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertTrue(access_granted,
                        "OTP: %s should be True for user bach" % otp)

        self._announce_test(
            "13. Benutzer beethoven deaktiviert seinen Token im Selfservice portal und versucht sich anzumelden."
        )

        selfservice.login("beethoven", "Test123!", test1_realm)
        selfservice.disable_token(serial_token_beethoven)
        selfservice.logout()

        # beethoven should be unable to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertFalse(
            access_granted,
            "OTP: beethovennewpin should be False for user beethoven")

        self._announce_test(
            "14. Der Admin entsperrt diesen Token, der Benutzer beethoven kann sich wieder anmelden."
        )

        token_view.open()
        token_view.select_token(serial_token_beethoven)
        driver.find_element_by_id("button_enable").click()

        time.sleep(1)
        # beethoven should be able to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        self.assertTrue(
            access_granted,
            "OTP: beethovennewpin should be able to authenticate after re-enabled token."
        )
Ejemplo n.º 43
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

        '''
        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
Ejemplo n.º 44
0
    def test_scenario01(self):
        """
        Scenario01 (https://wally/projects/linotp/wiki/TestingTest_Szenario_01)
        """

        driver = self.testcase.driver

        token_view = self.testcase.manage_ui.token_view
        user_view = self.testcase.manage_ui.user_view
        token_enroll = self.testcase.manage_ui.token_enroll

        selfservice = SelfService(self.testcase)

        # reset all views
        self.testcase.reset_resolvers_and_realms()
        self.testcase.manage_ui.policy_view.clear_policies()
        token_view.delete_all_tokens()

        self._announce_test("1. UserIdResolver anlegen")
        # Create LDAP UserIdResolver
        ldap_data = data.musicians_ldap_resolver
        ldap_resolver = self.testcase.useridresolver_manager.create_resolver(
            ldap_data)

        # Create SQL UserIdResolver
        sql_data = data.sql_resolver

        sql_resolver = self.testcase.useridresolver_manager.create_resolver(
            sql_data)
        self.testcase.useridresolver_manager.close()

        # Create realm for all resolvers
        realm_name1 = "SE_scenario01_realm1"
        realm_name2 = "SE_scenario01_realm2"

        self.testcase.realm_manager.create(realm_name1, [ldap_resolver])
        self.testcase.realm_manager.create(realm_name2, [sql_resolver])
        self.testcase.realm_manager.close()

        self._announce_test(
            "2. In Management Webinterface, check that all users are visible")

        self.check_users(realm_name1, ldap_data)
        self.check_users(realm_name2, sql_data)

        self._announce_test("3. eToken.xml ueber das Webinterface importieren")

        token_import_aladdin = TokenImportAladdin(self.testcase.manage_ui)

        aladdin_xml_path = os.path.join(self.testcase.manage_ui.test_data_dir,
                                        "aladdin.xml")
        token_import_aladdin.do_import(file_path=aladdin_xml_path)

        serial_token_bach = "oath137332"
        test1_realm = realm_name1.lower()

        self._announce_test(
            "4. Im Management Webinterface nun eine Policy anlegen")

        Policy(
            self.testcase.manage_ui,
            "SE_scenario01",
            "selfservice",
            "enrollMOTP, setOTPPIN, setMOTPPIN, resync, disable ",
            test1_realm,
        )

        self._announce_test("5. eToken zuweisen")

        user_view.select_realm(test1_realm)
        user_view.select_user("bach")

        token_view.assign_token(serial_token_bach, "1234")

        self._announce_test("6. Remote Token zuweisen")

        user_view.select_user("debussy")
        serial_token_debussy = token_enroll.create_remote_token(
            url="https://billybones",
            remote_serial="LSSP0002F653",
            pin="1234",
            remote_otp_length=6,
        )

        self._announce_test("7. Spass-Token zuweisen")

        user_view.select_user("beethoven")
        beethoven_token_password = "******"
        serial_token_beethoven = token_enroll.create_static_password_token(
            password=beethoven_token_password,
            description="Password Token enrolled with Selenium",
        )

        self._announce_test("8. Selfservice mOTP")

        motp_key = "1234123412341234"
        motp_pin = "1234"
        selfservice.open()
        selfservice.login("mozart", "Test123!", test1_realm)
        driver.find_element(By.ID, "motp_secret").clear()
        driver.find_element(By.ID, "motp_secret").send_keys(motp_key)
        driver.find_element(By.ID, "motp_s_pin1").clear()
        driver.find_element(By.ID, "motp_s_pin1").send_keys(motp_pin)
        driver.find_element(By.ID, "motp_s_pin2").clear()
        driver.find_element(By.ID, "motp_s_pin2").send_keys(motp_pin)
        driver.find_element(By.ID, "motp_self_desc").clear()
        driver.find_element(
            By.ID, "motp_self_desc").send_keys("Selenium self enrolled")
        driver.find_element(By.ID, "button_register_motp").click()
        alert_box_text = driver.find_element(By.ID, "alert_box_text").text
        m = re.match(
            r"""
                .*?
                Token\ enrolled\ successfully
                .*?
                [sS]erial(\ number)?:     # 'serial:' or 'Serial number:'
                \s*
                (?P<serial>\w+)           # For example: LSMO0001222C
                """,
            alert_box_text,
            re.DOTALL | re.VERBOSE,
        )
        assert m is not None, (
            "alert_box_text does not match regex. Possibly the token was not enrolled properly. %r"
            % alert_box_text)
        serial_token_mozart = m.group("serial")
        self.testcase.driver.find_element(
            By.XPATH,
            "//button[@type='button' and ancestor::div[@aria-describedby='alert_box']]",
        ).click()
        selfservice.logout()

        self._announce_test(
            "9. Alle 4 Benutzer melden sich im selfservice Portal an und setzen die PIN"
        )

        user_token_dict = {
            "bach": serial_token_bach,
            "debussy": serial_token_debussy,
            "mozart": serial_token_mozart,
            "beethoven": serial_token_beethoven,
        }

        for user, token in user_token_dict.items():
            selfservice.login(user, "Test123!", test1_realm)
            selfservice.set_pin(token, user + "newpin")
            selfservice.logout()

        self._announce_test("10. Authentisierung der 4 Benutzer ###")
        validate = Validate(
            self.testcase.http_protocol,
            self.testcase.http_host,
            self.testcase.http_port,
            self.testcase.http_username,
            self.testcase.http_password,
        )

        # seed is also set in testdata/aladdin.xml
        seed_oath137332 = "ff06df50017d3b981cfbc4ec4d374040164d8d19"
        seed_oath137332_bin = binascii.unhexlify(seed_oath137332)

        # Validate HOTP Token - bach
        hotp = HmacOtp()
        for counter in range(0, 4):
            otp = "bachnewpin" + hotp.generate(counter=counter,
                                               key=seed_oath137332_bin)
            access_granted, _ = validate.validate(user="******" + test1_realm,
                                                  password=otp)
            assert access_granted, ("OTP: " + otp + " for user " + "bach@" +
                                    test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        assert (not access_granted
                ), "OTP: 1234111111 should be False for user bach"

        # Validate Remote token - debussy

        # deactivated remote token test while no remote linotp integration
        # server is available
        '''
        remote_token_otp = "666666"
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        assert access_granted is True, "OTP: " + remote_token_otp + " for user " +
                        "debussy@" + test1_realm + " returned False"
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        assert access_granted is False, "OTP: 1234111111 should be False for user debussy"'''

        # Validate Spass token - beethoven

        # Correct PIN + password = success
        access_granted, _ = validate.validate(
            user="******" + test1_realm,
            password="******" + beethoven_token_password,
        )
        assert access_granted, ("OTP: " + "beethovennewpin" + " for user " +
                                "beethoven@" + test1_realm + " returned False")
        # wrong PIN + empty password = fail
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******")
        assert (not access_granted
                ), "OTP: randominvalidpin should be False for user beethoven"
        # correct PIN + wrong password = fail
        access_granted, _ = validate.validate(
            user="******" + test1_realm,
            password="******" + "wrongpassword",
        )
        assert (not access_granted
                ), "beethoven should not auth with wrong token password"
        # Password without pin = fail
        access_granted, _ = validate.validate(
            user="******" + test1_realm, password=beethoven_token_password)
        assert (not access_granted
                ), "beethoven should not auth with password and old pin"
        # Correct PIN + password = success (again)
        access_granted, _ = validate.validate(
            user="******" + test1_realm,
            password="******" + beethoven_token_password,
        )
        assert access_granted, ("OTP: " + "beethovennewpin" + " for user " +
                                "beethoven@" + test1_realm + " returned False")

        time.sleep(2)

        # Validate mOTP token - mozart
        current_epoch = time.time()
        motp_otp = calculate_motp(epoch=current_epoch,
                                  key=motp_key,
                                  pin=motp_pin)

        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        time.sleep(1)
        assert access_granted, ("OTP: " + motp_otp + " for user " + "mozart@" +
                                test1_realm + " returned False")
        motp_otp = calculate_motp(epoch=current_epoch - 4000,
                                  key=motp_key,
                                  pin=motp_pin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        assert not access_granted, (
            "OTP: mozartnewpin%s should be False for user mozart" % motp_otp)

        self._announce_test("11. mOTP Pin im selfservice ändern")

        new_motp_pin = "5588"

        selfservice.open()
        selfservice.login("mozart", "Test123!", test1_realm)
        selfservice.set_motp_pin(serial_token_mozart, new_motp_pin)
        selfservice.logout()

        time.sleep(10)  # otherwise next mOTP value might not be valid

        current_epoch = time.time()
        motp_otp = calculate_motp(epoch=current_epoch,
                                  key=motp_key,
                                  pin=new_motp_pin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password="******" +
                                              motp_otp)
        assert access_granted, ("OTP: mozartnewpin" + motp_otp + " for user " +
                                "mozart@" + test1_realm + " returned False")

        self._announce_test("12. Token Resynchronisierung")

        # Bach 'presses' his token more than 10 times and fails to authenticate
        counter = 50  # was 19
        hotp = HmacOtp()
        otp = "bachnewpin" + hotp.generate(counter=counter,
                                           key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        assert not access_granted, ("OTP: %s should be False for user bach" %
                                    otp)

        selfservice.login("bach", "Test123!", test1_realm)

        otp1 = hotp.generate(counter=counter + 1, key=seed_oath137332_bin)
        otp2 = hotp.generate(counter=counter + 2, key=seed_oath137332_bin)

        selfservice.resync_token(serial_token_bach, otp1, otp2)
        selfservice.logout()

        # Should be able to authenticate again
        otp = "bachnewpin" + hotp.generate(counter=counter + 3,
                                           key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        assert access_granted, "OTP: %s should be True for user bach" % otp

        self._announce_test(
            "13. Benutzer beethoven deaktiviert seinen Token im Selfservice portal und versucht sich anzumelden."
        )

        selfservice.login("beethoven", "Test123!", test1_realm)
        selfservice.disable_token(serial_token_beethoven)
        selfservice.logout()

        # beethoven should be unable to authenticate
        access_granted, _ = validate.validate(
            user="******" + test1_realm,
            password="******" + beethoven_token_password,
        )
        assert (not access_granted
                ), "OTP: beethovennewpin should be False for user beethoven"

        self._announce_test(
            "14. Der Admin entsperrt diesen Token, der Benutzer beethoven kann sich wieder anmelden."
        )

        token_view.open()
        token_view.enable_token(serial_token_beethoven)

        # beethoven should be able to authenticate
        access_granted, _ = validate.validate(
            user="******" + test1_realm,
            password="******" + beethoven_token_password,
        )
        assert (
            access_granted
        ), "OTP: beethovennewpin should be able to authenticate after re-enabled token."
Ejemplo n.º 45
0
    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
Ejemplo n.º 46
0
    def test_scenario01(self):
        """Tests Scenario 01 (https://wally/projects/linotp/wiki/TestingTest_Szenario_01)"""

        driver = self.driver

        self.reset_resolvers_and_realms()

        self._announce_test("1. UserIdResolver anlegen")
        # Create LDAP UserIdResolver
        ldap_data = data.musicians_ldap_resolver
        ldap_expected_users = ['bach', 'beethoven', 'berlioz', 'brahms', 'debussy', u'dvořák',
                               'haydn', 'mozart', u'حافظ', u'郎']
        ldap_num_expected_users = len(ldap_expected_users)
        ldap_resolver = self.useridresolver_manager.create_resolver(ldap_data)

        # Create SQL UserIdResolver
        sql_data = data.sql_resolver
        sql_resolver = self.useridresolver_manager.create_resolver(sql_data)
        sql_expected_users = ["corny", "kay", "eric", u"knöt"]
        sql_num_expected_users = len(sql_expected_users)

        # Create realm for all resolvers
        realm_name1 = "SE_scenario01_realm1"
        realm_name2 = "SE_scenario01_realm2"
        self.realm_manager.create(realm_name1, [ldap_resolver])
        self.realm_manager.create(realm_name2, [sql_resolver])

        self._announce_test("2. In Management Webinterface, check that all users are visible")

        user_view = UserView(driver, self.base_url, realm_name1)
        self.assertEqual(ldap_num_expected_users, user_view.get_num_users(),
                         "Not the expected number of users")
        for user in ldap_expected_users:
            self.assertTrue(user_view.user_exists(user), "User '" + user +
                            "' should exist.")

        user_view = UserView(driver, self.base_url, realm_name2)
        self.assertEqual(sql_num_expected_users, user_view.get_num_users(),
                         "Not the expected number of users")
        for user in sql_expected_users:
            self.assertTrue(user_view.user_exists(user), "User '" + user +
                            "' should exist.")

        self._announce_test("3. eToken.xml ueber das Webinterface importieren")

        seed_oath137332 = "ff06df50017d3b981cfbc4ec4d374040164d8d19"
        seed_oath137332_bin = binascii.unhexlify(seed_oath137332)
        file_content = """<Tokens>
<Token serial="00040008CFA5">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123412354</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="00040008CFA52">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb9}">
<Seed>123456</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath137332">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb1}">
<Seed>""" + seed_oath137332 + """</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
<Token serial="oath12482B">
<CaseModel>5</CaseModel>
<Model>101</Model>
<ProductionDate>02/19/2009</ProductionDate>
<ProductName>Safeword Alpine</ProductName>
<Applications>
<Application ConnectorID="{ab1397d2-ddb6-4705-b66e-9f83f322deb2}">
<Seed>6ec1d0e9915a2bebf84745b318e39e481249c1eb</Seed>
<MovingFactor>1</MovingFactor>
</Application>
</Applications>
</Token>
</Tokens>"""

        TokenImport(driver, self.base_url, "safenet", file_content, None)

        serial_token_bach = "oath137332"
        test1_realm = realm_name1.lower()

        self._announce_test("4. Im Management Webinterface nun eine Policy anlegen")

        Policy(driver, self.base_url, "SE_scenario01", "selfservice",
               "enrollMOTP, setOTPPIN, setMOTPPIN, resync, disable ",
               test1_realm)

        self._announce_test("5. eToken zuweisen")

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("bach")
        token_view = TokenView(self)
        token_view.assign_token(serial_token_bach, "1234")

        self._announce_test("6. Remote Token zuweisen")

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("debussy")
        remote_token = RemoteToken(driver=self.driver,
                                   base_url=self.base_url,
                                   url="https://billybones",
                                   remote_serial="LSSP0002F653",
                                   pin="1234",
                                   remote_otp_length=6,
                                   )
        serial_token_debussy = remote_token.serial
        remote_token_otp = "666666"

        self._announce_test("7. Spass-Token zuweisen")

        user_view = UserView(driver, self.base_url, test1_realm)
        user_view.select_user("beethoven")
        spass_token = SpassToken(
            driver=self.driver,
            base_url=self.base_url,
            pin=u"beethovenspass#ñô",
            description="SPass Token enrolled with Selenium"
            )
        serial_token_beethoven = spass_token.serial

        self._announce_test("8. Selfservice mOTP")

        motp_key = "1234123412341234"
        motp_pin = "1234"
        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("mozart@" + test1_realm)
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit() # Submits the form
        driver.find_element_by_id("motp_secret").clear()
        driver.find_element_by_id("motp_secret").send_keys(motp_key)
        driver.find_element_by_id("motp_s_pin1").clear()
        driver.find_element_by_id("motp_s_pin1").send_keys(motp_pin)
        driver.find_element_by_id("motp_s_pin2").clear()
        driver.find_element_by_id("motp_s_pin2").send_keys(motp_pin)
        driver.find_element_by_id("motp_self_desc").clear()
        driver.find_element_by_id("motp_self_desc").send_keys("Selenium self enrolled")
        driver.find_element_by_id("button_register_motp").click()
        alert_box_text = driver.find_element_by_id("alert_box_text").text
        m = re.match(
            r"""
                .*?
                Token\ enrolled\ successfully
                .*?
                [sS]erial(\ number)?:     # 'serial:' or 'Serial number:'
                \s*
                (?P<serial>\w+)           # For example: LSMO0001222C
                """,
            alert_box_text,
            re.DOTALL | re.VERBOSE
            )
        self.assertTrue(
            m is not None,
            "alert_box_text does not match regex. Possibly the token was not enrolled properly. %r" % alert_box_text
            )
        serial_token_mozart = m.group('serial')
        self.driver.find_element_by_xpath("//button[@type='button' and ancestor::div[@aria-describedby='alert_box']]").click()
        driver.find_element_by_link_text("Logout").click()

        self._announce_test("9. Alle 4 Benutzer melden sich im selfservice Portal an und setzen die PIN")

        user_token_dict = {
            "bach": serial_token_bach,
            "debussy": serial_token_debussy,
            "mozart": serial_token_mozart,
            "beethoven": serial_token_beethoven
            }
        for user in user_token_dict:
            driver.get(self.base_url + "/account/login")
            driver.find_element_by_id("login").clear()
            driver.find_element_by_id("login").send_keys("%s@%s" % (user, test1_realm))
            driver.find_element_by_id("password").clear()
            driver.find_element_by_id("password").send_keys("Test123!")
            driver.find_element_by_id("password").submit()
            driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='set PIN']").click()
            time.sleep(1)
            # driver.find_element_by_css_selector('#tokenDiv > ul > li > a').click()
            driver.find_element_by_id('tokenDiv').find_element_by_partial_link_text(user_token_dict[user]).click()
            driver.find_element_by_id("pin1").clear()
            driver.find_element_by_id("pin1").send_keys(user + "newpin")
            driver.find_element_by_id("pin2").clear()
            driver.find_element_by_id("pin2").send_keys(user + "newpin")
            driver.find_element_by_id("button_setpin").click()
            time.sleep(1)
            self.assertEqual("PIN set successfully", self.close_alert_and_get_its_text())
            driver.find_element_by_link_text("Logout").click()

        self._announce_test("10. Authentisierung der 4 Benutzer ###")
        validate = Validate(self.http_protocol,
                            self.http_host,
                            self.http_port,
                            self.http_username,
                            self.http_password)

        # Validate HOTP Token - bach
        hotp = HmacOtp()
        for counter in range(0, 20):
            otp = "bachnewpin" + hotp.generate(counter=counter, key=seed_oath137332_bin)
            access_granted, _ = validate.validate(user="******" +
                                                test1_realm, password=otp)
            self.assertTrue(access_granted, "OTP: " + otp + " for user " +
                            "bach@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user bach")

        # Validate Remote token - debussy
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: " + remote_token_otp + " for user " +
                        "debussy@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: 1234111111 should be False for user debussy")

        # Validate Spass token - beethoven
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertTrue(access_granted, "OTP: " + "beethovennewpin" + " for user " +
                        "beethoven@" + test1_realm + " returned False")
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******")
        self.assertFalse(access_granted, "OTP: randominvalidpin should be False for user beethoven")

        # Validate mOTP token - mozart
        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertTrue(access_granted, "OTP: " + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")
        motp_otp = calculate_motp(
            epoch=current_epoch - 4000,
            key=motp_key,
            pin=motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertFalse(access_granted, "OTP: mozartnewpin%s should be False for user mozart" % motp_otp)

        self._announce_test("11. mOTP Pin im selfservice ändern")

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("mozart", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='set mOTP PIN']").click()
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_mozart).click()
        driver.find_element_by_id("mpin1").clear()
        new_motp_pin = "5588"
        driver.find_element_by_id("mpin1").send_keys(new_motp_pin)
        driver.find_element_by_id("mpin2").clear()
        driver.find_element_by_id("mpin2").send_keys(new_motp_pin)
        driver.find_element_by_id("button_setmpin").click()
        self.assertEqual("mOTP PIN set successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        time.sleep(10) # otherwise next mOTP value might not be valid

        current_epoch = time.time()
        motp_otp = calculate_motp(
            epoch=current_epoch,
            key=motp_key,
            pin=new_motp_pin
            )
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + motp_otp)
        self.assertTrue(access_granted, "OTP: mozartnewpin" + motp_otp + " for user " +
                        "mozart@" + test1_realm + " returned False")

        self._announce_test("12. Token Resynchronisierung")

        # Bach 'presses' his token more than 10 times and fails to authenticate
        counter = 50 # was 19
        hotp = HmacOtp()
        otp = "bachnewpin" + hotp.generate(counter=counter, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertFalse(access_granted, "OTP: %s should be False for user bach" % otp)

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("bach", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='Resync Token']").click()
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_bach).click()
        otp1 = hotp.generate(counter=counter + 1, key=seed_oath137332_bin)
        otp2 = hotp.generate(counter=counter + 2, key=seed_oath137332_bin)
        driver.find_element_by_id("otp1").clear()
        driver.find_element_by_id("otp1").send_keys(otp1)
        driver.find_element_by_id("otp2").clear()
        driver.find_element_by_id("otp2").send_keys(otp2)
        driver.find_element_by_id("button_resync").click()
        self.assertEqual("Token resynced successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        # Should be able to authenticate again
        otp = "bachnewpin" + hotp.generate(counter=counter + 3, key=seed_oath137332_bin)
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                              password=otp)
        self.assertTrue(access_granted, "OTP: %s should be True for user bach" % otp)

        self._announce_test("13. Ein Benutzer debussy deaktiviert seinen Token im Selfservice portal und versucht sich anzumelden.")

        driver.get(self.base_url + "/account/login")
        driver.find_element_by_id("login").clear()
        driver.find_element_by_id("login").send_keys("%s@%s" % ("debussy", test1_realm))
        driver.find_element_by_id("password").clear()
        driver.find_element_by_id("password").send_keys("Test123!")
        driver.find_element_by_id("password").submit()
        driver.find_element_by_xpath("//div[@id='tabs']/ul/li/a/span[text()='Disable Token']").click()
        driver.find_element_by_id('tokenDiv').find_element_by_link_text(serial_token_debussy).click()
        driver.find_element_by_id("button_disable").click()
        self.assertEqual("Token disabled successfully", self.close_alert_and_get_its_text())
        driver.find_element_by_link_text("Logout").click()

        # debussy should be unable to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertFalse(access_granted, "OTP: debussynewpin" + remote_token_otp + "should be False for user debussy")

        self._announce_test("14. Der Admin entsperrt diesen Token, der Benutzer debussy kann sich wieder anmelden.")

        driver.get(self.base_url + "/manage")
        token_view = TokenView(self)
        token_view.select_token(serial_token_debussy)
        driver.find_element_by_id("button_enable").click()

        # debussy should be able to authenticate
        access_granted, _ = validate.validate(user="******" + test1_realm,
                                            password="******" + remote_token_otp)
        self.assertTrue(access_granted, "OTP: debussynewpin" + remote_token_otp + "should be True for user debussy")
Ejemplo n.º 47
0
    def test_otppin_3(self):
        """
        Test policy otppin=3 (ignore_pin) : TestRail C1910

        First we do some authentications with user a with
        otppin=3.

        Then we change the policy, that only users from
        a specific resolver (user B) get through with otppin=3.
        """

        # Define user A
        user_a = "bach"
        user_a_pw = "Test123!"
        user_a_realm = self.two_resolvers_realm_name
        user_a_token_pin = "1234"

        # Define user B
        user_b = "kay"
        user_b_pw = "test123!"
        user_b_realm = self.two_resolvers_realm_name
        user_b_token_pin = ""
        user_b_token_key = "3132333435363738393031323334353637383930"

        # Unhexlify for hotp.generate method
        user_b_token_seed_bin = binascii.unhexlify(user_b_token_key)

        # Create Token
        self.user_view.select_user(user_b)
        self.manage_ui.token_enroll.create_hotp_token(
                  pin=user_b_token_pin,
                  hmac_key=user_b_token_key)

        ###############################
        ##
        # First some tests with user A
        ##
        ###############################

        # Create policy
        Policy(self.manage_ui, "otppin3", "authentication",
               "otppin=3",
               "*",
               "*")  # user = "******"

        # Create event based HMAC token
        # Tokens were imported by self.import_tokens()
        self.user_view.select_realm(user_a_realm)
        self.user_view.select_user(user_a)

        # Unhexlify for hotp.generate method
        seed_oath137332_bin = binascii.unhexlify(self.seed_oath137332)

        # Assign token to user
        # Set a pin
        self.token_view.assign_token(self.serial_oath137332,
                                     user_a_token_pin)

        # authentication tests
        # - PIN+OTP -> successfully
        # - PW+OTP -> successfully
        # - nonsense+OTP -> successfully
        # - OTP -> successfully
        # - wront OTP -> fails

        hotp_a = HmacOtp()

        # PIN+OTP -> success
        otp = user_a_token_pin + \
            hotp_a.generate(counter=0,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        assert access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " + \
                        user_a + "@" + user_a_realm + " returned False"

        # PW+OTP -> success
        otp = user_a_pw + \
            hotp_a.generate(counter=1,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        assert access_granted, "OTPPIN=3, PW+OTP: " + otp + " for user " + \
                        user_a + "@" + user_a_realm + " returned False"

        # nonsense+OTP -> success
        otp = "nonsense" + \
            hotp_a.generate(counter=2,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        assert access_granted, "OTPPIN=3, nonsense+OTP: " + otp + " for user " + \
                        user_a + "@" + user_a_realm + " returned False"

        # OTP -> success
        otp = hotp_a.generate(counter=3,
                              key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        assert access_granted, "OTPPIN=3, OTP: " + otp + " for user " + \
                        user_a + "@" + user_a_realm + " returned False"

        # wrong OTP -> fails
        otp = "111111"

        access_denied, _ = self.validate.validate(user=user_a + "@" +
                                                  user_a_realm, password=otp)
        assert not access_denied, "OTPPIN=3, wrong OTP: " + otp + " for user " + \
                         user_a + "@" + user_a_realm + " returned True"

        ###########################
        #
        # Bring user B into game
        #
        # change policy
        #    user = resolverB:
        #
        # So the ignore_pin should
        # should only affect users
        # in resolverB
        #
        ###########################

        # Change policy
        Policy(self.manage_ui, "otppin3", "authentication",
               "otppin=3",
               "*",  # realm
               data.sql_resolver["name"] + ":")  # pick specific resolver

        hotp_b = HmacOtp()

        # PIN+OTP -> success
        otp = user_b_token_pin + \
            hotp_b.generate(counter=0,
                            key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        assert access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " + \
                        user_b + "@" + user_b_realm + " returned False"

        # PW+OTP -> success
        otp = user_b_pw + \
            hotp_b.generate(counter=1,
                            key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        assert access_granted, "OTPPIN=3, PW+OTP: " + otp + " for user " + \
                        user_b + "@" + user_b_realm + " returned False"

        # OTP -> success
        otp = hotp_b.generate(counter=2,
                              key=user_b_token_seed_bin)

        access_granted, _ = self.validate.validate(user=user_b + "@" +
                                                   user_b_realm, password=otp)
        assert access_granted, "OTPPIN=3, OTP: " + otp + " for user " + \
                        user_b + "@" + user_b_realm + " returned False"

        # wrong OTP -> fails
        otp = "111111"

        access_denied, _ = self.validate.validate(user=user_b + "@" +
                                                  user_b_realm, password=otp)
        assert not access_denied, "OTPPIN=3, wrong OTP: " + otp + " for user " + \
                         user_b + "@" + user_b_realm + " returned False"

        # Back to user A and try to authenticate
        # with changed policy!

        # OTP -> fails
        otp = hotp_a.generate(counter=4,
                              inc_counter=False,
                              key=seed_oath137332_bin)

        access_denied, _ = self.validate.validate(user=user_a + "@" +
                                                  user_a_realm, password=otp)
        assert not access_denied, "OTPPIN=3, OTP: " + otp + " for user " + \
                         user_a + "@" + user_a_realm + " returned True"

        # PIN+OTP -> success
        otp = user_a_token_pin + \
            hotp_a.generate(counter=4,
                            key=seed_oath137332_bin)

        access_granted, _ = self.validate.validate(user=user_a + "@" +
                                                   user_a_realm, password=otp)
        assert access_granted, "OTPPIN=3, PIN+OTP: " + otp + " for user " + \
                        user_a + "@" + user_a_realm + " returned False"
Ejemplo n.º 48
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

        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