Compare commits

...
Author SHA1 Message Date
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
RandyTheSilly 55b07eb8f6 Rebranding step 3 + final rpass version prep 2021-11-01 16:23:08 -04:00
RandyTheSilly 96161e870d Rebranding step 2 2021-11-01 15:17:29 -04:00
RandyTheSilly 8c557ee290 Rebranding step 1 2021-11-01 15:15:01 -04:00
RandyTheSilly 59be7d7602 Completed initial implementation of sshync 2021-11-01 13:59:25 -04:00
RandyTheSilly b60efd86d6 sftp/sshync syncing progress 2021-10-27 01:12:57 -04:00
RandyTheSilly 18b27c9dce Partial fix for data loss (syncing temporarily disabled) 2021-10-12 23:13:03 -04:00
RandyTheSilly 6cdc158074 Updated changelog/roadmap 2021-10-11 15:03:51 -04:00
RandyTheSilly 2911087b40 Fixed an issue with copying notes (2) 2021-10-11 13:47:53 -04:00
RandyTheSilly f7c0e81f02 Fixed an issue with copying notes 2021-10-11 13:45:50 -04:00
RandyTheSilly 02059d367c Updated roadmap 2021-10-11 13:22:36 -04:00
RandyTheSilly 91dcd4585a Update PKGBUILD... again 2021-10-07 23:20:15 -04:00
8 changed files with 845 additions and 859 deletions
+11 -11
View File
@@ -1,22 +1,22 @@
# Maintainer: Randall Winkhart <idgr at tutanota dot com>
pkgname=rpass
pkgver=2021.10.07.mr5
pkgname=sshyp
pkgver=2021.12.01.fr2
pkgrel=1
pkgdesc='An rsync-based password manager and alternative to GNU pass'
url='https://github.com/rwinkhart/rpass'
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/rpass/releases/download/v"$pkgver"/rpass-"$pkgver".tar.xz')
source_aarch64=('https://github.com/rwinkhart/rpass/releases/download/v"$pkgver"/rpass-"$pkgver".tar.xz')
sha512sums_x86_64=('a1600816cd37fa7055f603dd9fa3f0a4d1f37505083ebb93d30270536f87666718c45bf995c89af6c425af5fcd93bba2ac3df12d83eea6dc3207c4030d55d46b')
sha512sums_aarch64=('a1600816cd37fa7055f603dd9fa3f0a4d1f37505083ebb93d30270536f87666718c45bf995c89af6c425af5fcd93bba2ac3df12d83eea6dc3207c4030d55d46b')
source_x86_64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.12.01.fr2/sshyp-2021.12.01.fr2.tar.xz')
source_aarch64=('https://github.com/rwinkhart/sshyp/releases/download/v2021.12.01.fr2/sshyp-2021.12.01.fr2.tar.xz')
sha512sums_x86_64=('88b1db43a0234e00cc9b2b5aa6aff642a350109e101a1ebc95e06e7ebc294b09c8369eead06fd16bbffd1f6ce564fb1e8736685ee716f7806532710d7357a5cb')
sha512sums_aarch64=('88b1db43a0234e00cc9b2b5aa6aff642a350109e101a1ebc95e06e7ebc294b09c8369eead06fd16bbffd1f6ce564fb1e8736685ee716f7806532710d7357a5cb')
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
}
+52 -13
View File
@@ -1,16 +1,46 @@
# rpass
A very simple password manager with rsync integration - alternative to GNU pass
# 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 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)
rpass releases are available in the Arch User Repository as 'rpass'.
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:
```
git clone https://aur.archlinux.org/rpass.git
cd rpass
git clone https://aur.archlinux.org/sshyp.git
cd sshyp
makepkg -si
```
@@ -20,15 +50,16 @@ Packaging for other distributions coming soon.
Upon initial installation, be sure to run:
```
rpass config
sshyp tweak
```
This command will allow you to configure the settings necessary for rpass to function.
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:
```
rpass --help
sshyp --help
```
# Roadmap
@@ -38,14 +69,22 @@ Short-term Goals:
- create a man page
- overhaul argument system
- fix lots of bugs!
- make lots of optimizations!
Medium-term Goals:
- add libsecret integration to allow rpass to act as a gnome-keyring alternative
- create a minimal GUI app optimized for the Pinephone (also compatible with x86_64)
- create minimal GUI apps (Linux x86_64, Linux aarch64)
- auto-completion on tab for CLI version
Long-term Goals:
- make an Android port (including GUI)
- make a minimal Windows port
- investigate auto-completion on tab
- 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.10.07.mr5 /')
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[3].replace('\n', '') + "'")
else:
term('echo -n ' + "'" + copyline[3].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)
Executable
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/python3
# sshync 2021.12.01.unreleased6
# external modules
from os import system, remove, walk
from os.path import getmtime, join
from sys import exit as s_exit
# 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(',')
remove(_user_data[6] + 'sshync_database')
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
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
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')
def get_profile(_profile_dir):
try:
_profile_data = open(_profile_dir).readlines()
except (FileNotFoundError, IndexError):
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
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 -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
f"{_user_data[4]}{_title} <<< $'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 -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
f"{_user_data[4]}{_title} {_user_data[3]}{_title}")
else:
print(f"[{_title}] Not on remote server, uploading...")
system(f"sftp -p -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:{_user_data[4]}"
f"{_title} <<< $'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 -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:{_user_data[4]}"
f"{_title} {_user_data[3]}{_title}")
Executable
+482
View File
@@ -0,0 +1,482 @@
#!/usr/bin/python3
# external modules
from os import environ, remove, system
from shutil import copy, move, rmtree
from sys import argv, exit as s_exit
import random
import sshync
import string
# utility functions
def argument_filter(): # filters arguments to usable text
_argument_list = argv
_i, _argument = 0, ''
for _ in _argument_list:
while _i < len(_argument_list) - 1:
_i += 1
_argument += _argument_list[_i] + ' '
return _argument[:-1]
def replace_line(file_name, line_num, text): # replaces text in a given line with different text
_lines = open(file_name, 'r').readlines()
_lines[line_num] = text
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
_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)))
system(f"mkdir -p /dev/shm/{_shm_folder_gen}") # TODO generate with Python
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}")
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')
# argument-specific functions
def tweak(): # runs configuration wizard
# storage directory creation
system(f"mkdir -p /home/{environ.get('USER')}/.password-pasture")
# device type configuration
_device_type = input('\nIs this installation for a client or for a server? (C/s) ')
if _device_type == 'S' or _device_type == 's':
open("/var/lib/sshyp/sshyp-device", 'w').write(_device_type)
copy('/usr/bin/sshync.py', f"/home/{environ.get('USER')}/")
print('\nMake sure the ssh service is running and properly configured.\n\nConfiguration complete!')
else:
# device type configuration
_device_type = 'c' # ensure device type flag is properly set
open("/var/lib/sshyp/sshyp-device", 'w').write(_device_type)
# gpg configuration
_gpg_id = input('\nsshyp requires the use of a unique gpg key. Do you already have one that you are '
'willing to use? (y/N)')
if _gpg_id != 'y' and _gpg_id != 'Y':
print('\nA unique gpg key has been generated for you.')
system('gpg --full-generate-key')
_gpg_id = str(input('\nPlease input the ID of your gpg key: '))
open("/var/lib/sshyp/sshyp-gpg", 'w').write(_gpg_id + '\n')
# lock file generation
try:
open('/var/lib/sshyp/lock', 'x').write('')
except FileExistsError:
pass
system(f"gpg -r {str(_gpg_id)} -e /var/lib/sshyp/lock")
remove('/var/lib/sshyp/lock')
# ssh key configuration
_ssh_gen = (input('\nMake sure the ssh service on the remote server is running and properly configured.'
'\n\nrsync support requires a unique ssh key. Would you like to have this automatically '
'generated? (Y/n) '))
if _ssh_gen != 'n' and _ssh_gen != 'N':
system('ssh-keygen -t ed25519 -f ~/.ssh/sshyp')
else:
print(f"\nEnsure that the key file you are using is located at /home/{environ.get('USER')}/.ssh/sshyp")
# ssh ip+port configuration
print('\nExample input: 10.10.10.10:9999\n')
_ip_port = str(input('What is the IP and ssh port of the remote server? '))
_ip, _sep, _port = _ip_port.partition(':')
# ssh user configuration
_username_ssh = str(input('\nWhat is the username of the remote server? '))
print(f"\nEntry directory: /home/{_username_ssh}/.password-pasture/")
# sshync profile generation
sshync.make_profile('/var/lib/sshyp/sshyp.sshync', f"/home/{environ.get('USER')}/.password-pasture/",
f"/home/{_username_ssh}/.password-pasture/", f"/home/{environ.get('USER')}/.ssh/sshyp",
_ip, _port, _username_ssh)
print('\nConfiguration complete!\n')
def helper(): # displays help menu
print('\nsshyp Copyright (C) 2021 Randall Winkhart')
print("This is free software, and you are welcome to redistribute it under certain conditions;\nthis program comes "
"with ABSOLUTELY NO WARRANTY;\ntype `sshyp license' for details.")
print('\nUSAGE: sshyp [/<entry name>] [OPTION] [FLAG]\n')
print('Options: ')
print('help/--help/-h bring up this menu')
print('version/-v display sshyp version info')
print('tweak configure sshyp')
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('shear/-rm delete an existing entry')
print('sync/-s manually sync the entry directory via sshync\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 'sshyp /<entry name>'!")
print("When specifying entry names, do not include the file extension! '.gpg' is assumed!\n")
def version(): # displays version information
print('\n////////////////////////////////////////////////////////')
print('/ /')
print('/ sshyp Copyright (C) 2021 Randall Winkhart /')
print('/ /')
print('/ Version 2021.12.01.fr2 /')
print('/ The Lighter Update /')
print('/ /')
print('////////////////////////////////////////////////////////\n')
def no_arg(): # displays a list of entries and gives an option to select one for viewing
print("\nFor a list of usable commands, run 'sshyp help'.\n")
system(f"cd {directory}; ls -1 *")
_read_entry = str(input('\nEntry to read: '))
system(f"gpg -d '{directory}{_read_entry.replace('/', '', 1)}.gpg'")
print()
def show_license(): # displays licensing information
print('\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU General'
'\nPublic License as published by the Free Software Foundation, either version 3 of the License,\nor '
'(at your option) any later version.\n'
'\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\nwithout even '
'the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public '
'License for more details.\n\nhttps://opensource.org/licenses/GPL-3.0\n')
def read_shortcut(): # shortcut to quickly read an entry
system(f"gpg -d '{directory}{argument.replace('/', '', 1)}.gpg'")
def sync(): # calls sshync to sync changes to the user's server
print('\nSyncing entries with the server device...\n')
# set permissions before uploading
system('find ' + directory + ' -type d -exec chmod -R 700 {} +')
system('find ' + directory + ' -type f -exec chmod -R 600 {} +')
sshync.run_profile('/var/lib/sshyp/sshyp.sshync')
def add_info(): # displays 'add' syntax
print('\nUSAGE: sshyp 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')
def add_entry(): # adds a new entry
_entry_name = str(input('\nName of entry: '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
_shm_folder, _shm_entry = shm_gen()
if argument == 'add note' or argument == 'add -n':
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')
if argument == 'add password' or argument == 'add -p':
_username = str(input('Username: '))
_password = str(input('Password: '))
_url = str(input('URL: '))
_add_note = input('Add a note to this entry? (y/N) ')
if _add_note == 'y' or _add_note == 'Y':
system(f"nano /dev/shm/{_shm_folder}/{_shm_entry}-n")
_notes = open(f"/dev/shm/{_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'
+ _notes + '\n\n')
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
def add_folder(): # creates a new folder
_folder_name = str(input('Name of new folder: '))
system(f"mkdir '{directory}{_folder_name}'") # TODO create using Python
system(f"ssh -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}{_folder_name}'\"")
def edit_info(): # displays 'edit' syntax
print('\nUSAGE: sshyp 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')
def rename(): # renames an entry or folder TODO delete original from server to prevent re-downloading
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_entry_name = str(input('\nWhat would you like to rename/relocate? '))
_new_name = str(input('New Name: '))
if _entry_name.startswith('/'):
if _entry_name.replace('/', '', 1).__contains__('/'):
_folder, _sep, _folder_entry = _entry_name.replace('/', '', 1).partition('/')
move(f"{directory}{_folder}/{_folder_entry}.gpg", f"{directory}/{_new_name}.gpg")
else:
move(f"{directory}{_entry_name.replace('/', '', 1)}.gpg", f"{directory}{_new_name.replace('/', '', 1)}.gpg")
else:
move(f"{directory}{_entry_name}.gpg", f"{directory}{_new_name}.gpg")
def edit(): # edits the contents of an entry
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_entry_name = str(input('\nWhat file would you like to edit? '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output /dev/shm/{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
if argument == 'edit username' or argument == 'edit -u':
_detail = str(input('New Username: '))
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 0, _detail + '\n')
if argument == 'edit password' or argument == 'edit -p':
_detail = str(input('New Password: '))
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 1, _detail + '\n')
if argument == 'edit url' or argument == 'edit -l':
_detail = str(input('New URL: '))
replace_line(f"/dev/shm/{_shm_folder}/{_shm_entry}", 2, _detail + '\n')
if argument == 'edit note' or argument == 'edit -n':
edit_note(_shm_folder, _shm_entry)
remove(f"{directory}{_entry_name}.gpg")
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
def gen(): # generates a password for a new or an existing entry
_username, _url, _notes = None, None, None # sets base-line values to avoid errors
_shm_folder, _shm_entry = shm_gen()
if argument == 'gen update' or argument == 'gen -u':
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_entry_name = str(input('\nName of service: '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if argument != 'gen update' and argument != 'gen -u':
_username = str(input('Username: '))
_pass_length = int(input('How many characters should be in the password? '))
_pass_type = str(input('Should the password be simple (for compatibility) or complex (for security)? (s/C) '))
if _pass_type != 's':
_pass_type = string.ascii_letters + string.digits + string.punctuation
if _pass_type == 's':
_pass_type = string.ascii_letters + string.digits
_pass_gen = ''.join(random.SystemRandom().choice(_pass_type) for _ in range(_pass_length))
if argument != 'gen update' and argument != 'gen -u':
_url = str(input('URL: '))
_notes = str(input('Additional notes: ')) # TODO update w/new notes system
if argument != 'gen update' and argument != 'gen -u':
open(f"/dev/shm/{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _pass_gen + '\n' + _url +
'\n\n' + _notes + '\n\n')
if argument != 'gen update' and argument != 'gen -u':
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
else:
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')
remove(f"{directory}{_entry_name}.gpg")
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
def copy_info(): # displays 'copy' syntax
print('\nUSAGE: sshyp 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')
def copy_data(): # copies a specified field of an entry to the clipboard
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_read_entry = str(input('\nEntry to copy: '))
_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 environ.get('WAYLAND_DISPLAY') == 'wayland-0': # checks if the user is using Wayland or X for clipboard
if argument == 'copy username' or argument == 'copy -u':
system('wl-copy ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy password' or argument == 'copy -p':
system('wl-copy ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy url' or argument == 'copy -l':
system('wl-copy ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy note' or argument == 'copy -n':
system('wl-copy ' + "'" + _copy_line[4].replace('\n', '').replace("'", "'\\''") + "'")
else:
if argument == 'copy username' or argument == 'copy -u':
system('echo -n ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument == 'copy password' or argument == 'copy -p':
system('echo -n ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument == 'copy url' or argument == 'copy -l':
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}")
def remove_data(): # deletes an entry or folder from both the client and the server
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('gpg -d --output /dev/shm/sshyp.lock /var/lib/sshyp/lock.gpg')
_unlock = open('/dev/shm/sshyp.lock', 'r').readlines()
remove('/dev/shm/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")
# program start sequence
# import saved userdata
device_type = ''
try:
device_type = open('/var/lib/sshyp/sshyp-device').read().strip()
if device_type == 'c':
gpg_id = open('/var/lib/sshyp/sshyp-gpg').read().strip()
ssh_info = sshync.get_profile('/var/lib/sshyp/sshyp.sshync')
username_ssh = ssh_info[0].replace('\n', '')
ip = ssh_info[1].replace('\n', '')
port = ssh_info[2].replace('\n', '')
directory = str(ssh_info[3].replace('\n', ''))
directory_ssh = '/home/' + username_ssh + '/.password-pasture/'
except FileNotFoundError:
if device_type != 's' and device_type != 'S':
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print("Not all necessary configuration files are present. Please run 'sshyp tweak'!")
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
s_exit()
# retrieve typed argument
argument = argument_filter()
# run function based on argument
error = 0 # create an error flag to determine if syncing should occur at end
if argument.startswith('/'):
read_shortcut()
elif argument == '':
try:
no_arg()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'tweak':
try:
tweak()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'help' or argument == '--help' or argument == '-h':
helper()
elif argument == 'license':
show_license()
elif argument == 'version' or argument == '-v':
version()
elif argument == 'add':
add_info()
elif argument == 'add note' or argument == 'add -n' or argument == 'add password' or argument == 'add -p':
try:
add_entry()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'add folder' or argument == 'add -f':
try:
add_folder()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'edit':
edit_info()
elif argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit -r':
try:
rename()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'edit username' or argument == 'edit -u' or argument == 'edit password' or argument == 'edit -p' or \
argument == 'edit url' or argument == 'edit -l' or argument == 'edit note' or argument == 'edit -n':
try:
edit()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'gen' or argument == 'gen update' or argument == 'gen -u':
try:
gen()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'copy':
copy_info()
elif argument == 'copy username' or argument == 'copy -u' or argument == 'copy password' or argument == 'copy -p' or \
argument == 'copy url' or argument == 'copy -l' or argument == 'copy note' or argument == 'copy -n':
try:
copy_data()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'shear' or argument == '-rm':
try:
remove_data()
except KeyboardInterrupt:
print('\n')
s_exit()
elif argument == 'sync' or argument == '-s':
sync()
else:
error = 1 # set error flag to 1 to stop syncing
print("\nArgument error! Please run 'sshyp help' for a list of usable commands.\n")
s_exit()
# sync at end of program if any changes were made
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 != \
'tweak' and argument != 'shear' and argument != '-rm' and error == 0 and argument.startswith('/') is False:
sync()
@@ -1,5 +1,137 @@
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
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
This is the FINAL release of "rpass".
After this release, the project will be rebranded as "sshyp".
rpass's syncing system is fundamentally broken, hence the need for "sshyp"
and its new syncing system. I would highly advise against using this release.
New features:
- none
Changes:
- fixed an issue with copying notes (currently only copies first line, will be changed in the future)
- rpass is validated to work with Python 3.10 (no changes were needed)
Planned for next update (sshyp fr1)
- full project rebrand ("sshyp")
- new syncing back-end
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.10.07.mr5
The Notetaker Update - Fifth main release of rpass
+61
View File
@@ -0,0 +1,61 @@
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
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
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