async-xcb | ||
command | ||
dbus-service | ||
debian | ||
dialog-gtk3 | ||
locker | ||
settings | ||
systemd | ||
util | ||
xcb-xembed | ||
.dockerignore | ||
.gitignore | ||
90-backlight.rules | ||
bscreensaver.toml.example | ||
build.rs | ||
Cargo.lock | ||
Cargo.toml | ||
Dockerfile | ||
LICENSE | ||
Makefile | ||
README.md | ||
TODO.md |
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.
Screen Brightness
If you enable the setting that allows bscreensaver
to make your screen
brightness keys work while the screen is locked, this should hopefully
work without further intervention, if your display driver supports the
XBACKLIGHT
protocol. If not, bscreensaver
will attempt to use the
backlight controls in sysfs, which probably will not work without extra
setup, as those controls are usually only accessible to root. You can
give yourself (well, anyone in the video
group) access by adding a
udev rules file, say at /etc/udev/rules.d/90-backlight.rules
:
SUBSYSTEM=="backlight", ACTION=="add", \
RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness", \
RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
You may need to restart to get those settings applied, or you can just
run those commands yourself (replacing %k
with whatever directories
happen to be located there). Your user account will also need to be in
the video
group; if it isn't, you'll probably need to log out and in
again before any changes take effect.