deploy: harden mosquitto password_file guards (non-root, runuser errors, symlinks, traversal, all lines)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
@@ -1055,7 +1055,18 @@ if awk '/^set_units\(\)/,0' deploy.sh | sed -n '/^echo "== apply =="/,/^post_che
|
||||
t23=$(mktemp -d); mkdir -p "$t23/etc/conf.d" "$t23/stub" "$t23/nostub"
|
||||
echo secret > "$t23/pw"
|
||||
printf '# password_file /nope\nlistener 1883\npassword_file %s\n' "$t23/pw" > "$t23/etc/mosquitto.conf"
|
||||
stubru() { printf '#!/bin/sh\n# runuser -u USER -- test -r FILE\nexit %s\n' "$1" > "$t23/stub/runuser"; chmod +x "$t23/stub/runuser"; }
|
||||
stubru() { # stubru <rc of test -r> [rc of `true`] [rc of test -x] [only this file fails test -r (default: all)]
|
||||
cat > "$t23/stub/runuser" <<STUB
|
||||
#!/bin/sh
|
||||
shift 3
|
||||
case "\$1 \$2" in
|
||||
"true "*) exit ${2:-0} ;;
|
||||
"test -x") exit ${3:-0} ;;
|
||||
"test -r") if [ -z "${4:-}" ] || [ "\$3" = "${4:-}" ]; then exit $1; else exit 0; fi ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
chmod +x "$t23/stub/runuser"; }
|
||||
mq() { PATH="$t23/stub:/usr/bin:/bin" VANLINK_MOSQUITTO_USER=root ./deploy.sh --mosquitto-pwfile-check "$@" 2>&1; }
|
||||
stubru 1; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = "$t23/pw" ] && ok "23b: unreadable password file is reported (path only)" || bad "23b: unreadable: got '$o'"
|
||||
@@ -1082,6 +1093,41 @@ stubru 0; o=$(pcm)
|
||||
printf 'password_file %s\n' "$t23/pw" > "$t23/etc/mosquitto.conf"
|
||||
o=$(PATH="/usr/bin:/bin" VANLINK_MOSQUITTO_CONF="$t23/etc/mosquitto.conf" VANLINK_MOSQUITTO_USER=root POSTCHECK_WAIT=0 ./deploy.sh --post-check hosts/van.conf 2>&1 || true)
|
||||
! echo "$o" | grep -q 'is not readable by the mosquitto user' && ok "23c: runuser missing -> no warn" || bad "23c: runuser missing warned"
|
||||
# I3: several / quoted / symlinked password_file lines; runuser trouble reports nothing
|
||||
echo secret2 > "$t23/pw2"; ln -sf "$t23/pw2" "$t23/link"; ln -sf "$t23/nowhere" "$t23/dangling"; mkdir -p "$t23/adir"
|
||||
printf 'password_file %s\npassword_file %s\n' "$t23/pw" "$t23/pw2" > "$t23/etc/mosquitto.conf"
|
||||
stubru 1 0 0 "$t23/pw"; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = "$t23/pw" ] && ok "23b: two password_file lines, only the first unreadable -> that one" || bad "23b: two lines: got '$o'"
|
||||
stubru 1 0 0 "$t23/pw2"; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = "$t23/pw2" ] && ok "23b: the last line unreadable is found too" || bad "23b: last line: got '$o'"
|
||||
printf 'password_file "%s"\n' "$t23/pw" > "$t23/etc/mosquitto.conf"; stubru 1; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = "$t23/pw" ] && ok "23b: quoted path" || bad "23b: quoted: got '$o'"
|
||||
printf 'password_file %s\n' "$t23/link" > "$t23/etc/mosquitto.conf"; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = "$t23/pw2" ] && ok "23b: symlink -> resolved path reported" || bad "23b: symlink: got '$o'"
|
||||
for pf in "$t23/dangling" "$t23/adir" "relative/pw"; do
|
||||
printf 'password_file %s\n' "$pf" > "$t23/etc/mosquitto.conf"; o=$(mq "$t23/etc/mosquitto.conf")
|
||||
[ -z "$o" ] && ok "23b: $(basename "$pf") (dangling/dir/relative) -> nothing" || bad "23b: $pf: got '$o'"
|
||||
done
|
||||
printf 'password_file %s\n' "$t23/pw" > "$t23/etc/mosquitto.conf"
|
||||
stubru 1 125; o=$(mq "$t23/etc/mosquitto.conf"); [ -z "$o" ] && ok "23b: runuser -- true failing (125) -> nothing" || bad "23b: true fails: got '$o'"
|
||||
stubru 126; o=$(mq "$t23/etc/mosquitto.conf"); [ -z "$o" ] && ok "23b: test -r exiting 126 -> nothing" || bad "23b: rc 126: got '$o'"
|
||||
stubru 1 0 1; o=$(mq "$t23/etc/mosquitto.conf"); [ -z "$o" ] && ok "23b: untraversable dir -> not in the problem list (no chown)" || bad "23b: notraverse: got '$o'"
|
||||
pcm() { PATH="$t23/stub:/usr/bin:/bin" VANLINK_MOSQUITTO_CONF="$t23/etc/mosquitto.conf" VANLINK_MOSQUITTO_USER=root POSTCHECK_WAIT=0 ./deploy.sh --post-check hosts/van.conf 2>&1 || true; }
|
||||
o=$(pcm)
|
||||
echo "$o" | grep -qF -- "-> post-deploy: mosquitto cannot traverse $t23 to reach its password file" && ok "23c: untraversable dir -> distinct warn" || bad "23c: no notraverse warn"
|
||||
echo "$o" | grep -q 'is not readable by the mosquitto user' && bad "23c: notraverse also warned unreadable" || ok "23c: notraverse is not reported as unreadable"
|
||||
# non-root without a knob: nothing, and the neutral line
|
||||
stubru 1; o=$(PATH="$t23/stub:/usr/bin:/bin" ./deploy.sh --mosquitto-pwfile-check "$t23/etc/mosquitto.conf" 2>&1)
|
||||
[ -z "$o" ] && ok "23b: non-root without a test knob -> nothing" || bad "23b: non-root: got '$o'"
|
||||
o=$(PATH="$t23/stub:/usr/bin:/bin" POSTCHECK_WAIT=0 ./deploy.sh --post-check hosts/van.conf 2>&1 || true)
|
||||
echo "$o" | grep -q 'is not readable by the mosquitto user' && bad "23c: non-root real run warned about the pw file" || ok "23c: non-root, no knob -> no pw warning"
|
||||
o=$(bash -c '. <(sed -n "/^mosquitto_conf()/,/^post_check()/p" deploy.sh | sed "\$d"); mosquitto_conf() { echo "$1"; }; if mosquitto_can_probe; then echo probe; else [ -z "$(mosquitto_pwfile_paths "$1")" ] || echo NEUTRAL; fi' _ "$t23/etc/mosquitto.conf")
|
||||
[ "$o" = NEUTRAL ] && ok "23c: non-root branch with a configured password_file takes the neutral path" || bad "23c: neutral branch: got '$o'"
|
||||
grep -qF 'ok mosquitto password file: cannot verify as non-root (run with sudo)' deploy.sh && ok "23c: neutral line text present" || bad "23c: neutral line text missing"
|
||||
# I2: fix path shape and order
|
||||
if grep -qE '^ +if chown mosquitto:mosquitto "\$mq_pw" && chmod 0600 "\$mq_pw"; then' deploy.sh && grep -qF 'could NOT be fixed (do it manually' deploy.sh; then ok "23d: fix path is if/then/else with a NOT-fixed warn"; else bad "23d: fix path shape"; fi
|
||||
c=$(grep -n '^ *if chown mosquitto:mosquitto' deploy.sh | cut -d: -f1); r=$(grep -n '^systemctl restart mosquitto' deploy.sh | cut -d: -f1)
|
||||
[ -n "$c" ] && [ -n "$r" ] && [ "$c" -lt "$r" ] && ok "23d: chown block precedes the mosquitto restart" || bad "23d: chown/restart order ($c/$r)"
|
||||
rm -rf "$t23"
|
||||
|
||||
exit "$fail"
|
||||
|
||||
Reference in New Issue
Block a user