149 lines
6.1 KiB
Markdown
149 lines
6.1 KiB
Markdown
|
# 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.
|