Browse Source

Check if screensaver is running before taking action

master
Burathar 4 years ago
parent
commit
fbcd275d4a
  1. 16
      bin/kill_screensaver_graphic_program.sh
  2. 34
      bin/xscreensaver_yubilock.py

16
bin/kill_screensaver_graphic_program.sh

@ -4,17 +4,19 @@ function help () {
echo "Usage: $0 [OPTIONS] <file>" echo "Usage: $0 [OPTIONS] <file>"
echo "Cleans up xscreensaver graphic programs left behind after killing xscreensaver itself." echo "Cleans up xscreensaver graphic programs left behind after killing xscreensaver itself."
echo " -u specify a username for which to kill xscreensaver artifacts" echo " -u specify a username for which to kill xscreensaver artifacts"
echo " -d dummy; just check if screensaver graphic program is running and exit."
echo " -h display this output" echo " -h display this output"
exit 1 exit 1
} }
while getopts ':u:' opt ; do while getopts ':u:dh' opt ; do
case "$opt" in case "$opt" in
u) u)
username="${OPTARG}" username="${OPTARG}"
userid=`id -u "$username" 2>/dev/null` || { echo "$username is not a user on this system" && exit 1 ;} userid=`id -u "$username" 2>/dev/null` || { echo "$username is not a user on this system" && exit 1 ;}
[ "$userid" -lt 1000 ] && echo "User $username seems to be a systemuser (uid: $userid). Please specify a normal user." && exit 1 [ "$userid" -lt 1000 ] && echo "User $username seems to be a systemuser (uid: $userid). Please specify a normal user." && exit 1
;; ;;
d) dummy='true';;
h) help ;; h) help ;;
:) :)
echo "$0: Must supply an argument to -$OPTARG." >&2 echo "$0: Must supply an argument to -$OPTARG." >&2
@ -31,11 +33,13 @@ username="${username:-$USER}"
homedir=`eval echo "~$username"` homedir=`eval echo "~$username"`
selected_graphic_nr=`grep selected "$homedir/.xscreensaver" | cut -f 2` selected_graphic_nr=`grep selected "$homedir/.xscreensaver" | cut -f 2`
regex='/\\n\\/' regex='/\\n\\/'
graphic_process_name=`cat "$homedir/.xscreensaver" | awk "$regex && ++n == "$selected_graphic_nr" {getline; print; exit}" | cut -f 5 | cut -d ' ' -f 1 ` graphic_program_name=`cat "$homedir/.xscreensaver" | awk "$regex && ++n == "$selected_graphic_nr" {getline; print; exit}" | cut -f 5 | cut -d ' ' -f 1 `
echo "graphic_process_name: $graphic_process_name" [ -z "$graphic_program_name" ] && { echo Could not find selected graphic application && exit 1; }
[ -z "$graphic_process_name" ] && { echo Could not find selected graphic application && exit 1; } echo "graphic_program: $graphic_program_name"
graphic_processes=`ps -U "$username" | grep "$graphic_process_name" | awk '{$1=$1};1' | cut -d ' ' -f 1 | tr '\n' ' ' ` || { echo "No screensaver graphic processes were found for $username" && exit 0; }
echo "graphic_processes: $graphic_processes" graphic_processes=`ps -U "$username" | grep "$graphic_program_name" | awk '{$1=$1};1' | cut -d ' ' -f 1 | tr '\n' ' ' ` || { echo "No screensaver graphic processes were found for $username" && exit 0; }
[ -z "$graphic_processes" ] && { echo "No xscreensaver graphic processes seem to be running for $username" && exit 0; } [ -z "$graphic_processes" ] && { echo "No xscreensaver graphic processes seem to be running for $username" && exit 0; }
echo "graphic_processes: $graphic_processes"
[ "$dummy" = 'true' ] && exit 0
process_count=`echo $graphic_processes | wc -w` process_count=`echo $graphic_processes | wc -w`
kill $graphic_processes && echo "killed $process_count screensaver graphic processes for $username" kill $graphic_processes && echo "killed $process_count screensaver graphic processes for $username"

34
bin/xscreensaver_yubilock.py

@ -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
@ -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,6 +66,7 @@ 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)
@ -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,9 +124,7 @@ 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
@ -123,7 +137,9 @@ def get_args():
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'
@ -159,9 +175,7 @@ if __name__ == "__main__":
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())

Loading…
Cancel
Save