mirror of
https://github.com/rwinkhart/sshyp.git
synced 2026-09-02 23:27:17 -04:00
Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8403f4af98 | ||
|
|
4b24df0e97 | ||
|
|
ca007f55ac | ||
|
|
7afcfdb43d | ||
|
|
5178377827 | ||
|
|
ff9241368e | ||
|
|
6014de98dd | ||
|
|
6e7e42a69e | ||
|
|
0314bf36af | ||
|
|
93ac4ef824 | ||
|
|
65d10551f6 | ||
|
|
f6ddf2ad37 | ||
|
|
7f00570249 | ||
|
|
3d7f08e43e | ||
|
|
d82c9b5e02 | ||
|
|
9133a73553 | ||
|
|
ad039d6322 | ||
|
|
caa5fad0bc | ||
|
|
68ded52e8c | ||
|
|
85c59b302d | ||
|
|
954dd30361 | ||
|
|
65d1885311 | ||
|
|
5a7b45c3ac | ||
|
|
e5638255a8 | ||
|
|
2e32911470 | ||
|
|
4973d18034 | ||
|
|
6e13a6ebb3 | ||
|
|
dfbdc16079 | ||
|
|
3c4bf0115f | ||
|
|
762211bae0 | ||
|
|
d9adcac8ec |
@@ -42,7 +42,7 @@ cd sshyp
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
Packaging for other distributions coming soon.
|
||||
Pre-built packages exist for Arch, Debian, and Termux. These can be downloaded from the releases page.
|
||||
|
||||
# Building
|
||||
Since sshyp is written entirely in Python, it doesn't need to be compiled. It does, however, need to be packaged for installation.
|
||||
|
||||
+6
-13
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# sshync 2022.01.16.unreleased10
|
||||
# sshync 2022.01.17.unreleased13
|
||||
|
||||
# external modules
|
||||
|
||||
from os import system, remove, mkdir, walk
|
||||
from os import path, system, walk
|
||||
from os.path import getmtime, join, expanduser
|
||||
from sys import exit as s_exit
|
||||
from pathlib import Path
|
||||
@@ -14,16 +14,10 @@ from pathlib import Path
|
||||
|
||||
def get_titles_mods(_directory, _destination, _user_data):
|
||||
_title_list, _mod_list = [], []
|
||||
Path(path.expanduser('~/.config/sshync')).mkdir(0o700, parents=True, exist_ok=True) # create config directory
|
||||
# local fetching
|
||||
if _destination == 'l':
|
||||
if Path(expanduser('~/.config/sshync/database')).is_file():
|
||||
remove(expanduser('~/.config/sshync/database'))
|
||||
else:
|
||||
try:
|
||||
mkdir(expanduser('~/.config/sshync'), 0o700)
|
||||
except FileExistsError:
|
||||
pass
|
||||
system('touch ~/.config/sshync/database')
|
||||
open(expanduser('~/.config/sshync/database'), 'w').write('') # blanks out database file
|
||||
for _root, _directories, _files in walk(_directory):
|
||||
for _filename in _files:
|
||||
_title_list.append(join(_root.replace(_directory, '', 1), _filename))
|
||||
@@ -37,9 +31,8 @@ def get_titles_mods(_directory, _destination, _user_data):
|
||||
if _destination == 'r':
|
||||
system(f"ssh -i '{_user_data[5]}' -p {_user_data[2]} {_user_data[0]}@{_user_data[1]} \"python -c 'import sshync"
|
||||
f"; sshync.get_titles_mods(\"'\"{_user_data[4]}\"'\", \"'\"l\"'\", \"'\"{_user_data}\"'\")'\"")
|
||||
system(f"sftp -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
|
||||
f"'{expanduser(f'/home/{_user_data[0]}/.config/sshync/database')}' "
|
||||
f"'{expanduser('~/.config/sshync/database')}'")
|
||||
system(f"sftp -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
|
||||
f"'{expanduser(f'/home/{_user_data[0]}/.config/sshync/database')}' '{expanduser('~/.config/sshync/')}'")
|
||||
_titles, _sep, _mods = ' '.join(open(expanduser('~/.config/sshync/database')).readlines()).replace('\n', '')\
|
||||
.partition('^&*')
|
||||
_title_list, _mod_list = _titles.split(' ')[:-1], _mods.split(' ')[1:]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
# external modules
|
||||
|
||||
from os import environ, mkdir, remove, system, path
|
||||
from os import environ, listdir, path, remove, system
|
||||
from shutil import copy, move, rmtree
|
||||
from sys import argv, exit as s_exit
|
||||
from pathlib import Path
|
||||
@@ -19,28 +19,28 @@ def replace_line(file_name, line_num, text): # replaces text in a given line wi
|
||||
open(file_name, 'w').writelines(_lines)
|
||||
|
||||
|
||||
def shm_gen(): # generates random folder in /dev/shm for security and returns random names for the folder and temp file
|
||||
def shm_gen(): # generates a random temporary folder for security and returns random names for the folder and temp file
|
||||
_shm_folder_gen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
|
||||
for _ in range(random.randint(10, 30)))
|
||||
_shm_entry_gen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
|
||||
for _ in range(random.randint(10, 30)))
|
||||
mkdir(f"/dev/shm/{_shm_folder_gen}", 0o700)
|
||||
Path(tmp_dir + _shm_folder_gen).mkdir(0o700)
|
||||
return _shm_folder_gen, _shm_entry_gen
|
||||
|
||||
|
||||
def encrypt(_shm_folder, _shm_entry, _location):
|
||||
system(f"gpg -r {str(gpg_id)} -e '/dev/shm/{_shm_folder}/{_shm_entry}'")
|
||||
move(f"/dev/shm/{_shm_folder}/{_shm_entry}.gpg", f"{directory}{_location}.gpg")
|
||||
rmtree(f"/dev/shm/{_shm_folder}")
|
||||
system(f"gpg -r {str(gpg_id)} -e '{tmp_dir}{_shm_folder}/{_shm_entry}'")
|
||||
move(f"{tmp_dir}{_shm_folder}/{_shm_entry}.gpg", f"{directory}{_location}.gpg")
|
||||
rmtree(f"{tmp_dir}{_shm_folder}")
|
||||
|
||||
|
||||
def edit_note(_shm_folder, _shm_entry):
|
||||
lines = open(f"/dev/shm/{_shm_folder}/{_shm_entry}").readlines()
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'w').writelines(lines[0:3])
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}-n", 'w').writelines(lines[4:-2])
|
||||
system(f"nano /dev/shm/{_shm_folder}/{_shm_entry}-n")
|
||||
edit_notes = open(f"/dev/shm/{_shm_folder}/{_shm_entry}-n").read()
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'a').write('\n' + edit_notes + '\n\n')
|
||||
lines = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}").readlines()
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(lines[0:3])
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'w').writelines(lines[4:-2])
|
||||
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
|
||||
edit_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n").read()
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'a').write('\n' + edit_notes + '\n\n')
|
||||
|
||||
|
||||
# argument-specific functions
|
||||
@@ -48,20 +48,20 @@ def edit_note(_shm_folder, _shm_entry):
|
||||
|
||||
def tweak(): # runs configuration wizard
|
||||
# storage/config directory creation
|
||||
try:
|
||||
mkdir(path.expanduser('~/.password-pasture'), 0o700)
|
||||
except FileExistsError:
|
||||
pass
|
||||
try:
|
||||
mkdir(path.expanduser('~/.config/sshyp'), 0o700)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
Path(path.expanduser('~/.password-pasture')).mkdir(0o700, parents=True, exist_ok=True)
|
||||
Path(path.expanduser('~/.config/sshyp/devices')).mkdir(0o700, parents=True, exist_ok=True)
|
||||
if not Path(f"{path.expanduser('~/.config/sshyp/tmp')}").exists():
|
||||
if Path("/data/data/com.termux").exists():
|
||||
system(f"ln -s '/data/data/com.termux/files/usr/tmp' {path.expanduser('~/.config/sshyp/tmp')}")
|
||||
else:
|
||||
system(f"ln -s /dev/shm {path.expanduser('~/.config/sshyp/tmp')}")
|
||||
# device type configuration
|
||||
_device_type = input('\nIs this installation for a client or for a server? (C/s) ')
|
||||
if _device_type.lower() == 's':
|
||||
open(path.expanduser('~/.config/sshyp/sshyp-device'), 'w').write(_device_type)
|
||||
Path(path.expanduser('~/.config/sshyp/deleted')).mkdir(0o700, parents=True, exist_ok=True)
|
||||
copy('/usr/bin/sshync.py', path.expanduser('~/'))
|
||||
copy('/usr/bin/sshyp-shear.py', path.expanduser('~/shear.py'))
|
||||
print('\nMake sure the ssh service is running and properly configured.\n\nConfiguration complete!\n')
|
||||
s_exit()
|
||||
else:
|
||||
@@ -79,10 +79,7 @@ def tweak(): # runs configuration wizard
|
||||
open(path.expanduser('~/.config/sshyp/sshyp-gpg'), 'w').write(_gpg_id + '\n')
|
||||
|
||||
# lock file generation
|
||||
try:
|
||||
open(path.expanduser('~/.config/sshyp/lock'), 'x').write('')
|
||||
except FileExistsError:
|
||||
pass
|
||||
open(path.expanduser('~/.config/sshyp/lock'), 'w')
|
||||
system(f"gpg -r {str(_gpg_id)} -e {path.expanduser('~/.config/sshyp/lock')}")
|
||||
remove(f"{path.expanduser('~/.config/sshyp')}/lock")
|
||||
|
||||
@@ -108,6 +105,15 @@ def tweak(): # runs configuration wizard
|
||||
sshync.make_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'),
|
||||
path.expanduser('~/.password-pasture/'), f"/home/{_username_ssh}/.password-pasture/",
|
||||
path.expanduser('~/.ssh/sshyp'), _ip, _port, _username_ssh)
|
||||
|
||||
# device name configuration
|
||||
print('\nIMPORTANT: This name MUST be unique amongst your client devices. '
|
||||
'\nThis is used to keep track of which devices have up-to-date databases.\n')
|
||||
_client_device_name = str(input('What would you like to name this device? '))
|
||||
open(f"{path.expanduser('~/.config/sshyp/devices/')}{_client_device_name}", 'w')
|
||||
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {_port} {_username_ssh}@{_ip} "
|
||||
f"\"touch '/home/{_username_ssh}/.config/sshyp/devices/{_client_device_name}'\"")
|
||||
|
||||
print('\nConfiguration complete!\n')
|
||||
|
||||
|
||||
@@ -150,10 +156,10 @@ def print_info(): # prints help text based on argument
|
||||
elif argument == 'version' or argument == '-v':
|
||||
print('\n////////////////////////////////////////////////////////')
|
||||
print('/ /')
|
||||
print('/ sshyp Copyright (C) 2021 Randall Winkhart /')
|
||||
print('/ sshyp Copyright (C) 2021-2022 Randall Winkhart /')
|
||||
print('/ /')
|
||||
print('/ Version 2022.01.13.fr3.1 /')
|
||||
print('/ The Boxing Update /')
|
||||
print('/ Version 2022.02.16.fr4.1 /')
|
||||
print('/ The High-Tech Shears Update /')
|
||||
print('/ /')
|
||||
print('////////////////////////////////////////////////////////\n')
|
||||
elif argument == 'license':
|
||||
@@ -203,6 +209,28 @@ def read_shortcut(): # shortcut to quickly read an entry
|
||||
|
||||
def sync(): # calls sshync to sync changes to the user's server
|
||||
print('\nSyncing entries with the server device...\n')
|
||||
# check for deletions
|
||||
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"python -c 'import shear"
|
||||
f"; shear.check(\"'\"{client_device_name}\"'\")'\"")
|
||||
system(f"sftp -p -q -i '{path.expanduser('~/.ssh/sshyp')}' -P {port} {username_ssh}@{ip}:"
|
||||
f"'/home/{username_ssh}/.config/sshyp/deletion_database' {path.expanduser('~/.config/sshyp/')}")
|
||||
try:
|
||||
_deletion_database = open(path.expanduser('~/.config/sshyp/deletion_database')).readlines()
|
||||
except (FileNotFoundError, IndexError):
|
||||
print('\nThe deletion database does not exist or is corrupted.\n')
|
||||
_deletion_database = None
|
||||
s_exit()
|
||||
for _file in _deletion_database:
|
||||
if _file.endswith('/'):
|
||||
try:
|
||||
rmtree(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}")
|
||||
except FileNotFoundError:
|
||||
print('Folder does not exist locally.\n')
|
||||
else:
|
||||
try:
|
||||
remove(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}")
|
||||
except FileNotFoundError:
|
||||
print('File does not exist locally.\n')
|
||||
# set permissions before uploading
|
||||
system('find ' + directory + ' -type d -exec chmod -R 700 {} +')
|
||||
system('find ' + directory + ' -type f -exec chmod -R 600 {} +')
|
||||
@@ -216,9 +244,9 @@ def add_entry(): # adds a new entry
|
||||
_entry_name = _entry_name.replace('/', '', 1)
|
||||
if argument == 'add note' or argument == 'add -n':
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"nano /dev/shm/{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"/dev/shm/{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'w').writelines('\n\n\n\n' + _notes + '\n\n')
|
||||
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines('\n\n\n\n' + _notes + '\n\n')
|
||||
elif argument == 'add password' or argument == 'add -p':
|
||||
_username = str(input('Username: '))
|
||||
_password = str(input('Password: '))
|
||||
@@ -226,11 +254,11 @@ def add_entry(): # adds a new entry
|
||||
_add_note = input('Add a note to this entry? (y/N) ')
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
if _add_note.lower() == 'y':
|
||||
system(f"nano /dev/shm/{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"/dev/shm/{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
else:
|
||||
_notes = ''
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _password + '\n' + _url + '\n\n'
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _password + '\n' + _url + '\n\n'
|
||||
+ _notes + '\n\n')
|
||||
encrypt(_shm_folder, _shm_entry, _entry_name)
|
||||
system(f"gpg -d '{directory}{_entry_name}.gpg'")
|
||||
@@ -238,8 +266,9 @@ def add_entry(): # adds a new entry
|
||||
|
||||
def add_folder(): # creates a new folder
|
||||
_folder_name = str(input('Name of new folder: '))
|
||||
mkdir(directory + _folder_name, 0o700)
|
||||
system(f"ssh -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}{_folder_name}'\"")
|
||||
Path(directory + _folder_name).mkdir(0o700)
|
||||
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}"
|
||||
f"{_folder_name}'\"")
|
||||
|
||||
|
||||
def rename(): # renames an entry or folder TODO delete original from server to prevent re-downloading
|
||||
@@ -270,21 +299,21 @@ def edit(): # edits the contents of an entry
|
||||
if argument == 'edit username' or argument == 'edit -u':
|
||||
_detail = str(input('New Username: '))
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 0, _detail + '\n')
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 0, _detail + '\n')
|
||||
elif argument == 'edit password' or argument == 'edit -p':
|
||||
_detail = str(input('New Password: '))
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 1, _detail + '\n')
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 1, _detail + '\n')
|
||||
elif argument == 'edit url' or argument == 'edit -l':
|
||||
_detail = str(input('New URL: '))
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 2, _detail + '\n')
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 2, _detail + '\n')
|
||||
elif argument == 'edit note' or argument == 'edit -n':
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
edit_note(_shm_folder, _shm_entry)
|
||||
remove(f"{directory}{_entry_name}.gpg")
|
||||
encrypt(_shm_folder, _shm_entry, _entry_name)
|
||||
@@ -317,18 +346,18 @@ def gen(): # generates a password for a new or an existing entry
|
||||
_add_note = input('Add a note to this entry? (y/N) ')
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
if _add_note.lower() == 'y':
|
||||
system(f"nano /dev/shm/{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"/dev/shm/{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
|
||||
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
|
||||
else:
|
||||
_notes = ''
|
||||
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _pass_gen + '\n' + _url + '\n\n'
|
||||
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _pass_gen + '\n' + _url + '\n\n'
|
||||
+ _notes + '\n\n')
|
||||
encrypt(_shm_folder, _shm_entry, _entry_name)
|
||||
system(f"gpg -d '{directory}{_entry_name}.gpg'")
|
||||
else:
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 1, _pass_gen + '\n')
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
|
||||
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 1, _pass_gen + '\n')
|
||||
remove(f"{directory}{_entry_name}.gpg")
|
||||
encrypt(_shm_folder, _shm_entry, _entry_name)
|
||||
system(f"gpg -d '{directory}{_entry_name}.gpg'")
|
||||
@@ -342,9 +371,9 @@ def copy_data(): # copies a specified field of an entry to the clipboard
|
||||
print("\nThe file does not exist!\n")
|
||||
s_exit()
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_read_entry}.gpg'")
|
||||
_copy_line = open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'r').readlines()
|
||||
if Path("/data/data/com.termux").is_file(): # checks for Termux, Wayland, or X
|
||||
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_read_entry}.gpg'")
|
||||
_copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
|
||||
if Path("/data/data/com.termux").exists(): # checks for Termux, Wayland, or X
|
||||
if argument == 'copy username' or argument == 'copy -u':
|
||||
system('termux-clipboard-set ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
|
||||
elif argument == 'copy password' or argument == 'copy -p':
|
||||
@@ -371,25 +400,24 @@ def copy_data(): # copies a specified field of an entry to the clipboard
|
||||
system('echo -n ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
|
||||
elif argument == 'copy note' or argument == 'copy -n':
|
||||
system('echo -n ' + "'" + _copy_line[4].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
|
||||
rmtree(f"/dev/shm/{_shm_folder}")
|
||||
rmtree(f"{tmp_dir}{_shm_folder}")
|
||||
|
||||
|
||||
def remove_data(): # deletes an entry or folder from both the client and the server
|
||||
def remove_data(): # deletes an entry from the server and flags it for local deletion on sync
|
||||
print()
|
||||
system(f"cd {directory}; ls -1 *") # TODO replace with new list
|
||||
_entry_name = str(input('\nWhat would you like to delete? '))
|
||||
if _entry_name.startswith('/'):
|
||||
_entry_name = _entry_name.replace('/', '', 1)
|
||||
try:
|
||||
system(f"gpg -d --output /dev/shm/sshyp.lock {path.expanduser('~/.config/sshyp/lock.gpg')}")
|
||||
_unlock = open('/dev/shm/sshyp.lock', 'r').readlines()
|
||||
remove('/dev/shm/sshyp.lock')
|
||||
system(f"gpg -d --output {tmp_dir}sshyp.lock {path.expanduser('~/.config/sshyp/lock.gpg')}")
|
||||
_unlock = open(f"{tmp_dir}sshyp.lock", 'r').readlines()
|
||||
remove(f"{tmp_dir}sshyp.lock")
|
||||
except FileNotFoundError:
|
||||
print('\nAccess denied.\n')
|
||||
s_exit()
|
||||
if device_type == 'c':
|
||||
system(f"ssh -p {port} {username_ssh}@{ip} \"rm -rf '{directory_ssh}{_entry_name}.gpg'\"")
|
||||
remove(f"{directory}{_entry_name}.gpg")
|
||||
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"python -c 'import shear"
|
||||
f"; shear.delete(\"'\"{_entry_name}\"'\")'\"")
|
||||
|
||||
|
||||
# program start sequence
|
||||
@@ -406,6 +434,7 @@ argument = argument[:-1]
|
||||
# import saved userdata
|
||||
if argument != 'tweak':
|
||||
device_type = ''
|
||||
tmp_dir = path.expanduser('~/.config/sshyp/tmp/')
|
||||
try:
|
||||
device_type = open(path.expanduser('~/.config/sshyp/sshyp-device')).read().strip()
|
||||
if device_type == 'c':
|
||||
@@ -416,6 +445,7 @@ if argument != 'tweak':
|
||||
port = ssh_info[2].replace('\n', '')
|
||||
directory = str(ssh_info[3].replace('\n', ''))
|
||||
directory_ssh = '/home/' + username_ssh + '/.password-pasture/'
|
||||
client_device_name = listdir(path.expanduser('~/.config/sshyp/devices'))[0]
|
||||
except FileNotFoundError:
|
||||
if device_type.lower() != 's':
|
||||
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
|
||||
@@ -498,7 +528,7 @@ else:
|
||||
if argument != '' and argument != 'help' and argument != '--help' and argument != '-h' and argument != 'license' and \
|
||||
argument != 'add' and argument != 'sync' and argument != 'edit' and argument != 'copy username' and argument \
|
||||
!= 'copy -u' and argument != 'copy password' and argument != 'copy -p' and argument != 'copy url' and argument \
|
||||
!= 'copy -l' and argument != 'copy note' and argument != 'copy -n' and argument != 'copy' and argument != \
|
||||
'shear' and argument != '-rm' and argument != 'version' and argument != '-v' and error == 0 and \
|
||||
!= 'copy -l' and argument != 'copy note' and argument != 'copy -n' and argument != 'copy' and argument \
|
||||
!= 'version' and argument != '-v' and error == 0 and \
|
||||
argument.startswith('/') is False:
|
||||
sync()
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
# external modules
|
||||
|
||||
from os import remove, listdir
|
||||
from os.path import expanduser
|
||||
from shutil import rmtree
|
||||
|
||||
|
||||
# utility functions
|
||||
|
||||
def delete(_file_path):
|
||||
if _file_path.endswith('/'):
|
||||
try:
|
||||
rmtree(f"{expanduser('~/.password-pasture/')}{_file_path}")
|
||||
except FileNotFoundError:
|
||||
print('\nFolder does not exist remotely.')
|
||||
else:
|
||||
try:
|
||||
remove(f"{expanduser('~/.password-pasture/')}{_file_path}.gpg")
|
||||
except FileNotFoundError:
|
||||
print('\nFile does not exist remotely.\n')
|
||||
for _device_name in listdir(expanduser('~/.config/sshyp/devices')):
|
||||
open(f"{expanduser('~/.config/sshyp/deleted/')}{_file_path.replace('/', '@')}^&*{_device_name}", 'w')
|
||||
|
||||
|
||||
def check(_client_device_name):
|
||||
open(expanduser('~/.config/sshyp/deletion_database'), 'w').write('')
|
||||
for _file in listdir(expanduser('~/.config/sshyp/deleted')):
|
||||
_file_path = _file.replace('@', '/').split('^&*')[0]
|
||||
_device = _file.split('^&*')[1]
|
||||
if _device == _client_device_name:
|
||||
try:
|
||||
remove(f"{expanduser('~/.config/sshyp/deleted/')}{_file}")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
open(expanduser('~/.config/sshyp/deletion_database'), 'a').write(_file_path + '\n')
|
||||
+241
-1
@@ -1,8 +1,248 @@
|
||||
sshyp 2022.02.16.fr4.1
|
||||
|
||||
The High-Tech Shears Update - Patch 1
|
||||
|
||||
This release addresses a bug with local folder deletion.
|
||||
|
||||
Note: Upgrading to releases in the fr4 series requires the configuration ("sshyp tweak") to be re-done, as a device name now must be set (for multi-client deletion).
|
||||
|
||||
Changes:
|
||||
|
||||
- fixed an issue where folders could not be deleted locally
|
||||
- optimized deletion flags
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr5, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
^ this includes the new file list and thematic text art
|
||||
|
||||
sshync:
|
||||
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
|
||||
^ more details will be available in the sshync repo, once it is created
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
** allow for copying entire notes (not just first line)
|
||||
** ability to pass entries as arguments for more functions
|
||||
|
||||
&&
|
||||
|
||||
Backlog:
|
||||
|
||||
** create separate gui frontend targetting mobile and desktop Linux
|
||||
** auto-completion on tab (currently unsure of best way to make this work)
|
||||
|
||||
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
||||
|
||||
sshyp 2022.02.16.fr4
|
||||
|
||||
The High-Tech Shears Update
|
||||
|
||||
This release adds in a major feature: multi-client deletion (details below)
|
||||
|
||||
Note: This release requires the configuration ("sshyp tweak") to be re-done, as a device name now must be set (for multi-client deletion).
|
||||
|
||||
Features:
|
||||
|
||||
- added multi-client deletion
|
||||
^ this means that when an entry is deleted from one client (and thus the server), if another client that has a copy of the deleted entry tries to sync, instead of re-uploading the deleted entry, it will now also have its entry deleted.
|
||||
^ the current implementation requires a new Python script in addition to sshyp and sshync
|
||||
|
||||
Changes:
|
||||
|
||||
- fixed an issue where sshyp would use the wrong SSH key when trying to delete entries from or create folders on the server
|
||||
^ this is a fix that was recently applied to sshync - turns out I made the same mistake in sshyp
|
||||
- deleting folders should now work properly with "sshyp shear" if the directory is entered with a following "/"
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr5, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
^ this includes the new file list and thematic text art
|
||||
|
||||
sshync:
|
||||
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
|
||||
^ more details will be available in the sshync repo, once it is created
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
** allow for copying entire notes (not just first line)
|
||||
** ability to pass entries as arguments for more functions
|
||||
|
||||
&&
|
||||
|
||||
Backlog:
|
||||
|
||||
** create separate gui frontend targetting mobile and desktop Linux
|
||||
** auto-completion on tab (currently unsure of best way to make this work)
|
||||
|
||||
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
||||
|
||||
sshyp 2022.01.26.fr3.4
|
||||
|
||||
The Boxing Update - Patch 4
|
||||
|
||||
This release is a hotfix for 2022.01.17.fr3.3. It fixes a major bug with sshync.
|
||||
|
||||
Changes:
|
||||
|
||||
- sshync now correctly uses the auto-generated SSH key in all operations
|
||||
- an exception has been added for attempting to delete/shear a file that does not exist
|
||||
- the manpage has been updated and now includes setup instructions
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr4, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
^ this includes the new file list and thematic text art
|
||||
|
||||
sshync:
|
||||
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
|
||||
^ more details will be available in the sshync repo, once it is created
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** allow for multi-client deletion... somehow (in sshync)
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
** allow for copying entire notes (not just first line)
|
||||
** ability to pass entries as arguments for more functions
|
||||
|
||||
&&
|
||||
|
||||
Backlog:
|
||||
|
||||
** create separate gui frontend targetting mobile and desktop Linux
|
||||
** auto-completion on tab (currently unsure of best way to make this work)
|
||||
|
||||
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
||||
|
||||
sshyp 2022.01.17.fr3.3
|
||||
|
||||
The Boxing Update - Patch 3
|
||||
|
||||
This release is a hotfix for 2022.01.16.fr3.2. It fixes major bugs, especially with Termux.
|
||||
|
||||
Changes:
|
||||
|
||||
- the temporary directory for Termux is now sym-linked with its full path (no longer dangling)
|
||||
- the copy function can now properly detect if Termux is being used
|
||||
- ~/.config is created, if it does not already exist
|
||||
- "sshyp shear" now functions again, as a bug with the lock file has been fixed
|
||||
- sshync -should- now properly detect the database file on all platforms (was broken on Termux)
|
||||
- total lines of code have been slightly reduced with various small optimizations
|
||||
|
||||
Additions planned for minor releases:
|
||||
|
||||
** updated the manpage with more information regarding how sshyp works and how to set it up
|
||||
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
|
||||
** reduced total lines of code with small optimizations
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr4, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
^ this includes the new file list and thematic text art
|
||||
|
||||
sshync:
|
||||
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
|
||||
^ more details will be available in the sshync repo, once it is created
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** allow for multi-client deletion... somehow (in sshync)
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
** allow for copying entire notes (not just first line)
|
||||
** ability to pass entries as arguments for more functions
|
||||
|
||||
&&
|
||||
|
||||
Backlog:
|
||||
|
||||
** create separate gui frontend targetting mobile and desktop Linux
|
||||
** auto-completion on tab (currently unsure of best way to make this work)
|
||||
|
||||
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
||||
|
||||
sshyp 2022.01.16.fr3.2
|
||||
|
||||
The Boxing Update - Patch 2
|
||||
|
||||
This release is a hotfix for 2022.01.16.fr3.1. It fixes major bugs, including one massively impacting Termux.
|
||||
|
||||
Changes:
|
||||
|
||||
- sshyp now uses a symlink to the temporary storage directory, allowing for easy implementation of different temporary directories on different platforms
|
||||
^ the first usage of this is enabling the use of temporary storage on Termux
|
||||
- sshync now properly auto-generates its config directory
|
||||
|
||||
Additions planned for minor releases:
|
||||
|
||||
** updated the manpage with more information regarding how sshyp works and how to set it up
|
||||
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
|
||||
** reduced total lines of code with small optimizations
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr4, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
^ this includes the new file list and thematic text art
|
||||
|
||||
sshync:
|
||||
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
|
||||
^ more details will be available in the sshync repo, once it is created
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** allow for multi-client deletion... somehow (in sshync)
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
** allow for copying entire notes (not just first line)
|
||||
** ability to pass entries as arguments for more functions
|
||||
|
||||
&&
|
||||
|
||||
Backlog:
|
||||
|
||||
** create separate gui frontend targetting mobile and desktop Linux
|
||||
** auto-completion on tab (currently unsure of best way to make this work)
|
||||
|
||||
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
|
||||
|
||||
sshyp 2022.01.16.fr3.1
|
||||
|
||||
The Boxing Update
|
||||
The Boxing Update - Patch 1
|
||||
|
||||
This release is a hotfix for 2022.01.13.fr3. It fixes sshync/syncing support after the changes in the last release.
|
||||
|
||||
|
||||
+34
-4
@@ -1,4 +1,4 @@
|
||||
.TH sshyp 1 "10 January 2022" "2021.12.01.fr2.3" "sshyp man page"
|
||||
.TH sshyp 1 "16 February 2022" "2022.02.16.fr4.1" "sshyp man page"
|
||||
.SH NAME
|
||||
sshyp \- A very simple self-hosted, synchronized password manager. Alternative to GNU pass.
|
||||
.SH SYNOPSIS
|
||||
@@ -34,6 +34,10 @@ Creating a note-only entry:
|
||||
Syncing entries with the server:
|
||||
sshyp sync
|
||||
|
||||
Removing an existing folder saved as ~/.password-pasture/social:
|
||||
sshyp shear
|
||||
*when prompted for what to delete, since you are deleting a folder, be sure to enter your choice with a following "/", e.g. "social/" or "/social/"
|
||||
|
||||
.SH OPTIONS
|
||||
In order to quickly read an existing entry, just run "sshyp </entry name>".
|
||||
|
||||
@@ -66,9 +70,35 @@ copy:
|
||||
note/-n copy the note of an entry to your clipboard
|
||||
gen:
|
||||
update/-u generate a password for an existing entry
|
||||
.SH BUGS
|
||||
This is more of a current limitation than a bug, but:
|
||||
.SH LIMITATIONS
|
||||
The following limitations will be corrected in future updates:
|
||||
|
||||
Currently, if multiple clients are connected to a single server and a client deletes an entry, the entry is correctly deleted from the client and the server, but since the entry still exists on the other client, the next time it syncs the file will be re-uploaded. This will be fixed in an upcoming release of the syncing backend, sshync.
|
||||
Currently, folders (for sorting) are not replicated onto new clients (they need to be manually created before syncing).
|
||||
|
||||
Currently, the entry list displays each entry with the file extension ".gpg" visible (which you do not type when reading, modifying, or creating an entry). This will be corrected when the new entry list is added.
|
||||
|
||||
The following characters/character sequences are not supported in entry/folder titles:
|
||||
@ ^&*
|
||||
.SH SETUP
|
||||
sshyp operates on a client-server model, and thus requires you to have access to your own server (whether it be a physical home server or a cloud rental) with remote access via SSH.
|
||||
|
||||
The sshyp package includes modes for operating on both client and server devices, so only one package is necessary.
|
||||
|
||||
Server setup:
|
||||
Configure an openssh server (if sshyp was installed from the Debian package, the ssh server was not installed as a dependency and needs to be installed manually)
|
||||
Allow remote access to the SSH server w/public key authentication (disabling password-only authentication recommended)
|
||||
Install sshyp
|
||||
Run "sshyp tweak" and set the device type as server
|
||||
Done!
|
||||
|
||||
Client setup:
|
||||
Install sshyp
|
||||
Run "sshyp tweak" and follow the prompts
|
||||
Copy the generated public SSH key to the server using preferred method (manually adding to authorized_keys, ssh-copy-id, etc.)
|
||||
**this step will be automated in the future: if an entry library already exists on the server, make sure to manually recreate any folders that exist on the server in the ~/.password-pasture directory
|
||||
If you already have entries on the server, sync them using "sshyp sync"
|
||||
Done!
|
||||
|
||||
Please note that the server setup intentionally does not allow the reading of entries (it does not allow adding a gpg decryption key). For security purposes, only clients can read entries.
|
||||
.SH AUTHOR
|
||||
Randall Winkhart (https://github.com/rwinkhart)
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
sshyp 2022.01.16.fr3.1
|
||||
sshyp 2022.02.16.fr4.1
|
||||
|
||||
The Boxing Update
|
||||
The High-Tech Shears Update - Patch 1
|
||||
|
||||
This release is a hotfix for 2022.01.13.fr3. It fixes sshync/syncing support after the changes in the last release.
|
||||
This release addresses a bug with local folder deletion.
|
||||
|
||||
Note: Upgrading to releases in the fr4 series requires the configuration ("sshyp tweak") to be re-done, as a device name now must be set (for multi-client deletion).
|
||||
|
||||
Changes:
|
||||
|
||||
- sshync has been updated to work with the new config directory
|
||||
- sshync now uses its own directory to store the database file
|
||||
^ this is preperation for separating sshync into its own package
|
||||
- expanduser lines in sshyp have been simplified (no user-facing impact)
|
||||
|
||||
Additions planned for minor releases:
|
||||
|
||||
** updated the manpage with more information regarding how sshyp works and how to set it up
|
||||
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
|
||||
** reduced total lines of code with small optimizations
|
||||
- fixed an issue where folders could not be deleted locally
|
||||
- optimized deletion flags
|
||||
|
||||
&&
|
||||
|
||||
Planned for next major update (fr4, The sshyp Doing a Split Update):
|
||||
Planned for next major update (fr5, The sshyp Doing a Split Update):
|
||||
|
||||
sshyp:
|
||||
** sshyp has recieved a major visual overhaul
|
||||
@@ -31,9 +25,8 @@ sshync:
|
||||
|
||||
&&
|
||||
|
||||
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
|
||||
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
|
||||
|
||||
** allow for multi-client deletion... somehow (in sshync)
|
||||
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
|
||||
** imporove password generator to guarantee more secure results
|
||||
** enforce permissions on the server-side
|
||||
|
||||
Reference in New Issue
Block a user