fix: classify unauthorized by stderr presence, not denial wording

Review flagged the 'access not allowed' substring:
if tmux's denial text drifts while keeping exit 0, unauthorized
connections would classify as ok and the false-joined status/leave
misreporting would silently return. A clean authorized list-clients
writes nothing to stderr (verified 3.3a/3.5a/3.6-SunOS, incl. invited
read-only clients), so rc 0 plus any stderr output now classifies as
unauthorized: no message text consulted. Drift in any direction
degrades to a hidden party, never to a false ok.
This commit is contained in:
veg 2026-07-04 14:03:53 +00:00
parent b44a3b705f
commit 938491df1e
3 changed files with 45 additions and 16 deletions

33
party
View file

@ -343,26 +343,33 @@ is_party_alive() {
# Classify the caller's relationship to a party socket. Prints exactly
# one of:
# ok — live tmux server, the caller is authorized.
# unauthorized — live tmux server, but server-access rejected us.
# CAUTION, the reason this function exists: tmux
# answers a non-allowlisted user with "access not
# allowed" on stderr and EXIT STATUS 0 (verified live
# on 3.3a and 3.5a), for every command — including
# unauthorized — live tmux server, but it refused us. CAUTION, the
# reason this function exists: tmux answers a
# non-allowlisted user with "access not allowed" on
# stderr and EXIT STATUS 0 (verified live on 3.3a,
# 3.5a, and 3.6/SunOS), for every command — including
# has-session, which then reports any target as
# existing. Exit codes alone cannot distinguish
# authorized from unauthorized; the message can.
# authorized from unauthorized. We deliberately do NOT
# match the denial text either: wording could drift
# across tmux versions and silently reopen the
# false-authorized paths. A clean authorized
# list-clients writes nothing to stderr, so rc 0 plus
# ANY stderr output classifies as unauthorized. Should
# tmux ever warn on an authorized call, that degrades
# to a hidden party — never to a false "ok".
# dead — nothing speaking the tmux protocol at that socket
# (stale roster, killed server, AF_UNIX impostor).
# Unknown error text with nonzero rc falls through to "dead", so string
# drift in a future tmux degrades to hidden-party behavior, never to a
# false "ok".
party_conn_state() {
_cs_err=$("$PARTY_TMUX" -S "$1" list-clients 2>&1 >/dev/null) \
&& _cs_rc=0 || _cs_rc=$?
case "$_cs_err" in
*"access not allowed"*) printf 'unauthorized\n'; return 0 ;;
esac
if [ "$_cs_rc" -eq 0 ]; then printf 'ok\n'; else printf 'dead\n'; fi
if [ "$_cs_rc" -ne 0 ]; then
printf 'dead\n'
elif [ -n "$_cs_err" ]; then
printf 'unauthorized\n'
else
printf 'ok\n'
fi
}
# FS perms