Пример #1
0
def getDB(password, new=False, allowRemote=True, allowUpgrade=False):
    loc = urllib.parse.urlparse(args.database)
    # This is basically the same code as in Util.setupDataConnection().  Should consider moving to it.
    if (loc.scheme == 'http') or (loc.scheme == 'https'):
        if not allowRemote:
            raise Exception(
                "This command cannot be executed remotely.  You must execute it on the server directly."
            )
        # If no port specified, insert the port
        if loc.port is None:
            netloc = loc.netloc + ":" + Defaults.getDefault(
                'TARDIS_REMOTE_PORT')
            dbLoc = urllib.parse.urlunparse(
                (loc.scheme, netloc, loc.path, loc.params, loc.query,
                 loc.fragment))
        else:
            dbLoc = args.database
        tardisdb = RemoteDB.RemoteDB(dbLoc, args.client)
        cache = tardisdb
    else:
        basedir = os.path.join(args.database, args.client)
        if not args.dbdir:
            dbdir = os.path.join(args.database, args.client)
        else:
            dbdir = os.path.join(args.dbdir, args.client)
        dbfile = os.path.join(dbdir, args.dbname)
        if new and os.path.exists(dbfile):
            raise Exception("Database for client %s already exists." %
                            (args.client))

        cache = CacheDir.CacheDir(basedir, 2, 2, create=new)
        schema = args.schema if new else None
        tardisdb = TardisDB.TardisDB(dbfile,
                                     backup=False,
                                     initialize=schema,
                                     allow_upgrade=allowUpgrade)

    if tardisdb.needsAuthentication():
        if password is None:
            password = Util.getPassword(args.password,
                                        args.passwordfile,
                                        args.passwordprog,
                                        prompt="Password for %s: " %
                                        (args.client),
                                        allowNone=False,
                                        confirm=False)
        Util.authenticate(tardisdb, args.client, password)

        scheme = tardisdb.getCryptoScheme()
        logger.info("Using crypto scheme %d", scheme)
        crypt = TardisCrypto.getCrypto(scheme, password, args.client)
    else:
        crypt = TardisCrypto.getCrypto(0, None, None)

    return (tardisdb, cache, crypt)
Пример #2
0
def addPasswordOptions(parser, addscheme=False):
    passgroup = parser.add_argument_group(
        "Password/Encryption specification options")
    pwgroup = passgroup.add_mutually_exclusive_group()
    pwgroup.add_argument('--password',
                         '-P',
                         dest='password',
                         default=config.get(job, 'Password'),
                         nargs='?',
                         const=True,
                         help='Encrypt files with this password')
    pwgroup.add_argument(
        '--password-file',
        '-F',
        dest='passwordfile',
        default=config.get(job, 'PasswordFile'),
        help='Read password from file.  Can be a URL (HTTP/HTTPS or FTP)')
    pwgroup.add_argument(
        '--password-prog',
        dest='passwordprog',
        default=config.get(job, 'PasswordProg'),
        help='Use the specified command to generate the password on stdout')

    if addscheme:
        passgroup.add_argument('--scheme',
                               dest='scheme',
                               type=int,
                               choices=range(TardisCrypto.maxCryptoScheme + 1),
                               default=TardisCrypto.defaultCryptoScheme,
                               help='Use cryptography scheme\n' +
                               TardisCrypto.getCryptoNames())
    passgroup.add_argument('--keys',
                           dest='keys',
                           default=config.get(job, 'KeyFile'),
                           help='Load keys from file.')
Пример #3
0
def main():
    global logger
    progressbar.streams.wrap_stderr()
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('')
    args = processArgs()
    password = Util.getPassword(args.password, args.passwordfile, args.passwordprog)

    crypto = TardisCrypto.TardisCrypto(password, args.client)

    path = os.path.join(args.database, args.client, args.dbname)
    db = TardisDB.TardisDB(path, backup=False)

    Util.authenticate(db, args.client, password)
    (f, c) = db.getKeys()
    crypto.setKeys(f, c)

    cacheDir = CacheDir.CacheDir(os.path.join(args.database, args.client))

    if args.names or args.all:
        encryptFilenames(db, crypto)
    if args.dirs or args.all:
        generateDirHashes(db, crypto, cacheDir)
    if args.sigs or args.all:
        generateSignatures(db, crypto, cacheDir)
    if args.files or args.all:
        encryptFiles(db, crypto, cacheDir)
    if args.meta or args.all:
        generateMetadata(db, cacheDir)
Пример #4
0
def setPassword(password):
    try:
        (db, _, _) = getDB(None)
        crypt = TardisCrypto.getCrypto(TardisCrypto.defaultCryptoScheme,
                                       password)
        crypt.genKeys()
        (f, c) = crypt.getKeys()
        (salt,
         vkey) = srp.create_salted_verification_key(args.client, password)
        if args.keys:
            db.beginTransaction()
            db.setSrpValues(salt, vkey)
            db.setConfigValue('CryptoScheme', crypt.getCryptoScheme())
            Util.saveKeys(args.keys, db.getConfigValue('ClientID'), f, c)
        else:
            db.setKeys(salt, vkey, f, c)
            db.setConfigValue('CryptoScheme', crypt.getCryptoScheme())
        return 0
    except TardisDB.NotAuthenticated:
        logger.error('Client %s already has a password', args.client)
        if args.exceptions:
            logger.exception(e)
        return 1
    except TardisDB.AuthenticationFailed as e:
        logger.error("Authentication failed.  Bad password")
        if args.exceptions:
            logger.exception(e)
        return 1
    except Exception as e:
        logger.error(str(e))
        if args.exceptions:
            logger.exception(e)
        return 1
Пример #5
0
def main():
    global logger
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger('')
    args = processArgs()
    password = Util.getPassword(args.password, args.passwordfile,
                                args.passwordurl, args.passwordprog)

    crypto = TardisCrypto.TardisCrypto(password, args.client)
    token = crypto.createToken()

    #logger.info("Created token: %s", token)
    path = os.path.join(args.database, args.client, args.dbname)
    db = TardisDB.TardisDB(path, token=token, backup=False)
    (f, c) = db.getKeys()
    crypto.setKeys(f, c)

    cacheDir = CacheDir.CacheDir(os.path.join(args.database, args.client))

    #if args.sigs:
    #    generateSignatures(db, cacheDir)
    if args.filenames:
        encryptFilenames(db, crypto)
    if args.files:
        encryptFiles(db, crypto, cacheDir)
    if args.dirhash:
        generateDirHashes(db, crypto, cacheDir)
    if args.meta:
        generateMetadata(db, cacheDir)
Пример #6
0
def changePassword(crypt, oldpw):
    try:
        (db, _, crypt) = getDB(oldpw)

        # Get the new password
        try:
            newpw = Util.getPassword(args.newpw,
                                     args.newpwf,
                                     args.newpwp,
                                     prompt="New Password for %s: " %
                                     (args.client),
                                     allowNone=False,
                                     confirm=True,
                                     strength=True)
        except Exception as e:
            logger.critical(str(e))
            if args.exceptions:
                logger.exception(e)
            return -1

        scheme = db.getConfigValue('CryptoScheme', 1)
        crypt2 = TardisCrypto.getCrypto(scheme, newpw, args.client)

        # Load the keys, and insert them into the crypt object, to decyrpt them
        if args.keys:
            (f, c) = Util.loadKeys(args.keys, db.getConfigValue('ClientID'))
            # No need to check here, loadKeys() throws exception if nothing set.
        else:
            (f, c) = db.getKeys()
            if f is None or c is None:
                logger.critical(
                    "No keys loaded from database.  Please specify --keys as appropriate"
                )
                raise Exception("No keys loaded")
        crypt.setKeys(f, c)

        # Grab the keys from one crypt object.
        # Need to do this because getKeys/setKeys assumes they're encrypted, and we need the raw
        # versions
        crypt2._filenameKey = crypt._filenameKey
        crypt2._contentKey = crypt._contentKey
        # Now get the encrypted versions
        (f, c) = crypt2.getKeys()

        (salt, vkey) = srp.create_salted_verification_key(args.client, newpw)

        if args.keys:
            db.beginTransaction()
            db.setSrpValues(salt, vkey)
            Util.saveKeys(args.keys, db.getConfigValue('ClientID'), f, c)
            db.commit()
        else:
            db.setKeys(salt, vkey, f, c)
        return 0
    except Exception as e:
        logger.error(str(e))
        if args.exceptions:
            logger.exception(e)
        return 1
Пример #7
0
def validate(root, client, dbname, password):
    crypto = None
    token = None
    base = os.path.join(root, client)
    cache = CacheDir.CacheDir(base)
    if password:
        crypto = TardisCrypto.TardisCrypto(password, client)
        token = crypto.encryptFilename(client)
    db = TardisDB.TardisDB(os.path.join(base, dbname), token=token, backup=False)
    regen = Regenerate.Regenerator(cache, db, crypto)

    conn = db.conn

    cur = conn.execute("SELECT count(*) FROM CheckSums WHERE IsFile = 1")
    row = cur.fetchone()
    num = row[0]
    print("Checksums: %d" % (num))

    cur = conn.execute("SELECT Checksum FROM CheckSums WHERE IsFile = 1 ORDER BY Checksum ASC");
    pbar = pb.ProgressBar(widgets=[pb.Percentage(), ' ', pb.Counter(), ' ', pb.Bar(), ' ', pb.ETA(), ' ', pb.Timer() ], maxval=num)
    pbar.start()

    row = cur.fetchone()
    i = 1
    while row is not None:
        pbar.update(i)
        i += 1
        try:
            checksum = row['Checksum']
            if not checksum in checked:
                try:
                    f = regen.recoverChecksum(checksum)
                    if f:
                        m = hashlib.md5()
                        d = f.read(128 * 1024)
                        while d:
                            m.update(d)
                            d = f.read(128 * 1024)
                        res = m.hexdigest()
                        if res != checksum:
                            print("Checksums don't match.  Expected: %s, result %s" % (checksum, res))
                            checked[checksum] = 0
                            output.write(checksum + '\n')
                            output.flush()
                        else:
                            checked[checksum] = 1
                            valid.write(checksum + "\n")
                except Exception as e:
                    print("Caught exception processing %s: %s" % (checksum, str(e)))
                    output.write(checksum + '\n')
                    output.flush()

            row = cur.fetchone()
        except sqlite3.OperationalError as e:
            print("Caught operational error.  DB is probably locked.  Sleeping for a bit")
            time.sleep(90)
    pbar.finish()
Пример #8
0
def setupDataConnection(dataLoc, client, password, keyFile, dbName, dbLoc=None, allow_upgrade=False, retpassword=False):
    """ Setup a data connection to a client.   Determines the correct way to connect, either via direct filesystem, 
    or via TardisRemote (http).
    Returns a 3-tuple, the TardisDB object, the CacheDir object, and the appropriate crypto object
    """
    logger.debug("Connection requested for %s under %s", client, dataLoc)
    crypt = None

    loc = urllib.parse.urlparse(dataLoc)
    if (loc.scheme == 'http') or (loc.scheme == 'https'):
        logger.debug("Creating remote connection to %s", dataLoc)
        # If no port specified, insert the port
        if loc.port is None:
            netloc = loc.netloc + ":" + Defaults.getDefault('TARDIS_REMOTE_PORT')
            dbLoc = urllib.parse.urlunparse((loc.scheme, netloc, loc.path, loc.params, loc.query, loc.fragment))
        else:
            dbLoc = dataLoc
        # get the RemoteURL object
        logger.debug("==> %s %s", dbLoc, client)
        tardis = RemoteDB.RemoteDB(dbLoc, client)
        cache = tardis
    else:
        logger.debug("Creating direct connection to %s", dataLoc)
        cacheDir = os.path.join(loc.path, client)
        cache = CacheDir.CacheDir(cacheDir, create=False)
        if not dbLoc:
            dbDir = cacheDir
        else:
            dbDir = os.path.join(dbLoc, client)
        dbPath = os.path.join(dbDir, dbName)
        tardis = TardisDB.TardisDB(dbPath, allow_upgrade=allow_upgrade)

    needsAuth = tardis.needsAuthentication()
    if needsAuth and password is None:
        password = getPassword(True, None, None, "Password for %s: " % client, allowNone=False)

    if needsAuth:
        authenticate(tardis, client, password)
    elif password:
        raise TardisDB.AuthenticationFailed()

    # Password specified, so create the crypto unit
    #cryptoScheme = tardis.getConfigValue('CryptoScheme', '1')
    cryptoScheme = tardis.getCryptoScheme()

    crypt = TardisCrypto.getCrypto(cryptoScheme, password, client)
    if keyFile:
        (f, c) = loadKeys(keyFile, tardis.getConfigValue('ClientID'))
    else:
        (f, c) = tardis.getKeys()
    crypt.setKeys(f, c)

    if retpassword:
        return (tardis, cache, crypt, password)
    else:
        return (tardis, cache, crypt)
Пример #9
0
def setupDataConnection(dataLoc,
                        client,
                        password,
                        keyFile,
                        dbName,
                        dbLoc=None,
                        allow_upgrade=False):
    logger.debug("Connection requested for %s under %s", client, dataLoc)
    crypt = None

    loc = urlparse.urlparse(dataLoc)
    if (loc.scheme == 'http') or (loc.scheme == 'https'):
        logger.debug("Creating remote connection to %s", dataLoc)
        # If no port specified, insert the port
        if loc.port is None:
            netloc = loc.netloc + ":" + Defaults.getDefault(
                'TARDIS_REMOTE_PORT')
            dbLoc = urlparse.urlunparse((loc.scheme, netloc, loc.path,
                                         loc.params, loc.query, loc.fragment))
        else:
            dbLoc = dataLoc
        # get the RemoteURL object
        logger.debug("==> %s %s", dbLoc, client)
        tardis = RemoteDB.RemoteDB(dbLoc, client)
        cache = tardis
    else:
        logger.debug("Creating direct connection to %s", dataLoc)
        cacheDir = os.path.join(loc.path, client)
        cache = CacheDir.CacheDir(cacheDir, create=False)
        if not dbLoc:
            dbDir = cacheDir
        else:
            dbDir = os.path.join(dbLoc, client)
        dbPath = os.path.join(dbDir, dbName)
        tardis = TardisDB.TardisDB(dbPath, allow_upgrade=allow_upgrade)

    needsAuth = tardis.needsAuthentication()
    if needsAuth and password is None:
        password = getPassword(True, None, None, "Password for %s: " % client)

    if password:
        if needsAuth:
            authenticate(tardis, client, password)
        else:
            raise TardisDB.AuthenticationFailed()

        # Password specified, so create the crypto unit
        crypt = TardisCrypto.TardisCrypto(password, client)
        if keyFile:
            (f, c) = loadKeys(keyFile, tardis.getConfigValue('ClientID'))
        else:
            (f, c) = tardis.getKeys()
        crypt.setKeys(f, c)

    return (tardis, cache, crypt)
Пример #10
0
def main():
    logging.basicConfig(level=logging.DEBUG)
    args = processArgs()
    password = Util.getPassword(args.password, args.passwordfile,
                                args.passwordurl, args.passwordprog)

    crypto = TardisCrypto.TardisCrypto(password, args.client)
    token = crypto.createToken()

    path = os.path.join(args.database, args.client, args.dbname)
    db = TardisDB.TardisDB(path, backup=False)
    db.setToken(token)
Пример #11
0
def main():
    logging.basicConfig(level=logging.INFO)
    crypto = None
    token = None
    args = processArgs()
    password = Util.getPassword(args.password, args.passwordfile,
                                args.passwordurl, args.passwordprog)

    if password:
        crypto = TardisCrypto.TardisCrypto(password, args.client)

    path = os.path.join(args.database, args.client, args.dbname)
    db = TardisDB.TardisDB(path, token=token, backup=False)

    if crypto:
        (a, b) = db.getKeys()
        crypto.setKeys(a, b)

    conn = db.conn
    dirs = conn.execute(
        "SELECT Name as name, Inode AS inode, Device AS device, FirstSet as firstset, LastSet AS lastset FROM Files JOIN Names ON Files.NameId = Names.NameId WHERE Dir = 1"
    )
    while True:
        batch = dirs.fetchmany(1000)
        if not batch:
            break

        for d in batch:
            name = d['name']
            inode = d['inode']
            device = d['device']
            firstset = d['firstset']
            lastset = d['lastset']

            files = db.readDirectory((inode, device), current=lastset)
            (checksum, nfiles) = Util.hashDir(crypto, files, True)

            print("%-20s (%d, %d) [%d %d] -- %s %d") % (
                name, inode, device, firstset, lastset, checksum, nfiles)
            ckinfo = db.getChecksumInfo(checksum)
            if ckinfo:
                cksid = ckinfo['checksumid']
            else:
                cksid = db.insertChecksumFile(checksum,
                                              size=nfiles,
                                              isFile=False)

            db.updateDirChecksum((inode, device), cksid, current=lastset)
        conn.commit()
Пример #12
0
def main():
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    crypto = None
    args = processArgs()
    password = Util.getPassword(args.password, args.passwordfile, args.passwordurl, args.passwordprog)

    if password:
        crypto = TardisCrypto.TardisCrypto(password, args.client)

    path = os.path.join(args.database, args.client, args.dbname)
    db = TardisDB.TardisDB(path, backup=False)

    token = createToken(crypto, args.client)
    if not checkToken(db, token):
        logger.error("Password does not match")
        sys.exit(1)

    salt, vkey = srp.create_salted_verification_key(args.client, password)
    db.setSrpValues(salt, vkey)
    db._setConfigValue('Token', None)
Пример #13
0
def setupDataConnection(dataLoc, client, password, keyFile, dbName, dbLoc=None, allow_upgrade=False):
    crypt = None
    if password:
        crypt = TardisCrypto.TardisCrypto(password, client)
    password = None
    token = None
    if crypt:
        token = crypt.createToken()

    loc = urlparse.urlparse(dataLoc)
    if (loc.scheme == 'http') or (loc.scheme == 'https'):
        # If no port specified, insert the port
        if loc.port is None:
            netloc = loc.netloc + ":" + Defaults.getDefault('TARDIS_REMOTE_PORT')
            dbLoc = urlparse.urlunparse((loc.scheme, netloc, loc.path, loc.params, loc.query, loc.fragment))
        else:
            dbLoc = dataLoc
        # get the RemoteURL object
        tardis = RemoteDB.RemoteDB(dbLoc, client, token=token)
        cache = tardis
    else:
        cacheDir = os.path.join(loc.path, client)
        cache = CacheDir.CacheDir(cacheDir, create=False)
        if not dbLoc:
            dbDir = cacheDir
        else:
            dbDir = os.path.join(dbLoc, client)
        dbPath = os.path.join(dbDir, dbName)
        tardis = TardisDB.TardisDB(dbPath, token=token, allow_upgrade=allow_upgrade)

    if crypt:
        if keyFile:
            (f, c) = loadKeys(keyFile, tardis.getConfigValue('ClientID'))
        else:
            (f, c) = tardis.getKeys()
        crypt.setKeys(f, c)

    return (tardis, cache, crypt)
Пример #14
0
def sendDataPlain(sender, data, chunksize=(16 * 1024), compress=None, stats=None):
    """
    Send data, with no encryption, or calculation
    """
    encrypt = TardisCrypto.NullEncryptor()
    sendData(sender, data, encrypt, chunksize=chunksize, compress=compress, stats=stats)
Пример #15
0
def main():
    global logger, exceptionLogger, args
    parseArgs()
    logger = Util.setupLogging(args.verbose)
    exceptionLogger = Util.ExceptionLogger(logger, args.exceptions)

    # Commands which cannot be executed on remote databases
    allowRemote = args.command not in ['create', 'upgrade']

    db      = None
    crypt   = None
    cache   = None
    try:
        confirm = args.command in ['setpass', 'create']
        allowNone = args.command not in ['setpass', 'chpass']
        try:
            password = Util.getPassword(args.password, args.passwordfile, args.passwordprog, prompt="Password for %s: " % (args.client), allowNone=allowNone, confirm=confirm)
        except Exception as e:
            logger.critical(str(e))
            exceptionLogger.log(e)
            return -1
            
        if password:
            crypt = TardisCrypto.TardisCrypto(password, args.client)
            args.password = None

        if args.command == 'create':
            return createClient(crypt, password)

        if args.command == 'setpass':
            if not Util.checkPasswordStrength(password):
                return -1

            if not crypt:
                logger.error("No password specified")
                return -1
            return setPassword(crypt, password)

        if args.command == 'chpass':
            return changePassword(crypt, password)

        upgrade = (args.command == 'upgrade')

        try:
            (db, cache) = getDB(crypt, password, allowRemote=allowRemote, allowUpgrade=upgrade)

            if crypt and args.command != 'keys':
                if args.keys:
                    (f, c) = Util.loadKeys(args.keys, db.getConfigValue('ClientID'))
                else:
                    (f, c) = db.getKeys()
                crypt.setKeys(f, c)
        except TardisDB.AuthenticationException as e:
            logger.error("Authentication failed.  Bad password")
            exceptionLogger.log(e)
            sys.exit(1)
        except Exception as e:
            logger.critical("Unable to connect to database: %s", e)
            exceptionLogger.log(e)
            sys.exit(1)

        if args.command == 'keys':
            return moveKeys(db, crypt)
        elif args.command == 'list':
            return listBSets(db, crypt, cache)
        elif args.command == 'files':
            return listFiles(db, crypt)
        elif args.command == 'info':
            return bsetInfo(db)
        elif args.command == 'purge':
            return purge(db, cache)
        elif args.command == 'delete':
            return deleteBsets(db, cache)
        elif args.command == 'priority':
            return setPriority(db)
        elif args.command == 'rename':
            return renameSet(db)
        elif args.command == 'getconfig':
            return getConfig(db)
        elif args.command == 'setconfig':
            return setConfig(db)
        elif args.command == 'orphans':
            return removeOrphans(db, cache)
        elif args.command == 'upgrade':
            return
    except KeyboardInterrupt:
        pass
    except TardisDB.AuthenticationException as e:
        logger.error("Authentication failed.  Bad password")
        sys.exit(1)
    except Exception as e:
        logger.error("Caught exception: %s", str(e))
        exceptionLogger.log(e)
    finally:
        if db:
            db.close()
Пример #16
0
def main():
    global logger
    parseArgs()
    logger = Util.setupLogging(args.verbose)

    # Commands which cannot be executed on remote databases
    allowRemote = args.command not in ['create']

    db = None
    crypt = None
    cache = None
    try:
        password = Util.getPassword(args.password,
                                    args.passwordfile,
                                    args.passwordprog,
                                    prompt="Password for %s: " % (args.client),
                                    allowNone=(args.command != 'setPass'))
        if args.command in ['setpass', 'create']:
            if password and not checkPasswordStrength(password):
                return -1

            if args.password:
                pw2 = Util.getPassword(args.password,
                                       args.passwordfile,
                                       args.passwordprog,
                                       prompt='Confirm Password: '******'t match")
                    return -1
                pw2 = None

        if password:
            crypt = TardisCrypto.TardisCrypto(password, args.client)
            password = None
            args.password = None

        if args.command == 'create':
            return createClient(crypt)

        if args.command == 'setpass':
            if not crypt:
                logger.error("No password specified")
                return -1
            return setToken(crypt)

        if args.command == 'chpass':
            newpw = Util.getPassword(args.newpw,
                                     args.newpwf,
                                     args.newpwp,
                                     prompt="New Password for %s: " %
                                     (args.client),
                                     allowNone=False)
            if not checkPasswordStrength(newpw):
                return -1

            if args.newpw is True:
                newpw2 = Util.getPassword(args.newpw,
                                          args.newpwf,
                                          args.newpwp,
                                          prompt="New Password for %s: " %
                                          (args.client),
                                          allowNone=False)
                if newpw2 != newpw:
                    logger.error("Passwords don't match")
                    return -1
                newpw2 = None

            crypt2 = TardisCrypto.TardisCrypto(newpw, args.client)
            newpw = None
            args.newpw = None
            return changePassword(crypt, crypt2)

        try:
            (db, cache) = getDB(crypt, allowRemote=allowRemote)
            if crypt:
                if args.keys:
                    (f, c) = Util.loadKeys(args.keys,
                                           db.getConfigValue('ClientID'))
                else:
                    (f, c) = db.getKeys()
                crypt.setKeys(f, c)
        except Exception as e:
            logger.critical("Unable to connect to database: %s", e)
            sys.exit(1)

        if args.command == 'keys':
            return moveKeys(db, crypt)
        elif args.command == 'list':
            return listBSets(db)
        elif args.command == 'files':
            return listFiles(db, crypt)
        elif args.command == 'info':
            return bsetInfo(db)
        elif args.command == 'purge':
            return purge(db, cache)
        elif args.command == 'delete':
            return deleteBsets(db, cache)
        elif args.command == 'getconfig':
            return getConfig(db)
        elif args.command == 'setconfig':
            return setConfig(db)
        elif args.command == 'orphans':
            return removeOrphans(db, cache)
    except KeyboardInterrupt:
        pass
    except Exception as e:
        logger.error("Caught exception: %s", str(e))
        logger.exception(e)
    finally:
        if db:
            db.close()