panama-osd read the wrong brightnessctl field, showing the hardware max instead of a percentage on any backlight device. panama-doctor called three sibling scripts by bare name with nothing on PATH, making three health checks permanently and falsely report broken; its repair actions also reused the short probe timeout, so a slow-but- successful restart was reported as failed. panama-wifi-qr left the cleartext passphrase temp file behind on its failure path (the RETURN trap doesn't fire on exit), and its nmcli parsing broke on connection names containing a colon or backslash -- verified against a real NetworkManager profile. panama-power-profile's set command always returned success regardless of whether the write actually took. panama-keyring's daemon-origin check picked whichever gnome-keyring-daemon process happened to enumerate first in /proc, defeating the exact dual-daemon scenario it exists to detect; it now resolves the PID that actually owns the Secret Service D-Bus name. gnf aborted before running a firmware update whenever the metadata was already current (a non-error exit under set -e), and its flatpak update lacked the -y its own docs promise. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
150 lines
6.4 KiB
Bash
Executable File
150 lines
6.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# panama-wifi-qr renders a saved network as a QR code a phone can scan.
|
|
#
|
|
# The QR contains the network PASSWORD in machine-readable form, so most of what
|
|
# is worth testing here is about handling that safely rather than about QR
|
|
# codes. Both nmcli and qrencode are stubbed: the real ones would read this
|
|
# machine's actual passphrases, and a test that writes the daily driver's Wi-Fi
|
|
# password into a fixture directory is not one worth having.
|
|
|
|
set -uo pipefail
|
|
|
|
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
helper="$repo_dir/config/dot/quickshell/scripts/panama-wifi-qr"
|
|
|
|
fail() {
|
|
printf 'wifi qr contract: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
work="$(mktemp -d /tmp/panama-wifiqr.XXXXXX)"
|
|
trap 'rm -rf "$work"' EXIT
|
|
mkdir -p "$work/bin" "$work/run"
|
|
|
|
readonly SECRET='hunter2-secret'
|
|
|
|
cat >"$work/bin/nmcli" <<STUB
|
|
#!/usr/bin/env bash
|
|
# -e no -t -f NAME connection show: one name per line, no field to split, so
|
|
# a name containing ':' or '\\' (real nmcli would otherwise backslash-escape
|
|
# both) comes back byte-for-byte.
|
|
if [[ "\$*" == *"-f NAME connection show"* ]]; then
|
|
printf 'home net\n'
|
|
printf 'work-eap\n'
|
|
printf 'Cafe: Guest\n'
|
|
printf 'Wired connection 1\n'
|
|
exit 0
|
|
fi
|
|
name="\${@: -1}"
|
|
case "\$*" in
|
|
*connection.type*)
|
|
case "\$name" in
|
|
"home net"|"work-eap"|"Cafe: Guest") printf '802-11-wireless\n' ;;
|
|
"Wired connection 1") printf '802-3-ethernet\n' ;;
|
|
esac ;;
|
|
*802-11-wireless.ssid*)
|
|
# An SSID containing reserved characters, to prove they are escaped.
|
|
case "\$name" in
|
|
"home net") printf 'home;net\n' ;;
|
|
"work-eap") printf 'work-eap\n' ;;
|
|
"Cafe: Guest") printf 'Cafe: Guest\n' ;;
|
|
esac ;;
|
|
*802-11-wireless.hidden*) printf 'no\n' ;;
|
|
*802-11-wireless-security.psk*)
|
|
# work-eap is enterprise: no passphrase exists to share.
|
|
[[ "\$name" == "home net" ]] && printf '%s\n' "$SECRET" ;;
|
|
esac
|
|
exit 0
|
|
STUB
|
|
chmod +x "$work/bin/nmcli"
|
|
|
|
# Records its argv and its stdin separately, so the test can prove the secret
|
|
# arrived on stdin and never on the command line -- argv is world-readable
|
|
# through /proc while a process runs.
|
|
cat >"$work/bin/qrencode" <<'STUB'
|
|
#!/usr/bin/env bash
|
|
printf '%s\n' "$*" >>"$QRENCODE_ARGV_LOG"
|
|
out=""
|
|
prev=""
|
|
for arg in "$@"; do
|
|
[[ "$prev" == "-o" ]] && out="$arg"
|
|
prev="$arg"
|
|
done
|
|
cat >"$QRENCODE_STDIN_LOG"
|
|
printf 'fake-png' >"$out"
|
|
exit 0
|
|
STUB
|
|
chmod +x "$work/bin/qrencode"
|
|
|
|
export QRENCODE_ARGV_LOG="$work/argv.log"
|
|
export QRENCODE_STDIN_LOG="$work/stdin.log"
|
|
: >"$QRENCODE_ARGV_LOG"
|
|
: >"$QRENCODE_STDIN_LOG"
|
|
|
|
run() { PATH="$work/bin:$PATH" XDG_RUNTIME_DIR="$work/run" "$helper" "$@"; }
|
|
|
|
# ── Listing distinguishes shareable from not ────────────────────────────────
|
|
out="$(run list)"
|
|
jq -e . >/dev/null 2>&1 <<<"$out" || fail "list did not emit JSON: $out"
|
|
[[ "$(jq -r '.networks | length' <<<"$out")" == "3" ]] \
|
|
|| fail "only wireless connections belong in the list: $out"
|
|
jq -e '.networks[] | select(.name == "home net") | .shareable == true' >/dev/null <<<"$out" \
|
|
|| fail "a network with a passphrase must be shareable: $out"
|
|
jq -e '.networks[] | select(.name == "work-eap") | .shareable == false' >/dev/null <<<"$out" \
|
|
|| fail "an enterprise network has no passphrase, so a QR code for it cannot work: $out"
|
|
|
|
# A name containing a colon must survive intact: nmcli's terse mode would
|
|
# backslash-escape it (real nmcli escapes ':' and '\' in terse/-g output), and
|
|
# a naive colon-split parser truncates the name and misaligns the next field,
|
|
# dropping the network from the list entirely.
|
|
jq -e '.networks[] | select(.name == "Cafe: Guest")' >/dev/null <<<"$out" \
|
|
|| fail "a network name containing a colon was mangled or dropped: $out"
|
|
|
|
# ── The payload ─────────────────────────────────────────────────────────────
|
|
path="$(run qr 'home net' | jq -r .path)"
|
|
[[ -n "$path" && -e "$path" ]] || fail 'no image was produced'
|
|
|
|
payload="$(cat "$QRENCODE_STDIN_LOG")"
|
|
grep -q "P:$SECRET;" <<<"$payload" \
|
|
|| fail 'the passphrase did not reach the payload intact'
|
|
|
|
# The SSID is "home;net": unescaped, the semicolon ends the S: field early and
|
|
# the code describes a different network.
|
|
grep -qF 'S:home\;net;' <<<"$payload" \
|
|
|| fail "a reserved character in the SSID was not escaped: $payload"
|
|
|
|
[[ "$(wc -l <"$QRENCODE_STDIN_LOG")" == "0" ]] \
|
|
|| fail "the payload contains a newline; nmcli's trailing newline must be stripped: $(cat -A "$QRENCODE_STDIN_LOG")"
|
|
|
|
grep -q ';;$' <<<"$payload" || fail "the WIFI: URI must be terminated with ;;: $payload"
|
|
|
|
# ── The secret must never appear in argv ────────────────────────────────────
|
|
grep -q "$SECRET" "$QRENCODE_ARGV_LOG" \
|
|
&& fail 'the passphrase was passed as a command-line argument, where /proc exposes it to every process on the machine'
|
|
|
|
# ── The image and its directory must not be readable by others ──────────────
|
|
[[ "$(stat -c '%a' "$path")" == "600" ]] \
|
|
|| fail "the QR image is mode $(stat -c '%a' "$path"); it contains a password"
|
|
[[ "$(stat -c '%a' "$(dirname "$path")")" == "700" ]] \
|
|
|| fail "the directory holding QR images is mode $(stat -c '%a' "$(dirname "$path")")"
|
|
|
|
# ── No temporary payload files may survive ──────────────────────────────────
|
|
leftovers="$(find "$work/run" -name 'payload.*' | wc -l)"
|
|
[[ "$leftovers" == "0" ]] \
|
|
|| fail "$leftovers temporary payload file(s) containing the passphrase were left behind"
|
|
|
|
# ── An unknown network is an error, not an empty image ──────────────────────
|
|
out="$(run qr 'no-such-network')"
|
|
jq -e '.path == "" and .error != ""' >/dev/null <<<"$out" \
|
|
|| fail "an unknown network must be reported: $out"
|
|
|
|
# ── A name with a colon round-trips from list into qr ───────────────────────
|
|
# The name `list` emits must be exactly what `qr` needs to look the network
|
|
# back up; escaping it either direction breaks this lookup.
|
|
out="$(run qr 'Cafe: Guest')"
|
|
[[ "$(jq -r '.path' <<<"$out")" != "" ]] \
|
|
|| fail "a saved network name containing a colon could not be looked back up: $out"
|
|
|
|
printf 'wifi qr contract: PASS\n'
|