#!/bin/sh
# Does "Run as administrator" actually run a program as the SYSTEM account, and
# only after consent? (ADR 0012.)
#
# Starts a throwaway broker in test mode (the real one prompts on the secure
# surface, which needs a session), then, as an administrator:
#   - with consent, a program runs as the SYSTEM account;
#   - without consent, it is refused.
# The refusal is the mutant: elevation cannot pass vacuously. Runs as root --
# the broker forks a PAM monitor and drops to the SYSTEM account itself.
set -u

SG_LIB="${SG_LIB:-/usr/lib/stained-glass}"
# shellcheck source=lib/sg-common.sh
. "$SG_LIB/sg-common.sh"
SG_LIBEXEC="${SG_LIBEXEC:-/usr/libexec/stained-glass}"
: "${SG_ADMIN_GROUP:=sg-admins}"

[ "$(id -u)" = 0 ] || { echo "run as root: it starts the broker and acts as $SG_USER"; exit 2; }
[ -x "$SG_LIBEXEC/sg-brokerd" ] || { echo "SKIP: sg-brokerd not built"; exit 77; }
if ! getent passwd "$SG_USER" >/dev/null || ! getent passwd "$SG_SYSTEM_USER" >/dev/null; then
    echo "SKIP: needs $SG_USER and $SG_SYSTEM_USER"; exit 77
fi

RC=0
pass() { printf 'PASS  %s\n' "$*"; }
fail() { printf 'FAIL  %s\n' "$*"; RC=1; }

SOCK=/run/sg-elevate-check.sock
WHO=/tmp/sg-elevate-who
LOG=/run/sg-elevate-check.log

# The lab's session user must be an administrator for this to mean anything.
if ! id -nG "$SG_USER" | tr ' ' '\n' | grep -qx "$SG_ADMIN_GROUP"; then
    echo "SKIP: $SG_USER is not in $SG_ADMIN_GROUP (not an administrator on this machine)"; exit 77
fi

start_broker() {   # $1 = yes|no  (consent decision in test mode)
    pkill -f "[s]g-brokerd" 2>/dev/null || true
    rm -f "$SOCK" "$LOG"; sleep 1
    SG_BROKER_TEST=1 SG_BROKER_TEST_CONSENT="$1" SG_BROKER_SOCK="$SOCK" \
        SG_BROKERD_LOG="$LOG" SG_SYSTEM_USER="$SG_SYSTEM_USER" SG_ADMIN_GROUP="$SG_ADMIN_GROUP" \
        "$SG_LIBEXEC/sg-brokerd" >/dev/null 2>&1 </dev/null
    for _ in 1 2 3 4 5; do [ -S "$SOCK" ] && break; sleep 1; done
}
elevate_as_user() {   # runs sg-elevate as $SG_USER
    rm -f "$WHO"; : > "$WHO"; chmod 0666 "$WHO"
    runuser -u "$SG_USER" -- env SG_BROKER_SOCK="$SOCK" \
        "$SG_LIBEXEC/sg-elevate" -- /bin/sh -c "id -un > $WHO 2>/dev/null" >/dev/null 2>&1
}

# 1. With consent, the program runs as the SYSTEM account.
start_broker yes
elevate_as_user
sleep 1
who=$(cat "$WHO" 2>/dev/null || echo "")
if [ "$who" = "$SG_SYSTEM_USER" ]; then
    pass "an administrator's program elevated: ran as $who (the SYSTEM account)"
else
    fail "elevated program ran as '$who', expected $SG_SYSTEM_USER"
fi

# 2. Without consent, it must be refused (the mutant).
start_broker no
elevate_as_user
sleep 1
who=$(cat "$WHO" 2>/dev/null || echo "")
if [ "$who" = "$SG_SYSTEM_USER" ]; then
    fail "a program ran as $SG_SYSTEM_USER with consent denied -- the gate proves nothing"
else
    pass "without consent, elevation is refused"
fi

pkill -f "[s]g-brokerd" 2>/dev/null || true
rm -f "$SOCK" "$WHO" "$LOG"

echo
if [ "$RC" -eq 0 ]; then echo "RESULT: PASS"; else echo "RESULT: FAIL"; fi
exit "$RC"
