Compare commits

...
Author SHA1 Message Date
RandyTheSilly b08456e873 Updated documentation for release fr4.7 2022-02-16 16:24:11 -05:00
RandyTheSilly ef828b88a0 Added user-facing messages when deleting via sync 2022-02-16 16:10:37 -05:00
RandyTheSilly bde243c644 Continuation of recursive fix 2022-02-16 15:59:11 -05:00
RandyTheSilly 894f406fd2 Fix recursive folder syncing reporting incorrect directories 2022-02-16 15:57:23 -05:00
RandyTheSilly 00b935f1bb Allow for recursive folder syncing 2022-02-16 15:43:33 -05:00
RandyTheSilly 49608cb839 Updated changelog for fr4.6 2022-02-16 13:51:12 -05:00
RandyTheSilly a417478aa0 Fixed critical typo preventing folder syncing from working 2022-02-16 13:46:42 -05:00
RandyTheSilly 344c74b728 Updated changelog for release fr4.5 2022-02-16 13:28:00 -05:00
RandyTheSilly fc0e4bb4a5 Bump version 2022-02-16 13:23:43 -05:00
RandyTheSilly 37867cb673 More renaming 2022-02-16 13:22:10 -05:00
RandyTheSilly 86aa7da038 Renamed file to avoid syntax error 2022-02-16 13:20:24 -05:00
RandyTheSilly 9231257af8 Updated README.md to reflect new folder syncing changes 2022-02-16 12:50:29 -05:00
RandyTheSilly 102f22143f Updated manpage to reflect new folder syncing changes 2022-02-16 12:48:24 -05:00
RandyTheSilly 3dd12b4d6d Updated changelog for release fr4.4 2022-02-16 12:46:52 -05:00
RandyTheSilly a0b5dad073 Automatically remove old device names locally 2022-02-16 12:37:20 -05:00
RandyTheSilly 2ba19f9a39 Initial folder sync implementation 2022-02-16 12:02:45 -05:00
RandyTheSilly 8af71ceb1a More renaming 2022-02-16 09:44:24 -05:00
RandyTheSilly 81c9b35c75 Rename deletion check function 2022-02-16 09:27:22 -05:00
RandyTheSilly eeabc18f18 Fixed typo 2022-02-16 09:23:29 -05:00
RandyTheSilly 73128665fb Rename sshyp-shear.py to sshyp-remote.py for future intentions 2022-02-16 09:15:33 -05:00
RandyTheSilly 607a4709f6 Update README.md 2022-02-16 01:42:08 -05:00
RandyTheSilly c643e861d9 Updated changelog for release fr4.3 2022-02-16 01:39:35 -05:00
RandyTheSilly 23e7e375ae Properly applied fix from last commit 2022-02-16 01:35:48 -05:00
RandyTheSilly b8743d5fe2 Fixed local entry (not folders this time) deletion 2022-02-16 01:33:08 -05:00
RandyTheSilly e95aa85453 Updated changelog for release fr4.2 2022-02-16 01:18:12 -05:00
RandyTheSilly caf130568e Version bump for release fr4.2 2022-02-16 01:15:19 -05:00
RandyTheSilly f65adc17f3 Actually fixed local folder deletion this time 2022-02-16 01:13:35 -05:00
RandyTheSilly fc2f42a1aa Removed extra new line printed after some remote file checks 2022-02-16 01:07:03 -05:00
RandyTheSilly 8403f4af98 Updated changelog for release fr4.1 2022-02-16 00:50:39 -05:00
RandyTheSilly 4b24df0e97 Deletion flags no longer end in 'del' 2022-02-16 00:45:26 -05:00
RandyTheSilly ca007f55ac '.' is no longer an unsupported character 2022-02-16 00:42:16 -05:00
RandyTheSilly 7afcfdb43d Updated manpage to disclose unsupported characters 2022-02-16 00:32:55 -05:00
RandyTheSilly 5178377827 Fixed local folder deletion 2022-02-16 00:23:48 -05:00
RandyTheSilly ff9241368e Updated changelog for release fr4 2022-02-15 23:59:05 -05:00
RandyTheSilly 6014de98dd Version bump for release fr4 2022-02-15 23:54:10 -05:00
RandyTheSilly 6e7e42a69e Added folder deletion instructions to manpage 2022-02-15 23:48:23 -05:00
RandyTheSilly 0314bf36af Added folder deletion 2022-02-15 23:41:23 -05:00
RandyTheSilly 93ac4ef824 Updated manpage to reflect multi-client deletion 2022-02-15 22:30:13 -05:00
RandyTheSilly 65d10551f6 Fixed SSH identity file used for folder creation 2022-02-02 13:55:04 -05:00
RandyTheSilly f6ddf2ad37 Updated changelog 2022-02-02 09:42:15 -05:00
RandyTheSilly 7f00570249 Implemented multi-client deletion 2022-02-02 09:23:43 -05:00
RandyTheSilly 3d7f08e43e Added initial script for multi-client deletion 2022-02-02 04:50:06 -05:00
RandyTheSilly d82c9b5e02 Version bump for release fr3.4 2022-01-26 14:36:34 -05:00
RandyTheSilly 9133a73553 Updated changelog for release 2022-01-26 14:30:41 -05:00
RandyTheSilly ad039d6322 Updated manpage 2022-01-26 12:09:45 -05:00
RandyTheSilly caa5fad0bc Added exception when trying to shear a file that doesn't exist 2022-01-17 02:05:01 -05:00
RandyTheSilly 68ded52e8c Fixed sshync using wrong identity file in some cases 2022-01-17 01:57:04 -05:00
RandyTheSilly 85c59b302d Updated changelog for release fr3.3 2022-01-17 00:49:46 -05:00
RandyTheSilly 954dd30361 Small optimization with blanking sshync database file 2022-01-17 00:40:57 -05:00
RandyTheSilly 65d1885311 Fixed checking for sshync database file 2022-01-17 00:36:56 -05:00
RandyTheSilly 5a7b45c3ac Fixed unlocking for "sshyp shear" 2022-01-17 00:16:16 -05:00
RandyTheSilly e5638255a8 Update README.md 2022-01-17 00:07:15 -05:00
RandyTheSilly 2e32911470 Various path optimizations 2022-01-16 23:58:47 -05:00
RandyTheSilly 4973d18034 ~/.config is created if it does not already exist 2022-01-16 23:41:29 -05:00
RandyTheSilly 6e13a6ebb3 Fixed clipboard detection for Termux 2022-01-16 23:09:47 -05:00
RandyTheSilly dfbdc16079 Use full path for Termux tmp symlink 2022-01-16 22:20:43 -05:00
RandyTheSilly 3c4bf0115f Updated changelog for release fr3.2 2022-01-16 21:33:35 -05:00
RandyTheSilly 762211bae0 Fixed temporary directory for Termux 2022-01-16 21:01:56 -05:00
RandyTheSilly d9adcac8ec sshync now properly generates its config directory 2022-01-16 16:27:05 -05:00
RandyTheSilly 1d9000ab16 Updated changelog for release fr3.1 2022-01-16 05:45:43 -05:00
RandyTheSilly bdea49268d Update README.md 2022-01-16 05:39:18 -05:00
RandyTheSilly 187ea39861 Re-wrote get_titles_mods for better fr3 compatibility 2022-01-16 05:29:41 -05:00
RandyTheSilly ee8e7fc8a5 Simplified expanduser statements 2022-01-15 18:32:59 -05:00
RandyTheSilly 8a4ae469fa Another attempt at updating sshync for fr3 compatibility 2022-01-13 05:02:35 -05:00
RandyTheSilly 4330617060 Partial revert for last fix 2022-01-13 04:36:58 -05:00
RandyTheSilly 54397dcd13 Partial sync fix 2022-01-13 04:31:28 -05:00
RandyTheSilly 0e7595489b Update changelog for release fr3 2022-01-13 03:06:16 -05:00
RandyTheSilly cd378aadc2 Version bump to 2022.01.13.fr3 2022-01-13 03:03:04 -05:00
RandyTheSilly d26c2a5e08 ~/.config/sshyp is now auto-generated 2022-01-13 02:56:34 -05:00
RandyTheSilly b24bcdd413 Updated packaging script to reflect new config file directory 2022-01-13 02:53:04 -05:00
RandyTheSilly b0fa1f99c9 Changed method for detecting Termux 2022-01-13 02:46:18 -05:00
RandyTheSilly 2825b43659 Changed config directory from /var/lib/sshyp to ~/.config/sshyp (for Termux compatibility) 2022-01-13 02:34:35 -05:00
RandyTheSilly 49721cd39a Added Termux clipboard support 2022-01-13 01:57:07 -05:00
RandyTheSilly 715d58fb62 Added Debian support/improved support for other formats in packaging script 2022-01-13 01:25:56 -05:00
RandyTheSilly 73307e2b3c Added error message for unimplemented options 2022-01-12 20:09:11 -05:00
RandyTheSilly ab739e3920 Fixed packaging script using incorrect directories 2022-01-12 19:31:15 -05:00
RandyTheSilly 0253872c8d (hopefully) fixed generic packaging 2022-01-12 18:43:44 -05:00
RandyTheSilly 2d2b0aa0ec Updated roadmap for future releases 2022-01-12 18:16:43 -05:00
rwinkhart 532784d817 Delete PKGBUILD 2022-01-12 22:58:39 +00:00
RandyTheSilly 6d1bf9f96c Added Termux and PKGBUILD support to packaging script 2022-01-12 17:57:23 -05:00
RandyTheSilly 67a7c2e382 Update README.md 2022-01-12 00:56:33 -05:00
RandyTheSilly 9f229e7ae7 Updated packaging script to build in the active directory 2022-01-12 00:40:12 -05:00
RandyTheSilly e3b0d2dbe7 Added a packaging script 2022-01-12 00:24:12 -05:00
RandyTheSilly ce4e32c8f4 Updated roadmap for future releases 2022-01-11 21:42:33 -05:00
RandyTheSilly 0fb339a2ab Updated PKGBUILD 2022-01-10 23:38:15 -05:00
RandyTheSilly 51ac1a49fd Update README.md 2022-01-10 23:29:18 -05:00
RandyTheSilly 87576338fd Updated changelogs for release 2022-01-10 23:20:36 -05:00
RandyTheSilly 6116de41b1 Bumped sshync version number 2022-01-10 23:13:42 -05:00
RandyTheSilly a218e77e41 Updated gen command to new notes system 2022-01-10 22:59:52 -05:00
RandyTheSilly e00fd64c66 Further prevention of /dev/shm file retention 2022-01-10 22:36:19 -05:00
RandyTheSilly e2f45c7cac Prevent /dev/shm files being generated before a keyboard interrupt 2022-01-10 22:23:21 -05:00
RandyTheSilly 700d5701fd Fixed temporary file deletion 2022-01-10 09:57:36 -05:00
RandyTheSilly ac6f6f279f Fixed editing a file that doesn't exist 2022-01-10 09:39:29 -05:00
RandyTheSilly 019aa58411 Combined print functions 2022-01-10 08:35:46 -05:00
RandyTheSilly 398ac8a04a Simplified input checking w/.lower() 2022-01-10 02:46:53 -05:00
RandyTheSilly d63c663dd0 Fixed downloading with special characters 2022-01-10 02:37:37 -05:00
RandyTheSilly 078d6026e0 Fixed downloading with special characters 2022-01-10 02:36:01 -05:00
RandyTheSilly 76c4fff520 Removed unnecessary line from man page 2022-01-10 02:21:10 -05:00
RandyTheSilly 2ba2dd57e4 Added man page 2022-01-10 02:14:55 -05:00
RandyTheSilly e64ef1103d Updated roadmap 2021-12-05 19:32:15 -05:00
RandyTheSilly d3971af85b Updated roadmap 2021-12-05 19:13:29 -05:00
RandyTheSilly 7840f47b9f Removed old reference to rsync in config string 2021-12-04 12:06:05 -05:00
RandyTheSilly 21785ce380 Updated roadmap 2021-12-02 20:54:26 -05:00
RandyTheSilly c716073525 Added roadmap for next update 2021-12-02 00:11:38 -05:00
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
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
RandyTheSilly 4cefccf4c6 Updated PKGBUILD 2021-10-07 23:14:46 -04:00
RandyTheSilly ea117c2cb5 Updated changelog and PKGBUILD 2021-10-07 23:12:11 -04:00
RandyTheSilly 0a74d36845 Update readme 2021-10-07 23:04:35 -04:00
RandyTheSilly 2bf1859bc7 Cleanup and security enhancements in preparation for release 5 2021-10-07 22:59:59 -04:00
RandyTheSilly e1e7254fc1 Fixed naming error 2021-10-07 17:05:40 -04:00
RandyTheSilly 338af44841 Added multi-line notes support 2021-10-07 16:15:02 -04:00
RandyTheSilly 5aa22c82fc Changed SSH key type to ed25519 2021-10-07 09:36:33 -04:00
RandyTheSilly 9e8c580bb7 Fixed issues with copy syntax (2) 2021-09-23 14:28:30 -04:00
RandyTheSilly 864caffbca Fixed issues with copy syntax 2021-09-23 14:19:18 -04:00
RandyTheSilly f82f3c78a0 Added roadmap for next update 2021-09-23 09:44:15 -04:00
RandyTheSilly 17812d5ca4 Added url to PKGBUILD 2021-09-15 19:22:05 -04:00
RandyTheSilly 5df1ae30a4 Updated PKGBUILD 2021-09-15 19:03:51 -04:00
RandyTheSilly 366c76d683 Fxed sync and remote entry deletion 2021-09-15 18:54:10 -04:00
RandyTheSilly 2f3807294a Updated PKGBUILD 2021-09-15 01:40:50 -04:00
RandyTheSilly c455a9a7fb Fixed gpg key prompt in config 2021-09-15 01:38:06 -04:00
RandyTheSilly 691aaab634 Fixed gpg key prompt in config 2021-09-15 01:37:04 -04:00
RandyTheSilly 0365c17a34 Added share folder 2021-09-15 01:15:13 -04:00
RandyTheSilly 87502ceb22 Added PKGBUILD, corrected typos 2021-09-15 01:14:05 -04:00
RandyTheSilly 330fa5f89e Re-organized repo 2021-09-15 01:01:22 -04:00
RandyTheSilly 11550f114e added exceptions, offline support, fixes, and lots of code cleanup 2021-09-15 00:54:43 -04:00
RandyTheSilly e8412405e6 removed unused files 2021-09-14 14:16:57 -04:00
RandyTheSilly 0340848447 condensed config files 2021-09-14 14:04:50 -04:00
RandyTheSilly 1bdef1382f fixed client-side deletion via ssh 2021-09-14 13:15:28 -04:00
RandyTheSilly e9bbc48c14 optimized /dev/shm string generation 2021-09-14 12:36:32 -04:00
RandyTheSilly 6be6d75000 completed implementation of clipboard support 2021-09-11 18:29:29 -04:00
RandyTheSilly 254aca0839 improved clipboard method 2021-09-11 16:45:28 -04:00
RandyTheSilly 3da92ff20b Merge branch 'main' of https://github.com/rwinkhart/rpass 2021-09-10 15:04:14 -04:00
RandyTheSilly ca0cf57ffe initial clipboard support 2021-09-10 15:03:35 -04:00
RandyTheSilly 72f36c5046 initial clipboard support 2021-09-10 14:54:33 -04:00
rwinkhart c253c5e2b7 Update README.md 2021-09-09 14:39:20 +00:00
RandyTheSilly 5c457e4ec0 Re-ordered config wizard for better rsync support 2021-09-08 00:54:00 -04:00
RandyTheSilly f06684798d Added version info argument 2021-09-08 00:13:50 -04:00
RandyTheSilly 04dbd0624f Merge branch 'main' of https://github.com/rwinkhart/rpass 2021-09-08 00:01:49 -04:00
rwinkhart 9e2aa21ab2 Delete .SRCINFO 2021-09-08 04:01:12 +00:00
rwinkhart 865841f1cd Delete PKGBUILD 2021-09-08 04:01:05 +00:00
RandyTheSilly 98b6d40c19 Fixed gpg decryption warnings 2021-09-07 23:59:58 -04:00
rwinkhart ae6726bb3c Update README.md 2021-09-08 03:46:44 +00:00
rwinkhart 5a78902700 Update README.md 2021-09-08 02:48:50 +00:00
rwinkhart ab815a1b77 Update README.md 2021-09-08 02:48:27 +00:00
rwinkhart 4c625bb978 Update README.md 2021-09-08 02:40:29 +00:00
rwinkhart 9f824ab72d Update README.md 2021-09-08 02:38:01 +00:00
rwinkhart 61026d0c28 Update README.md 2021-09-08 02:35:36 +00:00
18 changed files with 2212 additions and 814 deletions
-15
View File
@@ -1,15 +0,0 @@
pkgbase = rpass
pkgdesc = An rsync-based password manager and alternative to GNU pass
pkgver = 2021.09.07.pr3.1
pkgrel = 1
arch = x86_64
arch = aarch64
license = GPL3
depends = python
depends = gnupg
depends = openssh
depends = rsync
source = https://cloud.watergateserver.xyz/api/public/dl/6b0Wqz-J
sha512sums = f59cd1cd3c981b9424fba85bfd5e7b33e26a482d48b9b47a77be6f8e7cecbf078ec956a46b37db488d5173cd0a439f572ff06fc7d35cc3e9b0a7666e49cadeee
pkgname = rpass
-21
View File
@@ -1,21 +0,0 @@
# Maintainer: Randall Winkhart (Cuan) <idgr at tutanota dot com>
pkgname=rpass
pkgver=2021.09.07.pr3.1
pkgrel=1
pkgdesc="An rsync-based password manager and alternative to GNU pass"
arch=('x86_64' 'aarch64')
license=('GPL3')
depends=( python gnupg openssh rsync )
source=('https://cloud.watergateserver.xyz/api/public/dl/6b0Wqz-J')
sha512sums=('f59cd1cd3c981b9424fba85bfd5e7b33e26a482d48b9b47a77be6f8e7cecbf078ec956a46b37db488d5173cd0a439f572ff06fc7d35cc3e9b0a7666e49cadeee')
package() {
mv 6b0Wqz-J rpass-2021.09.07.pr3.1.tar.xz
tar xf rpass-2021.09.07.pr3.1.tar.xz -C "${pkgdir}"
chown -R "$USER" ${pkgdir}/var/lib/rpass
}
+100 -7
View File
@@ -1,14 +1,107 @@
# rpass
A 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 (all ISAs)
Arch Linux (x86_64, aarch64)
rpass is available in the Arch User Repository as 'rpass'.
sshyp releases are 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
```
Pre-built packages exist for Arch, Debian, and Termux. These can be downloaded from the releases page.
# Building
Since sshyp is written entirely in Python, it doesn't need to be compiled. It does, however, need to be packaged for installation.
A packaging script is included in the root directory of the repo in order to package sshyp for your distribution. To package sshyp from source, simply run:
```
git clone https://github.com/rwinkhart/sshyp.git
cd sshyp
./package.sh
```
The packaging script has been tested on Arch Linux with dpkg as a dependency for Debian and Termux packaging.
The AUR version and the packages attatched to the release tags were already packaged using this script.
Currently, the script can create packages for Arch (PKGBUILD), Debian, Termux, and generic. Packaging for other distributions coming soon.
# Usage
Upon initial installation (on both the server and client devices), be sure to run:
```
sshyp tweak
```
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.
Please note that decrypting and reading entries is disabled on server devices for security reasons. Only devices configured as clients can use the gpg key to decrypt entries.
All available options can be found with:
```
sshyp --help
```
Or alternatively, in the new manpage:
```
man sshyp
```
# Roadmap
Short-term Goals:
- create new file list w/color and w/o file extensions
- overhaul argument system
- fix lots of bugs!
- make lots of optimizations!
Medium-term Goals:
- 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
Currently, the entry list displays each entry with the file extension ".gpg" visible (which you do not type when reading, modifying, or creating an entry). This will be corrected when the new entry list is added.
Executable
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/python3
# sshync 2022.01.17.unreleased13
# external modules
from os import path, system, walk
from os.path import getmtime, join, expanduser
from sys import exit as s_exit
from pathlib import Path
# utility functions
def get_titles_mods(_directory, _destination, _user_data):
_title_list, _mod_list = [], []
Path(path.expanduser('~/.config/sshync')).mkdir(0o700, parents=True, exist_ok=True) # create config directory
# local fetching
if _destination == 'l':
open(expanduser('~/.config/sshync/database'), 'w').write('') # blanks out database file
for _root, _directories, _files in walk(_directory):
for _filename in _files:
_title_list.append(join(_root.replace(_directory, '', 1), _filename))
_mod_list.append(int(getmtime(join(_root, _filename))))
for _title in _title_list:
open(expanduser('~/.config/sshync/database'), 'a').write(str(_title) + '\n')
open(expanduser('~/.config/sshync/database'), 'a').write('^&*\n')
for _mod in _mod_list:
open(expanduser('~/.config/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 -i '{_user_data[5]}' -P {_user_data[2]} {_user_data[0]}@{_user_data[1]}:"
f"'{expanduser(f'/home/{_user_data[0]}/.config/sshync/database')}' '{expanduser('~/.config/sshync/')}'")
_titles, _sep, _mods = ' '.join(open(expanduser('~/.config/sshync/database')).readlines()).replace('\n', '')\
.partition('^&*')
_title_list, _mod_list = _titles.split(' ')[:-1], _mods.split(' ')[1:]
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', '')
return _user, _ip, _port, _local_dir, _remote_dir, _identity
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(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]}:"
f"'{_user_data[4]}{_title}' {_user_data[3]}{'/'.join(_title.split('/')[:-1]) + '/'}")
Executable
+555
View File
@@ -0,0 +1,555 @@
#!/usr/bin/python3
# external modules
from os import environ, listdir, path, remove, system
from shutil import copy, move, rmtree
from sys import argv, exit as s_exit
from pathlib import Path
import random
import sshync
import string
# utility functions
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 a random temporary folder for security and returns random names for the folder and temp file
_shm_folder_gen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
_shm_entry_gen = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
Path(tmp_dir + _shm_folder_gen).mkdir(0o700)
return _shm_folder_gen, _shm_entry_gen
def encrypt(_shm_folder, _shm_entry, _location):
system(f"gpg -r {str(gpg_id)} -e '{tmp_dir}{_shm_folder}/{_shm_entry}'")
move(f"{tmp_dir}{_shm_folder}/{_shm_entry}.gpg", f"{directory}{_location}.gpg")
rmtree(f"{tmp_dir}{_shm_folder}")
def edit_note(_shm_folder, _shm_entry):
lines = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}").readlines()
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(lines[0:3])
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'w').writelines(lines[4:-2])
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
edit_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n").read()
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'a').write('\n' + edit_notes + '\n\n')
# argument-specific functions
def tweak(): # runs configuration wizard
# storage/config directory creation
Path(path.expanduser('~/.password-pasture')).mkdir(0o700, parents=True, exist_ok=True)
Path(path.expanduser('~/.config/sshyp/devices')).mkdir(0o700, parents=True, exist_ok=True)
if not Path(f"{path.expanduser('~/.config/sshyp/tmp')}").exists():
if Path("/data/data/com.termux").exists():
system(f"ln -s '/data/data/com.termux/files/usr/tmp' {path.expanduser('~/.config/sshyp/tmp')}")
else:
system(f"ln -s /dev/shm {path.expanduser('~/.config/sshyp/tmp')}")
# device type configuration
_device_type = input('\nIs this installation for a client or for a server? (C/s) ')
if _device_type.lower() == 's':
open(path.expanduser('~/.config/sshyp/sshyp-device'), 'w').write(_device_type)
Path(path.expanduser('~/.config/sshyp/deleted')).mkdir(0o700, parents=True, exist_ok=True)
copy('/usr/bin/sshync.py', path.expanduser('~/'))
copy('/usr/bin/sshypRemote.py', path.expanduser('~/sshypRemote.py'))
print('\nMake sure the ssh service is running and properly configured.\n\nConfiguration complete!\n')
s_exit()
else:
# device type configuration
_device_type = 'c' # ensure device type flag is properly set
open(path.expanduser('~/.config/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.lower() != '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(path.expanduser('~/.config/sshyp/sshyp-gpg'), 'w').write(_gpg_id + '\n')
# lock file generation
open(path.expanduser('~/.config/sshyp/lock'), 'w')
system(f"gpg -r {str(_gpg_id)} -e {path.expanduser('~/.config/sshyp/lock')}")
remove(f"{path.expanduser('~/.config/sshyp')}/lock")
# ssh key configuration
_ssh_gen = (input('\nMake sure the ssh service on the remote server is running and properly configured.'
'\n\nSync support requires a unique ssh key. Would you like to have this automatically '
'generated? (Y/n) '))
if _ssh_gen.lower() != 'n':
system('ssh-keygen -t ed25519 -f ~/.ssh/sshyp')
else:
print(f"\nEnsure that the key file you are using is located at {path.expanduser('~/.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(path.expanduser('~/.config/sshyp/sshyp.sshync'),
path.expanduser('~/.password-pasture/'), f"/home/{_username_ssh}/.password-pasture/",
path.expanduser('~/.ssh/sshyp'), _ip, _port, _username_ssh)
# device name configuration
for _name in listdir(path.expanduser('~/.config/sshyp/devices')): # remove existing device name
remove(f"{path.expanduser('~/.config/sshyp/devices/')}{_name}")
print('\nIMPORTANT: This name MUST be unique amongst your client devices. '
'\nThis is used to keep track of which devices have up-to-date databases.\n')
_client_device_name = str(input('What would you like to name this device? '))
open(f"{path.expanduser('~/.config/sshyp/devices/')}{_client_device_name}", 'w')
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {_port} {_username_ssh}@{_ip} "
f"\"touch '/home/{_username_ssh}/.config/sshyp/devices/{_client_device_name}'\"")
print('\nConfiguration complete!\n')
def print_info(): # prints help text based on argument
if argument == 'help' or argument == '--help' or argument == '-h':
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")
elif argument == 'version' or argument == '-v':
print('\n////////////////////////////////////////////////////////')
print('/ /')
print('/ sshyp Copyright (C) 2021-2022 Randall Winkhart /')
print('/ /')
print('/ Version 2022.02.16.fr4.7 /')
print('/ The High-Tech Shears Update /')
print('/ /')
print('////////////////////////////////////////////////////////\n')
elif argument == 'license':
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')
elif argument == 'add':
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')
elif argument == 'edit':
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')
elif argument == 'copy':
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 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 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')
# check for deletions
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"python -c 'import sshypRemote"
f"; sshypRemote.deletion_check(\"'\"{client_device_name}\"'\")'\"")
system(f"sftp -p -q -i '{path.expanduser('~/.ssh/sshyp')}' -P {port} {username_ssh}@{ip}:"
f"'/home/{username_ssh}/.config/sshyp/deletion_database' {path.expanduser('~/.config/sshyp/')}")
try:
_deletion_database = open(path.expanduser('~/.config/sshyp/deletion_database')).readlines()
except (FileNotFoundError, IndexError):
print('\nThe deletion database does not exist or is corrupted.\n')
_deletion_database = None
s_exit()
for _file in _deletion_database:
if _file[:-1].endswith('/'):
try:
print(f"Removing folder {path.expanduser('~/.password-pasture/')}{_file[:-1]}...\n")
rmtree(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}")
except FileNotFoundError:
print('Folder does not exist locally.\n')
else:
try:
print(f"Removing entry {path.expanduser('~/.password-pasture/')}{_file[:-1]}...\n")
remove(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}.gpg")
except (FileNotFoundError, IsADirectoryError):
print('File does not exist locally.\n')
# check for new folders
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"python -c 'import sshypRemote"
f"; sshypRemote.folder_check()'\"")
system(f"sftp -p -q -i '{path.expanduser('~/.ssh/sshyp')}' -P {port} {username_ssh}@{ip}:"
f"'/home/{username_ssh}/.config/sshyp/folder_database' {path.expanduser('~/.config/sshyp/')}")
try:
_folder_database = open(path.expanduser('~/.config/sshyp/folder_database')).readlines()
except (FileNotFoundError, IndexError):
print('\nThe folder database does not exist or is corrupted.\n')
_folder_database = None
s_exit()
for _folder in _folder_database:
if Path(f"{path.expanduser('~')}{_folder[:-1]}").is_dir():
pass
else:
print(f"Adding folder {path.expanduser('~')}{_folder[:-1]}...\n")
Path(f"{path.expanduser('~')}{_folder[:-1]}").mkdir(0o700, parents=True, exist_ok=True)
# 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(path.expanduser('~/.config/sshyp/sshyp.sshync'))
def add_entry(): # adds a new entry
_shm_folder, _shm_entry = None, None # sets base-line values to avoid errors
_entry_name = str(input('\nName of entry: '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if argument == 'add note' or argument == 'add -n':
_shm_folder, _shm_entry = shm_gen()
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines('\n\n\n\n' + _notes + '\n\n')
elif argument == 'add password' or argument == 'add -p':
_username = str(input('Username: '))
_password = str(input('Password: '))
_url = str(input('URL: '))
_add_note = input('Add a note to this entry? (y/N) ')
_shm_folder, _shm_entry = shm_gen()
if _add_note.lower() == 'y':
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
else:
_notes = ''
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _password + '\n' + _url + '\n\n'
+ _notes + '\n\n')
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
def add_folder(): # creates a new folder
_folder_name = str(input('Name of new folder: '))
Path(directory + _folder_name).mkdir(0o700)
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}"
f"{_folder_name}'\"")
def rename(): # renames an entry or folder TODO delete original from server to prevent re-downloading
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
_shm_folder, _shm_entry = None, None # sets base-line values to avoid errors
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_entry_name = str(input('\nWhat file would you like to edit? '))
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print("\nYou are trying to edit a file that does not exist!\n")
s_exit()
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if argument == 'edit username' or argument == 'edit -u':
_detail = str(input('New Username: '))
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 0, _detail + '\n')
elif argument == 'edit password' or argument == 'edit -p':
_detail = str(input('New Password: '))
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 1, _detail + '\n')
elif argument == 'edit url' or argument == 'edit -l':
_detail = str(input('New URL: '))
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 2, _detail + '\n')
elif argument == 'edit note' or argument == 'edit -n':
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
edit_note(_shm_folder, _shm_entry)
remove(f"{directory}{_entry_name}.gpg")
encrypt(_shm_folder, _shm_entry, _entry_name)
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
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' or argument == 'gen -u':
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print("\nYou are trying to edit a file that does not exist!\n")
s_exit()
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.lower() == 's':
_pass_type = string.ascii_letters + string.digits
else:
_pass_type = string.ascii_letters + string.digits + string.punctuation
_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: '))
_add_note = input('Add a note to this entry? (y/N) ')
_shm_folder, _shm_entry = shm_gen()
if _add_note.lower() == 'y':
system(f"nano {tmp_dir}{_shm_folder}/{_shm_entry}-n")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
else:
_notes = ''
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_username + '\n' + _pass_gen + '\n' + _url + '\n\n'
+ _notes + '\n\n')
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
else:
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 1, _pass_gen + '\n')
remove(f"{directory}{_entry_name}.gpg")
encrypt(_shm_folder, _shm_entry, _entry_name)
system(f"gpg -d '{directory}{_entry_name}.gpg'")
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: '))
if not Path(f"{directory}{_read_entry}.gpg").is_file():
print("\nThe file does not exist!\n")
s_exit()
_shm_folder, _shm_entry = shm_gen()
system(f"gpg -d --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_read_entry}.gpg'")
_copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
if Path("/data/data/com.termux").exists(): # checks for Termux, Wayland, or X
if argument == 'copy username' or argument == 'copy -u':
system('termux-clipboard-set ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy password' or argument == 'copy -p':
system('termux-clipboard-set ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy url' or argument == 'copy -l':
system('termux-clipboard-set ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'")
elif argument == 'copy note' or argument == 'copy -n':
system('termux-clipboard-set ' + "'" + _copy_line[4].replace('\n', '').replace("'", "'\\''") + "'")
elif environ.get('WAYLAND_DISPLAY') == 'wayland-0':
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"{tmp_dir}{_shm_folder}")
def remove_data(): # deletes an entry from the server and flags it for local deletion on sync
print()
system(f"cd {directory}; ls -1 *") # TODO replace with new list
_entry_name = str(input('\nWhat would you like to delete? '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
try:
system(f"gpg -d --output {tmp_dir}sshyp.lock {path.expanduser('~/.config/sshyp/lock.gpg')}")
_unlock = open(f"{tmp_dir}sshyp.lock", 'r').readlines()
remove(f"{tmp_dir}sshyp.lock")
except FileNotFoundError:
print('\nAccess denied.\n')
s_exit()
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"python -c 'import sshypRemote"
f"; sshypRemote.delete(\"'\"{_entry_name}\"'\")'\"")
# program start sequence
# retrieve typed argument
argument_list = argv
i, argument = 0, ''
for _ in argument_list:
while i < len(argument_list) - 1:
i += 1
argument += argument_list[i] + ' '
argument = argument[:-1]
# import saved userdata
if argument != 'tweak':
device_type = ''
tmp_dir = path.expanduser('~/.config/sshyp/tmp/')
try:
device_type = open(path.expanduser('~/.config/sshyp/sshyp-device')).read().strip()
if device_type == 'c':
gpg_id = open(path.expanduser('~/.config/sshyp/sshyp-gpg')).read().strip()
ssh_info = sshync.get_profile(path.expanduser('~/.config/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/'
client_device_name = listdir(path.expanduser('~/.config/sshyp/devices'))[0]
except FileNotFoundError:
if device_type.lower() != 's':
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print("Not all necessary configuration files are present. Please run 'sshyp tweak'!")
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
s_exit()
else:
try:
tweak()
s_exit()
except KeyboardInterrupt:
print('\n')
s_exit()
# 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 == 'help' or argument == '--help' or argument == '-h' or argument == 'license' or argument == 'version' \
or argument == '-v' or argument == 'add' or argument == 'edit' or argument == 'copy':
print_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 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 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 \
!= 'version' and argument != '-v' and error == 0 and \
argument.startswith('/') is False:
sync()
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/python3
# external modules
from os import listdir, remove, walk
from os.path import expanduser
from shutil import rmtree
# utility functions
def delete(_file_path):
if _file_path.endswith('/'):
try:
rmtree(f"{expanduser('~/.password-pasture/')}{_file_path}")
except FileNotFoundError:
print('\nFolder does not exist remotely.')
else:
try:
remove(f"{expanduser('~/.password-pasture/')}{_file_path}.gpg")
except FileNotFoundError:
print('\nFile does not exist remotely.')
for _device_name in listdir(expanduser('~/.config/sshyp/devices')):
open(f"{expanduser('~/.config/sshyp/deleted/')}{_file_path.replace('/', '@')}^&*{_device_name}", 'w')
def deletion_check(_client_device_name):
open(expanduser('~/.config/sshyp/deletion_database'), 'w').write('')
for _file in listdir(expanduser('~/.config/sshyp/deleted')):
_file_path = _file.replace('@', '/').split('^&*')[0]
_device = _file.split('^&*')[1]
if _device == _client_device_name:
try:
remove(f"{expanduser('~/.config/sshyp/deleted/')}{_file}")
except FileNotFoundError:
pass
open(expanduser('~/.config/sshyp/deletion_database'), 'a').write(_file_path + '\n')
def folder_check():
open(expanduser('~/.config/sshyp/folder_database'), 'w').write('')
for _root, _directories, _files in walk(expanduser('~/.password-pasture')):
for _dir in _directories:
open(expanduser('~/.config/sshyp/folder_database'), 'a')\
.write(f"{_root.replace(expanduser('~'), '')}/{_dir}\n")
+1125
View File
File diff suppressed because it is too large Load Diff
+103
View File
@@ -0,0 +1,103 @@
.TH sshyp 1 "16 February 2022" "2022.02.16.fr4.7" "sshyp man page"
.SH NAME
sshyp \- A very simple self-hosted, synchronized password manager. Alternative to GNU pass.
.SH SYNOPSIS
sshyp [OPTION] [[FLAG]] [/<entry name>]
.SH DESCRIPTION
sshyp is a lightweight password and note management program written in Python. sshyp is used via CLI and is self-hosted with a client-server model. sshyp expects that you have access to a personal server with a properly configured ssh server, ideally accepting remote connections.
.SH EXAMPLES
Setting up sshyp for the first time or altering its configuration (also recommended after major updates):
sshyp tweak
*follow the prompts
Reading an existing entry saved as ~/.password-pasture/development/github.gpg:
sshyp /development/github
Copying the password of an existing entry saved as ~/.password-pasture/financial/bank.gpg:
sshyp copy -p
*answer the prompt with "/financial/bank"
*enter decryption password
Editing the username of an existing entry saved as ~/.password-pasture/game.gpg:
sshyp edit -u
*answer the first prompt with "game"
*follow the prompts
Making a new entry using the built-in password generator:
sshyp gen
*follow the prompts
Creating a note-only entry:
sshyp add -n
*follow the prompts
Syncing entries with the server:
sshyp sync
Removing an existing folder saved as ~/.password-pasture/social:
sshyp shear
*when prompted for what to delete, since you are deleting a folder, be sure to enter your choice with a following "/", e.g. "social/" or "/social/"
.SH OPTIONS
In order to quickly read an existing entry, just run "sshyp </entry name>".
Options for other operations are as follows:
help/--help/-h bring up the help menu
version/-v display sshyp version info
tweak configure sshyp
add add an entry
gen generate a new password
edit edit an existing entry
copy copy details of an entry to your clipboard
shear/-rm delete an existing entry
sync/-s manually sync the entry directory via sshync
.SH FLAGS
add:
password/-p add a password entry
note/-n add a note entry
folder/-f add a new folder for entries
edit:
rename/relocate/-r rename or relocate an entry
username/-u change the username of an entry
password/-p change the password of an entry
note/-n change the note attached to an entry
url/-l change the url attached to an entry
copy:
username/-u copy the username of an entry to your clipboard
password/-p copy the password of an entry to your clipboard
url/-l copy the URL of an entry to your clipboard
note/-n copy the note of an entry to your clipboard
gen:
update/-u generate a password for an existing entry
.SH LIMITATIONS
The following limitations will be corrected in future updates:
Currently, the entry list displays each entry with the file extension ".gpg" visible (which you do not type when reading, modifying, or creating an entry). This will be corrected when the new entry list is added.
The following characters/character sequences are not supported in entry/folder titles:
@ ^&*
.SH SETUP
sshyp operates on a client-server model, and thus requires you to have access to your own server (whether it be a physical home server or a cloud rental) with remote access via SSH.
The sshyp package includes modes for operating on both client and server devices, so only one package is necessary.
Server setup:
Configure an openssh server (if sshyp was installed from the Debian package, the ssh server was not installed as a dependency and needs to be installed manually)
Allow remote access to the SSH server w/public key authentication (disabling password-only authentication recommended)
Install sshyp
Run "sshyp tweak" and set the device type as server
Done!
Client setup:
Install sshyp
Run "sshyp tweak" and follow the prompts
Copy the generated public SSH key to the server using preferred method (manually adding to authorized_keys, ssh-copy-id, etc.)
**this step will be automated in the future: if an entry library already exists on the server, make sure to manually recreate any folders that exist on the server in the ~/.password-pasture directory
If you already have entries on the server, sync them using "sshyp sync"
Done!
Please note that the server setup intentionally does not allow the reading of entries (it does not allow adding a gpg decryption key). For security purposes, only clients can read entries.
.SH AUTHOR
Randall Winkhart (https://github.com/rwinkhart)
Executable
+125
View File
@@ -0,0 +1,125 @@
#!/bin/bash
# This script packages sshyp (from source) for various Linux environments.
# NOTE It is recommended to instead use the latest officially packaged and tagged release.
# NOTE If using Arch, it is recommended to install from the AUR or from the PKGBUILD attatched to the latest official release.
# NOTE As of release fr4, sshync will become a separate package and thus a dependency for sshyp. sshync is automatically installed with the PKGBUILD version.
echo -e '\nOptions (please enter the number only):'
echo -e '\nDistribution Packages:\n\n1. Debian\n2. Termux\n3. Generic (used for PKGBUILD/APKBUILD)'
echo -e '\nBuild Scripts:\n\n4. Alpine Linux (APKBUILD)\n5. Arch Linux (PKGBUILD, also builds local generic package)'
echo -e '\nOther:\n\n6. All (generates all distribution packages and build scripts)\n'
read -n 1 -r -p "Distribution: " distro
echo -e '\n\nThe value entered in this field will only affect the version reported to the package manager. The latest source is used regardless.\n'
read -r -p "Version number: " version
echo -e '\nThe value entered in this field will only affect the revision number for build scripts.\n'
read -r -p "Revision number: " revision
if [ "$distro" == "4" ] || [ "$distro" == "5" ] || [ "$distro" == "6" ]; then
echo -e '\nOptions (please enter the number only):'
echo -e '\n1. GitHub Release Tag\n2. Local\n'
read -r -p "Source (for build scripts): " source
if [ "$source" == "1" ]; then
source='https://github.com/rwinkhart/sshyp/releases/download/v$pkgver/sshyp-$pkgver.tar.xz'
else
source=local://sshyp-"$version".tar.xz
fi
fi
mkdir -p packages
if [ "$distro" == "1" ] || [ "$distro" == "6" ]; then
echo -e '\nPackaging for Debian...\n'
mkdir -p packages/debiantemp/sshyp_"$version"-"$revision"_all/{DEBIAN,usr}
mkdir -p packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1
echo "Package: sshyp
Version: $version
Section: utils
Architecture: all
Maintainer: Randall Winkhart <idgr at tutanota dot com>
Description: A light-weight, self-hosted, synchronized password manager
Depends: python3, gnupg, openssh-client, nano, xclip, wl-clipboard
Priority: optional
Installed-Size: 35
" > packages/debiantemp/sshyp_"$version"-"$revision"_all/DEBIAN/control
cp -r bin packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/
cp -r share packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/
cp extra/manpage packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
gzip packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
dpkg-deb --build --root-owner-group packages/debiantemp/sshyp_"$version"-"$revision"_all/
mv packages/debiantemp/sshyp_"$version"-"$revision"_all.deb packages/
rm -rf packages/debiantemp
echo -e "\nDebian packaging complete.\n"
fi
if [ "$distro" == "2" ] || [ "$distro" == "6" ]; then
echo -e '\nPackaging for Termux...\n'
mkdir -p packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/{data,DEBIAN}
mkdir -p packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1
echo "Package: sshyp
Version: $version
Section: utils
Architecture: all
Maintainer: Randall Winkhart <idgr at tutanota dot com>
Description: A light-weight, self-hosted, synchronized password manager
Depends: python, gnupg, openssh, nano, termux-api, termux-am
Priority: optional
Installed-Size: 35
" > packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/DEBIAN/control
cp -r bin packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/
cp -r share packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/
cp extra/manpage packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1
gzip packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1
dpkg-deb --build --root-owner-group packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/
mv packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux.deb packages/
rm -rf packages/termuxtemp
echo -e "\nTermux packaging complete.\n"
fi
if [ "$distro" == "3" ] || [ "$distro" == "5" ] || [ "$distro" == "6" ]; then
echo -e '\nPackaging as generic...\n'
mkdir -p packages/archtemp/usr
cp -r bin packages/archtemp/usr/
cp -r share packages/archtemp/usr/
mkdir -p packages/archtemp/usr/share/man/man1
cp extra/manpage packages/archtemp/usr/share/man/man1/sshyp.1
gzip packages/archtemp/usr/share/man/man1/sshyp.1
tar -C packages/archtemp -cvf packages/sshyp-"$version".tar.xz usr/
rm -rf packages/archtemp
sha512="$(sha512sum packages/sshyp-"$version".tar.xz | awk '{print $1;}')"
echo -e "\nsha512 sum:\n$sha512"
echo -e "\nGeneric packaging complete.\n"
fi
if [ "$distro" == "5" ] || [ "$distro" == "6" ]; then
echo -e '\nGenerating PKGBUILD...'
echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com>
pkgname=sshyp
pkgver="$version"
pkgrel="$revision"
pkgdesc='A light-weight, self-hosted, synchronized password manager'
url='https://github.com/rwinkhart/sshyp'
arch=('any')
license=('GPL3')
depends=(python gnupg openssh nano xclip wl-clipboard)
source=(\""$source"\")
sha512sums=('"$sha512"')
package() {
tar xf sshyp-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\""
}
" > packages/PKGBUILD
echo -e "\nPKGBUILD generated.\n"
fi
if [ "$distro" == "4" ]; then
echo -e '\nThis packaging format is not yet supported, but will be in the near future!\n'
fi
+53
View File
@@ -0,0 +1,53 @@
sshyp 2022.02.16.fr4.7
The High-Tech Shears Update - Patch 7
This release enables recursive folder syncing.
Note: Upgrading from releases older than fr4.7 requires the configuration ("sshyp tweak") to be re-done, as the configuration process has changed.
Changes:
- re-wrote folder checking function to fetch subdirectories recursively
- added in user-facing messages for when folders are being synced or entries are being removed
- fixed a typo preventing folder syncing from working (actually tested this time)
&&
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
^ this includes the new file list and thematic text art
sshync:
** sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
The full history of changes to "sshyp" can be found on the following page:
https://raw.githubusercontent.com/rwinkhart/sshyp/main/extra/changelog-total
Legend:
** = feature/change not yet finished/implemented
- = feature/change implemented and pushed upstream
^ = note regarding the above feature/change
&& = visual separater for patch notes for different planned major version releases
@@ -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
-605
View File
@@ -1,605 +0,0 @@
#!/usr/bin/python
# rpass 2021.09.07.pr3.1
# rpass is the gnu pass alternative for those who don't want to use git
# rpass is freely licensed for modification and redistribution under the GNU General Public License V3
from os import system
from os import remove
from os import environ
from shutil import move
from shutil import rmtree
from sys import argv
import random
import string
def clear():
print("\n" * 100)
def term(cmd):
_ = system(cmd)
def replace_line(file_name, line_num, text):
lines = open(file_name, 'r').readlines()
lines[line_num] = text
out = open(file_name, 'w')
out.writelines(lines)
out.close()
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)
def rsyncup():
term(rsyncupp + ' ' + directory + ' ' + usernamessh + '@' + ip + ':' + directoryssh)
def rsyncdown():
term(rsyncdownn + ' ' + usernamessh + '@' + ip + ':' + directoryssh + ' ' + directory)
# argument - filter the argument to usable text - some replacements are only done once to prevent interference
argument = str(argv).replace('[', '', 1).replace(']', '', 1).replace(',', '').replace("'", '') \
.replace(' ', '', 1).replace('/usr/bin/', '', 1).replace('rpass', '', 1)
# startup help
if argument == '':
clear()
print("use 'help', '--help', or '-h' to see a list of commands")
print()
print('<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>')
print("If you are receiving errors, run 'rpass config' and go through the guided setup wizard.")
print('This MUST be done before rpass will function!!')
print('<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>')
print()
print('rpass is currently early software with very little polish')
print()
# help
if argument == 'help' or argument == '--help' or argument == '-h':
print()
print('rpass Copyright (C) 2021 Randall Winkhart')
print("This program comes with ABSOLUTELY NO WARRANTY; for details type `rpass show w'. This is free software, "
"and you are welcome to redistribute it under certain conditions; type `rpass show c' for details.")
print()
print('USAGE: rpass [/<entry name>] [OPTION] [FLAG]')
print()
print('Options: ')
print('help/--help/-h bring up this menu')
print('config configure rpass')
print('add add an entry')
print('gen generate a new password')
print('edit edit an existing entry')
print('remove/-rm delete an existing entry')
print('sync/-s manually sync the entry directory via rsync')
print()
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('gen:')
print(' update/-u generate a password for an existing entry')
print()
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!")
print()
# 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()
print('https://opensource.org/licenses/GPL-3.0')
print()
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.')
print()
# config
if argument == 'config':
print()
directorychoice = str(input('Would you like to use the default entry directory (~/.rpass-store/)? (Y/n) '))
if directorychoice != 'n':
with open("/var/lib/rpass/rpassdir", 'w') as f:
f.write('/home/' + environ.get('USER') + '/.rpass-store/' + '\n')
if directorychoice == 'n':
print()
print('Format: /this/path/ends/with/a/slash/')
print()
directory = str(input('Please input a custom directory: '))
with open("/var/lib/rpass/rpassdir", 'w') as f:
f.write(directory + '\n')
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: '))
with open("/var/lib/rpass/rpassgpg", 'w') as f:
f.write(gpgid + '\n')
if gpgpresent != 'y':
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':
term('gpg --full-generate-key')
print()
gpgid = str(input('Please input the ID of your gpg key: '))
with open("/var/lib/rpass/rpassgpg", 'w') as f:
f.write(gpgid + '\n')
if gpggen == 'n' or gpggen == 'N':
exit()
print()
syncsetup = str(input('Would you like to configure rsync over ssh for entry backup and syncing? (Y/n) '))
if syncsetup != 'n':
print()
sshgen = str(input('rsync support requires a unique ssh key. Would you like to have this '
'automatically generated? (Y/n) '))
if sshgen != 'n':
term('ssh-keygen -f ~/.ssh/rpass')
print()
print('The server device(s) should be configured first.')
print()
devicetype = str(input('Will this be a client or a server device? (c/S) '))
if devicetype != 'c':
print()
print('Make sure the ssh service is running and that the proper port is forwarded.')
if devicetype == 'c':
print()
print('Make sure the ssh service is running and that the proper port is forwarded on the remote server.')
print('Example input: 10.10.10.10:9999')
print()
ip_port = str(input('What is the IP and ssh port of the remote server? '))
print()
usernamessh = str(input('What is the username of the remote server? '))
ip, sep, port = ip_port.partition(':')
with open("/var/lib/rpass/rpassuserssh", 'w') as f:
f.write(usernamessh + '\n')
with open("/var/lib/rpass/rpassrsyncup", 'w') as f:
f.write('rsync -v -H -r -l -t -p -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + '\n')
with open("/var/lib/rpass/rpassrsyncdown", 'w') as f:
f.write('rsync -v -H -r -l -t -p --delete -e ' + '"ssh -i ~/.ssh/rpass -p ' + port + '" ' + '\n')
with open("/var/lib/rpass/rpassip", 'w') as f:
f.write(ip + '\n')
print()
print('Default directory: ' + '/home/' + usernamessh + '/.rpass-store/')
print()
directoryssh = str(input('Is the remote server using the default password directory? (Y/n) '))
if directoryssh != 'n':
directoryssh = ('/home/' + usernamessh + '/.rpass-store/')
if directoryssh == 'n' or directoryssh == 'N':
print()
print('Format: /this/path/ends/with/a/slash/')
print()
directoryssh = str(input('What directory is the server using?: '))
with open("/var/lib/rpass/rpassdirssh", 'w') as f:
f.write(directoryssh + '\n')
# import userdata
with open("/var/lib/rpass/rpassgpg") as f:
gpgid = f.read().strip()
with open("/var/lib/rpass/rpassdir") as f:
directory = f.read().strip()
term('mkdir -p ' + directory)
with open("/var/lib/rpass/rpassdirssh") as f:
directoryssh = f.read().strip()
with open("/var/lib/rpass/rpassrsyncup") as f:
rsyncupp = f.read().strip()
with open("/var/lib/rpass/rpassrsyncdown") as f:
rsyncdownn = f.read().strip()
with open("/var/lib/rpass/rpassip") as f:
ip = f.read().strip()
with open("/var/lib/rpass/rpassuserssh") as f:
usernamessh = f.read().strip()
if argument == '':
print()
term('cd ~/.rpass-store; ls -1 *')
print()
readentry = str(input('Entry to read: '))
clear()
term('gpg -d ' + directory + "'" + readentry.replace('/', '', 1) + "'" + '.gpg')
print()
# 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()
print('USAGE: 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')
print()
if argument == 'add note' or argument == 'add -n':
clear()
entryname = str(input('Name of note: '))
notes = str(input('Contents of note: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines('\n\n\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines('\n\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines('\n\n\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
if argument == 'add password' or argument == 'add -p':
clear()
entryname = str(input('Name of service: '))
username = str(input('Username: '))
password = str(input('Password: '))
url = str(input('URL: '))
notes = str(input('Additional notes: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + password + '\n' + url + '\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + password + '\n' + url + '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + password + '\n' + url + '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
if argument == 'add folder' or argument == 'add -f':
newfolder = str(input('Name of new folder: '))
term('mkdir ' + "'" + directory + newfolder + "'")
# edit
if argument == 'edit':
print()
print('USAGE: 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(' note/-n change the note attached to an entry')
print(' url/-l change the url attached to an entry')
print()
if argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit -r':
clear()
term('cd ~/.rpass-store; 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')
if argument == 'edit username' or argument == 'edit -u':
clear()
term('cd ~/.rpass-store; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
username = str(input('New Username: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg --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 --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 --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' + "'")
if argument == 'edit password' or argument == 'edit -p':
clear()
term('cd ~/.rpass-store; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
password = str(input('New Password: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg --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 --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 --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' + "'")
if argument == 'edit url' or argument == 'edit -l':
clear()
term('cd ~/.rpass-store; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
url = str(input('New URL: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg --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 --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 --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' + "'")
if argument == 'edit note' or argument == 'edit -n':
clear()
term('cd ~/.rpass-store; ls -1 *')
print()
entryname = str(input('What file would you like to edit? '))
notes = str(input('New Note: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
term('gpg --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
folder + '/' + folderentry + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 3, notes + '\n')
remove(directory + folder + '/' + folderentry + '.gpg')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
term('gpg --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory +
entryname.replace('/', '', 1) + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 3, notes + '\n')
remove(directory + entryname.replace('/', '', 1) + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
term('gpg --output /dev/shm/' + shmfolder + '/' + shmentry + ' ' + directory + entryname + '.gpg')
replace_line('/dev/shm/' + shmfolder + '/' + shmentry, 3, notes + '\n')
remove(directory + entryname + '.gpg')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
# gen
if argument == 'gen':
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: '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
folder, sep, folderentry = entryname.replace('/', '', 1).partition('/')
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + passgen + '\n' + url + '\n' + notes + '\n\n')
encryptfolder()
term('gpg -d ' + directory + folder + '/' + "'" + folderentry + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + passgen + '\n' + url + '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname.replace('/', '', 1) + '.gpg' + "'")
else:
with open('/dev/shm/' + shmfolder + '/' + shmentry, 'w') as f:
f.writelines(username + '\n' + passgen + '\n' + url + '\n' + notes + '\n\n')
encrypt()
term('gpg -d ' + directory + "'" + entryname + '.gpg' + "'")
if argument == 'gen update' or argument == 'gen -u':
clear()
term('cd ~/.rpass-store; 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) '))
# generate random strings for /dev/shm
shmfolder = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
shmentry = ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits)
for _ in range(random.randint(10, 30)))
term('mkdir -p /dev/shm/' + shmfolder)
# end string and folder generation
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 --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 --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 --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' + "'")
# remove
if argument == 'remove' or argument == '-rm':
clear()
term('cd ~/.rpass-store; ls -1 *')
print()
entryname = str(input('What would you like to delete? '))
if entryname.startswith('/'):
if entryname.replace('/', '', 1).__contains__('/'):
remove(directory + entryname.replace('/', '', 1) + '.gpg')
else:
rmtree(directory + entryname.replace('/', '', 1))
else:
remove(directory + entryname + '.gpg')
# 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 argument.__contains__('add') or argument.__contains__('-rm') or argument.__contains__('remove') or argument. \
__contains__('edit') or argument.__contains__('gen') or argument == 'sync' or argument == '-s':
rsyncup()
rsyncdown()
print()
print('Please note that as of this time, entries can only be deleted if removed from the central server in a '
'client-server scenario. This will be adjusted soon.')
print()
-165
View File
@@ -1,165 +0,0 @@
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass-2021.09.08.pr4
The Housekeeping Update - Fourth public release of rpass
This release focuses primarily on polishing rpass and tying up loose ends before
making any major changes in the future.
New features:
**overhaul error message using exceptions
**add exceptions for unknown arguments
**make clean, colorful file list by exporting to document and removing extensions
**make a manpage
**multi-line notes?
Changes:
**move project to github
**change gpg prompt to get rid of expiration date
**get rid of gpg decryption warnings
**optimize code (specifically for when there is no folder but there is a slash)
**add version info argument
**update rsync config wizard
**properly comment the code
**validate for Python 3.10
Planned for next update (The Secret Update):
- allow to function as alternative to gnome keyring (libsecret integration)
Planned, no timeline:
- create separate gui frontend targetting mobile devices (first linux phones, maybe android at a later date - 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)
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.09.07.pr3.1
The Sync and Foundations Update - Hotfix
Changes:
- gpg configuration now prompts for expiration, rather than defaulting to two years
- rsync is now configured to not delete anything from any remote device when uploading
^ this behavior may be modified in the future - this is a quick fix to prevent data loss
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.09.07.pr3
The Sync and Foundations Update - Third public release of rpass.
As of this version, rpass has its intended base set of features and is considered usable.
It will now primarily recieve bug fixes and polish updates to prepare it to go
cross-platform and to make it compatible with GUI frontends.
New features:
- rsync support!
- new entry format with URL field (for future use)
- the temporary directory (/dev/shm) for editing entries has been somewhat secured
Changes:
- 'rpass edit relocate' is now properly bound
- dropped the use of 'echo'
- added 'rsync' and 'openssh' as dependencies
- fixed a bug with deleting entries from folders
- entry directory now has more secure permissions
^ these permissions are re-enforced every time rpass is used
- fixed some small typos and potential bugs, made some small optimizations
Planned for next update (The Housekeeping Update):
- move to github
- get rid of gpg decryption warnings
- proper error messages using 'except'
- add exceptions for unknown arguments
- cleanup file list by exporting to document and removing .gpg, adding color
- add a manpage
- allow notes to be multiple lines long (break lines after so many characters)
- validate for Python 3.10
- properly comment the code
Planned, no timeline:
- allow to function as alternative to gnome keyring (libsecret integration)
- create separate gui frontend targetting mobile devices (first linux phones, maybe android at a later date - 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)
- ability to pass entries as arguments for more functions
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.09.02.pr2
The Folder Update - Second public release of rpass.
New features:
- entry and folder titles can now have spaces and be as long as you want
- entires and folders can now be deleted with 'rpass remove' or 'rpass -rm'
- entries now properly save to folders via 'rpass add' and should no longer throw errors
- entries saved in folders are now readable
- existing entries can now be moved to, from, and between folders
- previews are now shown after creating or editing an entry
Changes:
- every pre-existing function of rpass has been updated to work with the new folder system
- dropped awk as a dependency
- removed 'argument' file in /var/lib/rpass
- reduced unneccessary characters in argument parsing to decrease compatibility issues
- ensured all user input is handled correctly as a string or an integer
- lots of miscellaneous optimizations
Expected for next update (The rsync Update):
- rsync (over ssh) support!
^ including any fixes, changes, or optimizations necessary to make that happen
- new file formatting with support for URLs
^all entries created in new format should be compatible with future versions of rpass
- secure /dev/shm with random text generator
Expected for the next (next) update (The Housekeeping Update)
- get rid of gpg decryption warnings
- proper error messages using 'except'
- add exceptions for unknown arguments
- cleanup file list by exporting to document and removing .gpg, adding color
Planned, no timeline:
- make platform agnostic (basically, add windows support)
- create separate gui frontend targetting mobile devices (first linux phones, android at a later date)
^ the gui will also function on desktop linux
- ability to pass entries as arguments for more functions
- auto-completion on tab
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
rpass 2021.09.01.pr1.1
First public release of rpass.
Early build, missing critical features (e.g. sync support and the ability to have spaces in filenames).
What is currently functional:
- guided configuration wizard
- generate passwords
- add existing passwords
- make notes
- sort notes and passwords into folders
- gpg encryption
- edit password/note entries
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
View File
View File
View File
View File
View File