initial commit
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user