mirror of
https://github.com/rwinkhart/sshyp-labs.git
synced 2026-08-28 04:46:48 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb1aca70bc | ||
|
|
80425bec2e | ||
|
|
d72c4a5c12 | ||
|
|
d339e4c734 | ||
|
|
240939178e | ||
|
|
b98122f4d8 | ||
|
|
7be5509fa7 | ||
|
|
8413c305c2 | ||
|
|
25a5731936 | ||
|
|
286645dd31 | ||
|
|
ec633c5104 | ||
|
|
9540e9874f | ||
|
|
0020ac313b | ||
|
|
ee8d875095 | ||
|
|
5d1eeb1f75 | ||
|
|
769f522b2a | ||
|
|
018912cfc5 | ||
|
|
d53fc304d5 | ||
|
|
adcb13fd89 | ||
|
|
2421bc2ff3 | ||
|
|
0a4efc2002 | ||
|
|
90884b4cd7 | ||
|
|
bc09ec5e30 | ||
|
|
e9a1728c6f | ||
|
|
08bc5dec87 | ||
|
|
23be7f8c30 | ||
|
|
0bbcda37f2 | ||
|
|
19ff50a5db | ||
|
|
ac035db597 | ||
|
|
fb267085eb | ||
|
|
90c3de83b5 | ||
|
|
a635207cee | ||
|
|
b9b06a4800 | ||
|
|
4e76b641a6 | ||
|
|
ed40b01e85 | ||
|
|
c8e54cef43 | ||
|
|
8fe7675ca3 | ||
|
|
45fd0631ca | ||
|
|
d4ed9b0da1 | ||
|
|
0953f60d0b | ||
|
|
580d511a50 |
@@ -0,0 +1 @@
|
||||
*
|
||||
@@ -1,22 +1,21 @@
|
||||
# sshyp-labs
|
||||
Experimental extensions for the sshyp password manager.
|
||||
Extensions for the [sshyp password manager](https://github.com/rwinkhart/sshyp).
|
||||
|
||||
sshyp-labs is currently the home of sshyp-mfa and password-pasture (sshyp-gui).
|
||||
When new functionality is desired that goes outside of sshyp's primary goals or requires venturing outside of the Python standard library, said functionality is implemented as an extension.
|
||||
|
||||
# Installation
|
||||
For most sshyp-supported platforms, sshyp extensions should be installed from the `sshyp tweak` menu's "extension management" option.
|
||||
|
||||
For **Haiku and Termux _ONLY_**, use the packages from the [releases page](https://github.com/rwinkhart/sshyp-labs/releases).
|
||||
|
||||
# Available Extensions
|
||||
sshyp-mfa - [installation and usage instructions](https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa)
|
||||
[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)
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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.
|
||||
[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
|
||||
sshyp-mfa relies 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 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.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
git add -f LICENSE README.md commit.sh extensions extra pointers .gitignore
|
||||
git commit -m "$1"
|
||||
git push
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/bin/sh
|
||||
|
||||
version='1.5.1.3'
|
||||
if [ -z "$2" ]; then
|
||||
revision=1
|
||||
else
|
||||
revision="$2"
|
||||
fi
|
||||
|
||||
_create_hpkg() {
|
||||
printf '\npackaging for Haiku...\n'
|
||||
mkdir -p output/haikutemp/lib/sshyp/extensions
|
||||
printf "name sshyp_mfa
|
||||
version "$version"-"$revision"
|
||||
architecture any
|
||||
summary \"An MFA (TOTP/Steam) key generator for the sshyp password manager\"
|
||||
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.\"
|
||||
packager \"Randall Winkhart <idgr at tutanota dot com>\"
|
||||
vendor \"Randall Winkhart\"
|
||||
licenses {
|
||||
\"GNU GPL v3\"
|
||||
}
|
||||
copyrights {
|
||||
\"2021-2023 Randall Winkhart\"
|
||||
}
|
||||
provides {
|
||||
sshyp_mfa = "$version"
|
||||
}
|
||||
requires {
|
||||
sshyp_client
|
||||
}
|
||||
urls {
|
||||
\"https://github.com/rwinkhart/sshyp-labs\"
|
||||
}
|
||||
" > output/haikutemp/.PackageInfo
|
||||
cp ./sshyp-mfa.py output/haikutemp/lib/sshyp/sshyp-mfa
|
||||
printf '[config]\ninput = copy -m\noutput = /system/lib/sshyp/sshyp-mfa\n' > ./output/haikutemp/lib/sshyp/extensions/sshyp-mfa.ini
|
||||
sed -i '1 s/.*/#!\/bin\/env\ python3.11/' output/haikutemp/lib/sshyp/sshyp-mfa
|
||||
cd output/haikutemp
|
||||
package create -b HAIKU-sshyp_mfa-"$version"-"$revision"_all.hpkg
|
||||
package add HAIKU-sshyp_mfa-"$version"-"$revision"_all.hpkg lib
|
||||
cd ../..
|
||||
mv output/haikutemp/HAIKU-sshyp_mfa-"$version"-"$revision"_all.hpkg output/
|
||||
rm -rf output/haikutemp
|
||||
printf "\nHaiku packaging complete\n\n"
|
||||
} &&
|
||||
|
||||
_create_termux() {
|
||||
printf '\npackaging for Termux...\n'
|
||||
mkdir -p output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/DEBIAN \
|
||||
output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/extensions
|
||||
printf "Package: sshyp-mfa
|
||||
Version: $version
|
||||
Section: utils
|
||||
Architecture: all
|
||||
Maintainer: Randall Winkhart <idgr at tutanota dot com>
|
||||
Description: An MFA (TOTP/Steam) key generator for the sshyp password manager
|
||||
Depends: sshyp-client
|
||||
Priority: optional
|
||||
Installed-Size: 100
|
||||
" > output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/DEBIAN/control
|
||||
cp ./sshyp-mfa.py output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/sshyp-mfa
|
||||
printf '[config]\ninput = copy -m\noutput = /data/data/com.termux/files/usr/lib/sshyp/sshyp-mfa\n' > ./output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/extensions/sshyp-mfa.ini
|
||||
dpkg-deb --build --root-owner-group output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/
|
||||
mv output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux.deb output/TERMUX-sshyp-mfa_"$version"-"$revision"_all.deb
|
||||
rm -rf output/termuxtemp
|
||||
printf '\nTermux packaging complete\n\n'
|
||||
} &&
|
||||
|
||||
case "$1" in
|
||||
haiku)
|
||||
_create_hpkg
|
||||
;;
|
||||
termux)
|
||||
_create_termux
|
||||
;;
|
||||
*)
|
||||
printf '\nusage: package.sh [target] <revision>\n\ntargets: haiku termux\n\n'
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,3 @@
|
||||
[config]
|
||||
input = copy -m
|
||||
output = /usr/lib/sshyp/sshyp-mfa
|
||||
Executable
+101
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
from base64 import b32decode
|
||||
from configparser import ConfigParser
|
||||
from hmac import new as hmac_new
|
||||
from os import environ, listdir, uname
|
||||
from os.path import expanduser, isdir, isfile
|
||||
from sshyp import decrypt, whitelist_verify
|
||||
from struct import pack, unpack
|
||||
from subprocess import PIPE, Popen, run
|
||||
from sys import argv, exit as s_exit
|
||||
from time import sleep, strftime, time
|
||||
home = expanduser("~")
|
||||
|
||||
|
||||
def totp(_secret, _algo, _digits, _period): # uses provided information to generate a standard totp key
|
||||
_secret = b32decode(_secret.upper() + '=' * ((8 - len(_secret)) % 8))
|
||||
_counter = pack('>Q', int(time() / _period))
|
||||
_hmac = hmac_new(_secret, _counter, _algo).digest()
|
||||
_offset = _hmac[-1] & 0x0f
|
||||
_binary = unpack('>L', _hmac[_offset:_offset + 4])[0] & 0x7fffffff
|
||||
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
|
||||
if not isfile(f"{directory}{arguments[0]}.gpg"):
|
||||
print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) does not exist\u001b[0m\n")
|
||||
s_exit(1)
|
||||
if quick_unlock_enabled:
|
||||
_mfa_data = decrypt(directory + arguments[0],
|
||||
_quick_pass=whitelist_verify(sshyp_data.get('SSHYNC', 'port'),
|
||||
sshyp_data.get('SSHYNC', 'user'),
|
||||
sshyp_data.get('SSHYNC', 'ip'),
|
||||
listdir(f"{home}/.config/sshyp/devices")[0],
|
||||
sshyp_data.get('SSHYNC', 'identity_file')))
|
||||
else:
|
||||
_mfa_data = decrypt(directory + arguments[0])
|
||||
try:
|
||||
_type = _mfa_data[4].split('otpauth://')[1].split('/')[0]
|
||||
_secret = _mfa_data[4].split('?secret=')[1].split('&issuer=')[0]
|
||||
_algo = _mfa_data[4].split('&algorithm=')[1].split('&digits=')[0]
|
||||
_digits = int(_mfa_data[4].split('&digits=')[1].split('&period=')[0])
|
||||
_period = int(_mfa_data[4].split('&period=')[1])
|
||||
return _type, _secret, _algo, _digits, _period
|
||||
except IndexError:
|
||||
print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) does not contain valid mfa data\u001b[0m\n")
|
||||
s_exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# argument fetcher
|
||||
arguments = argv[1:]
|
||||
if len(arguments) < 1 or not arguments[0].startswith('/'):
|
||||
print("\nsshyp-mfa extension usage: sshyp </entry name> copy -m\n\nrun 'man sshyp-mfa' for more information\n")
|
||||
s_exit(1)
|
||||
|
||||
# user data fetcher
|
||||
sshyp_data = ConfigParser()
|
||||
sshyp_data.read(f"{home}/.config/sshyp/sshyp.ini")
|
||||
directory = f"{home}/.local/share/sshyp/"
|
||||
quick_unlock_enabled = sshyp_data.getboolean('CLIENT-ONLINE', 'quick_unlock_enabled')
|
||||
|
||||
# main process: runs functions to generate MFA key, then continuously copies up-to-date MFA key to clipboard
|
||||
try:
|
||||
mfa_data, copied = mfa_read_shortcut(), None
|
||||
print('\nmfa key copied to clipboard\n\nuntil this process is closed, your clipboard will be automatically '
|
||||
'updated with the newest mfa key')
|
||||
while True:
|
||||
if str(int(strftime('%S'))/mfa_data[4]).endswith('.0') or copied is None:
|
||||
if copied is None:
|
||||
copied = 1
|
||||
if mfa_data[0] == 'steam':
|
||||
_mfa_key = steam_otp(b32decode(mfa_data[1]))
|
||||
else:
|
||||
_mfa_key = totp(mfa_data[1], mfa_data[2], mfa_data[3], mfa_data[4])
|
||||
if 'WSL_DISTRO_NAME' in environ: # WSL clipboard detection
|
||||
run(('powershell.exe', '-c', "Set-Clipboard '" + _mfa_key + "'"))
|
||||
elif 'WAYLAND_DISPLAY' in environ: # Wayland clipboard detection
|
||||
run('wl-copy', stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
||||
elif uname()[0] == 'Haiku': # Haiku clipboard detection
|
||||
run(('clipboard', '-c', _mfa_key))
|
||||
elif uname()[0] == 'Darwin': # MacOS clipboard detection
|
||||
run('pbcopy', stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
||||
elif isdir("/data/data/com.termux"): # Termux (Android) clipboard detection
|
||||
run(('termux-clipboard-set', _mfa_key))
|
||||
else: # X11 clipboard detection
|
||||
run(('xclip', '-sel', 'c'), stdin=Popen(('printf', _mfa_key), stdout=PIPE).stdout)
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
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.0.2/extensions/sshyp-mfa/sshyp-mfa.py
|
||||
ini = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.0.2/extensions/sshyp-mfa/sshyp-mfa.ini
|
||||
@@ -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.2/extensions/sshyp-mfa/sshyp-mfa.py
|
||||
ini = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.1.2/extensions/sshyp-mfa/sshyp-mfa.ini
|
||||
@@ -0,0 +1,5 @@
|
||||
[sshyp-mfa]
|
||||
desc = reads mfa/2fa secrets from sshyp entries to generate and copy totp/Steam otp keys to the clipboard
|
||||
usage = sshyp /<entry name> copy -m<br><br>to add mfa data to a sshyp entry, insert it into the SECOND notes line for a given entry using the following format:<br><br> otpauth://<OTP METHOD>/<ACCOUNT NAME, NOT USED>?secret=<SECRET>&issuer=<ISSUER, NOT USED>&algorithm=<ALGORITHM>&digits=<DIGITS>&period=<REFRESH PERIOD><br><br>what to put in each of the above spaces:<br><br> <OTP METHOD> is almost always 'totp', but in the case of Steam, it needs to be set to 'steam'.<br> <ACCOUNT NAME, NOT USED> is a part of the Authenticator backup format, but it is not used in sshyp-mfa. Set to anything.<br> <SECRET> refers to the secret used to generate your MFA key. This is usually directly provided by the issuer, but it is sometimes hidden and more easily retrieved by copying it from a QR-compatible MFA app (such as Aegis).<br> <ISSUER, NOT USED> is a part of the Authenticator backup format, but it is not used in sshyp-mfa. Set to anything.<br> <ALGORITHM> refers to the algorithm used to generate your MFA key based on your secret. This is almost always 'sha1'.<br> <DIGITS> refers to the intended length of your MFA key. This is almost always '6', but in the case of Steam, it needs to be set to '5'.<br> <REFRESH PERIOD> refers to the interval at which a new MFA key needs to be generated. This is almost always '30', for 30 seconds.<br><br>examples:<br><br> GitHub (standard 6-digit totp):<br> otpauth://totp/MyNameIsBob?secret=YUGBSG65SG9SDBSDF56SBFVSC86SBVD6&issuer=GitHub&algorithm=sha1&digits=6&period=30<br><br> Steam (5-character totp):<br> otpauth://steam/SteamUser?secret=VGVG34GH2GJHVCK7HGVS7&issuer=Steam&algorithm=sha1&digits=5&period=30<br><br>for more information, visit:<br><br> https://github.com/rwinkhart/sshyp-labs/wiki/sshyp-mfa
|
||||
exe = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.1.3/extensions/sshyp-mfa/sshyp-mfa.py
|
||||
ini = https://raw.githubusercontent.com/rwinkhart/sshyp-labs/v1.5.1.3/extensions/sshyp-mfa/sshyp-mfa.ini
|
||||
@@ -1,44 +0,0 @@
|
||||
.TH sshyp-mfa 1 "04 March 2023" "v1.4.0.1" "sshyp-mfa man page"
|
||||
.SH NAME
|
||||
sshyp-mfa \- An MFA (TOTP/Steam) key generator for the sshyp password manager.
|
||||
.SH SYNOPSIS
|
||||
Extension Usage: sshyp </entry name> copy -m
|
||||
|
||||
Direct Usage: sshyp-mfa </entry name>
|
||||
.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.
|
||||
.SH EXAMPLES
|
||||
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
|
||||
|
||||
.SH SETUP
|
||||
sshyp-mfa requires a pre-existing functional sshyp setup.
|
||||
|
||||
MFA keys are generated off of MFA data placed in the second line of a sshyp entry's notes field. This data needs to be added manually, through sshyp, and must be in Authenticator backup format.
|
||||
|
||||
It might be easiest to import all of your MFA keys into Authenticator, export them into plain text, then add all of the exported MFA data into the second notes line in their respective sshyp entries.
|
||||
.SH FORMAT
|
||||
Format: otpauth://<OTP METHOD>/<ACCOUNT NAME, NOT USED>?secret=<SECRET>&issuer=<ISSUER, NOT USED>&algorithm=<ALGORITHM>&digits=<DIGITS>&period=<REFRESH PERIOD>
|
||||
|
||||
Help! What do I put in each of those spaces?
|
||||
|
||||
<OTP METHOD> is almost always 'totp', but in the case of Steam, it needs to be set to 'steam'.
|
||||
|
||||
<ACCOUNT NAME, NOT USED> is a part of the Authenticator backup format, but it is not used in sshyp-mfa. Set to anything.
|
||||
|
||||
<SECRET> refers to the secret used to generate your MFA key. This is usually directly provided by the issuer, but it is sometimes hidden and more easily retrieved by copying it from a QR-compatible MFA app (such as Aegis).
|
||||
|
||||
<ISSUER, NOT USED> is a part of the Authenticator backup format, but it is not used in sshyp-mfa. Set to anything.
|
||||
|
||||
<ALGORITHM> refers to the algorithm used to generate your MFA key based on your secret. This is almost always 'sha1'.
|
||||
|
||||
<DIGITS> refers to the intended length of your MFA key. This is almost always '6', but in the case of Steam, it needs to be set to '5'.
|
||||
|
||||
<REFRESH PERIOD> refers to the interval at which a new MFA key needs to be generated. This is almost always '30', for 30 seconds.
|
||||
|
||||
Example configuration (for most services, see above for differences regarding Steam):
|
||||
|
||||
otpauth://totp/MyNameIsBob?secret=YUGBSG65SG9SDBSDF56SBFVSC86SBVD6&issuer=Github&algorithm=sha1&digits=6&period=30
|
||||
.SH AUTHOR
|
||||
Randall Winkhart (https://github.com/rwinkhart)
|
||||
@@ -1,3 +0,0 @@
|
||||
[config]
|
||||
input = copy -m
|
||||
output = sshyp-mfa
|
||||
@@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from base64 import b32decode
|
||||
from os import environ, listdir, path, uname
|
||||
from pathlib import Path
|
||||
from sshync import get_profile
|
||||
from sshyp import decrypt, shm_gen, whitelist_verify
|
||||
from subprocess import PIPE, Popen, run
|
||||
from sys import argv, exit as s_exit
|
||||
from time import sleep, strftime, time
|
||||
|
||||
|
||||
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))
|
||||
_counter = pack('>Q', int(time() / _period))
|
||||
_mac = new_mac(_secret, _counter, _algo).digest()
|
||||
_offset = _mac[-1] & 0x0f
|
||||
_binary = unpack('>L', _mac[_offset:_offset + 4])[0] & 0x7fffffff
|
||||
return str(_binary)[-_digits:].zfill(_digits)
|
||||
|
||||
|
||||
def mfa_read_shortcut(): # extracts MFA info from the user-specified sshyp entry
|
||||
from shutil import rmtree
|
||||
if not Path(f"{directory}{arguments[0]}.gpg").exists():
|
||||
print(f"\n\u001b[38;5;9merror: entry ({arguments[0]}) does not exist\u001b[0m\n")
|
||||
s_exit(1)
|
||||
_shm_folder, _shm_entry = shm_gen()
|
||||
if quick_unlock_enabled == 'y':
|
||||
decrypt(directory + arguments[0], _shm_folder, _shm_entry, whitelist_verify(port, username_ssh, ip, device_id))
|
||||
else:
|
||||
decrypt(directory + arguments[0], _shm_folder, _shm_entry, False)
|
||||
try:
|
||||
_mfa_data = open(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}/{_shm_entry}", 'r').readlines()
|
||||
_type = _mfa_data[4].split('otpauth://')[1].split('/')[0]
|
||||
_secret = _mfa_data[4].split('?secret=')[1].split('&issuer=')[0]
|
||||
_algo = _mfa_data[4].split('&algorithm=')[1].split('&digits=')[0]
|
||||
_digits = int(_mfa_data[4].split('&digits=')[1].split('&period=')[0])
|
||||
_period = int(_mfa_data[4].split('&period=')[1])
|
||||
rmtree(f"{path.expanduser('~/.config/sshyp/tmp/')}{_shm_folder}")
|
||||
return _type, _secret, _algo, _digits, _period
|
||||
except IndexError:
|
||||
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}")
|
||||
s_exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# argument fetcher
|
||||
arguments = argv[1:]
|
||||
if len(arguments) < 1 or not arguments[0].startswith('/'):
|
||||
print("\nsshyp-mfa extension usage: sshyp </entry name> copy -m\n\nrun 'man sshyp-mfa' for more information\n")
|
||||
s_exit(1)
|
||||
|
||||
# user data fetcher
|
||||
device_id = listdir(path.expanduser('~/.config/sshyp/devices'))[0]
|
||||
quick_unlock_enabled = open(path.expanduser('~/.config/sshyp/sshyp-data')).readlines()[3].rstrip()
|
||||
ssh_info = get_profile(path.expanduser('~/.config/sshyp/sshyp.sshync'))
|
||||
username_ssh = str(ssh_info[0].rstrip())
|
||||
ip = str(ssh_info[1].rstrip())
|
||||
port = str(ssh_info[2].rstrip())
|
||||
directory = str(ssh_info[3].rstrip())
|
||||
|
||||
# main process: runs functions to generate MFA key, then continuously copies up-to-date MFA key to clipboard
|
||||
try:
|
||||
mfa_data, copied = mfa_read_shortcut(), None
|
||||
print('\nmfa key copied to clipboard\n\nuntil this process is closed, your clipboard will be automatically '
|
||||
'updated with the newest mfa key')
|
||||
while True:
|
||||
if str(int(strftime('%S'))/mfa_data[4]).endswith('.0') or copied is None:
|
||||
if copied is None:
|
||||
copied = 1
|
||||
if mfa_data[0] == 'steam':
|
||||
from steam.guard import generate_twofactor_code as steam_totp
|
||||
_mfa_key = steam_totp(b32decode(mfa_data[1]))
|
||||
else:
|
||||
_mfa_key = totp(mfa_data[1], mfa_data[2], mfa_data[3], mfa_data[4])
|
||||
if 'WAYLAND_DISPLAY' in environ: # Wayland clipboard detection
|
||||
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
|
||||
run(['termux-clipboard-set', _mfa_key])
|
||||
else: # X11 clipboard detection
|
||||
run(['xclip', '-sel', 'c'], stdin=Popen(['echo', '-n', _mfa_key], stdout=PIPE).stdout)
|
||||
sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
print('\n')
|
||||
s_exit(0)
|
||||
@@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
version=$(sed -n '1{p;q}' ../version)
|
||||
if [ -z "$2" ]; then
|
||||
revision=1
|
||||
else
|
||||
revision="$2"
|
||||
fi
|
||||
|
||||
_create_generic() {
|
||||
echo -e '\npackaging as generic...\n'
|
||||
mkdir -p output/generictemp/usr/{bin,lib/sshyp,share/man/man1}
|
||||
cp -r lib/. output/generictemp/usr/lib/sshyp/
|
||||
ln -s /usr/lib/sshyp/sshyp-mfa.py output/generictemp/usr/bin/sshyp-mfa
|
||||
cp -r share output/generictemp/usr/
|
||||
cp extra/manpage output/generictemp/usr/share/man/man1/sshyp-mfa.1
|
||||
gzip output/generictemp/usr/share/man/man1/sshyp-mfa.1
|
||||
tar -C output/generictemp -cvJf output/sshyp-mfa-"$version".tar.xz usr/
|
||||
rm -rf output/generictemp
|
||||
sha512="$(sha512sum output/sshyp-mfa-"$version".tar.xz | awk '{print $1;}')"
|
||||
echo -e "\nsha512 sum:\n$sha512"
|
||||
echo -e "\ngeneric packaging complete\n"
|
||||
} &&
|
||||
|
||||
_create_pkgbuild() {
|
||||
source='https://github.com/rwinkhart/sshyp-labs/releases/download/v$pkgver/sshyp-mfa-$pkgver.tar.xz'
|
||||
echo -e '\ngenerating PKGBUILD...'
|
||||
echo "# Maintainer: Randall Winkhart <idgr at tutanota dot com>
|
||||
pkgname=sshyp-mfa
|
||||
pkgver="$version"
|
||||
pkgrel="$revision"
|
||||
pkgdesc='An MFA (TOTP/Steam) key generator for the sshyp password manager'
|
||||
url='https://github.com/rwinkhart/sshyp-labs'
|
||||
arch=('any')
|
||||
license=('GPL-3.0-only')
|
||||
depends=(sshyp)
|
||||
source=(\""$source"\")
|
||||
sha512sums=('"$sha512"')
|
||||
|
||||
package() {
|
||||
|
||||
tar xf sshyp-mfa-"\"\$pkgver\"".tar.xz -C "\"\${pkgdir}\""
|
||||
|
||||
}
|
||||
" > output/PKGBUILD
|
||||
echo -e "\nPKGBUILD generated\n"
|
||||
} &&
|
||||
|
||||
_create_apkbuild() {
|
||||
source='https://github.com/rwinkhart/sshyp-labs/releases/download/v$pkgver/sshyp-mfa-$pkgver.tar.xz'
|
||||
echo -e '\ngenerating APKBUILD...'
|
||||
echo "# Maintainer: Randall Winkhart <idgr@tutanota.com>
|
||||
pkgname=sshyp-mfa
|
||||
pkgver="$version"
|
||||
pkgrel="$((revision-1))"
|
||||
pkgdesc='An MFA (TOTP/Steam) key generator for the sshyp password manager'
|
||||
options=!check
|
||||
url='https://github.com/rwinkhart/sshyp-labs'
|
||||
arch='noarch'
|
||||
license='GPL-3.0-only'
|
||||
depends='sshyp'
|
||||
source=\""$source"\"
|
||||
|
||||
package() {
|
||||
mkdir -p "\"\$pkgdir\""
|
||||
cp -r "\"\$srcdir/usr/"\" "\"\$pkgdir\""
|
||||
}
|
||||
|
||||
sha512sums=\"
|
||||
"$sha512' 'sshyp-mfa-\"\$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/{man/man1,packages/sshyp-mfa}}
|
||||
echo "name sshypmfa
|
||||
version "$version"-"$revision"
|
||||
architecture any
|
||||
summary \"An MFA (TOTP/Steam) key generator for the sshyp password manager\"
|
||||
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.\"
|
||||
packager \"Randall Winkhart <idgr at tutanota dot com>\"
|
||||
vendor \"Randall Winkhart\"
|
||||
licenses {
|
||||
\"GNU GPL v3\"
|
||||
}
|
||||
copyrights {
|
||||
\"2021-2022 Randall Winkhart\"
|
||||
}
|
||||
provides {
|
||||
sshypmfa = "$version"
|
||||
cmd:sshypmfa
|
||||
}
|
||||
requires {
|
||||
sshyp
|
||||
}
|
||||
urls {
|
||||
\"https://github.com/rwinkhart/sshyp-labs\"
|
||||
}
|
||||
" > output/haikutemp/.PackageInfo
|
||||
cp -r lib/. output/haikutemp/lib/sshyp/
|
||||
sed -i '1 s/.*/#!\/bin\/env\ python3.10/' output/haikutemp/lib/sshyp/sshyp-mfa.py
|
||||
ln -s /system/lib/sshyp/sshyp-mfa.py output/haikutemp/bin/sshyp-mfa
|
||||
cp -r share/licenses/sshyp-mfa/. output/haikutemp/documentation/packages/sshyp-mfa/
|
||||
cp extra/manpage output/haikutemp/documentation/man/man1/sshyp-mfa.1
|
||||
gzip output/haikutemp/documentation/man/man1/sshyp-mfa.1
|
||||
cd output/haikutemp
|
||||
package create -b sshyp-mfa-"$version"-"$revision"_all.hpkg
|
||||
package add sshyp-mfa-"$version"-"$revision"_all.hpkg bin lib documentation
|
||||
cd ../..
|
||||
mv output/haikutemp/sshyp-mfa-"$version"-"$revision"_all.hpkg output/
|
||||
rm -rf output/haikutemp
|
||||
echo -e "\nHaiku packaging complete\n"
|
||||
} &&
|
||||
|
||||
_create_deb() {
|
||||
echo -e '\npackaging for Debian/Ubuntu...\n'
|
||||
mkdir -p output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/{DEBIAN,usr/{lib/sshyp,bin,share/man/man1}}
|
||||
echo "Package: sshyp-mfa
|
||||
Version: $version
|
||||
Section: utils
|
||||
Architecture: all
|
||||
Maintainer: Randall Winkhart <idgr at tutanota dot com>
|
||||
Description: An MFA (TOTP/Steam) key generator for the sshyp password manager
|
||||
Depends: sshyp
|
||||
Priority: optional
|
||||
Installed-Size: 100
|
||||
" > output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/DEBIAN/control
|
||||
cp -r lib/. output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/usr/lib/sshyp/
|
||||
ln -s /usr/lib/sshyp/sshyp-mfa.py output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/usr/bin/sshyp-mfa
|
||||
cp -r share output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/usr/
|
||||
cp extra/manpage output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/usr/share/man/man1/sshyp-mfa.1
|
||||
gzip output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/usr/share/man/man1/sshyp-mfa.1
|
||||
dpkg-deb --build --root-owner-group output/debiantemp/sshyp-mfa_"$version"-"$revision"_all/
|
||||
mv output/debiantemp/sshyp-mfa_"$version"-"$revision"_all.deb output/
|
||||
rm -rf output/debiantemp
|
||||
echo -e "\nDebian/Ubuntu packaging complete\n"
|
||||
} &&
|
||||
|
||||
_create_termux() {
|
||||
echo -e '\npackaging for Termux...\n'
|
||||
mkdir -p output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/{DEBIAN,data/data/com.termux/files/usr/{lib/sshyp,bin,share/man/man1}}
|
||||
echo "Package: sshyp-mfa
|
||||
Version: $version
|
||||
Section: utils
|
||||
Architecture: all
|
||||
Maintainer: Randall Winkhart <idgr at tutanota dot com>
|
||||
Description: An MFA (TOTP/Steam) key generator for the sshyp password manager
|
||||
Depends: sshyp
|
||||
Priority: optional
|
||||
Installed-Size: 100
|
||||
" > output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/DEBIAN/control
|
||||
cp -r lib/. output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/lib/sshyp/
|
||||
ln -s /data/data/com.termux/files/usr/lib/sshyp/sshyp-mfa.py output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/bin/sshyp-mfa
|
||||
cp -r share output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/
|
||||
cp extra/manpage output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp-mfa.1
|
||||
gzip output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/data/data/com.termux/files/usr/share/man/man1/sshyp-mfa.1
|
||||
dpkg-deb --build --root-owner-group output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux/
|
||||
mv output/termuxtemp/sshyp-mfa_"$version"-"$revision"_all_termux.deb output/
|
||||
rm -rf output/termuxtemp
|
||||
echo -e "\nTermux packaging complete\n"
|
||||
} &&
|
||||
|
||||
_create_rpm() {
|
||||
echo -e '\npackaging for Fedora...\n'
|
||||
rm -rf ~/rpmbuild
|
||||
rpmdev-setuptree
|
||||
cp output/sshyp-mfa-"$version".tar.xz ~/rpmbuild/SOURCES
|
||||
echo "Name: sshyp-mfa
|
||||
Version: "$version"
|
||||
Release: "$revision"
|
||||
Summary: An MFA (TOTP/Steam) key generator for the sshyp password manager
|
||||
BuildArch: noarch
|
||||
License: GPL-3.0-only
|
||||
URL: https://github.com/rwinkhart/sshyp-labs
|
||||
Source0: sshyp-mfa-"$version".tar.xz
|
||||
Requires: sshyp
|
||||
%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.
|
||||
%install
|
||||
tar xf %{_sourcedir}/sshyp-mfa-"$version".tar.xz -C %{_sourcedir}
|
||||
cp -r %{_sourcedir}/usr %{buildroot}
|
||||
%files
|
||||
/usr/bin/sshyp-mfa
|
||||
/usr/lib/sshyp/sshyp-mfa.py
|
||||
/usr/lib/sshyp/extensions/sshyp-mfa
|
||||
%license /usr/share/licenses/sshyp-mfa/license
|
||||
%doc /usr/share/man/man1/sshyp-mfa.1.gz
|
||||
" > ~/rpmbuild/SPECS/sshyp-mfa.spec
|
||||
rpmbuild -bb ~/rpmbuild/SPECS/sshyp-mfa.spec
|
||||
mv ~/rpmbuild/RPMS/noarch/* output/
|
||||
rm -rf ~/rpmbuild
|
||||
echo -e "\nFedora packaging complete\n"
|
||||
} &&
|
||||
|
||||
_create_freebsd_pkg() {
|
||||
echo -e '\npackaging for FreeBSD...\n'
|
||||
mkdir -p output/freebsdtemp/usr/{lib/sshyp,bin,share/man/man1}
|
||||
echo "name: sshyp-mfa
|
||||
version: \""$version"\"
|
||||
abi = \"FreeBSD:13:*\";
|
||||
arch = \"freebsd:13:*\";
|
||||
origin: security/sshyp-mfa
|
||||
comment: \"a sshyp extension\"
|
||||
desc: \"an MFA (TOTP/Steam) key generator for the sshyp password manager\"
|
||||
maintainer: <idgr at tutanota dot com>
|
||||
www: https://github.com/rwinkhart/sshyp-labs
|
||||
prefix: /
|
||||
\"deps\" : {
|
||||
\"sshyp\" : {
|
||||
\"origin\" : \"security/sshyp\"
|
||||
},
|
||||
},
|
||||
" > output/freebsdtemp/+MANIFEST
|
||||
echo "/usr/bin/sshyp-mfa
|
||||
/usr/lib/sshyp/sshyp-mfa.py
|
||||
/usr/lib/sshyp/extensions/sshyp-mfa
|
||||
/usr/share/licenses/sshyp-mfa/license
|
||||
/usr/share/man/man1/sshyp-mfa.1.gz
|
||||
" > output/freebsdtemp/plist
|
||||
cp -r lib/. output/freebsdtemp/usr/lib/sshyp/
|
||||
ln -s /usr/lib/sshyp/sshyp-mfa.py output/freebsdtemp/usr/bin/sshyp-mfa
|
||||
cp -r share output/freebsdtemp/usr/
|
||||
cp extra/manpage output/freebsdtemp/usr/share/man/man1/sshyp-mfa.1
|
||||
gzip output/freebsdtemp/usr/share/man/man1/sshyp-mfa.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 [ "$1" == "generic" ]; then # build scripts
|
||||
_create_generic
|
||||
elif [ "$1" == "pkgbuild" ]; then
|
||||
_create_generic
|
||||
_create_pkgbuild
|
||||
elif [ "$1" == "apkbuild" ]; then
|
||||
_create_generic
|
||||
_create_apkbuild
|
||||
elif [ "$1" == "haiku" ]; then # distribution packages
|
||||
_create_hpkg
|
||||
elif [ "$1" == "debian" ]; then
|
||||
_create_deb
|
||||
elif [ "$1" == "termux" ]; then
|
||||
_create_termux
|
||||
elif [ "$1" == "fedora" ]; then
|
||||
_create_generic
|
||||
_create_rpm
|
||||
elif [ "$1" == "freebsd" ]; then
|
||||
_create_freebsd_pkg
|
||||
elif [ "$1" == "buildable-arch" ]; then
|
||||
_create_generic
|
||||
_create_pkgbuild
|
||||
_create_apkbuild
|
||||
if [[ $(pacman -Q dpkg) == "dpkg"* ]]; then
|
||||
_create_deb
|
||||
_create_termux
|
||||
fi
|
||||
if [[ "$(pacman -Q freebsd-pkg)" == "freebsd-pkg"* ]]; then
|
||||
_create_freebsd_pkg
|
||||
fi
|
||||
else
|
||||
echo -e '\nusage: package.sh [target] <revision>\n\ntargets:\n mainline: pkgbuild apkbuild haiku fedora debian\n experimental: freebsd termux\n other: buildable-arch\n'
|
||||
fi
|
||||
@@ -1 +0,0 @@
|
||||
steam[client]
|
||||
@@ -1,14 +0,0 @@
|
||||
sshyp-mfa is a FOSS extension for the sshyp password manager.
|
||||
Copyright (C) 2022-2023 Randall Winkhart idgr@tutanota.com
|
||||
|
||||
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
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
Reference in New Issue
Block a user