#!/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" <"$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")" == "2" ]] \ || 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" # ── 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" printf 'wifi qr contract: PASS\n'