Exemple #1
0
def runCommand(cmdName, arg):
    log.verbose(f"runCommand {cmdName} {arg}")
    before_mtime = 0

    cmd = config.CONFIG['commands'][cmdName]
    if cmd is None:
        log.error("no command configured for 'deleteFile'")
        log.warning(f"path {path} was not deleted")
        return

    cmdArgs = cmd.replace("{}", arg).split()
    log.verbose(f"cmdArgs: {cmdArgs}")
    if os.path.exists(arg):
        before_mtime = os.path.getmtime(arg)
    try:
        ret = subprocess.call(args=cmdArgs, shell=False)
        log.verbose(f"ret: {ret}")
        if ret != 0:
            log.warning("process exited with error")
    except Exception as e:
        log.error(f"error running command '{cmd} {arg}' -> {e}")
        return False

    if not os.path.exists(arg):
        return False
    after_mtime = os.path.getmtime(arg)
    log.verbose(f"before mtime: {before_mtime}")
    log.verbose(f"after mtime: {after_mtime}")
    return after_mtime > before_mtime
Exemple #2
0
def encryptVPath(path):
    log.verbose(f"encryptVPath path={path}")
    (plainPath, vpath) = validateEncryptVPath(path)
    log.verbose(f"encryptVpath plainPath={plainPath}, vpath={vpath}")
    pp64 = getPassPhrase(config.CONFIG['general']['group'], True)
    crypto.encryptFile(plainPath, vpath, pp64)
    file.deletePath(plainPath)
Exemple #3
0
def cmd_reencrypt(cmd, path):
    log.verbose(f"cmd_reencrypt cmd={cmd}, path={path}")
    tmpdir = utils.getTmpDir()
    try:
        tmppath = os.path.join(tmpdir, str(os.getpid()))
        vault.reencryptVPath(path, tmppath)
    finally:
        file.deleteDir(tmpdir)
Exemple #4
0
def openVPath(path, destpath, cmd):
    log.verbose(f"openVPath {path} {destpath} {cmd}")
    (plainPath, vpath) = validateOpenVPath(path)
    pp64 = getPassPhrase(config.CONFIG['general']['group'], False)
    crypto.decryptFile(vpath, destpath, pp64)
    if destpath is not None and cmd is not None:
        if utils.runCommand(cmd, destpath):
            log.warning("file has been modified; updates discarded")
Exemple #5
0
def cmd_edit(cmd, path):
    log.verbose(f"cmd_edit {cmd}, {path}")
    tmpdir = utils.getTmpDir()
    try:
        tmppath = os.path.join(tmpdir, str(os.getpid()))
        vault.editVPath(path, tmppath, cmd)
    finally:
        file.deleteDir(tmpdir)
Exemple #6
0
def deletePath(path):

    log.verbose(f"deletePath path={path}")
    if not os.path.exists(path):
        log.info("path " + path + " does not exist")
    else:
        utils.runCommand('delete_file', path)
        if os.path.exists(path):
            raise errors.VaultError(f"error deleting file {path}")
Exemple #7
0
def connect(sock, port):

    try:
        log.verbose(f"connecting to server on port {port}")
        sock.connect(('localhost', int(port)))
    except socket.error as e:
        if e.errno == errno.ECONNREFUSED:
            return False
        log.error(f"error connecting to server: {e}")
        raise e
    return True
Exemple #8
0
def getTmpDir():

    td = getVaultDir()
    prefix = config.CONFIG['internal']['tmp.dir.prefix']
    p = "%s%s" % (prefix, str(os.getpid()))
    path = os.path.join(td, p)
    log.verbose(f"tmp tmp dir: {path}")
    if os.path.exists(path):
        log.error(f"tempory directory {path} already exists")
    os.mkdir(path)
    if not os.path.exists(path):
        log.error(f"tempory directory {path} was not created")
    return path
Exemple #9
0
def reencryptVPath(path, destpath):
    log.verbose(f"reencryptVPath path={path}, destpath={destpath}")
    (plainPath, vpath) = validateReencryptVPath(path)
    log.verbose(f"reencryptVpath plainPath={plainPath}, vpath={vpath}")
    group = config.CONFIG['general']['group']
    group_current = group + ".current"
    group_new = group + ".new"

    pp64 = getPassPhrase(group_current, False, " (current)")
    crypto.decryptFile(vpath, destpath, pp64)

    pp64 = getPassPhrase(group_new, True, " (new)")
    crypto.encryptFile(destpath, vpath, pp64)
Exemple #10
0
def deleteDir(path):

    if not re.match("^/\w+/\w+", path):
        raise errors.VaultError(f"invalid vault directory")

    log.verbose(f"deleteDir path={path}")

    if not os.path.exists(path):
        log.info(f"path {path} does not exist")
    else:
        utils.runCommand('delete_dir', path)
        if os.path.exists(path):
            raise errors.VaultError(f"error deleting directory {path}")
Exemple #11
0
def getServerPort(vdir):

    log.verbose(f"getServerPort vdir={vdir}")
    pidFile = os.path.join(vdir, 'server.pid')
    if not os.path.exists(pidFile):
        log.verbose(f"pidfile {pidFile} does not exist")
        log.info("launching server")
        args = ['gpg-vault-server', vdir]
        global pid
        pid = subprocess.Popen(args=args, shell=False).pid
        log.verbose(f"pid: {pid}")

    count = 10
    while not os.path.exists(pidFile):
        log.info("waiting for server to start")
        time.sleep(1)

    f = open(pidFile, "r")
    lines = f.readlines()
    if lines is None or len(lines) != 2:
        log.error(f"cannot read pidFile {pidFile}")
        exit(1)

    port = int(lines[1])
    log.verbose(f"found server port={port}")
    return port
Exemple #12
0
def getPassPhrase(group, confirm, tag=""):
    log.verbose(f"getting passphrase group={group}, comfirm={confirm}")
    pp = client.sendRequest(['get', group])
    if len(pp) >= 1:
        log.verbose("got passphrase from server")
        log.sensitive(f"passphrase (base64): {pp[0]}")
        return pp[0]
    pp = ''
    try:
        while pp == '':
            pp = getpass.getpass(f"Passphrase{tag}: ")
        if confirm:
            pp2 = ''
            while pp2 == '':
                pp2 = getpass.getpass(f"Confirm Passphrase{tag}: ")
            if pp != pp2:
                del pp
                del pp2
                raise errors.VaultSecurityError("Passphrases do not match")
            del pp2
        log.sensitive(f"passphrase |{pp}|")
        pp64 = utils.str2b64(
            pp)  # base64.b64encode(pp.encode('utf-8')).decode('utf-8')
        log.sensitive(f"base64 |{pp64}|")
        client.sendRequest(['set', group, pp64])
        del pp
        return pp64
    except EOFError as e:
        log.verbose(f"exception raised: {e}")
        raise errors.VaultQuit(str(e))
    except Exception as e:
        log.verbose(f"exception raised: {e}")
        raise errors.VaultQuit(str(e))
Exemple #13
0
def validateVPaths(path):
    (plainPath, vpath) = validateVPath(path)
    log.verbose(f"validating plainPath={plainPath}, vpath={vpath}")
    if os.path.islink(plainPath):
        raise errors.VaultError("'" + plainPath + "' is a symbolic link")
    if os.path.exists(plainPath) and os.path.exists(vpath):
        if os.path.getmtime(plainPath) > os.path.getmtime(vpath):
            older = f"{plainPath} is more recent"
        else:
            older = f"{vpath} is more recent"
        raise errors.VaultError(
            f"both '{plainPath}' and '{vpath}' exist ({older})")
    if os.path.islink(vpath):
        raise errors.VaultError(f"'{vpath}' is a symbolic link")
    return (plainPath, vpath)
Exemple #14
0
def run(cmd, files):

    client.sendRequest(['ping'])

    if files is None:
        runForFile(cmd, None)
    else:
        for file in config.CONFIG['files']:
            log.verbose("running command '" + cmd + "' on file '" + file + "'")
            runForFile(cmd, file)

    if utils.isTrue(config.CONFIG['general']['kill_server']):
        client.killServer()

    exit(0)
Exemple #15
0
def backupFile(path):
    log.verbose(f"backupFile path={path}")
    if not os.path.exists(path):
        return
    backup_path = path + config.CONFIG['internal']['ext.backup']
    if os.path.exists(backup_path):
        deletePath(backup_path)
    log.verbose(f"backupFile renaming {path} to {backup_path}")
    os.rename(path, backup_path)
    if os.path.exists(path):
        raise VaultError(
            f"error creating backup of {path}; file still exists after renaming to {backup_path}"
        )
    if not os.path.exists(backup_path):
        raise VaultError(
            f"error creating backup of {path}; backup file {backup_path} not created"
        )
Exemple #16
0
def decryptFile(vpath, destPath, pp64):
    log.verbose(f"decyptFile vpath={vpath} destPath={destPath}")
    passphrase = utils.b642str(pp64)
    log.sensitive(f"passphrase |{passphrase}|")
    args = [
        'gpg', '--quiet', '--batch', '--ignore-mdc-error', '--decrypt',
        '--passphrase-fd', '0'
    ]
    if destPath is not None:
        args.extend(['--output', destPath])
    args.append(vpath)
    log.verbose(f"args: {args}")
    gpgErrorLog = os.path.join(utils.getVaultDir(), "gpg.error.log")
    try:
        gpgError = open(gpgErrorLog, "a")
    except IOError:
        raise errors.VaultError(
            f"Unable to open gpg error log file '{gpgErrorlog}'")
    try:
        gpg = subprocess.Popen(args=args,
                               shell=False,
                               stdin=subprocess.PIPE,
                               stderr=gpgError)
        gpg.stdin.write(passphrase.encode('utf-8'))
        gpg.stdin.close()
        gpg.wait()
        if gpg.returncode != 0:
            raise errors.VaultSecurityError("Failed to decrypt file '" +
                                            vpath + "'")
    finally:
        log.verbose("closing gpg error file")
        if gpgError:
            gpgError.close
Exemple #17
0
def encryptFile(srcPath, destPath, pp64):
    log.verbose(f"encyptFile srcPath={srcPath} destPath={destPath}")
    passphrase = utils.b642str(pp64)
    log.sensitive(f"passphrase |{passphrase}|")
    if os.path.exists(destPath):
        file.deletePath(destPath)
    args = [
        'gpg', '--quiet', '--batch', '-c', '--symmetric', '--passphrase-fd',
        '0', '--output', destPath, srcPath
    ]
    log.verbose(f"args: {args}")
    gpgErrorLog = os.path.join(utils.getVaultDir(), "gpg.stderr.log")
    log.info(f"encrypting file {srcPath} to {destPath}")
    try:
        gpgError = open(gpgErrorLog, "a")
    except IOError:
        raise errors.VaultError("Unable to open gpg error log file '" +
                                gpgErrorLog + "'")
    try:
        gpg = subprocess.Popen(args=args,
                               shell=False,
                               stdin=subprocess.PIPE,
                               stderr=gpgError)
        gpg.stdin.write(passphrase.encode('utf-8'))
        gpg.stdin.close()
        gpg.wait()
        if gpg.returncode != 0:
            raise errors.VaultSecurityError(
                "Failed to encrypt file '" + srcPath + "'", [])
    finally:
        log.verbose("closing gpg error file")
        if gpgError:
            gpgError.close
Exemple #18
0
def sendRequest(args):

    log.verbose(f"sendRequest args={args}")
    req = " ".join(args)
    tryAgain = True
    while tryAgain:
        tryAgain = False
        port = getServerPort(utils.getVaultDir())
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            if connect(sock, port):
                log.verbose("sending request to server")
                sock.sendall((req + "\n").encode('utf-8'))
                reply = sock.recv(1024)
            else:
                # Assume the server is not running
                log.info("cannot connect; trying again")
                time.sleep(1)
                deleteServerPort(utils.getVaultDir())
                tryAgain = True
                continue
        finally:
            sock.close()

    ret = re.split('\s+', reply.decode('utf-8'))
    if ret is None or len(ret) < 1:
        raise VaultError('unable to process reply')

    log.sensitive(f"response: {ret}")
    if ret[0] == 'ok':
        log.verbose('reply ok')
        return ret[1:]
    elif ret[0] == 'error':
        log.verbose(f"reply {ret}")
        raise errors.VaultSecurityError(str(ret))
    else:
        log.verbose(f"unexpected reply {ret}")
        raise errors.VaultError('unable to process reply')
Exemple #19
0
def getVPathExt(path):
    for vext in config.CONFIG['internal']['vexts']:
        vpath = path + vext
        log.verbose(f"checking for vpath {vpath}")
        if os.path.exists(vpath):
            log.verbose(f"found {vpath}")
            return vext
    log.verbose("no files found; using default extension")
    return config.CONFIG['internal']['vext.default']
Exemple #20
0
def editVPath(path, destpath, cmd):
    log.verbose(f"editVPath {path} {destpath} {cmd}")
    (plainPath, vpath) = validateEditVPath(path)
    log.verbose(f"editVpath plainPath={plainPath}, vpath={vpath}")
    if os.path.exists(vpath):
        log.verbose(f"editVpath vpath {vpath} exists; decrypting")
        pp64 = getPassPhrase(config.CONFIG['general']['group'], False)
        crypto.decryptFile(vpath, destpath, pp64)
    else:
        log.verbose(f"editVpath vpath {vpath} does not exist")
        pp64 = getPassPhrase(config.CONFIG['general']['group'], True)
    if utils.runCommand(cmd, destpath):
        file.backupFile(path)
        crypto.encryptFile(destpath, vpath, pp64)
    else:
        if os.path.exists(destpath):
            log.warning("file has not been modified")
        else:
            log.warning("file has not been created")
    file.deletePath(destpath)
Exemple #21
0
def validateVPath(path):
    log.verbose(f"validating path='{path}'")
    (base, ext) = utils.splitPath(path)
    log.verbose(f"base={base}, ext={ext}")
    (vext) = getVPathExt(base + ext)
    log.verbose(f"vpath ext={vext}")
    if base == '':
        raise errors.VaultError(f"Invalid path '{path}' (base)")
    if ext == '':
        raise errors.VaultError(f"Invalid path '{path}' (ext)")
    if vext == '':
        raise errors.VaultError(f"Invalid path '{path}' (vext)")
    return (base + ext, base + ext + vext)
Exemple #22
0
def getVaultDir():

    home = os.path.expanduser("~")

    log.verbose(f"home dir: {home}")

    if not os.path.exists(home):
        error(f"Directory {home} does not exist")

    t = config.WORK_DIR_NAME
    vdir = os.path.join(home, t)
    log.verbose(f"vault directory: {vdir}")

    if not os.path.exists(vdir):
        log.verbose(f"creating directory {vdir}")
        os.mkdir(vdir)
        if not os.path.exists(vdir):
            log.error(f"failed to create directory {vdir}")

    return vdir
Exemple #23
0
def cmd_encrypt(cmd, path):
    log.verbose(f"cmd_encrypt cmd={cmd}, path={path}")
    vault.encryptVPath(path)
Exemple #24
0
def cmd_clear(cmd, path):
    log.verbose(f"cmd_clear {cmd}, {path}")
    cmd_reset()
Exemple #25
0
 def __init__(self, e):
     log.verbose(f"VaultQuit: {e}")
     self.error = e
Exemple #26
0
 def __init__(self, e):
     log.verbose(f"VaultSecurityError: {e}")
     self.error = e
Exemple #27
0
def cmd_reset():
    log.verbose("sending reset request")
    client.sendRequest(['reset'])
Exemple #28
0
def cmd_cat(cmd, path):
    log.verbose(f"cmd_cat {cmd}, {path}")
    vault.openVPath(path, None, None)
    print("")
    utils.oswarning()