mirror of
https://github.com/rwinkhart/sshyp-labs.git
synced 2026-09-02 15:17:35 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da6b1658a4 | ||
|
|
5df741726f | ||
|
|
ea020c4bf1 | ||
|
|
3568601520 | ||
|
|
e9ee114452 | ||
|
|
8c1a3c340c | ||
|
|
0ad86a1040 | ||
|
|
931d7a0494 | ||
|
|
f0eb398f07 | ||
|
|
1216d06975 | ||
|
|
8e45b15fee | ||
|
|
6ee49d6b95 | ||
|
|
7b03cfdc5e |
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[config]
|
||||||
|
input = copy -m
|
||||||
|
output = sshyp-mfa
|
||||||
+18
-25
@@ -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')
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
Reference in New Issue
Block a user