Пример #1
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:
        db_challenges = Session.query(Challenge)\
            .filter(Challenge.transid == transid)\
            .all()

    challenges.extend(db_challenges)

    LOG.debug('[getTransactions4serial] %r' % challenges)
    return challenges
Пример #2
0
def deleteRealm(realmname):
    '''
    delete the realm from the Database Table with the given name

    :param realmname: the to be deleted realm
    :type  realmname: string
    '''

    log.debug("[delete] delete Realm object with name=%s" % realmname)
    r = getRealmObject(name=realmname)
    if r is None:
        ''' if no realm is found, we re-try the lowercase name for backward compatibility '''
        r = getRealmObject(name=realmname.lower())
    realmId = 0
    if r is not None:
        realmId = r.id

        if realmId != 0:
            log.debug("[deleteRealm] Now deleting all realations with realm_id=%i" % realmId)
            Session.query(TokenRealm).filter(TokenRealm.realm_id == realmId).delete()
        Session.delete(r)

    else:
        log.warning("[deleteRealm] There is no realm object with the name %s to be deleted." % realmname)
        return False
    # now delete all relations, i.e. remove all Tokens from this realm.

    return True
Пример #3
0
    def test_updateExisting(self):
        # Test the following conditions:
        # - An entry is created with chunklength > 1
        # - The type and description are not set
        # - The entry is reduced to one chunk
        # Verify that the resulting config entry has
        # correctly set the type and description

        key = 'linotp.testupdate'
        longvalue = '*' * 2000
        value = 'value'
        typ = None
        description = None

        _storeConfigDB(key, longvalue, typ, description)
        assert Session.query(Config).count() == 2
        oldentries = Session.query(Config).all()
        assert len(oldentries) == 2

        _storeConfigDB(key, value, typ, description)
        entries = Session.query(Config).all()
        assert len(entries) == 1

        entry = entries[0]
        assert entry.Key == key
        assert entry.Value == value
        assert entry.Description == description
        assert entry.Type == typ
Пример #4
0
def deleteRealm(realmname):
    '''
    delete the realm from the Database Table with the given name

    :param realmname: the to be deleted realm
    :type  realmname: string
    '''

    log.debug("[delete] delete Realm object with name=%s" % realmname)
    r = getRealmObject(name=realmname)
    if r is None:
        ''' if no realm is found, we re-try the lowercase name for backward compatibility '''
        r = getRealmObject(name=realmname.lower())
    realmId = 0
    if r is not None:
        realmId = r.id

        if realmId != 0:
            log.debug(
                "[deleteRealm] Now deleting all realations with realm_id=%i" %
                realmId)
            Session.query(TokenRealm).filter(
                TokenRealm.realm_id == realmId).delete()
        Session.delete(r)

    else:
        log.warning(
            "[deleteRealm] There is no realm object with the name %s to be deleted."
            % realmname)
        return False
    # now delete all relations, i.e. remove all Tokens from this realm.

    return True
Пример #5
0
def deleteRealm(realmname):
    '''
    delete the realm from the Database Table with the given name

    :param realmname: the to be deleted realm
    :type  realmname: string
    '''

    log.debug("deleting realm object with name=%s" % realmname)
    r = getRealmObject(name=realmname)
    if r is None:
        ''' if no realm is found, we re-try the lowercase name for backward compatibility '''
        r = getRealmObject(name=realmname.lower())
    realmId = 0
    if r is not None:
        realmId = r.id

        if realmId != 0:
            log.debug("Deleting token relations for realm with id %i" % realmId)
            Session.query(TokenRealm).filter(TokenRealm.realm_id == realmId).delete()
        Session.delete(r)

    else:
        log.warning("Realm with name %s was not found." % realmname)
        return False
    # now delete all relations, i.e. remove all Tokens from this realm.

    # finally we delete the 'realmname' cache
    from linotp.lib.user import delete_realm_resolver_cache
    delete_realm_resolver_cache(realmname)

    return True
Пример #6
0
    def test_updateExisting(self):
        # Test the following conditions:
        # - An entry is created with chunklength > 1
        # - The type and description are not set
        # - The entry is reduced to one chunk
        # Verify that the resulting config entry has
        # correctly set the type and description

        key = 'linotp.testupdate'
        longvalue = '*' * 2000
        value = 'value'
        typ = None
        description = None

        _storeConfigDB(key, longvalue, typ, description)
        self.assertEqual(Session.query(Config).count(), 2)
        oldentries = Session.query(Config).all()
        self.assertEqual(len(oldentries), 2)

        _storeConfigDB(key, value, typ, description)
        entries = Session.query(Config).all()
        self.assertEqual(len(entries), 1)

        entry = entries[0]
        self.assertEqual(entry.Key, key)
        self.assertEqual(entry.Value, value)
        self.assertEqual(entry.Description, '')  # None is converted to ''
        self.assertEqual(entry.Type, typ)
Пример #7
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
Пример #8
0
def deleteRealm(realmname):
    '''
    delete the realm from the Database Table with the given name

    :param realmname: the to be deleted realm
    :type  realmname: string
    '''

    log.debug("deleting realm object with name=%s" % realmname)
    r = getRealmObject(name=realmname)
    if r is None:
        ''' if no realm is found, we re-try the lowercase name for backward compatibility '''
        r = getRealmObject(name=realmname.lower())
    realmId = 0
    if r is not None:
        realmId = r.id

        if realmId != 0:
            log.debug("Deleting token relations for realm with id %i" % realmId)
            Session.query(TokenRealm).filter(TokenRealm.realm_id == realmId).delete()
        Session.delete(r)

    else:
        log.warning("Realm with name %s was not found." % realmname)
        return False
    # now delete all relations, i.e. remove all Tokens from this realm.

    # finally we delete the 'realmname' cache
    from linotp.lib.user import delete_realm_resolver_cache
    delete_realm_resolver_cache(realmname)

    return True
Пример #9
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:
        db_challenges = Session.query(Challenge).filter(Challenge.transid == transid).all()

    challenges.extend(db_challenges)

    LOG.debug("[getTransactions4serial] %r" % challenges)
    return challenges
Пример #10
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
Пример #11
0
    def test_updateExisting(self):
        # Test the following conditions:
        # - An entry is created with chunklength > 1
        # - The type and description are not set
        # - The entry is reduced to one chunk
        # Verify that the resulting config entry has
        # correctly set the type and description

        key = 'linotp.testupdate'
        longvalue = '*' * 2000
        value = 'value'
        typ = None
        description = None

        _storeConfigDB(key, longvalue, typ, description)
        self.assertEqual(Session.query(Config).count(), 2)
        oldentries = Session.query(Config).all()
        self.assertEqual(len(oldentries), 2)

        _storeConfigDB(key, value, typ, description)
        entries = Session.query(Config).all()
        self.assertEqual(len(entries), 1)

        entry = entries[0]
        self.assertEqual(entry.Key, key)
        self.assertEqual(entry.Value, value)
        self.assertEqual(entry.Description, '')  # None is converted to ''
        self.assertEqual(entry.Type, typ)
Пример #12
0
 def deleteToken(self):
     # # some dbs (eg. DB2) runs in deadlock, if the TokenRealm entry
     # # is deleteted via foreign key relation
     # # so we delete it explicitly
     Session.query(TokenRealm).filter(
         TokenRealm.token_id == self.LinOtpTokenId).delete()
     Session.delete(self)
     return True
Пример #13
0
 def deleteToken(self):
     log.debug('deleteToken()')
     ## some dbs (eg. DB2) runs in deadlock, if the TokenRealm entry
     ## is deleteted via foreign key relation
     ## so we delete it explicit
     Session.query(TokenRealm).filter(TokenRealm.token_id == self.LinOtpTokenId).delete()
     Session.delete(self)
     log.debug('delete token success')
     return True
Пример #14
0
    def test_set_loglevel(self, app, client):
        name = 'linotp.lib.user'
        config_entry = Session.query(LoggingConfig).get(name)
        assert not config_entry

        params = dict(
            loggerName=name,
            level=10,
        )
        client.post('/maintenance/setLogLevel', json=params)

        config_entry = Session.query(LoggingConfig).get(name)
        assert config_entry.level == 10
Пример #15
0
    def _get_tokens_in_realm(self, valid_realms):
        ## get all matching realms
        realm_id_tuples = Session.query(Realm.id).\
                            filter(Realm.name.in_(valid_realms)).all()
        realm_ids = set()
        for realm_tuple in realm_id_tuples:
            realm_ids.add(realm_tuple[0])
        ## get all tokenrealm ids
        token_id_tuples = Session.query(TokenRealm.token_id).\
                    filter(TokenRealm.realm_id.in_(realm_ids)).all()
        token_ids = set()
        for token_tuple in token_id_tuples:
            token_ids.add(token_tuple[0])

        return token_ids
Пример #16
0
    def _get_tokens_in_realm(self, valid_realms):
        ## get all matching realms
        realm_id_tuples = Session.query(Realm.id).\
                            filter(Realm.name.in_(valid_realms)).all()
        realm_ids = set()
        for realm_tuple in realm_id_tuples:
            realm_ids.add(realm_tuple[0])
        ## get all tokenrealm ids
        token_id_tuples = Session.query(TokenRealm.token_id).\
                    filter(TokenRealm.realm_id.in_(realm_ids)).all()
        token_ids = set()
        for token_tuple in token_id_tuples:
            token_ids.add(token_tuple[0])

        return token_ids
Пример #17
0
    def get_token_data(self):
        # get all tokens
        tokens = Session.query(model_token).all()

        for token in tokens:
            token_data = {}
            serial = token.LinOtpTokenSerialnumber
            token_data['Serial'] = serial

            if token.isPinEncrypted():
                pin = token.getPin()
                enc_value = self.crypter.encrypt(input_data=pin,
                                        just_mac=serial + token.LinOtpPinHash)
                token_data['TokenPin'] = enc_value

            # the userpin is used in motp and ocra/ocra2 token
            if token.LinOtpTokenPinUser:
                user_pin_obj = token.getUserPin()
                user_pin = user_pin_obj.getKey()
                enc_value = self.crypter.encrypt(input_data=user_pin,
                                    just_mac=serial + token.LinOtpTokenPinUser)
                token_data['TokenUserPin'] = enc_value

            # then we retrieve as well the original value,
            # to identify changes
            encKey = token.LinOtpKeyEnc

            secObj = token.getHOtpKey()
            seed = secObj.getKey()
            enc_value = self.crypter.encrypt(input_data=seed,
                                            just_mac=serial + encKey)
            token_data['TokenSeed'] = enc_value
            # next we look for tokens, where the pin is encrypted
            yield token_data
Пример #18
0
    def set_token_data(self, token_data):

        serial = token_data["Serial"]
        tokens = Session.query(model_token).\
            filter(model_token.LinOtpTokenSerialnumber == serial).all()
        token = tokens[0]

        if 'TokenPin' in token_data:
            enc_pin = token_data['TokenPin']
            token_pin = self.crypter.decrypt(enc_pin,
                                just_mac=serial + token.LinOtpPinHash)
            # prove, we can write
            token.setPin(token_pin, hashed=False)

        if 'TokenUserPin' in token_data:
            enc_user_pin = token_data['TokenUserPin']
            user_pin = self.crypter.decrypt(enc_user_pin,
                               just_mac=serial + token.LinOtpTokenPinUser)
            # prove, we can write
            token.setUserPin(user_pin)

        # we put the current crypted seed in the mac to check if
        # something changed in meantime
        encKey = token.LinOtpKeyEnc
        enc_seed = token_data['TokenSeed']
        token_seed = self.crypter.decrypt(enc_seed,
                                          just_mac=serial + encKey)
        token.setHKey(token_seed, reset_failcount=False)
Пример #19
0
def getRealmObject(name="", id=0):
    '''
    returns the Realm Object for a given realm name.
    If the given realm name is not found, it returns "None"

    :param name: realmname to be searched
    :type  name: string

    TODO: search by id not implemented, yet
    :param id:   id of the realm object
    :type  id:   integer

    :return : realmObject - the database object
    :rtype  : the sql db object
    '''

    log.debug("Getting realm object for name=%s, id=%i", name, id)
    realmObj = None

    name = '' + str(name)
    if (0 == id):
        realmObjects = Session.query(Realm).filter(func.lower(Realm.name) == name.lower())
        if realmObjects.count() > 0:
            realmObj = realmObjects[0]

    return realmObj
Пример #20
0
    def webkdc_userinfo(self):
        # Called by WebAuth via the Elm remctld scripts.
        # Returns information about whether the user owns any tokens.

        # TODO: Require some sort of session token.
        param = {}

        try:
            param.update(request.params)
            user = getUserFromParam(param, optionalOrRequired = True)
            if (user is not None and user.isEmpty() == False):
                (userid, idResolver, idResolverClass) = getUserId(user)

                sqlQuery = Session.query(model.Token).with_lockmode("update").filter(
                   model.Token.LinOtpUserid == userid).filter(
                    model.Token.LinOtpIdResClass == idResolverClass).filter(
                     model.Token.LinOtpIsactive == 1)

                tokenList = []
                for token in sqlQuery:
                    tokenList.append(token.LinOtpTokenSerialnumber)

            Session.commit()

            return sendResult(response, tokenList, 0)

        except Exception as exx:
            log.error("[webkdc_userinfo] validate/webkdc_userinfo failed: %r" % exx)
            log.error("[webkdc_userinfo] %s" % traceback.format_exc())

            Session.rollback()
            return sendError(response, u"validate/webkdc_userinfo failed: %s" % unicode(exx), 0)
        finally:
            Session.close()
Пример #21
0
def _storeConfigEntryDB(key, value, typ=None, desc=None):
    """
    lowest level for storing database entries in the config table
    """

    confEntries = Session.query(Config).filter(Config.Key == unicode(key))
    theConf = None

    # update
    if confEntries.count() == 1:
        theConf = confEntries[0]
        theConf.Value = unicode(value)
        if (typ is not None):
            theConf.Type = unicode(typ)
        if (desc is not None):
            theConf.Description = unicode(desc)

    # insert
    elif confEntries.count() == 0:
        theConf = Config(
                        Key=unicode(key),
                        Value=unicode(value),
                        Type=unicode(typ),
                        Description=unicode(desc)
                        )
    if theConf is not None:
        Session.add(theConf)

    return 101
Пример #22
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
Пример #23
0
def getRealmObject(name=u"", id=0):
    '''
    returns the Realm Object for a given realm name.
    If the given realm name is not found, it returns "None"

    :param name: realmname to be searched
    :type  name: string

    TODO: search by id not implemented, yet
    :param id:   id of the realm object
    :type  id:   integer

    :return : realmObject - the database object
    :rtype  : the sql db object
    '''

    log.debug("Getting realm object for name=%s, id=%i", name, id)
    realmObj = None

    name = u'' + str(name)
    if (0 == id):
        realmObjects = Session.query(Realm).filter(func.lower(Realm.name) == name.lower())
        if realmObjects.count() > 0:
            realmObj = realmObjects[0]

    return realmObj
Пример #24
0
    def active_users_total(self, realmlist):
        """
        get the total number of users of active tokens
        for all resolvers which are in allowed realms

        users are counted per resolver, so if resolver is in more than one
        realm, its uers will only be counted once

        :param realmlist: list of (existing and allowed) realms
        :return: number of users in allowed realms who own an active token
        """
        realm_cond = tuple()
        for realm in realmlist:
            realm_cond += (or_(Realm.name == realm),)

        user_and_resolver = Session.query(Token.LinOtpUserid,
                                          Token.LinOtpIdResolver,
                                          Token.LinOtpIdResClass,
                                          Token.LinOtpIsactive)\
            .join(TokenRealm)\
            .join(Realm)\
            .filter(or_(*realm_cond),
                    and_(Token.LinOtpIsactive == True,
                         Token.LinOtpIdResolver != ''))\
            .group_by(Token.LinOtpUserid, Token.LinOtpIdResolver,
                      Token.LinOtpIsactive, Token.LinOtpIdResClass)

        all_server_total = user_and_resolver.count()
        return all_server_total
Пример #25
0
    def active_users_per_realm(self, realm=None):
        """
        get the number of users which are assigned to an active token in total
            or per realm and resolver
        :param realm: name of realm
        :return: dict with
                keys: resolvernames
                values: number of active token users
        """
        realminfo = context.get('Config').getRealms().get(realm)
        resolver_specs = realminfo.get('useridresolver', '')
        realmdict = {}

        for resolver_spec in resolver_specs:
            __, config_identifier = parse_resolver_spec(resolver_spec)
            act_users_per_resolver = Session.query(Token.LinOtpUserid,
                                                   Token.LinOtpIdResolver,
                                                   Token.LinOtpIdResClass,
                                                   Token.LinOtpIsactive)\
                .join(TokenRealm)\
                .join(Realm)\
                .filter(and_(
                            Token.LinOtpIsactive == True,
                            Token.LinOtpIdResClass == resolver_spec,
                            Realm.name == realm
                ))\
                .group_by(Token.LinOtpUserid, Token.LinOtpIdResolver,
                          Token.LinOtpIsactive, Token.LinOtpIdResClass)

            realmdict[config_identifier] = act_users_per_resolver.count()

        return realmdict
Пример #26
0
def set_logging_level(name, level):

    """
    sets the logging level in the database as well as
    in the current running logger

    :param name: Name of the logger
    :param level: New level (must be integer)
    """

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

    logger = logging.getLogger(name)
    logger.setLevel(level)

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

    config_entry = Session.query(LoggingConfig).get(name)

    if config_entry is None:
        new_config_entry = LoggingConfig(name, level)
        Session.add(new_config_entry)
        return

    config_entry.level = level
Пример #27
0
    def get_token_data(self):
        """
        get all tokens
        """
        tokens = Session.query(model_token).all()

        for token in tokens:
            token_data = {}
            serial = token.LinOtpTokenSerialnumber
            token_data["Serial"] = serial

            if token.isPinEncrypted():
                iv, enc_pin = token.get_encrypted_pin()
                pin = SecretObj.decrypt_pin(enc_pin, hsm=self.hsm)
                enc_value = self.crypter.encrypt(input_data=pin, just_mac=serial + token.LinOtpPinHash)
                token_data["TokenPin"] = enc_value

            # the userpin is used in motp and ocra/ocra2 token
            if token.LinOtpTokenPinUser:
                key, iv = token.getUserPin()
                user_pin = SecretObj.decrypt(key, iv, hsm=self.hsm)
                enc_value = self.crypter.encrypt(input_data=user_pin, just_mac=serial + token.LinOtpTokenPinUser)
                token_data["TokenUserPin"] = enc_value

            # then we retrieve as well the original value,
            # to identify changes
            encKey = token.LinOtpKeyEnc

            key, iv = token.get_encrypted_seed()
            secObj = SecretObj(key, iv, hsm=self.hsm)
            seed = secObj.getKey()
            enc_value = self.crypter.encrypt(input_data=seed, just_mac=serial + encKey)
            token_data["TokenSeed"] = enc_value
            # next we look for tokens, where the pin is encrypted
            yield token_data
Пример #28
0
    def get_sync_status(self):
        """
        check if cache and config db are synced

        if sync is True, the synctime is returned
        else, the difference (cache-time - database_time) is given
        :return: dict with keys 'sync' and 'synctime'
        """
        result = {'sync': False}

        linotp_conf = LinOtpConfig()
        linotp_time = linotp_conf.get('linotp.Config')

        # get db entry for config
        entry = Session.query(config_model).filter(
            config_model.Key == 'linotp.Config').one()
        db_time = entry.Value

        # if the times are not in syc, LinOTP keeps its status
        # cached but does not update its timestamp of sync
        if db_time == linotp_time:
            result['sync'] = True
            result['synctime'] = db_time
            now = datetime.datetime.now()
            result['now'] = unicode(now)

        else:
            format_string = '%Y-%m-%d %H:%M:%S.%f'
            linotp_t = datetime.datetime.strptime(str(linotp_time), format_string)
            db_t = datetime.datetime.strptime(str(db_time), format_string)
            result['cache_to_db_diff'] = unicode(linotp_t - db_t)
            result['db_time'] = db_time

        return result
Пример #29
0
    def set_config_entry(self, config_entry):
        """
        set the config entry - using the standard way, so that the new value
        will be encrypted using the new encryption key and potetialy as well an
        new iv.

        before storing the new entry, the old value in its encryted form is
        read. The


        :param config_entry: the config entry, as a dict
        :return: - nothing -
        """

        key = config_entry['Key']
        typ = config_entry['Type']
        desc = config_entry['Description']
        if desc == 'None':
            desc = None

        config_entries = Session.query(model_config).\
                         filter(model_config.Key == key).all()
        entry = config_entries[0]

        # decypt the real value
        enc_value = config_entry['Value']
        value = self.crypter.decrypt(enc_value,
                                     just_mac='enc%s' % key + entry.Value)

        _storeConfigDB(key, value, typ=typ, desc=desc)
Пример #30
0
    def test_storeConfigDB_encoding(self):
        # Test round trip of _storeConfigDB with entries that require
        # encoding of special characters
        conf = {
            'Key': 'linotp.TËST',
            'Value': 'VALUEÄ',
            'Type': 'TYPEß',
            'Description': 'DESCRIPTIÖN',
        }

        _storeConfigDB(conf['Key'], conf['Value'], conf['Type'],
                       conf['Description'])

        # Check value is correctly returned
        stored_value = _retrieveConfigDB(conf['Key'])
        assert conf['Value'] == stored_value

        # Check type, description in database
        entries = Session.query(Config).all()

        assert (len(entries) == 1)
        stored_conf = entries[0]

        for key in list(conf.keys()):
            assert conf[key] == getattr(stored_conf, key), \
                             "Key should match key:%s - expected %r, recevied %r" % (key, conf[key], getattr(stored_conf, key))
Пример #31
0
def init_logging_config():

    """
    Loads the persistent logging configuration from the database,
    sets the appropriate mappers (to enrich results with request
    ids, remote addresses, etc) and adds the handler defined in
    the global configuration.

    Should be called ONCE at the start of the server
    """

    root_logger = logging.getLogger()

    for handler in root_logger.handlers:
        filter_ = RequestContextFilter()
        handler.addFilter(filter_)

    stderr_handler = logging.StreamHandler()
    formatter = ColorFormatter('%(asctime)s %(levelname)s - %(message)s')
    stderr_handler.setFormatter(formatter)

    root_logger.addHandler(stderr_handler)

    config_entries = Session.query(LoggingConfig).all()

    for config_entry in config_entries:
        logger = logging.getLogger(config_entry.name)
        logger.setLevel(config_entry.level)
Пример #32
0
    def active_users_per_realm(self, realm=None):
        """
        get the number of users which are assigned to an active token in total
            or per realm and resolver
        :param realm: name of realm
        :return: dict with
                keys: resolvernames
                values: number of active token users
        """
        realminfo = context.get('Config').getRealms().get(realm)
        resolver_specs = realminfo.get('useridresolver', '')
        realmdict = {}

        for resolver_spec in resolver_specs:
            __, config_identifier = parse_resolver_spec(resolver_spec)
            act_users_per_resolver = Session.query(Token.LinOtpUserid,
                                                   Token.LinOtpIdResolver,
                                                   Token.LinOtpIdResClass,
                                                   Token.LinOtpIsactive)\
                .join(TokenRealm)\
                .join(Realm)\
                .filter(and_(
                            Token.LinOtpIsactive == True,
                            Token.LinOtpIdResClass == resolver_spec,
                            Realm.name == realm
                ))\
                .group_by(Token.LinOtpUserid, Token.LinOtpIdResolver,
                          Token.LinOtpIsactive, Token.LinOtpIdResClass)

            realmdict[config_identifier] = act_users_per_resolver.count()

        return realmdict
Пример #33
0
    def set_token_data(self, token_data):

        serial = token_data["Serial"]
        tokens = Session.query(model_token).\
            filter(model_token.LinOtpTokenSerialnumber == serial).all()
        token = tokens[0]

        if 'TokenPin' in token_data:
            enc_pin = token_data['TokenPin']
            token_pin = self.crypter.decrypt(enc_pin,
                                just_mac=serial + token.LinOtpPinHash)
            # prove, we can write
            enc_pin = SecretObj.encrypt_pin(token_pin)
            iv = enc_pin.split(':')[0]
            token.set_encrypted_pin(enc_pin, binascii.unhexlify(iv))

        if 'TokenUserPin' in token_data:
            token_enc_user_pin = token_data['TokenUserPin']
            user_pin = self.crypter.decrypt(token_enc_user_pin,
                               just_mac=serial + token.LinOtpTokenPinUser)
            # prove, we can write
            iv, enc_user_pin = SecretObj.encrypt(user_pin, hsm=self.hsm)
            token.setUserPin(enc_user_pin, iv)

        # we put the current crypted seed in the mac to check if
        # something changed in meantime
        encKey = token.LinOtpKeyEnc
        enc_seed = token_data['TokenSeed']
        token_seed = self.crypter.decrypt(enc_seed,
                                          just_mac=serial + encKey)

        # the encryption of the token seed is not part of the model anymore
        iv, enc_token_seed = SecretObj.encrypt(token_seed)
        token.set_encrypted_seed(enc_token_seed, iv, reset_failcount=False)
Пример #34
0
    def test_storeConfigDB_encoding(self):
        # Test round trip of _storeConfigDB with entries that require
        # encoding of special characters
        conf = {
            'Key': u'linotp.TËST',
            'Value': u'VALUEÄ',
            'Type': u'TYPEß',
            'Description': u'DESCRIPTIÖN',
        }

        _storeConfigDB(conf['Key'], conf['Value'],
                       conf['Type'], conf['Description'])

        # Check value is correctly returned
        stored_value = _retrieveConfigDB(conf['Key'])
        self.assertEqual(conf['Value'], stored_value)

        # Check type, description in database
        entries = Session.query(Config).all()

        assert(len(entries) == 1)
        stored_conf = entries[0]

        for key in conf.keys():
            self.assertEqual(conf[key], getattr(stored_conf, key),
                             "Key should match key:%s - expected %r, recevied %r" % (key, conf[key], getattr(stored_conf, key)))
Пример #35
0
def _storeConfigEntryDB(key, value, typ=None, desc=None):
    """
    lowest level for storing database entries in the config table
    """

    confEntries = Session.query(Config).filter(Config.Key == unicode(key))
    theConf = None

    # update
    if confEntries.count() == 1:
        theConf = confEntries[0]
        theConf.Value = unicode(value)
        if (typ is not None):
            theConf.Type = unicode(typ)
        if (desc is not None):
            theConf.Description = unicode(desc)

    # insert
    elif confEntries.count() == 0:
        theConf = Config(
                        Key=unicode(key),
                        Value=unicode(value),
                        Type=unicode(typ),
                        Description=unicode(desc)
                        )
    if theConf is not None:
        Session.add(theConf)

    return 101
Пример #36
0
def _removeConfigDB(key):
    log.debug('removeConfigDB %r' % key)
    num = 0

    if (not key.startswith("linotp.")):
        if not key.startswith('enclinotp.'):
            key = u"linotp." + key

    confEntries = Session.query(Config).filter(Config.Key == unicode(key))

    num = confEntries.count()
    if num == 1:
        theConf = confEntries[0]

        try:
            # Session.add(theConf)
            Session.delete(theConf)

        except Exception as e:
            log.exception('[removeConfigDB] failed')
            raise ConfigAdminError("remove Config failed for %r: %r" %
                                   (key, e),
                                   id=1133)

    return num
Пример #37
0
def delete(realms, status, date=None):
    """
    delete all rows in reporting database before a given date

    :param date: (optional)day until which all rows will be deleted
    :type date: string in format: 'yyyy-mm-dd'

    :return: number of deleted rows
    """

    if not isinstance(realms, (list, tuple)):
        realms = realms.split(',')

    realm_cond = tuple()
    for realm in realms:
       realm_cond += (or_(Reporting.realm == realm),)

    status_cond = tuple()
    for stat in status:
        status_cond += (or_(Reporting.parameter == stat),)

    date_cond = tuple()
    if date:
        date_cond += (and_(Reporting.timestamp < date),)

    conds = (and_(*date_cond), or_(*realm_cond), or_(*status_cond),)

    rows = Session.query(Reporting).filter(*conds)
    row_num = rows.count()

    for row in rows:
        Session.delete(row)
    return row_num
Пример #38
0
    def get_sync_status(self):
        """
        check if cache and config db are synced

        if sync is True, the synctime is returned
        else, the difference (cache-time - database_time) is given
        :return: dict with keys 'sync' and 'synctime'
        """
        result = {'sync': False}

        linotp_conf = LinOtpConfig()
        linotp_time = linotp_conf.get('linotp.Config')

        # get db entry for config
        entry = Session.query(config_model).filter(
            config_model.Key == 'linotp.Config').one()
        db_time = entry.Value

        # if the times are not in syc, LinOTP keeps its status
        # cached but does not update its timestamp of sync
        if db_time == linotp_time:
            result['sync'] = True
            result['synctime'] = db_time
            now = datetime.datetime.now()
            result['now'] = unicode(now)

        else:
            format_string = '%Y-%m-%d %H:%M:%S.%f'
            linotp_t = datetime.datetime.strptime(str(linotp_time),
                                                  format_string)
            db_t = datetime.datetime.strptime(str(db_time), format_string)
            result['cache_to_db_diff'] = unicode(linotp_t - db_t)
            result['db_time'] = db_time

        return result
Пример #39
0
    def active_users_total(self, realmlist):
        """
        get the total number of users of active tokens
        for all resolvers which are in allowed realms

        users are counted per resolver, so if resolver is in more than one
        realm, its uers will only be counted once

        :param realmlist: list of (existing and allowed) realms
        :return: number of users in allowed realms who own an active token
        """
        realm_cond = tuple()
        for realm in realmlist:
            realm_cond += (or_(Realm.name == realm), )

        user_and_resolver = Session.query(Token.LinOtpUserid,
                                          Token.LinOtpIdResolver,
                                          Token.LinOtpIdResClass,
                                          Token.LinOtpIsactive)\
            .join(TokenRealm)\
            .join(Realm)\
            .filter(or_(*realm_cond),
                    and_(Token.LinOtpIsactive == True,
                         Token.LinOtpIdResolver != ''))\
            .group_by(Token.LinOtpUserid, Token.LinOtpIdResolver,
                      Token.LinOtpIsactive, Token.LinOtpIdResClass)

        all_server_total = user_and_resolver.count()
        return all_server_total
Пример #40
0
    def get_active_tokencount(self):
        """
        get the number of active tokens from all realms (including norealm)

        :return: number of active tokens
        """
        active = Token.LinOtpIsactive == True
        token_active = Session.query(Token).filter(active).count()
        return token_active
Пример #41
0
    def get_active_tokencount(self):
        """
        get the number of active tokens from all realms (including norealm)

        :return: number of active tokens
        """
        active = Token.LinOtpIsactive == True
        token_active = Session.query(Token).filter(active).count()
        return token_active
Пример #42
0
def _removeConfigDB(key):
    """
    remove entry from config table

    :param key: the name of the entry
    :return: number of deleted entries
    """
    log.debug('removeConfigDB %r' % key)

    if (not key.startswith("linotp.")):
        if not key.startswith('enclinotp.'):
            key = u"linotp." + key

    confEntries = Session.query(Config).filter(
        Config.Key == unicode(key)).all()

    if not confEntries:
        return 0

    theConf = confEntries[0]

    to_be_deleted = []
    to_be_deleted.append(theConf)

    # if entry is a contious type, delete all of this kind
    if theConf.Type == 'C' and theConf.Description[:len('0:')] == '0:':
        _start, end = theConf.Description.split(':')
        search_key = "%s__[%%:%s]" % (key, end)
        cont_entries = Session.query(Config).filter(
            Config.Key.like(search_key)).all()
        to_be_deleted.extend(cont_entries)

    try:
        for entry in to_be_deleted:
            # Session.add(theConf)
            Session.delete(entry)

    except Exception as e:
        log.exception('[removeConfigDB] failed')
        raise ConfigAdminError("remove Config failed for %r: %r" % (key, e),
                               id=1133)

    return len(to_be_deleted)
Пример #43
0
def delete_reporting():
    """
    delete all rows in reporting database

    :return: number of deleted rows
    """
    rows = Session.query(Reporting)
    row_num = rows.count()
    for row in rows.all():
        Session.delete(row)
    return row_num
Пример #44
0
def _removeConfigDB(key):
    """
    remove entry from config table

    :param key: the name of the entry
    :return: number of deleted entries
    """
    log.debug('removeConfigDB %r' % key)

    if (not key.startswith("linotp.")):
        if not key.startswith('enclinotp.'):
            key = u"linotp." + key

    confEntries = Session.query(Config).filter(Config.Key == unicode(key)).all()

    if not confEntries:
        return 0

    theConf = confEntries[0]

    to_be_deleted = []
    to_be_deleted.append(theConf)

    # if entry is a contious type, delete all of this kind
    if theConf.Type == 'C' and theConf.Description[:len('0:')] == '0:':
        _start, end = theConf.Description.split(':')
        search_key = "%s__[%%:%s]" % (key, end)
        cont_entries = Session.query(Config).filter(Config.Key.like(search_key)).all()
        to_be_deleted.extend(cont_entries)

    try:
        for entry in to_be_deleted:
            # Session.add(theConf)
            Session.delete(entry)

    except Exception as e:
        log.exception('[removeConfigDB] failed')
        raise ConfigAdminError("remove Config failed for %r: %r"
                               % (key, e), id=1133)

    return len(to_be_deleted)
Пример #45
0
    def deleteToken(self):
        # some dbs (eg. DB2) runs in deadlock, if the TokenRealm entry
        # is deleteted via foreign key relation
        # so we delete it explicitly
        token_realm_entries = Session.query(TokenRealm).filter(
            TokenRealm.token_id == self.LinOtpTokenId).all()

        for token_realm_entry in token_realm_entries:
            Session.delete(token_realm_entry)

        Session.delete(self)
        return True
Пример #46
0
    def deleteToken(self):
        # some dbs (eg. DB2) runs in deadlock, if the TokenRealm entry
        # is deleteted via foreign key relation
        # so we delete it explicitly
        token_realm_entries = Session.query(TokenRealm).filter(
                            TokenRealm.token_id == self.LinOtpTokenId).all()

        for token_realm_entry in token_realm_entries:
            Session.delete(token_realm_entry)

        Session.delete(self)
        return True
Пример #47
0
def init_logging_config():
    """
    Loads the persistent logging configuration from the database

    Should be called ONCE at the start of the server
    """

    config_entries = Session.query(LoggingConfig).all()

    for config_entry in config_entries:
        logger = logging.getLogger(config_entry.name)
        logger.setLevel(config_entry.level)
Пример #48
0
    def get_config_info(self):
        """
        get some counts from config db
        :return: dict with keys 'total', 'ldapresolver', 'sqlresolver',
            'passwdresolver', 'policies', 'realms'
        """
        result = {}
        # the number of config entries
        result['total'] = Session.query(config_model).count()

        # the number of resolver defintions
        ldap = Session.query(config_model).filter(
            config_model.Key.like('linotp.ldapresolver.%')).count()
        result['ldapresolver'] = ldap / 13

        sql = Session.query(config_model).filter(
            config_model.Key.like('linotp.sqlresolver.%')).count()
        result['sqlresolver'] = sql / 12

        passwd = Session.query(config_model).filter(
            config_model.Key.like('linotp.passwdresolver.%')).count()
        result['passwdresolver'] = passwd

        # the number of policy definitions
        policies = Session.query(config_model).filter(
            config_model.Key.like('linotp.Policy.%')).count()
        result['policies'] = policies / 7

        # the number of realm definition (?)
        realms = Session.query(config_model).filter(
            config_model.Key.like('linotp.useridresolver.group.%')).count()
        result['realms'] = realms

        return result
Пример #49
0
    def get_config_info(self):
        """
        get some counts from config db
        :return: dict with keys 'total', 'ldapresolver', 'sqlresolver',
            'passwdresolver', 'policies', 'realms'
        """
        result = {}
        # the number of config entries
        result['total'] = Session.query(config_model).count()

        # the number of resolver defintions
        ldap = Session.query(config_model).filter(
            config_model.Key.like('linotp.ldapresolver.%')).count()
        result['ldapresolver'] = ldap / 13

        sql = Session.query(config_model).filter(
            config_model.Key.like('linotp.sqlresolver.%')).count()
        result['sqlresolver'] = sql / 12

        passwd = Session.query(config_model).filter(
            config_model.Key.like('linotp.passwdresolver.%')).count()
        result['passwdresolver'] = passwd

        # the number of policy definitions
        policies = Session.query(config_model).filter(
            config_model.Key.like('linotp.Policy.%')).count()
        result['policies'] = policies / 7

        # the number of realm definition (?)
        realms = Session.query(config_model).filter(
            config_model.Key.like('linotp.useridresolver.group.%')).count()
        result['realms'] = realms

        return result
Пример #50
0
    def _get_realm_condition(self, valid_realms, filterRealm):
        """
         create the condition for only getting certain realms!
        """
        rcondition = None
        if '*' in valid_realms:
            log.debug("[TokenIterator::init] wildcard for realm '*' found."
                      " Tokens of all realms will be displayed")
            return rcondition

        if len(valid_realms) > 0:
            log.debug("[TokenIterator::init] adding filter condition"
                      " for realm %r" % valid_realms)

            # get all matching realms
            token_ids = self._get_tokens_in_realm(valid_realms)
            rcondition = and_(Token.LinOtpTokenId.in_(token_ids))
            return rcondition

        if ("''" in filterRealm or '""' in filterRealm
                or "/:no realm:/" in filterRealm):
            log.debug("[TokenIterator::init] search for all tokens, which are"
                      " in no realm")

            # get all tokenrealm ids
            token_id_tuples = Session.query(TokenRealm.token_id).all()
            token_ids = set()
            for token_tuple in token_id_tuples:
                token_ids.add(token_tuple[0])

            ## define the token id not condition
            rcondition = and_(not_(Token.LinOtpTokenId.in_(token_ids)))
            return rcondition

        if filterRealm:
            # get all matching realms
            search_realms = set()

            realms = getRealms()
            for realm in realms:
                for frealm in filterRealm:
                    if fnmatch.fnmatch(realm, frealm):
                        search_realms.add(realm)

            search_realms = list(search_realms)

            # define the token id condition
            token_ids = self._get_tokens_in_realm(search_realms)
            rcondition = and_(Token.LinOtpTokenId.in_(token_ids))
            return rcondition

        return rcondition
Пример #51
0
    def _get_realm_condition(self, valid_realms, filterRealm):
        """
         create the condition for only getting certain realms!
        """
        rcondition = None
        if '*' in valid_realms:
            log.debug("[TokenIterator::init] wildcard for realm '*' found."
                      " Tokens of all realms will be displayed")
            return rcondition

        if len(valid_realms) > 0:
            log.debug("[TokenIterator::init] adding filter condition"
                      " for realm %r" % valid_realms)

            # get all matching realms
            token_ids = self._get_tokens_in_realm(valid_realms)
            rcondition = and_(Token.LinOtpTokenId.in_(token_ids))
            return rcondition

        if ("''" in filterRealm or '""' in filterRealm or
              "/:no realm:/" in filterRealm):
            log.debug("[TokenIterator::init] search for all tokens, which are"
                      " in no realm")

            # get all tokenrealm ids
            token_id_tuples = Session.query(TokenRealm.token_id).all()
            token_ids = set()
            for token_tuple in token_id_tuples:
                token_ids.add(token_tuple[0])

            ## define the token id not condition
            rcondition = and_(not_(Token.LinOtpTokenId.in_(token_ids)))
            return rcondition

        if filterRealm:
            # get all matching realms
            search_realms = set()

            realms = getRealms()
            for realm in realms:
                for frealm in filterRealm:
                    if fnmatch.fnmatch(realm, frealm):
                        search_realms.add(realm)

            search_realms = list(search_realms)

            # define the token id condition
            token_ids = self._get_tokens_in_realm(search_realms)
            rcondition = and_(Token.LinOtpTokenId.in_(token_ids))
            return rcondition

        return rcondition
Пример #52
0
def init_logging_config():

    """
    Loads the persistent logging configuration from the database

    Should be called ONCE at the start of the server
    """

    config_entries = Session.query(LoggingConfig).all()

    for config_entry in config_entries:
        logger = logging.getLogger(config_entry.name)
        logger.setLevel(config_entry.level)
Пример #53
0
def _retrieveConfigDB(Key):
    log.debug('[retrieveConfigDB] key: %r' % Key)

    # prepend "lonotp." if required
    key = Key
    if (not key.startswith("linotp.")):
        if (not key.startswith("enclinotp.")):
            key = "linotp." + Key

    myVal = None
    key = u'' + key
    entries = Session.query(Config).filter(Config.Key == key).all()

    if not entries:
        return None

    theConf = entries[0]

    # other types than continous: we are done
    if theConf.Type != 'C':
        myVal = theConf.Value
        myVal = _expandHere(myVal)
        return myVal

    # else we have the continue type: we iterate over all entries where the
    # number of entries is stored in the description as range end
    _start, end = theConf.Description.split(':')

    # start accumulating the value
    value = theConf.Value

    for i in range(int(end)):
        search_key = "%s__[%d:%d]" % (key, i, int(end))
        cont_entries = Session.query(Config).filter(
            Config.Key == search_key).all()
        if cont_entries:
            value = value + cont_entries[0].Value

    return value
Пример #54
0
def _retrieveConfigDB(Key):
    log.debug('[retrieveConfigDB] key: %r' % Key)

    # prepend "lonotp." if required
    key = Key
    if (not key.startswith("linotp.")):
        if (not key.startswith("enclinotp.")):
            key = "linotp." + Key

    myVal = None
    key = u'' + key
    entries = Session.query(Config).filter(Config.Key == key).all()

    if not entries:
        return None

    theConf = entries[0]

    # other types than continous: we are done
    if theConf.Type != 'C':
        myVal = theConf.Value
        myVal = _expandHere(myVal)
        return myVal

    # else we have the continue type: we iterate over all entries where the
    # number of entries is stored in the description as range end
    _start, end = theConf.Description.split(':')

    # start accumulating the value
    value = theConf.Value

    for i in range(int(end)):
        search_key = "%s__[%d:%d]" % (key, i, int(end))
        cont_entries = Session.query(Config).filter(Config.Key == search_key).all()
        if cont_entries:
            value = value + cont_entries[0].Value

    return value
Пример #55
0
    def lookup_challenge(self, state=0):
        '''
        database lookup to find all challenges belonging to a token and or
        if exist with a transaction state

        :param state: the optional parameter identified the state/transactionId

        :return: the list of challenges
        '''

        challenges = []

        if state == 0:
            challenges = Session.query(Challenge).\
              filter(Challenge.tokenserial == self.token.getSerial()).\
              all()
        else:
            challenges = Session.query(Challenge).\
              filter(Challenge.tokenserial == self.token.getSerial()).\
              filter(Challenge.transid == state).\
              all()

        return challenges
Пример #56
0
def _retrieveConfigDB(Key):
    log.debug('[retrieveConfigDB] key: %r' % Key)

    # # prepend "lonotp." if required
    key = Key
    if (not key.startswith("linotp.")):
        if (not key.startswith("enclinotp.")):
            key = "linotp." + Key

    myVal = None
    key = u'' + key
    for theConf in Session.query(Config).filter(Config.Key == key):
        myVal = theConf.Value
        myVal = _expandHere(myVal)
    return myVal