The thread-per-connection TLS path bounded only the handshake read, so a peer
advertising a zero TCP receive window could stall our certificate write and pin
the thread forever; add a write deadline (cleared once the handshake completes).
The wss listener ran backend.accept() with no deadline at all — bound its TLS
handshake both ways too. Both reset via the same-socket shutdown handle.
A holder's channel messages reach +D (deaf) members: gate the deaf-skip in
to_channel_tagged and the TAGMSG fanout on the sender's users/ignore-privdeaf
(relayed/service messages, which have no local sender, are unaffected). Granted
by the auspex class; verified live (netadmin reaches a deaf user, a restricted
oper does not).
Convert the remaining oper bypass/visibility gates to named privileges:
channels/restricted-create, channels/ignore-nonicks, users/ignore-callerid,
users/secret-whois, users/ignore-restrictmsg, servers/use-disabled-commands,
servers/ignore-securelist, servers/ignore-blockamsg. The override class gains
the channel/message/anti-spam bypasses, auspex gains secret-whois +
ignore-callerid, server gains use-disabled-commands; netadmin keeps all via
privs=*. Docs updated; verified restricted-create + ignore-nonicks live.
README + operators.md now cover the three permission axes (commands, named
privileges, usermode/chanmode allowlists) with the *,-token syntax, the standard
privileges table (users/auspex, channels/auspex, servers/auspex, channels/override,
users/flood, users/ignore-commonchans), and the connect-notice auspex redaction.
+s has its own dispatch in apply_user_modes, so it bypassed the per-oper-type
usermode allowlist. Gate it on can_use_mode('s') like the generic oper modes;
non-opers are still rejected by apply_snomask, services under sudo pass through.
commands=/privs= now honour a -token removal (e.g. *,-DIE), threaded through
resolve as deny sets and applied in the command gate + has_priv. WHOIS of a
+I (hidechans) user's channel list now needs users/auspex, not any oper.
The usermodes=/chanmodes= class/type keys were parsed then ignored. Add a
ModeAllow allowlist to the resolved oper type + can_use_mode(), checked in
the oper-only mode handlers (services under mode_sudo pass through).
Unspecified stays permissive so built-in types are unrestricted; a type
opts into restriction with an explicit letter list (or * = all).
Add a central privs registry and convert raw is_oper gates to named
privileges: users/flood (message + join flood exempt), channels/override
(the +k/+b/+i/+l/+z/+R/+J / CBAN / max-channels join bypasses),
servers/auspex (hidden services in LINKS/MAP), users/ignore-commonchans
(+c PM gate). The override class now grants channels/override + users/flood;
the auspex class adds servers/auspex. netadmin keeps all via privs=*.
Add has_priv/user_has_priv and wire the auspex privileges into their gates:
WHOIS real host+IP + geo, WHO secret-channel members + hidden +i users,
LIST secret/private channels, and the connect-notice IP/geo redaction.
Only netadmin holds every privilege by default; the reusable auspex class
grants the pair to any other oper type. Replaces the ad-hoc snoop type gate.
Per-viewer rendering via new snotice_c_gated: only opers whose type is in
snoop_sensitive_opertype (default netadmin) see the raw IP and geo/ASN;
lower opers see a 🔒 restricted redaction. Logs keep the full line.