# bscreensaver ## What `bsreensaver` is a simple X11 screen locker for Linux that is designed to be secure (in the same vein as `xscreensaver`), but also secure, meaning that once the screen is locked, it will be incredibly difficult to unlock the screen without a password, even if crash-level bugs are found in many of `bscreensaver`'s isolated components. ## Why `xscreensaver` is likely one of (if not the) most secure screen lockers out there. However, the unlock dialog, despite my attempts to theme it (mainly by changing colors and border widths) is extremely ugly. Even if I could get it to look decently nice, it would still not fit in with my GTK-based desktop. The last time I looked at the other GTK-based screensavers (`gnome-screensaver`, `xfce4-screensaver`), they both embedded the unlock dialog into the main screen locking process. This is terrible for security, as GTK is a very large toolkit that is difficult to secure. Crasher bugs may not always be high-priority items for the developers to fix, especially if a crash is obscure and only happens in unlikely scenarios. Unfortunately, these types of crash bugs are critical for a screen locker, as this can mean that doing something strange (like, say, repeatedly pressing some key combination while shaking the mouse around) can cause the locker to crash, unlocking the system without authentication. ## Build and Installation `bscreensaver` is written in Rust, and requires `cargo` and a Rust compiler installed. Stable rust is fine, though something fairly recent (as of May 2022) is required. A `Makefile` is provided to make things easy. Run `make` to build a release version of the software, and `make install` to install it. By default, components will be installed under `/usr/local`. You may pass `PREFIX`, `BINDIR`, `LIBEXECDIR`, `DATADIR`, and `MANDIR` to your invocation of `make` and `make install` to customize the installation. Be sure to pass these with `make` as well, because the build process embeds filesystem paths into the binary so the main locker process can find its helper applications. You can also pass `DESTDIR` to install to a staging directory (e.g. for building distribution packages). I've also included a `deb-pkg` target that will use Docker to build a Debian package. ## Configuration The locker looks for a configuration file in the relative path `bscreensaver/bscreensaver.toml` using the XDG base directories specification. In practice, by default it should look for files in the following places: * `/etc/xdg/bscreensaver/bscreensaver.toml` * `$HOME/.config/bscreensaver/bscreensaver.toml` Settings in these files are "additive" in that each file is read and parsed, and settings in "later" files override settings specified in "earlier" files. A sample configuration file is included (`bscreensaver.toml.example`). Distributions may install this to `/usr/share/doc/bscreensaver` or possibly `/etc/xdg/bscreensaver`. You need not edit the configuration file manually, but can instead run the `bscreensaver-settings` program, which displays a settings UI. ## Architecture `bscreensaver` is broken up into several pieces, each which run in their own isolated process: * locker * dialog * dbus-service * systemd-service * command * settings ### Locker The locker component is the most critical. It's responsible for drawing blank windows on the screen and grabbing the keyboard and mouse. When it detects mouse movement or key presses, it will run the dialog component, and examine its exit status to determine if the screen should be unlocked. This component must not crash under any circumstances. A crash here means that a locked screen is now unlocked. This component should have has few dependencies as possible, and should handle errors in such a way that the program tries very hard to stay running even when unexpected things happen. ### Command The command component is a small bit of functionality that uses a hidden X11 window to allow the locker process to be sent commands (such as "lock", "deactivate", or "restart"). The locker process, on startup, creates a hidden X11 window, and then publishes the ID of this window in a property on the screen's root window. When someone uses the command component to send a command to the locker, the command component finds the command window's ID, and then sends it a client message. ### Dialog The dialog component draws a password prompt on the screen, and then validates that the password entered was correct. If the password is correct, the dialog exits with status 0. If not, or if authentication is canceled, it exits with a failure status. The dialog process and locker process also communicate using the XEMBED protocol, which allows us to seamlessly embed X11 UI from one process into another. ### DBus Service The DBus service is launched by the locker process and acquires the `org.freedesktop.ScreenSaver` bus name, and responds to requests to inhibit and uninhibit the screen locker (for example, when you are playing a video on your computer, you don't want the screen to lock, even if you don't move the mouse or touch a key). It communicates with the locker process using the command component. To inhibit the locker, it periodically sends a "deactivate" command to the locker, which causes it to reset its user activity timeout (assuming the locker is currently unlocked). ### Systemd Service The systemd service handles locking the screen on suspend and presenting the unlock dialog on resume. If you close the lid of your laptop, you probably want the screen to lock immediately. The `bscreensaver` systemd service registers a sleep inhibitor with systemd that causes it to delay sleep so that the systemd service can be notified of impending sleep, and use the command component to instruct the locker to lock, before telling systemd that it's ok to sleep. When the computer wakes back up, it again receives a notification from systemd, which allows it to present the unlock dialog immediately after resuming. ### Settings The settings component is a standalone GTK app that presents a settings dialog, which reads from and writes to your configuration file.