Files
2026-07-26 21:19:04 +02:00

160 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# att_lock
An Android-style **4×4 dot pattern** screen locker for `wlroots`-based Wayland
compositors (Sway, Hyprland, river, labwc, …). It uses the secure
[`ext-session-lock-v1`] protocol, verifies the drawn pattern against a salted
hash stored in an XDG-compliant directory, and falls back to **PAM** password
authentication.
[`ext-session-lock-v1`]: https://wayland.app/protocols/ext-session-lock-v1
## Features
- **4×4 dot grid**, drawn by dragging with a **pointer or touch** — including
Android's rule that intermediate dots on a straight line get captured.
- **Rotation / any aspect ratio**: the grid is a centred square sized from the
compositor-provided surface dimensions, so portrait, landscape and rotated
outputs all just work. HiDPI (integer `wl_output` scale) is honoured.
- **First-run setup**: with no stored pattern (or `--setup`) you draw the
pattern twice to confirm it. It is stored as a salted **yescrypt** hash
(falling back to sha512crypt) at `$XDG_DATA_HOME/att_lock/pattern.hash`
(mode `0600`), never in plaintext. The hash uses cost factor 9 (~0.22 s per
attempt) and covers your username as well as the pattern, so the same pattern
on two accounts produces unrelated hashes.
- **PAM password fallback**: start typing at the unlock screen to switch to a
password field authenticated through PAM (for "forgot pattern").
- **Background image** via a command-line argument (PNG), scaled to cover.
- Secure by construction: if the process dies while locked, the compositor
keeps the session locked (a guarantee of `ext-session-lock-v1`).
## Build
The build system is **Nix flakes**.
```sh
# One-off build:
nix build # -> ./result/bin/att_lock
# Or a dev shell + meson:
nix develop
meson setup build
ninja -C build # -> ./build/att_lock
```
Dependencies (provided by the flake): `wayland`, `wayland-scanner`, `cairo`,
`libxkbcommon`, `pam` (linux-pam), `libxcrypt`, plus `meson`/`ninja`/`pkg-config`.
## Usage
```
att_lock [options] [IMAGE]
-i, --image PATH Background image (PNG); also accepted positionally
-p, --pam-service NAME PAM service for the password fallback (default: login)
-m, --min-dots N Minimum dots in a pattern (default: 4)
--setup Force (re)creation of the stored pattern
-h, --help Show help
```
Examples:
```sh
att_lock ~/wallpaper.png # lock with a background
att_lock --setup # re-record the pattern, then unlock
att_lock -p att_lock -i bg.png # use a dedicated PAM service
```
### Unlocking
- **Draw** your pattern (≥ `--min-dots` dots) and release to unlock.
- **Type** any character to switch to the **password** field; press **Enter** to
authenticate via PAM, **Esc** to go back to the pattern.
After 4 failed attempts, further attempts are locked out for an escalating
delay — 15 s, then 30 s, 60 s, 120 s, 240 s, capped at 5 minutes — with the
remaining time shown on screen. The counter is shared between the pattern and
the password field, so switching to the password does not sidestep an active
lockout, and it is held in memory only (there is no way to restart the locker
to clear it, since the compositor keeps the session locked regardless). The
countdown uses a monotonic clock, so it cannot be skipped by changing the
system time or by suspending the machine.
## PAM configuration
The password fallback authenticates through PAM using the service named by
`--pam-service` (default `login`, which exists on most systems). For a
dedicated service, create one that stacks `pam_unix`:
**NixOS** (`configuration.nix`):
```nix
security.pam.services.att_lock = {}; # inherits sane defaults (pam_unix)
```
then run `att_lock --pam-service att_lock`.
**Other distros** (`/etc/pam.d/att_lock`):
```
auth include login
account include login
```
> The pattern itself is **not** checked by PAM — it is verified against the
> local salted hash. PAM only backs the password fallback.
## Wiring it into your compositor
Use it as your lock command, e.g. with `swayidle`:
```sh
swayidle -w \
timeout 300 'att_lock ~/wallpaper.png' \
before-sleep 'att_lock ~/wallpaper.png'
```
or bind it in Sway:
```
bindsym $mod+Escape exec att_lock ~/wallpaper.png
```
## Notes & limitations
- A pattern is not a password. The lockout above throttles *online* guessing at
the lock screen, but it cannot help offline: even at cost factor 9 there are
only 43,680 possible 4-dot patterns, so anyone who obtains `pattern.hash` can
search that space at their own pace. Raise `--min-dots` if that matters to
you; each extra dot multiplies the space by roughly an order of magnitude.
- Patterns are also far more shoulder-surfable than typed passwords, and on
touchscreens finger smudges can reveal them.
- Hash files written by versions before the `att_lock-hash-v3` format are not
readable; att_lock reports this and asks you to draw a new pattern. The PAM
password fallback still works in the meantime. In particular, v3 is the
format written since this project was renamed from `wlpattern`: the account
name and the project name are both baked into the hash input, so a pattern
enrolled under `wlpattern` (in `$XDG_DATA_HOME/wlpattern/`) cannot be carried
over and must be re-drawn once.
- Background images must be **PNG** (loaded via Cairo). Convert other formats
first (e.g. `magick in.jpg out.png`).
- The pattern is rendered identically on every connected output; the live
drag segment is drawn on the output receiving input.
- Rendering uses `wl_shm` + Cairo (no GPU/EGL dependency).
## Layout
```
flake.nix Nix flake: package + dev shell
meson.build build definition
protocols/ext-session-lock-v1.xml vendored Wayland protocol
src/main.c Wayland client, input, unlock/setup logic
src/pattern.c grid geometry + pattern sequence model
src/render.c wl_shm buffers + Cairo drawing
src/auth.c hashing/storage (crypt) + PAM
src/att_lock.h shared types and interfaces
```
## License
MIT. The vendored protocol XML is MIT (wlroots contributors).