13 Commits
7 changed files with 40 additions and 37 deletions
+8 -3
View File
@@ -1,16 +1,21 @@
# sshyp-labs # sshyp-labs
Experimental extensions for the sshyp password manager. Experimental extensions for the sshyp password manager.
sshyp-labs is currently the home of sshyp-mfa, and soon to be the home of password-pasture (sshyp-gui). sshyp-labs is currently the home of sshyp-mfa and password-pasture (sshyp-gui).
# Available Extensions # Available Extensions
sshyp-mfa - [installation and usage instructions](https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa) sshyp-mfa - [installation and usage instructions](https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa)
sshyp-mfa is a unique approach to generating multi-factor authentication keys. Upon running `sshyp-mfa <target entry>`, sshyp-mfa is a unique approach to generating multi-factor authentication keys. Upon running `sshyp </entry name> copy -m`,
an MFA key will be generated and copied to your clipboard. sshyp-mfa will continue to run in the background and copy a an MFA key will be generated and copied to your clipboard. sshyp-mfa will continue to run in the background and copy a
new key to your clipboard every time the actively copied one expires. Never worry about a TOTP timer expiring, again! new key to your clipboard every time the actively copied one expires. Never worry about a TOTP timer expiring again!
At any time, sshyp-mfa can be closed with ctrl+c to stop this process. At any time, sshyp-mfa can be closed with ctrl+c to stop this process.
password-pasture - [installation and usage instructions](https://github.com/rwinkhart/sshyp-labs/wiki/password-pasture)
password-pasture is an incredibly experimental GTK4 GUI interface for sshyp. It is currently not in a usable state
and has not been updated since sshyp v1.1.X. Development is set to resume after sshyp is more feature-complete.
# Acknowledgements # Acknowledgements
sshyp-mfa relies on [ValvePython/steam](https://github.com/ValvePython/steam) for Steam support. sshyp-mfa relies on [ValvePython/steam](https://github.com/ValvePython/steam) for Steam support.
+5 -5
View File
@@ -1,15 +1,15 @@
.TH sshyp-mfa 1 "12 July 2022" "rolling" "sshyp-mfa man page" .TH sshyp-mfa 1 "04 March 2023" "v1.4.0.1" "sshyp-mfa man page"
.SH NAME .SH NAME
sshyp-mfa \- An MFA (TOTP/Steam) key generator for the sshyp password manager. sshyp-mfa \- An MFA (TOTP/Steam) key generator for the sshyp password manager.
.SH SYNOPSIS .SH SYNOPSIS
sshyp-mfa [/<entry name>] Extension Usage: sshyp </entry name> copy -m
Direct Usage: sshyp-mfa </entry name>
.SH DESCRIPTION .SH DESCRIPTION
sshyp-mfa is an extension for the sshyp password manager that reads MFA data from sshyp entries and generates generic TOTP and Steam keys. sshyp-mfa is an extension for the sshyp password manager that reads MFA data from sshyp entries and generates generic TOTP and Steam keys.
.SH EXAMPLES .SH EXAMPLES
Viewing the entry database:
sshyp-mfa
Generating and copying an MFA key for an existing entry saved as ~/.local/share/sshyp-mfa/development/github.gpg Generating and copying an MFA key for an existing entry saved as ~/.local/share/sshyp-mfa/development/github.gpg
sshyp /development/github copy -m
sshyp-mfa /development/github sshyp-mfa /development/github
.SH SETUP .SH SETUP
+3
View File
@@ -0,0 +1,3 @@
[config]
input = copy -m
output = sshyp-mfa
+18 -25
View File
@@ -1,10 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from base64 import b32decode from base64 import b32decode
from os import environ, listdir, path, system, uname from os import environ, listdir, path, uname
from pathlib import Path from pathlib import Path
from sshync import get_profile from sshync import get_profile
from sshyp import decrypt, entry_list_gen, shm_gen, whitelist_verify from sshyp import decrypt, shm_gen, whitelist_verify
from subprocess import PIPE, Popen, run
from sys import argv, exit as s_exit from sys import argv, exit as s_exit
from time import sleep, strftime, time from time import sleep, strftime, time
@@ -20,16 +21,16 @@ def totp(_secret, _algo, _digits, _period): # uses provided information to gene
return str(_binary)[-_digits:].zfill(_digits) return str(_binary)[-_digits:].zfill(_digits)
def mfa_read_shortcut(): # reads and extracts MFA info from the user-specified sshyp entry def mfa_read_shortcut(): # extracts MFA info from the user-specified sshyp entry
from shutil import rmtree from shutil import rmtree
if not Path(f"{directory}{argument}.gpg").exists(): if not Path(f"{directory}{arguments[0]}.gpg").exists():
print(f"\n\u001b[38;5;9merror: entry ({argument}) does not exist\u001b[0m\n") print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) does not exist\u001b[0m\n")
s_exit(1) s_exit(1)
_shm_folder, _shm_entry = shm_gen() _shm_folder, _shm_entry = shm_gen()
if quick_unlock_enabled == 'y': if quick_unlock_enabled == 'y':
decrypt(directory + argument, _shm_folder, _shm_entry, gpg, whitelist_verify(port, username_ssh, ip, device_id)) decrypt(directory + arguments[0], _shm_folder, _shm_entry, whitelist_verify(port, username_ssh, ip, device_id))
else: else:
decrypt(directory + argument, _shm_folder, _shm_entry, gpg, False) decrypt(directory + arguments[0], _shm_folder, _shm_entry, False)
try: try:
_mfa_data = open(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}/{_shm_entry}", 'r').readlines() _mfa_data = open(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}/{_shm_entry}", 'r').readlines()
_type = _mfa_data[4].split('otpauth://')[1].split('/')[0] _type = _mfa_data[4].split('otpauth://')[1].split('/')[0]
@@ -40,16 +41,16 @@ def mfa_read_shortcut(): # reads and extracts MFA info from the user-specified
rmtree(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}") rmtree(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}")
return _type, _secret, _algo, _digits, _period return _type, _secret, _algo, _digits, _period
except IndexError: except IndexError:
print(f"\n\u001b[38;5;9merror: entry ({argument}) does not contain valid mfa data\u001b[0m\n") print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) does not contain valid mfa data\u001b[0m\n")
rmtree(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}") rmtree(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}")
s_exit(1) s_exit(1)
if __name__ == '__main__': if __name__ == '__main__':
# argument fetcher # argument fetcher
argument_list = argv arguments = argv[1:]
if not len(argv) == 1 and not argv[1].strip().startswith('/'): if len(arguments) < 1 or not arguments[0].startswith('/'):
print(f"\n\u001b[38;5;9merror: invalid argument - run 'man sshyp-mfa' for usage information\u001b[0m\n") print("\nsshyp-mfa extension usage: sshyp </entry name> copy -m\n\nrun 'man sshyp-mfa' for more information\n")
s_exit(1) s_exit(1)
# user data fetcher # user data fetcher
@@ -60,17 +61,9 @@ if __name__ == '__main__':
ip = str(ssh_info[1].rstrip()) ip = str(ssh_info[1].rstrip())
port = str(ssh_info[2].rstrip()) port = str(ssh_info[2].rstrip())
directory = str(ssh_info[3].rstrip()) directory = str(ssh_info[3].rstrip())
if uname()[0] == 'Haiku': # set proper gpg command for OS
gpg = 'gpg --pinentry-mode loopback'
else:
gpg = 'gpg'
# main process: runs functions to generate MFA key, then continuously copies up-to-date MFA key to clipboard # main process: runs functions to generate MFA key, then continuously copies up-to-date MFA key to clipboard
try: try:
if len(argument_list) == 1:
entry_list_gen()
argument_list.append(input('entry to read: '))
argument = ' '.join(argument_list[1:]).replace('/', '', 1)
mfa_data, copied = mfa_read_shortcut(), None mfa_data, copied = mfa_read_shortcut(), None
print('\nmfa key copied to clipboard\n\nuntil this process is closed, your clipboard will be automatically ' print('\nmfa key copied to clipboard\n\nuntil this process is closed, your clipboard will be automatically '
'updated with the newest mfa key') 'updated with the newest mfa key')
@@ -83,14 +76,14 @@ if __name__ == '__main__':
_mfa_key = steam_totp(b32decode(mfa_data[1])) _mfa_key = steam_totp(b32decode(mfa_data[1]))
else: else:
_mfa_key = totp(mfa_data[1], mfa_data[2], mfa_data[3], mfa_data[4]) _mfa_key = totp(mfa_data[1], mfa_data[2], mfa_data[3], mfa_data[4])
if uname()[0] == 'Haiku': # Haiku clipboard detection if 'WAYLAND_DISPLAY' in environ: # Wayland clipboard detection
system(f"clipboard -c '{_mfa_key}'") run(['wl-copy', _mfa_key])
elif uname()[0] == 'Haiku': # Haiku clipboard detection
run(['clipboard', '-c', _mfa_key])
elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection elif Path("/data/data/com.termux").exists(): # Termux (Android) clipboard detection
system(f"termux-clipboard-set '{_mfa_key}'") run(['termux-clipboard-set', _mfa_key])
elif environ.get('WAYLAND_DISPLAY') == 'wayland-0': # Wayland clipboard detection
system(f"wl-copy '{_mfa_key}'")
else: # X11 clipboard detection else: # X11 clipboard detection
system(f"echo -n '{_mfa_key}' | xclip -sel c") run(['xclip', '-sel', 'c'], stdin=Popen(['echo', '-n', _mfa_key], stdout=PIPE).stdout)
sleep(1) sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
print('\n') print('\n')
+4 -2
View File
@@ -52,7 +52,7 @@ _create_apkbuild() {
echo "# Maintainer: Randall Winkhart <idgr@tutanota.com> echo "# Maintainer: Randall Winkhart <idgr@tutanota.com>
pkgname=sshyp-mfa pkgname=sshyp-mfa
pkgver="$version" pkgver="$version"
pkgrel="$revision" pkgrel="$((revision-1))"
pkgdesc='An MFA (TOTP/Steam) key generator for the sshyp password manager' pkgdesc='An MFA (TOTP/Steam) key generator for the sshyp password manager'
options=!check options=!check
url='https://github.com/rwinkhart/sshyp-labs' url='https://github.com/rwinkhart/sshyp-labs'
@@ -67,7 +67,7 @@ package() {
} }
sha512sums=\" sha512sums=\"
"$sha512' 'sshyp-mfa\"\$pkgver\".tar.xz" "$sha512' 'sshyp-mfa-\"\$pkgver\".tar.xz"
\" \"
" > output/APKBUILD " > output/APKBUILD
echo -e "\nAPKBUILD generated\n" echo -e "\nAPKBUILD generated\n"
@@ -185,6 +185,7 @@ cp -r %{_sourcedir}/usr %{buildroot}
%files %files
/usr/bin/sshyp-mfa /usr/bin/sshyp-mfa
/usr/lib/sshyp/sshyp-mfa.py /usr/lib/sshyp/sshyp-mfa.py
/usr/lib/sshyp/extensions/sshyp-mfa
%license /usr/share/licenses/sshyp-mfa/license %license /usr/share/licenses/sshyp-mfa/license
%doc /usr/share/man/man1/sshyp-mfa.1.gz %doc /usr/share/man/man1/sshyp-mfa.1.gz
" > ~/rpmbuild/SPECS/sshyp-mfa.spec " > ~/rpmbuild/SPECS/sshyp-mfa.spec
@@ -215,6 +216,7 @@ prefix: /
" > output/freebsdtemp/+MANIFEST " > output/freebsdtemp/+MANIFEST
echo "/usr/bin/sshyp-mfa echo "/usr/bin/sshyp-mfa
/usr/lib/sshyp/sshyp-mfa.py /usr/lib/sshyp/sshyp-mfa.py
/usr/lib/sshyp/extensions/sshyp-mfa
/usr/share/licenses/sshyp-mfa/license /usr/share/licenses/sshyp-mfa/license
/usr/share/man/man1/sshyp-mfa.1.gz /usr/share/man/man1/sshyp-mfa.1.gz
" > output/freebsdtemp/plist " > output/freebsdtemp/plist
+1 -1
View File
@@ -1,5 +1,5 @@
sshyp-mfa is a FOSS extension for the sshyp password manager. sshyp-mfa is a FOSS extension for the sshyp password manager.
Copyright (C) 2022 Randall Winkhart idgr@tutanota.com Copyright (C) 2022-2023 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 version 3 (only) of the GNU General Public License it under the terms of version 3 (only) of the GNU General Public License
+1 -1
View File
@@ -1 +1 @@
1.2.0.1 1.4.0.1