From 7b3270d70f0e2e026d1039e19f181f85ccfe8127 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Fri, 12 May 2023 20:20:41 -0400 Subject: [PATCH] Modularized configuration options for use in a future options menu Former-commit-id: 45002b7ea5579407d47b14301b67dc0904f1121b Former-commit-id: 4859a01aec7f9d1a70e1d887c6e4ab9a1f955fb8 --- lib/sshyp.py | 4 +- lib/stweak.py | 199 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 123 insertions(+), 80 deletions(-) diff --git a/lib/sshyp.py b/lib/sshyp.py index c65e920..891f6fd 100755 --- a/lib/sshyp.py +++ b/lib/sshyp.py @@ -748,8 +748,8 @@ if __name__ == "__main__": print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n') s_exit(1) else: - import stweak - stweak.settings() + from stweak import initial_setup + initial_setup() s_exit() # run function based on arguments diff --git a/lib/stweak.py b/lib/stweak.py index b0d8d95..47e182e 100644 --- a/lib/stweak.py +++ b/lib/stweak.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from curses import curs_set, newwin, A_BOLD, A_REVERSE, KEY_UP, KEY_DOWN, noecho, nocbreak, endwin, initscr, cbreak +from curses import curs_set, newwin, A_REVERSE, KEY_UP, KEY_DOWN, noecho, nocbreak, endwin, initscr, cbreak from curses.textpad import rectangle, Textbox from os import environ, listdir, remove, symlink from pathlib import Path @@ -14,6 +14,7 @@ from os import uname from os.path import exists, expanduser, isfile # PORT END UNAME-IMPORT home = expanduser("~") +sshyp_data = [] # creates a radio selection between the provided options @@ -22,7 +23,7 @@ def settings_radio(_stdscr, _options, _pretext): _selected = 0 while True: _stdscr.clear() - _stdscr.addstr(0, 0, _pretext, A_BOLD) + _stdscr.addstr(0, 0, _pretext) for _i, _option in enumerate(_options): _y = _i + 2 if _i == _selected: @@ -58,7 +59,7 @@ def settings_text(_stdscr, _pretext): return _box.gather().strip() -# cleanly terminates curses +# cleanly exit curses def settings_terminate(_stdscr): nocbreak() _stdscr.keypad(False) # TODO Needed?? @@ -66,11 +67,103 @@ def settings_terminate(_stdscr): endwin() +# device+sync type selection +def install_type(_stdscr): + _offline_mode = False + # PORT START TWEAK-DEVTYPE + _install_type = settings_radio(_stdscr, ('server', 'client (ssh-synchronized)', 'client (offline)'), + 'device + sync type configuration') + if _install_type == 0: + _dev_type = 'server' + Path(f"{home}/.config/sshyp/deleted").mkdir(mode=0o700, exist_ok=True) + Path(f"{home}/.config/sshyp/whitelist").mkdir(mode=0o700, exist_ok=True) + settings_terminate(_stdscr) + print(f"\nmake sure the ssh service is running and properly configured") + else: + _dev_type = 'client' + if _install_type == 2: + _offline_mode = True + Path(f"{home}/.local/share/sshyp").mkdir(mode=0o700, parents=True, exist_ok=True) + # PORT END TWEAK-DEVTYPE + return _dev_type, _offline_mode + + +# gpg configuration +def gpg_config(_stdscr): + # gpg key selection + _uid_list = [_item for _item in run(['gpg', '-k', '--with-colons'], + stdout=PIPE, text=True).stdout.splitlines() if _item.startswith('uid')] + _clean_uid_list = [] + for _uid in _uid_list: + _clean_uid_list.append(sub(r':+', ':', _uid).split(':')[4]) + _clean_uid_list.append('auto-generate') + _gpg_id_sel = settings_radio(_stdscr, _clean_uid_list, 'gpg key selection') + _gpg_id = _clean_uid_list[_gpg_id_sel] + if _gpg_id == 'auto-generate': + print('\na unique gpg key is being generated for you...') + if not isfile(f"{home}/.config/sshyp/gpg-gen"): + open(f"{home}/.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\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n', + 'Expire-Date: 0']) + run(['gpg', '--batch', '--generate-key', f"{home}/.config/sshyp/gpg-gen"]) + remove(f"{home}/.config/sshyp/gpg-gen") + _gpg_id = run(['gpg', '-k'], stdout=PIPE, text=True).stdout.splitlines()[-3].strip() + return _gpg_id + + +# text editor configuration +def editor_config(_stdscr): + _editor = settings_text(_stdscr, 'enter the name of your preferred text editor:\n\n\n\n\n' + '(ctrl+g/enter to confirm)\n\nexample input: vim') + return _editor + + +# ssh+sshync configuration +def ssh_config(_stdscr): + # ssh+sshync configuration + _uiport = settings_text(_stdscr, 'enter the username, ip, and ssh port of your sshyp server:\n\n\n\n\n(' + 'ctrl+g/enter to confirm)\n\nexample inputs:\n\n ipv4: user@10.10.10.' + '10:22\n ipv6: user@[2000:2000:2000:2000:2000:2000:2000:2000]:22\n ' + 'domain: user@mydomain.com:22').lstrip('[').replace(']', '') + _uiport_split = _uiport.split('@') + _username_ssh = _uiport_split[0] + _iport = _uiport_split[1].rsplit(':', 1) + + # sshync profile generation + make_profile(f"{home}/.config/sshyp/sshyp.sshync", + f"{home}/.local/share/sshyp/", f"/home/{_username_ssh}/.local/share/sshyp/", + f"{home}/.ssh/sshyp", _iport[0], _iport[1], _username_ssh) + return _iport[1], _username_ssh, _iport[0] + + +# device id configuration +def dev_id_config(_stdscr): + for _id in listdir(f"{home}/.config/sshyp/devices"): + remove(f"{home}/.config/sshyp/devices/{_id}") + _device_id_prefix = settings_text(_stdscr, 'name this device:\n\n\n\n\n(ctrl+g/enter to confirm)\n\n' + 'important:\u001b[0m this id \u001b[4;1mmust\u001b[0m be ' + 'unique amongst your client devices\n\nthis is used to keep ' + 'track of database syncing and quick-unlock permissions\n') + _device_id_suffix = string_gen('f', randint(24, 48)) + _device_id = _device_id_prefix + '-' + _device_id_suffix + open(f"{home}/.config/sshyp/devices/{_device_id}", 'w') + return _device_id + + +# quick-unlock configuration +def quick_unlock_config(_stdscr): + _quick_unlock_sel = settings_radio(_stdscr, ('yes', 'no'), 'enable quick-unlock?') + if _quick_unlock_sel == 0: + _enabled = 'yes' + else: + _enabled = 'no' + return _enabled + + # ARGUMENT-SPECIFIC FUNCTIONS # runs configuration wizard -def settings(): - # set to avoid PEP8 warnings - _sshyp_data = None +def initial_setup(): # config directory creation Path(f"{home}/.config/sshyp/devices").mkdir(mode=0o700, parents=True, exist_ok=True) @@ -94,97 +187,46 @@ def settings(): # curses menu tree try: # device+sync type selection - # PORT START TWEAK-DEVTYPE - _install_type = settings_radio(_stdscr, ('server', 'client (ssh-synchronized)', 'client (offline)'), - 'device + sync type configuration') - if _install_type == 0: - _sshyp_data = ['server'] - Path(f"{home}/.config/sshyp/deleted").mkdir(mode=0o700, exist_ok=True) - Path(f"{home}/.config/sshyp/whitelist").mkdir(mode=0o700, exist_ok=True) - settings_terminate(_stdscr) - print(f"\nmake sure the ssh service is running and properly configured") - else: - _offline_mode = False - if _install_type == 2: - _offline_mode = True - _sshyp_data = ['client'] - Path(f"{home}/.local/share/sshyp").mkdir(mode=0o700, parents=True, exist_ok=True) - # PORT END TWEAK-DEVTYPE + _dev_sync_types = install_type(_stdscr) + sshyp_data.append(_dev_sync_types[0]) - # gpg key selection - _uid_list = [_item for _item in run(['gpg', '-k', '--with-colons'], - stdout=PIPE, text=True).stdout.splitlines() if _item.startswith('uid')] - _clean_uid_list = [] - for _uid in _uid_list: - _clean_uid_list.append(sub(r':+', ':', _uid).split(':')[4]) - _clean_uid_list.append('auto-generate') - _gpg_id_sel = settings_radio(_stdscr, _clean_uid_list, 'gpg key selection') - _gpg_id = _clean_uid_list[_gpg_id_sel] - if _gpg_id == 'auto-generate': - print('\na unique gpg key is being generated for you...') - if not isfile(f"{home}/.config/sshyp/gpg-gen"): - open(f"{home}/.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\n', 'Name-Email: https://github.com/rwinkhart/sshyp\n', - 'Expire-Date: 0']) - run(['gpg', '--batch', '--generate-key', f"{home}/.config/sshyp/gpg-gen"]) - remove(f"{home}/.config/sshyp/gpg-gen") - _sshyp_data.append(run(['gpg', '-k'], stdout=PIPE, text=True).stdout.splitlines()[-3].strip()) - else: - _sshyp_data.append(_gpg_id) + if _dev_sync_types[0] == 'client': - # text editor configuration - _sshyp_data.append(settings_text(_stdscr, 'enter the name of your preferred text editor:\n\n\n\n\n' - '(ctrl+g/enter to confirm)\n\nexample input: vim')) - # lock file generation + # gpg configuration + sshyp_data.append(gpg_config(_stdscr)) + + # lock file generation (requires gpg configuration) if isfile(f"{home}/.config/sshyp/lock.gpg"): remove(f"{home}/.config/sshyp/lock.gpg") open(f"{home}/.config/sshyp/lock", 'w') - run(['gpg', '-qr', str(_sshyp_data[1]), '-e', f"{home}/.config/sshyp/lock"]) + run(['gpg', '-qr', str(sshyp_data[1]), '-e', f"{home}/.config/sshyp/lock"]) remove(f"{home}/.config/sshyp/lock") - # ssh configuration - if not _offline_mode: - _uiport = settings_text(_stdscr, 'enter the username, ip, and ssh port of your sshyp server:\n\n\n\n\n(' - 'ctrl+g/enter to confirm)\n\nexample inputs:\n\n ipv4: user@10.10.10.' - '10:22\n ipv6: user@[2000:2000:2000:2000:2000:2000:2000:2000]:22\n ' - 'domain: user@mydomain.com:22').lstrip('[').replace(']', '') - _uiport_split = _uiport.split('@') - _username_ssh = _uiport_split[0] - _iport = _uiport_split[1].rsplit(':', 1) + # text editor configuration + sshyp_data.append(editor_config(_stdscr)) - # sshync profile generation - make_profile(f"{home}/.config/sshyp/sshyp.sshync", - f"{home}/.local/share/sshyp/", f"/home/{_username_ssh}/.local/share/sshyp/", - f"{home}/.ssh/sshyp", _iport[0], _iport[1], _username_ssh) + # online (synchronized mode) configuration + if not _dev_sync_types[1]: + + # ssh+sshync configuration + _ip, _username_ssh, _port = ssh_config(_stdscr) # device id configuration - # remove existing device id - for _id in listdir(f"{home}/.config/sshyp/devices"): - remove(f"{home}/.config/sshyp/devices/{_id}") - _device_id_prefix = settings_text(_stdscr, 'name this device:\n\n\n\n\n(ctrl+g/enter to confirm)\n\n' - 'important:\u001b[0m this id \u001b[4;1mmust\u001b[0m be ' - 'unique amongst your client devices\n\nthis is used to keep ' - 'track of database syncing and quick-unlock permissions\n') - _device_id_suffix = string_gen('f', randint(24, 48)) - _device_id = _device_id_prefix + '-' + _device_id_suffix - open(f"{home}/.config/sshyp/devices/{_device_id}", 'w') + _device_id = dev_id_config(_stdscr) # quick-unlock configuration - _quick_unlock_sel = settings_radio(_stdscr, ('yes', 'no'), 'enable quick-unlock?') - if _quick_unlock_sel == 0: - _sshyp_data.append('yes') - else: - _sshyp_data.append('no') + sshyp_data.append(quick_unlock_config(_stdscr)) + # cleanly exit curses settings_terminate(_stdscr) # test server connection and attempt to register device id - copy_id_check(_iport[1], _username_ssh, _iport[0], _device_id) + copy_id_check(_ip, _username_ssh, _port, _device_id) else: if isfile(f"{home}/.config/sshyp/sshyp.sshync"): remove(f"{home}/.config/sshyp/sshyp.sshync") + # cleanly exit curses settings_terminate(_stdscr) # PORT START CLIPTOOL @@ -201,12 +243,13 @@ def settings(): # PORT END CLIPTOOL except KeyboardInterrupt: + # cleanly exit curses settings_terminate(_stdscr) # write main config file (sshyp-data) with open(f"{home}/.config/sshyp/sshyp-data", 'w') as _config_file: _lines = 0 - for _item in _sshyp_data: + for _item in sshyp_data: _lines += 1 _config_file.write(str(_item) + '\n') while _lines < 4: