Partial fix for data loss (syncing temporarily disabled)

This commit is contained in:
2021-10-12 23:13:03 -04:00
parent 6cdc158074
commit 18b27c9dce
3 changed files with 120 additions and 42 deletions
+34 -33
View File
@@ -1,8 +1,9 @@
#!/usr/bin/python3 #!/usr/bin/python3
# internal modules # external modules
from os import system import sshync
from os import system as term
from os import remove from os import remove
from os import environ from os import environ
from shutil import move from shutil import move
@@ -14,16 +15,12 @@ import random
import string import string
# custom modules # internal modules
def clear(): def clear():
print('\n' * 100) print('\n' * 100)
def term(cmd):
_ = system(cmd)
def string_found(string1, string2): def string_found(string1, string2):
if search(r"\b" + escape(string1) + r"\b", string2): if search(r"\b" + escape(string1) + r"\b", string2):
return True return True
@@ -116,7 +113,7 @@ if argument == 'version' or argument == '-v':
print('/ /') print('/ /')
print('/ rpass Copyright (C) 2021 Randall Winkhart /') print('/ rpass Copyright (C) 2021 Randall Winkhart /')
print('/ /') print('/ /')
print('/ Version 2021.10.12.mr5.1 /') print('/ Version 2021.10.13.mr5.1 /')
print('/ The Notetaker Update /') print('/ The Notetaker Update /')
print('/ /') print('/ /')
print('////////////////////////////////////////////////////////\n') print('////////////////////////////////////////////////////////\n')
@@ -141,17 +138,9 @@ if argument == 'show c':
if argument == 'config': if argument == 'config':
try: try:
print() print()
directorychoice = str(input('Would you like to use the default entry directory (~/.rpass-store/)? (Y/n) '))
if directorychoice == 'n' or directorychoice == 'N':
print('\nFormat: /this/path/ends/with/a/slash/\n')
directory = str(input('Please input a custom directory: '))
open("/var/lib/rpass/rpass-dir", 'w').write(directory + '\n')
else:
open("/var/lib/rpass/rpass-dir", 'w').write('/home/' + environ.get('USER') + '/.rpass-store/' + '\n')
print()
devicetype = str(input('Will this be a client, server, or offline device? (C/s/o) ')) devicetype = str(input('Will this be a client, server, or offline device? (C/s/o) '))
if devicetype == 's' or devicetype == 'S': if devicetype == 's' or devicetype == 'S':
open("/var/lib/rpass/rpass-ssh", 'w').write('\n\n\n\n' + devicetype) open("/var/lib/rpass/rpass-device", 'w').write(devicetype)
print('\nMake sure the ssh service is running and properly configured.\n') print('\nMake sure the ssh service is running and properly configured.\n')
print('Configuration complete!\n') print('Configuration complete!\n')
else: else:
@@ -182,7 +171,7 @@ if argument == 'config':
term('gpg -r ' + str(gpgid) + ' -e ' + '/var/lib/rpass/lock') term('gpg -r ' + str(gpgid) + ' -e ' + '/var/lib/rpass/lock')
remove('/var/lib/rpass/lock') remove('/var/lib/rpass/lock')
if devicetype == 'o' or devicetype == 'O': if devicetype == 'o' or devicetype == 'O':
open("/var/lib/rpass/rpass-ssh", 'w').write('\n\n\n\n' + devicetype) open("/var/lib/rpass/rpass-device", 'w').write(devicetype)
print('\nConfiguration complete!\n') print('\nConfiguration complete!\n')
elif devicetype != 's' and devicetype != 'S': elif devicetype != 's' and devicetype != 'S':
devicetype = 'c' devicetype = 'c'
@@ -203,8 +192,11 @@ if argument == 'config':
directoryssh = str(input('What directory is the server using?: ')) directoryssh = str(input('What directory is the server using?: '))
else: else:
directoryssh = ('/home/' + usernamessh + '/.rpass-store/') directoryssh = ('/home/' + usernamessh + '/.rpass-store/')
open("/var/lib/rpass/rpass-ssh", 'w').write(usernamessh + '\n' + ip + '\n' + port + '\n' + directoryssh + open("/var/lib/rpass/rpass-device", 'w').write(devicetype)
'\n' + devicetype) sshync.make_sentinel_profile('/var/lib/rpass/rpass.sshync', '/home/' + environ.get('USER') +
'/.rpass-store/', directoryssh, '/home/' + environ.get('USER') +
'/.ssh/rpass', ip, port, usernamessh, '/var/lib/rpass/mod_time',
'/home/nixon/mod_time')
print('\nConfiguration complete!\n') print('\nConfiguration complete!\n')
except KeyboardInterrupt: except KeyboardInterrupt:
print('\n\nConfiguration cancelled.\n') print('\n\nConfiguration cancelled.\n')
@@ -220,23 +212,20 @@ if argument == '':
# import userdata # import userdata
try: try:
sshinfo = open("/var/lib/rpass/rpass-ssh").readlines() devicetype = open('/var/lib/rpass/rpass-device').read().strip()
gpgid = open("/var/lib/rpass/rpass-gpg").read().strip()
sshinfo = sshync.get_profile('/var/lib/rpass/rpass.sshync')
usernamessh = sshinfo[0].replace('\n', '') usernamessh = sshinfo[0].replace('\n', '')
ip = sshinfo[1].replace('\n', '') ip = sshinfo[1].replace('\n', '')
port = sshinfo[2].replace('\n', '') port = sshinfo[2].replace('\n', '')
directoryssh = sshinfo[3].replace('\n', '') directory = str(sshinfo[3].replace('\n', ''))
devicetype = sshinfo[4].replace('\n', '') directoryssh = sshinfo[4].replace('\n', '')
except (FileNotFoundError, IndexError):
usernamessh, ip, port, directoryssh, devicetype = (0, 0, 0, 0, 0)
directory = ''
try:
gpgid = open("/var/lib/rpass/rpass-gpg").read().strip()
directory = open("/var/lib/rpass/rpass-dir").read().strip()
term('mkdir -p ' + directory) term('mkdir -p ' + directory)
except FileNotFoundError: except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print("Not all necessary configuration files are present. Please run 'rpass config'!") print("Not all necessary configuration files are present. Please run 'rpass config'!")
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
devicetype, sshinfo, directory, directoryssh, ip, port, usernamessh = [0, 0, 0, 0, 0, 0, 0]
exit() exit()
# no argument # no argument
@@ -305,6 +294,7 @@ if argument == 'add note' or argument == 'add -n':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('add')
if argument == 'add password' or argument == 'add -p': if argument == 'add password' or argument == 'add -p':
try: try:
@@ -348,10 +338,12 @@ if argument == 'add password' or argument == 'add -p':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('add')
if argument == 'add folder' or argument == 'add -f': if argument == 'add folder' or argument == 'add -f':
newfolder = str(input('Name of new folder: ')) newfolder = str(input('Name of new folder: '))
term('mkdir ' + "'" + directory + newfolder + "'") term('mkdir ' + "'" + directory + newfolder + "'")
open("/var/lib/rpass/mod_time", 'w').write('add')
# edit # edit
@@ -389,6 +381,7 @@ if argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit
print('The file you requested to edit does not exist!') print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('edit')
if argument == 'edit username' or argument == 'edit -u': if argument == 'edit username' or argument == 'edit -u':
try: try:
@@ -431,6 +424,7 @@ if argument == 'edit username' or argument == 'edit -u':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('edit')
if argument == 'edit password' or argument == 'edit -p': if argument == 'edit password' or argument == 'edit -p':
try: try:
@@ -473,6 +467,7 @@ if argument == 'edit password' or argument == 'edit -p':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('edit')
if argument == 'edit url' or argument == 'edit -l': if argument == 'edit url' or argument == 'edit -l':
try: try:
@@ -515,6 +510,7 @@ if argument == 'edit url' or argument == 'edit -l':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('edit')
if argument == 'edit note' or argument == 'edit -n': if argument == 'edit note' or argument == 'edit -n':
try: try:
@@ -556,6 +552,7 @@ if argument == 'edit note' or argument == 'edit -n':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('edit')
# copy # copy
@@ -593,6 +590,7 @@ if argument == 'copy username' or argument == 'copy -u':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('copy')
if argument == 'copy password' or argument == 'copy -p': if argument == 'copy password' or argument == 'copy -p':
try: try:
@@ -619,6 +617,7 @@ if argument == 'copy password' or argument == 'copy -p':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('copy')
if argument == 'copy url' or argument == 'copy -l': if argument == 'copy url' or argument == 'copy -l':
try: try:
@@ -645,6 +644,7 @@ if argument == 'copy url' or argument == 'copy -l':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('copy')
if argument == 'copy note' or argument == 'copy -n': if argument == 'copy note' or argument == 'copy -n':
try: try:
@@ -671,6 +671,7 @@ if argument == 'copy note' or argument == 'copy -n':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('copy')
# gen # gen
@@ -717,6 +718,7 @@ if argument == 'gen':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('gen')
if argument == 'gen update' or argument == 'gen -u': if argument == 'gen update' or argument == 'gen -u':
try: try:
@@ -765,6 +767,7 @@ if argument == 'gen update' or argument == 'gen -u':
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder) rmtree('/dev/shm/' + shmfolder)
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('gen')
# remove # remove
@@ -805,6 +808,7 @@ if argument == 'remove' or argument == '-rm':
print('The file you requested to delete does not exist!') print('The file you requested to delete does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
exit() exit()
open("/var/lib/rpass/mod_time", 'w').write('rm')
if argument.__contains__('-rm') or string_found('remove', argument) or string_found('add', argument) or \ if argument.__contains__('-rm') or string_found('remove', argument) or string_found('add', argument) or \
string_found('edit', argument) or string_found('gen', argument) or string_found('copy', argument) or \ string_found('edit', argument) or string_found('gen', argument) or string_found('copy', argument) or \
@@ -828,7 +832,4 @@ if devicetype == 'c':
if argument.__contains__('-rm') or string_found('remove', argument) or string_found('add', argument) or \ if argument.__contains__('-rm') or string_found('remove', argument) or string_found('add', argument) or \
string_found('edit', argument) or string_found('gen', argument) or argument == 'sync' or argument == '-s': string_found('edit', argument) or string_found('gen', argument) or argument == 'sync' or argument == '-s':
print('Syncing entries with other device(s)...\n') print('Syncing entries with other device(s)...\n')
term('rsync -v -H -r -l -t -p -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + directory + ' ' + sshync.run_profile('/var/lib/rpass/rpass.sshync')
usernamessh + '@' + ip + ':' + directoryssh)
term('rsync -v -H -r -l -t -p --delete -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + usernamessh
+ '@' + ip + ':' + directoryssh + ' ' + directory)
Executable
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/python3
# sshync 2021.10.12.unreleased1
# sshync is a wrapper around sftp that functions as a Python library alternative to scp
# openssh (on POSIX compliant Unix) is required
# sshync will always overwrite the older files with the newer files, regardless of all other conditions
# ^the age is determined by the date and time of the last modification to the files
# syncing via sshync is always done recursively
# external modules
from os.path import getmtime
from subprocess import getoutput as term_output
# internal modules
def make_profile(profile_dir, local_dir, remote_dir, identity, ip, port, user):
open(profile_dir, 'w').write(user + '\n' + ip + '\n' + port + '\n' + local_dir + '\n' + remote_dir + '\n' + identity
+ '\n\n\n')
def make_sentinel_profile(profile_dir, local_dir, remote_dir, identity, ip, port, user, local_sentinel, rem_sentinel):
open(profile_dir, 'w').write(user + '\n' + ip + '\n' + port + '\n' + local_dir + '\n' + remote_dir + '\n' + identity
+ '\n' + local_sentinel + '\n' + rem_sentinel + '\n')
def get_profile(profile_dir):
try:
profile_data = open(profile_dir).readlines()
except (FileNotFoundError, IndexError):
profile_data = 0
return profile_data
def run_profile(profile_dir):
# import profile data
profile_data = get_profile(profile_dir)
user = profile_data[0].replace('\n', '')
ip = profile_data[1].replace('\n', '')
port = profile_data[2].replace('\n', '')
local_dir = profile_data[3].replace('\n', '')
remote_dir = profile_data[4].replace('\n', '')
identity = profile_data[5].replace('\n', '')
local_sentinel = profile_data[6].replace('\n', '')
rem_sentinel = profile_data[7].replace('\n', '')
# get file modification times
if local_sentinel == '':
local_modification_time = getmtime(local_dir)
remote_modification_time = float(
term_output("ssh -i " + "'" + identity + "'" + " -p " + port + " " + user + "@" +
ip + " \"python -c 'from os.path import getmtime; mod_time = "
"(getmtime(" + '\\"' + remote_dir + '\\"' + ")); print(mod_time);"
"'" + "\""))
else:
local_modification_time = getmtime(local_sentinel)
remote_modification_time = float(
term_output("ssh -i " + "'" + identity + "'" + " -p " + port + " " + user + "@" +
ip + " \"python -c 'from os.path import getmtime; mod_time = "
"(getmtime(" + '\\"' + rem_sentinel + '\\"' + ")); print(mod_time);"
"'" + "\""))
# compare file modification times
if local_modification_time > remote_modification_time:
print('\nLocal is newer, uploading...\n') # upload
else:
print('\nRemote is newer, downloading...\n') # download
+16 -9
View File
@@ -1,27 +1,33 @@
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.10.12.mr5.1 rpass 2021.10.13.mr5.1
The Notetaker Update - Patch 1 The Notetaker Update - (Mega) Patch 1
This release fixes major bugs from previous releases and offers new packages of rpass. This release fixes major bugs from previous releases.
This includes a complete overhaul of the entry syncing system.
New features: New features:
**rpass is now packaged for Termux (basic Android support) - none!
**rpass is now packaged for Alpine Linux
**custom SSH keys are now properly supported
Changes: Changes:
- fixed an issue with copying notes (currently only copies first line, may be changed in the future) - fixed an issue with copying notes (currently only copies first line, will be changed in the future)
**fixed an issue with syncing that could cause data loss ** fixed an issue with syncing that could cause data loss
^ This issue has been in rpass (undiagnosed) since rsync support was first introduced - ^ This issue has been in rpass (undiagnosed) since rsync support was first introduced -
the solution involved dropping rsync and switching to sftp. the solution involved dropping rsync and switching to sftp.
This change should have no user-facing impact and is overall a net positive, This change should have no user-facing impact and is overall a net positive,
as rsync is no longer a dependency and the data loss bug is now fixed. as rsync is no longer a dependency and the data loss bug is now fixed.
Time to rename rpass! Time to rename rpass!
- rpass is validated to work with Python 3.10 - rpass is validated to work with Python 3.10 (no changes were needed)
Planned for next update (Patch mr5.2)
**package for Termux (basic Android support)
**package for Alpine Linux
**re-add support for custom directories and custom ssh keys
**adjust copy note feature to copy all lines
Planned for next update (The Beauty Update): Planned for next update (The Beauty Update):
@@ -36,6 +42,7 @@ Planned for next update (The Optimus Update):
- add an entry name masking system - add an entry name masking system
- modularize and shrink rpass code as much as possible - modularize and shrink rpass code as much as possible
- shrink rpass package size as much as possible - shrink rpass package size as much as possible
^ run question modules in file write commands to return values
Planned, no timeline: Planned, no timeline: