|
|
@ -2,6 +2,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
#TODO: |
|
|
|
#TODO: |
|
|
|
# - resolve exploit where key is plugged in and out quickly, resulting in an unlocked state |
|
|
|
# - resolve exploit where key is plugged in and out quickly, resulting in an unlocked state |
|
|
|
|
|
|
|
# - Add async scheduler that runs update_lock_state() every 1 minute or so |
|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
|
import os |
|
|
|
import sys |
|
|
|
import sys |
|
|
@ -37,10 +38,10 @@ def setup_logger(logfile): |
|
|
|
def execute(command: str, shell_on: bool = False, background: bool = False): |
|
|
|
def execute(command: str, shell_on: bool = False, background: bool = False): |
|
|
|
if background : |
|
|
|
if background : |
|
|
|
subprocess.run(command, shell=shell_on, |
|
|
|
subprocess.run(command, shell=shell_on, |
|
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False) |
|
|
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False) |
|
|
|
return |
|
|
|
return |
|
|
|
process = subprocess.Popen(command, shell=shell_on, stdout=subprocess.PIPE, |
|
|
|
process = subprocess.Popen(command, shell=shell_on, stdout=subprocess.PIPE, |
|
|
|
stderr=subprocess.PIPE) #Carefull with variables: shellcode injection |
|
|
|
stderr=subprocess.PIPE) #Carefull with variables: shellcode injection |
|
|
|
out, err = process.communicate() |
|
|
|
out, err = process.communicate() |
|
|
|
if out != b'' : |
|
|
|
if out != b'' : |
|
|
|
logger.info(out.decode('utf-8').rstrip()) |
|
|
|
logger.info(out.decode('utf-8').rstrip()) |
|
|
@ -48,6 +49,12 @@ def execute(command: str, shell_on: bool = False, background: bool = False): |
|
|
|
logger.error(err.decode('utf-8').rstrip()) |
|
|
|
logger.error(err.decode('utf-8').rstrip()) |
|
|
|
return '' if out == b'' else out.decode('utf-8') |
|
|
|
return '' if out == b'' else out.decode('utf-8') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def screensaver_running(): |
|
|
|
|
|
|
|
graphic_program_instances = execute(f"{script_dir}/kill_screensaver_graphic_program.sh -d | grep graphic_processes | wc -l", shell_on=True) |
|
|
|
|
|
|
|
if int(graphic_program_instances) > 0: |
|
|
|
|
|
|
|
return True |
|
|
|
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
def lock_screen(): |
|
|
|
def lock_screen(): |
|
|
|
if args.dummy : |
|
|
|
if args.dummy : |
|
|
|
return |
|
|
|
return |
|
|
@ -59,9 +66,10 @@ def lock_screen(): |
|
|
|
def unlock_screen(): |
|
|
|
def unlock_screen(): |
|
|
|
if args.dummy : |
|
|
|
if args.dummy : |
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
logger.info('xscreen process to be killed:') |
|
|
|
logger.info('xscreen process to be killed:') |
|
|
|
xscreensaver_pid = execute(r'ps -A | grep -oPm 1 "\d{2,}(?=\s.+xscreensaver)" || echo null', |
|
|
|
xscreensaver_pid = execute(r'ps -A | grep -oPm 1 "\d{2,}(?=\s.+xscreensaver)" || echo null', |
|
|
|
shell_on=True) |
|
|
|
shell_on=True) |
|
|
|
|
|
|
|
|
|
|
|
if xscreensaver_pid != 'null': |
|
|
|
if xscreensaver_pid != 'null': |
|
|
|
execute('kill %s' % xscreensaver_pid, shell_on=True) |
|
|
|
execute('kill %s' % xscreensaver_pid, shell_on=True) |
|
|
@ -83,22 +91,30 @@ def get_yubikey_serials() -> int: |
|
|
|
except yubico.yubikey.YubiKeyError: |
|
|
|
except yubico.yubikey.YubiKeyError: |
|
|
|
pass |
|
|
|
pass |
|
|
|
except USBError as error: |
|
|
|
except USBError as error: |
|
|
|
logger.error('get_yubikey_serials() threw: %s', str(error)) |
|
|
|
logger.info('get_yubikey_serials() threw: %s', str(error)) |
|
|
|
|
|
|
|
|
|
|
|
if not serials: |
|
|
|
if not serials: |
|
|
|
logger.info('no yubikey connected') |
|
|
|
logger.info('no yubikey connected') |
|
|
|
|
|
|
|
|
|
|
|
return serials |
|
|
|
return serials |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_lock_state(): |
|
|
|
|
|
|
|
if any(serial in yubikey_serials for serial in get_yubikey_serials()): |
|
|
|
|
|
|
|
if screensaver_running(): |
|
|
|
|
|
|
|
logger.debug('screen will be unlocked') |
|
|
|
|
|
|
|
unlock_screen() |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
if not screensaver_running(): |
|
|
|
|
|
|
|
logger.debug('screen will be locked') |
|
|
|
|
|
|
|
lock_screen() |
|
|
|
|
|
|
|
|
|
|
|
def device_added(device, last_yubikey_time): |
|
|
|
def device_added(device, last_yubikey_time): |
|
|
|
logger.debug('device connected: %s', device.sys_name) |
|
|
|
logger.debug('device connected: %s', device.sys_name) |
|
|
|
if (datetime.now() - last_yubikey_time).total_seconds() > 0.3 : |
|
|
|
if (datetime.now() - last_yubikey_time).total_seconds() > 0.3 : |
|
|
|
# This is not nice, yubikey call can cause key to reconnect. |
|
|
|
# This is not nice, yubikey call can cause key to reconnect. |
|
|
|
# This cooldown prevents endless reconnect loops |
|
|
|
# This cooldown prevents endless reconnect loops |
|
|
|
|
|
|
|
|
|
|
|
if any(serial in yubikey_serials for serial in get_yubikey_serials()): |
|
|
|
update_lock_state() |
|
|
|
logger.debug('screen will be unlocked') |
|
|
|
|
|
|
|
unlock_screen() |
|
|
|
|
|
|
|
return datetime.now() |
|
|
|
return datetime.now() |
|
|
|
return last_yubikey_time |
|
|
|
return last_yubikey_time |
|
|
|
|
|
|
|
|
|
|
@ -108,22 +124,22 @@ def device_removed(device: pyudev.Device, last_yubikey_time): |
|
|
|
# This is not nice, yubikey call can cause key to reconnect. |
|
|
|
# This is not nice, yubikey call can cause key to reconnect. |
|
|
|
# This cooldown prevents endless reconnect loops |
|
|
|
# This cooldown prevents endless reconnect loops |
|
|
|
|
|
|
|
|
|
|
|
if not any(serial in yubikey_serials for serial in get_yubikey_serials()): |
|
|
|
update_lock_state() |
|
|
|
logger.debug('screen will be locked') |
|
|
|
|
|
|
|
lock_screen() |
|
|
|
|
|
|
|
return datetime.now() |
|
|
|
return datetime.now() |
|
|
|
return last_yubikey_time |
|
|
|
return last_yubikey_time |
|
|
|
|
|
|
|
|
|
|
|
def get_args(): |
|
|
|
def get_args(): |
|
|
|
parser = argparse.ArgumentParser(description="Deamon that monitors for a specific YubiKey \ |
|
|
|
parser = argparse.ArgumentParser(description="Deamon that monitors for a specific YubiKey \ |
|
|
|
serial number. When the YubiKey is connected, any running xscreensaver instance will be \ |
|
|
|
serial number. When the YubiKey is connected, any running xscreensaver instance will be \ |
|
|
|
unlocked. When it is removed, xscreensaver will lock again.") |
|
|
|
unlocked. When it is removed, xscreensaver will lock again.") |
|
|
|
parser.add_argument('-d', '--dummy', action='store_true', \ |
|
|
|
parser.add_argument('-d', '--dummy', action='store_true', \ |
|
|
|
help='don\'t actually lock and unlock the display') |
|
|
|
help='don\'t actually lock and unlock the display') |
|
|
|
parser.add_argument('-v', '--verbose', action='store_true', help='increase output verbosity') |
|
|
|
parser.add_argument('-v', '--verbose', action='store_true', help='increase output verbosity') |
|
|
|
return parser.parse_args() |
|
|
|
return parser.parse_args() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def daemon(monitor): |
|
|
|
def daemon(monitor): |
|
|
|
|
|
|
|
|
|
|
|
last_yubikey_time = datetime.fromtimestamp(0) |
|
|
|
last_yubikey_time = datetime.fromtimestamp(0) |
|
|
|
lastdevice = 'hidraw-2' |
|
|
|
lastdevice = 'hidraw-2' |
|
|
|
|
|
|
|
|
|
|
@ -153,15 +169,13 @@ if __name__ == "__main__": |
|
|
|
|
|
|
|
|
|
|
|
execute('id > /tmp/id.txt &', shell_on=True, background = True) |
|
|
|
execute('id > /tmp/id.txt &', shell_on=True, background = True) |
|
|
|
setup_logger(config.get("HOSTCONFIG", "logfile", |
|
|
|
setup_logger(config.get("HOSTCONFIG", "logfile", |
|
|
|
fallback="log.log")) |
|
|
|
fallback="log.log")) |
|
|
|
|
|
|
|
|
|
|
|
# start xscreensaver process |
|
|
|
# start xscreensaver process |
|
|
|
execute('DISPLAY=:0 xscreensaver -no-splash&', shell_on=True, background = True) |
|
|
|
execute('DISPLAY=:0 xscreensaver -no-splash&', shell_on=True, background = True) |
|
|
|
|
|
|
|
|
|
|
|
# Lock the machine if no key is inserted when the script is started |
|
|
|
# Lock the machine if no key is inserted when the script is started |
|
|
|
if not any(serial in yubikey_serials for serial in get_yubikey_serials()): |
|
|
|
update_lock_state() |
|
|
|
logger.debug('screen will be locked') |
|
|
|
|
|
|
|
lock_screen() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
daemon(get_hid_event_monitor()) |
|
|
|
daemon(get_hid_event_monitor()) |
|
|
|
|
|
|
|
|
|
|
|