Compare commits

...
188 Commits
Author SHA1 Message Date
RandyTheSilly 3a6655e977 Removed '~' from generated filename character pool to avoid issues with quick-unlock
Former-commit-id: bcb77c5030c48693bcd0a479f7576e6ddc4d6729 [formerly 109141a266]
Former-commit-id: b7bd4134b3bee5760aaa56064a1ad9b29957fa1c
2022-11-06 13:25:35 -05:00
RandyTheSilly 9d1f0a065b Corrected date in man page
Former-commit-id: 61310403c6cfe504e1b8453c29e564459cd08bef [formerly 57cc730d92]
Former-commit-id: 3f614eb15a35f252188ee0a807c5b324ce409084
2022-11-06 11:21:21 -05:00
RandyTheSilly 8298966d8f Fixed documentation location in Haiku
Former-commit-id: 4d7a9a8f9b18efd21cb4273dc2dcaed189fdd21e [formerly 790ac573e5]
Former-commit-id: 2d7cb8bb642a96080be8c6396506cd7257d76bca
2022-11-06 10:50:25 -05:00
RandyTheSilly d4d9fb88fd Updated quick-unlock failure error message
Former-commit-id: bd491483ab2b0d09ccfb6c007c786262553d66a7 [formerly 8b8e0c510f]
Former-commit-id: 6a64c402f0687bc3babb0370cd0785a6b2e487f7
2022-11-06 00:49:44 -04:00
RandyTheSilly 2beeb1dc38 Only check whitelist status if the gpg agent is locked (speeds up successive quick-unlock attempts)
Former-commit-id: 57486bc120fc8734cbaf1694655ad9bc14c3276b [formerly 0b0c8a37d1]
Former-commit-id: 171de872a6f4c1f08f151d8b287d1584ac4f7061
2022-11-06 00:43:25 -04:00
RandyTheSilly 86ad4e5cad Added instructions for enabling Bash completions
Former-commit-id: 35b317ff508a4da2c1052cbda230be4e4af42985 [formerly 5fa30fa770]
Former-commit-id: c48091e8a5849359e2a6ef97970d30c008d6a70d
2022-11-06 00:15:28 -04:00
RandyTheSilly e55c812a06 Fixed device id fetching (and quick-unlock verification) on Haiku
Former-commit-id: 2ed945a3fea77e8be59bb2c8c92361cf23f950e8 [formerly 8b3bf04945]
Former-commit-id: 0df6eeb06ab5d68c8252a1b4515895d1eed313ff
2022-11-05 23:57:09 -04:00
RandyTheSilly a0351d19d3 Fixed FreeBSD package symlink target
Former-commit-id: b3d5912d8e12ecea8234ca071cf242fc4b4411cf [formerly 24be16faaa]
Former-commit-id: 2ac9997b4e22f2a9f5d4ffcef75476ce1ae24318
2022-11-05 22:42:53 -04:00
RandyTheSilly 90c15bcda8 Specified changelog location in Fedora package
Former-commit-id: b16bfc43bd29de0ff64d081ec33ffccd86a63e0c [formerly 446cab94c2]
Former-commit-id: d8886c635b20705e8188e14d4bbc8a780e6c1afc
2022-11-05 22:39:28 -04:00
RandyTheSilly cb754c5ba7 Removed executable bits where they are not needed
Former-commit-id: 26ea77aa4734c759aa7e68607250a74ea9d57b71 [formerly e3af035bce]
Former-commit-id: b3acead7183e5c60258b3e0ae9da861f4896f649
2022-11-05 22:33:48 -04:00
RandyTheSilly 9979de26d0 Fixed options/flags layout in man page
Former-commit-id: bcfb14f5de98ae07a743a0d3e3efe2911e594259 [formerly 687a606160]
Former-commit-id: a0c3a8727d5adcc750bfa57305102a23778c42af
2022-11-05 19:40:00 -04:00
RandyTheSilly 4207ecb555 Update 'whitelist del' example to match 'whitelist add' example
Former-commit-id: 16e37f29fe93494f41b82d8bb0bc8cc4f2dc9a59 [formerly e840b9def0]
Former-commit-id: ce1baa1ec004251186d24e228c91608c4641f3ea
2022-11-05 19:32:01 -04:00
RandyTheSilly 8bcfd3fcd8 Fix spacing between exit codes in man page
Former-commit-id: 10708f1512aa4f7aa0d4c410d8d204e27c83eb2f [formerly 486fc39f22]
Former-commit-id: 91a167647b61de66301ab7bf14046637057ec4f3
2022-11-05 19:28:27 -04:00
RandyTheSilly 78588f686e Update whitelist add example in man page to match new string generation
Former-commit-id: dd8e68e426c0a54c038551246877366959bd82fc [formerly a63d1caa2e]
Former-commit-id: d020cf6afd738db53dfde8f0bcd09aedf62b13cc
2022-11-05 19:27:20 -04:00
RandyTheSilly 4753bb4c37 Update synopsis in man page
Former-commit-id: c0b0484f0b221484edda25620844db8414d5e3cd [formerly c2639d1f42]
Former-commit-id: d88298469cb341750174cc9d3c25d2d3ab39056a
2022-11-05 19:22:39 -04:00
RandyTheSilly 81ccdf71ea Fixed visual issue with version info screen
Former-commit-id: 62838cdd5811c70bc60c92803971f4c4e3b2326a [formerly 9cd5066cc9]
Former-commit-id: 326b58542b773f86e333ca6a9f2f07a2c267557a
2022-11-05 19:12:51 -04:00
RandyTheSilly 67eb1a44ca Update documentation for v1.2.0
Former-commit-id: 6068da810b16810c8afc0322cdd26fea734e3671 [formerly 517d2a3d22]
Former-commit-id: a8b3385517fe0f3bc33b7ede1951bae56cd3a265
2022-11-05 18:27:43 -04:00
RandyTheSilly 8af7de10a7 Added a packaging option to create all packages buildable on Arch Linux
Former-commit-id: c8ec6a71c06308ffd9bfc82061c2c8df18c8755f [formerly 80594712c7]
Former-commit-id: e8b9266385f7e2a64de49a863ccb89305f537712
2022-11-05 17:56:14 -04:00
RandyTheSilly 3108a072dd Fixed editing entries with new string generation
Former-commit-id: 957b2fd14635380ebcc1639e60bff0ccb8a7ed13 [formerly ca983d4992]
Former-commit-id: 9e6461835b8e7f2111fa64f5759b88fb00a8cb62
2022-11-05 15:34:19 -04:00
RandyTheSilly 65be0eaf6f Allow complex string generation for /dev/shm and device ids
Former-commit-id: 534577ba9d348aa3bfbce63a940229594a2ae68d [formerly 0614c2c83b]
Former-commit-id: c28b84e388cb9969a881a2a0ab15dfd814875a47
2022-11-05 15:21:30 -04:00
RandyTheSilly bb34025c31 Removed generated password length limit
Former-commit-id: ac2d03db87329e939ef6a0a9494653f53c160348 [formerly 900f216ac0]
Former-commit-id: ad17b1a2d026ab6ee221dfb260acb6a8a79200de
2022-11-05 14:01:49 -04:00
RandyTheSilly 278231fe40 Several fixes to allow the Haiku package to work again
Former-commit-id: a1babda0d16b3a264a53936fd76f79d00b56976a [formerly 022ad9ef6d]
Former-commit-id: a3a64fe962fd866bae3b5a8293293f9bad211994
2022-11-04 00:30:48 -04:00
RandyTheSilly 7356777e50 Made spacing in server help menus consistent with client help menus
Former-commit-id: 6b5209753e1a4d91de9f058bd4003def53b9e44c [formerly a1d5c8607c]
Former-commit-id: f1dc1e65d8eb65b58c87be822e1540e6862fce57
2022-11-03 22:58:35 -04:00
RandyTheSilly 5a33eb26f0 Fedora now only requires openssh-clients, rather than the openssh meta package
Former-commit-id: 320ec033563f9bf6d246c82ba504ee29085dfb5f [formerly 942febfac9]
Former-commit-id: ec41cf2e719ad9127ed84322f91248075e52ccbc
2022-11-03 22:47:58 -04:00
RandyTheSilly d796c48ede Made exit codes more specific to their errors
Former-commit-id: 62c004c84333a8b8645ea3247fdb56c1509a36f9 [formerly 33f7330886]
Former-commit-id: 0d849ab1792d4c960cf632f75a28feba5610f57e
2022-10-26 13:32:23 -04:00
RandyTheSilly b1fd934b96 Added bash-completion as an optional dependency where applicable
Former-commit-id: 2ad3b6bf53ac4c211a3e06079e0b32d7c362949f [formerly 07394c1740]
Former-commit-id: a985cf7c1230bc4f0f821ad83e689ddd769ba8d0
2022-10-25 23:10:51 -04:00
RandyTheSilly 9848d38a0b Fixed quick-unlock requirng passphrase regardless of whether or not it is needed - again
Former-commit-id: 53325cbf8c6f46d4e83c4e9ed4b9f9d4b1196bd5 [formerly a26ca86977]
Former-commit-id: 21fb1f899370f428ea08e1e5bb50bc2610e00983
2022-10-25 11:53:52 -04:00
RandyTheSilly 2ab409e95e Require _client_device_id as parameter to whitelist_verify (for extension support)
Former-commit-id: 608cd556ac34c6d64a0559398a43c180e41e1510 [formerly 51d99992a5]
Former-commit-id: d0e316a16321a13972be7233c88ffb61d5f5c3f7
2022-10-24 15:31:06 -04:00
RandyTheSilly 64d46f1746 Initial enablement of extension support for quick-unlock
Former-commit-id: 91400c4725bf786d727695287ec122c01d2447da [formerly d887047fd0]
Former-commit-id: 9576649c2d5f2de0fd6a8cfa5a92afae45304f45
2022-10-20 15:25:57 -04:00
RandyTheSilly e9c787cfe3 Removed an exit statement that was preventing extensions from working
Former-commit-id: 1f89608ad6b7a6a65aca87742991f9195937d8a1 [formerly 304c1b09f0]
Former-commit-id: 8856ed6d9f72fd72f7a91d35dd987f00f1f8eaaf
2022-10-19 15:13:14 -04:00
RandyTheSilly c200b5bbec Allow fallback to standard unlock if quick-unlock fails
Former-commit-id: b6bfe67cdd983da31366ec45c7f5950f856d0dfe [formerly 6b20b82dd5]
Former-commit-id: f685be2b3e57f396ca41a8d2d1e3382a0f978990
2022-10-19 11:34:02 -04:00
RandyTheSilly b6593e609b Created local _quick_enabled for decrypt() for extension support
Former-commit-id: 996ed134188de1425a4ffb0f1bb741fd38b25ab1 [formerly e66ecd9514]
Former-commit-id: 1792c36fd44437f22ad1f86cedcf1c66083715cc
2022-10-19 10:14:39 -04:00
RandyTheSilly 32b0c39fb6 Removed need to re-enter quick-unlock passphrase is the gpg agent is already unlocked
Former-commit-id: e1c94c5f40e1ad16f710c11008c22ce353e50ade [formerly c8691372ca]
Former-commit-id: 94164815b1ee10e3a99c5c48f288f86b751b2449
2022-10-19 10:04:52 -04:00
RandyTheSilly 6b8e24b0b2 Optimized decrypt()
Former-commit-id: 8ad01f00ecf678ea8716507745791818343eaf66 [formerly 2b98562dca]
Former-commit-id: fdc02b6db471b98fbbdf55ddc381a25b68477f0b
2022-10-19 09:33:38 -04:00
RandyTheSilly 2d47f42414 Fixed string_gen complex generating unprintable strings
Former-commit-id: beec4dc72264edf0a2818a5088c849a310d5f7d0 [formerly 9d990eb9f6]
Former-commit-id: 09895d9c665ece34d74c5c68ce6657952c19ca59
2022-10-18 14:54:10 -04:00
RandyTheSilly a773056202 Fixed shearing and renaming entries with quick-unlock
Former-commit-id: f2e3558a0f923d0b5082987858d0e0e59f820f7d [formerly 07cf7a558f]
Former-commit-id: f5036da37b69cb339aba710aa53c9bbf9853567a
2022-10-18 13:35:12 -04:00
RandyTheSilly 097aca8c43 Automatically set quick-unlock passphrase length if the user specifies an invalid option
Former-commit-id: 0343f407b9c9bae5d68af1a0d1cd8028ff9b09be [formerly fa7e03bcf7]
Former-commit-id: dd454b8b47747b556d3268eaf6a38bda5a6a2627
2022-10-13 16:49:08 -04:00
RandyTheSilly 275b07e53f Removed unnecessary s_exit() statements
Former-commit-id: ab2a098f5d620ad8b25665a55e0051c2509e9c99 [formerly f5161ef5cb]
Former-commit-id: 6842c72fb31ab57fc59e0643a332d66b24ab050c
2022-10-13 10:58:07 -04:00
RandyTheSilly 46d539f386 Made error message for when quick-unlock fails more clear
Former-commit-id: 2acc2f84b9205e32cf5bd6bda23abb576002c2a9 [formerly fd12a3c003]
Former-commit-id: 14dc80d8c7c22baed913a0c84abdb3c67138bef9
2022-10-12 16:24:27 -04:00
RandyTheSilly 0adf00d81e Respect the user-specifed quick-unlock passphrase length
Former-commit-id: 5ef20818df71d226d14bf97d99d8646b09a0a7b6 [formerly 70ee2c6d04]
Former-commit-id: 65b4c531f2e84aa5198e1c77a1d0624482cd70e0
2022-10-12 14:57:33 -04:00
RandyTheSilly 46b212988f Truncate max quick-unlock password length
Former-commit-id: c405a82ba419a61bc6d65e89315c8306cec3f01e [formerly 35ee78f717]
Former-commit-id: 53d536d2c37dfca60fd154a90e7857fd1204fc35
2022-10-12 14:53:48 -04:00
RandyTheSilly 3e8772786a Fixed failed decryption on excluded.gpg
Former-commit-id: 8bd59bcf06d63daad654f9ddea9e5ccbcf1b2ea5 [formerly 8dd5101c7f]
Former-commit-id: 6b4e01337c3a0a337a558384283a467eb9e7de1c
2022-10-12 14:37:54 -04:00
RandyTheSilly 3a01157cb3 Fixed quick-unlock gpg key passphrase creation and made quick-unlock more verbose
Former-commit-id: 88dc9cc46cbdaaa3fc547b81758892ebc463573d [formerly 844280c13e]
Former-commit-id: 454e554a4009ed89d3413d57662cde7cca7d9289
2022-10-12 13:39:01 -04:00
RandyTheSilly 079a1412ae Attempt remote imports from /lib/sshyp, rather than /bin
Former-commit-id: 839058d4882b8c8837b4543e6b290643d9f1d409 [formerly d9e2a7d4e1]
Former-commit-id: eeb4a7bb40356e453a41e0176e40d08c6056a7c1
2022-10-12 12:48:08 -04:00
RandyTheSilly 359edcd46c Ensure generated device id is a valid file name
Former-commit-id: 950080785d4666364b5452a4e0b48ce999852ef8 [formerly 3147d9327b]
Former-commit-id: da5d01ac15b077cb2d63668ee9be491ef597a105
2022-10-12 12:32:54 -04:00
RandyTheSilly 60c2920f3c Fixed quick-unlock configuration looking for an integer as input
Former-commit-id: 4a87cd897e7cc5f480d4b68c809ee794af88b7eb [formerly 29c7b931c9]
Former-commit-id: 49fc70a301120b8c7221ec10328186f41ef7294c
2022-10-12 12:19:02 -04:00
RandyTheSilly a3cd6a1f17 Implemented quick-unlock decryption support
Former-commit-id: e09eafab15796554dd5ae4013834c68a99b1df8a [formerly b81018c122]
Former-commit-id: 6a539e12d1ff63e29ba551b3b4622c4022673ff0
2022-10-12 12:06:07 -04:00
RandyTheSilly 8c2b7df1da Simplify client-side quick-unlock configuration
Former-commit-id: efb36f511a0d12172d0274c10f4000ce0b3822fa [formerly 5a9457cc5d]
Former-commit-id: fd65329c7834164054de79f6d0889c2a3957b7d9
2022-10-12 11:46:12 -04:00
RandyTheSilly 994eaee49b Initial implementation of quick-unlock verification
Former-commit-id: a71a8d0a7a1964597e5c52889b8f89117ba82ab9 [formerly 845f968aeb]
Former-commit-id: e53a2994ca43ac3a82c0cdeb88e74c180c20d85a
2022-10-11 17:08:30 -04:00
RandyTheSilly 8f0eb1134a Properly increment _i in whitelist_setup()
Former-commit-id: afced727ea431a420d43780f417e991c3457641c [formerly 9b0b4acf77]
Former-commit-id: 1d5bb9e6359e5a39d49764d8d920d776532f8de6
2022-10-11 12:42:42 -04:00
RandyTheSilly c95643ca89 Added server-side whitelist setup
Former-commit-id: 5cfa4acfc90eaa977feec5ddc427bc5292b228d7 [formerly c9934368a4]
Former-commit-id: 266b7c430437bf807de97833b20c7047058b332d
2022-10-11 12:40:35 -04:00
RandyTheSilly 35ea8bf7d7 Reduced questions asked for quick-unlock setup
Former-commit-id: 0903f70d8924df22eb5c09ff25a8adfd81bf7859 [formerly 243c3c466e]
Former-commit-id: 65d4a73935b03cb9eef41689e3e8f82b85e62ebf
2022-10-11 10:51:00 -04:00
RandyTheSilly 60431b623c Fixed decryption of multi-word entries
Former-commit-id: 3175538b5d759e29a70718fa10950d68e1822014 [formerly 40213aa518]
Former-commit-id: 9da31c6b23689091ad1be58cd71aab0c8c6bb379
2022-10-11 09:47:24 -04:00
RandyTheSilly 185ae4ebff Move a rarely used import statement closer to where it's needed in sshync
Former-commit-id: aceb7e080b29fedf9e8a52ab052af32450491b88 [formerly c31a5a1664]
Former-commit-id: 9844be47e81146aff688e7e1c8462ffc147ab29d
2022-10-11 09:28:13 -04:00
RandyTheSilly 1e290a1f26 Only import rarely used modules when they're needed
Former-commit-id: 1ec2f9c6884f0e06b32d693c38ffe5c698b7dc52 [formerly 8642601eee]
Former-commit-id: d5078e981c24350843ec99597cbbfed619f555bf
2022-10-11 09:22:40 -04:00
RandyTheSilly 71157633df Fixed renaming folders and receiving false error messages when renaming entries in offline mode
Former-commit-id: 49f2fef8ea219945446347df3d782c0660429a05 [formerly 71585770eb]
Former-commit-id: 5e956861f47581704d85bfee5d52728be784d6b3
2022-10-11 09:10:31 -04:00
RandyTheSilly 03487348ea Fixed deleting and renaming entries in offline mode
Former-commit-id: eb690eae6213b2863ac9f93c2fecacb1f77128fd [formerly affcb3adbe]
Former-commit-id: 15fc77ab3728b8f40f8d33bbd6df759fdc7c1283
2022-10-10 19:37:38 -04:00
RandyTheSilly 2d20ddbb97 Fixed folder creation in offline mode
Former-commit-id: 1669541a827e1f6c68e28e738778a131d56645c5 [formerly 45605bf7bc]
Former-commit-id: 62aa51979453eaa9fea50766cbab9fd968c5e65f
2022-10-10 18:20:43 -04:00
RandyTheSilly 21287ca57f Fixed bugs causing entries to not be saved or entries being saved to the wrong place
Former-commit-id: b8ff6c48caefdd051bc54705a9c08bf41add925a [formerly 772eaa0846]
Former-commit-id: 1700df7af1a9b1ce30ca881e8bfc5f6c42ed1666
2022-10-10 17:52:14 -04:00
RandyTheSilly 612f288904 Put .py files in /usr/lib/sshyp, symlink executables to /usr/bin
Former-commit-id: c44a817f58d2f232d93c2d38ca27c4b091a3c523 [formerly c9c88a041d]
Former-commit-id: cb19027d8aa9a1ea97a02bfaf3b41292f5a3f232
2022-10-10 11:16:56 -04:00
RandyTheSilly 0fbe084ff7 Correctly add strings to config file list
Former-commit-id: 7defa79968068b45f64deb0f7df183650ce111b5 [formerly cc4324f953]
Former-commit-id: a431ad4d3e40a85658d59b03455fbabc0667e41e
2022-10-08 21:33:35 -04:00
RandyTheSilly fdf90e043a Overwrite old configuration file
Former-commit-id: ca68d65edcb90d827ee8588d4c251e8bfb35fac6 [formerly 48170f494e]
Former-commit-id: 68c2175fea457766e0c0f8d2fe5751fc2812dbe0
2022-10-08 21:19:47 -04:00
RandyTheSilly b89158d0bb Bug fixes for the revised config file format and server-side arguments
Former-commit-id: 7a924b6a74a488a1116f341110d2bda73ea37cca [formerly 324a5f9a7c]
Former-commit-id: f24a5a8a859fa603b721f888393b25fe944d698e
2022-10-08 21:10:47 -04:00
RandyTheSilly dede7cf8ac Initial addition of offline mode
Former-commit-id: 8bd18e3b3ba4d5d737c25416632ba13a6a38c0ef [formerly 2c1241a1bc]
Former-commit-id: fdb675335dd16ed90cf1deb439a665ba2b3621bb
2022-10-06 16:42:58 -04:00
RandyTheSilly 6d3ba2714b Client-side whitelist error message now shows up will all additional whitelist options
Former-commit-id: c67567cdfd1881a10a39a3ab2b8deb27d9bed01c [formerly d069ab82f9]
Former-commit-id: 70339b78b1d65b2850c9deb431419eb6c9bf4eff
2022-10-06 09:02:32 -04:00
RandyTheSilly 09991a2a30 Added error message for when whitelist is used client-side
Former-commit-id: 70e01336cf53c78905784e6ec730d0c8f542d410 [formerly b8b99755f0]
Former-commit-id: 82f626a998106db61f101b21f2d1f1479eb604cd
2022-10-06 08:57:48 -04:00
RandyTheSilly c5884024de Use rstrip() in place of replace() where applicable
Former-commit-id: 6b0a80036ec8166663dfdbd02c720f4b5ed23064 [formerly 88e97d0131]
Former-commit-id: 1e861149b7485ef6676ce4c5b721dd4ea0d8ba90
2022-10-06 08:47:38 -04:00
RandyTheSilly 1e2166ddaf Added quick-unlock configuration, tweaked config files
Former-commit-id: bc51fe8e937af4b1723af804965eae0e2e0a4ed4 [formerly 012796f052]
Former-commit-id: 52db53b8633894dd5d0f3d5a0abfa4aeede41c61
2022-10-05 23:46:32 -04:00
RandyTheSilly 86487b8ae5 Rename 'device name' to 'device id'
Former-commit-id: 35521f185ee50203d24dab3e3ae84cf8930eb7e7 [formerly 0a450018de]
Former-commit-id: 783fab372f69f811417dd4f7be6269aaff7f15aa
2022-10-04 23:47:19 -04:00
RandyTheSilly fa05312d49 Whitelist bugfixes and polish
Former-commit-id: fa8991e443fb5117d1a69afa4cd0b0017bacda1f [formerly 773f27946e]
Former-commit-id: e417225d361e3fdb1021885336ec7a9f86e0fdaa
2022-10-04 22:50:05 -04:00
RandyTheSilly 71d942ffae Initial quick-unlock whitelist implementation
Former-commit-id: 0ec410451bf7799bd1c603e8ebc25401efe2850b [formerly 5f7074e04e]
Former-commit-id: ce55288649a10ef7cb20ad2dc1c815a13d263988
2022-10-04 21:08:11 -04:00
RandyTheSilly cc1a099363 Optimized device type setup
Former-commit-id: 3e7b61794bf27e88f0cee1cb3771ee474ef1df70 [formerly 2a56a3c427]
Former-commit-id: 20568fbd2f980319b9a167c3142dc6ee5ca87a6e
2022-10-04 15:12:14 -04:00
RandyTheSilly d6342faf84 Properly detect whitelist argument
Former-commit-id: 5bea6aa37ae4356de2d64d077da7c7f60eba3aa3 [formerly a573778972]
Former-commit-id: be5c0832c95991b9103c7ad97f13d76e60b61dba
2022-10-04 15:03:27 -04:00
RandyTheSilly c7cae5303a Add dedicated server help menu
Former-commit-id: 36a139597b19d1c5ad9c08424723069d72221b11 [formerly c009dd63ab]
Former-commit-id: 46227a7c5aad5aff8ecfd8529bc53e433b3a57a8
2022-10-04 14:37:04 -04:00
RandyTheSilly 1d80cb08ce Allow some arguments when running as server
Former-commit-id: c4d50678ff19fe452eb06de70e3890e919e0d0b2 [formerly aadca0ad44]
Former-commit-id: 21750ce3902b7e8bcc50b1068198c4a329c3912b
2022-10-04 13:42:21 -04:00
RandyTheSilly 8163aee868 Swap URL and note options in edit help menu for visual consistency
Former-commit-id: 974a7cbb5a21e9b093c690ef67621e41de16bfdd [formerly 6ffc65f0d0]
Former-commit-id: de6cc2e91778ac13a193e4d77edb297cb8dd543c
2022-10-04 13:25:31 -04:00
RandyTheSilly 7c061f561f Removed metainfo file, as it did not solve the issue with Debian licesning
Former-commit-id: 2a9ee72c9e6dca49ef7a95d62902237def77969f [formerly 8980bef8ce]
Former-commit-id: 11313daff2acf3980925e45776a88f7f40aff964
2022-10-04 13:18:25 -04:00
RandyTheSilly 339d20bc3e Update license to GPL-3.0-only
Former-commit-id: 89163bb523391768dcfdee8c9873ab5443cd66d0 [formerly 1436cdfb90]
Former-commit-id: 3a8ce9b0569a32839344a9fdfd664af28ce1fe07
2022-10-04 12:44:39 -04:00
RandyTheSilly 434f5f85cd Added metainfo.xml file for AppStream metadata
Former-commit-id: ad6f791e8c5c7036f70de16125e016cb9e7e40a3 [formerly 374c2336c8]
Former-commit-id: c855d50011ca4107fd007cf693575cff1178beb4
2022-10-04 11:44:35 -04:00
RandyTheSilly 22d9605781 Update README.md
Former-commit-id: 943e9e1f7daedddaaa861f4845118fb8db4c7803 [formerly 5c58151888]
Former-commit-id: 2925645b0f261b98a738240fcb6abec83622f8f7
2022-09-21 11:24:12 -04:00
RandyTheSilly d644f8df01 Initial implementation of non-interactive packaging script
Former-commit-id: 92c811513a6190f7d0f9e479e84bd54eb7a13556 [formerly 7e29a9ba9e]
Former-commit-id: 5fe414bb4dfbe286b53845826c9bdcf20ab5b22f
2022-09-12 15:21:55 -04:00
RandyTheSilly 551789636d Slight line count reduction
Former-commit-id: 442835aaecb34b116ca8a44109e08a0643344271 [formerly b27f4cb805]
Former-commit-id: 1087b9aae0e2c0e641e7f44e901ac16e07a33270
2022-09-08 10:19:43 -04:00
RandyTheSilly 9ab175a8d8 Roughly halved the amount of time to source bash completions
Former-commit-id: 624a99a5727e49b12c1468c27110cee893124fd2 [formerly f411a56d1f]
Former-commit-id: 48802e27abb02efaf80743bd4fc8dbe3a03219fa
2022-09-08 09:47:59 -04:00
RandyTheSilly e5a4d80e3b Packaging script shebang changed to "/usr/bin/env bash"
Former-commit-id: 6d7053b0f6e1e3aec1373d664acfb3fc71c00cc9 [formerly 6542e8f7e2]
Former-commit-id: f9506fab60e02e0f402ea246feab5c5ae8d77888
2022-09-07 09:46:09 -04:00
RandyTheSilly 0920dcf004 Fixed completions not generating
Former-commit-id: 3f8c64047f12456fd3c1ce8243293beb323912a2 [formerly 915a17b8e9]
Former-commit-id: 0e322f3cda6e75f2db8b9e649028fccbf1ae09ad
2022-09-05 14:29:43 -04:00
RandyTheSilly e18b3b4d0a Allow path completions alongside shortcuts
Former-commit-id: 8404cf01dd8b828b69d85bdbe520ad422a47b1ae [formerly d037acd5b0]
Former-commit-id: ae522f2d127096c5654748a53f4bffef7e234609
2022-09-04 15:10:04 -04:00
RandyTheSilly ffccc88a1d The _path_gen function is no longer run twice (completion is much faster now)
Former-commit-id: 996add6978d32e2a1d72b12352baa682645b3061 [formerly 2ed8b69abf]
Former-commit-id: 2e90025a3d6aaba8ff1987cb3731727a15d5b2e4
2022-09-04 14:55:39 -04:00
RandyTheSilly e1ec834e5c Added initial Bash completion script
Former-commit-id: 81ff7f4a6e515e36cea79953a0212bfd3f89958e [formerly 510ca3bfbb]
Former-commit-id: a85ddda326e5d210ce47bc03a668e3f4ba3537c9
2022-09-04 14:49:43 -04:00
RandyTheSilly 018d0c511d Updated README.md for release v1.1.2
Former-commit-id: 4eb7a866fa03d5990a300120974def01ab4babec [formerly 0ce5b1c1f6]
Former-commit-id: b0e3e46e63b15184ad7d600ccc5e33e98c185081
2022-08-27 14:27:35 -04:00
RandyTheSilly 55b94fc4cc Removed option for using local source from packaging script, as it is mostly unnecessary and/or broken
Former-commit-id: 86a32b1b3e217708078d5d99f8e30571169697a6 [formerly 35068270af]
Former-commit-id: db7e4d8eedcda2d94a5cec75e4ef9e354eec0687
2022-08-27 14:08:58 -04:00
RandyTheSilly 3f9c4e2c8d Automatically calculate revision number for Alpine packaging
Former-commit-id: 2de24f3dc4b9e5f5e27265da1271ea96be0387f5 [formerly cd5c9150a5]
Former-commit-id: 2c613cdc811dc127968a46758c4f238562bc64f9
2022-08-27 13:53:09 -04:00
RandyTheSilly 166ac50f42 Updated documentation for release v1.1.2
Former-commit-id: e212291e40989a1c50cbccf27060dbc7744da668 [formerly f97c9ad4f9]
Former-commit-id: 150048cc1ab40ee49e83295cedcdc9c3b1c49a8c
2022-08-27 13:12:58 -04:00
RandyTheSilly df1c6482a8 Optimized cross-device entry deletion code
Former-commit-id: 2a1dcda6460c06103846b41fbf2d83bf78c05527 [formerly f1aca39fd1]
Former-commit-id: 268b5564ff2f4cc157ebe039e9c46826a4bdb878
2022-08-27 12:46:54 -04:00
RandyTheSilly 38c6ef3d1b rename() now uses entry_name_fetch()
Former-commit-id: c3a3e7b95eb85225dd0bfbbbb15ac81d78adf7e2 [formerly 1f0b23c25f]
Former-commit-id: d2fe8fce784a01a9f5c127ad1eb3d05550624425
2022-08-27 12:11:59 -04:00
RandyTheSilly 7bea6093b8 Properly handle exception for attempting to copy a field that does not exist
Former-commit-id: 57c07b5ad482413febc9b6ee4e27c3f3a5f4fe11 [formerly 7355092cfe]
Former-commit-id: dc1d96e23a8a558c4b880b997a17e3a8d7cfcadd
2022-08-26 18:04:01 -04:00
RandyTheSilly f9ca6f8e94 Fixed generic package not being compressed
Former-commit-id: 600f05d063f52cfc34b58abef6acb799ce35f651 [formerly 56a99d09ef]
Former-commit-id: 90d9f29f91c3e44cf0e2ef75a8bbbd48ad3aa52c
2022-08-14 19:16:04 -04:00
RandyTheSilly 75d8eb7b7d Added Alpine packaging support, fixed packaging woes regarding a bad shebang
Former-commit-id: 2a440affcd09a28554c4ebe316408889047dc052 [formerly a83297c52b]
Former-commit-id: 41d6aebd702925cfbd4089f974b09250f3f6d8b3
2022-08-14 19:13:50 -04:00
RandyTheSilly 39316d04a2 Updated documentation for release v1.1.1
Former-commit-id: defed7054804d7bf36e93c302282039d335d6561 [formerly 558512ba52]
Former-commit-id: f6cf7d3e5633652439a46c51f9d5cfad007f2236
2022-07-21 22:40:29 -04:00
RandyTheSilly 3e9a4c0403 Fixed gpg auto-generation adding extra spaces to gpg-gen file
Former-commit-id: 0a273095a3a13d2997655c19ff62a674b135f530 [formerly 83a408ca0b]
Former-commit-id: eeee558508a68dcb9e243eea4e049704448c9f3e
2022-07-21 19:34:25 -04:00
RandyTheSilly 3bc07b48ef Fixed encrypt() using global tmp_dir
Former-commit-id: 2e993a03f745ae5b4a4f58acc6695e0660bc278c [formerly b6d3f7c5d1]
Former-commit-id: 9306abe18fe741cdd36280798f4bcffc66a77dd7
2022-07-21 01:37:53 -04:00
RandyTheSilly 5234e8c048 Improved encrypt() usability by extensions
Former-commit-id: 1dad668c15e2e1629c0233c80b88763ed5535c04 [formerly 0c975eab8f]
Former-commit-id: 3bddba6995f6aa92de8ea00500cb64b08d7e17db
2022-07-21 01:29:59 -04:00
RandyTheSilly b7c3535955 Exposed encrypt() function to be used by extensions
Former-commit-id: a055f6359a1bd2b81191ef1ef7b5dfb9432f75b2 [formerly 033bbd59de]
Former-commit-id: 451bafbfaaec27086c8c6cb50cb918ca94cf5497
2022-07-20 16:23:43 -04:00
RandyTheSilly 1f52c45c43 Bump version to v1.1.1
Former-commit-id: b2aad92f56b7931daf7ccab2a44793b29bec61f3 [formerly 5aeaee4c8f]
Former-commit-id: 2c651547721c89147dff385e0ad25d2d44694870
2022-07-17 07:29:56 -04:00
RandyTheSilly 7723baa69e Convert add_entry() and gen() to use optimized_edit()
Former-commit-id: 09f1256a4eed4bc042af7149f15ebb5b1197cbe8 [formerly 2d40db5467]
Former-commit-id: f7aa3b0cd2a761283ed11646b6c8fbb6f8130501
2022-07-17 07:25:12 -04:00
RandyTheSilly b680cc96d6 Significant overhaul to entry format optimization
Former-commit-id: 032103385be1ec017f97192829d591acd7a8c902 [formerly 8f318446bf]
Former-commit-id: 7ae69f3bafa268df1cf114d443d367ff45618f4a
2022-07-17 05:37:54 -04:00
RandyTheSilly f750fe1e4d Fixed compatibility check not adding the correct number of lines under certain circumstances
Former-commit-id: 93a4ff7bd25e38ae0a2b40d147afa51b08d73e04 [formerly a4368d60eb]
Former-commit-id: 58c89fcb9728bcfb430aaaf0df817f696688f1cd
2022-07-16 19:32:57 -04:00
RandyTheSilly b96db3ad92 Updated date in manpage for release v1.1.0
Former-commit-id: f9b74560f437e3dcc3d731909599957c460e8e8b [formerly 393ef08a21]
Former-commit-id: ddd1f4834f044d5e3da5016218138690627bcbfe
2022-07-14 03:21:43 -04:00
RandyTheSilly 224fc1fc6d Minor visual consistency tweak for Haiku gpg key generation
Former-commit-id: 1afd8df260d65f210e90cc93270971bf2c2fcb46 [formerly c5c110d0b4]
Former-commit-id: a24c571e55d987595250ebcfc558924cec675c62
2022-07-14 02:53:39 -04:00
RandyTheSilly 0bd2e45dba Fixed Termux packaging
Former-commit-id: 6d38a02d6211412bc99615704f311f820bdcef27 [formerly 4b02fd02b8]
Former-commit-id: 92f48521175fb89015cdb6dc9d99fb9485650c1f
2022-07-13 07:44:29 -04:00
RandyTheSilly 6410843911 Updated changelog for v1.1.0
Former-commit-id: 7ebe77ae88f470586d291eb4054cbdfa6f365950 [formerly de28d19969]
Former-commit-id: 7d27d41aef11546e74dc7073c8b260566addb0d7
2022-07-13 04:48:11 -04:00
RandyTheSilly 3dda6d8428 Update README.md
Former-commit-id: 5b20287fab20945ddc8841249503c321d6cbf999 [formerly beeb426ac8]
Former-commit-id: 90746e5b5225435bf8fd7ab9c2659fa5547a0c14
2022-07-11 22:30:48 -04:00
RandyTheSilly 4f31af5eff Clean up for automatically created gpg generation file
Former-commit-id: eba9c2f414fd59d655e2d3b992b2a8982745e01f [formerly e2b8e31f50]
Former-commit-id: 1166007ce70d0e1d61f2e2d8c3fab78970a6407b
2022-07-11 22:19:31 -04:00
RandyTheSilly bfb830c5e5 Fixed Haiku gpg key generation
Former-commit-id: 1a441cea301049608232742f4fddcc6338adf0a7 [formerly a673404fae]
Former-commit-id: 5ad1eef49307617c0f629f0a660d977f1784d380
2022-07-11 19:06:58 -04:00
RandyTheSilly 790121e7ea Greatly improved 'sshyp tweak' readability
Former-commit-id: 1f0f3ad2ca92e321c4819a14e9db1a961ff0816d [formerly d6bc4a2301]
Former-commit-id: 331e6e9b3d78f4aab1e4c958d526466a469ac515
2022-07-11 04:16:33 -04:00
rwinkhart 4168b800f8 Reduced code used for argument parsing
Former-commit-id: fb6b5f10b1077e2bba9c6bf43c23a59a455491eb [formerly faea36f6cd]
Former-commit-id: 5292e931128c413557c0e9609c009d7430949cf7
2022-07-10 05:41:49 -04:00
rwinkhart 801d515697 Restored banner image
Former-commit-id: 77219101a9c71848dce9d96e7dd17d9440d03b6c [formerly 398999b23f]
Former-commit-id: 77a032369f2f492f8227fa927da3a1b3d88ad7d0
2022-07-10 00:16:50 -04:00
rwinkhart 379970d53b Moved conversion scripts to sshyp-labs repo
Former-commit-id: b2ce1378324b6b19b71a54f02e4ac34a94d17728 [formerly 77873d061b]
Former-commit-id: ab23a45ed7b1d11597823081b2f0132b4b01ec2f
2022-07-10 00:15:56 -04:00
rwinkhart 4abb3ed718 Fixed entries readout not skipping lines between fields under certain conditions
Former-commit-id: 952acd940a754745d1798070113ea6c4d9d84408 [formerly f6875b15f0]
Former-commit-id: 496bdf8eb8abb6aa6c55e355e2b0457002793811
2022-07-09 23:35:08 -04:00
rwinkhart 6690fd15c9 Updated sshyp-refresh to use new entry directory
Former-commit-id: 9dedbb71ef7cf4f45511780d62a4c51d75d782a9 [formerly 8c520d972e]
Former-commit-id: 900cc5e3e7c0508a2629cfcb002faebb7c1d3753
2022-07-09 18:17:24 -04:00
rwinkhart 1582e73a98 Removed unused import
Former-commit-id: a7209c33c11d1eb36b7b27a1184b783f23253ff4 [formerly 01d59ce79a]
Former-commit-id: 8a9c2cb3017b966c138ebe9ae4cf8a1ea252ddca
2022-07-08 06:17:06 -04:00
rwinkhart dfe1703e62 gpg key generation and input is now automated
Former-commit-id: 97072166a69bc920cf39a87aa05f03ffc783d3d0 [formerly 9e49aa0bcb]
Former-commit-id: 9037e0b2a5f41f5db6616fc730ba21a8aec4dbe1
2022-07-08 06:14:13 -04:00
rwinkhart 7a76130b26 Updated banner artwork
Former-commit-id: c51116e0cdb7866b2c0bb969a23b57c4cb2cb7ff [formerly a2a473454f]
Former-commit-id: b5636d731c0398a17ca972d15325cced3c4df36a
2022-07-08 02:24:55 -04:00
rwinkhart 98dcbf57c6 Updated directory specified in the manpage
Former-commit-id: 934137a00c709169d9c316aa6a670eb6ef832f8f [formerly 2639cea365]
Former-commit-id: 98831f08192eb3deeb596594a9a24cbdb1c8dd1f
2022-07-08 00:46:23 -04:00
rwinkhart a5946d558a Added comments to every function
Former-commit-id: 6b8f15be379d51af5ced2449b1db7749d528dcf4 [formerly 87ae61ae30]
Former-commit-id: f5919588095deb509e899cff4e024dd76affbbce
2022-07-08 00:39:48 -04:00
rwinkhart 30fb5ed041 Updated compatibility with the upcoming sshyp-mfa extension
Former-commit-id: 3d900bfcce18345a9595deca8951b3a91bdfa85b [formerly bf22987544]
Former-commit-id: 34cbff97d0e671e71acd2baa95a0d129e1bafe79
2022-06-30 22:11:19 -04:00
rwinkhart fb1f5b92c3 Disabled all arguments on server except for 'tweak'
Former-commit-id: b35e7fca86b9fc7937dfb6119a8ba154ebade8fe [formerly c7fa3e3d09]
Former-commit-id: 7cab5ad48bd0a41d630fd5f943aa2e32c50ad434
2022-06-30 21:56:08 -04:00
rwinkhart 61b2186b0a In compliance with the XDG base directory spec, entries are now stored in ~/.local/share/sshyp/
Former-commit-id: fbb98f890b417395345a7a71ad158e48fa36a7ef [formerly 0c1f34bc30]
Former-commit-id: 91bd7170c0c56c093cf2126ce089be0e8255d6ce
2022-06-30 21:22:20 -04:00
rwinkhart 2113b93481 Allow the user to choose preferred editor, drop nano as dependency
Former-commit-id: d84048c212beca87419aac3577cf32c01d4f518f [formerly 9891fe4a81]
Former-commit-id: 2204730779caa4adad44a03f1fcd0bb76f25a1cd
2022-06-30 20:27:59 -04:00
RandyTheSilly 2030d90114 Fixed license name for Fedora package
Former-commit-id: 4caad0c333bdb66c3945692368ba26c702060426 [formerly 50972fcdf8]
Former-commit-id: 2645a1286c5d23f05f22e9dde0ead1edde6e27d5
2022-06-21 23:39:07 -04:00
RandyTheSilly 75071601e6 Update packaging for sshyp.py rename
Former-commit-id: 1f52fb7fb48c7e1152314d065602139f62b5ea2e [formerly 37fe8e37e7]
Former-commit-id: 8f17c38475e647b511bc7858c3859d3c65e29882
2022-06-21 23:37:45 -04:00
RandyTheSilly 9a0a261d55 Removed unused code in entry_name_fetch()
Former-commit-id: 047a66dc53042dda37f6825862c2fc14fb3a17cc [formerly 1f2543fe3f]
Former-commit-id: 4bb6fca31988c8ef74a4e4a730f1d25e9b21481d
2022-06-21 23:18:54 -04:00
RandyTheSilly 4ca2d89464 Updated read_shortcut() to use argument_list[] notation
Former-commit-id: 01a62c169c089618c8015f94f9d63ddbfb295d37 [formerly c0f3296a75]
Former-commit-id: 4bf2ff467f12d9f1e7c5f7fd0187d441718808a7
2022-06-21 23:12:03 -04:00
RandyTheSilly f90ec5c900 Optimized import statement for random
Former-commit-id: e18122f2bc1df6525c890d42ae02d90062e5bd6e [formerly c2f43e563a]
Former-commit-id: a993e29ce0410dd63a4171d10e3dc842c9297be5
2022-06-21 23:03:00 -04:00
RandyTheSilly fa0a4fe0b8 Removed unnecessary arguments in usage of decrypt()
Former-commit-id: cd966935bf552d5b5222c59e1887544b79e8a6aa [formerly db0142d202]
Former-commit-id: c3347ea5164901f8377414b097af426b1569b26d
2022-06-21 22:58:39 -04:00
RandyTheSilly c85a9d2ccd Compatibility with upcoming sshyp-mfa standalone extension
Former-commit-id: adf34e9d38e3ce5a7d96738a97593fca777aa244 [formerly f184864e90]
Former-commit-id: ff632e3bd21132c838ba4602d99ab4106d387971
2022-06-21 22:44:10 -04:00
RandyTheSilly 43351fd66f Bump version to v1.0.1
Former-commit-id: 73a9e537a08596e3a527f7c7b45405bd43818d54 [formerly 4aa9036d42]
Former-commit-id: 249daa62a333460a5c3142815872b3e26b4ad6a8
2022-06-21 03:46:24 -04:00
RandyTheSilly 096bdb0773 Updated changelog
Former-commit-id: 90c2c0be99f4e250b4a710c7f4013f73f648c0ed [formerly fdaff41f6f]
Former-commit-id: 4d8658fd6473e33ac3d4fecf88cfb500d2d44959
2022-06-21 03:44:48 -04:00
RandyTheSilly 330396c5f1 Improved usage of Popen in copy() function + removed import statement for subprocess.STDOUT
Former-commit-id: bbc39da1d30845aadac3430b0d8758d6958a159c [formerly 88417f5f67]
Former-commit-id: 5be7fe4d68ae5153ef1dbde3018b15ed5fe944b0
2022-06-21 03:28:56 -04:00
RandyTheSilly 8576f63479 Optimized copy_name_check() function
Former-commit-id: 07e02ab7b0bbf030b0ee1baedd8dbb7ec5ef2e4e [formerly 47e8383146]
Former-commit-id: 570a930a9c63aaa5315285ccf1a84316f4e6199a
2022-06-21 03:13:55 -04:00
RandyTheSilly 393f241538 Optimized decrypt() function (fixes issue #1)
Former-commit-id: d94cce05e9695f4d0744b5a3f4232ad48b146ed2 [formerly 3ad5acfc99]
Former-commit-id: b7edcf31903826ebb8010f6e694b728e1616a70f
2022-06-21 03:03:23 -04:00
rwinkhart c557d5bfee Update README.md
Added CodeQL badge

Former-commit-id: fa618db3f76919e31da43758bda1652f19e63912 [formerly 6f18076068]
Former-commit-id: 809209a1ba762b6dacb8a1eb9f7199873787438b
2022-06-20 09:15:39 +00:00
rwinkhart acca7d888c Create codeql-analysis.yml
Former-commit-id: 8323ea0d21b761f9ec50a79e926b15d691c9700a [formerly 492b10a44e]
Former-commit-id: 72b9d6a984840d399124efe919adaadd5d0d7f04
2022-06-20 09:05:07 +00:00
rwinkhart 2f3b3c67ba Delete codeql-analysis.yml
Former-commit-id: bedaabebf13648b28a564c575ff82723ddf70904 [formerly 94f5420f83]
Former-commit-id: 61593eb69cc8abb1120925965aaf81504cb8dd4f
2022-06-20 09:04:37 +00:00
rwinkhart 88d2402e88 Create codeql-analysis.yml
Former-commit-id: 3551b0bdb4902910a23abfcb369965f8bfb3dde8 [formerly 4f90e5ca0b]
Former-commit-id: b50cad12f70384329acc728a2628a83158c604af
2022-06-20 08:58:03 +00:00
RandyTheSilly 928aacc64a No longer package Fedora with the "All" option (to ensure Fedora is only packaged from itself)
Former-commit-id: 84a32263eb6ceb32063ba0c3fd6ecc49c59fc579 [formerly 90454645e0]
Former-commit-id: 8e57ca2e811b3cbf73c9356c103ae189022f9a9f
2022-06-20 03:49:51 -04:00
RandyTheSilly 094bdcb418 Updated documentation
Former-commit-id: 49716c1645645bdc47992c7d480f51a81e457e0e [formerly c0ac590e4b]
Former-commit-id: d0d798a715d10136bfc9c67352a2e8893ddfbff1
2022-06-20 03:45:43 -04:00
RandyTheSilly 419ff51e75 Properly handle exception for non-integer input with pass_gen()
Former-commit-id: b2c4bd2cd8cf7db4516f47a48bde46610d2e9f5c [formerly 964561b33b]
Former-commit-id: c92d23fa9ee173e5e0540ecbb060b1edf8ec05c9
2022-06-20 03:35:19 -04:00
RandyTheSilly 2111a0454e Optimized gen() function
Former-commit-id: 3706f28b1e9a0ccf59dd75076692a30534fe017c [formerly 6398ef8ec0]
Former-commit-id: 35419b0570ca452d27e0f8cae322bec552e1023d
2022-06-20 03:23:36 -04:00
RandyTheSilly 5d902f0324 Fixed error when generating a new password entry with no additional arguments
Former-commit-id: 642e7756a42374eac08df6ce1ec2ac37a803a2ce [formerly 45ee9ff40b]
Former-commit-id: b5e1a2cca9be722ae40e5a8b6b2431251344daac
2022-06-20 03:15:08 -04:00
RandyTheSilly 505ffdb489 Fixed accidental overwriting when creating a new file of a name that is already present + some fixes for renaming and generating
Former-commit-id: 947ab5d1ac6dc5b07836bc075d202b32f563ab6c [formerly a06fc38968]
Former-commit-id: 97c3bda15e6e67e8f5503aa21ac69e54c27ae42c
2022-06-20 03:08:08 -04:00
RandyTheSilly 5cab1ad091 Fix FreeBSD errors on entry creation/editing due to attempting to access a directory with limited permissions
Former-commit-id: d0ec9fcc1d155c11c4c4cee86ba13815ccf06d2b [formerly 1860edaccf]
Former-commit-id: e94a9e94804fccea66d9f57673c26ac54dd0e13d
2022-06-20 02:11:33 -04:00
RandyTheSilly 2e2404636b Corrected installed size for Debian/Termux packages
Former-commit-id: 6b15b2962add508a3e52e4301080143188641a7c [formerly abe9fed749]
Former-commit-id: 76bbde9f50cbf2bb662d93c537dee25ad6b03c64
2022-06-20 02:02:07 -04:00
RandyTheSilly 6cb5bd405f Update README.md
Former-commit-id: 38d003983687f031ef2dc50122db52429d0cd340 [formerly 71662a53f1]
Former-commit-id: cb658bef3fdf54ed6dfb546468368113a4660518
2022-06-20 01:12:47 -04:00
RandyTheSilly c93965c9a5 Clarify FreeBSD support in version screen
Former-commit-id: 92ef1fe11f9c5818e7356f475b93ade6af37e4b2 [formerly 99282ea5b0]
Former-commit-id: d072d2719fc308239efde87f0547548e568ccd1c
2022-06-20 00:31:08 -04:00
RandyTheSilly d685e07d32 Clarify that the Fedora package must be built using Fedora
Former-commit-id: 872539a685e693ad39e98dc7147fb03b14b03799 [formerly 4b77990d97]
Former-commit-id: fb405f8b9845c1b14def2e4be7a865e158937042
2022-06-20 00:26:21 -04:00
RandyTheSilly 192f58fef5 Replace claims of Red Hat support with Fedora, as testing is not done with other Red Hat distributions
Former-commit-id: 8b8a719d2ab61fb3071d7977876edb406a6de322 [formerly afe05cf76f]
Former-commit-id: d5e6f980a9f354d2202ae5c9cfa275eca3eb337d
2022-06-20 00:16:06 -04:00
RandyTheSilly 106f22f757 Cleaned up ascii art in banner
Former-commit-id: 3738bcb955c614a67f95c459888d8f3dfdd20444 [formerly f2d704a447]
Former-commit-id: f10b328ca54dc3114f3c1611a59da6bb52247a24
2022-06-19 23:28:46 -04:00
RandyTheSilly ae414dadda Added banner to README.md
Former-commit-id: 02625dc2573dc43cceab4a5d8aba597f64f39039 [formerly 3e8ab76db7]
Former-commit-id: 1c20fe718096e7b8106b42c4ebe687d77c004582
2022-06-19 23:11:56 -04:00
RandyTheSilly c9e99732a2 Replaced 100h mascot with banner
Former-commit-id: 7334c3e7b066816a68858f051781a4c80b02b99c [formerly be0c226e15]
Former-commit-id: bad996992a2b239424cffd8bd1649d638082e229
2022-06-19 23:06:36 -04:00
RandyTheSilly fc37368447 Replaced 400h mascot image with 100h mascot image
Former-commit-id: b6a210e20f3c04806775cabd9abde4fe9a9506aa [formerly 61525bd81e]
Former-commit-id: 98835f143f3857377a8df2899d0123e5e8053fdd
2022-06-19 22:21:01 -04:00
RandyTheSilly ca2bc98735 Added 400 pixel tall version of sshyp mascot image
Former-commit-id: 157fdf477353d9134c8a80efbcfc1fd769c0c484 [formerly 21205f48dd]
Former-commit-id: 4fc37ca74a4c4ac1cc8f11edd1e1595c9b0e6253
2022-06-19 22:19:20 -04:00
RandyTheSilly f44391612d Added full-resolution mascot image
Former-commit-id: 86c57c8f87
2022-06-19 22:12:44 -04:00
RandyTheSilly 8c0e9eb6df Update README.md 2022-06-17 03:19:21 -04:00
RandyTheSilly c03e818560 Update documentation 2022-06-17 03:16:01 -04:00
RandyTheSilly 0b653000ef Increased visual density of entry list 2022-06-17 02:41:50 -04:00
RandyTheSilly 9f89dce42b Update rename function to new entry name fetcher 2022-06-17 02:33:26 -04:00
RandyTheSilly e7b2e19039 Updated input text for adding an entry 2022-06-17 02:24:53 -04:00
RandyTheSilly 80b6b4abd2 Restored custom input prompts, fixed "add folder" not using new entry name fetcher, made all input prompts serve entry list 2022-06-17 02:18:23 -04:00
RandyTheSilly 758e9f331c Added entry name fetching function to get user input with a cleaner method 2022-06-17 01:50:06 -04:00
RandyTheSilly ba14c0e74b Optimized argument parsing 2022-06-16 17:11:02 -04:00
RandyTheSilly 1991672618 Initial FreeBSD packaging support 2022-06-16 16:11:24 -04:00
RandyTheSilly 9b600dabbf Decrypt lock file to /dev/null 2022-06-12 03:23:22 -04:00
RandyTheSilly e42641079d Added error message for failed decryption 2022-06-12 02:40:24 -04:00
RandyTheSilly 7c6cbaec35 Fixes for Red Hat packaging 2022-06-11 21:42:23 -04:00
RandyTheSilly cb441933db Initial Red Hat packaging support 2022-06-11 20:48:27 -04:00
RandyTheSilly dad1a34575 Added a check to ensure ssh and syncing support are properly configured (also disabled syncing support if not properly configured, acting as a form of offline mode) 2022-06-05 21:27:02 -04:00
RandyTheSilly 3a30812de5 Properly handled exception for unfinished configuration files 2022-05-30 16:51:47 -04:00
RandyTheSilly e1930f9457 Various visual consistency updates 2022-05-30 16:48:18 -04:00
RandyTheSilly 05df3dd903 Updated missing config files message to be in-line with new error message styling 2022-05-30 15:45:07 -04:00
RandyTheSilly 5c1195f42d Updated password length limit message to be in-line with new error message styling 2022-05-30 15:40:10 -04:00
RandyTheSilly 30aa3e2438 Further improvements to visual consistency of errors 2022-05-30 15:33:37 -04:00
RandyTheSilly a8ea1eb444 Fix for occasional IndexError exceptions with new argument system 2022-05-30 15:10:47 -04:00
RandyTheSilly 8e053f25b8 More styling consistency changes 2022-05-30 14:48:30 -04:00
RandyTheSilly a175a270e0 Updated entry reader with more consistent color styling 2022-05-30 14:35:43 -04:00
RandyTheSilly d116582144 Improved argument system to more accurately handle incorrect user inputs 2022-05-30 02:38:18 -04:00
RandyTheSilly f760b5420c Reduced visual complexity of help screens 2022-05-26 05:32:46 -04:00
RandyTheSilly 6498a076f2 Overhauled version screen w/ascii art 2022-05-26 05:05:25 -04:00
RandyTheSilly f4a0c52ca8 Update documentation 2022-05-23 02:17:42 -04:00
14 changed files with 1834 additions and 1184 deletions
+72
View File
@@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '34 22 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+31 -31
View File
@@ -1,12 +1,18 @@
# sshyp
A very simple self-hosted, synchronized password manager for UNIX systems (currently Haiku/Linux). Alternative to (and compatible with) pass/password-store.
![sshyp](https://github.com/rwinkhart/sshyp-labs/blob/main/extra/artwork/sshyp-banner.png)
Compatible with entries created by pass/password-store.
[![CodeQL](https://github.com/rwinkhart/sshyp/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)](https://github.com/rwinkhart/sshyp/actions/workflows/codeql-analysis.yml)
The only password-store compatible CLI password manager available for Haiku.
pronounced as: 'sheep', 'shēp'
"sshyp" stands for "sshync passwords", or "ssh sync passwords".
"sshync" is the custom syncing backend (based on sftp) used by "sshyp".
sshyp is a very simple self-hosted, synchronized password manager for UNIX(-like) systems (currently Haiku/FreeBSD/Linux).
sshyp is compatible with entries created by pass/password-store, as its original goal was to be like pass/password-store, but far more user-friendly to synchronize with a self-hosted server.
sshyp is (as of writing) the only password-store compatible CLI password manager available for Haiku.
sshyp makes use of a custom sftp wrapper, called sshync (ssh+sync), to reliably sync user entries with a local or remote server.
The name "sshyp" is a combination of its syncing library, "sshync", and "passwords".
# WARNING
It is your responsibility to assess the security and stability of "sshyp" before using it and ensure it meets your needs.
@@ -20,33 +26,25 @@ 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 devices
- securely sync said passwords and notes seamlessly between devices (or just manage them offline)
- utilize [extensions](https://github.com/rwinkhart/sshyp-labs) to interact with your entries is additional ways (such as generating TOTP keys or managing your entries in a GUI)
- everything above with entries created by pass/password-store!
- everything above on Haiku, Linux, and Termux (an Android terminal emulator)!
What sshyp will likely do:
- (planned v1.1.0) 2FA/MFA management (was previously not on the roadmap, but could be beneficial in reducing phone usage)
- (planned v1.2.0) everything it already does, but also in a GUI for Linux/Haiku
- everything above on Haiku, FreeBSD, Linux, and Termux (an Android terminal emulator)!
What sshyp definitely won't do:
- Non-UNIX support, e.g. Windows (I'd be happy to link to third-party ports, if someone were to make them)
- Non-UNIX(-like) support, e.g. Windows (I'd be happy to link to third-party ports, if someone were to make them)
# Installation
Arch Linux (all ISAs)
Please see the [installation guide](https://github.com/rwinkhart/sshyp/wiki/Installation) in the sshyp wiki for directions specific to your distribution/OS.
sshyp releases are available in the Arch User Repository as 'sshyp'.
Pre-built packages exist for Haiku, FreeBSD, Alpine Linux, Arch Linux, Debian/Ubuntu Linux, Fedora Linux, and Termux. These can be downloaded from the releases page.
Install with your preferred AUR helper or use:
Requests for additional distribution/OS support can be filed as issues.
```
git clone https://aur.archlinux.org/sshyp.git
cd sshyp
makepkg -si
```
Extensions are available in the [sshyp-labs](https://github.com/rwinkhart/sshyp-labs) repository.
Pre-built packages exist for Haiku, Arch Linux, Debian Linux, and Termux. These can be downloaded from the releases page.
Bash completions can be enabled by installing your distribution's "bash-completion" package and restarting your terminal.
# Building
Since sshyp is written entirely in Python, it doesn't need to be compiled. It does, however, need to be packaged for installation.
@@ -56,14 +54,16 @@ A packaging script is included in the root directory of the repo in order to pac
```
git clone https://github.com/rwinkhart/sshyp.git
cd sshyp
./package.sh
./package.sh [target] <revision>
```
The packaging script has been tested on Arch Linux with dpkg as a dependency for Debian and Termux packaging.
The packaging script has been tested on Arch Linux with "dpkg" as a dependency for Debian/Ubuntu and Termux packaging and "freebsd-pkg" as a dependency for FreeBSD packaging.
Haiku and Fedora packaging must be done on their own respective distributions.
The AUR version and the packages attatched to the release tags were already packaged using this script.
Currently, the script can create packages for Haiku, Arch Linux (PKGBUILD), Debian Linux, Termux, and generic. Packaging for other systems coming soon.
Currently, the script can create packages for Haiku, FreeBSD, Alpine Linux (APKBUILD), Arch Linux (PKGBUILD), Debian/Ubuntu Linux, Fedora Linux, Termux, and generic.
# Usage
Upon initial installation (on both the server and client devices), be sure to run:
@@ -72,8 +72,7 @@ Upon initial installation (on both the server and client devices), be sure to ru
sshyp tweak
```
This command will allow you to configure the settings necessary for sshyp to function.
To ensure configuration compatibility, it is a good idea to run 'sshyp tweak' after each major update.
This command will allow you to configure the settings necessary for sshyp to function. To ensure configuration compatibility, it is a good idea to run 'sshyp tweak' after each major 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.
@@ -92,10 +91,11 @@ man sshyp
# Roadmap
Short-term Goals:
- 2FA/MFA management
- create minimal GUI apps (Linux x86_64, Linux aarch64)
- various optimizations/bug fixes
- create minimal GUI app (Linux x86_64, Linux aarch64) - being done as an [extension](https://github.com/rwinkhart/sshyp-labs)
- significant optimizations
- vaious bug fixes
Long-term Goals:
- a fun surprise
- seize the thrones, shear the humans
-713
View File
@@ -1,713 +0,0 @@
#!/bin/python3
# external modules
from os import environ, listdir, path, remove, system, uname, walk
from pathlib import Path
import random
from shutil import get_terminal_size, move, rmtree
import sshync
import string
from subprocess import Popen
from sys import argv, exit as s_exit
from textwrap import fill
# utility functions
def entry_list_gen(): # generates and prints a list of all folders and entries
print('\n\u001b[38;5;0;48;5;15msshyp entries:\u001b[0m\n')
_entry_list, _color_alternator = [], 1
for _entry in sorted(listdir(path.expanduser('~/.password-pasture'))):
if Path(path.expanduser(f"~/.password-pasture/{_entry}")).is_file():
if _color_alternator == 1:
_entry_list.append(f"{_entry.replace('.gpg', '')}")
_color_alternator = 2
else:
_entry_list.append(f"\u001b[38;5;8m{_entry.replace('.gpg', '')}\u001b[0m")
_color_alternator = 1
_real = len(' '.join(_entry_list)) - (5.5 * len(_entry_list))
if _real <= get_terminal_size()[0]:
_width = len(' '.join(_entry_list))
else:
_width = (len(' '.join(_entry_list)) / (_real / get_terminal_size()[0]) - 25)
try:
print(fill(' '.join(_entry_list), width=_width) + '\n')
except ValueError:
pass
for _root, _directories, _files in walk(path.expanduser('~/.password-pasture')):
for _dir in sorted(_directories):
_inner_dir = f"{_root.replace(path.expanduser('~/.password-pasture'), '')}/{_dir}"
print(f"\n\u001b[38;5;15;48;5;238m{_inner_dir}/\u001b[0m")
_entry_list, _color_alternator = [], 1
for _s_root, _s_directories, _s_files in walk(path.expanduser(f"~/.password-pasture{_inner_dir}")):
for _entry in sorted(_s_files):
if _color_alternator == 1:
_entry_list.append(f"{_entry.replace('.gpg', '')}")
_color_alternator = 2
else:
_entry_list.append(f"\u001b[38;5;8m{_entry.replace('.gpg', '')}\u001b[0m")
_color_alternator = 1
_real = len(' '.join(_entry_list)) - (5.5 * len(_entry_list))
if _real <= get_terminal_size()[0]:
_width = len(' '.join(_entry_list))
else:
_width = (len(' '.join(_entry_list)) / (_real / get_terminal_size()[0]) - 25)
try:
print(fill(' '.join(_entry_list), width=_width) + '\n')
except ValueError:
print('\u001b[38;5;208m-empty directory!-\u001b[0m\n')
def entry_reader(_decrypted_entry):
_entry_lines, _notes_flag = open(_decrypted_entry, 'r').readlines(), 0
print()
for _num in range(len(_entry_lines)):
try:
if _num == 0 and _entry_lines[1] != '\n':
print(f"\u001b[38;5;0;48;5;15mUsername:\u001b[0m\n{_entry_lines[1]}")
elif _num == 1 and _entry_lines[0] != '\n':
print(f"\u001b[38;5;0;48;5;15mPassword:\u001b[0m\n{_entry_lines[0]}")
elif _num == 2 and _entry_lines[2] != '\n':
print(f"\u001b[38;5;0;48;5;15mURL:\u001b[0m\n{_entry_lines[_num]}")
elif _num >= 3 and _entry_lines[_num] != '\n' and _notes_flag != 1:
_notes_flag = 1
print('\u001b[38;5;0;48;5;15mNotes:\u001b[0m\n' + _entry_lines[_num].replace('\n', ''))
elif _num >= 3 and _notes_flag == 1:
print(_entry_lines[_num].replace('\n', ''))
if _notes_flag == 1:
try:
_line_test = _entry_lines[_num + 1]
except IndexError:
print()
except IndexError:
if _num == 0:
print(f"\u001b[38;5;0;48;5;15mPassword:\u001b[0m\n{_entry_lines[0]}")
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 pass_gen():
def _pass_gen_function(__complexity, __length):
if __complexity.lower() == 's':
__character_pool = string.ascii_letters + string.digits
else:
__character_pool = string.ascii_letters + string.digits + string.punctuation
__gen = ''.join(random.SystemRandom().choice(__character_pool) for _ in range(__length))
__min_special, __special = round(.2 * __length), 0
for __character in __gen:
if not __character.isalpha():
__special += 1
if __special < __min_special:
__gen = _pass_gen_function(__complexity, __length)
return __gen
_length = int(input('How many characters should be in the password? '))
if _length > 840:
_length = 840
print('\n\u001b[38;5;208mPassword length has been limited to the maximum of 840 characters.\u001b[0m\n')
_complexity = str(input('Should the password be simple (for compatibility) or complex (for security)? (s/C) '))
_gen = _pass_gen_function(_complexity, _length)
return _gen
def encrypt(_shm_folder, _shm_entry, _location):
system(f"{gpg} -qr {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[3:])
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(edit_notes)
# 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 uname()[0] == 'Haiku':
system(f"ln -s /tmp {path.expanduser('~/.config/sshyp/tmp')}")
elif 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)
print('\nMake sure the ssh service is running and properly configured.\n\nConfiguration complete!\n')
s_exit(0)
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(f"{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} -qr {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':
if uname()[0] == 'Haiku':
Path(f"{path.expanduser('~')}/.ssh").mkdir(0o700, exist_ok=True)
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('\n\u001b[38;5;0;48;5;15msshyp Copyright (C) 2021-2022 Randall Winkhart\u001b[0m\n')
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('\n\u001b[38;5;15;48;5;238mUSAGE: sshyp [OPTION [FLAG] [<entry name>]] | [/<entry name>]\u001b[0m\n')
print('\u001b[38;5;0;48;5;15mOptions:\u001b[0m')
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('\u001b[38;5;0;48;5;15mFlags:\u001b[0m')
print('\u001b[38;5;15;48;5;238madd:\u001b[0m')
print(' password/-p add a password entry')
print(' note/-n add a note entry')
print(' folder/-f add a new folder for entries')
print('\u001b[38;5;15;48;5;238medit:\u001b[0m')
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('\u001b[38;5;15;48;5;238mcopy:\u001b[0m')
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('\u001b[38;5;15;48;5;238mgen:\u001b[0m')
print(' update/-u generate a password for an existing entry\n')
print("\u001b[38;5;0;48;5;15mTip:\u001b[0m You can quickly read an entry with 'sshyp /<entry name>'!")
elif argument == 'version' or argument == '-v':
print('\n\u001b[38;5;0;48;5;15m////////////////////////////////////////////////////////\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m '
'\u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15msshyp Copyright (C) 2021-2022 '
'Randall Winkhart\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m '
'\u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15mVersion 1.0.0'
'\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15mThe Polished Trotters '
'Update\u001b[38;5;15;48;5;238m \u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m/\u001b[38;5;15;48;5;238m '
'\u001b[38;5;0;48;5;15m/\u001b[0m')
print('\u001b[38;5;0;48;5;15m////////////////////////////////////////////////////////\u001b[0m\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('\n\u001b[38;5;15;48;5;238mUSAGE: sshyp add {FLAG {<entry name>}}\u001b[0m\n')
print('\u001b[38;5;0;48;5;15mFlags:\u001b[0m')
print('\u001b[38;5;15;48;5;238madd:\u001b[0m')
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('\n\u001b[38;5;15;48;5;238mUSAGE: sshyp edit {FLAG {<entry name>}}\u001b[0m\n')
print('\u001b[38;5;0;48;5;15mFlags:\u001b[0m')
print('\u001b[38;5;15;48;5;238medit:\u001b[0m')
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('\n\u001b[38;5;15;48;5;238mUSAGE: sshyp copy {FLAG {<entry name>}}\u001b[0m\n')
print('\u001b[38;5;0;48;5;15mFlags:\u001b[0m')
print('\u001b[38;5;15;48;5;238mcopy:\u001b[0m')
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'.")
entry_list_gen()
_read_entry = str(input('Entry to read: '))
if not Path(f"{directory}{_read_entry}.gpg").exists():
print(f"\n\u001b[38;5;1mError: entry ({_read_entry}) does not exist\u001b[0m\n")
s_exit(1)
_shm_folder, _shm_entry = shm_gen()
system(f"{gpg} -qd --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_read_entry}.gpg'")
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}")
def read_shortcut(): # shortcut to quickly read an entry
if not Path(f"{directory}{argument.replace('/', '', 1)}.gpg").exists():
print(f"\n\u001b[38;5;1mError: entry ({argument.replace('/', '', 1)}) does not exist\u001b[0m\n")
s_exit(1)
_shm_folder, _shm_entry = shm_gen()
system(f"{gpg} -qd --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{argument.replace('/', '', 1)}.gpg'")
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}")
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} \"cd /bin; python -c "
f"'import sshypRemote; sshypRemote.deletion_check(\"'\"{client_device_name}\"'\")'\"")
system(f"scp -pqs -P {port} -i '{path.expanduser('~/.ssh/sshyp')}' {username_ssh}@{ip}:'/home/{username_ssh}"
f"/.config/sshyp/deletion_database' {path.expanduser('~/.config/sshyp/')}")
try:
_deletion_database = open(path.expanduser('~/.config/sshyp/deletion_database')).readlines()
except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;1mError: the deletion database does not exist or is corrupted.\u001b[0m\n')
_deletion_database = None
s_exit(1)
for _file in _deletion_database:
if _file[:-1].endswith('/'):
try:
if silent_sync != 1:
print(f"\u001b[38;5;208m{_file[:-1]}\u001b[0m has been sheared, removing...")
rmtree(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}")
except FileNotFoundError:
if silent_sync != 1:
print('Folder does not exist locally.')
else:
try:
if silent_sync != 1:
print(f"\u001b[38;5;208m{_file[:-1]}\u001b[0m has been sheared, removing...")
remove(f"{path.expanduser('~/.password-pasture/')}{_file[:-1]}.gpg")
except (FileNotFoundError, IsADirectoryError):
if silent_sync != 1:
print('File does not exist locally.')
# check for new folders
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c "
f"'import sshypRemote; sshypRemote.folder_check()'\"")
system(f"scp -pqs -P {port} -i '{path.expanduser('~/.ssh/sshyp')}' {username_ssh}@{ip}:'/home/{username_ssh}"
f"/.config/sshyp/folder_database' {path.expanduser('~/.config/sshyp/')}")
try:
_folder_database = open(path.expanduser('~/.config/sshyp/folder_database')).readlines()
except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;1mError: the folder database does not exist or is corrupted.\u001b[0m\n')
_folder_database = None
s_exit(1)
for _folder in _folder_database:
if Path(f"{path.expanduser('~')}{_folder[:-1]}").is_dir():
pass
else:
print(f"\u001b[38;5;2m{_folder.replace('/.password-pasture/', '')[:-1]}/\u001b[0m does not exist locally, "
f"creating...")
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
if argument == 'add note' or argument == 'add -n' or argument == 'add password' or argument == 'add -p':
_entry_name = str(input('\nName of entry: '))
else:
_entry_name = argument.split(' ')
del _entry_name[:2]
_entry_name = ' '.join(_entry_name)
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if argument.startswith('add note') or argument.startswith('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' + _notes)
elif argument.startswith('add password') or argument.startswith('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(_password + '\n' + _username + '\n' + _url +
'\n' + _notes)
print('\nEntry preview:')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(_shm_folder, _shm_entry, _entry_name)
def add_folder(): # creates a new folder
if argument == 'add folder' or argument == 'add -f':
_folder_name = str(input('Name of new folder: '))
else:
_folder_name = argument.split(' ')
del _folder_name[:2]
_folder_name = ' '.join(_folder_name)
if _folder_name.startswith('/'):
_folder_name = _folder_name.replace('/', '', 1)
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
if argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit -r':
entry_list_gen()
_entry_name = str(input('What would you like to rename/relocate? '))
else:
_entry_name = argument.split(' ')
del _entry_name[:2]
_entry_name = ' '.join(_entry_name)
if not Path(f"{directory}{_entry_name}.gpg").exists():
print(f"\n\u001b[38;5;1mError: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1)
_new_name = str(input('New Name: '))
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if _entry_name.endswith('/'):
move(f"{directory}{_entry_name}", f"{directory}{_new_name}")
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}"
f"{_new_name}'\"")
else:
move(f"{directory}{_entry_name}.gpg", f"{directory}{_new_name}.gpg")
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c "
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\")'\"")
def edit(): # edits the contents of an entry
_shm_folder, _shm_entry = None, None # sets base-line values to avoid errors
if 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':
entry_list_gen()
_entry_name = str(input('What file would you like to edit? '))
else:
_entry_name = argument.split(' ')
del _entry_name[:2]
_entry_name = ' '.join(_entry_name)
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;1mError: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1)
_shm_folder, _shm_entry = shm_gen()
system(f"{gpg} -qd --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
# compatibility check for GNU pass entries (ensuring they have at least four lines)
_lines = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
if len(_lines) < 3:
while len(_lines) < 3:
_lines.append('\n')
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_lines)
if argument.startswith('edit username') or argument.startswith('edit -u'):
_detail = str(input('New Username: '))
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 1, _detail + '\n')
elif argument.startswith('edit password') or argument.startswith('edit -p'):
_detail = str(input('New Password: '))
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 0, _detail + '\n')
elif argument.startswith('edit url') or argument.startswith('edit -l'):
_detail = str(input('New URL: '))
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 2, _detail + '\n')
elif argument.startswith('edit note') or argument.startswith('edit -n'):
edit_note(_shm_folder, _shm_entry)
remove(f"{directory}{_entry_name}.gpg")
print('\nEntry preview:')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(_shm_folder, _shm_entry, _entry_name)
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' or argument == 'gen':
if argument == 'gen update' or argument == 'gen -u':
entry_list_gen()
else:
print()
_entry_name = str(input('Name of service: '))
elif argument.startswith('gen update') or argument.startswith('gen -u'):
_entry_name = argument.split(' ')
del _entry_name[:2]
_entry_name = ' '.join(_entry_name)
else:
_entry_name = argument.split(' ')
del _entry_name[:1]
_entry_name = ' '.join(_entry_name)
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
if argument.startswith('gen update') or argument.startswith('gen -u'):
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;1mError: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1)
else:
_username = str(input('Username: '))
_password = pass_gen()
if not argument.startswith('gen update') and not argument.startswith('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(_password + '\n' + _username + '\n' + _url + '\n'
+ _notes)
print('\nEntry preview:')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(_shm_folder, _shm_entry, _entry_name)
else:
_shm_folder, _shm_entry = shm_gen()
system(f"{gpg} -qd --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_entry_name}.gpg'")
replace_line(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 0, _password + '\n')
remove(f"{directory}{_entry_name}.gpg")
print('\nEntry preview:')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(_shm_folder, _shm_entry, _entry_name)
def copy_data(): # copies a specified field of an entry to the clipboard
if 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':
entry_list_gen()
_read_entry = str(input('Entry to copy: '))
else:
_read_entry = argument.split(' ')
del _read_entry[:2]
_read_entry = ' '.join(_read_entry)
if not Path(f"{directory}{_read_entry}.gpg").is_file():
print(f"\n\u001b[38;5;1mError: entry ({_read_entry}) does not exist\u001b[0m\n")
s_exit(1)
_shm_folder, _shm_entry = shm_gen()
system(f"{gpg} -qd --output {tmp_dir}{_shm_folder}/{_shm_entry} '{directory}{_read_entry}.gpg'")
_copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
if uname()[0] == 'Haiku': # Haiku clipboard detection
if argument.startswith('copy username') or argument.startswith('copy -u'):
system('clipboard -c ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy password') or argument.startswith('copy -p'):
system('clipboard -c ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy url') or argument.startswith('copy -l'):
system('clipboard -c ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy note') or argument.startswith('copy -n'):
system('clipboard -c ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'")
Popen('sleep 30; clipboard -r', shell=True)
elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection
if argument.startswith('copy username') or argument.startswith('copy -u'):
system('termux-clipboard-set ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy password') or argument.startswith('copy -p'):
system('termux-clipboard-set ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy url') or argument.startswith('copy -l'):
system('termux-clipboard-set ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy note') or argument.startswith('copy -n'):
system('termux-clipboard-set ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'")
Popen("sleep 30; termux-clipboard-set ''", shell=True)
elif environ.get('WAYLAND_DISPLAY') == 'wayland-0': # Wayland clipboard detection
if argument.startswith('copy username') or argument.startswith('copy -u'):
system('wl-copy ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy password') or argument.startswith('copy -p'):
system('wl-copy ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy url') or argument.startswith('copy -l'):
system('wl-copy ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'")
elif argument.startswith('copy note') or argument.startswith('copy -n'):
system('wl-copy ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'")
Popen('sleep 30; wl-copy -c', shell=True)
else: # X11 clipboard detection
if argument.startswith('copy username') or argument.startswith('copy -u'):
system('echo -n ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument.startswith('copy password') or argument.startswith('copy -p'):
system('echo -n ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument.startswith('copy url') or argument.startswith('copy -l'):
system('echo -n ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument.startswith('copy note') or argument.startswith('copy -n'):
system('echo -n ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c')
Popen("sleep 30; echo -n '' | xclip -sel c", shell=True)
rmtree(f"{tmp_dir}{_shm_folder}")
def remove_data(): # deletes an entry from the server and flags it for local deletion on sync
if argument == 'shear' or argument == '-rm':
entry_list_gen()
_entry_name = str(input('What would you like to delete? '))
else:
_entry_name = argument.split(' ')
del _entry_name[:1]
_entry_name = ' '.join(_entry_name)
if _entry_name.startswith('/'):
_entry_name = _entry_name.replace('/', '', 1)
try:
system(f"{gpg} -qd --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(1)
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c "
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\")'\"")
if __name__ == "__main__":
try:
silent_sync = 0
# retrieve typed argument
argument_list, argument = argv, ''
del argument_list[0]
for _argument in argument_list:
argument += _argument + ' '
argument = argument[:-1]
if uname()[0] == 'Haiku': # set proper gpg command for OS
gpg = 'gpg --pinentry-mode loopback'
else:
gpg = 'gpg'
# 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(1)
else:
tweak()
s_exit(0)
# 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 == '':
no_arg()
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.startswith('add note') or argument.startswith('add -n') or argument.startswith('add password') \
or argument.startswith('add -p'):
add_entry()
elif argument.startswith('add folder') or argument.startswith('add -f'):
add_folder()
elif argument.startswith('edit rename') or argument.startswith('edit relocate') or argument.startswith(
'edit -r'):
silent_sync = 1
rename()
elif argument.startswith('edit username') or argument.startswith('edit -u') or argument.startswith(
'edit password') \
or argument.startswith('edit -p') or argument.startswith('edit url') or argument.startswith(
'edit -l') or \
argument.startswith('edit note') or argument.startswith('edit -n'):
edit()
elif argument.startswith('gen'):
gen()
elif argument.startswith('copy username') or argument.startswith('copy -u') or argument.startswith(
'copy password') \
or argument.startswith('copy -p') or argument.startswith('copy url') or argument.startswith('copy -l') \
or argument.startswith('copy note') or argument.startswith('copy -n'):
copy_data()
elif argument.startswith('shear') or argument.startswith('-rm'):
remove_data()
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(1)
# 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 not argument\
.startswith('copy username') and not argument.startswith('copy -u') and not argument\
.startswith('copy password') and not argument.startswith('copy -p') and not argument\
.startswith('copy url') and not argument.startswith('copy -l') and not argument.startswith('copy note')\
and not argument.startswith('copy -n') and argument != 'copy' and argument != 'version' and argument \
!= '-v' and error == 0 and argument.startswith('/') is False:
sync()
s_exit(0)
except KeyboardInterrupt:
print('\n')
s_exit(0)
Executable → Regular
+324 -135
View File
@@ -1,3 +1,194 @@
sshyp v1.2.0
the brisk bahh update
this release focuses on speeding up the sshyp user experience by adding
new features that reduce wasted time
compatibility-breaking changes:
- new configuration options (quick-unlock, offline mode) have been added and
the configuration files have been reorganized
^ simply running "sshyp tweak" and following the setup wizard will correct any compatibility
issues
- for quick-unlock security, device names have been replaced with more secure device ids
^ older device names are still compatible, but for security reasons it is recommended
to delete any pre-existing device names from the server and allow "sshyp tweak" to re-register
your devices
user-facing features:
- quick-unlock mode has been added
^ this allows you to use a shortened version of your password by verifying that your device
is whitelisted on your sshyp server - it's both faster and more secure than standard unlock,
but it requires an active connection to your sshyp server to authenticate (otherwise it will
fall back to standard unlock)
- full support for offline usage
^ though sshyp could be used without a server before, it now can be configured to not attempt
to find one ever - this saves time and hides sync failure error messages
- bash completions have been added
^ if you have bash-completion installed, you can now use the tab key in bash to auto-complete
sshyp arguments and entry names (client only, not added for server-specific arguments)
^ if you do not have bash-completion installed, you can source
/usr/share/bash-completion/completions/sshyp (Linux/BSD) or
/boot/system/data/bash-completion/completions/sshyp (Haiku) in your ~/.bashrc to
use this feature
fixes/optimizations:
- fixed entries with multi-word titles failing to decrypt
- password generation is now much faster and more resource efficient
- there is no longer a length limit on generated passwords
- improved visual consistency of help menus
- rarely used modules are now imported only when needed
- sshyp now uses one fewer configuration file
other notable changes:
- sshyp is now specifically licensed under the GPL-3.0-only (keyword: only)
- sshyp now has some possible arguments and its own help menu when running in server mode
- temporary files in /dev/shm are now generated with more complex names
- sshyp now installs in /usr/lib/sshyp (Linux/BSD) or /system/lib/sshyp (Haiku) instead of
/usr/bin or /bin (it is still symlinked to the old directories)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp v1.1.2
the sheecrets update - patch two
this is a general polish/bugfix release
user-facing features:
- packaging support for Alpine Linux/postmarketOS
- the rename() function is no longer unnecessarily verbose
- handled exception for when the user attempts to copy an entry field that does not exist
fixes/optimizations:
- replaced shebang with "#!/usr/bin/env python3" for improved compatibility with various systems
^ does not affect Haiku packaging
- fixed the generic package not actually being compressed
- reduced lines of code used for cross-device entry deletion
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp v1.1.1
the sheecrets update - patch one
this is a polish/bug fix release that makes tweaks to the entry format (without breaking compatibility)
compatibility-breaking changes:
- none; the entry format tweaks are backward compatible with sshyp v1.0.0+
^ the new format is slightly more efficient in terms of storage space
^ if you would like to upgrade to it, run this script (after updating to v1.1.1):
https://raw.githubusercontent.com/rwinkhart/sshyp-labs/main/extra/conversion-scripts/sshyp-refresh-1.1.1%2B.py
user-facing features:
- entries (when editing or adding) are now run through the new optimized_edit() function to strip trailing new lines
and ensure the format of the entries is fully compatible with all of sshyp's functions
fixes:
- when adding a note to an entry, there is no longer a chance the first note line will be added as a url
if the entry is using an older format/pass format
- the gpg auto-generation file temporarily created by sshyp no longer includes extra spaces
^ seems to serve no functional purpose - fixed for the sake of polish
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp v1.1.0
the sheecrets update
the main focus of this release was adding extension support (particularly for sshyp-mfa)
and cleaning up the configuration experience
compatibility-breaking changes:
- the entry directory has been moved from ~/.password-pasture to ~/.local/share/sshyp
as a means of complying with the XDG base directory spec
^ this requires the user to move their entry directory to the new location manually
^ if this is not done, sshyp will not be able to find entries made prior to v1.1.0
- due to a new configuration option (preferred text editor), 'sshyp tweak' must be run after updating
user-facing features:
- extension support
^ some of sshyp's critical functions can now be imported into other programs to extend
upon sshyp's functionality
^ the first usecase of this is sshyp-mfa, which can be found at https://github.com/rwinkhart/sshyp-labs
- a new configuration experience
^ the 'sshyp tweak' menu has been made much more readable, and now the automatically generated
gpg key has its id automatically input, making the process easier for the user
- customizable text editor
^ the text editor used for editing notes can now be set to any editor preferred by the user
^ this means that nano was dropped as a dependency
fixes:
- to avoid exceptions on server devices, all arguments (apart from 'tweak') have been disabled on servers
- fixed entry readout not printing blank lines between fields under certain conditions
- various optimizations
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp v1.0.1
The Polished Trotters Update - Patch 1
This is a hotfix for the Haiku decryption bug.
Changes:
- subprocess.Popen has been replaced with subprocess.run where applicable
- stdout is no longer captured with any subprocess.Popen or subprocess.run usages
^ this fixes decryption on Haiku
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp v1.0.0
The Polished Trotters Update
This release brings 'sshyp' in line with the original goals of the project.
As such, it is being crowned "v1.0.0", and is considered a stable base for future expansions.
Features:
- sshyp has been modified to run on Haiku, an open-source re-implementation of BeOS
^ new package formats have been added for Haiku, FreeBSD, and Fedora Linux
- the entry format has been changed to support entries created in pass/password-store
^ this change requires existing entry libraries to be converted - see the sshyp v1.0.0 release page on GitHub for a conversion script
- majorly overhauled visual experience for sshyp
^ this includes a new entry list, a new entry readout, colored output, ascii art, and more!
- entries can now optionally be passed as arguments, directly
^ as opposed to the user being prompted for an entry name after running a command
Changes:
- corrected outdated licensing and copyright information
- 'if __name__=="__main__":' convention is now used
- help screens have been overhauled
- improved password generator to guarantee more secure results
- fixed errors when trying to sync with a multi-word entry on the server
- sshync now uses 'scp' (via the sftp protocol), rather than 'sftp'
- rename function now properly allows for renaming folders
- renaming an entry/folder will now properly delete the old entry/folder from the server
- entry previews at the time of entry creation/editing no longer require entering the gpg password more times than necessary
- entries will no longer be overwritten if attempting to create a new entry that uses an already existing name
- the clipboard now automatically clears after 30 seconds
- sshyp server no longer needs to create copies of its libraries in ~/
- added more and improved existing exceptions
- the lock file is now decrypted to /dev/null
- ...and lots of minor (under the hood) changes!
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
sshyp 2022.02.16.fr4.7
The High-Tech Shears Update - Patch 7
@@ -17,28 +208,28 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- 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
- 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)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -59,29 +250,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -102,29 +293,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -149,29 +340,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -192,29 +383,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -236,29 +427,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -280,29 +471,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -331,29 +522,29 @@ Changes:
Planned for next major update (fr5, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr6, The Farmer Shearing the sshyp Update):
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -374,30 +565,30 @@ Changes:
Planned for next major update (fr4, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
** allow for multi-client deletion... somehow (in sshync)
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- allow for multi-client deletion... somehow (in sshync)
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -418,39 +609,39 @@ Changes:
Additions planned for minor releases:
** updated the manpage with more information regarding how sshyp works and how to set it up
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
** reduced total lines of code with small optimizations
- updated the manpage with more information regarding how sshyp works and how to set it up
- ensured that it is now impossible for ghosts of entires to remain in /dev/shm
- reduced total lines of code with small optimizations
&&
Planned for next major update (fr4, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
** allow for multi-client deletion... somehow (in sshync)
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- allow for multi-client deletion... somehow (in sshync)
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -468,39 +659,39 @@ Changes:
Additions planned for minor releases:
** updated the manpage with more information regarding how sshyp works and how to set it up
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
** reduced total lines of code with small optimizations
- updated the manpage with more information regarding how sshyp works and how to set it up
- ensured that it is now impossible for ghosts of entires to remain in /dev/shm
- reduced total lines of code with small optimizations
&&
Planned for next major update (fr4, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
** allow for multi-client deletion... somehow (in sshync)
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- allow for multi-client deletion... somehow (in sshync)
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -519,39 +710,39 @@ Changes:
Additions planned for minor releases:
** updated the manpage with more information regarding how sshyp works and how to set it up
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
** reduced total lines of code with small optimizations
- updated the manpage with more information regarding how sshyp works and how to set it up
- ensured that it is now impossible for ghosts of entires to remain in /dev/shm
- reduced total lines of code with small optimizations
&&
Planned for next major update (fr4, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
** allow for multi-client deletion... somehow (in sshync)
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- allow for multi-client deletion... somehow (in sshync)
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -574,39 +765,39 @@ Changes:
Additions planned for minor releases:
** updated the manpage with more information regarding how sshyp works and how to set it up
** ensured that it is now impossible for ghosts of entires to remain in /dev/shm
** reduced total lines of code with small optimizations
- updated the manpage with more information regarding how sshyp works and how to set it up
- ensured that it is now impossible for ghosts of entires to remain in /dev/shm
- reduced total lines of code with small optimizations
&&
Planned for next major update (fr4, The sshyp Doing a Split Update):
sshyp:
** sshyp has recieved a major visual overhaul
- 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
- sshync has been split into a separate package and now has standalone functionality as a backup/syncing utility
^ more details will be available in the sshync repo, once it is created
&&
Planned for next, next major update (fr5, The Farmer Shearing the sshyp Update):
** allow for multi-client deletion... somehow (in sshync)
** when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
** imporove password generator to guarantee more secure results
** enforce permissions on the server-side
** allow for copying entire notes (not just first line)
** ability to pass entries as arguments for more functions
- allow for multi-client deletion... somehow (in sshync)
- when syncing, a check is made to see if any folders are not on all devices - if the check comes back true, it is corrected (in sshyp)
- imporove password generator to guarantee more secure results
- enforce permissions on the server-side
- allow for copying entire notes (not just first line)
- ability to pass entries as arguments for more functions
&&
Backlog:
** create separate gui frontend targetting mobile and desktop Linux
** auto-completion on tab (currently unsure of best way to make this work)
- create separate gui frontend targetting mobile and desktop Linux
- auto-completion on tab (currently unsure of best way to make this work)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
@@ -1121,5 +1312,3 @@ What is currently functional:
- sort notes and passwords into folders
- gpg encryption
- edit password/note entries
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
+69 -28
View File
@@ -1,41 +1,52 @@
.TH sshyp 1 "22 May 2022" "v1.0.0" "sshyp man page"
.TH sshyp 1 "06 November 2022" "v1.2.0" "sshyp man page"
.SH NAME
sshyp \- A very simple self-hosted, synchronized password manager for UNIX systems. Alternative to (and compatible with) pass/password-store.
sshyp \- A very simple self-hosted, synchronized password manager for UNIX(-like) systems. Alternative to (and compatible with) pass/password-store.
.SH SYNOPSIS
sshyp [OPTION] [[FLAG]] [/<entry name>]
Client Usage: sshyp [option [flag] [<entry name>]] | [/<entry name>]
Server Usage: sshyp [option [flag] [<device id>]]
.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
.SH EXAMPLES (CLIENT)
Setting up sshyp for the first time or altering its configuration (also recommended after major updates):
sshyp tweak
Viewing the entry database:
sshyp
Reading an existing entry saved as ~/.password-pasture/development/github.gpg:
Reading an existing entry saved as ~/.local/share/sshyp/development/github.gpg:
sshyp /development/github
Copying the password of an existing entry saved as ~/.password-pasture/financial/bank.gpg:
Copying the password of an existing entry saved as ~/.local/share/sshyp/financial/bank.gpg:
sshyp copy -p /financial/bank
Editing the username of an existing entry saved as ~/.password-pasture/game.gpg:
Editing the username of an existing entry saved as ~/.local/share/sshyp/game.gpg:
sshyp edit -u game
Making a new entry saved as ~/.password-pasture/school/university.gpg using the built-in password generator:
Making a new entry saved as ~/.local/share/sshyp/school/university.gpg using the built-in password generator:
sshyp gen /school/university
Creating a note-only entry saved as ~/.password-pasture/notes/testNote.gpg:
Creating a note-only entry saved as ~/.local/share/sshyp/notes/testNote.gpg:
sshyp add -n /notes/testNote
Manually syncing entries with the server:
sshyp sync
Removing an existing folder saved as ~/.password-pasture/social:
Removing an existing folder saved as ~/.local/share/sshyp/social:
sshyp shear social/
.SH EXAMPLES (SERVER)
Setting up the quick-unlock whitelist:
sshyp whitelist setup
.SH OPTIONS
USAGE: sshyp [OPTION [FLAG] [<entry name>]] | [/<entry name>]
Checking the quick-unlock whitelist status of all registered client devices:
sshyp whitelist list
Adding a device with the id "laptop-im|lAoa;&;r&o:ez((g/Dz;EVb.nO_" to the quick-unlock whitelist:
sshyp whitelist add 'laptop-im|lAoa;&;r&o:ez((g/Dz;EVb.nO_'
Removing a device with the id "laptop-im|lAoa;&;r&o:ez((g/Dz;EVb.nO_" from the quick-unlock whitelist:
sshyp whitelist del 'laptop-im|lAoa;&;r&o:ez((g/Dz;EVb.nO_'
.SH OPTIONS (CLIENT)
help/--help/-h bring up the help menu
version/-v display sshyp version info
tweak configure sshyp
@@ -45,24 +56,38 @@ USAGE: sshyp [OPTION [FLAG] [<entry name>]] | [/<entry name>]
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
.SH FLAGS (CLIENT)
add:
password/-p add a password entry
note/-n add a note entry
folder/-f add a new folder for entries
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
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
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
update/-u generate a password for an existing entry
.SH OPTIONS (SERVER)
help/--help/-h bring up this menu
version/-v display sshyp version info
tweak configure sshyp
whitelist manage the quick-unlock whitelist
.SH FLAGS (SERVER)
whitelist:
setup set up the quick-unlock whitelist
list/-l view all registered device ids and their quick-unlock whitelist status
add whitelist a device id for quick-unlock
delete/del remove a device id from the quick-unlock whitelist
.SH LIMITATIONS
The following characters/character sequences are not supported in entry/folder titles:
@@ -73,19 +98,35 @@ sshyp operates on a client-server model, and thus requires you to have access to
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)
Configure an OpenSSH server (if sshyp was installed from the Debian package, openssh-server and openssh-sftp-server must be installed manually - if sshyp was installed from the Fedora package, openssh-server must 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
Optionally, run "sshyp whitelist setup" and configure quick-unlock
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.)
Copy the generated public SSH key (located at ~/.ssh/sshyp.pub) to the server using preferred method (manually adding to authorized_keys, ssh-copy-id, etc.)
If you already have entries on the server, sync them using "sshyp sync"
Optionally, Bash completions can be enabled by installing your distribution's "bash-completion" package and restarting your terminal
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 EXIT CODES
0 - no error
1 - argument error
2 - configuration error
3 - data not found error
4 - data already exists error
5 - decryption/encryption error
6 - server data retrieval error
.SH AUTHOR
Randall Winkhart (https://github.com/rwinkhart)
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
_path_gen() {
local sshyp_path="$HOME/.local/share/sshyp"
local sshyp_path_length="$(("${#sshyp_path}" + 1))"
readarray -t full_paths < <(find "$sshyp_path" -type f -exec ls {} \;)
for path in "${full_paths[@]}"; do
trimmed_path=$(echo ${path%????} | cut -c"$sshyp_path_length"-)
trimmed_path=$(echo ${trimmed_path// /\\ })
trimmed_paths+=("$trimmed_path")
done
} &&
# from this point, this completions script was partially generated by
# completely (https://github.com/dannyben/completely)
_sshyp_completions() {
if [ "${#COMP_WORDS[@]}" -gt "4" ]; then
return
fi
local cur=${COMP_WORDS[COMP_CWORD]}
local compline="${COMP_WORDS[@]:1:$COMP_CWORD-1}"
case "$compline" in
'add password'* | 'add -p'* | 'add note'* | 'add -n'* | 'add folder'*| 'add -f'* | 'edit relocate'* | 'edit -r'* | 'edit username'* | 'edit -u'* | 'edit password'* | 'edit -p'* | 'edit url'* | 'edit -l'* | 'edit note'* | 'edit -n'* | 'copy username'* | 'copy -u'* | 'copy password'* | 'copy -p'* | 'copy note'* | 'copy -n'* | 'copy url'* | 'copy -l'* | 'gen update'* | 'gen -u'*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "$(printf "'%s' " "${trimmed_paths[@]}")" -- "$cur" )
;;
'edit'*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "relocate username password note url" -- "$cur" )
;;
'copy'*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "username password url note" -- "$cur" )
;;
'add'*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "password note folder" -- "$cur" )
;;
'gen'*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "update" -- "$cur" )
;;
*)
while read; do COMPREPLY+=( "$REPLY" ); done < <( compgen -W "help version tweak add gen edit copy shear sync $(printf "'%s' " "${trimmed_paths[@]}")" -- "$cur" )
;;
esac
} &&
_path_gen && complete -F _sshyp_completions sshyp
-48
View File
@@ -1,48 +0,0 @@
#!/bin/python3
from os import path, remove, system, walk
from pathlib import Path
from shutil import move, rmtree
if __name__ == "__main__":
gpg_id = input('\nWhat is the ID of the GPG key you would like to use for re-encryption?\n\nID: ')
pasture = path.expanduser('~/.password-pasture')
if Path(f"{pasture}.new").exists():
rmtree(f"{pasture}.new")
if Path(f"{pasture}.old").exists():
rmtree(f"{pasture}.old")
if path.isdir(pasture):
for dirPath, dirNames, filenames in walk(pasture):
for filename in sorted(filenames):
Path(dirPath.replace(pasture, pasture + '.new')).mkdir(0o700, parents=True, exist_ok=True)
system(f"gpg -d '{dirPath}/{filename}' "
f"> '{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}'")
_old_contents, _new_contents = \
open(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}", 'r').readlines(), ''
for _num in range(len(_old_contents)):
if _num == 0:
try:
_new_contents += _old_contents[1]
except IndexError:
_new_contents += '\n'
elif _num == 1:
_new_contents += _old_contents[0]
elif _num == 3:
if _old_contents[_num] == ' ' or _old_contents[_num] == '\n':
pass
else:
_new_contents += _old_contents[_num]
else:
_new_contents += _old_contents[_num]
for _num in reversed(range(len(_new_contents))):
if _new_contents[_num] == '\n' or _new_contents[_num] == '':
_new_contents = _new_contents[:-1]
else:
break
open(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}", 'w').writelines(_new_contents)
system(f"gpg -qr {str(gpg_id)} -e '{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}'")
remove(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}")
else:
print(f"\nError: no entry folder ({pasture}) found\n")
move(pasture, f"{pasture}.old")
move(f"{pasture}.new", pasture)
-41
View File
@@ -1,41 +0,0 @@
#!/bin/python3
from os import path, remove, system, walk
from pathlib import Path
from shutil import move, rmtree
if __name__ == "__main__":
gpg_id = input('\nWhat is the ID of the GPG key you would like to use for re-encryption?\n\nID: ')
pasture = path.expanduser('~/.password-pasture')
if Path(f"{pasture}.new").exists():
rmtree(f"{pasture}.new")
if Path(f"{pasture}.old").exists():
rmtree(f"{pasture}.old")
if path.isdir(pasture):
for dirPath, dirNames, filenames in walk(pasture):
for filename in sorted(filenames):
Path(dirPath.replace(pasture, pasture + '.new')).mkdir(0o700, parents=True, exist_ok=True)
system(f"gpg -d '{dirPath}/{filename}' "
f"> '{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}'")
_old_contents, _new_contents = \
open(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}", 'r').readlines(), ''
for _num in range(len(_old_contents)):
if _num == 3:
if _old_contents[_num] == ' ' or _old_contents[_num] == '\n':
pass
else:
_new_contents += _old_contents[_num]
else:
_new_contents += _old_contents[_num]
for _num in reversed(range(len(_new_contents))):
if _new_contents[_num] == '\n' or _new_contents[_num] == '':
_new_contents = _new_contents[:-1]
else:
break
open(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}", 'w').writelines(_new_contents)
system(f"gpg -qr {str(gpg_id)} -e '{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}'")
remove(f"{dirPath.replace(pasture, pasture + '.new')}/{filename[:-4]}")
else:
print(f"\nError: no entry folder ({pasture}) found\n")
move(pasture, f"{pasture}.old")
move(f"{pasture}.new", pasture)
+20 -19
View File
@@ -1,16 +1,16 @@
#!/bin/python3
#!/usr/bin/env python3
# external modules
from os import path, system, walk
from os.path import expanduser, getmtime, join
from pathlib import Path
from sys import exit as s_exit
# utility functions
def get_titles_mods(_directory, _destination, _user_data):
def get_titles_mods(_directory, _destination, _user_data): # fetches and returns lists of titles and their mod times
from pathlib import Path
_title_list, _mod_list = [], []
Path(path.expanduser('~/.config/sshync')).mkdir(0o700, parents=True, exist_ok=True) # create config directory
# local fetching
@@ -27,8 +27,9 @@ def get_titles_mods(_directory, _destination, _user_data):
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]} \"cd /bin; python -c 'impo"
f"rt sshync; sshync.get_titles_mods(\"'\"{_user_data[4]}\"'\", \"'\"l\"'\", \"'\"{_user_data}\"'\")'\"")
system(f"ssh -i '{_user_data[5]}' -p {_user_data[2]} {_user_data[0]}@{_user_data[1]} \"cd /lib/sshyp; python -c"
f" 'import sshync; sshync.get_titles_mods(\"'\"{_user_data[4]}\"'\", \"'\"l\"'\", \"'\"{_user_data}"
f"\"'\")'\"")
system(f"scp -pqs -P {_user_data[2]} -i '{_user_data[5]}' {_user_data[0]}@{_user_data[1]}:"
f"'/home/{_user_data[0]}/.config/sshync/database' '{expanduser('~/.config/sshync/')}'")
_titles, _sep, _mods = '*&^'.join(open(expanduser('~/.config/sshync/database')).readlines()).replace('\n', '')\
@@ -37,7 +38,8 @@ def get_titles_mods(_directory, _destination, _user_data):
return _title_list, _mod_list
def sort_titles_mods(_list_1, _list_2):
def sort_titles_mods(_list_1, _list_2): # creates and returns two lists (of titles and mod times) generated by sorting
# information from two different, provided lists
_title_list_2_sorted, _mod_list_2_sorted = [], []
# title sorting
for _title in _list_1[0]:
@@ -52,29 +54,28 @@ def sort_titles_mods(_list_1, _list_2):
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 make_profile(_profile_dir, _local_dir, _remote_dir, _identity, _ip, _port, _user): # creates a sshync job profile
open(_profile_dir, 'w').write(f"{_user}\n{_ip}\n{_port}\n{_local_dir}\n{_remote_dir}\n{_identity}\n")
def get_profile(_profile_dir):
def get_profile(_profile_dir): # returns a list of data read from a sshync job profile
try:
_profile_data = open(_profile_dir).readlines()
except (FileNotFoundError, IndexError):
print('\nEither the profile does not exist, or it is corrupted.\n')
print('\n\u001b[38;5;9merror: the profile does not exist or is corrupted.\u001b[0m\n')
_profile_data = None
s_exit(1)
s_exit(3)
# 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', '')
_user = _profile_data[0].rstrip()
_ip = _profile_data[1].rstrip()
_port = _profile_data[2].rstrip()
_local_dir = _profile_data[3].rstrip()
_remote_dir = _profile_data[4].rstrip()
_identity = _profile_data[5].rstrip()
return _user, _ip, _port, _local_dir, _remote_dir, _identity
def run_profile(_profile_dir):
def run_profile(_profile_dir): # runs a sshync job profile
_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))
Executable
+966
View File
@@ -0,0 +1,966 @@
#!/usr/bin/env python3
# external modules
from os import environ, listdir, path, remove, system, uname, walk
from pathlib import Path
from random import randint, SystemRandom
from shutil import get_terminal_size, move, rmtree
import sshync
from subprocess import CalledProcessError, Popen, PIPE, run
from sys import argv, exit as s_exit
# BELOW - utility functions
def entry_list_gen(_directory=path.expanduser('~/.local/share/sshyp/')): # generates and prints full entry list
from textwrap import fill
print('\n\u001b[38;5;0;48;5;15msshyp entries:\u001b[0m\n')
_entry_list, _color_alternator = [], 1
for _entry in sorted(listdir(_directory)):
if Path(f"{_directory}{_entry}").is_file():
if _color_alternator == 1:
_entry_list.append(f"{_entry.replace('.gpg', '')}")
_color_alternator = 2
else:
_entry_list.append(f"\u001b[38;5;8m{_entry.replace('.gpg', '')}\u001b[0m")
_color_alternator = 1
_real = len(' '.join(_entry_list)) - (5.5 * len(_entry_list))
if _real <= get_terminal_size()[0]:
_width = len(' '.join(_entry_list))
else:
_width = (len(' '.join(_entry_list)) / (_real / get_terminal_size()[0]) - 25)
try:
print(fill(' '.join(_entry_list), width=_width) + '\n')
except ValueError:
pass
for _root, _directories, _files in walk(_directory):
for _dir in sorted(_directories):
_inner_dir = f"{_root.replace(_directory, '')}/{_dir}"
print(f"\u001b[38;5;15;48;5;238m{_inner_dir}/\u001b[0m")
_entry_list, _color_alternator = [], 1
for _s_root, _s_directories, _s_files in walk(f"{_directory[:-1]}{_inner_dir}"):
for _entry in sorted(_s_files):
if _color_alternator == 1:
_entry_list.append(f"{_entry.replace('.gpg', '')}")
_color_alternator = 2
else:
_entry_list.append(f"\u001b[38;5;8m{_entry.replace('.gpg', '')}\u001b[0m")
_color_alternator = 1
_real = len(' '.join(_entry_list)) - (5.5 * len(_entry_list))
if _real <= get_terminal_size()[0]:
_width = len(' '.join(_entry_list))
else:
_width = (len(' '.join(_entry_list)) / (_real / get_terminal_size()[0]) - 25)
try:
print(fill(' '.join(_entry_list), width=_width) + '\n')
except ValueError:
print('\u001b[38;5;9m-empty directory-\u001b[0m\n')
def entry_reader(_decrypted_entry): # displays the contents of an entry in a readable format
_entry_lines, _notes_flag = open(_decrypted_entry, 'r').readlines(), 0
print()
for _num in range(len(_entry_lines)):
try:
if _num == 0 and _entry_lines[1] != '\n':
print(f"\u001b[38;5;15;48;5;238musername:\u001b[0m\n{_entry_lines[1].strip()}\n")
elif _num == 1 and _entry_lines[0] != '\n':
print(f"\u001b[38;5;15;48;5;238mpassword:\u001b[0m\n{_entry_lines[0].strip()}\n")
elif _num == 2 and _entry_lines[2] != '\n':
print(f"\u001b[38;5;15;48;5;238murl:\u001b[0m\n{_entry_lines[_num].strip()}\n")
elif _num >= 3 and _entry_lines[_num] != '\n' and _notes_flag != 1:
_notes_flag = 1
print(f"\u001b[38;5;15;48;5;238mnotes:\u001b[0m\n{_entry_lines[_num].strip()}")
elif _num >= 3 and _notes_flag == 1:
print(_entry_lines[_num].replace('\n', ''))
if _notes_flag == 1:
try:
_line_test = _entry_lines[_num + 1]
except IndexError:
print()
except IndexError:
if _num == 0:
print(f"\u001b[38;5;15;48;5;238mpassword:\u001b[0m\n{_entry_lines[0]}\n")
def entry_name_fetch(_entry_name_location): # fetches and returns entry name from user input or from provided argument
if type(_entry_name_location) == str:
entry_list_gen()
_entry_name = str(input(_entry_name_location))
else:
_entry_name_split = argument.split(' ')
del _entry_name_split[:_entry_name_location]
_entry_name = ' '.join(_entry_name_split)
if _entry_name.startswith('/'):
return _entry_name.replace('/', '', 1)
else:
return _entry_name
def string_gen(_complexity, _length): # generates and returns a random string based on input
import string
if _complexity == 's':
_character_pool = string.ascii_letters + string.digits
elif _complexity == 'f':
_character_pool = string.digits + string.ascii_letters + string.punctuation.replace('/', '').replace('\\', '')\
.replace("'", '').replace('"', '').replace('`', '').replace('~', '')
else:
_character_pool = string.digits + string.ascii_letters + string.punctuation
_min_special, _special = round(.2 * _length), 0
while True:
_gen = ''.join(SystemRandom().choice(_character_pool) for _ in range(_length))
for _character in _gen:
if not _character.isalpha():
_special += 1
if _special >= _min_special:
break
return _gen
def pass_gen(): # prompts the user for necessary information to generate a password and passes it to string_gen
try:
_length = int(input('password length: '))
except ValueError:
print(f"\n\u001b[38;5;9merror: a non-integer value was input for password length\u001b[0m\n")
_gen = pass_gen()
return _gen
_complexity = str(input('password complexity - simple (for compatibility) or complex (for security)? (s/C) '))
if _complexity != 's' and _complexity != 'S':
_complexity = 'c'
_gen = string_gen(_complexity.lower(), _length)
return _gen
def shm_gen(_tmp_dir=path.expanduser('~/.config/sshyp/tmp/')): # creates a temporary directory for entry editing
_shm_folder_gen = string_gen('f', randint(12, 48))
_shm_entry_gen = string_gen('f', randint(12, 48))
Path(_tmp_dir + _shm_folder_gen).mkdir(0o700)
return _shm_folder_gen, _shm_entry_gen
def encrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, _gpg_id, _tmp_dir=path.expanduser('~/.config/sshyp/tmp/')):
# encrypts an entry and cleans up the temporary files
system(f"{_gpg_com} -qr {str(_gpg_id)} -e '{_tmp_dir}{_shm_folder}/{_shm_entry}'")
move(f"{_tmp_dir}{_shm_folder}/{_shm_entry}.gpg", f"{_entry_dir}.gpg")
rmtree(f"{_tmp_dir}{_shm_folder}")
def decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, _quick_pass,
_tmp_dir=path.expanduser('~/.config/sshyp/tmp/')): # decrypts an entry to a temporary directory
if not isinstance(_quick_pass, bool):
_unlock_method = f"gpg --pinentry-mode loopback --passphrase '{_quick_pass}' -qd --output "
else:
_unlock_method = f"{_gpg_com} -qd --output "
if _shm_folder == 0 and _shm_entry == 0:
_output_target = f"/dev/null {path.expanduser('~/.config/sshyp/lock.gpg')}"
else:
_output_target = f"'{_tmp_dir}{_shm_folder}/{_shm_entry}' '{_entry_dir}.gpg'"
try:
run(_unlock_method + _output_target, shell=True, stderr=PIPE, check=True, close_fds=True)
except CalledProcessError:
if not isinstance(_quick_pass, bool):
print('\n\u001b[38;5;9merror: quick-unlock failed as a result of an incorrect passphrase, an unreachable '
'sshyp server, or an invalid configuration\n\nfalling back to standard unlock\u001b[0m\n')
try:
run(f"{_gpg_com} -qd --output {_output_target}", shell=True, stderr=PIPE, check=True,
close_fds=True)
except CalledProcessError:
print('\n\u001b[38;5;9merror: could not decrypt - ensure the correct gpg key is present\u001b[0m\n')
s_exit(5)
else:
print('\n\u001b[38;5;9merror: could not decrypt - ensure the correct gpg key is present\u001b[0m\n')
s_exit(5)
def determine_decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com):
if quick_unlock_enabled == 'y':
decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, whitelist_verify(port, username_ssh, ip,
client_device_id))
else:
decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, False)
def optimized_edit(_lines, _edit_data, _edit_line): # ensures an edited entry is optimized for best compatibility
while len(_lines) < _edit_line + 1:
_lines += ['\n']
if _edit_data is not None:
_lines[_edit_line] = _edit_data.strip('\n').rstrip() + '\n'
for _num in range(len(_lines)):
if not _lines[_num].endswith('\n'):
_lines[_num] += '\n'
for _num in reversed(range(len(_lines))):
if _lines[_num] == '\n':
_lines = _lines[:-1]
elif _lines[_num].endswith('\n'):
_lines[_num] = _lines[_num].rstrip()
break
else:
break
return _lines
def edit_note(_shm_folder, _shm_entry, _lines): # edits the note attached to an entry
_reg_lines = _lines[0:3]
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'w').writelines(_lines[3:])
system(f"{editor} '{tmp_dir}{_shm_folder}/{_shm_entry}-n'")
_new_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n").readlines()
while len(_reg_lines) < 3:
_reg_lines += ['\n']
_noted_lines = _reg_lines + _new_notes
return _noted_lines
def copy_id_check(_port, _username_ssh, _ip, _client_device_id):
# attempts to connect to the user's server via ssh to register the device for syncing
_command = f"ssh -o ConnectTimeout=3 -i '{path.expanduser('~/.ssh/sshyp')}' -p {_port} {_username_ssh}@{_ip} " \
f"\"touch '/home/{_username_ssh}/.config/sshyp/devices/{_client_device_id}'\""
try:
run(_command, shell=True, stderr=PIPE, check=True, close_fds=True)
except CalledProcessError:
print('\n\u001b[38;5;9mwarning: ssh connection could not be made - ensure the public key (~/.ssh/sshyp.pub) is '
'registered on the remote server and that the entered ip, port, and username are correct\n\nsyncing '
'functionality will be disabled until this is addressed\u001b[0m\n')
open(path.expanduser('~/.config/sshyp/ssh-error'), 'w').write('1')
return 1
open(path.expanduser('~/.config/sshyp/ssh-error'), 'w').write('0')
return 0
# BELOW - argument-specific functions
def tweak(): # runs configuration wizard
_divider = f"\n{'=' * (get_terminal_size()[0] - int((.5 * get_terminal_size()[0])))}\n\n"
# config directory creation
Path(path.expanduser('~/.config/sshyp/devices')).mkdir(0o700, parents=True, exist_ok=True)
if not Path(f"{path.expanduser('~/.config/sshyp/tmp')}").exists():
if uname()[0] == 'Haiku' or uname()[0] == 'FreeBSD':
system(f"ln -s /tmp {path.expanduser('~/.config/sshyp/tmp')}")
elif 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('\nclient or server installation? (C/s) ')
if _device_type.lower() == 's':
_sshyp_data = ['server']
Path(path.expanduser('~/.config/sshyp/deleted')).mkdir(0o700, exist_ok=True)
Path(path.expanduser('~/.config/sshyp/whitelist')).mkdir(0o700, exist_ok=True)
print(f"\n\u001b[4;1mmake sure the ssh service is running and properly configured\u001b[0m")
else:
_sshyp_data = ['client']
Path(path.expanduser('~/.local/share/sshyp')).mkdir(0o700, parents=True, exist_ok=True)
# gpg configuration
_gpg_gen = input(f"{_divider}sshyp requires the use of a unique gpg key - use an (e)xisting key or (g)enerate a"
f" new one? (E/g) ")
if _gpg_gen.lower() != 'g':
system(f"{gpg} -k")
_sshyp_data += [str(input('gpg key id: '))]
else:
print('\na unique gpg key is being generated for you...')
if not Path(path.expanduser('~/.config/sshyp/gpg-gen')).is_file():
open(path.expanduser('~/.config/sshyp/gpg-gen'), 'w').writelines([
'Key-Type: 1\n', 'Key-Length: 4096\n', 'Key-Usage: sign encrypt\n', 'Name-Real: sshyp\n',
'Name-Comment: gpg-sshyp\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n', 'Expire-Date: 0'])
if uname()[0] == 'Haiku':
run(gpg + ' --batch --generate-key --passphrase ' + "'" +
input('\ngpg passphrase: ') + "'" + " '" +
path.expanduser('~/.config/sshyp/gpg-gen') + "'", shell=True)
else:
run(f"{gpg} --batch --generate-key '{path.expanduser('~/.config/sshyp/gpg-gen')}'", shell=True)
remove(path.expanduser('~/.config/sshyp/gpg-gen'))
_sshyp_data += [run(f"{gpg} -k", shell=True, stdout=PIPE, text=True).stdout.split('\n')[-4].strip()]
# text editor configuration
_sshyp_data += [input(f"{_divider}example input: vim\n\npreferred text editor: ")]
# lock file generation
if Path(path.expanduser('~/.config/sshyp/lock.gpg')).is_file():
remove(path.expanduser('~/.config/sshyp/lock.gpg'))
open(path.expanduser('~/.config/sshyp/lock'), 'w')
system(f"{gpg} -qr {str(_sshyp_data[1])} -e {path.expanduser('~/.config/sshyp/lock')}")
remove(path.expanduser('~/.config/sshyp/lock'))
# ssh key configuration
_offline_mode = False
_ssh_gen = (input(f"{_divider}make sure the ssh service on the remote server is running and properly "
f"configured\n\nsync support requires a unique ssh key - would you like to have this "
f"automatically generated? (Y/n/o(ffline)) "))
if _ssh_gen.lower() != 'n' and _ssh_gen.lower() != 'o' and _ssh_gen.lower() != 'offline':
if uname()[0] == 'Haiku':
Path(f"{path.expanduser('~')}/.ssh").mkdir(0o700, exist_ok=True)
system('ssh-keygen -t ed25519 -f ~/.ssh/sshyp')
elif _ssh_gen.lower() == 'n':
print(f"\n\u001b[4;1mensure that the key file you are using is located at "
f"{path.expanduser('~/.ssh/sshyp')}\u001b[0m")
elif _ssh_gen.lower() == 'o' or _ssh_gen.lower() == 'offline':
_offline_mode = True
print('\nsshyp has been set to offline mode - to enable syncing, run "sshyp tweak" again')
if not _offline_mode:
# ssh ip+port configuration
_ip_port = str(input(f"{_divider}example input: 10.10.10.10:9999\n\nip and ssh port of sshyp server: "))
_ip, _sep, _port = _ip_port.partition(':')
# ssh user configuration
_username_ssh = str(input('\nusername of the remote server: '))
# sshync profile generation
sshync.make_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'),
path.expanduser('~/.local/share/sshyp/'), f"/home/{_username_ssh}/.local/share/sshyp/",
path.expanduser('~/.ssh/sshyp'), _ip, _port, _username_ssh)
# device id configuration
for _id in listdir(path.expanduser('~/.config/sshyp/devices')): # remove existing device id
remove(f"{path.expanduser('~/.config/sshyp/devices/')}{_id}")
print(f"{_divider}\u001b[4;1mimportant:\u001b[0m this id \u001b[4;1mmust\u001b[0m be unique amongst your "
f"client devices\n\nthis is used to keep track of database syncing and quick-unlock permissions\n")
_device_id_prefix = str(input('device id: ')) + '-'
_device_id_suffix = string_gen('f', randint(24, 48))
_device_id = _device_id_prefix + _device_id_suffix
open(f"{path.expanduser('~/.config/sshyp/devices/')}{_device_id}", 'w')
# quick-unlock configuration
print(f"{_divider}this allows you to use a shorter version of your gpg key password and\n"
f"requires a constant connection to your sshyp server to authenticate")
_sshyp_data += [input('\nenable quick-unlock? (y/N) ').lower()]
if _sshyp_data[3] == 'y':
print(f"\nquick-unlock has been enabled client-side - in order for this device to be able to read "
f"entries,\nyou must first login to the sshyp server and run:\n\nsshyp whitelist setup "
f"(if not already done)\nsshyp whitelist add '{_device_id}'")
# test server connection and attempt to register device id
copy_id_check(_port, _username_ssh, _ip, _device_id)
elif Path(path.expanduser('~/.config/sshyp/sshyp.sshync')).is_file():
remove(path.expanduser('~/.config/sshyp/sshyp.sshync'))
# write main config file (sshyp-data)
with open(path.expanduser('~/.config/sshyp/sshyp-data'), 'w') as _config_file:
_lines = 0
for _item in _sshyp_data:
_lines += 1
_config_file.write(_item + '\n')
while _lines < 4:
_lines += 1
_config_file.write('n')
print(f"{_divider}configuration complete\n")
def print_info(): # prints help text based on argument
if argument_list[1] == 'help' or argument_list[1] == '--help' or argument_list[1] == '-h':
print('\n\u001b[1msshyp copyright (c) 2021-2022 randall winkhart\u001b[0m\n')
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")
if device_type == 'client':
print('\n\u001b[1musage:\u001b[0m sshyp [option [flag] [<entry name>]] | [/<entry name>]\n')
print('\u001b[1moptions:\u001b[0m')
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')
print('\n\u001b[1mflags:\u001b[0m')
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(' url/-l change the url attached to an entry')
print(' note/-n change the note 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')
print("\n\u001b[1mtip:\u001b[0m you can quickly read an entry with 'sshyp /<entry name>'\n")
else:
print('\n\u001b[1musage:\u001b[0m sshyp [option [flag] [<device id>]]\n')
print('\u001b[1moptions:\u001b[0m')
print('help/--help/-h bring up this menu')
print('version/-v display sshyp version info')
print('tweak configure sshyp')
print('whitelist manage the quick-unlock whitelist')
print('\n\u001b[1mflags:\u001b[0m')
print('whitelist:')
print(' setup set up the quick-unlock whitelist')
print(' list/-l view all registered device ids and their quick-unlock whitelist status')
print(' add whitelist a device id for quick-unlock')
print(' delete/del remove a device id from the quick-unlock whitelist\n')
elif argument_list[1] == 'version' or argument_list[1] == '-v':
print('\nsshyp is a simple, self-hosted, sftp-synchronized password manager\nfor unix(-like) systems (haiku/'
'freebsd/linux/termux)\n\nsshyp is a viable alternative to (and compatible with) pass/password-store\n')
print(" .. \u001b[38;5;9m♥♥ ♥♥\u001b[0m ..\n .''.''/()\\ \u001b[38;5;13m"
"♥♥♥♥♥♥♥\u001b[0m /()\\''.''.\n * : \u001b[38;5;9m♥♥♥♥♥\u001b[0m : *"
"\n `..'..' \u001b[38;5;13m♥♥♥\u001b[0m `..'..'\n // \\\\ "
"\u001b[38;5;9m♥\u001b[0m // \\\\")
print('\u001b[38;5;7;48;5;8m<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m '
'\u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m \u001b[38;5;15;48;5;8msshyp copyright (c) 2021-2022 '
'randall winkhart\u001b[38;5;15;48;5;15m \u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m '
'\u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m \u001b[38;5;15;48;5;8mversion 1.2.0'
'\u001b[38;5;15;48;5;15m \u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m \u001b[38;5;15;48;5;8mthe brisk bahh '
'update\u001b[38;5;15;48;5;15m \u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m '
'\u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\u001b[0m\n')
print('see https://github.com/rwinkhart/sshyp for more information\n')
elif argument_list[1] == 'license':
print('\nThis program is free software: you can redistribute it and/or modify it under the terms\nof version 3 '
'(only) of the GNU General Public License as published by the Free Software Foundation.\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_list[1] == 'add':
print('\n\u001b[1musage:\u001b[0m sshyp add [flag [<entry name>]]\u001b[0m\n')
print('\u001b[1mflags:\u001b[0m')
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_list[1] == 'edit':
print('\n\u001b[1musage:\u001b[0m sshyp edit [flag [<entry name>]]\u001b[0m\n')
print('\u001b[1mflags:\u001b[0m')
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_list[1] == 'copy':
print('\n\u001b[1musage:\u001b[0m sshyp copy [flag [<entry name>]]\u001b[0m\n')
print('\u001b[1mflags:\u001b[0m')
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')
elif argument_list[1] == 'whitelist':
if device_type == 'server':
print('\n\u001b[1musage:\u001b[0m sshyp whitelist [flag [<device id>]]\u001b[0m\n')
print('\u001b[1mflags:\u001b[0m')
print('whitelist:')
print(' setup set up the quick-unlock whitelist')
print(' list/-l view all registered device ids and their quick-unlock whitelist status')
print(' add whitelist a device id for quick-unlock')
print(' delete/del remove a device id from the quick-unlock whitelist\n')
else:
print('\n\u001b[38;5;9merror: argument (whitelist) only available on server\u001b[0m\n')
s_exit(0)
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'")
_entry_name = entry_name_fetch('entry to read: ')
if not Path(f"{directory}{_entry_name}.gpg").exists():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(3)
_shm_folder, _shm_entry = shm_gen()
determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}")
def read_shortcut(): # shortcut to quickly read an entry
if not Path(f"{directory}{argument.replace('/', '', 1)}.gpg").exists():
print(f"\n\u001b[38;5;9merror: entry ({argument.replace('/', '', 1)}) does not exist\u001b[0m\n")
s_exit(3)
_shm_folder, _shm_entry = shm_gen()
determine_decrypt(directory + argument.replace('/', '', 1), _shm_folder, _shm_entry, gpg)
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}")
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} \"cd /lib/sshyp; python -c "
f"'import sshypRemote; sshypRemote.deletion_check(\"'\"{client_device_id}\"'\")'\"")
system(f"scp -pqs -P {port} -i '{path.expanduser('~/.ssh/sshyp')}' {username_ssh}@{ip}:'/home/{username_ssh}"
f"/.config/sshyp/deletion_database' {path.expanduser('~/.config/sshyp/')}")
try:
_deletion_database = open(path.expanduser('~/.config/sshyp/deletion_database')).readlines()
except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;9merror: the deletion database does not exist or is corrupted\u001b[0m\n')
_deletion_database = None
s_exit(6)
for _file in _deletion_database:
try:
if silent_sync != 1:
print(f"\u001b[38;5;208m{_file[:-1]}\u001b[0m has been sheared, removing...")
if _file[:-1].endswith('/'):
rmtree(f"{directory}{_file[:-1]}")
else:
remove(f"{directory}{_file[:-1]}.gpg")
except FileNotFoundError:
if silent_sync != 1:
print('location does not exist locally')
# check for new folders
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /lib/sshyp; python -c "
f"'import sshypRemote; sshypRemote.folder_check()'\"")
system(f"scp -pqs -P {port} -i '{path.expanduser('~/.ssh/sshyp')}' {username_ssh}@{ip}:'/home/{username_ssh}"
f"/.config/sshyp/folder_database' {path.expanduser('~/.config/sshyp/')}")
try:
_folder_database = open(path.expanduser('~/.config/sshyp/folder_database')).readlines()
except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;9merror: the folder database does not exist or is corrupted\u001b[0m\n')
_folder_database = None
s_exit(6)
for _folder in _folder_database:
if Path(f"{path.expanduser('~')}{_folder[:-1]}").is_dir():
pass
else:
print(f"\u001b[38;5;2m{_folder.replace('/.local/share/sshyp/', '')[:-1]}/\u001b[0m does not exist locally, "
f"creating...")
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 whitelist_setup(): # takes input from the user to set up quick-unlock password
_gpg_password_temp = str(input('\nfull gpg passphrase: '))
_half_length = int(len(_gpg_password_temp)/2)
try:
_short_password_length = int(input(f"\nquick unlock pin length (must be half the length of gpg password or "
f"less) ({_half_length}): "))
if _short_password_length > _half_length:
_short_password_length = _half_length
except ValueError:
_short_password_length = _half_length
_i, _quick_unlock_password, _quick_unlock_password_excluded = 0, '', ''
for _char in _gpg_password_temp:
if _i % 2 == 1 and _i < _short_password_length*2:
_quick_unlock_password += _char
else:
_quick_unlock_password_excluded += _char
_i += 1
# create assembly key
open(path.expanduser('~/.config/sshyp/gpg-gen'), 'w').writelines([
'Key-Type: 1\n', 'Key-Length: 4096\n', 'Key-Usage: sign encrypt\n', 'Name-Real: sshyp\n',
'Name-Comment: gpg-sshyp-whitelist\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n', 'Expire-Date: 0'])
run('gpg -q --pinentry-mode loopback --batch --generate-key --passphrase ' + "'" + _quick_unlock_password + "'" +
" '" + path.expanduser('~/.config/sshyp/gpg-gen') + "'", shell=True)
remove(path.expanduser('~/.config/sshyp/gpg-gen'))
_gpg_id = run(f"{gpg} -k", shell=True, stdout=PIPE, text=True).stdout.split('\n')[-4].strip()
# encrypt excluded with the assembly key
_shm_folder, _shm_entry = shm_gen()
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').write(_quick_unlock_password_excluded)
encrypt(path.expanduser('~/.config/sshyp/excluded'), _shm_folder, _shm_entry, gpg, _gpg_id)
print(f"\nyour quick-unlock passphrase: {_quick_unlock_password}")
def whitelist_verify(_port, _username_ssh, _ip, _client_device_id):
# checks the user's whitelist status and fetches the full gpg key password if possible
try:
run(f"gpg --pinentry-mode cancel -qd --output /dev/null {path.expanduser('~/.config/sshyp/lock.gpg')}",
shell=True, stderr=PIPE, check=True, close_fds=True)
return False
except CalledProcessError:
_i, _full_password = 0, ''
_server_whitelist = run('ssh -i ' + "'" + path.expanduser('~/.ssh/sshyp') + "' -p " + _port + " " +
_username_ssh + '@' + _ip + " 'ls ~/.config/sshyp/whitelist'",
shell=True, stdout=PIPE, text=True)
for _device_id in _server_whitelist.stdout.rstrip().split('\n'):
if _device_id == _client_device_id:
_quick_unlock_password = input('\nquick-unlock passphrase: ')
_quick_unlock_password_excluded = \
run('ssh -i ' + "'" + path.expanduser('~/.ssh/sshyp') + "' -p " + _port + " " + _username_ssh + '@'
+ _ip + f" 'gpg --pinentry-mode loopback --passphrase '{_quick_unlock_password}' -qd"
f" ~/.config/sshyp/excluded.gpg'", shell=True, stdout=PIPE, text=True).stdout.rstrip()
while _i < len(_quick_unlock_password_excluded):
try:
_full_password += _quick_unlock_password_excluded[_i]
except IndexError:
pass
try:
_full_password += _quick_unlock_password[_i]
except IndexError:
pass
_i += 1
break
return _full_password
def whitelist_list(): # shows the quick-unlock whitelist status of device ids
_whitelisted_ids = listdir(path.expanduser('~/.config/sshyp/whitelist'))
_device_ids = listdir(path.expanduser('~/.config/sshyp/devices'))
print('\n\u001b[1mquick-unlock whitelisted device ids:\u001b[0m')
for _id in _whitelisted_ids:
print(_id)
print('\n\u001b[1mother registered device ids:\u001b[0m')
for _id in _device_ids:
if _id not in _whitelisted_ids:
print(_id)
print()
def whitelist_manage(): # adds or removes quick-unlock whitelisted device ids
if len(argument_list) == 3:
whitelist_list()
_device_id = input('device id: ')
else:
_argument_split = argument.split(' ')
del _argument_split[:2]
_device_id = ' '.join(_argument_split)
if argument_list[2] == 'add':
if _device_id in listdir(path.expanduser('~/.config/sshyp/devices')):
open(path.expanduser(f"~/.config/sshyp/whitelist/{_device_id}"), 'w').write('')
whitelist_list()
else:
print(f"\n\u001b[38;5;9merror: device id ({_device_id}) is not registered\u001b[0m\n")
s_exit(2)
elif Path(path.expanduser(f"~/.config/sshyp/whitelist/{_device_id}")).is_file():
remove(path.expanduser(f"~/.config/sshyp/whitelist/{_device_id}"))
whitelist_list()
def add_entry(): # adds a new entry
_shm_folder, _shm_entry = None, None # sets base-line values to avoid errors
if len(argument_list) < 4:
_entry_name = entry_name_fetch('name of new entry: ')
else:
_entry_name = entry_name_fetch(2)
if Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n")
s_exit(4)
if argument_list[2] == 'note' or argument_list[2] == '-n':
_shm_folder, _shm_entry = shm_gen()
system(f"{editor} '{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(optimized_edit(['', '', '', _notes], None, -1))
elif argument_list[2] == 'password' or argument_list[2] == '-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"{editor} '{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(optimized_edit([_password, _username, _url, _notes], None, -1))
print('\n\u001b[1mentry preview:\u001b[0m')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg, gpg_id)
def add_folder(): # creates a new folder
if len(argument_list) < 4:
_entry_name = entry_name_fetch('name of new folder: ')
else:
_entry_name = entry_name_fetch(2)
Path(directory + _entry_name).mkdir(0o700)
if ssh_error != 1:
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p "
f"'{directory_ssh}{_entry_name}'\"")
def rename(): # renames an entry or folder
if argument == 'edit rename' or argument == 'edit relocate' or argument == 'edit -r':
_entry_name = entry_name_fetch('entry/folder to rename/relocate: ')
else:
_entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file() and not Path(f"{directory}{_entry_name}").is_dir():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(3)
_new_name = entry_name_fetch('new name: ')
if Path(f"{directory}{_new_name}.gpg").is_file() or Path(f"{directory}{_new_name}").is_dir():
print(f"\n\u001b[38;5;9merror: ({_new_name}) already exists\u001b[0m\n")
s_exit(4)
if _entry_name.endswith('/'):
move(f"{directory}{_entry_name}", f"{directory}{_new_name}")
if ssh_error != 1:
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p "
f"'{directory_ssh}{_new_name}'\"")
else:
move(f"{directory}{_entry_name}.gpg", f"{directory}{_new_name}.gpg")
if ssh_error != 1:
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /lib/sshyp; python -c "
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\", \"'\"remotely\"'\")'\"")
def edit(): # edits the contents of an entry
_shm_folder, _shm_entry, _detail, _edit_line = None, None, None, None # sets values to avoid PEP8 warnings
if len(argument_list) < 4:
_entry_name = entry_name_fetch('entry to edit: ')
else:
_entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(3)
_shm_folder, _shm_entry = shm_gen()
determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
if argument_list[2] == 'username' or argument_list[2] == '-u':
_detail, _edit_line = str(input('username: ')), 1
elif argument_list[2] == 'password' or argument_list[2] == '-p':
_detail, _edit_line = str(input('password: ')), 0
elif argument_list[2] == 'url' or argument_list[2] == '-l':
_detail, _edit_line = str(input('url: ')), 2
if argument_list[2] == 'note' or argument_list[2] == '-n':
_edit_line = 2
_new_lines = optimized_edit(edit_note(_shm_folder, _shm_entry,
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()), None, -1)
else:
_new_lines = optimized_edit(open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines(), _detail, _edit_line)
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_new_lines)
remove(f"{directory}{_entry_name}.gpg")
print('\n\u001b[1mentry preview:\u001b[0m')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg, gpg_id)
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' or argument == 'gen':
_entry_name = entry_name_fetch('name of entry: ')
elif argument_list[2] == 'update' or argument_list[2] == '-u':
_entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(3)
else:
_entry_name = entry_name_fetch(1)
if len(argument_list) == 2 or (not argument_list[2] == 'update' and not argument_list[2] == '-u'):
if Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n")
s_exit(4)
_username = str(input('username: '))
_password = pass_gen()
_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"{editor} '{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(optimized_edit([_password, _username, _url, _notes], None, -1))
else:
_shm_folder, _shm_entry = shm_gen()
determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
_new_lines = optimized_edit(open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines(), pass_gen(), 0)
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_new_lines)
remove(f"{directory}{_entry_name}.gpg")
print('\n\u001b[1mentry preview:\u001b[0m')
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
encrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg, gpg_id)
def copy_data(): # copies a specified field of an entry to the clipboard
if len(argument_list) < 4:
_entry_name = entry_name_fetch('entry to copy: ')
else:
_entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(3)
_shm_folder, _shm_entry = shm_gen()
determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
_copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
if uname()[0] == 'Haiku': # Haiku clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u':
system('clipboard -c ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('clipboard -c ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('clipboard -c ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('clipboard -c ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen('sleep 30; clipboard -r', shell=True, close_fds=True)
elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u':
system('termux-clipboard-set ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('termux-clipboard-set ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('termux-clipboard-set ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('termux-clipboard-set ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen("sleep 30; termux-clipboard-set ''", shell=True, close_fds=True)
elif environ.get('WAYLAND_DISPLAY') == 'wayland-0': # Wayland clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u':
system('wl-copy ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('wl-copy ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('wl-copy ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('wl-copy ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen('sleep 30; wl-copy -c', shell=True, close_fds=True)
else: # X11 clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u':
system('echo -n ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('echo -n ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('echo -n ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('echo -n ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
Popen("sleep 30; echo -n '' | xclip -sel c", shell=True, close_fds=True)
rmtree(f"{tmp_dir}{_shm_folder}")
def remove_data(): # deletes an entry from the server and flags it for local deletion on sync
if argument == 'shear' or argument == '-rm':
_entry_name = entry_name_fetch('entry/folder to shear: ')
else:
_entry_name = entry_name_fetch(1)
determine_decrypt(path.expanduser('~/.config/sshyp/lock.gpg'), 0, 0, gpg)
if ssh_error != 1:
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /lib/sshyp; python -c "
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\", \"'\"remotely\"'\")'\"")
else:
from sshypRemote import delete as offline_delete
offline_delete(_entry_name, '')
if __name__ == "__main__":
try:
silent_sync, ssh_error = 0, 0
# retrieve typed argument
argument_list = argv
argument = ' '.join(argument_list[1:])
if uname()[0] == 'Haiku': # set proper gpg command for OS
gpg = 'gpg --pinentry-mode loopback'
else:
gpg = 'gpg'
# import saved userdata
device_type = ''
if argument != 'tweak':
tmp_dir = path.expanduser('~/.config/sshyp/tmp/')
try:
sshyp_data = open(path.expanduser('~/.config/sshyp/sshyp-data')).readlines()
device_type = sshyp_data[0].rstrip()
if device_type == 'client':
directory = path.expanduser('~/.local/share/sshyp/')
gpg_id = sshyp_data[1].rstrip()
editor = sshyp_data[2].rstrip()
quick_unlock_enabled = sshyp_data[3].rstrip()
if Path(path.expanduser('~/.config/sshyp/sshyp.sshync')).is_file():
ssh_info = sshync.get_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'))
username_ssh = ssh_info[0].rstrip()
ip = ssh_info[1].rstrip()
port = ssh_info[2].rstrip()
directory_ssh = str(ssh_info[4].rstrip())
client_device_id = listdir(path.expanduser('~/.config/sshyp/devices'))[0].rstrip()
ssh_error = int(open(path.expanduser('~/.config/sshyp/ssh-error')).read().rstrip())
if ssh_error != 0:
ssh_error = copy_id_check(port, username_ssh, ip, client_device_id)
else:
ssh_error = 1
elif len(argument_list) <= 1 or (argument_list[1] != "help" and argument_list[1] != "--help" and
argument_list[1] != "-h" and argument_list[1] != "license" and
argument_list[1] != "version" and argument_list[1] != "-v" and
argument_list[1] != "whitelist"):
print(f"\n\u001b[38;5;9merror: invalid server argument - run 'sshyp help' to "
f"list usable commands\u001b[0m\n")
s_exit(1)
except (FileNotFoundError, IndexError):
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print("not all necessary configuration files are present - please run 'sshyp tweak'")
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
s_exit(2)
else:
tweak()
s_exit(0)
# run function based on arguments
if argument.startswith('/'):
read_shortcut()
elif argument == '':
no_arg()
elif argument == 'help' or argument == '--help' or argument == '-h' or argument == 'license' or argument \
== 'version' or argument == '-v':
print_info()
elif argument_list[1] == 'whitelist':
if device_type == 'server':
if len(argument_list) == 2:
print_info()
elif argument_list[2] == 'list' or argument_list[2] == '-l':
whitelist_list()
elif argument_list[2] == 'add' or argument_list[2] == 'delete' or argument_list[2] == 'del':
whitelist_manage()
elif argument_list[2] == 'setup':
whitelist_setup()
else:
print_info()
else:
print_info()
elif argument_list[1] == 'add':
if len(argument_list) == 2:
print_info()
elif argument_list[2] == 'note' or argument_list[2] == '-n' or argument_list[2] == 'password' or \
argument_list[2] == '-p':
add_entry()
elif argument_list[2] == 'folder' or argument_list[2] == '-f':
add_folder()
else:
print_info()
elif argument_list[1] == 'edit':
if len(argument_list) == 2:
print_info()
elif argument_list[2] == 'rename' or argument_list[2] == 'relocate' or argument_list[2] == '-r':
silent_sync = 1
rename()
elif argument_list[2] == 'username' or argument_list[2] == '-u' or argument_list[2] == 'password' or \
argument_list[2] == '-p' or argument_list[2] == 'url' or argument_list[2] == '-l' or \
argument_list[2] == 'note' or argument_list[2] == '-n':
edit()
else:
print_info()
elif argument_list[1] == 'gen':
gen()
elif argument_list[1] == 'copy':
if len(argument_list) == 2:
print_info()
elif argument_list[2] == 'username' or argument_list[2] == '-u' or argument_list[2] == 'password' or \
argument_list[2] == '-p' or argument_list[2] == 'url' or argument_list[2] == '-l' or \
argument_list[2] == 'note' or argument_list[2] == '-n':
try:
copy_data()
except IndexError:
print(f"\n\u001b[38;5;9merror: field does not exist in entry\u001b[0m\n")
s_exit(3)
else:
print_info()
elif argument_list[1] == 'shear' or argument_list[1] == '-rm':
remove_data()
elif argument_list[1] != 'sync' and argument_list[1] != '-s':
print(f"\n\u001b[38;5;9merror: invalid argument - run 'sshyp help' to list usable commands\u001b[0m\n")
s_exit(1)
# sync if any changes were made
if len(argument_list) > 1 and ssh_error == 0 \
and ((argument_list[1] == 'sync' or argument_list[1] == '-s' or argument_list[1] == 'gen' or
argument_list[1] == 'shear' or argument_list[1] == '-rm') or
((argument_list[1] == 'add' or argument_list[1] == 'edit') and len(argument_list) > 2)):
sync()
except KeyboardInterrupt:
print('\n')
+12 -15
View File
@@ -1,4 +1,4 @@
#!/bin/python3
#!/usr/bin/env python3
# external modules
@@ -9,22 +9,19 @@ 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('Folder does not exist remotely.')
else:
try:
remove(f"{expanduser('~/.password-pasture/')}{_file_path}.gpg")
except FileNotFoundError:
print('File does not exist remotely.')
def delete(_file_path, _target_database): # deletes an entry or folder, should be run remotely via ssh
try:
if _file_path.endswith('/'):
rmtree(f"{expanduser('~/.local/share/sshyp/')}{_file_path}")
else:
remove(f"{expanduser('~/.local/share/sshyp/')}{_file_path}.gpg")
except FileNotFoundError:
print(f"location does not exist {_target_database}")
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):
def deletion_check(_client_device_name): # creates a list of entries and folders to be deleted from a local machine
open(expanduser('~/.config/sshyp/deletion_database'), 'w').write('')
for _file in listdir(expanduser('~/.config/sshyp/deleted')):
_file_path = _file.replace('@', '/').split('^&*')[0]
@@ -37,9 +34,9 @@ def deletion_check(_client_device_name):
open(expanduser('~/.config/sshyp/deletion_database'), 'a').write(_file_path + '\n')
def folder_check():
def folder_check(): # creates a list of folders to be compared with those of a local machine
open(expanduser('~/.config/sshyp/folder_database'), 'w').write('')
for _root, _directories, _files in walk(expanduser('~/.password-pasture')):
for _root, _directories, _files in walk(expanduser('~/.local/share/sshyp')):
for _dir in _directories:
open(expanduser('~/.config/sshyp/folder_database'), 'a')\
.write(f"{_root.replace(expanduser('~'), '')}/{_dir}\n")
+241 -119
View File
@@ -1,40 +1,80 @@
#!/bin/bash
#!/usr/bin/env bash
# This script packages sshyp (from source) for various UNIX 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.
echo -e '\nOptions (please enter the number only):'
echo -e '\nDistribution Packages:\n\n1. Haiku\n2. Debian\n3. Termux\n4. Generic (used for PKGBUILD/APKBUILD)'
echo -e '\nBuild Scripts:\n\n5. Alpine Linux (APKBUILD)\n6. Arch Linux (PKGBUILD, also builds local generic package)'
echo -e '\nOther:\n\n7. All (generates all distribution packages (excluding Haiku, as this must be done on Haiku) 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" == "5" ] || [ "$distro" == "6" ] || [ "$distro" == "7" ]; 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
version=$(sed -n '1{p;q}' share/doc/sshyp/changelog | cut -c8-)
if [ -z "$2" ]; then
revision=1
else
revision="$2"
fi
mkdir -p packages
_create_generic() {
echo -e '\npackaging as generic...\n'
mkdir -p output/generictemp/usr/{bin,lib/sshyp,share/{man/man1,bash-completion/completions}}
cp -r lib/. output/generictemp/usr/lib/sshyp/
ln -s /usr/lib/sshyp/sshyp.py output/generictemp/usr/bin/sshyp
cp -r share output/generictemp/usr/
cp extra/sshyp-completion.bash output/generictemp/usr/share/bash-completion/completions/sshyp
cp extra/manpage output/generictemp/usr/share/man/man1/sshyp.1
gzip output/generictemp/usr/share/man/man1/sshyp.1
tar -C output/generictemp -cvJf output/sshyp-"$version".tar.xz usr/
rm -rf output/generictemp
sha512="$(sha512sum output/sshyp-"$version".tar.xz | awk '{print $1;}')"
echo -e "\nsha512 sum:\n$sha512"
echo -e "\ngeneric packaging complete\n"
} &&
if [ "$distro" == "1" ]; then
echo -e '\nPackaging for Haiku...\n'
mkdir -p packages/haikutemp/documentation/man/man1
mkdir -p packages/haikutemp/documentation/packages/sshyp
_create_pkgbuild() {
source='https://github.com/rwinkhart/sshyp/releases/download/v$pkgver/sshyp-$pkgver.tar.xz'
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=('GPL-3.0-only')
depends=(python gnupg openssh xclip wl-clipboard)
optdepends=('bash-completion: bash completion support')
source=(\""$source"\")
sha512sums=('"$sha512"')
package() {
tar xf sshyp-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\""
}
" > output/PKGBUILD
echo -e "\nPKGBUILD generated\n"
} &&
_create_apkbuild() {
echo -e '\ngenerating APKBUILD...'
echo "# Maintainer: Randall Winkhart <idgr@tutanota.com>
pkgname=sshyp
pkgver="$version"
pkgrel="$((revision-1))"
pkgdesc='A light-weight, self-hosted, synchronized password manager'
options=!check
url='https://github.com/rwinkhart/sshyp'
arch='noarch'
license='GPL-3.0-only'
depends='python3 gnupg openssh xclip wl-clipboard'
source=\""$source"\"
package() {
mkdir -p "\"\$pkgdir\""
cp -r "\"\$srcdir/usr/"\" "\"\$pkgdir\""
}
sha512sums=\"
"$sha512' 'sshyp-\"\$pkgver\".tar.xz"
\"
" > output/APKBUILD
echo -e "\nAPKBUILD generated\n"
} &&
_create_hpkg() {
echo -e '\npackaging for Haiku...\n'
mkdir -p output/haikutemp/{bin,lib/sshyp,documentation/{packages/sshyp,man/man1},data/bash-completion/completions}
echo "name sshyp
version "$version"-"$revision"
architecture any
@@ -55,115 +95,197 @@ provides {
requires {
gnupg
openssh
python3
nano
python310
}
urls {
\"https://github.com/rwinkhart/sshyp\"
}
" > packages/haikutemp/.PackageInfo
cp -r bin packages/haikutemp/
cp -r share/doc/sshyp/ packages/haikutemp/documentation/packages/
cp -r share/licenses/sshyp/ packages/haikutemp/documentation/packages/
cp extra/manpage packages/haikutemp/documentation/man/man1/sshyp.1
gzip packages/haikutemp/documentation/man/man1/sshyp.1
cd packages/haikutemp
" > output/haikutemp/.PackageInfo
cp -r lib/. output/haikutemp/lib/sshyp/
sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshync.py
sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshyp.py
sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshypRemote.py
ln -s /system/lib/sshyp/sshyp.py output/haikutemp/bin/sshyp
cp -r share/doc/sshyp/. output/haikutemp/documentation/packages/sshyp/
cp -r share/licenses/sshyp/. output/haikutemp/documentation/packages/sshyp/
cp extra/sshyp-completion.bash output/haikutemp/data/bash-completion/completions/sshyp
cp extra/manpage output/haikutemp/documentation/man/man1/sshyp.1
gzip output/haikutemp/documentation/man/man1/sshyp.1
cd output/haikutemp
package create -b sshyp-"$version"-"$revision"_all.hpkg
package add sshyp-"$version"-"$revision"_all.hpkg bin documentation
package add sshyp-"$version"-"$revision"_all.hpkg bin lib documentation data
cd ../..
mv packages/haikutemp/sshyp-"$version"-"$revision"_all.hpkg packages/
rm -rf packages/haikutemp
echo -e "\nHaiku packaging complete.\n"
fi
mv output/haikutemp/sshyp-"$version"-"$revision"_all.hpkg output/
rm -rf output/haikutemp
echo -e "\nHaiku packaging complete\n"
} &&
if [ "$distro" == "2" ] || [ "$distro" == "7" ]; 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
_create_deb() {
echo -e '\npackaging for Debian/Ubuntu...\n'
mkdir -p output/debiantemp/sshyp_"$version"-"$revision"_all/{DEBIAN,usr/{lib/sshyp,bin,share/{bash-completion/completions,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
Depends: python3, gnupg, openssh-client, xclip, wl-clipboard
Suggests: bash-completion
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
Installed-Size: 14584
" > output/debiantemp/sshyp_"$version"-"$revision"_all/DEBIAN/control
cp -r lib/. output/debiantemp/sshyp_"$version"-"$revision"_all/usr/lib/sshyp/
ln -s /usr/lib/sshyp/sshyp.py output/debiantemp/sshyp_"$version"-"$revision"_all/usr/bin/sshyp
cp -r share output/debiantemp/sshyp_"$version"-"$revision"_all/usr/
cp extra/sshyp-completion.bash output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/bash-completion/completions/sshyp
cp extra/manpage output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
gzip output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
dpkg-deb --build --root-owner-group output/debiantemp/sshyp_"$version"-"$revision"_all/
mv output/debiantemp/sshyp_"$version"-"$revision"_all.deb output/
rm -rf output/debiantemp
echo -e "\nDebian/Ubuntu packaging complete\n"
} &&
if [ "$distro" == "3" ] || [ "$distro" == "7" ]; 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
_create_termux() {
echo -e '\npackaging for Termux...\n'
mkdir -p output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/{DEBIAN,data/data/com.termux/files/usr/{lib/sshyp,bin,share/{bash-completion/completions,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
Depends: python, gnupg, openssh, termux-api, termux-am
Suggests: bash-completion
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
Installed-Size: 14584
" > output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/DEBIAN/control
cp -r lib/. output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/
ln -s /data/data/com.termux/files/usr/lib/sshyp/sshyp.py output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/bin/sshyp
cp -r share output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/
cp extra/sshyp-completion.bash output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/bash-completion/completions/sshyp
cp extra/manpage output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1
gzip output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1
dpkg-deb --build --root-owner-group output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/
mv output/termuxtemp/sshyp_"$version"-"$revision"_all_termux.deb output/
rm -rf output/termuxtemp
echo -e "\nTermux packaging complete\n"
} &&
if [ "$distro" == "4" ] || [ "$distro" == "6" ] || [ "$distro" == "7" ]; 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
_create_rpm() {
echo -e '\npackaging for Fedora...\n'
rm -rf ~/rpmbuild
rpmdev-setuptree
cp output/sshyp-"$version".tar.xz ~/rpmbuild/SOURCES
echo "Name: sshyp
Version: "$version"
Release: "$revision"
Summary: A light-weight, self-hosted, synchronized password manager
BuildArch: noarch
License: GPL-3.0-only
URL: https://github.com/rwinkhart/sshyp
Source0: sshyp-"$version".tar.xz
Requires: python gnupg openssh-clients wl-clipboard
Recommends: bash-completion
%description
sshyp is a password-store compatible CLI password manager available for UNIX(-like) systems - its primary goal is to make syncing passwords and notes across devices as easy as possible via CLI.
%install
tar xf %{_sourcedir}/sshyp-"$version".tar.xz -C %{_sourcedir}
cp -r %{_sourcedir}/usr %{buildroot}
%files
/usr/bin/sshyp
/usr/lib/sshyp/sshyp.py
/usr/lib/sshyp/sshync.py
/usr/lib/sshyp/sshypRemote.py
/usr/share/bash-completion/completions/sshyp
%license /usr/share/licenses/sshyp/license
%changelog /usr/share/doc/sshyp/changelog
%doc /usr/share/man/man1/sshyp.1.gz
" > ~/rpmbuild/SPECS/sshyp.spec
rpmbuild -bb ~/rpmbuild/SPECS/sshyp.spec
mv ~/rpmbuild/RPMS/noarch/* output/
rm -rf ~/rpmbuild
echo -e "\nFedora packaging complete\n"
} &&
if [ "$distro" == "6" ] || [ "$distro" == "7" ]; then
echo -e '\nGenerating PKGBUILD...'
echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com>
_create_freebsd_pkg() {
echo -e '\npackaging for FreeBSD...'
mkdir -p output/freebsdtemp/usr/{lib/sshyp,bin,share/{bash-completion/completions,man/man1}}
echo "name: sshyp
version: \""$version"\"
abi = \"FreeBSD:13:*\";
arch = \"freebsd:13:*\";
origin: security/sshyp
comment: \"a password manager\"
desc: \"a light-weight, self-hosted, synchronized password manager\"
maintainer: <idgr at tutanota dot com>
www: https://github.com/rwinkhart/sshyp
prefix: /
\"deps\" : {
\"python\" : {
\"origin\" : \"lang/python\"
},
\"gnupg\" : {
\"origin\" : \"security/gnupg\"
},
\"xclip\" : {
\"origin\" : \"x11/xclip\"
},
\"wl-clipboard\" : {
\"origin\" : \"x11/wl-clipboard\"
},
},
" > output/freebsdtemp/+MANIFEST
echo "/usr/bin/sshyp
/usr/lib/sshyp/sshync.py
/usr/lib/sshyp/sshyp.py
/usr/lib/sshyp/sshypRemote.py
/usr/share/bash-completion/completions/sshyp
/usr/share/doc/sshyp/changelog
/usr/share/licenses/sshyp/license
/usr/share/man/man1/sshyp.1.gz
" > output/freebsdtemp/plist
cp -r lib/. output/freebsdtemp/usr/lib/sshyp/
ln -s /usr/lib/sshyp/sshyp.py output/freebsdtemp/usr/bin/sshyp
cp -r share output/freebsdtemp/usr/
cp extra/sshyp-completion.bash output/freebsdtemp/usr/share/bash-completion/completions/sshyp
cp extra/manpage output/freebsdtemp/usr/share/man/man1/sshyp.1
gzip output/freebsdtemp/usr/share/man/man1/sshyp.1
pkg create -m output/freebsdtemp/ -r output/freebsdtemp/ -p output/freebsdtemp/plist -o output/
rm -rf output/freebsdtemp
echo -e "\nFreeBSD packaging complete\n"
} &&
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'
if [ "$1" == "generic" ]; then # build scripts
_create_generic
elif [ "$1" == "pkgbuild" ]; then
_create_generic
_create_pkgbuild
elif [ "$1" == "apkbuild" ]; then
_create_generic
_create_apkbuild
elif [ "$1" == "haiku" ]; then # distribution packages
_create_hpkg
elif [ "$1" == "debian" ]; then
_create_deb
elif [ "$1" == "termux" ]; then
_create_termux
elif [ "$1" == "fedora" ]; then
_create_generic
_create_rpm
elif [ "$1" == "freebsd" ]; then
_create_freebsd_pkg
elif [ "$1" == "buildable-arch" ]; then
_create_generic
_create_pkgbuild
_create_apkbuild
if [[ $(pacman -Q dpkg) == "dpkg"* ]]; then
_create_deb
_create_termux
fi
if [[ "$(pacman -Q freebsd-pkg)" == "freebsd-pkg"* ]]; then
_create_freebsd_pkg
fi
else
echo -e '\nusage: package.sh [target] <revision>\n\ntargets:\n mainline: pkgbuild apkbuild haiku fedora debian\n experimental: freebsd termux\n other: buildable-arch\n'
fi
+46 -31
View File
@@ -1,42 +1,57 @@
sshyp v1.0.0
sshyp v1.2.0
The Polished Trotters Update
the brisk bahh update
This release brings 'sshyp' in line with the original goals of the project.
As such, it is being crowned "v1.0.0", and is considered a stable base for future expansions.
this release focuses on speeding up the sshyp user experience by adding
new features that reduce wasted time
Features:
compatibility-breaking changes:
- sshyp has been modified to run on Haiku, an open-source re-implementation of BeOS
- the entry format has been changed to support entries created in pass/password-store
^ this change requires existing entry libraries to be converted - see the sshyp v1.0.0 release page on GitHub for a conversion script
- majorly overhauled visual experience for sshyp
^ this includes a new entry list, a new entry readout, coloured output, and more!
- entries can now optionally be passed as arguments, directly
^ as opposed to the user being prompted for an entry name after running a command
- new configuration options (quick-unlock, offline mode) have been added and
the configuration files have been reorganized
^ simply running "sshyp tweak" and following the setup wizard will correct any compatibility
issues
- for quick-unlock security, device names have been replaced with more secure device ids
^ older device names are still compatible, but for security reasons it is recommended
to delete any pre-existing device names from the server and allow "sshyp tweak" to re-register
your devices
Changes:
user-facing features:
- corrected outdated liscensing and copyright information
- 'if __name__=="__main__":' convention is now used
- help screens have been overhauled
- improved password generator to guarantee more secure results
- fixed errors when trying to sync with a multi-word entry on the server
- sshync now uses 'scp' (via the sftp protocal), rather than 'sftp'
- rename function now properly allows for renaming folders
- renaming an entry/folder will now properly delete the old entry/folder from the server
- entry previews at the time of entry creation/editing no longer require entering the gpg password more times than necessary
- the clipboard now automatically clears after 30 seconds
- sshyp server no longer needs to create copies of its libraries in ~/
- ...and lots of minor (under the hood) changes!
- quick-unlock mode has been added
^ this allows you to use a shortened version of your password by verifying that your device
is whitelisted on your sshyp server - it's both faster and more secure than standard unlock,
but it requires an active connection to your sshyp server to authenticate (otherwise it will
fall back to standard unlock)
- full support for offline usage
^ though sshyp could be used without a server before, it now can be configured to not attempt
to find one ever - this saves time and hides sync failure error messages
- bash completions have been added
^ if you have bash-completion installed, you can now use the tab key in bash to auto-complete
sshyp arguments and entry names (client only, not added for server-specific arguments)
^ if you do not have bash-completion installed, you can source
/usr/share/bash-completion/completions/sshyp (Linux/BSD) or
/boot/system/data/bash-completion/completions/sshyp (Haiku) in your ~/.bashrc to
use this feature
fixes/optimizations:
- fixed entries with multi-word titles failing to decrypt
- password generation is now much faster and more resource efficient
- there is no longer a length limit on generated passwords
- improved visual consistency of help menus
- rarely used modules are now imported only when needed
- sshyp now uses one fewer configuration file
other notable changes:
- sshyp is now specifically licensed under the GPL-3.0-only (keyword: only)
- sshyp now has some possible arguments and its own help menu when running in server mode
- temporary files in /dev/shm are now generated with more complex names
- sshyp now installs in /usr/lib/sshyp (Linux/BSD) or /system/lib/sshyp (Haiku) instead of
/usr/bin or /bin (it is still symlinked to the old directories)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
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
Executable → Regular
+3 -4
View File
@@ -2,9 +2,8 @@
Copyright (C) 2022 Randall Winkhart idgr@tutanota.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
it under the terms of version 3 (only) of the GNU General Public License
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -12,4 +11,4 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
along with this program. If not, see <http://www.gnu.org/licenses/>.