Compare commits

..
Author SHA1 Message Date
RandyTheSilly c64a4fedb1 Updated PKGBUILD for release 2021-12-01 22:10:34 -05:00
RandyTheSilly 81263ac375 Fixed syncing support 2021-12-01 22:07:25 -05:00
RandyTheSilly ec079f996a Updated version number 2021-12-01 22:05:51 -05:00
RandyTheSilly edad359330 Updated changelog 2021-12-01 22:04:50 -05:00
RandyTheSilly 649c405d49 Updated changelog 2021-12-01 21:34:07 -05:00
RandyTheSilly 0f382af9c8 Updated changelog 2021-12-01 21:25:59 -05:00
RandyTheSilly b7e129e0dd Fixed spacing in server config 2021-12-01 21:16:13 -05:00
RandyTheSilly dc63176263 Updated PKGBUILD for release 2021-12-01 21:00:47 -05:00
RandyTheSilly 5e5e6ea905 Updated changelog 2021-12-01 20:58:57 -05:00
RandyTheSilly 6b4eeabfc0 Folders and now created natively with Python 2021-12-01 20:55:34 -05:00
RandyTheSilly 2600eae464 Fixed checking version triggering synchronization 2021-12-01 20:26:39 -05:00
RandyTheSilly 3152201ead Fixed broken tweak argument on new installs 2021-12-01 20:14:58 -05:00
RandyTheSilly 2b31d00f32 Updated PKGBUILD for release 2021-12-01 19:46:51 -05:00
RandyTheSilly 61c7543cfa Updated README.md 2021-12-01 19:45:32 -05:00
RandyTheSilly 246c84ff1f Updated PKGBUILD for release 2021-12-01 19:42:21 -05:00
RandyTheSilly 23ad878a71 Updated changelog 2021-12-01 19:38:52 -05:00
RandyTheSilly 8ff7705577 More prep for release 2021-12-01 19:35:39 -05:00
RandyTheSilly b0213eca8e Full re-write of sshync 2021-12-01 19:19:06 -05:00
RandyTheSilly 9efeca546a Prep for release 2021-12-01 19:17:59 -05:00
RandyTheSilly b21a60ca88 Improved remove (shear) functionality 2021-11-18 12:39:29 -05:00
RandyTheSilly 9095cf9e74 Revert accidental interpreter change, update release estimate 2021-11-18 12:32:18 -05:00
RandyTheSilly f15b90d32a Fixed nested folders, replaced bloated folder detection code 2021-11-18 12:27:10 -05:00
RandyTheSilly 29cc47c8d9 Updated documentation 2021-11-16 15:13:24 -05:00
RandyTheSilly f7ee816c62 Replaced exit() with sys.exit() 2021-11-16 11:26:07 -05:00
RandyTheSilly aee22ba779 New folders are now also created on the remote server 2021-11-15 19:48:08 -05:00
RandyTheSilly 83ef92da63 Removed useless import statement 2021-11-15 19:30:14 -05:00
RandyTheSilly 27eab28fc9 Added f-string, fixed misc. bugs 2021-11-15 19:25:27 -05:00
RandyTheSilly 8a4b5d72d1 Merge branch 'main' of https://github.com/rwinkhart/sshyp 2021-11-11 22:34:23 -05:00
RandyTheSilly 801177d386 Full re-write of sshyp! 2021-11-11 22:33:14 -05:00
rwinkhart b8611ab9fd Update README.md 2021-11-05 14:59:20 +00:00
RandyTheSilly 9a2986ab21 Final prep for first sshyp release 2021-11-05 10:56:17 -04:00
RandyTheSilly a81f892c4c Prep for first release of sshyp 2021-11-05 10:04:55 -04:00
RandyTheSilly aa9dd11793 Fixed bugs with config and syncing w/o files 2021-11-04 23:02:59 -04:00
RandyTheSilly c1da61bee5 Allow sshync to work w/sshyp 2021-11-04 20:23:09 -04:00
RandyTheSilly c34898b325 Ported rpass to sshyp 2021-11-01 20:31:11 -04:00
RandyTheSilly 621db67d34 Rebranding step 6 2021-11-01 19:02:12 -04:00
RandyTheSilly 3045a97f4c Rebranding step 5 2021-11-01 18:05:22 -04:00
RandyTheSilly 844c751957 Added link to changelog 2021-11-01 18:02:32 -04:00
RandyTheSilly be9d621c62 Rebranding step 4 2021-11-01 17:59:32 -04:00
rwinkhart 850aa60ba5 Delete changelog-sshyp 2021-11-01 21:52:45 +00:00
rwinkhart da4e229208 Delete rpass 2021-11-01 21:52:22 +00:00
9 changed files with 785 additions and 1820 deletions
+10 -11
View File
@@ -1,23 +1,22 @@
# Maintainer: Randall Winkhart <idgr at tutanota dot com>
# The source package is no longer recieving updates past this version.
pkgname=rpass
pkgver=2021.11.01.mr5.1
pkgname=sshyp
pkgver=2021.12.01.fr2.2
pkgrel=1
pkgdesc='An rsync-based password manager and alternative to GNU pass'
pkgdesc='A self-hosted, synchronized password manager'
url='https://github.com/rwinkhart/sshyp'
arch=('x86_64' 'aarch64')
license=('GPL3')
depends=( python gnupg openssh rsync nano xclip wl-clipboard)
depends=( python gnupg openssh nano xclip wl-clipboard)
source_x86_64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.11.01.mr5.1/rpass-2021.11.01.mr5.1.tar.xz')
source_aarch64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.11.01.mr5.1/rpass-2021.11.01.mr5.1.tar.xz')
sha512sums_x86_64=('bf0c958721de1a13ca814d91bf74cbaaebe458198cba14b96b95fb1eeb72a1b901c8d3d00ea4c18ddff0d10d9ef6504a17a4caa345917412108df4787add61fd')
sha512sums_aarch64=('bf0c958721de1a13ca814d91bf74cbaaebe458198cba14b96b95fb1eeb72a1b901c8d3d00ea4c18ddff0d10d9ef6504a17a4caa345917412108df4787add61fd')
source_x86_64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.12.01.fr2.2/sshyp-2021.12.01.fr2.2.tar.xz')
source_aarch64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.12.01.fr2.2/sshyp-2021.12.01.fr2.2.tar.xz')
sha512sums_x86_64=('470f7b4fd2bb0cc34a98e8ab5506ae4bc82e311616e2a81ee4fc559dd9e2c2e46a05517a49ba4d4fe108f341f92250bd1d63acca134d277b37d2475e03713adf')
sha512sums_aarch64=('470f7b4fd2bb0cc34a98e8ab5506ae4bc82e311616e2a81ee4fc559dd9e2c2e46a05517a49ba4d4fe108f341f92250bd1d63acca134d277b37d2475e03713adf')
package() {
tar xf rpass-"$pkgver".tar.xz -C "${pkgdir}"
chown -R "$USER" ${pkgdir}/var/lib/rpass
tar xf sshyp-"$pkgver".tar.xz -C "${pkgdir}"
chown -R "$USER" ${pkgdir}/var/lib/sshyp
}
+42 -7
View File
@@ -1,13 +1,40 @@
# sshyp
A very simple self-hosted, synchronized password manager. Alternative to GNU pass.
"sshyp" stands for "sshync passwords", or "ssh sync passwords".
"sshync" is the custom syncing backend (based on sftp) used by "sshyp".
# WARNING
It is your responsibility to assess the security and stability of "sshyp" before using it and ensure it meets your needs.
I am not responsible for any data loss or breaches of your information resulting from the use of "sshyp".
"sshyp" is a new project that is constantly being updated, and though safety and security are priorities, they cannot be guaranteed.
# Mission Statement
sshyp aims to make it as simple as possible to manage passwords and notes via CLI across multiple devices in a self-hosted fashion.
sshyp aims to make it as simple as possible to manage passwords and notes via CLI across multiple devices in a secure, self-hosted fashion.
What sshyp can do:
- securely manage a collection of encrypted passwords and notes via CLI
- generate new, secure passwords to the user's choice in length and complexity
- securely sync said passwords and notes seamlessly between multiple POSIX compliant Unix devices
What sshyp will do:
- everything it already does, but also in a GUI for Linux/Android
- have a distinct retro theme
- receive many usability enhancements
What sshyp definitely won't do:
- 2FA/MFA (for security purposes, this should not be handled by your password manager)
- Windows support (I don't use Windows and I have no interest in developing for it)
# Installation
Arch Linux (x86_64, aarch64)
sshyp releases are available in the Arch User Repository as 'sshyp'.
Note: currently unavailable in the AUR (the older version, "rpass", will remain available until sshyp is stable)
sshyp releases will be available in the Arch User Repository as 'sshyp'.
Install with your preferred AUR helper or use:
@@ -23,11 +50,11 @@ Packaging for other distributions coming soon.
Upon initial installation, be sure to run:
```
sshyp config
sshyp tweak
```
This command will allow you to configure the settings necessary for rpass to function.
As of right now, rpass is rapidly changing, and as such, it is a good idea to run "rpass config" after each update.
This command will allow you to configure the settings necessary for sshyp to function.
As of right now, sshyp is rapidly changing, and as such, it is a good idea to run "sshyp tweak" after each update.
All available options can be found with:
@@ -38,7 +65,6 @@ sshyp --help
# Roadmap
Short-term Goals:
- re-write bad, leftover "rpass" code
- create new file list w/color and w/o file extensions
- create a man page
- overhaul argument system
@@ -47,9 +73,18 @@ Short-term Goals:
Medium-term Goals:
- create minimal GUI apps (Linux x86_64, Linux aarch64, Android aarch64)
- create minimal GUI apps (Linux x86_64, Linux aarch64)
- auto-completion on tab for CLI version
Long-term Goals:
- seize the thrones, shear the humans
# Known Issues
Broken Features in Latest Release:
- the 'gen' function uses the older notetaking system
Broken Features in Source:
- the 'gen' function uses the older notetaking system
-834
View File
@@ -1,834 +0,0 @@
#!/usr/bin/python3
# internal modules
from os import system
from os import remove
from os import environ
from shutil import move
from shutil import rmtree
from sys import argv
from re import search
from re import escape
import random
import string
# custom modules
def clear():
print('\n' * 100)
def term(cmd):
_ = system(cmd)
def string_found(string1, string2):
if search(r"\b" + escape(string1) + r"\b", string2):
return True
return False
def replace_line(file_name, line_num, text):
xlines = open(file_name, 'r').readlines()
xlines[line_num] = text
open(file_name, 'w').writelines(xlines)
def edit_note():
lines = open('/dev/shm/' + shmfolder + '/' + shmentry).readlines()
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(lines[0:3])
open('/dev/shm/' + shmfolder + '/' + shmentry + '-n', 'w').writelines(lines[4:-2])
term('nano /dev/shm/' + shmfolder + '/' + shmentry + '-n')
edit_notes = open('/dev/shm/' + shmfolder + '/' + shmentry + '-n').read()
open('/dev/shm/' + shmfolder + '/' + shmentry, 'a').write('\n' + edit_notes + '\n\n')
def shmgen():
shmfoldergen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentrygen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfoldergen)
return shmfoldergen, shmentrygen
def encrypt():
term('gpg -r ' + str(gpgid) + ' -e ' + "'" + '/dev/shm/' + shmfolder + '/' + shmentry + "'")
move('/dev/shm/' + shmfolder + '/' + shmentry + '.gpg', directory + entryname.replace('/', '', 1) + '.gpg')
rmtree('/dev/shm/' + shmfolder)
def encryptfolder():
term('gpg -r ' + str(gpgid) + ' -e ' + "'" + '/dev/shm/' + shmfolder + '/' + shmentry + "'")
move('/dev/shm/' + shmfolder + '/' + shmentry + '.gpg', directory + folder + '/' + folderentry + '.gpg')
rmtree('/dev/shm/' + shmfolder)
# argument - filter the argument to usable text
argument = str(argv).replace('[', '', 1).replace(']', '', 1).replace(',', '').replace("'", '') \
.replace(' ', '', 1).replace('/usr/bin/', '', 1).replace('rpass', '', 1)
# help
if argument == 'help' or argument == '--help' or argument == '-h':
print('\nrpass Copyright (C) 2021 Randall Winkhart')
print("This program comes with ABSOLUTELY NO WARRANTY; for details type `rpass show w'.\nThis is free software, "
"and you are welcome to redistribute it under certain conditions; type `rpass show c' for details.")
print('\nUSAGE: rpass [/<entry name>] [OPTION] [FLAG]\n')
print('Options: ')
print('help/--help/-h bring up this menu')
print('version/-v display rpass version info')
print('config configure rpass')
print('add add an entry')
print('gen generate a new password')
print('edit edit an existing entry')
print('copy copy details of an entry to your clipboard')
print('remove/-rm delete an existing entry')
print('sync/-s manually sync the entry directory via rsync\n')
print('Flags:')
print('add:')
print(' password/-p add a password entry')
print(' note/-n add a note entry')
print(' folder/-f add a new folder for entries')
print('edit:')
print(' rename/relocate/-r rename or relocate an entry')
print(' username/-u change the username of an entry')
print(' password/-p change the password of an entry')
print(' note/-n change the note attached to an entry')
print(' url/-l change the url attached to an entry')
print('copy:')
print(' username/-u copy the username of an entry to your clipboard')
print(' password/-p copy the password of an entry to your clipboard')
print(' url/-l copy the URL of an entry to your clipboard')
print(' note/-n copy the note of an entry to your clipboard')
print('gen:')
print(' update/-u generate a password for an existing entry\n')
print("Tip: You can quickly read an entry with 'rpass /<entry name>'!")
print("When specifying entry names, do not include the file extension! '.gpg' is assumed!\n")
# version info
if argument == 'version' or argument == '-v':
print('\n////////////////////////////////////////////////////////')
print('/ /')
print('/ rpass Copyright (C) 2021 Randall Winkhart /')
print('/ /')
print('/ Version 2021.11.01.mr5.1 /')
print('/ The Notetaker Update /')
print('/ /')
print('////////////////////////////////////////////////////////\n')
# licensing info
if argument == 'show w':
clear()
print('This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;')
print('without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.')
print('See the GNU General Public License for more details.')
print('\nhttps://opensource.org/licenses/GPL-3.0\n')
if argument == 'show c':
clear()
print('This program is free software: you can redistribute it and/or modify it under the terms of the GNU General')
print('Public License as published by the Free Software Foundation, either version 3 of the License,')
print('or (at your option) any later version.\n')
# config
if argument == 'config':
try:
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) '))
if devicetype == 's' or devicetype == 'S':
open("/var/lib/rpass/rpass-ssh", 'w').write('\n\n\n\n' + devicetype)
print('\nMake sure the ssh service is running and properly configured.\n')
print('Configuration complete!\n')
else:
gpgid = ''
print()
gpgpresent = str(input(
'rpass requires the use of a unique gpg key. Do you already have one you are willing to use? (y/N) '))
if gpgpresent == 'y' or gpgpresent == 'Y':
print()
gpgid = str(input('Please input the ID of your gpg key: '))
open("/var/lib/rpass/rpass-gpg", 'w').write(gpgid + '\n')
else:
print()
gpggen = str(
input('Would you like to generate one now? Note that if you choose not to do this, you will have '
'to re-run "rpass config" to specify a gpg key when you acquire one (Y/n) '))
if gpggen == 'n' or gpggen == 'N':
exit()
else:
term('gpg --full-generate-key')
print()
gpgid = str(input('Please input the ID of your gpg key: '))
open("/var/lib/rpass/rpass-gpg", 'w').write(gpgid + '\n')
try:
open('/var/lib/rpass/lock', 'x').write('locked')
except FileExistsError:
pass
term('gpg -r ' + str(gpgid) + ' -e ' + '/var/lib/rpass/lock')
remove('/var/lib/rpass/lock')
if devicetype == 'o' or devicetype == 'O':
open("/var/lib/rpass/rpass-ssh", 'w').write('\n\n\n\n' + devicetype)
print('\nConfiguration complete!\n')
elif devicetype != 's' and devicetype != 'S':
devicetype = 'c'
print('\nMake sure the ssh service on the remote server is running and properly configured.\n')
sshgen = str(input('rsync support requires a unique ssh key. Would you like to have this '
'automatically generated? (Y/n) '))
if sshgen != 'n' and sshgen != 'N':
term('ssh-keygen -t ed25519 -f ~/.ssh/rpass')
print('\nExample input: 10.10.10.10:9999\n')
ip_port = str(input('What is the IP and ssh port of the remote server? '))
print()
ip, sep, port = ip_port.partition(':')
usernamessh = str(input('What is the username of the remote server? '))
print('\nDefault directory: ' + '/home/' + usernamessh + '/.rpass-store/\n')
directoryssh = str(input('Is the remote server using the default password directory? (Y/n) '))
if directoryssh == 'n' or directoryssh == 'N':
print('\nFormat: /this/path/ends/with/a/slash/\n')
directoryssh = str(input('What directory is the server using?: '))
else:
directoryssh = ('/home/' + usernamessh + '/.rpass-store/')
open("/var/lib/rpass/rpass-ssh", 'w').write(usernamessh + '\n' + ip + '\n' + port + '\n' + directoryssh +
'\n' + devicetype)
print('\nConfiguration complete!\n')
except KeyboardInterrupt:
print('\n\nConfiguration cancelled.\n')
exit()
# startup help
if argument == '':
clear()
print("Use 'help', '--help', or '-h' to see a list of commands.\n")
print('rpass is currently early software with very little polish\n')
# import userdata
try:
sshinfo = open("/var/lib/rpass/rpass-ssh").readlines()
usernamessh = sshinfo[0].replace('\n', '')
ip = sshinfo[1].replace('\n', '')
port = sshinfo[2].replace('\n', '')
directoryssh = sshinfo[3].replace('\n', '')
devicetype = 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)
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print("Not all necessary configuration files are present. Please run 'rpass config'!")
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
exit()
# no argument
if argument == '':
try:
print()
term('cd ' + directory + '; ls -1 *')
print()
readentry = str(input('Entry to read: '))
clear()
term('gpg -d ' + directory + "'" + readentry.replace('/', '', 1) + "'" + '.gpg')
print()
except KeyboardInterrupt:
print('\n\nSelection cancelled.\n')
exit()
# read shortcut
if argument.startswith('/'):
if argument.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = argument.replace('/', '', 1).partition('/')
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d ' + directory + "'" + argument.replace('/', '', 1) + '.gpg' + "'")
# add
if argument == 'add':
print('\nUSAGE: rpass add [FLAG]')
print('Flags:')
print('add:')
print(' password/-p add a password entry')
print(' note/-n add a note entry')
print(' folder/-f add a new folder for entries\n')
if argument == 'add note' or argument == 'add -n':
try:
clear()
entryname = str(input('Name of note: '))
except KeyboardInterrupt:
entryname, notes = (0, 0)
print('\n\nEntry add cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
term('nano /dev/shm/' + shmfolder + '/' + shmentry + '-n')
notes = open('/dev/shm/' + shmfolder + '/' + shmentry + '-n', 'r').read()
try:
if entryname.startswith('/'): # check if user input contains slashes
if entryname.replace('/', '', 1).__contains__('/'): # create folder and entry if there are two slashes
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines('\n\n\n\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else: # create entry if there is only one slash
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines('\n\n\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else: # create entry if there are no slashes
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines('\n\n\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The folder you requested to access does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'add password' or argument == 'add -p':
try:
clear()
entryname = str(input('Name of service: '))
username = str(input('Username: '))
password = str(input('Password: '))
url = str(input('URL: '))
except KeyboardInterrupt:
entryname, username, password, url, notes = (0, 0, 0, 0, 0)
print('\n\nEntry add cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
add_note = input('Add a note to this entry? (y/N) ')
if add_note == 'y' or add_note == 'Y':
term('nano /dev/shm/' + shmfolder + '/' + shmentry + '-n')
notes = open('/dev/shm/' + shmfolder + '/' + shmentry + '-n', 'r').read()
else:
notes = ''
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + password + '\n' + url
+ '\n\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + password + '\n' + url
+ '\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + password + '\n' + url
+ '\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The folder you requested to access does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'add folder' or argument == 'add -f':
newfolder = str(input('Name of new folder: '))
term('mkdir ' + "'" + directory + newfolder + "'")
# edit
if argument == 'edit':
print('\nUSAGE: rpass edit [FLAG]')
print('Flags:')
print('edit:')
print(' rename/relocate/-r rename or relocate an entry')
print(' username/-u change the username of an entry')
print(' password/-p change the password of an entry')
print(' url/-l change the url attached to an entry')
print(' note/-n change the note attached to an entry\n')
if argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit -r':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
newname = str(input('New Name: '))
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
move(directory + folder + '/' + folderentry + '.gpg', directory + '/' + newname + '.gpg')
else:
move(directory + entryname.replace('/', '', 1) + '.gpg',
directory + newname.replace('/', '', 1) + '.gpg')
else:
move(directory + entryname + '.gpg', directory + newname + '.gpg')
except KeyboardInterrupt:
print('\n\nEdit cancelled.\n')
exit()
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
exit()
if argument == 'edit username' or argument == 'edit -u':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
username = str(input('New Username: '))
except KeyboardInterrupt:
entryname, username = (0, 0)
print('\n\nEdit cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 0, username + '\n')
remove(directory + folder + '/' + folderentry + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 0, username + '\n')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 0, username + '\n')
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'edit password' or argument == 'edit -p':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
password = str(input('New Password: '))
except KeyboardInterrupt:
entryname, password = (0, 0)
print('\n\nEdit cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, password + '\n')
remove(directory + folder + '/' + folderentry + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, password + '\n')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, password + '\n')
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'edit url' or argument == 'edit -l':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
url = str(input('New URL: '))
except KeyboardInterrupt:
entryname, url = (0, 0)
print('\n\nEdit cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 2, url + '\n')
remove(directory + folder + '/' + folderentry + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 2, url + '\n')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 2, url + '\n')
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'edit note' or argument == 'edit -n':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
except KeyboardInterrupt:
entryname, notes = (0, 0)
print('\n\nEdit cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
edit_note()
remove(directory + folder + '/' + folderentry + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
edit_note()
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
edit_note()
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
# copy
if argument == 'copy':
print('\nUSAGE: rpass copy [FLAG]')
print('Flags:')
print('copy:')
print(' username/-u copy the username of an entry to your clipboard')
print(' password/-p copy the password of an entry to your clipboard')
print(' url/-l copy the URL of an entry to your clipboard')
print(' note/-n copy the note of an entry to your clipboard\n')
if argument == 'copy username' or argument == 'copy -u':
try:
print()
term('cd ' + directory + '; ls -1 *')
print()
readentry = str(input('Entry to copy: '))
except KeyboardInterrupt:
readentry = 0
print('\n\nCopy cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + readentry + '.gpg')
copyline = open('/dev/shm/' + shmfolder + '/' + shmentry, 'r').readlines()
if environ.get('WAYLAND_DISPLAY') == 'wayland-0':
term('wl-copy ' + "'" + copyline[0].replace('\n', '') + "'")
else:
term('echo -n ' + "'" + copyline[0].replace('\n', '') + "'" + ' | xclip -sel c')
rmtree('/dev/shm/' + shmfolder)
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'copy password' or argument == 'copy -p':
try:
print()
term('cd ' + directory + '; ls -1 *')
print()
readentry = str(input('Entry to copy: '))
except KeyboardInterrupt:
readentry = 0
print('\n\nCopy cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + readentry + '.gpg')
copyline = open('/dev/shm/' + shmfolder + '/' + shmentry, 'r').readlines()
if environ.get('WAYLAND_DISPLAY') == 'wayland-0':
term('wl-copy ' + "'" + copyline[1].replace('\n', '').replace("'", "'\\''") + "'")
else:
term('echo -n ' + "'" + copyline[1].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
rmtree('/dev/shm/' + shmfolder)
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'copy url' or argument == 'copy -l':
try:
print()
term('cd ' + directory + '; ls -1 *')
print()
readentry = str(input('Entry to copy: '))
except KeyboardInterrupt:
readentry = 0
print('\n\nCopy cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + readentry + '.gpg')
copyline = open('/dev/shm/' + shmfolder + '/' + shmentry, 'r').readlines()
if environ.get('WAYLAND_DISPLAY') == 'wayland-0':
term('wl-copy ' + "'" + copyline[2].replace('\n', '') + "'")
else:
term('echo -n ' + "'" + copyline[2].replace('\n', '') + "'" + ' | xclip -sel c')
rmtree('/dev/shm/' + shmfolder)
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'copy note' or argument == 'copy -n':
try:
print()
term('cd ' + directory + '; ls -1 *')
print()
readentry = str(input('Entry to copy: '))
except KeyboardInterrupt:
readentry = 0
print('\n\nCopy cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + readentry + '.gpg')
copyline = open('/dev/shm/' + shmfolder + '/' + shmentry, 'r').readlines()
if environ.get('WAYLAND_DISPLAY') == 'wayland-0':
term('wl-copy ' + "'" + copyline[4].replace('\n', '') + "'")
else:
term('echo -n ' + "'" + copyline[4].replace('\n', '') + "'" + ' | xclip -sel c')
rmtree('/dev/shm/' + shmfolder)
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
# gen
if argument == 'gen':
try:
clear()
entryname = str(input('Name of service: '))
username = str(input('Username: '))
passlength = int(input('How many characters should be in the password? '))
passtype = str(input('Should the password be simple (for compatibility) or complex (for security)? (s/C) '))
if passtype != 's':
passtype = string.ascii_letters + string.digits + string.punctuation
if passtype == 's':
passtype = string.ascii_letters + string.digits
passgen = ''.join(random.SystemRandom().choice(passtype) for _ in range(passlength))
url = str(input('URL: '))
notes = str(input('Additional notes: '))
except KeyboardInterrupt:
entryname, username, passgen, url, notes = (0, 0, 0, 0, 0)
print('\n\nEntry generation cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + passgen + '\n' + url
+ '\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + passgen + '\n' + url
+ '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
open('/dev/shm/' + shmfolder + '/' + shmentry, 'w').writelines(username + '\n' + passgen + '\n' + url
+ '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The folder you requested to access does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
if argument == 'gen update' or argument == 'gen -u':
try:
clear()
term('cd ' + directory + '; ls -1 *')
print()
entryname = str(input('Which password would you like to re-generate? '))
passlength = int(input('How many characters should be in the password? '))
passtype = str(input('Should the password be simple (for compatibility) or complex (for security)? (s/C) '))
except KeyboardInterrupt:
entryname, passlength, passtype = (0, 0, 0)
print('\n\nEntry generation cancelled.\n')
exit()
shmfolder, shmentry = shmgen()
try:
if passtype != 's':
passtype = string.ascii_letters + string.digits + string.punctuation
if passtype == 's':
passtype = string.ascii_letters + string.digits
passgen = ''.join(random.SystemRandom().choice(passtype) for _ in range(passlength))
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, passgen + '\n')
remove(directory + folder + '/' + folderentry.replace('/', '', 1) + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, passgen + '\n')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg -d --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 1, passgen + '\n')
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to edit does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
rmtree('/dev/shm/' + shmfolder)
exit()
# remove
if argument == 'remove' or argument == '-rm':
clear()
term('cd ' + directory + '; ls -1 *')
print()
try:
entryname = str(input('What would you like to delete? '))
try:
term('gpg -d --output /dev/shm/rpass.lock /var/lib/rpass/lock.gpg')
unlocker = open('/dev/shm/rpass.lock', 'r').readlines()
remove('/dev/shm/rpass.lock')
except FileNotFoundError:
print('\nAccess denied.\n')
exit()
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
if devicetype == 'c':
term('ssh -p ' + port + ' ' + usernamessh + '@' + ip + ' "' + ' rm -rf ' + "'" + directoryssh +
entryname.replace('/', '', 1) + '.gpg' + "'" + '"')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
else:
if devicetype == 'c':
term('ssh -p ' + port + ' ' + usernamessh + '@' + ip + ' "' + ' rm -rf ' + "'" + directoryssh +
entryname.replace('/', '', 1) + "'" + '"')
rmtree(directory + entryname.replace('/', '', 1))
else:
if devicetype == 'c':
term('ssh -p ' + port + ' ' + usernamessh + '@' + ip + ' "' + ' rm -rf ' + "'" + directoryssh +
entryname + '.gpg' + "'" + '"')
remove(directory + entryname + '.gpg')
except KeyboardInterrupt:
print('\n\nDeletion cancelled.\n')
exit()
except FileNotFoundError:
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('The file you requested to delete does not exist!')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
exit()
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('/', argument) or argument == 'sync' or argument == '-s' or argument == '' or argument == 'help' \
or argument == '--help' or argument == '-h' or argument == 'version' or argument == '-v' or argument == \
'config' or argument == 'show w' or argument == 'show c':
pass
else:
print('\n!!!!!!!!!!!!!!!')
print('Argument error!')
print('!!!!!!!!!!!!!!!')
print("\nUse 'help', '--help', or '-h' to see a list of commands.\n")
# permissions - applied pre-sync to ensure permissions are correct before upload
term('find ' + directory + ' -type d -exec chmod -R 700 {} +')
term('find ' + directory + ' -type f -exec chmod -R 600 {} +')
# rsync - ran at end of program to ensure all files are properly synced
if devicetype == 'c':
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':
print('Syncing entries with other device(s)...\n')
term('rsync -v -H -r -l -t -p -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + directory + ' ' +
usernamessh + '@' + ip + ':' + directoryssh)
term('rsync -v -H -r -l -t -p --delete -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + usernamessh
+ '@' + ip + ':' + directoryssh + ' ' + directory)
+91 -190
View File
@@ -1,208 +1,109 @@
#!/usr/bin/python3
# Main Targets:
# TODO Make it so that when a new folder is created in sshyp, it is automatically created on the remote server
# TODO Replace references to rpass/sshyp directory with a changeable variable
# TODO Clean everything up and move sshync to a separate package
# TODO Add dry run support
# sshync 2021.11.01.unreleased3
# sshync was created to solve a problem with rpass/sshyp, and as such, sshync will be bundled with sshyp until it is
# polished enough for a standalone release
# sshync is a wrapper around sftp that allows easy remote directory synchronization via Python
# 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
# sshync 2021.12.01.unreleased7
# external modules
from os import walk
from os import system as term
from os.path import getmtime
from os.path import join as path_join
from os import system, remove, walk
from os.path import getmtime, join
from sys import exit as s_exit
# internal modules
# utility functions
def get_titles_mods(_directory, _destination, _user_data):
_title_list, _mod_list = [], []
# local fetching
if _destination == 'l':
if type(_user_data) == str:
_user_data = str(_user_data).strip('(').strip(')').replace(' ', '').split(',')
try:
remove(_user_data[6] + 'sshync_database')
except FileNotFoundError:
pass
for _root, _directories, _files in walk(_directory):
for _filename in _files:
_title_list.append(join(_root.replace(_directory, '', 1), _filename))
_mod_list.append(int(getmtime(join(_root, _filename))))
i = -1
for _title in _title_list:
open(_user_data[6] + 'sshync_database', 'a').write(str(_title) + '\n')
open(_user_data[6] + 'sshync_database', 'a').write('^&*\n')
for _mod in _mod_list:
open(_user_data[6] + 'sshync_database', 'a').write(str(_mod) + '\n')
# remote fetching
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]}:'{_user_data[6]}sshync_database' "
f"'{_user_data[6]}sshync_database'")
_titles, _sep, _mods = ' '.join(open(_user_data[6] + 'sshync_database').readlines()).replace('\n', '').partition('^&*')
_title_list, _mod_list = _titles.split(' ')[:-1], _mods.split(' ')[1:]
return _title_list, _mod_list
# recursively scans a local directory for all files and saves file paths and mod times to lists
def get_file_paths_mod(directory, name_database, time_database):
file_paths = []
temp_mod_times = []
mod_times = []
for root, directories, files in walk(directory):
for filename in files:
filepath = path_join(root, filename)
file_paths.append(filepath)
temp_mod_times.append(str(getmtime(filepath)))
for time in temp_mod_times:
mod_times.append(round(float(time), 2))
open(name_database, 'w').write(str(file_paths))
open(time_database, 'w').write(str(mod_times))
return file_paths, mod_times
def sort_titles_mods(_list_1, _list_2):
_title_list_2_sorted, _mod_list_2_sorted = [], []
# title sorting
for _title in _list_1[0]:
if _title in _list_2[0]:
_title_list_2_sorted.append(_title)
for _title in _list_2[0]:
if _title not in _title_list_2_sorted:
_title_list_2_sorted.append(_title)
# mod time sorting
for _title in _title_list_2_sorted:
_mod_list_2_sorted.append(_list_2[1][_list_2[0].index(_title)])
return _title_list_2_sorted, _mod_list_2_sorted
# recursively scans a remote directory for all files and saves file paths and mod times to lists
def get_file_paths_mod_remote(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', '')
remote_dir = profile_data[4].replace('\n', '')
identity = profile_data[5].replace('\n', '')
term("ssh -i " + "'" + identity + "'" + " -p " + port + " " + user + "@" + ip + " \"python -c \'import sshync; "
"sshync.get_file_paths_mod(" +
"\"'\"" + remote_dir + "/\"'\", " + "\"'\"/var/lib/rpass/sshyncdatabase_names\"'\", " +
"\"'\"/var/lib/rpass/sshyncdatabase_times\"'\")\'\"")
term(
'sftp -P ' + port + ' ' + user + '@' + ip + ':/var/lib/rpass/sshyncdatabase_names ' +
'/var/lib/rpass/sshyncdatabase_names')
term(
'sftp -P ' + port + ' ' + user + '@' + ip + ':/var/lib/rpass/sshyncdatabase_times ' +
'/var/lib/rpass/sshyncdatabase_times')
remote_mod_names = (open('/var/lib/rpass/sshyncdatabase_names').read()).replace('[', '').replace(']', '').replace(
' ', '').replace("'", '').split(',')
remote_mod_times = (open('/var/lib/rpass/sshyncdatabase_times').read()).replace('[', '').replace(']', '').replace(
' ', '').replace("'", '').split(',')
return remote_mod_names, remote_mod_times
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')
# regular profiles check the mod time of every individual file in the directory, making them slow but versatile
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')
# returns the settings for a specified profile
def get_profile(profile_dir):
def get_profile(_profile_dir):
try:
profile_data = open(profile_dir).readlines()
_profile_data = open(_profile_dir).readlines()
except (FileNotFoundError, IndexError):
profile_data = 0
return profile_data
print('\nEither the profile does not exist, or it is corrupted.\n')
_profile_data = None
s_exit()
# extract data from profile
_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', '')
_data_dir = ' '.join(_profile_dir.split('/')[:-1]).replace(' ', '/') + '/'
return _user, _ip, _port, _local_dir, _remote_dir, _identity, _data_dir
# sorts name lists so that local and remote are in the same order
def name_sort(local_names, remote_names):
remote_names_new = []
for ele in local_names:
if ele in remote_names:
remote_names_new.append(ele)
for ele in remote_names:
if ele not in remote_names_new:
remote_names_new.append(ele)
return remote_names_new
# sorts time lists to compensate for name list re-ordering
def time_sort(old_names, new_names, old_times):
remote_mod_times_new = []
new_pos = -1
for title in new_names:
new_pos += 1
if title in old_names:
old_pos = old_names.index(title)
remote_mod_times_new.append(old_times[old_pos])
return remote_mod_times_new
getter_loop_count = -1
def loop_getter(split_remote_dir):
global getter_loop_count
getter_loop_count += 1
new_var = split_remote_dir[getter_loop_count] + '/'
return new_var
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', '')
# get file modification times
local_mod_names, local_mod_times = get_file_paths_mod(local_dir + '/', '/var/lib/rpass/sshyncdatabase_names',
'/var/lib/rpass/sshyncdatabase_times')
remote_mod_times = []
remote_mod_names, remote_mod_times_temp = get_file_paths_mod_remote('/var/lib/rpass/rpass.sshync')
for time in remote_mod_times_temp: # remove quotes from remote_mod_times
remote_mod_times.append(float(time))
lmod_short = []
rmod_short = []
matching_names = []
matching_times_local = []
matching_times_remote = []
for lmod in local_mod_names:
lmod_short.append(lmod.replace(local_dir, ''))
for rmod in remote_mod_names:
rmod_short.append(rmod.replace(remote_dir, ''))
rmod_short_old = rmod_short
rmod_short = name_sort(lmod_short, rmod_short)
remote_mod_times = time_sort(rmod_short_old, rmod_short, remote_mod_times)
i = -1
for lshort in lmod_short:
i += 1
if lshort in rmod_short:
matching_names.append(lshort)
matching_times_local.append(local_mod_times[i])
def run_profile(_profile_dir):
_user_data = get_profile(_profile_dir)
_remote_titles_mods_saver = get_titles_mods(_user_data[4], 'r', _user_data) # saved to prevent re-walking directory
_index_l = sort_titles_mods(_remote_titles_mods_saver, get_titles_mods(_user_data[3], 'l', _user_data))
_index_r = sort_titles_mods(_index_l, _remote_titles_mods_saver)
_i = -1
for _title in _index_l[0]:
_i += 1
if _title in _index_r[0]:
# compare mod times and sync
if int(_index_l[1][_i]) > int(_index_r[1][_i]):
print(f"[{_title}] Local is newer, uploading...")
system(f"sftp -p -q -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
f"{_user_data[4]}{'/'.join(_title.split('/')[:-1]) + '/'} <<< $'put {_user_data[3]}{_title}'")
elif int(_index_l[1][_i]) < int(_index_r[1][_i]):
print(f"[{_title}] Remote is newer, downloading...")
system(f"sftp -p -q -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
f"{_user_data[4]}{_title} {_user_data[3]}{'/'.join(_title.split('/')[:-1]) + '/'}")
else:
print('Uploading ' + lshort)
lshort_split = lshort.replace('/', '', 1).split('/')
c = -1
for _ in lshort_split:
c += 1
global getter_loop_count
getter_loop_count = -1
q = ''
for _ in range(c):
q += loop_getter(lshort_split)
term('sftp -p -i ' + "'" + identity + "' " + '-P ' + port + ' ' + user + '@' + ip + ':' + remote_dir + q +
" <<< $'put " + local_dir + lshort.replace('/', '', 1) + "'")
i = -1
for rshort in rmod_short:
i += 1
if rshort in lmod_short:
matching_times_remote.append(float(remote_mod_times[i]))
else:
print('Downloading ' + rshort)
term('sftp -p -i ' + "'" + identity + "' " + '-P ' + port + ' ' + user + '@' + ip + ':' + remote_dir +
rshort.replace('/', '', 1) + ' ' + local_dir + rshort.replace('/', '', 1))
i = -1
for ltime in matching_times_local:
i += 1
ltime = int(ltime)
if ltime == int(matching_times_remote[i]):
print('Local ' + matching_names[i] + ' is up to date, not syncing.')
elif ltime > int(matching_times_remote[i]):
print('Local ' + matching_names[i] + ' is newer, uploading.')
matching_names_split = matching_names[i].replace('/', '', 1).split('/')
c = -1
for _ in matching_names_split:
c += 1
getter_loop_count = -1
q = ''
for _ in range(c):
q += loop_getter(matching_names_split)
term('sftp -p -i ' + "'" + identity + "' " + '-P ' + port + ' ' + user + '@' + ip + ':' + remote_dir + q +
" <<< $'put " + local_dir + matching_names[i].replace('/', '', 1) + "'")
elif ltime < int(matching_times_remote[i]):
print('Local ' + matching_names[i] + ' is older, downloading.')
term('sftp -p -i ' + "'" + identity + "' " + '-P ' + port + ' ' + user + '@' + ip + ':' + remote_dir +
matching_names[i].replace('/', '', 1) + ' ' + local_dir + matching_names[i].replace('/', '', 1))
print(f"[{_title}] Not on remote server, uploading...")
system(f"sftp -p -q -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:{_user_data[4]}"
f"{'/'.join(_title.split('/')[:-1]) + '/'} <<< $'put {_user_data[3]}{_title}'")
for _title in _index_r[0]:
if _title not in _index_l[0]:
print(f"[{_title}] Not in local directory, downloading...")
system(f"sftp -p -q -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:{_user_data[4]}"
f"{_title} {_user_data[3]}{'/'.join(_title.split('/')[:-1]) + '/'}")
+383 -731
View File
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,211 @@
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp 2021.12.01.fr2.2
The Lighter Update - Patch 2
This release is a hotfix for 2021.12.01.fr2.1.
Changes:
- a major fix for "/var/lib/sshync_database" needing to already exist server-side
- a major fix for syncing functionality (it should actually work now)
- silenced some sftp output
An fr2.3 patch is planned for this version. It will include the following:
- fixes for any new bugs that may be discovered in the new sshyp and sshync code
- the gen command in sshyp will be updated to use the newer notetaking system
- printing functions in sshyp will be combined into one function (arguments will determine section to print)
- file not found exceptions will be re-implemented
- when syncing, a check will be made to see if any folders are not on all devices and this will be corrected
Planned for next major update (The Fluffier Update):
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
- imporove password generator to guarantee more secure results
Planned for next, next major update (The Shears Update Pt. 1):
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- detatch sshync and make it a separate package
- manpage
Planned for next, next, next major update (The Shears Update Pt. 2):
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
Backlog:
- package for more Linux distributions, such as Debian and Fedora
- create separate gui frontend targetting mobile and desktop Linux
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp 2021.12.01.fr2.1
The Lighter Update - Patch 1
This release is a hotfix for 2021.12.01.fr2.
Changes:
- fixed a bug where "sshyp tweak" would not function on new installations
- moved the argument parser to the global process
- running "sshyp version" or "sshyp -v" no longer triggers syncing
- folders are now created natively with Python, rather than through system commands
An fr2.2 patch is planned for this version. It will include the following:
- fixes for any new bugs that may be discovered in the new sshyp and sshync code
- the gen command in sshyp will be updated to use the newer notetaking system
- printing functions in sshyp will be combined into one function (arguments will determine section to print)
- file not found exceptions will be re-implemented
Planned for next major update (The Fluffier Update):
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
- imporove password generator to guarantee more secure results
Planned for next, next major update (The Shears Update Pt. 1):
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- detatch sshync and make it a separate package
- manpage
Planned for next, next, next major update (The Shears Update Pt. 2):
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
Backlog:
- package for more Linux distributions, such as Debian and Fedora
- create separate gui frontend targetting mobile and desktop Linux
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp 2021.12.01.fr2
The Lighter Update
This release features a major re-write of old "rpass" code.
sshyp is now more reliable and better documented.
New features:
- a full re-write of the old "rpass" code used in the last release
^ includes more reliable argument parsing and various optimizations
- a full re-write of "sshync", many issues fixed
^fixed many instances where sshync would refuse to upload/download
^fixed errors that were being thrown despite sshync working as intended
- new folders are now also created on the server
Changes:
- nested folders actually work now
- multi-word entry and folder titles are fixed
An fr2.1 patch is planned for this version. It will include the following:
- fixes for any new bugs that may be discovered in the new sshyp and sshync code
- the gen command in sshyp will be updated to use the newer notetaking system
- printing functions in sshyp will be combined into one function (arguments will determine section to print)
- file not found exceptions will be re-implemented
- the argument parser will be moved to the global process (no need for it to be in a function)
- folders will be created natively in python
Planned for next major update (The Fluffier Update):
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
- imporove password generator to guarantee more secure results
Planned for next, next major update (The Shears Update Pt. 1):
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- detatch sshync and make it a separate package
- manpage
Planned for next, next, next major update (The Shears Update Pt. 2):
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
Backlog:
- package for more Linux distributions, such as Debian and Fedora
- create separate gui frontend targetting mobile and desktop Linux
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp 2021.11.05.fr1
First public release of sshyp.
This release fixes major bugs from rpass and rebrands the project.
New features:
- an entirely new syncing back-end called sshync (custom Python wrapper around sftp)
^ in thoery, all syncing-related data loss should now be fixed, however, this new
system has just been created and is still under testing. Maybe wait for a few patches
before trusting this system.
Changes:
- branding has been updated to reflect new project name and goals
- custom directories, custom ssh keys, and offline only mode are removed (may be temporary)
^ the configuration wizard is being re-written in the next major update
Planned for next update (The Fluffy Update):
- modularized and optimized code
^ some older, bad code from "rpass" will be re-written.
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
Planned for next update (The Sheep w/Shears Update):
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- ability to pass entries as arguments for more functions
- detatch sshync and make it a separate package
- manpage
Planned, no timeline:
- create separate gui frontend targetting mobile devices (Android + Linux phones)
^ the gui will also function on desktop linux
- package for more Linux distributions, such as Debian and Fedora)
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.11.01.mr5.1
The Notetaker Update - Patch 1
-46
View File
@@ -1,46 +0,0 @@
sshyp 2021.11.01.fr1
First public release of sshyp.
This release fixes major bugs from rpass and rebrands the project.
New features:
- an entirely new syncing back-end called sshync (custom Python wrapper around sftp)
^ in thoery, all syncing-related data loss should now be fixed, however, this new
system has just been created and is still under testing. Maybe wait for a few patches
before trusting this system.
Changes:
- branding has been updated to reflect new project name and goals
Planned for next update (The Fluffy Update):
- modularized and optimized code
^ some older, bad code from "rpass" will be re-written.
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
Planned for next update (The Sheep w/Shears Update):
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- ability to pass entries as arguments for more functions
- detatch sshync and make it a separate package
- manpage
Planned, no timeline:
- create separate gui frontend targetting mobile devices (first Android + Linux phones - official iOS client not likely)
^ the gui will also function on desktop linux
- make platform agnostic (add Windows support and package for more Linux distributions, such as Debian and Fedora)
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Future changelogs will include a link to the complete history of patches across rpass and sshyp.
+52
View File
@@ -0,0 +1,52 @@
sshyp 2021.12.01.fr2.2
The Lighter Update - Patch 2
This release is a hotfix for 2021.12.01.fr2.1.
Changes:
- a major fix for "/var/lib/sshync_database" needing to already exist server-side
- a major fix for syncing functionality (it should actually work now)
- silenced some sftp output
An fr2.3 patch is planned for this version. It will include the following:
- fixes for any new bugs that may be discovered in the new sshyp and sshync code
- the gen command in sshyp will be updated to use the newer notetaking system
- printing functions in sshyp will be combined into one function (arguments will determine section to print)
- file not found exceptions will be re-implemented
- when syncing, a check will be made to see if any folders are not on all devices and this will be corrected
Planned for next major update (The Fluffier Update):
- new visual features
^ this includes the new file list and thematic text art. sshyp will be
getting a retro computing theme.
- packages for more environments
^ "sshyp" will be officially packaged for Arch Linux, Alpine Linux, and Termux (Android).
Debian/Ubuntu and Fedora packaging will come later.
- imporove password generator to guarantee more secure results
Planned for next, next major update (The Shears Update Pt. 1):
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- allow for multi-client deletion... somehow
- detatch sshync and make it a separate package
- manpage
Planned for next, next, next major update (The Shears Update Pt. 2):
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
Backlog:
- package for more Linux distributions, such as Debian and Fedora
- create separate gui frontend targetting mobile and desktop Linux
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
The full history of changes to "sshyp" can be found on the following page:
https://raw.githubusercontent.com/rwinkhart/sshyp/main/extra/changelog-total
@@ -1,4 +1,4 @@
rpass is a FOSS password manager that takes advantage of rsync
sshyp is a FOSS password manager that takes advantage of rsync
Copyright (C) 2021 Randall Winkhart idgr@tutanota.com
This program is free software: you can redistribute it and/or modify