Compare commits

...
97 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
11 changed files with 869 additions and 435 deletions
Executable → Regular
View File
Executable → Regular
+12 -11
View File
@@ -2,6 +2,8 @@
[![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) [![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)
pronounced as: 'sheep', 'shēp'
sshyp is a very simple self-hosted, synchronized password manager for UNIX(-like) systems (currently Haiku/FreeBSD/Linux). 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 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.
@@ -24,15 +26,11 @@ What sshyp can do:
- securely manage a collection of encrypted passwords and notes via CLI - securely manage a collection of encrypted passwords and notes via CLI
- generate new, secure passwords to the user's choice in length and complexity - 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) - 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 with entries created by pass/password-store!
- everything above on Haiku, FreeBSD, Linux, and Termux (an Android terminal emulator)! - everything above on Haiku, FreeBSD, Linux, and Termux (an Android terminal emulator)!
What sshyp will likely do:
- (planned v1.2.0) everything it already does, but also in a GUI for Linux/Haiku
What sshyp definitely won't do: What sshyp definitely won't do:
- Non-UNIX(-like) 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)
@@ -40,12 +38,14 @@ What sshyp definitely won't do:
# Installation # Installation
Please see the [installation guide](https://github.com/rwinkhart/sshyp/wiki/Installation) in the sshyp wiki for directions specific to your distribution/OS. Please see the [installation guide](https://github.com/rwinkhart/sshyp/wiki/Installation) in the sshyp wiki for directions specific to your distribution/OS.
Pre-built packages exist for Haiku, FreeBSD, Arch Linux, Debian/Ubuntu Linux, Fedora Linux, and Termux. These can be downloaded from the releases page. 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.
Requests for additional distribution/OS support can be filed as issues. Requests for additional distribution/OS support can be filed as issues.
Extensions are available in the [sshyp-labs](https://github.com/rwinkhart/sshyp-labs) repository. Extensions are available in the [sshyp-labs](https://github.com/rwinkhart/sshyp-labs) repository.
Bash completions can be enabled by installing your distribution's "bash-completion" package and restarting your terminal.
# Building # Building
Since sshyp is written entirely in Python, it doesn't need to be compiled. It does, however, need to be packaged for installation. Since sshyp is written entirely in Python, it doesn't need to be compiled. It does, however, need to be packaged for installation.
@@ -54,7 +54,7 @@ A packaging script is included in the root directory of the repo in order to pac
``` ```
git clone https://github.com/rwinkhart/sshyp.git git clone https://github.com/rwinkhart/sshyp.git
cd sshyp cd sshyp
./package.sh ./package.sh [target] <revision>
``` ```
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. 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.
@@ -63,7 +63,7 @@ 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. 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, FreeBSD, Arch Linux (PKGBUILD), Debian/Ubuntu Linux, Fedora Linux, Termux, and generic. Currently, the script can create packages for Haiku, FreeBSD, Alpine Linux (APKBUILD), Arch Linux (PKGBUILD), Debian/Ubuntu Linux, Fedora Linux, Termux, and generic.
# Usage # Usage
Upon initial installation (on both the server and client devices), be sure to run: Upon initial installation (on both the server and client devices), be sure to run:
@@ -91,8 +91,9 @@ man sshyp
# Roadmap # Roadmap
Short-term Goals: Short-term Goals:
- create minimal GUI app (Linux x86_64, Linux aarch64) - create minimal GUI app (Linux x86_64, Linux aarch64) - being done as an [extension](https://github.com/rwinkhart/sshyp-labs)
- various optimizations/bug fixes - significant optimizations
- vaious bug fixes
Long-term Goals: Long-term Goals:
Executable → Regular
+76
View File
@@ -1,3 +1,79 @@
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 sshyp v1.1.1
the sheecrets update - patch one the sheecrets update - patch one
Executable → Regular
+61 -20
View File
@@ -1,11 +1,13 @@
.TH sshyp 1 "21 July 2022" "v1.1.1" "sshyp man page" .TH sshyp 1 "06 November 2022" "v1.2.0" "sshyp man page"
.SH NAME .SH NAME
sshyp \- A very simple self-hosted, synchronized password manager for UNIX(-like) 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 .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 .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. 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): Setting up sshyp for the first time or altering its configuration (also recommended after major updates):
sshyp tweak sshyp tweak
@@ -32,10 +34,19 @@ Manually syncing entries with the server:
Removing an existing folder saved as ~/.local/share/sshyp/social: Removing an existing folder saved as ~/.local/share/sshyp/social:
sshyp shear social/ sshyp shear social/
.SH EXAMPLES (SERVER)
Setting up the quick-unlock whitelist:
sshyp whitelist setup
.SH OPTIONS Checking the quick-unlock whitelist status of all registered client devices:
USAGE: sshyp [OPTION [FLAG] [<entry name>]] | [/<entry name>] 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 help/--help/-h bring up the help menu
version/-v display sshyp version info version/-v display sshyp version info
tweak configure sshyp tweak configure sshyp
@@ -45,24 +56,38 @@ USAGE: sshyp [OPTION [FLAG] [<entry name>]] | [/<entry name>]
copy copy details of an entry to your clipboard copy copy details of an entry to your clipboard
shear/-rm delete an existing entry shear/-rm delete an existing entry
sync/-s manually sync the entry directory via sshync sync/-s manually sync the entry directory via sshync
.SH FLAGS .SH FLAGS (CLIENT)
add: add:
password/-p add a password entry password/-p add a password entry
note/-n add a note entry note/-n add a note entry
folder/-f add a new folder for entries folder/-f add a new folder for entries
edit: edit:
rename/relocate/-r rename or relocate an entry rename/relocate/-r rename or relocate an entry
username/-u change the username of an entry username/-u change the username of an entry
password/-p change the password of an entry password/-p change the password of an entry
note/-n change the note attached to an entry note/-n change the note attached to an entry
url/-l change the url attached to an entry url/-l change the url attached to an entry
copy: copy:
username/-u copy the username 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 password/-p copy the password of an entry to your clipboard
url/-l copy the URL 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 note/-n copy the note of an entry to your clipboard
gen: 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 .SH LIMITATIONS
The following characters/character sequences are not supported in entry/folder titles: The following characters/character sequences are not supported in entry/folder titles:
@@ -73,10 +98,11 @@ 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. The sshyp package includes modes for operating on both client and server devices, so only one package is necessary.
Server setup: 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) Allow remote access to the SSH server w/public key authentication (disabling password-only authentication recommended)
Install sshyp Install sshyp
Run "sshyp tweak" and set the device type as server Run "sshyp tweak" and set the device type as server
Optionally, run "sshyp whitelist setup" and configure quick-unlock
Done! Done!
Client setup: Client setup:
@@ -84,8 +110,23 @@ Client setup:
Run "sshyp tweak" and follow the prompts Run "sshyp tweak" and follow the prompts
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.) 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" 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! 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. 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 .SH AUTHOR
Randall Winkhart (https://github.com/rwinkhart) 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
+13 -13
View File
@@ -1,16 +1,16 @@
#!/bin/python3 #!/usr/bin/env python3
# external modules # external modules
from os import path, system, walk from os import path, system, walk
from os.path import expanduser, getmtime, join from os.path import expanduser, getmtime, join
from pathlib import Path
from sys import exit as s_exit from sys import exit as s_exit
# utility functions # utility functions
def get_titles_mods(_directory, _destination, _user_data): # fetches and returns lists of titles and their mod times 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 = [], [] _title_list, _mod_list = [], []
Path(path.expanduser('~/.config/sshync')).mkdir(0o700, parents=True, exist_ok=True) # create config directory Path(path.expanduser('~/.config/sshync')).mkdir(0o700, parents=True, exist_ok=True) # create config directory
# local fetching # local fetching
@@ -27,8 +27,9 @@ def get_titles_mods(_directory, _destination, _user_data): # fetches and return
open(expanduser('~/.config/sshync/database'), 'a').write(str(_mod) + '\n') open(expanduser('~/.config/sshync/database'), 'a').write(str(_mod) + '\n')
# remote fetching # remote fetching
if _destination == 'r': 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" system(f"ssh -i '{_user_data[5]}' -p {_user_data[2]} {_user_data[0]}@{_user_data[1]} \"cd /lib/sshyp; python -c"
f"rt sshync; sshync.get_titles_mods(\"'\"{_user_data[4]}\"'\", \"'\"l\"'\", \"'\"{_user_data}\"'\")'\"") 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]}:" 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/')}'") f"'/home/{_user_data[0]}/.config/sshync/database' '{expanduser('~/.config/sshync/')}'")
_titles, _sep, _mods = '*&^'.join(open(expanduser('~/.config/sshync/database')).readlines()).replace('\n', '')\ _titles, _sep, _mods = '*&^'.join(open(expanduser('~/.config/sshync/database')).readlines()).replace('\n', '')\
@@ -54,8 +55,7 @@ def sort_titles_mods(_list_1, _list_2): # creates and returns two lists (of tit
def make_profile(_profile_dir, _local_dir, _remote_dir, _identity, _ip, _port, _user): # creates a sshync job profile def make_profile(_profile_dir, _local_dir, _remote_dir, _identity, _ip, _port, _user): # creates a sshync job profile
open(_profile_dir, 'w').write(_user + '\n' + _ip + '\n' + _port + '\n' + _local_dir + '\n' + _remote_dir + '\n' + open(_profile_dir, 'w').write(f"{_user}\n{_ip}\n{_port}\n{_local_dir}\n{_remote_dir}\n{_identity}\n")
_identity + '\n')
def get_profile(_profile_dir): # returns a list of data read from a sshync job profile def get_profile(_profile_dir): # returns a list of data read from a sshync job profile
@@ -64,14 +64,14 @@ def get_profile(_profile_dir): # returns a list of data read from a sshync job
except (FileNotFoundError, IndexError): except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;9merror: the profile does not exist or is corrupted.\u001b[0m\n') print('\n\u001b[38;5;9merror: the profile does not exist or is corrupted.\u001b[0m\n')
_profile_data = None _profile_data = None
s_exit(1) s_exit(3)
# extract data from profile # extract data from profile
_user = _profile_data[0].replace('\n', '') _user = _profile_data[0].rstrip()
_ip = _profile_data[1].replace('\n', '') _ip = _profile_data[1].rstrip()
_port = _profile_data[2].replace('\n', '') _port = _profile_data[2].rstrip()
_local_dir = _profile_data[3].replace('\n', '') _local_dir = _profile_data[3].rstrip()
_remote_dir = _profile_data[4].replace('\n', '') _remote_dir = _profile_data[4].rstrip()
_identity = _profile_data[5].replace('\n', '') _identity = _profile_data[5].rstrip()
return _user, _ip, _port, _local_dir, _remote_dir, _identity return _user, _ip, _port, _local_dir, _remote_dir, _identity
+414 -216
View File
@@ -1,4 +1,4 @@
#!/bin/python3 #!/usr/bin/env python3
# external modules # external modules
@@ -7,15 +7,14 @@ from pathlib import Path
from random import randint, SystemRandom from random import randint, SystemRandom
from shutil import get_terminal_size, move, rmtree from shutil import get_terminal_size, move, rmtree
import sshync import sshync
import string
from subprocess import CalledProcessError, Popen, PIPE, run from subprocess import CalledProcessError, Popen, PIPE, run
from sys import argv, exit as s_exit from sys import argv, exit as s_exit
from textwrap import fill
# BELOW - utility functions # BELOW - utility functions
def entry_list_gen(_directory=path.expanduser('~/.local/share/sshyp/')): # generates and prints full entry list 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') print('\n\u001b[38;5;0;48;5;15msshyp entries:\u001b[0m\n')
_entry_list, _color_alternator = [], 1 _entry_list, _color_alternator = [], 1
for _entry in sorted(listdir(_directory)): for _entry in sorted(listdir(_directory)):
@@ -99,43 +98,47 @@ def entry_name_fetch(_entry_name_location): # fetches and returns entry name fr
return _entry_name return _entry_name
def shm_gen(_tmp_dir=path.expanduser('~/.config/sshyp/tmp/')): # creates a temporary directory for entry editing def string_gen(_complexity, _length): # generates and returns a random string based on input
_shm_folder_gen = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) import string
for _ in range(randint(10, 30))) if _complexity == 's':
_shm_entry_gen = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) _character_pool = string.ascii_letters + string.digits
for _ in range(randint(10, 30))) elif _complexity == 'f':
Path(_tmp_dir + _shm_folder_gen).mkdir(0o700) _character_pool = string.digits + string.ascii_letters + string.punctuation.replace('/', '').replace('\\', '')\
return _shm_folder_gen, _shm_entry_gen .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(): # generates and returns a random password based on user-specified options def pass_gen(): # prompts the user for necessary information to generate a password and passes it to string_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(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
try: try:
_length = int(input('password length: ')) _length = int(input('password length: '))
except ValueError: except ValueError:
print(f"\n\u001b[38;5;9merror: a non-integer value was input for password length\u001b[0m\n") print(f"\n\u001b[38;5;9merror: a non-integer value was input for password length\u001b[0m\n")
_gen = pass_gen() _gen = pass_gen()
return _gen return _gen
if _length > 840:
_length = 840
print('\n\u001b[38;5;9mpassword length has been limited to the maximum of 840 characters\u001b[0m\n')
_complexity = str(input('password complexity - simple (for compatibility) or complex (for security)? (s/C) ')) _complexity = str(input('password complexity - simple (for compatibility) or complex (for security)? (s/C) '))
_gen = _pass_gen_function(_complexity, _length) if _complexity != 's' and _complexity != 'S':
_complexity = 'c'
_gen = string_gen(_complexity.lower(), _length)
return _gen 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/')): 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 # encrypts an entry and cleans up the temporary files
system(f"{_gpg_com} -qr {str(_gpg_id)} -e '{_tmp_dir}{_shm_folder}/{_shm_entry}'") system(f"{_gpg_com} -qr {str(_gpg_id)} -e '{_tmp_dir}{_shm_folder}/{_shm_entry}'")
@@ -143,17 +146,39 @@ def encrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, _gpg_id, _tmp_dir=pat
rmtree(f"{_tmp_dir}{_shm_folder}") rmtree(f"{_tmp_dir}{_shm_folder}")
def decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_command, _tmp_dir=path.expanduser('~/.config/sshyp/tmp/')): def decrypt(_entry_dir, _shm_folder, _shm_entry, _gpg_com, _quick_pass,
# decrypts an entry to a temporary directory _tmp_dir=path.expanduser('~/.config/sshyp/tmp/')): # decrypts an entry to a temporary directory
if _shm_folder == 0 and _shm_entry == 0: if not isinstance(_quick_pass, bool):
_command = f"{_gpg_command} -qd --output /dev/null {path.expanduser('~/.config/sshyp/lock.gpg')}" _unlock_method = f"gpg --pinentry-mode loopback --passphrase '{_quick_pass}' -qd --output "
else: else:
_command = f"{_gpg_command} -qd --output {_tmp_dir}{_shm_folder}/{_shm_entry} {_entry_dir}.gpg" _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: try:
run(_command, shell=True, stderr=PIPE, check=True, close_fds=True) run(_unlock_method + _output_target, shell=True, stderr=PIPE, check=True, close_fds=True)
except CalledProcessError: except CalledProcessError:
print(f"\n\u001b[38;5;9merror: could not decrypt - ensure the correct gpg key is present\u001b[0m\n") if not isinstance(_quick_pass, bool):
s_exit(1) 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 def optimized_edit(_lines, _edit_data, _edit_line): # ensures an edited entry is optimized for best compatibility
@@ -178,7 +203,7 @@ def optimized_edit(_lines, _edit_data, _edit_line): # ensures an edited entry i
def edit_note(_shm_folder, _shm_entry, _lines): # edits the note attached to an entry def edit_note(_shm_folder, _shm_entry, _lines): # edits the note attached to an entry
_reg_lines = _lines[0:3] _reg_lines = _lines[0:3]
open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'w').writelines(_lines[3:]) open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'w').writelines(_lines[3:])
system(f"{editor} {tmp_dir}{_shm_folder}/{_shm_entry}-n") system(f"{editor} '{tmp_dir}{_shm_folder}/{_shm_entry}-n'")
_new_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n").readlines() _new_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n").readlines()
while len(_reg_lines) < 3: while len(_reg_lines) < 3:
_reg_lines += ['\n'] _reg_lines += ['\n']
@@ -186,10 +211,10 @@ def edit_note(_shm_folder, _shm_entry, _lines): # edits the note attached to an
return _noted_lines return _noted_lines
def copy_name_check(_port, _username_ssh, _ip, _client_device_name): 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 # 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} " \ _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_name}'\"" f"\"touch '/home/{_username_ssh}/.config/sshyp/devices/{_client_device_id}'\""
try: try:
run(_command, shell=True, stderr=PIPE, check=True, close_fds=True) run(_command, shell=True, stderr=PIPE, check=True, close_fds=True)
except CalledProcessError: except CalledProcessError:
@@ -206,8 +231,8 @@ def copy_name_check(_port, _username_ssh, _ip, _client_device_name):
def tweak(): # runs configuration wizard def tweak(): # runs configuration wizard
_divider = f"\n{'=' * (get_terminal_size()[0] - int((.5 * get_terminal_size()[0])))}\n\n" _divider = f"\n{'=' * (get_terminal_size()[0] - int((.5 * get_terminal_size()[0])))}\n\n"
# storage/config directory creation
Path(path.expanduser('~/.local/share/sshyp')).mkdir(0o700, parents=True, exist_ok=True) # config directory creation
Path(path.expanduser('~/.config/sshyp/devices')).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 not Path(f"{path.expanduser('~/.config/sshyp/tmp')}").exists():
if uname()[0] == 'Haiku' or uname()[0] == 'FreeBSD': if uname()[0] == 'Haiku' or uname()[0] == 'FreeBSD':
@@ -216,25 +241,24 @@ def tweak(): # runs configuration wizard
system(f"ln -s '/data/data/com.termux/files/usr/tmp' {path.expanduser('~/.config/sshyp/tmp')}") system(f"ln -s '/data/data/com.termux/files/usr/tmp' {path.expanduser('~/.config/sshyp/tmp')}")
else: else:
system(f"ln -s /dev/shm {path.expanduser('~/.config/sshyp/tmp')}") system(f"ln -s /dev/shm {path.expanduser('~/.config/sshyp/tmp')}")
# device type configuration # device type configuration
_device_type = input('\nclient or server installation? (C/s) ') _device_type = input('\nclient or server installation? (C/s) ')
if _device_type.lower() == 's': if _device_type.lower() == 's':
open(path.expanduser('~/.config/sshyp/sshyp-device'), 'w').write(_device_type) _sshyp_data = ['server']
Path(path.expanduser('~/.config/sshyp/deleted')).mkdir(0o700, parents=True, exist_ok=True) Path(path.expanduser('~/.config/sshyp/deleted')).mkdir(0o700, exist_ok=True)
print(f"\n\u001b[4;1mmake sure the ssh service is running and properly configured\u001b[0m\n" Path(path.expanduser('~/.config/sshyp/whitelist')).mkdir(0o700, exist_ok=True)
f"{_divider}configuration complete\n") print(f"\n\u001b[4;1mmake sure the ssh service is running and properly configured\u001b[0m")
s_exit(0)
else: else:
# device type configuration _sshyp_data = ['client']
_device_type = 'c' # ensure device type flag is properly set Path(path.expanduser('~/.local/share/sshyp')).mkdir(0o700, parents=True, exist_ok=True)
open(path.expanduser('~/.config/sshyp/sshyp-device'), 'w').write(_device_type)
# gpg configuration # gpg configuration
_gpg_id = input(f"{_divider}sshyp requires the use of a unique gpg key - use an (e)xisting key or (g)enerate " _gpg_gen = input(f"{_divider}sshyp requires the use of a unique gpg key - use an (e)xisting key or (g)enerate a"
f"a new one? (E/g) ") f" new one? (E/g) ")
if _gpg_id.lower() != 'g': if _gpg_gen.lower() != 'g':
system(f"{gpg} -k") system(f"{gpg} -k")
_gpg_id = str(input('gpg key id: ')) _sshyp_data += [str(input('gpg key id: '))]
else: else:
print('\na unique gpg key is being generated for you...') print('\na unique gpg key is being generated for you...')
if not Path(path.expanduser('~/.config/sshyp/gpg-gen')).is_file(): if not Path(path.expanduser('~/.config/sshyp/gpg-gen')).is_file():
@@ -248,90 +272,133 @@ def tweak(): # runs configuration wizard
else: else:
run(f"{gpg} --batch --generate-key '{path.expanduser('~/.config/sshyp/gpg-gen')}'", shell=True) run(f"{gpg} --batch --generate-key '{path.expanduser('~/.config/sshyp/gpg-gen')}'", shell=True)
remove(path.expanduser('~/.config/sshyp/gpg-gen')) remove(path.expanduser('~/.config/sshyp/gpg-gen'))
_gpg_id = run(f"{gpg} -k", shell=True, stdout=PIPE, text=True).stdout.split('\n')[-4].strip() _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 # lock file generation
if Path(path.expanduser('~/.config/sshyp/lock.gpg')).is_file(): if Path(path.expanduser('~/.config/sshyp/lock.gpg')).is_file():
remove(path.expanduser('~/.config/sshyp/lock.gpg')) remove(path.expanduser('~/.config/sshyp/lock.gpg'))
open(path.expanduser('~/.config/sshyp/lock'), 'w') open(path.expanduser('~/.config/sshyp/lock'), 'w')
system(f"{gpg} -qr {str(_gpg_id)} -e {path.expanduser('~/.config/sshyp/lock')}") system(f"{gpg} -qr {str(_sshyp_data[1])} -e {path.expanduser('~/.config/sshyp/lock')}")
remove(path.expanduser('~/.config/sshyp/lock')) remove(path.expanduser('~/.config/sshyp/lock'))
# ssh key configuration # ssh key configuration
_offline_mode = False
_ssh_gen = (input(f"{_divider}make sure the ssh service on the remote server is running and properly " _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"configured\n\nsync support requires a unique ssh key - would you like to have this "
f"automatically generated? (Y/n) ")) f"automatically generated? (Y/n/o(ffline)) "))
if _ssh_gen.lower() != 'n': if _ssh_gen.lower() != 'n' and _ssh_gen.lower() != 'o' and _ssh_gen.lower() != 'offline':
if uname()[0] == 'Haiku': if uname()[0] == 'Haiku':
Path(f"{path.expanduser('~')}/.ssh").mkdir(0o700, exist_ok=True) Path(f"{path.expanduser('~')}/.ssh").mkdir(0o700, exist_ok=True)
system('ssh-keygen -t ed25519 -f ~/.ssh/sshyp') system('ssh-keygen -t ed25519 -f ~/.ssh/sshyp')
else: elif _ssh_gen.lower() == 'n':
print(f"\n\u001b[4;1mensure that the key file you are using is located at " print(f"\n\u001b[4;1mensure that the key file you are using is located at "
f"{path.expanduser('~/.ssh/sshyp')}\u001b[0m") 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')
# ssh ip+port configuration if not _offline_mode:
_ip_port = str(input(f"{_divider}example input: 10.10.10.10:9999\n\nip and ssh port of the remote server: ")) # ssh ip+port configuration
_ip, _sep, _port = _ip_port.partition(':') _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 # ssh user configuration
_username_ssh = str(input('\nusername of the remote server: ')) _username_ssh = str(input('\nusername of the remote server: '))
# sshyp-only data storage # sshync profile generation
open(path.expanduser('~/.config/sshyp/sshyp-data'), 'w')\ sshync.make_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'),
.write(_gpg_id + '\n' + input(f"{_divider}example input: vim\n\npreferred text editor: ")) path.expanduser('~/.local/share/sshyp/'), f"/home/{_username_ssh}/.local/share/sshyp/",
path.expanduser('~/.ssh/sshyp'), _ip, _port, _username_ssh)
# sshync profile generation # device id configuration
sshync.make_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'), for _id in listdir(path.expanduser('~/.config/sshyp/devices')): # remove existing device id
path.expanduser('~/.local/share/sshyp/'), f"/home/{_username_ssh}/.local/share/sshyp/", remove(f"{path.expanduser('~/.config/sshyp/devices/')}{_id}")
path.expanduser('~/.ssh/sshyp'), _ip, _port, _username_ssh) 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')
# device name configuration # quick-unlock configuration
for _name in listdir(path.expanduser('~/.config/sshyp/devices')): # remove existing device name print(f"{_divider}this allows you to use a shorter version of your gpg key password and\n"
remove(f"{path.expanduser('~/.config/sshyp/devices/')}{_name}") f"requires a constant connection to your sshyp server to authenticate")
print(f"{_divider}\u001b[4;1mimportant:\u001b[0m this name \u001b[4;1mmust\u001b[0m be unique amongst your " _sshyp_data += [input('\nenable quick-unlock? (y/N) ').lower()]
f"client devices\n\nthis is used to keep track of which devices have up-to-date databases\n") if _sshyp_data[3] == 'y':
_client_device_name = str(input('device name: ')) print(f"\nquick-unlock has been enabled client-side - in order for this device to be able to read "
open(f"{path.expanduser('~/.config/sshyp/devices/')}{_client_device_name}", 'w') f"entries,\nyou must first login to the sshyp server and run:\n\nsshyp whitelist setup "
copy_name_check(_port, _username_ssh, _ip, _client_device_name) f"(if not already done)\nsshyp whitelist add '{_device_id}'")
print(f"{_divider}configuration complete\n") # 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 def print_info(): # prints help text based on argument
if argument_list[1] == 'help' or argument_list[1] == '--help' or argument_list[1] == '-h': 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('\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 " 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") "comes with absolutely no warranty;\ntype 'sshyp license' for details")
print('\n\u001b[1musage:\u001b[0m sshyp [option [flag] [<entry name>]] | [/<entry name>]\n') if device_type == 'client':
print('\u001b[1moptions:\u001b[0m') print('\n\u001b[1musage:\u001b[0m sshyp [option [flag] [<entry name>]] | [/<entry name>]\n')
print('help/--help/-h bring up this menu') print('\u001b[1moptions:\u001b[0m')
print('version/-v display sshyp version info') print('help/--help/-h bring up this menu')
print('tweak configure sshyp') print('version/-v display sshyp version info')
print('add add an entry') print('tweak configure sshyp')
print('gen generate a new password') print('add add an entry')
print('edit edit an existing entry') print('gen generate a new password')
print('copy copy details of an entry to your clipboard') print('edit edit an existing entry')
print('shear/-rm delete an existing entry') print('copy copy details of an entry to your clipboard')
print('sync/-s manually sync the entry directory via sshync\n') print('shear/-rm delete an existing entry')
print('\u001b[1mflags:\u001b[0m') print('sync/-s manually sync the entry directory via sshync')
print('add:') print('\n\u001b[1mflags:\u001b[0m')
print(' password/-p add a password entry') print('add:')
print(' note/-n add a note entry') print(' password/-p add a password entry')
print(' folder/-f add a new folder for entries') print(' note/-n add a note entry')
print('edit:') print(' folder/-f add a new folder for entries')
print(' rename/relocate/-r rename or relocate an entry') print('edit:')
print(' username/-u change the username of an entry') print(' rename/relocate/-r rename or relocate an entry')
print(' password/-p change the password of an entry') print(' username/-u change the username of an entry')
print(' note/-n change the note attached to an entry') print(' password/-p change the password of an entry')
print(' url/-l change the url attached to an entry') print(' url/-l change the url attached to an entry')
print('copy:') print(' note/-n change the note attached to an entry')
print(' username/-u copy the username of an entry to your clipboard') print('copy:')
print(' password/-p copy the password of an entry to your clipboard') print(' username/-u copy the username of an entry to your clipboard')
print(' url/-l copy the url of an entry to your clipboard') print(' password/-p copy the password of an entry to your clipboard')
print(' note/-n copy the note of an entry to your clipboard') print(' url/-l copy the url of an entry to your clipboard')
print('gen:') print(' note/-n copy the note of an entry to your clipboard')
print(' update/-u generate a password for an existing entry\n') print('gen:')
print("\u001b[1mtip:\u001b[0m you can quickly read an entry with 'sshyp /<entry name>'") 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': 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/' 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') 'freebsd/linux/termux)\n\nsshyp is a viable alternative to (and compatible with) pass/password-store\n')
@@ -346,21 +413,20 @@ def print_info(): # prints help text based on argument
'randall winkhart\u001b[38;5;15;48;5;15m \u001b[38;5;7;48;5;8m/\u001b[0m') '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 ' print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m '
'\u001b[38;5;7;48;5;8m/\u001b[0m') '\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.1.1' 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') '\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 sheecrets ' 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') '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 ' print('\u001b[38;5;7;48;5;8m/\u001b[38;5;15;48;5;15m '
'\u001b[38;5;7;48;5;8m/\u001b[0m') '\u001b[38;5;7;48;5;8m/\u001b[0m')
print('\u001b[38;5;7;48;5;8m<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\u001b[0m\n') print('\u001b[38;5;7;48;5;8m<><><><><><><><><><><><><><><><><><><><><><><><><><><><>\u001b[0m\n')
print('see https://github.com/rwinkhart/sshyp for more information\n') print('see https://github.com/rwinkhart/sshyp for more information\n')
elif argument_list[1] == 'license': elif argument_list[1] == 'license':
print('\nThis program is free software: you can redistribute it and/or modify it under the terms of the GNU ' print('\nThis program is free software: you can redistribute it and/or modify it under the terms\nof version 3 '
'General\nPublic License as published by the Free Software Foundation, either version 3 of the License,' '(only) of the GNU General Public License as published by the Free Software Foundation.\n\nThis program '
'\nor (at your option) any later version.\n\nThis program is distributed in the hope that it will be ' 'is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;\nwithout even the implied '
'useful, but WITHOUT ANY WARRANTY;\nwithout even the implied warranty of MERCHANTABILITY or FITNESS FOR A' 'warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public License for'
' PARTICULAR PURPOSE.\nSee the GNU General Public License for more details.' ' more details.\n\nhttps://opensource.org/licenses/GPL-3.0\n')
'\n\nhttps://opensource.org/licenses/GPL-3.0\n')
elif argument_list[1] == 'add': elif argument_list[1] == 'add':
print('\n\u001b[1musage:\u001b[0m sshyp add [flag [<entry name>]]\u001b[0m\n') print('\n\u001b[1musage:\u001b[0m sshyp add [flag [<entry name>]]\u001b[0m\n')
print('\u001b[1mflags:\u001b[0m') print('\u001b[1mflags:\u001b[0m')
@@ -385,6 +451,18 @@ def print_info(): # prints help text based on argument
print(' password/-p copy the password 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(' url/-l copy the url of an entry to your clipboard')
print(' note/-n copy the note of an entry to your clipboard\n') 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 def no_arg(): # displays a list of entries and gives an option to select one for viewing
@@ -392,9 +470,9 @@ def no_arg(): # displays a list of entries and gives an option to select one fo
_entry_name = entry_name_fetch('entry to read: ') _entry_name = entry_name_fetch('entry to read: ')
if not Path(f"{directory}{_entry_name}.gpg").exists(): 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") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg) determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}") entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}") rmtree(f"{tmp_dir}{_shm_folder}")
@@ -402,9 +480,9 @@ def no_arg(): # displays a list of entries and gives an option to select one fo
def read_shortcut(): # shortcut to quickly read an entry def read_shortcut(): # shortcut to quickly read an entry
if not Path(f"{directory}{argument.replace('/', '', 1)}.gpg").exists(): 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") print(f"\n\u001b[38;5;9merror: entry ({argument.replace('/', '', 1)}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
decrypt(directory + argument.replace('/', '', 1), _shm_folder, _shm_entry, gpg) determine_decrypt(directory + argument.replace('/', '', 1), _shm_folder, _shm_entry, gpg)
entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}") entry_reader(f"{tmp_dir}{_shm_folder}/{_shm_entry}")
rmtree(f"{tmp_dir}{_shm_folder}") rmtree(f"{tmp_dir}{_shm_folder}")
@@ -412,8 +490,8 @@ def read_shortcut(): # shortcut to quickly read an entry
def sync(): # calls sshync to sync changes to the user's server def sync(): # calls sshync to sync changes to the user's server
print('\nsyncing entries with the server device...\n') print('\nsyncing entries with the server device...\n')
# check for deletions # check for deletions
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c " 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_name}\"'\")'\"") 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}" 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/')}") f"/.config/sshyp/deletion_database' {path.expanduser('~/.config/sshyp/')}")
try: try:
@@ -421,26 +499,20 @@ def sync(): # calls sshync to sync changes to the user's server
except (FileNotFoundError, IndexError): except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;9merror: the deletion database does not exist or is corrupted\u001b[0m\n') print('\n\u001b[38;5;9merror: the deletion database does not exist or is corrupted\u001b[0m\n')
_deletion_database = None _deletion_database = None
s_exit(1) s_exit(6)
for _file in _deletion_database: for _file in _deletion_database:
if _file[:-1].endswith('/'): try:
try: if silent_sync != 1:
if silent_sync != 1: print(f"\u001b[38;5;208m{_file[:-1]}\u001b[0m has been sheared, removing...")
print(f"\u001b[38;5;208m{_file[:-1]}\u001b[0m has been sheared, removing...") if _file[:-1].endswith('/'):
rmtree(f"{directory}{_file[:-1]}") rmtree(f"{directory}{_file[:-1]}")
except FileNotFoundError: else:
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"{directory}{_file[:-1]}.gpg") remove(f"{directory}{_file[:-1]}.gpg")
except (FileNotFoundError, IsADirectoryError): except FileNotFoundError:
if silent_sync != 1: if silent_sync != 1:
print('file does not exist locally.') print('location does not exist locally')
# check for new folders # check for new folders
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c " system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /lib/sshyp; python -c "
f"'import sshypRemote; sshypRemote.folder_check()'\"") f"'import sshypRemote; sshypRemote.folder_check()'\"")
system(f"scp -pqs -P {port} -i '{path.expanduser('~/.ssh/sshyp')}' {username_ssh}@{ip}:'/home/{username_ssh}" 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/')}") f"/.config/sshyp/folder_database' {path.expanduser('~/.config/sshyp/')}")
@@ -449,7 +521,7 @@ def sync(): # calls sshync to sync changes to the user's server
except (FileNotFoundError, IndexError): except (FileNotFoundError, IndexError):
print('\n\u001b[38;5;9merror: the folder database does not exist or is corrupted\u001b[0m\n') print('\n\u001b[38;5;9merror: the folder database does not exist or is corrupted\u001b[0m\n')
_folder_database = None _folder_database = None
s_exit(1) s_exit(6)
for _folder in _folder_database: for _folder in _folder_database:
if Path(f"{path.expanduser('~')}{_folder[:-1]}").is_dir(): if Path(f"{path.expanduser('~')}{_folder[:-1]}").is_dir():
pass pass
@@ -463,6 +535,107 @@ def sync(): # calls sshync to sync changes to the user's server
sshync.run_profile(path.expanduser('~/.config/sshyp/sshyp.sshync')) 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 def add_entry(): # adds a new entry
_shm_folder, _shm_entry = None, None # sets base-line values to avoid errors _shm_folder, _shm_entry = None, None # sets base-line values to avoid errors
if len(argument_list) < 4: if len(argument_list) < 4:
@@ -471,10 +644,10 @@ def add_entry(): # adds a new entry
_entry_name = entry_name_fetch(2) _entry_name = entry_name_fetch(2)
if Path(f"{directory}{_entry_name}.gpg").is_file(): if Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n")
s_exit(1) s_exit(4)
if argument_list[2] == 'note' or argument_list[2] == '-n': if argument_list[2] == 'note' or argument_list[2] == '-n':
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
system(f"{editor} {tmp_dir}{_shm_folder}/{_shm_entry}-n") system(f"{editor} '{tmp_dir}{_shm_folder}/{_shm_entry}-n'")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read() _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)) 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': elif argument_list[2] == 'password' or argument_list[2] == '-p':
@@ -484,7 +657,7 @@ def add_entry(): # adds a new entry
_add_note = input('add a note to this entry? (y/N) ') _add_note = input('add a note to this entry? (y/N) ')
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
if _add_note.lower() == 'y': if _add_note.lower() == 'y':
system(f"{editor} {tmp_dir}{_shm_folder}/{_shm_entry}-n") system(f"{editor} '{tmp_dir}{_shm_folder}/{_shm_entry}-n'")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read() _notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
else: else:
_notes = '' _notes = ''
@@ -501,8 +674,9 @@ def add_folder(): # creates a new folder
else: else:
_entry_name = entry_name_fetch(2) _entry_name = entry_name_fetch(2)
Path(directory + _entry_name).mkdir(0o700) Path(directory + _entry_name).mkdir(0o700)
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p '{directory_ssh}" if ssh_error != 1:
f"{_entry_name}'\"") 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 def rename(): # renames an entry or folder
@@ -512,20 +686,21 @@ def rename(): # renames an entry or folder
_entry_name = entry_name_fetch(2) _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(): 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") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
_new_name = str(input('new name: ')) _new_name = entry_name_fetch('new name: ')
print(f"{directory}{_new_name}")
if Path(f"{directory}{_new_name}.gpg").is_file() or Path(f"{directory}{_new_name}").is_dir(): 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") print(f"\n\u001b[38;5;9merror: ({_new_name}) already exists\u001b[0m\n")
s_exit(1) s_exit(4)
if _entry_name.endswith('/'): if _entry_name.endswith('/'):
move(f"{directory}{_entry_name}", f"{directory}{_new_name}") 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}" if ssh_error != 1:
f"{_new_name}'\"") system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"mkdir -p "
f"'{directory_ssh}{_new_name}'\"")
else: else:
move(f"{directory}{_entry_name}.gpg", f"{directory}{_new_name}.gpg") 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 " if ssh_error != 1:
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\")'\"") 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 def edit(): # edits the contents of an entry
@@ -536,9 +711,9 @@ def edit(): # edits the contents of an entry
_entry_name = entry_name_fetch(2) _entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file(): 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") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg) determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
if argument_list[2] == 'username' or argument_list[2] == '-u': if argument_list[2] == 'username' or argument_list[2] == '-u':
_detail, _edit_line = str(input('username: ')), 1 _detail, _edit_line = str(input('username: ')), 1
elif argument_list[2] == 'password' or argument_list[2] == '-p': elif argument_list[2] == 'password' or argument_list[2] == '-p':
@@ -566,20 +741,20 @@ def gen(): # generates a password for a new or an existing entry
_entry_name = entry_name_fetch(2) _entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file(): 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") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
else: else:
_entry_name = entry_name_fetch(1) _entry_name = entry_name_fetch(1)
if len(argument_list) == 2 or (not argument_list[2] == 'update' and not argument_list[2] == '-u'): 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(): if Path(f"{directory}{_entry_name}.gpg").is_file():
print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) already exists\u001b[0m\n")
s_exit(1) s_exit(4)
_username = str(input('username: ')) _username = str(input('username: '))
_password = pass_gen() _password = pass_gen()
_url = str(input('url: ')) _url = str(input('url: '))
_add_note = input('add a note to this entry? (y/N) ') _add_note = input('add a note to this entry? (y/N) ')
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
if _add_note.lower() == 'y': if _add_note.lower() == 'y':
system(f"{editor} {tmp_dir}{_shm_folder}/{_shm_entry}-n") system(f"{editor} '{tmp_dir}{_shm_folder}/{_shm_entry}-n'")
_notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read() _notes = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}-n", 'r').read()
else: else:
_notes = '' _notes = ''
@@ -587,7 +762,7 @@ def gen(): # generates a password for a new or an existing entry
.writelines(optimized_edit([_password, _username, _url, _notes], None, -1)) .writelines(optimized_edit([_password, _username, _url, _notes], None, -1))
else: else:
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg) 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) _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) open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'w').writelines(_new_lines)
remove(f"{directory}{_entry_name}.gpg") remove(f"{directory}{_entry_name}.gpg")
@@ -603,49 +778,49 @@ def copy_data(): # copies a specified field of an entry to the clipboard
_entry_name = entry_name_fetch(2) _entry_name = entry_name_fetch(2)
if not Path(f"{directory}{_entry_name}.gpg").is_file(): 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") print(f"\n\u001b[38;5;9merror: entry ({_entry_name}) does not exist\u001b[0m\n")
s_exit(1) s_exit(3)
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg) determine_decrypt(directory + _entry_name, _shm_folder, _shm_entry, gpg)
_copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines() _copy_line = open(f"{tmp_dir}{_shm_folder}/{_shm_entry}", 'r').readlines()
if uname()[0] == 'Haiku': # Haiku clipboard detection if uname()[0] == 'Haiku': # Haiku clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u': if argument_list[2] == 'username' or argument_list[2] == '-u':
system('clipboard -c ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'") system('clipboard -c ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p': elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('clipboard -c ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'") system('clipboard -c ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l': elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('clipboard -c ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'") system('clipboard -c ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n': elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('clipboard -c ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'") system('clipboard -c ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen('sleep 30; clipboard -r', shell=True, close_fds=True) Popen('sleep 30; clipboard -r', shell=True, close_fds=True)
elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u': if argument_list[2] == 'username' or argument_list[2] == '-u':
system('termux-clipboard-set ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'") system('termux-clipboard-set ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p': elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('termux-clipboard-set ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'") system('termux-clipboard-set ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l': elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('termux-clipboard-set ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'") system('termux-clipboard-set ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n': elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('termux-clipboard-set ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'") system('termux-clipboard-set ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen("sleep 30; termux-clipboard-set ''", shell=True, close_fds=True) Popen("sleep 30; termux-clipboard-set ''", shell=True, close_fds=True)
elif environ.get('WAYLAND_DISPLAY') == 'wayland-0': # Wayland clipboard detection elif environ.get('WAYLAND_DISPLAY') == 'wayland-0': # Wayland clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u': if argument_list[2] == 'username' or argument_list[2] == '-u':
system('wl-copy ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'") system('wl-copy ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'password' or argument_list[2] == '-p': elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('wl-copy ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'") system('wl-copy ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'url' or argument_list[2] == '-l': elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('wl-copy ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'") system('wl-copy ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'")
elif argument_list[2] == 'note' or argument_list[2] == '-n': elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('wl-copy ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'") system('wl-copy ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'")
Popen('sleep 30; wl-copy -c', shell=True, close_fds=True) Popen('sleep 30; wl-copy -c', shell=True, close_fds=True)
else: # X11 clipboard detection else: # X11 clipboard detection
if argument_list[2] == 'username' or argument_list[2] == '-u': if argument_list[2] == 'username' or argument_list[2] == '-u':
system('echo -n ' + "'" + _copy_line[1].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c') system('echo -n ' + "'" + _copy_line[1].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'password' or argument_list[2] == '-p': elif argument_list[2] == 'password' or argument_list[2] == '-p':
system('echo -n ' + "'" + _copy_line[0].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c') system('echo -n ' + "'" + _copy_line[0].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'url' or argument_list[2] == '-l': elif argument_list[2] == 'url' or argument_list[2] == '-l':
system('echo -n ' + "'" + _copy_line[2].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c') system('echo -n ' + "'" + _copy_line[2].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
elif argument_list[2] == 'note' or argument_list[2] == '-n': elif argument_list[2] == 'note' or argument_list[2] == '-n':
system('echo -n ' + "'" + _copy_line[3].replace('\n', '').replace("'", "'\\''") + "'" + ' | xclip -sel c') system('echo -n ' + "'" + _copy_line[3].rstrip().replace("'", "'\\''") + "'" + ' | xclip -sel c')
Popen("sleep 30; echo -n '' | xclip -sel c", shell=True, close_fds=True) Popen("sleep 30; echo -n '' | xclip -sel c", shell=True, close_fds=True)
rmtree(f"{tmp_dir}{_shm_folder}") rmtree(f"{tmp_dir}{_shm_folder}")
@@ -655,9 +830,13 @@ def remove_data(): # deletes an entry from the server and flags it for local de
_entry_name = entry_name_fetch('entry/folder to shear: ') _entry_name = entry_name_fetch('entry/folder to shear: ')
else: else:
_entry_name = entry_name_fetch(1) _entry_name = entry_name_fetch(1)
decrypt(path.expanduser('~/.config/sshyp/lock.gpg'), 0, 0, gpg) determine_decrypt(path.expanduser('~/.config/sshyp/lock.gpg'), 0, 0, gpg)
system(f"ssh -i '{path.expanduser('~/.ssh/sshyp')}' -p {port} {username_ssh}@{ip} \"cd /bin; python -c " if ssh_error != 1:
f"'import sshypRemote; sshypRemote.delete(\"'\"{_entry_name}\"'\")'\"") 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__": if __name__ == "__main__":
@@ -672,34 +851,41 @@ if __name__ == "__main__":
gpg = 'gpg' gpg = 'gpg'
# import saved userdata # import saved userdata
device_type = ''
if argument != 'tweak': if argument != 'tweak':
device_type = ''
tmp_dir = path.expanduser('~/.config/sshyp/tmp/') tmp_dir = path.expanduser('~/.config/sshyp/tmp/')
try: try:
device_type = open(path.expanduser('~/.config/sshyp/sshyp-device')).read().strip() sshyp_data = open(path.expanduser('~/.config/sshyp/sshyp-data')).readlines()
if device_type == 'c': device_type = sshyp_data[0].rstrip()
ssh_info = sshync.get_profile(path.expanduser('~/.config/sshyp/sshyp.sshync')) if device_type == 'client':
username_ssh = ssh_info[0].replace('\n', '') directory = path.expanduser('~/.local/share/sshyp/')
ip = ssh_info[1].replace('\n', '') gpg_id = sshyp_data[1].rstrip()
port = ssh_info[2].replace('\n', '') editor = sshyp_data[2].rstrip()
directory = str(ssh_info[3].replace('\n', '')) quick_unlock_enabled = sshyp_data[3].rstrip()
directory_ssh = str(ssh_info[4].replace('\n', '')) if Path(path.expanduser('~/.config/sshyp/sshyp.sshync')).is_file():
client_device_name = listdir(path.expanduser('~/.config/sshyp/devices'))[0] ssh_info = sshync.get_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'))
sshyp_data = open(path.expanduser('~/.config/sshyp/sshyp-data')).readlines() username_ssh = ssh_info[0].rstrip()
gpg_id = sshyp_data[0].replace('\n', '') ip = ssh_info[1].rstrip()
editor = sshyp_data[1].replace('\n', '') port = ssh_info[2].rstrip()
ssh_error = int(open(path.expanduser('~/.config/sshyp/ssh-error')).read().strip()) directory_ssh = str(ssh_info[4].rstrip())
if ssh_error != 0: client_device_id = listdir(path.expanduser('~/.config/sshyp/devices'))[0].rstrip()
ssh_error = copy_name_check(port, username_ssh, ip, client_device_name) ssh_error = int(open(path.expanduser('~/.config/sshyp/ssh-error')).read().rstrip())
else: if ssh_error != 0:
print('running as server, option disabled') ssh_error = copy_id_check(port, username_ssh, ip, client_device_id)
s_exit(0) 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): except (FileNotFoundError, IndexError):
if device_type.lower() != 's': print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
print('\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') print("not all necessary configuration files are present - please run 'sshyp tweak'")
print("not all necessary configuration files are present - please run 'sshyp tweak'") print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n')
print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') s_exit(2)
s_exit(1)
else: else:
tweak() tweak()
s_exit(0) s_exit(0)
@@ -712,6 +898,20 @@ if __name__ == "__main__":
elif argument == 'help' or argument == '--help' or argument == '-h' or argument == 'license' or argument \ elif argument == 'help' or argument == '--help' or argument == '-h' or argument == 'license' or argument \
== 'version' or argument == '-v': == 'version' or argument == '-v':
print_info() 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': elif argument_list[1] == 'add':
if len(argument_list) == 2: if len(argument_list) == 2:
print_info() print_info()
@@ -722,7 +922,6 @@ if __name__ == "__main__":
add_folder() add_folder()
else: else:
print_info() print_info()
s_exit(0)
elif argument_list[1] == 'edit': elif argument_list[1] == 'edit':
if len(argument_list) == 2: if len(argument_list) == 2:
print_info() print_info()
@@ -735,7 +934,6 @@ if __name__ == "__main__":
edit() edit()
else: else:
print_info() print_info()
s_exit(0)
elif argument_list[1] == 'gen': elif argument_list[1] == 'gen':
gen() gen()
elif argument_list[1] == 'copy': elif argument_list[1] == 'copy':
@@ -744,7 +942,11 @@ if __name__ == "__main__":
elif argument_list[2] == 'username' or argument_list[2] == '-u' or argument_list[2] == 'password' or \ 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] == '-p' or argument_list[2] == 'url' or argument_list[2] == '-l' or \
argument_list[2] == 'note' or argument_list[2] == '-n': argument_list[2] == 'note' or argument_list[2] == '-n':
copy_data() 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: else:
print_info() print_info()
elif argument_list[1] == 'shear' or argument_list[1] == '-rm': elif argument_list[1] == 'shear' or argument_list[1] == '-rm':
@@ -754,15 +956,11 @@ if __name__ == "__main__":
s_exit(1) s_exit(1)
# sync if any changes were made # sync if any changes were made
if len(argument_list) > 1 and ssh_error == 0 and \ if len(argument_list) > 1 and ssh_error == 0 \
((argument_list[1] == 'sync' or argument_list[1] == '-s' or argument_list[1] == 'gen' or 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' argument_list[1] == 'shear' or argument_list[1] == '-rm') or
or argument_list[1] == 'edit') ((argument_list[1] == 'add' or argument_list[1] == 'edit') and len(argument_list) > 2)):
and len(argument_list) > 2)):
sync() sync()
s_exit(0)
except KeyboardInterrupt: except KeyboardInterrupt:
print('\n') print('\n')
s_exit(0)
+7 -10
View File
@@ -1,4 +1,4 @@
#!/bin/python3 #!/usr/bin/env python3
# external modules # external modules
@@ -9,17 +9,14 @@ from shutil import rmtree
# utility functions # utility functions
def delete(_file_path): # deletes an entry or folder, should be run remotely via ssh def delete(_file_path, _target_database): # deletes an entry or folder, should be run remotely via ssh
if _file_path.endswith('/'): try:
try: if _file_path.endswith('/'):
rmtree(f"{expanduser('~/.local/share/sshyp/')}{_file_path}") rmtree(f"{expanduser('~/.local/share/sshyp/')}{_file_path}")
except FileNotFoundError: else:
print('folder does not exist remotely')
else:
try:
remove(f"{expanduser('~/.local/share/sshyp/')}{_file_path}.gpg") remove(f"{expanduser('~/.local/share/sshyp/')}{_file_path}.gpg")
except FileNotFoundError: except FileNotFoundError:
print('file does not exist remotely') print(f"location does not exist {_target_database}")
for _device_name in listdir(expanduser('~/.config/sshyp/devices')): for _device_name in listdir(expanduser('~/.config/sshyp/devices')):
open(f"{expanduser('~/.config/sshyp/deleted/')}{_file_path.replace('/', '@')}^&*{_device_name}", 'w') open(f"{expanduser('~/.config/sshyp/deleted/')}{_file_path.replace('/', '@')}^&*{_device_name}", 'w')
+191 -147
View File
@@ -1,39 +1,80 @@
#!/bin/bash #!/usr/bin/env bash
# This script packages sshyp (from source) for various UNIX(-like) environments. version=$(sed -n '1{p;q}' share/doc/sshyp/changelog | cut -c8-)
# Dependencies (Arch Linux): dpkg (packaging for Debian/Termux), freebsd-pkg (packaging for FreeBSD) if [ -z "$2" ]; then
# Dependencies (Fedora) (can only package for self): rpmdevtools revision=1
# NOTE It is recommended to instead use the latest officially packaged and tagged release. else
revision="$2"
echo -e '\nOptions (please enter the number only):'
echo -e '\nPackage Formats:\n\n1. Haiku\n2. Debian&Ubuntu Linux\n3. Fedora Linux\n4. FreeBSD\n5. Termux\n6. Generic (used for PKGBUILD/APKBUILD)'
echo -e '\nBuild Scripts:\n\n7. Arch Linux (PKGBUILD)'
echo -e '\nOther:\n\n8. All (generates all distribution packages (excluding Haiku and Fedora, as these must be packaged on their respective distributions) 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" == "7" ] || [ "$distro" == "8" ]; then
echo -e '\nOptions (please enter the number only):'
echo -e '\n1. GitHub Release Tag\n2. Local\n'
read -r -p "Source (for build scripts): " source
if [ "$source" == "1" ]; then
source='https://github.com/rwinkhart/sshyp/releases/download/v$pkgver/sshyp-$pkgver.tar.xz'
else
source=local://sshyp-"$version".tar.xz
fi
fi 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 _create_pkgbuild() {
echo -e '\nPackaging for Haiku...\n' source='https://github.com/rwinkhart/sshyp/releases/download/v$pkgver/sshyp-$pkgver.tar.xz'
mkdir -p packages/haikutemp/documentation/{man/man1,packages/sshyp} 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 echo "name sshyp
version "$version"-"$revision" version "$version"-"$revision"
architecture any architecture any
@@ -54,30 +95,34 @@ provides {
requires { requires {
gnupg gnupg
openssh openssh
python3 python310
} }
urls { urls {
\"https://github.com/rwinkhart/sshyp\" \"https://github.com/rwinkhart/sshyp\"
} }
" > packages/haikutemp/.PackageInfo " > output/haikutemp/.PackageInfo
cp -r bin packages/haikutemp/ cp -r lib/. output/haikutemp/lib/sshyp/
ln -s /bin/sshyp.py packages/haikutemp/bin/sshyp sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshync.py
cp -r share/doc/sshyp/ packages/haikutemp/documentation/packages/ sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshyp.py
cp -r share/licenses/sshyp/ packages/haikutemp/documentation/packages/ sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshypRemote.py
cp extra/manpage packages/haikutemp/documentation/man/man1/sshyp.1 ln -s /system/lib/sshyp/sshyp.py output/haikutemp/bin/sshyp
gzip packages/haikutemp/documentation/man/man1/sshyp.1 cp -r share/doc/sshyp/. output/haikutemp/documentation/packages/sshyp/
cd packages/haikutemp 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 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 ../.. cd ../..
mv packages/haikutemp/sshyp-"$version"-"$revision"_all.hpkg packages/ mv output/haikutemp/sshyp-"$version"-"$revision"_all.hpkg output/
rm -rf packages/haikutemp rm -rf output/haikutemp
echo -e "\nHaiku packaging complete.\n" echo -e "\nHaiku packaging complete\n"
fi } &&
if [ "$distro" == "2" ] || [ "$distro" == "8" ]; then _create_deb() {
echo -e '\nPackaging for Debian...\n' echo -e '\npackaging for Debian/Ubuntu...\n'
mkdir -p packages/debiantemp/sshyp_"$version"-"$revision"_all/{DEBIAN,usr/share/man/man1} mkdir -p output/debiantemp/sshyp_"$version"-"$revision"_all/{DEBIAN,usr/{lib/sshyp,bin,share/{bash-completion/completions,man/man1}}}
echo "Package: sshyp echo "Package: sshyp
Version: $version Version: $version
Section: utils Section: utils
@@ -85,23 +130,25 @@ Architecture: all
Maintainer: Randall Winkhart <idgr at tutanota dot com> Maintainer: Randall Winkhart <idgr at tutanota dot com>
Description: A light-weight, self-hosted, synchronized password manager Description: A light-weight, self-hosted, synchronized password manager
Depends: python3, gnupg, openssh-client, xclip, wl-clipboard Depends: python3, gnupg, openssh-client, xclip, wl-clipboard
Suggests: bash-completion
Priority: optional Priority: optional
Installed-Size: 185 Installed-Size: 14584
" > packages/debiantemp/sshyp_"$version"-"$revision"_all/DEBIAN/control " > output/debiantemp/sshyp_"$version"-"$revision"_all/DEBIAN/control
cp -r bin packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/ cp -r lib/. output/debiantemp/sshyp_"$version"-"$revision"_all/usr/lib/sshyp/
ln -s /usr/bin/sshyp.py packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/bin/sshyp ln -s /usr/lib/sshyp/sshyp.py output/debiantemp/sshyp_"$version"-"$revision"_all/usr/bin/sshyp
cp -r share packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/ cp -r share output/debiantemp/sshyp_"$version"-"$revision"_all/usr/
cp extra/manpage packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1 cp extra/sshyp-completion.bash output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/bash-completion/completions/sshyp
gzip packages/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1 cp extra/manpage output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
dpkg-deb --build --root-owner-group packages/debiantemp/sshyp_"$version"-"$revision"_all/ gzip output/debiantemp/sshyp_"$version"-"$revision"_all/usr/share/man/man1/sshyp.1
mv packages/debiantemp/sshyp_"$version"-"$revision"_all.deb packages/ dpkg-deb --build --root-owner-group output/debiantemp/sshyp_"$version"-"$revision"_all/
rm -rf packages/debiantemp mv output/debiantemp/sshyp_"$version"-"$revision"_all.deb output/
echo -e "\nDebian packaging complete.\n" rm -rf output/debiantemp
fi echo -e "\nDebian/Ubuntu packaging complete\n"
} &&
if [ "$distro" == "5" ] || [ "$distro" == "8" ]; then _create_termux() {
echo -e '\nPackaging for Termux...\n' echo -e '\npackaging for Termux...\n'
mkdir -p packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/{data/data/com.termux/files/usr/share/man/man1,DEBIAN} 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 echo "Package: sshyp
Version: $version Version: $version
Section: utils Section: utils
@@ -109,79 +156,61 @@ Architecture: all
Maintainer: Randall Winkhart <idgr at tutanota dot com> Maintainer: Randall Winkhart <idgr at tutanota dot com>
Description: A light-weight, self-hosted, synchronized password manager Description: A light-weight, self-hosted, synchronized password manager
Depends: python, gnupg, openssh, termux-api, termux-am Depends: python, gnupg, openssh, termux-api, termux-am
Suggests: bash-completion
Priority: optional Priority: optional
Installed-Size: 185 Installed-Size: 14584
" > packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/DEBIAN/control " > output/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 lib/. output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/
ln -s /data/data/com.termux/files/usr/bin/sshyp.py packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/bin/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 packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/ cp -r share output/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 cp extra/sshyp-completion.bash output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/bash-completion/completions/sshyp
gzip packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1 cp extra/manpage output/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/ gzip output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp.1
mv packages/termuxtemp/sshyp_"$version"-"$revision"_all_termux.deb packages/ dpkg-deb --build --root-owner-group output/termuxtemp/sshyp_"$version"-"$revision"_all_termux/
rm -rf packages/termuxtemp mv output/termuxtemp/sshyp_"$version"-"$revision"_all_termux.deb output/
echo -e "\nTermux packaging complete.\n" rm -rf output/termuxtemp
fi echo -e "\nTermux packaging complete\n"
} &&
if [ "$distro" == "3" ] || [ "$distro" == "4" ] || [ "$distro" == "6" ] || [ "$distro" == "7" ] || [ "$distro" == "8" ]; then _create_rpm() {
echo -e '\nPackaging as generic...\n' echo -e '\npackaging for Fedora...\n'
mkdir -p packages/generictemp/usr/share/man/man1
cp -r bin packages/generictemp/usr/
ln -s /usr/bin/sshyp.py packages/generictemp/usr/bin/sshyp
cp -r share packages/generictemp/usr/
cp extra/manpage packages/generictemp/usr/share/man/man1/sshyp.1
gzip packages/generictemp/usr/share/man/man1/sshyp.1
tar -C packages/generictemp -cvf packages/sshyp-"$version".tar.xz usr/
rm -rf packages/generictemp
sha512="$(sha512sum packages/sshyp-"$version".tar.xz | awk '{print $1;}')"
echo -e "\nsha512 sum:\n$sha512"
echo -e "\nGeneric packaging complete.\n"
fi
if [ "$distro" == "3" ]; then
echo -e '\nPackaging for Fedora...\n'
rm -rf ~/rpmbuild rm -rf ~/rpmbuild
rpmdev-setuptree rpmdev-setuptree
cp packages/sshyp-"$version".tar.xz ~/rpmbuild/SOURCES cp output/sshyp-"$version".tar.xz ~/rpmbuild/SOURCES
echo "Name: sshyp echo "Name: sshyp
Version: "$version" Version: "$version"
Release: "$revision" Release: "$revision"
Summary: A light-weight, self-hosted, synchronized password manager Summary: A light-weight, self-hosted, synchronized password manager
BuildArch: noarch BuildArch: noarch
License: GPL-3.0-only
License: GPLv3
URL: https://github.com/rwinkhart/sshyp URL: https://github.com/rwinkhart/sshyp
Source0: sshyp-"$version".tar.xz Source0: sshyp-"$version".tar.xz
Requires: python gnupg openssh-clients wl-clipboard
Requires: python gnupg openssh wl-clipboard Recommends: bash-completion
%description %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. 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 %install
tar xf %{_sourcedir}/sshyp-"$version".tar.xz -C %{_sourcedir} tar xf %{_sourcedir}/sshyp-"$version".tar.xz -C %{_sourcedir}
cp -r %{_sourcedir}/usr %{buildroot} cp -r %{_sourcedir}/usr %{buildroot}
%files %files
/usr/bin/sshyp /usr/bin/sshyp
/usr/bin/sshyp.py /usr/lib/sshyp/sshyp.py
/usr/bin/sshync.py /usr/lib/sshyp/sshync.py
/usr/bin/sshypRemote.py /usr/lib/sshyp/sshypRemote.py
/usr/share/bash-completion/completions/sshyp
%license /usr/share/licenses/sshyp/license %license /usr/share/licenses/sshyp/license
%doc /usr/share/doc/sshyp/changelog %changelog /usr/share/doc/sshyp/changelog
%doc /usr/share/man/man1/sshyp.1.gz %doc /usr/share/man/man1/sshyp.1.gz
" > ~/rpmbuild/SPECS/sshyp.spec " > ~/rpmbuild/SPECS/sshyp.spec
rpmbuild -bb ~/rpmbuild/SPECS/sshyp.spec rpmbuild -bb ~/rpmbuild/SPECS/sshyp.spec
mv ~/rpmbuild/RPMS/noarch/* packages/ mv ~/rpmbuild/RPMS/noarch/* output/
rm -rf ~/rpmbuild rm -rf ~/rpmbuild
echo -e "\nFedora packaging complete.\n" echo -e "\nFedora packaging complete\n"
fi } &&
if [ "$distro" == "4" ] || [ "$distro" == "8" ]; then _create_freebsd_pkg() {
echo -e '\nPackaging for FreeBSD...\n' echo -e '\npackaging for FreeBSD...'
mkdir -p packages/FreeBSDtemp/bin mkdir -p output/freebsdtemp/usr/{lib/sshyp,bin,share/{bash-completion/completions,man/man1}}
tar xf packages/sshyp-"$version".tar.xz -C packages/FreeBSDtemp
ln -s /usr/local/bin/python3 packages/FreeBSDtemp/bin/python3
echo "name: sshyp echo "name: sshyp
version: \""$version"\" version: \""$version"\"
abi = \"FreeBSD:13:*\"; abi = \"FreeBSD:13:*\";
@@ -206,42 +235,57 @@ prefix: /
\"origin\" : \"x11/wl-clipboard\" \"origin\" : \"x11/wl-clipboard\"
}, },
}, },
" > packages/FreeBSDtemp/+MANIFEST " > output/freebsdtemp/+MANIFEST
echo "/bin/python3 echo "/usr/bin/sshyp
/usr/bin/sshync.py /usr/lib/sshyp/sshync.py
/usr/bin/sshyp /usr/lib/sshyp/sshyp.py
/usr/bin/sshyp.py /usr/lib/sshyp/sshypRemote.py
/usr/bin/sshypRemote.py /usr/share/bash-completion/completions/sshyp
/usr/share/doc/sshyp/changelog /usr/share/doc/sshyp/changelog
/usr/share/licenses/sshyp/license /usr/share/licenses/sshyp/license
/usr/share/man/man1/sshyp.1.gz /usr/share/man/man1/sshyp.1.gz
" > packages/FreeBSDtemp/plist " > output/freebsdtemp/plist
pkg create -m packages/FreeBSDtemp/ -r packages/FreeBSDtemp/ -p packages/FreeBSDtemp/plist -o packages/ cp -r lib/. output/freebsdtemp/usr/lib/sshyp/
rm -rf packages/FreeBSDtemp ln -s /usr/lib/sshyp/sshyp.py output/freebsdtemp/usr/bin/sshyp
echo -e "\nFreeBSD packaging complete.\n" cp -r share output/freebsdtemp/usr/
fi 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"
} &&
if [ "$distro" == "7" ] || [ "$distro" == "8" ]; then if [ "$1" == "generic" ]; then # build scripts
echo -e '\nGenerating PKGBUILD...' _create_generic
echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com> elif [ "$1" == "pkgbuild" ]; then
_create_generic
pkgname=sshyp _create_pkgbuild
pkgver="$version" elif [ "$1" == "apkbuild" ]; then
pkgrel="$revision" _create_generic
pkgdesc='A light-weight, self-hosted, synchronized password manager' _create_apkbuild
url='https://github.com/rwinkhart/sshyp' elif [ "$1" == "haiku" ]; then # distribution packages
arch=('any') _create_hpkg
license=('GPL3') elif [ "$1" == "debian" ]; then
depends=(python gnupg openssh xclip wl-clipboard) _create_deb
elif [ "$1" == "termux" ]; then
source=(\""$source"\") _create_termux
sha512sums=('"$sha512"') elif [ "$1" == "fedora" ]; then
_create_generic
package() { _create_rpm
elif [ "$1" == "freebsd" ]; then
tar xf sshyp-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\"" _create_freebsd_pkg
elif [ "$1" == "buildable-arch" ]; then
} _create_generic
" > packages/PKGBUILD _create_pkgbuild
echo -e "\nPKGBUILD generated.\n" _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 fi
Executable → Regular
+42 -14
View File
@@ -1,27 +1,55 @@
sshyp v1.1.1 sshyp v1.2.0
the sheecrets update - patch one the brisk bahh update
this is a polish/bug fix release that makes tweaks to the entry format (without breaking compatibility) this release focuses on speeding up the sshyp user experience by adding
new features that reduce wasted time
compatibility-breaking changes: compatibility-breaking changes:
- none; the entry format tweaks are backward compatible with sshyp v1.0.0+ - new configuration options (quick-unlock, offline mode) have been added and
^ the new format is slightly more efficient in terms of storage space the configuration files have been reorganized
^ if you would like to upgrade to it, run this script (after updating to v1.1.1): ^ simply running "sshyp tweak" and following the setup wizard will correct any compatibility
https://raw.githubusercontent.com/rwinkhart/sshyp-labs/main/extra/conversion-scripts/sshyp-refresh-1.1.1%2B.py 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: user-facing features:
- entries (when editing or adding) are now run through the new optimized_edit() function to strip trailing new lines - quick-unlock mode has been added
and ensure the format of the entries is fully compatible with all of sshyp's functions ^ 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: fixes/optimizations:
- when adding a note to an entry, there is no longer a chance the first note line will be added as a url - fixed entries with multi-word titles failing to decrypt
if the entry is using an older format/pass format - password generation is now much faster and more resource efficient
- the gpg auto-generation file temporarily created by sshyp no longer includes extra spaces - there is no longer a length limit on generated passwords
^ seems to serve no functional purpose - fixed for the sake of polish - 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)
<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
Executable → Regular
+3 -4
View File
@@ -2,9 +2,8 @@
Copyright (C) 2022 Randall Winkhart idgr@tutanota.com Copyright (C) 2022 Randall Winkhart idgr@tutanota.com
This program is free software: you can redistribute it and/or modify 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 it under the terms of version 3 (only) of the GNU General Public License
the Free Software Foundation, either version 3 of the License, or as published by the Free Software Foundation.
(at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -12,4 +11,4 @@
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License 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/>.