git.lucas.co / cce-display-manager
login greeter
git clone https://git.lucas.co/cce-display-manager.git

scripts/cce-gnome-keyring-start (2.1K)

 1 #!/bin/sh
 2 # cce-gnome-keyring-start — run gnome-keyring-daemon, unlocked, as ONE process.
 3 #
 4 # Two failures this shape is deliberately built around, both hit on 2026-08-29:
 5 #
 6 #  1. `gnome-keyring-daemon --unlock` does NOT exit — it daemonizes into a
 7 #     second keyring daemon. Two daemons racing for org.freedesktop.secrets is
 8 #     the same class of bug that made the old KeePassXC setup unpredictable.
 9 #     So the password goes into the daemon's own stdin at startup instead.
10 #
11 #  2. `systemd-creds decrypt` as a non-root user delegates to a polkit-gated
12 #     root service. It succeeds in an interactive session and fails at login
13 #     (io.systemd.InteractiveAuthenticationRequired), which wedged the greeter.
14 #     tpm2-tools talks to /dev/tpmrm0 directly via the `tss` group — no agent,
15 #     no prompt, no authorization step that can be absent at boot.
16 #
17 # Login here is by fingerprint, so PAM never sees a password and cannot unlock
18 # anything; the keyring password is sealed to the TPM instead.
19 
20 set -eu
21 
22 DIR="${CCE_KEYRING_DIR:-$HOME/.config/cce}"
23 PUB="$DIR/keyring-seal.pub"
24 PRIV="$DIR/keyring-seal.priv"
25 
26 [ -r "$PRIV" ] || { echo "no TPM seal at $PRIV; run cce-gnome-keyring-enroll" >&2; exit 1; }
27 
28 TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT INT TERM
29 
30 # The TPM serializes, so a request racing another user of it fails
31 # transiently. Retry the whole unseal, primary key included.
32 n=0
33 until PW=$( { tpm2_createprimary -Q -C o -g sha256 -G ecc -c "$TMP/primary.ctx" \
34               && tpm2_load -Q -C "$TMP/primary.ctx" -u "$PUB" -r "$PRIV" -c "$TMP/seal.ctx" \
35               && tpm2_unseal -c "$TMP/seal.ctx"; } 2>&1 ); do
36     n=$((n + 1))
37     if [ "$n" -ge 5 ]; then
38         echo "TPM unseal failed after $n attempts: $PW" >&2
39         exit 1
40     fi
41     sleep 1
42 done
43 
44 # --unlock reads the password from stdin and creates the login keyring if it is
45 # missing. --foreground keeps this under systemd instead of forking away.
46 printf '%s' "$PW" | exec gnome-keyring-daemon \
47     --foreground \
48     --components=pkcs11,secrets \
49     --unlock \
50     --control-directory="${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR unset}/keyring"