Beispiel #1
0
    def _getEmailProviderConfig(self):
        """
        get the defined e-mail provider config definition

        :return: dict of the e-mail provider definition
        :rtype: dict
        """
        LOG.debug('[getEmailProviderConfig] begin. load the e-mail ' +
                  'provider config definition')

        config = {}
        tConfig = getFromConfig("enclinotp.EmailProviderConfig", None)
        if tConfig is None:
            tConfig = getFromConfig("EmailProviderConfig", "{}")

        LOG.debug("[getEmailProviderConfig] provider config: %s"
                  % tConfig)

        try:
            if tConfig is not None:
                config = loads(tConfig)
        except ValueError as exx:
            raise ValueError('Failed to load provider config:%r %r'
                             % (tConfig, exx))

        LOG.debug('[getEmailProviderConfig] e-mail provider config'
                  ' found: config %r' % (config))
        return config
Beispiel #2
0
    def get_challenge_validity(self):
        '''
        This method returns the token specific challenge validity

        :return: int - validity in seconds
        '''

        validity = 120

        try:
            validity = int(getFromConfig('DefaultChallengeValidityTime', 120))

            # handle the token specific validity
            typ = self.getType()
            lookup_for = typ.capitalize() + 'ChallengeValidityTime'
            validity = int(getFromConfig(lookup_for, validity))

            # instance specific timeout
            validity = int(self.getFromTokenInfo('challenge_validity_time',
                                                 validity))

        except ValueError:
            validity = 120

        return validity
Beispiel #3
0
    def check_encryption(self):
        """
        check if a value, which got written into config, got encrypted
        :return:
        """
        test_key = 'linotp.testkey'

        linotp_conf = LinOtpConfig()

        if test_key not in linotp_conf:
            storeConfig(test_key, '', typ='password', desc=None)

        old_value = getFromConfig(test_key, defVal=None)

        now = datetime.datetime.now()
        new_value_plain = unicode(now)

        storeConfig(test_key, new_value_plain, typ='password', desc=None)

        new_value_enc = getFromConfig(test_key, defVal=None)

        # if new_value_enc != old_value: something new was written into db
        # if new_value_enc != new_value_plain: the new value got encrypted
        if new_value_enc and new_value_plain != new_value_enc != old_value:
            return True

        return False
Beispiel #4
0
    def loadLinOtpSMSProviderConfig(self):
        '''
        load the defined sms provider config definition

        :return: dict of the sms provider definition
        :rtype: dict
        '''
        log.debug('[loadLinOtpSMSProviderConfig] begin. load the sms ' +
                                                  'provider config definition')

        ## get User realm
        config = {}

        tConfig = getFromConfig("enclinotp.SMSProviderConfig", None)
        if tConfig is None:
            tConfig = getFromConfig("SMSProviderConfig", "{}")

        ## fix the handling of multiline config entries
        lconfig = []
        lines = tConfig.splitlines()
        for line in lines:
            line = line.strip('\\')
            if len(line) > 0:
                lconfig.append(line)

        tConfig = " ".join(lconfig)
        log.debug("[loadLinOtpSMSProviderConfig] providerconfig: %s"
                                                                    % tConfig)

        if tConfig is not None:
            config = loads(tConfig)

        log.debug('[loadLinOtpSMSProviderConfig] sms provider config' +
                                                ' found: config %r' % (config))
        return config
Beispiel #5
0
    def loadLinOtpSMSProviderConfig(self):
        """
        load the defined sms provider config definition

        :return: dict of the sms provider definition
        :rtype: dict
        """
        log.debug("[loadLinOtpSMSProviderConfig] begin. load the sms " + "provider config definition")

        # # get User realm
        config = {}

        tConfig = getFromConfig("enclinotp.SMSProviderConfig", None)
        if tConfig is None:
            tConfig = getFromConfig("SMSProviderConfig", "{}")

        # # fix the handling of multiline config entries
        lconfig = []
        lines = tConfig.splitlines()
        for line in lines:
            line = line.strip("\\")
            if len(line) > 0:
                lconfig.append(line)

        tConfig = " ".join(lconfig)
        log.debug("[loadLinOtpSMSProviderConfig] providerconfig: %s" % tConfig)
        try:
            if tConfig is not None:
                config = loads(tConfig)
        except ValueError as exx:
            raise ValueError("Failed to load provider config:%r %r" % (tConfig, exx))

        log.debug("[loadLinOtpSMSProviderConfig] sms provider config" + " found: config %r" % (config))
        return config
Beispiel #6
0
    def autosync(self, hmac2Otp, anOtpVal):
        '''
        auto - sync the token based on two otp values
        - internal method to realize the autosync within the
        checkOtp method

        :param hmac2Otp: the hmac object (with reference to the token secret)
        :type hmac2Otp: hmac object

        :param anOtpVal: the actual otp value
        :type anOtpVal: string

        :return: counter or -1 if otp does not exist
        :rtype:  int

        '''
        log.debug("[autosync] begin. Autosync the token, based on: hmac2Otp: %r, anOtpVal: %r" % (hmac2Otp, anOtpVal))

        res = -1
        autosync = False

        ## get autosync from config or use False as default
        async = getFromConfig("AutoResync", False)
        # TODO: nasty:
        # The SQLite database returns AutoResync as a boolean and not as a string.
        # So the boolean has no .lower()
        if isinstance(async, bool):
            autosync = async
Beispiel #7
0
def _initalGetRealms():
    '''
    initaly parse all config entries, and extract the realm definition

    :return : a dict with all realm definitions
    :rtype  : dict of definitions
    '''

    Realms = {}
    defRealmConf = "linotp.useridresolver"
    realmConf = "linotp.useridresolver.group."
    defaultRealmDef = "linotp.DefaultRealm"
    defaultRealm = None

    dc = getLinotpConfig()
    for entry in dc:

        if entry.startswith(realmConf):

            #the realm might contain dots "."
            # so take all after the 3rd dot for realm
            r = {}
            realm = entry.split(".", 3)
            theRealm = realm[3].lower()
            r["realmname"] = realm[3]
            r["entry"] = entry

            ##resids          = env.config[entry]
            resids = getFromConfig(entry)

            # we adjust here the *ee resolvers from the config
            # so we only have to deal with the un-ee resolvers in the server
            # which match the available resolver classes

            resids = resids.replace("useridresolveree.", "useridresolver.")
            r["useridresolver"] = resids.split(",")

            Realms[theRealm] = r

        if entry == defRealmConf:
            r = {}

            theRealm = "_default_"
            r["realmname"] = theRealm
            r["entry"] = defRealmConf

            #resids          = env.config[entry]
            resids = getFromConfig(entry)
            r["useridresolver"] = resids.split(",")

            defaultRealm = "_default_"
            Realms[theRealm] = r

        if entry == defaultRealmDef:
            defaultRealm = getFromConfig(defaultRealmDef)

    if defaultRealm is not None:
        _setDefaultRealm(Realms, defaultRealm)

    return Realms
Beispiel #8
0
    def autosync(self, hmac2Otp, anOtpVal):
        '''
        auto - sync the token based on two otp values
        - internal method to realize the autosync within the
        checkOtp method

        :param hmac2Otp: the hmac object (with reference to the token secret)
        :type hmac2Otp: hmac object

        :param anOtpVal: the actual otp value
        :type anOtpVal: string

        :return: counter or -1 if otp does not exist
        :rtype:  int

        '''
        log.debug("[autosync] begin. Autosync the token, based on: hmac2Otp: %r, anOtpVal: %r" % (hmac2Otp, anOtpVal))

        res = -1
        autosync = False

        try:
            async = getFromConfig("AutoResync")
            if async is None:
                autosync = False
            elif "true" == async.lower():
                autosync = True
Beispiel #9
0
    def __init__(self, aToken):
        '''
        constructor - create a token object

        :param aToken: instance of the orm db object
        :type aToken:  orm object

        '''

        TokenClass.__init__(self, aToken)
        self.setType(u"TOTP")
        self.hKeyRequired = True

        ''' timeStep defines the granularity: '''
        self.timeStep = getFromConfig("totp.timeStep", 30) or 30

        ''' window size in seconds:
            30 seconds with as step width of 30 seconds results
            in a window of 1  which is one attempt
        '''
        self.timeWindow = getFromConfig("totp.timeWindow", 180) or 180


        '''the time shift is specified in seconds  - and could be
        positive and negative
        '''
        self.timeShift = getFromConfig("totp.timeShift", 0)

        '''we support various hashlib methods, but only on create
        which is effectively set in the update
        '''
        self.hashlibStr = getFromConfig("totp.hashlib", u'sha1') or 'sha1'

        return
Beispiel #10
0
def _initalGetRealms():
    '''
    initaly parse all config entries, and extract the realm definition

    :return : a dict with all realm definitions
    :rtype  : dict of definitions
    '''

    Realms = {}
    defRealmConf = "linotp.useridresolver"
    realmConf = "linotp.useridresolver.group."
    defaultRealmDef = "linotp.DefaultRealm"
    defaultRealm = None


    dc = getLinotpConfig()
    for entry in dc:

        if entry.startswith(realmConf):

            #the realm might contain dots "."
            # so take all after the 3rd dot for realm
            r = {}
            realm = entry.split(".", 3)
            theRealm = realm[3].lower()
            r["realmname"] = realm[3]
            r["entry"] = entry

            ##resids          = env.config[entry]
            resids = getFromConfig(entry)
            r["useridresolver"] = resids.split(",")

            Realms[theRealm] = r

        if entry == defRealmConf:
            r = {}

            theRealm = "_default_"
            r["realmname"] = theRealm
            r["entry"] = defRealmConf

            #resids          = env.config[entry]
            resids = getFromConfig(entry)
            r["useridresolver"] = resids.split(",")

            defaultRealm = "_default_"
            Realms[theRealm] = r

        if entry == defaultRealmDef:
            defaultRealm = getFromConfig(defaultRealmDef)

    if defaultRealm is not None:
        _setDefaultRealm(Realms, defaultRealm)

    return Realms
Beispiel #11
0
    def setDefaults(self):
        # set the defaults

        self.token.LinOtpOtpLen = int(
            getFromConfig("DefaultOtpLen") or 6)
        self.token.LinOtpCountWindow = int(
            getFromConfig("DefaultCountWindow") or 10)
        self.token.LinOtpMaxFail = int(
            getFromConfig("DefaultMaxFailCount") or 10)
        self.token.LinOtpSyncWindow = int(
            getFromConfig("DefaultSyncWindow") or 1000)

        self.token.LinOtpTokenType = u'' + self.type
        return
Beispiel #12
0
def verify_duration(lic_dict, raiseException=False):
    """
    verify that the license duration is not already expired

    :param lic_dict: the license info object
    :return: boolean, if expired or not
    """

    if not (lic_dict.license_expiration
            and 'days' in lic_dict.license_expiration):
        return False

    date_format = "%d%m%y"

    # get the decrypted value from the config, if there is one
    duration = getFromConfig('enclinotp.license_duration', None)

    # no entry set by now, so this must be an error
    if not duration:
        log.error("License incorrectly installed!")
        return False

    # ok, we already have an entry
    else:
        # fetch config and split the signature and the expiration date
        _signature, _sep, date = duration.rpartition(':')
        expiration_date = datetime.datetime.strptime(date, date_format)
        now = datetime.datetime.now()
        if now > expiration_date + datetime.timedelta(days=1):
            return False

    return True
def test_local_admins_enable_command(app, runner, resolver, res_list):

    # Forcibly remove the resolver from the admin realm.
    admin_realm_name = app.config["ADMIN_REALM_NAME"].lower()
    admin_resolvers_key = f"useridresolver.group.{admin_realm_name}"

    set_config(
        key=admin_resolvers_key,
        value=res_list,
        typ="text",
        description="None",
    )
    resolver.session.commit()

    # Try to re-add it using the enable command.
    result = runner.invoke(cli_main, ["local-admins", "enable"])

    assert result.exit_code == 0

    # See whether it is there now.
    admin_resolvers = getFromConfig(admin_resolvers_key, "")
    if admin_resolvers:
        first_resolver = admin_resolvers.split(",")[0].strip()
        assert (
            first_resolver
            == "useridresolver.SQLIdResolver.IdResolver."
            + resolver.admin_resolver_name
        )
    else:
        assert False, "still no resolvers in admin realm"
Beispiel #14
0
    def get_config_items(self):
        """
        iterator function, to return a config entry in the migration format

        it reads all config entries from the config table, which have the type
        password. The decrypted value is taken from the linotp config

        :return: dictionary with the config entry: key, type, description
                 and the value, which is a dict with the encryption relevant
                 data like: encrypted_data, iv, mac
        """

        config_entries = model_config.query.filter_by(Type="password").all()
        for entry in config_entries:

            key = "enc%s" % entry.Key
            value = getFromConfig(key)

            # calculate encryption and add mac from mac_data
            enc_value = self.crypter.encrypt(input_data=value,
                                             just_mac=key + entry.Value)

            config_item = {
                "Key": entry.Key,
                "Value": enc_value,
                "Type": entry.Type,
                "Description": entry.Description,
            }

            yield config_item
Beispiel #15
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)
Beispiel #16
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)
Beispiel #17
0
    def get_config_items(self):
        """
        iterator function, to return a config entry in the migration format

        it reads all config entries from the config table, which have the type
        password. The decrypted value is taken from the linotp config

        :return: dictionary with the config entry: key, type, description
                 and the value, which is a dict with the encryption relevant
                 data like: encrypted_data, iv, mac
        """

        config_entries = Session.query(model_config).\
                         filter(model_config.Type == 'password').all()
        for entry in config_entries:

            key = 'enc%s' % entry.Key
            value = getFromConfig(key)

            # calculate encryption and add mac from mac_data
            enc_value = self.crypter.encrypt(input_data=value,
                                             just_mac=key + entry.Value)

            config_item = {
                "Key": entry.Key,
                "Value": enc_value,
                "Type": entry.Type,
                "Description": entry.Description
            }

            yield config_item
Beispiel #18
0
def get_client(request):
    '''
    This function returns the client.

    It first tries to get the client as it is passed as the HTTP Client
    via REMOTE_ADDR.

    If this client Address is in a list, that is allowed to overwrite its
    client address (like e.g. a FreeRADIUS server, which will always pass the
    FreeRADIUS address but not the address of the RADIUS client) it checks for
    the existance of the client parameter.
    '''
    may_overwrite = []
    over_client = getFromConfig("mayOverwriteClient", "")
    try:
        may_overwrite = [c.strip() for c in over_client.split(',')]
    except Exception as e:
        log.warning("evaluating config entry 'mayOverwriteClient': %r" % e)

    client = _get_client_from_request(request)

    if client in may_overwrite or client is None:
        log.debug("client %s may overwrite!" % client)

        client = get_request_param(request, "client")
        if client:
            log.debug("client overwritten to %s" % client)

    log.debug("returning client %s" % client)
    return client
Beispiel #19
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)
Beispiel #20
0
def getSupportLicenseInfo():
    """
    get the current support and subscription information

    :param validate: inform program to validate or not the license info
    :return: tuple of dict with the license information and signature
             in case of an error, the dict and the signature are empty
    """
    refreshConfig()
    lic_dict = LicenseInfo()
    lic_sign = ""

    try:
        licString = getFromConfig("license", '')

        if licString:

            lic_text = binascii.unhexlify(licString.encode('utf-8')).decode()
            lic_dict, lic_sign = parseSupportLicense(lic_text)
            lic_dict['expire'] = get_expiration_date(lic_dict)

    except InvalidLicenseException as exx:
        log.info('Invalid license error: %r' % exx)

    return lic_dict, lic_sign
Beispiel #21
0
    def _getEmailProviderClass(self):
        """
        getEmailProviderClass():

        helper method to load the EmailProvider class from config

        checks, if the submitMessage method exists
        if not an error is thrown
        """
        LOG.debug('[getEmailProviderClass] begin. get the e-mail Provider '
                  'class definition')
        email_provider = getFromConfig("EmailProvider",
                                       self.DEFAULT_EMAIL_PROVIDER)
        if not email_provider:
            raise Exception("No EmailProvider defined.")
        (email_provider_package,
         email_provider_class_name) = email_provider.rsplit(".", 1)

        if not email_provider_package or not email_provider_class_name:
            raise Exception(
                "Could not load e-mail provider class. Maybe EmailProvider is "
                "not set in the config file.")

        mod = __import__(email_provider_package, globals(), locals(),
                         [email_provider_class_name])
        # TODO Kay sagt hier soll das Modul global geladen werden (mit einem bisher nicht existierenden Hook)
        provider_class = getattr(mod, email_provider_class_name)
        if not hasattr(provider_class, "submitMessage"):
            raise NameError(
                "EmailProvider AttributeError: " + email_provider_package +
                "." + email_provider_class_name +
                " instance of EmailProvider has no method 'submitMessage'")
        return provider_class
Beispiel #22
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.utcnow())
        if curTime:
            tCounter = self.time2float(curTime)

        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)
Beispiel #23
0
def getSupportLicenseInfo():
    """
    get the current support and subscription information

    :return: dict with the license informstion
    """
    info = {}

    refreshConfig()
    licString = getFromConfig("license", None)
    if licString:
        try:
            lic_str = binascii.unhexlify(licString)
        except TypeError:
            lic_str = licString
        (info, _lic_sign, _lic_txt) = parseSupportLicense(lic_str)

    else:
        # if we have no licens in the config, we compose the
        # comuninity edition text
        info.update(support_info)
        version = get_version_number()
        info["version"] = "LinOTP %s" % version

    return info
Beispiel #24
0
    def createChallenge(self, transactionid, options=None):
        """
        This method creates a challenge, which is submitted to the user.
        The submitted challenge will be preserved in the challenge
        database.

        This method is called *after* the method
        :py:meth:`~linotp.tokens.base.TokenClass.initChallenge`.

        :param transactionid: the id of this challenge
        :param options: the request context parameters / data
        :type options: dict
        :return: tuple of (bool, message, data, attributes)

        The return tuple builds up like this:

        ``bool`` if submit was successfull;
        ``message`` which is displayed in the JSON response;
        ``data`` is preserved in the challenge;
        additional ``attributes``, which are displayed in the JSON response.
        """

        message = getFromConfig(self.type.upper() + "_CHALLENGE_PROMPT",
                                'Otp: ')

        data = {'serial': self.getSerial()}
        attributes = None
        return (True, message, data, attributes)
    def getOtp(self, curTime=None):
        ## kay: init value
        res = (-1, 0, 0, 0)

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError:
            return res

        secObj = self._get_secret_object()
        dpw = dpwOtp(secObj, otplen)

        date_string = None
        if curTime:
            if type(curTime) == datetime.datetime:
                date_string = curTime.strftime("%d%m%y")
            elif type(curTime) == unicode:
                date_string = datetime.datetime.strptime(
                    curTime, "%Y-%m-%d %H:%M:%S.%f").strftime("%d%m%y")
            else:
                log.error(
                    "[getOtp] invalid curTime: %r. You need to specify a datetime.datetime"
                    % type(curTime))
        otpval = dpw.getOtp(date_string)
        pin = self.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True":
            combined = "%s%s" % (pin, otpval)

        return (1, pin, otpval, combined)
Beispiel #26
0
def check_license_restrictions():
    """
    check if there are restrictions, which are caused by the license

    :return: boolean - True if there are  restrictions
    """

    license_str = getFromConfig('license')
    if not license_str:
        return False

    licString = binascii.unhexlify(license_str).decode()
    lic_dict, lic_sign = parseSupportLicense(licString)
    res, reason = verifyLicenseInfo(
        lic_dict, lic_sign, checkVolume=False, raiseException=False)

    if not res:
        log.info("license check: %r", reason)
        return True

    res, msg = verify_volume(lic_dict)
    if not res:
        log.info("License check: Too many tokens enrolled %r", msg)
        return True

    res, _msg = verify_expiration(lic_dict)
    if res is False:
        log.info("License check: License expired!")
        return True

    return False
Beispiel #27
0
    def __init__(self, a_token):
        '''
        constructor - create a token object

        :param aToken: instance of the orm db object
        :type aToken:  orm object

        '''
        log.debug("[init]  begin. Create a token object with: a_token %r" %
                  (a_token))

        TokenClass.__init__(self, a_token)
        self.setType(u"HMAC")
        self.hKeyRequired = True

        # we support various hashlib methods, but only on create
        # which is effectively set in the update

        self.hashlibStr = u"sha1"
        try:
            self.hashlibStr = getFromConfig("hotp.hashlib", u'sha1')
        except Exception as ex:
            log.error('[init] Failed to get the hotp.hashlib (%r)' % (ex))
            raise Exception(ex)

        log.debug("[init]  end. Token object created")
        return
Beispiel #28
0
def get_challenges(serial=None, transid=None):
    '''
    get_challenges - give all challenges for a given token

    :param serial:   serial of the token
    :param transid:  transaction id, if None, all will be retrieved
    :return:         return a list of challenge dict
    '''
    log.debug('[get_challenges] %r' % (serial))

    challenges = []
    if transid is None and serial is None:
        return challenges

    if transid is None:
        db_challenges = Session.query(Challenge)\
            .filter(Challenge.tokenserial == u'' + serial)\
            .order_by(desc(Challenge.id))\
            .all()
    else:
        transid_len = int(getFromConfig('TransactionIdLength', 12))
        if len(transid) == transid_len:
            db_challenges = Session.query(Challenge)\
                .filter(Challenge.transid == transid)\
                .all()
        else:
            db_challenges = Session.query(Challenge)\
                .filter(Challenge.transid.startswith(transid))\
                .all()

    challenges.extend(db_challenges)

    log.debug('[getTransactions4serial] %r' % challenges)
    return challenges
Beispiel #29
0
def get_challenges(serial=None, transid=None):
    '''
    get_challenges - give all challenges for a given token

    :param serial:   serial of the token
    :param transid:  transaction id, if None, all will be retrieved
    :return:         return a list of challenge dict
    '''
    log.debug('[get_challenges] %r' % (serial))

    challenges = []
    if transid is None and serial is None:
        return challenges

    if transid is None:
        db_challenges = Session.query(Challenge)\
            .filter(Challenge.tokenserial == u'' + serial)\
            .order_by(desc(Challenge.id))\
            .all()
    else:
        transid_len = int(getFromConfig('TransactionIdLength', 12))
        if len(transid) == transid_len:
            db_challenges = Session.query(Challenge)\
                .filter(Challenge.transid == transid)\
                .all()
        else:
            db_challenges = Session.query(Challenge)\
                .filter(Challenge.transid.startswith(transid))\
                .all()

    challenges.extend(db_challenges)

    log.debug('[getTransactions4serial] %r' % challenges)
    return challenges
Beispiel #30
0
def test_getsearchfields_case_sensitive_resolver_names(fthsm, app):

    g.request_context["Config"] = getLinotpConfig()  # This sucks.
    g.request_context["CacheManager"] = app.cache  # This sucks even worse.

    admin_realm_name = app.config["ADMIN_REALM_NAME"]
    admin_resolvers_key = f"useridresolver.group.{admin_realm_name}"
    admin_resolvers = getFromConfig(admin_resolvers_key, "")
    _, _, aci = admin_resolvers.rpartition(".")

    user = User(
        login="******", realm=admin_realm_name, resolver_config_identifier=aci
    )

    # If the user's resolver config identifier matches its resolver, then the
    # `getSearchFields` function should return a set of search fields. If there
    # is no match, the result should be empty. Hence if we tweak the RCI to be
    # the uppercase version, then if the comparison is case-sensitive the result
    # should be empty.

    user.resolver_config_identifier = user.resolver_config_identifier.upper()
    search_fields = getSearchFields(user)
    assert (
        not search_fields
    ), "getSearchFields resolver name comparison is not case-sensitive"
Beispiel #31
0
def test_getuserlist_case_sensitive_resolver_names(fthsm, app, admin_res):

    g.request_context["Config"] = getLinotpConfig()  # This sucks.
    g.request_context["CacheManager"] = app.cache  # This sucks even worse.
    g.request_context["UserLookup"] = {}  # Don't get me started.

    admin_realm_name = app.config["ADMIN_REALM_NAME"]
    admin_resolvers_key = f"useridresolver.group.{admin_realm_name}"
    admin_resolvers = getFromConfig(admin_resolvers_key, "")
    _, _, aci = admin_resolvers.rpartition(".")

    # As before, if we make the RCI uppercase and the `getUserList()` function
    # still returns a user list, then the comparison must have been
    # case-insensitive. With a case-sensitive comparison, the result should
    # be empty.

    search_user = User(
        login="******",
        realm=admin_realm_name,
        resolver_config_identifier=aci.upper(),
    )
    user_list = getUserList({}, search_user)
    assert (
        not user_list
    ), "getUserList resolver name comparison is not case-sensitive"
Beispiel #32
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)
Beispiel #33
0
def getSupportLicenseInfo():
    """
    get the current support and subscription information

    :return: dict with the license informstion
    """
    info = {}

    refreshConfig()
    licString = getFromConfig("license", None)
    if licString:
        try:
            lic_str = binascii.unhexlify(licString)
        except TypeError:
            lic_str = licString
        (info, _lic_sign, _lic_txt) = parseSupportLicense(lic_str)

    else:
        # if we have no licens in the config, we compose the
        # comuninity edition text
        info.update(support_info)
        version = get_version_number()
        info['version'] = 'LinOTP %s' % version

    return info
Beispiel #34
0
    def __init__(self, a_token):
        '''
        constructor - create a token object

        :param aToken: instance of the orm db object
        :type aToken:  orm object

        '''
        log.debug("[init]  begin. Create a token object with: a_token %r" % (a_token))

        TokenClass.__init__(self, a_token)
        self.setType(u"HMAC")
        self.hKeyRequired = True

        # we support various hashlib methods, but only on create
        # which is effectively set in the update

        self.hashlibStr = u"sha1"
        try:
            self.hashlibStr = getFromConfig("hotp.hashlib", u'sha1')
        except Exception as ex:
            log.error('[init] Failed to get the hotp.hashlib (%r)' % (ex))
            raise Exception(ex)


        log.debug("[init]  end. Token object created")
        return
Beispiel #35
0
    def createChallenge(self, transactionid, options=None):
        """
        This method creates a challenge, which is submitted to the user.
        The submitted challenge will be preserved in the challenge
        database.

        This method is called *after* the method
        :py:meth:`~linotp.tokens.base.TokenClass.initChallenge`.

        :param transactionid: the id of this challenge
        :param options: the request context parameters / data
        :type options: dict
        :return: tuple of (bool, message, data, attributes)

        The return tuple builds up like this:

        ``bool`` if submit was successfull;
        ``message`` which is displayed in the JSON response;
        ``data`` is preserved in the challenge;
        additional ``attributes``, which are displayed in the JSON response.
        """

        message = getFromConfig(self.type.upper() + "_CHALLENGE_PROMPT",
                                'Otp: ')

        data = {'serial': self.getSerial()}
        attributes = None
        return (True, message, data, attributes)
Beispiel #36
0
def check_duration(expire, lic_info):
    """
    check duration - check only for duration in days

    :param: the expiration string value
    :return: tuple of bool and the amount of days as string
    """
    if 'days' not in expire:
        return False, 'no expiration days found!'

    lic_sign = lic_info.signature

    # if there is already a license with duration installed
    # check if it is still valid
    date_format = "%d%m%y"
    duration = getFromConfig('enclinotp.license_duration', None)

    if duration:
        signature, _sep, date = duration.rpartition(':')
        expiration_date = datetime.datetime.strptime(date, date_format)

        # only check the current license
        if base64.b64encode(lic_sign)[:500] == signature:
            now = datetime.datetime.now()
            expiration_date = datetime.datetime.strptime(date, date_format)

            # preserve the volatile expiration date
            lic_info["expire"] = expiration_date.strftime("%Y-%m-%d")

            if now > expiration_date + datetime.timedelta(days=1):
                return False, 'License expired'

    duration = int(expire.replace('days', '').strip())
    return duration > 0, "%d days" % duration
Beispiel #37
0
def get_client():
    '''
    This function returns the client.

    It first tries to get the client as it is passed as the HTTP Client via REMOTE_ADDR.

    If this client Address is in a list, that is allowed to overwrite its client address (like e.g.
    a FreeRADIUS server, which will always pass the FreeRADIUS address but not the address of the
    RADIUS client) it checks for the existance of the client parameter.
    '''
    may_overwrite = []
    over_client = getFromConfig("mayOverwriteClient", "")
    log.debug("[get_client] config entry mayOverwriteClient: %s" % over_client)
    try:
        may_overwrite = [ c.strip() for c in over_client.split(',') ]
    except Exception as e:
        log.warning("[get_client] evaluating config entry 'mayOverwriteClient': %r" % e)

    client = get_client_from_request()
    log.debug("[get_client] got the original client %s" % client)

    if client in may_overwrite or client == None:
        log.debug("[get_client] client %s may overwrite!" % client)
        if get_client_from_param():
            client = get_client_from_param()
            log.debug("[get_client] client overwritten to %s" % client)

    log.debug("[get_client] returning %s" % client)
    return client
Beispiel #38
0
def check_license_restrictions():
    """
    check if there are restrictions, which are caused by the license
    """

    license_str = getFromConfig('license')
    if not license_str:
        return False

    licString = binascii.unhexlify(license_str)
    lic_dict, lic_sign = parseSupportLicense(licString)
    res, reason = verifyLicenseInfo(lic_dict, lic_sign,
                                    raiseException=False)

    if not (lic_dict.license_type and lic_dict.license_type == 'demo'):
        return False

    import linotp.lib.token
    installed_tokens = int(linotp.lib.token.getTokenNumResolver())
    allowed_tokens = lic_dict.get('token-num', 'unlimited')
    try:
        allowed_tokens = int(allowed_tokens.strip())
        if installed_tokens >= allowed_tokens:
            return True
    except ValueError as _val_err:
        # in case of no int we ignore this restriction as it could
        # be a string representation like 'unlimited'
        pass

    res, _msg = verify_expiration(lic_dict)
    if res is False:
        return True

    return False
Beispiel #39
0
    def _getEmailProviderClass(self):
        """
        getEmailProviderClass():

        helper method to load the EmailProvider class from config

        checks, if the submitMessage method exists
        if not an error is thrown
        """
        LOG.debug('[getEmailProviderClass] begin. get the e-mail Provider '
                  'class definition')
        email_provider = getFromConfig("EmailProvider",
                                       self.DEFAULT_EMAIL_PROVIDER)
        if not email_provider:
            raise Exception("No EmailProvider defined.")
        (email_provider_package, email_provider_class_name) = \
                                                email_provider.rsplit(".", 1)

        if not email_provider_package or not email_provider_class_name:
            raise Exception("Could not load e-mail provider class. Maybe "
                            "EmailProvider is not set in the config file.")

        mod = __import__(email_provider_package, globals(), locals(),
                         [email_provider_class_name])

        # TODO Kay sagt hier soll das Modul global geladen werden (mit einem
        #     bisher nicht existierenden Hook)

        provider_class = getattr(mod, email_provider_class_name)
        if not hasattr(provider_class, "submitMessage"):
            raise NameError("EmailProvider AttributeError: %s.%s instance of "
                            "EmailProvider has no method 'submitMessage'" %
                            (email_provider_package, email_provider_class_name))

        return provider_class
Beispiel #40
0
def check_duration(expire, lic_info):
    """
    check duration - check only for duration in days

    :param: the expiration string value
    :return: tuple of bool and the amount of days as string
    """
    if 'days' not in expire:
        return False, 'no expiration days found!'

    lic_sign = lic_info.signature

    # if there is already a license with duration installed
    # check if it is still valid
    date_format = "%d%m%y"
    duration = getFromConfig('enclinotp.license_duration', None)

    if duration:
        signature, _sep, date = duration.rpartition(':')
        expiration_date = datetime.datetime.strptime(date, date_format)

        # only check the current license
        if base64.b64encode(lic_sign)[:500] == signature:
            now = datetime.datetime.now()
            expiration_date = datetime.datetime.strptime(date, date_format)

            # preserve the volatile expiration date
            lic_info["expire"] = expiration_date.strftime("%Y-%m-%d")

            if now > expiration_date + datetime.timedelta(days=1):
                return False, 'License expired'

    duration = int(expire.replace('days', '').strip())
    return duration > 0, "%d days" % duration
Beispiel #41
0
def verify_duration(lic_dict, raiseException=False):
    """
    verify that the license duration is not already expired

    :param lic_dict: the license info object
    :return: boolean, if expired or not
    """

    if not (lic_dict.license_expiration and
            'days' in lic_dict.license_expiration):
        return False

    date_format = "%d%m%y"

    # get the decrypted value from the config, if there is one
    duration = getFromConfig('enclinotp.license_duration', None)

    # no entry set by now, so this must be an error
    if not duration:
        log.error("license incorrectly installed!")
        return False

    # ok, we already have an entry
    else:
        # fetch config and split the signature and the expiration date
        _signature, _sep, date = duration.rpartition(':')
        expiration_date = datetime.datetime.strptime(date, date_format)
        now = datetime.datetime.now()
        if now > expiration_date + datetime.timedelta(days=1):
            return False

    return True
Beispiel #42
0
    def getOtp(self, curTime=None):
        ## kay: init value
        res = (-1, 0, 0, 0)

        try:
            otplen = int(self.token.LinOtpOtpLen)
        except ValueError:
            return res

        secretHOtp = self.token.getHOtpKey()

        dpw = dpwOtp(secretHOtp, otplen)

        date_string = None
        if curTime:
            if type(curTime) == datetime.datetime:
                date_string = curTime.strftime("%d%m%y")
            elif type(curTime) == unicode:
                date_string = datetime.datetime.strptime(curTime, "%Y-%m-%d %H:%M:%S.%f").strftime("%d%m%y")
            else:
                log.error("[getOtp] invalid curTime: %r. You need to specify a datetime.datetime" % type(curTime))
        otpval = dpw.getOtp(date_string)
        pin = self.token.getPin()
        combined = "%s%s" % (otpval, pin)
        if getFromConfig("PrependPin") == "True" :
            combined = "%s%s" % (pin, otpval)

        return (1, pin, otpval, combined)
Beispiel #43
0
    def samlcheck(self):
        '''
        This function is used to validate the username and the otp value/password
        in a SAML environment. If ``linotp.allowSamlAttributes = True``
        then the attributes of the authenticated users are also contained
        in the response.

        method:
            validate/samlcheck

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixes password component and the OTP value
            * realm:   optional realm to match the user to a useridresolver

        returns:
            JSON response
        '''

        try:
            opt = None
            param = self.request_params
            (ok, opt) = self._check(param)
            attributes = {}

            if True == ok:
                allowSAML = False
                try:
                    allowSAML = getFromConfig("allowSamlAttributes")
                except:
                    log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False.")
                if "True" == allowSAML:
                    ## Now we get the attributes of the user
                    user = getUserFromParam(param)
                    (uid, resId, resIdC) = getUserId(user)
                    userInfo = getUserInfo(uid, resId, resIdC)
                    log.debug("[samlcheck] getting attributes for: %s@%s"
                              % (user.login, user.realm))

                    res = userInfo
                    for key in ['username',
                                'surname',
                                'mobile',
                                'phone',
                                'givenname',
                                'email']:
                        if key in res:
                            attributes[key] = res[key]

            Session.commit()
            return sendResult(response, { 'auth': ok, 'attributes' : attributes } , 0, opt)

        except Exception as exx:
            log.exception("[samlcheck] validate/check failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
Beispiel #44
0
    def samlcheck(self):
        '''
        This function is used to validate the username and the otp value/password
        in a SAML environment. If ``linotp.allowSamlAttributes = True``
        then the attributes of the authenticated users are also contained
        in the response.

        method:
            validate/samlcheck

        arguments:
            * user:    username / loginname
            * pass:    the password that consists of a possible fixes password component and the OTP value
            * realm:   optional realm to match the user to a useridresolver

        returns:
            JSON response
        '''

        try:
            opt = None
            param = request.params
            (ok, opt) = self._check(param)
            attributes = {}

            if True == ok:
                allowSAML = False
                try:
                    allowSAML = getFromConfig("allowSamlAttributes")
                except:
                    log.warning("[samlcheck] Calling controller samlcheck. But allowSamlAttributes is False.")
                if "True" == allowSAML:
                    ## Now we get the attributes of the user
                    user = getUserFromParam(param)
                    (uid, resId, resIdC) = getUserId(user)
                    userInfo = getUserInfo(uid, resId, resIdC)
                    log.debug("[samlcheck] getting attributes for: %s@%s"
                              % (user.login, user.realm))

                    res = userInfo
                    for key in ['username',
                                'surname',
                                'mobile',
                                'phone',
                                'givenname',
                                'email']:
                        if key in res:
                            attributes[key] = res[key]

            Session.commit()
            return sendResult(response, { 'auth': ok, 'attributes' : attributes } , 0, opt)

        except Exception as exx:
            log.exception("[samlcheck] validate/check failed: %r" % exx)
            Session.rollback()
            return sendResult(response, False, 0)

        finally:
            Session.close()
Beispiel #45
0
def getSplitAtSign():
    '''
    returns the config value of splitAtSign.
    if True, the username should be split if there is an at sign.
    if False, the username will be taken unchanged for loginname.
    '''
    splitAtSign = getFromConfig("splitAtSign", "true") or 'true'
    return "true" == splitAtSign.lower()
Beispiel #46
0
 def tokenview(self):
     """
     This is the template for the token TAB
     """
     c.title = "LinOTP Management"
     c.tokenArray = []
     c.getotp_active = boolean(getFromConfig("linotpGetotp.active", False))
     return render("/manage/tokenview.mako")
Beispiel #47
0
def getSplitAtSign():
    '''
    returns the config value of splitAtSign.
    if True, the username should be split if there is an at sign.
    if False, the username will be taken unchanged for loginname.
    '''
    splitAtSign = getFromConfig("splitAtSign", "true") or 'true'
    return "true" == splitAtSign.lower()
Beispiel #48
0
    def get_helper_params_post(cls, param, user=None):

        helper_param = {}

        tok_type = "ocra"

        # take the keysize from the ocrasuite
        ocrasuite = param.get("ocrasuite", None)
        activationcode = param.get("activationcode", None)
        sharedsecret = param.get("sharedsecret", None)
        serial = param.get("serial", None)
        genkey = param.get("genkey", None)

        if activationcode is not None:
            # dont create a new key
            genkey = None
            serial = getRolloutToken4User(user=user,
                                          serial=serial,
                                          tok_type=tok_type)
            if serial is None:
                raise Exception('no token found for user: %r or serial: %r' %
                                (user, serial))
            helper_param['serial'] = serial
            helper_param['activationcode'] = \
                normalize_activation_code(activationcode)

        if ocrasuite is None:
            if sharedsecret is not None or activationcode is not None:
                ocrasuite = getFromConfig("QrOcraDefaultSuite",
                                          'OCRA-1:HOTP-SHA256-6:C-QA64')
            else:
                ocrasuite = getFromConfig("OcraDefaultSuite",
                                          'OCRA-1:HOTP-SHA256-8:C-QN08')
            helper_param['ocrasuite'] = ocrasuite

        if genkey is not None:
            if ocrasuite.find('-SHA256'):
                key_size = 32
            elif ocrasuite.find('-SHA512'):
                key_size = 64
            else:
                key_size = 20
            helper_param['key_size'] = key_size

        return helper_param
Beispiel #49
0
def set_duration(lic_dict, raiseException=False):
    """
    set the duration value in linotp config and thus in config database

    :param lic_dict: the license info object
    :param raiseException: switch to control if an exception should be thrown
           in case of a problem
    """

    # if there is no expiration in the license we just can go on
    if not (lic_dict.license_expiration and
            'days' in lic_dict.license_expiration):
        return True

    lic_sign = lic_dict.signature
    days = lic_dict.license_expiration.replace('days', '').strip()
    try:
        days = int(days)
    except ValueError as _val:
        raise Exception('Unable to interpret duration in'
                        ' license description')

    # we have a timely limited version, so we have to check if there is
    # already a license like this installed by comparing the signatures
    date_format = "%d%m%y"

    # get the decrypted value from the config, if there is one
    expiration = getFromConfig('enclinotp.license_duration', None)
    if expiration:
        # fetch config and split the signature and the expiration date
        signature, _sep, _date_str = expiration.rpartition(':')

        # here we only verify that the license signature is not the same
        # - we only take a slice as the stored signature will be
        #   stored in an encrypted way and then will become too long
        if base64.b64encode(lic_sign)[:500] == signature:
            error = _('License already installed!')
            if raiseException:
                raise Exception(error)
            else:
                log.error(error)
                return False

    # so we calculate the expiration and store this together
    # with the license signature
    expires = datetime.datetime.now() + datetime.timedelta(days=days)
    expires_str = expires.strftime(date_format)

    # we take only some bytes as it is encrypted afterwards
    signature = base64.b64encode(lic_sign)[:500]
    license_expire = "%s:%s" % (signature, expires_str)

    storeConfig("license_duration", license_expire, typ='password')
    log.info("license_expiration %s" % license_expire)


    return True
Beispiel #50
0
def set_duration(lic_dict, raiseException=False):
    """
    set the duration value in linotp config and thus in config database

    :param lic_dict: the license info object
    :param raiseException: switch to control if an exception should be thrown
           in case of a problem
    """
    _ = context['translate']
    # if there is no expiration in the license we just can go on
    if not (lic_dict.license_expiration and
            'days' in lic_dict.license_expiration):
        return True

    lic_sign = lic_dict.signature
    days = lic_dict.license_expiration.replace('days', '').strip()
    try:
        days = int(days)
    except ValueError as _val:
        raise Exception('Unable to interpret duration in'
                        ' license description')

    # we have a timely limited version, so we have to check if there is
    # already a license like this installed by comparing the signatures
    date_format = "%d%m%y"

    # get the decrypted value from the config, if there is one
    expiration = getFromConfig('enclinotp.license_duration', None)
    if expiration:
        # fetch config and split the signature and the expiration date
        signature, _sep, _date_str = expiration.rpartition(':')

        # here we only verify that the license signature is not the same
        # - we only take a slice as the stored signature will be
        #   stored in an encrypted way and then will become too long
        if base64.b64encode(lic_sign)[:500] == signature:
            error = _('License already installed!')
            if raiseException:
                raise Exception(error)
            else:
                log.error(error)
                return False

    # so we calculate the expiration and store this together
    # with the license signature
    expires = datetime.datetime.now() + datetime.timedelta(days=days)
    expires_str = expires.strftime(date_format)

    # we take only some bytes as it is encrypted afterwards
    signature = base64.b64encode(lic_sign)[:500]
    license_expire = "%s:%s" % (signature, expires_str)

    storeConfig("license_duration", license_expire, typ='password')
    log.info("license_expiration %s" % license_expire)


    return True
Beispiel #51
0
    def maxChallengeJanitor(cls, transId=None, serial=None):
        '''
        maxChallengeJanitor - remove for one token (serial) all challengens
                              but the last ones

        :param transId:     the current transaction, which provides a
                            the lookup for the serial number
        :type transId:     string

        :param serial:     the serial number of the token
        :type serial:     string

        :return: - nothing

        '''

        maxChallDef = getFromConfig("OcraMaxChallenges", '3')
        try:
            ones = int(maxChallDef)
        except ValueError as ex:
            log.exception('Failed to convert OcraMaxChallenges value from '
                          'config: %r :%r' % (maxChallDef, ex))
            ones = 3

        if ones <= 0:
            ones = 3

        if transId is not None:
            challenges = Session.query(OcraChallenge).filter(
                OcraChallenge.transid == u'' + transId)
            if challenges is None:
                return

            for challenge in challenges:
                serial = challenge.tokenserial

        if serial is None:
            log.info('Ocra max challenge janitor: Failed to lookup result '
                     'for transid %r or serial %r' % (transId, serial))
            return

        challenges = Session.query(OcraChallenge).\
            filter(OcraChallenge.tokenserial == u'' + serial)\
            .order_by(desc(OcraChallenge.id))

        lastIds = set()
        for challenge in challenges:
            if len(lastIds) < ones:
                lastIds.add(challenge.id)
            else:
                log.info(
                    "Dropping ocra challenge %r (transaction id %r) "
                    "for token %r", challenge.id, challenge.transid,
                    challenge.tokenserial)
                Session.delete(challenge)

        return
Beispiel #52
0
    def __init__(self, aToken):
        HmacTokenClass.__init__(self, aToken)
        self.setType(u"email")
        self.hKeyRequired = False

        # we support various hashlib methods, but only on create
        # which is effectively set in the update
        self.hashlibStr = getFromConfig("hotp.hashlib", "sha1")
        self.mode = ['challenge']
Beispiel #53
0
    def __init__(self, aToken):
        HmacTokenClass.__init__(self, aToken)
        self.setType(u"sms")
        self.hKeyRequired = False

        # we support various hashlib methods, but only on create
        # which is effectively set in the update
        self.hashlibStr = getFromConfig("hotp.hashlib", "sha1")
        self.mode = ['challenge']
Beispiel #54
0
    def get_helper_params_post(cls, param, user=None):

        helper_param = {}

        tok_type = "ocra"

        # take the keysize from the ocrasuite
        ocrasuite = param.get("ocrasuite", None)
        activationcode = param.get("activationcode", None)
        sharedsecret = param.get("sharedsecret", None)
        serial = param.get("serial", None)
        genkey = param.get("genkey", None)

        if activationcode is not None:
            # dont create a new key
            genkey = None
            serial = getRolloutToken4User(user=user, serial=serial,
                                          tok_type=tok_type)
            if serial is None:
                raise Exception('no token found for user: %r or serial: %r'
                                % (user, serial))
            helper_param['serial'] = serial
            helper_param['activationcode'] = \
                normalize_activation_code(activationcode)

        if ocrasuite is None:
            if sharedsecret is not None or activationcode is not None:
                ocrasuite = getFromConfig("QrOcraDefaultSuite",
                                          'OCRA-1:HOTP-SHA256-6:C-QA64')
            else:
                ocrasuite = getFromConfig("OcraDefaultSuite",
                                          'OCRA-1:HOTP-SHA256-8:C-QN08')
            helper_param['ocrasuite'] = ocrasuite

        if genkey is not None:
            if ocrasuite.find('-SHA256'):
                key_size = 32
            elif ocrasuite.find('-SHA512'):
                key_size = 64
            else:
                key_size = 20
            helper_param['key_size'] = key_size

        return helper_param
Beispiel #55
0
def do_nagging(lic_info, nag_days=7):
    """
    do nagging - answer the question if nagging should be done

    :param lic_info: the license info
    :return: boolean - True if nagging should be displayed
    """
    d_fmt = "%Y-%m-%d"

    # we start 7 days after download license was installed
    nag_offset = nag_days

    if not (
        lic_info.license_type
        and (
            lic_info.license_type == "download"
            or lic_info.license_type == "demo"
        )
    ):
        return False

    # in case there is no duration definition in 'xx days' we do the nagging
    if not lic_info.license_expiration:
        log.error(
            "Download license format error: Missing expiration definition!"
        )
        return True

    now_date = datetime.datetime.now().date()

    expire = get_expiration_date(lic_info)
    expire_date = datetime.datetime.strptime(expire, d_fmt).date()

    # calculate back, when the license was enrolled
    duration = int(lic_info.license_expiration.replace("days", "").strip())
    lic_start_date = expire_date - datetime.timedelta(days=duration)

    # calulate the nagging start date with given nag_offset
    nag_start_date = lic_start_date + datetime.timedelta(days=nag_offset)

    if now_date <= nag_start_date:
        return False

    # ok, we are in the nagging time frame, so start nagging
    last_nagged = getFromConfig("last_nagged")
    if last_nagged:
        # nag only once a day: check, if we nagged already today
        last_nag_date = datetime.datetime.strptime(last_nagged, d_fmt).date()
        # check if we nagged already today
        if last_nag_date >= now_date:
            return False

    datum = now_date.strftime(d_fmt)
    storeConfig("last_nagged", datum, desc="last nagged")

    return True
Beispiel #56
0
def getUserFromParam(param,
                     optionalOrRequired,
                     optional=False,
                     required=False):
    realm = ""
    conf = ""

    if optional:
        optionalOrRequired = True
    if required:
        optionalOrRequired = False

    log.debug("[getUserFromParam] entering function")
    user = getParam(param, "user", optionalOrRequired)
    log.debug("[getUserFromParam] got user <<%r>>" % user)

    if user is None:
        user = ""
    else:
        splitAtSign = getFromConfig("splitAtSign", "true")

        if splitAtSign.lower() == "true":
            (user, realm) = splitUser(user)

    if "realm" in param:
        realm = param["realm"]

    if user != "":
        if realm is None or realm == "":
            realm = getDefaultRealm()

    usr = User(user, realm, "")

    if "resConf" in param:
        conf = param["resConf"]
        # with the short resolvernames, we have to extract the
        # configuration name from the resolver spec
        if "(" in conf and ")" in conf:
            res_conf, resolver_typ = conf.split(" ")
            conf = res_conf
        usr.conf = conf
    else:
        if len(usr.login) > 0 or len(usr.realm) > 0 or len(usr.conf) > 0:
            res = getResolversOfUser(usr)
            usr.saveResolvers(res)
            if len(res) > 1:
                log.error("[getUserFromParam] user %r@%r in more than one "
                          "resolver: %r" % (user, realm, res))
                raise Exception("The user %s@%s is in more than one resolver:"
                                " %s" % (user, realm, unicode(res)))

    log.debug("[getUserFromParam] creating user object %r,%r,%r" %
              (user, realm, conf))
    log.debug("[getUserFromParam] created user object %r " % usr)

    return usr
Beispiel #57
0
    def submitChallenge(self, options=None, pin=None):
        '''
        submit the sms message - former method name was checkPin

        :param options: the request options context

        :return: tuple of success and message
        '''
        log.debug("[submitChallenge] entering function")
        res = 0
        user = None

        if options is None:
            options = {}

        message = options.get('challenge', None)

        # it is configurable, if sms should be triggered by a valid pin
        send_by_PIN = getFromConfig("sms.sendByPin") or True

        if self.isActive() == True and send_by_PIN == True:
            counter = self.getOtpCount()
            log.debug("[submitChallenge] counter=%r" % counter)
            self.incOtpCounter(counter, reset=False)
            # At this point we must not bail out in case of an
            # Gateway error, since checkPIN is successful. A bail
            # out would cancel the checking of the other tokens
            try:

                if options is not None and type(options) == dict:
                    user = options.get('user', None)
                    # a given message overrules the policy defined message
                    if user and not message:
                        _sms_ret, message = get_auth_smstext(
                                                realm=user.realm)

                if not message:
                    message = "<otp>"

                res, message = self.sendSMS(message=message, pin=pin)
                if res is None:
                    res = False
                    message = "failed to submitt sms"
                self.info['info'] = "SMS sent: %r" % res

            except Exception as e:
                # The PIN was correct, but the SMS could not be sent.
                self.info['info'] = unicode(e)
                info = ("The SMS could not be sent: %r" % e)
                log.warning("[submitChallenge] %s" % info)
                res = False
                message = info
        if len(message) == 0:
            pass

        return res, message
Beispiel #58
0
    def autosync(self, ocraSuite, passw, challenge):
        '''
        try to resync a token automaticaly, if a former and the current request failed

        :param  ocraSuite: the ocraSuite of the current Token
        :type  ocraSuite: ocra object
        :param  passw:
        '''
        log.debug('[OcraToken::autosync] %r : %r' % (passw, challenge))
        res = -1

        autosync = False

        try:
            async = getFromConfig("AutoResync")
            if async is None:
                autosync = False
            elif "true" == async.lower():
                autosync = True
Beispiel #59
0
    def getSyncTimeOut(self):
        '''
        get the token sync timeout value

        :return: timeout value in seconds
        :rtype:  int
        '''

        timeOut = int(getFromConfig("AutoResyncTimeout", 5 * 60))
        return timeOut
Beispiel #60
0
    def submitChallenge(self, options=None):
        '''
        submit the sms message - former method name was checkPin

        :param options: the request options context

        :return: tuple of success and message
        '''
        res = 0
        user = None

        if options is None:
            options = {}

        message = options.get('challenge', None)

        # it is configurable, if sms should be triggered by a valid pin
        send_by_PIN = getFromConfig("sms.sendByPin") or True

        if self.isActive() == True and send_by_PIN == True:
            counter = self.getOtpCount()
            log.debug("[submitChallenge] counter=%r" % counter)
            self.incOtpCounter(counter, reset=False)
            # At this point we must not bail out in case of an
            # Gateway error, since checkPIN is successful. A bail
            # out would cancel the checking of the other tokens
            try:

                if options is not None and type(options) == dict:
                    user = options.get('user', None)
                    # a given message overrules the policy defined message
                    if user and not message:
                        _sms_ret, message = get_auth_smstext(
                            realm=user.realm, context=self.context)

                if not message:
                    message = "<otp>"

                res, message = self.sendSMS(message=message)
                if res is None:
                    res = False
                    message = "failed to submitt sms"
                self.info['info'] = "SMS sent: %r" % res

            except Exception as e:
                # The PIN was correct, but the SMS could not be sent.
                self.info['info'] = unicode(e)
                info = ("The SMS could not be sent: %r" % e)
                log.warning("[submitChallenge] %s" % info)
                res = False
                message = info
        if len(message) == 0:
            pass

        return res, message