diff --git a/Makefile b/Makefile index c970c5b..1da976f 100644 --- a/Makefile +++ b/Makefile @@ -61,6 +61,14 @@ setup-usbguard: systemctl enable --now usbguard usbguard-dbus systemctl restart usbguard usbguard-dbus + # Restart usb-auth-guard for all logged-in users so they pick up the + # new usbguard-dbus instance (the old D-Bus match rule is now stale). + @for uid in $$(loginctl list-users 2>/dev/null | awk 'NR>1 && /^[[:space:]]*[0-9]+[[:space:]]/{print $$1}'); do \ + user=$$(id -un $$uid 2>/dev/null) || continue; \ + systemctl --user -M $$uid@ restart usb-auth-guard 2>/dev/null && \ + echo " Restarted usb-auth-guard for user $$user" || true; \ + done + @echo "==> USBGuard configured!" @echo " Devices connected NOW are trusted. New devices will require auth." diff --git a/README.md b/README.md index fe3d95f..351647d 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,12 @@ curl -fsSL https://raw.githubusercontent.com/SolVerNA/usb-auth-guard/master/inst ```bash # if needed: -# sudo apt-get install -y make dpkg-dev +# sudo apt-get install -y git make dpkg-dev git clone https://github.com/SolVerNA/usb-auth-guard cd usb-auth-guard make deb -sudo dpkg -i ./usb-auth-guard_1.0.0.deb +sudo apt install -y ./usb-auth-guard_1.0.0.deb # installs usbguard and all other dependencies automatically +sudo make setup-usbguard # trust currently connected devices, put USBGuard into block mode systemctl --user enable --now usb-auth-guard ``` diff --git a/src/usb-auth-guard b/src/usb-auth-guard index 7967f78..b0e6379 100644 --- a/src/usb-auth-guard +++ b/src/usb-auth-guard @@ -95,15 +95,46 @@ def main(): try: bus = dbus.SystemBus() + bus.get_name_owner('org.usbguard1') + except dbus.DBusException as e: + log.error('Cannot connect to USBGuard D-Bus: %s', e) + log.error('Run: sudo systemctl start usbguard-dbus') + sys.exit(1) + + state = {'iface': None} + + def subscribe(): proxy = bus.get_object('org.usbguard1', '/org/usbguard1/Devices') iface = dbus.Interface(proxy, dbus_interface='org.usbguard.Devices1') iface.connect_to_signal('DevicePresenceChanged', on_device_presence_changed) + state['iface'] = iface log.info('Listening for USBGuard events...') + + try: + subscribe() except dbus.DBusException as e: - log.error('Cannot connect to USBGuard D-Bus: %s', e) - log.error('Run: sudo systemctl start usbguard-dbus') + log.error('Cannot subscribe to USBGuard D-Bus signals: %s', e) sys.exit(1) + # Re-subscribe automatically when usbguard-dbus restarts. + # Each restart gives the process a new unique D-Bus name; without re-subscribing + # the old match rule is stale and DevicePresenceChanged signals are never received. + def on_usbguard_name_changed(new_owner): + if new_owner and state['iface'] is None: + log.info('USBGuard D-Bus reappeared, re-subscribing...') + try: + subscribe() + except dbus.DBusException as e: + log.error('Re-subscribe failed: %s', e) + elif not new_owner and state['iface'] is not None: + log.warning('USBGuard D-Bus disappeared, waiting for restart...') + state['iface'] = None + + # watch_name_owner fires immediately with the current owner; because + # subscribe() above already populated state['iface'], the + # "new_owner and iface is None" branch is skipped for that initial call. + bus.watch_name_owner('org.usbguard1', on_usbguard_name_changed) + loop = GLib.MainLoop() try: loop.run()