mirror of
https://github.com/rwinkhart/sshyp-labs.git
synced 2026-09-02 07:07:36 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7be5509fa7 | ||
|
|
8413c305c2 | ||
|
|
25a5731936 | ||
|
|
286645dd31 | ||
|
|
ec633c5104 |
@@ -9,11 +9,13 @@ For most sshyp-supported platforms, sshyp extensions should be installed from th
|
|||||||
For **Haiku and Termux _ONLY_**, use the packages from the [releases page](https://github.com/rwinkhart/sshyp-labs/releases).
|
For **Haiku and Termux _ONLY_**, use the packages from the [releases page](https://github.com/rwinkhart/sshyp-labs/releases).
|
||||||
|
|
||||||
# Available Extensions
|
# Available Extensions
|
||||||
[sshyp-mfa](https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa): read mfa data from sshyp entries to generate and copy totp keys to the clipboard (optional Steam support)
|
[sshyp-mfa](https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa): read mfa data from sshyp entries to generate and copy totp keys to the clipboard (includes Steam support)
|
||||||
|
|
||||||
[password-pasture](https://github.com/rwinkhart/sshyp-labs/wiki/password-pasture): a HIGHLY experimental GTK4 sshyp GUI - very incomplete (last updated for sshyp v1.1.x)
|
[password-pasture](https://github.com/rwinkhart/sshyp-labs/wiki/password-pasture): a HIGHLY experimental GTK4 sshyp GUI - very incomplete (last updated for sshyp v1.1.x)
|
||||||
|
|
||||||
# Acknowledgements
|
# Acknowledgements
|
||||||
sshyp-mfa optionally depends on [ValvePython/steam](https://github.com/ValvePython/steam) for Steam support.
|
|
||||||
|
|
||||||
sshyp-mfa's TOTP support is partially derrived from [susam/mintotp](https://github.com/susam/mintotp).
|
sshyp-mfa's TOTP support is partially derrived from [susam/mintotp](https://github.com/susam/mintotp).
|
||||||
|
|
||||||
|
sshyp-mfa's Steam support is partially derrived from [ValvePython/steam](https://github.com/ValvePython/steam).
|
||||||
|
|
||||||
|
These packages are _not_ required as dependencies; the necessary code from each is included in sshyp-mfa.
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from base64 import b32decode
|
from base64 import b32decode
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
from hmac import new as hmac_new
|
||||||
from os import environ, listdir, uname
|
from os import environ, listdir, uname
|
||||||
from os.path import expanduser, isdir, isfile
|
from os.path import expanduser, isdir, isfile
|
||||||
from sshyp import decrypt, whitelist_verify
|
from sshyp import decrypt, whitelist_verify
|
||||||
|
from struct import pack, unpack
|
||||||
from subprocess import PIPE, Popen, run
|
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
|
||||||
@@ -11,25 +13,37 @@ home = expanduser("~")
|
|||||||
|
|
||||||
|
|
||||||
def totp(_secret, _algo, _digits, _period): # uses provided information to generate a standard totp key
|
def totp(_secret, _algo, _digits, _period): # uses provided information to generate a standard totp key
|
||||||
from hmac import new as new_mac
|
|
||||||
from struct import pack, unpack
|
|
||||||
_secret = b32decode(_secret.upper() + '=' * ((8 - len(_secret)) % 8))
|
_secret = b32decode(_secret.upper() + '=' * ((8 - len(_secret)) % 8))
|
||||||
_counter = pack('>Q', int(time() / _period))
|
_counter = pack('>Q', int(time() / _period))
|
||||||
_mac = new_mac(_secret, _counter, _algo).digest()
|
_hmac = hmac_new(_secret, _counter, _algo).digest()
|
||||||
_offset = _mac[-1] & 0x0f
|
_offset = _hmac[-1] & 0x0f
|
||||||
_binary = unpack('>L', _mac[_offset:_offset + 4])[0] & 0x7fffffff
|
_binary = unpack('>L', _hmac[_offset:_offset + 4])[0] & 0x7fffffff
|
||||||
return str(_binary)[-_digits:].zfill(_digits)
|
return str(_binary)[-_digits:].zfill(_digits)
|
||||||
|
|
||||||
|
|
||||||
|
def steam_otp(_secret): # uses provided information to generate a Steam-compatible otp
|
||||||
|
_hmac = hmac_new(bytes(_secret), msg=pack('>Q', int(time()//30)), digestmod='sha1').digest()
|
||||||
|
_start = ord(_hmac[19:20]) & 0xF
|
||||||
|
_codeint = unpack('>I', _hmac[_start:_start+4])[0] & 0x7fffffff
|
||||||
|
_charset = '23456789BCDFGHJKMNPQRTVWXY'
|
||||||
|
_code = ''
|
||||||
|
for _ in range(5):
|
||||||
|
_codeint, _i = divmod(_codeint, len(_charset))
|
||||||
|
_code += _charset[_i]
|
||||||
|
return _code
|
||||||
|
|
||||||
|
|
||||||
def mfa_read_shortcut(): # extracts MFA info from the user-specified sshyp entry
|
def mfa_read_shortcut(): # extracts MFA info from the user-specified sshyp entry
|
||||||
if not isfile(f"{directory}{arguments[0]}.gpg"):
|
if not isfile(f"{directory}{arguments[0]}.gpg"):
|
||||||
print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) 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)
|
||||||
if quick_unlock_enabled == 'true':
|
if quick_unlock_enabled == 'true':
|
||||||
_mfa_data = decrypt(directory + arguments[0],
|
_mfa_data = decrypt(directory + arguments[0],
|
||||||
_quick_pass=whitelist_verify(sshyp_data.get('SSHYNC', 'port'),
|
_quick_pass=whitelist_verify(sshyp_data.get('SSHYNC', 'port'),
|
||||||
sshyp_data.get('SSHYNC', 'user'), sshyp_data.get('SSHYNC', 'ip'),
|
sshyp_data.get('SSHYNC', 'user'),
|
||||||
listdir(f"{home}/.config/sshyp/devices")[0]))
|
sshyp_data.get('SSHYNC', 'ip'),
|
||||||
|
listdir(f"{home}/.config/sshyp/devices")[0],
|
||||||
|
sshyp_data.get('SSHYNC', 'identity_file')))
|
||||||
else:
|
else:
|
||||||
_mfa_data = decrypt(directory + arguments[0])
|
_mfa_data = decrypt(directory + arguments[0])
|
||||||
try:
|
try:
|
||||||
@@ -67,18 +81,13 @@ if __name__ == '__main__':
|
|||||||
if copied is None:
|
if copied is None:
|
||||||
copied = 1
|
copied = 1
|
||||||
if mfa_data[0] == 'steam':
|
if mfa_data[0] == 'steam':
|
||||||
try:
|
_mfa_key = steam_otp(b32decode(mfa_data[1]))
|
||||||
from steam.guard import generate_twofactor_code as steam_totp
|
|
||||||
_mfa_key = steam_totp(b32decode(mfa_data[1]))
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
print('\n\u001b[38;5;9merror: steam module not found\n\ninstall with "pip install -U \'steam[client]\'"\u001b[0m\n')
|
|
||||||
s_exit(6)
|
|
||||||
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 'WSL_DISTRO_NAME' in environ: # WSL clipboard detection
|
if 'WSL_DISTRO_NAME' in environ: # WSL clipboard detection
|
||||||
run(('powershell.exe', '-c', 'Set-Clipboard', _mfa_key))
|
run(('powershell.exe', '-c', "Set-Clipboard '" + _mfa_key + "'"))
|
||||||
elif 'WAYLAND_DISPLAY' in environ: # Wayland clipboard detection
|
elif 'WAYLAND_DISPLAY' in environ: # Wayland clipboard detection
|
||||||
run(('wl-copy', _mfa_key))
|
run('wl-copy', stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
||||||
elif uname()[0] == 'Haiku': # Haiku clipboard detection
|
elif uname()[0] == 'Haiku': # Haiku clipboard detection
|
||||||
run(('clipboard', '-c', _mfa_key))
|
run(('clipboard', '-c', _mfa_key))
|
||||||
elif uname()[0] == 'Darwin': # MacOS clipboard detection
|
elif uname()[0] == 'Darwin': # MacOS clipboard detection
|
||||||
@@ -89,5 +98,4 @@ if __name__ == '__main__':
|
|||||||
run(('xclip', '-sel', 'c'), stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
run(('xclip', '-sel', 'c'), stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
||||||
sleep(1)
|
sleep(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print('\n')
|
|
||||||
s_exit(0)
|
s_exit(0)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[sshyp-mfa]
|
||||||
|
desc = read mfa data from sshyp entries to generate and copy totp keys to the clipboard (optional Steam support)
|
||||||
|
usage = sshyp /<entry name> copy -m
|
||||||
|
exe = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.1.1/extensions/sshyp-mfa/sshyp-mfa.py
|
||||||
|
ini = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.1.1/extensions/sshyp-mfa/sshyp-mfa.ini
|
||||||
Reference in New Issue
Block a user