Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
0

Configure Feed

Select the types of activity you want to include in your feed.

ircd.rs / docs / superpowers / plans / 2026-06-18-p11-slice253-service-umode.md
4.6 kB

P11 slice 253 — +S service umode + KILL immunity#

Goal#

Add the charybdis +S (UMODE_SERVICE) user mode: a server-set-only umode (a client/oper MODE +S is silently ignored — set only on an S2S burst) whose holder is immune to an operator's KILL. The last named charybdis umode candidate in [[leveva-user-mode-wiring]] (alongside +l locops, which needs a LOCOPS command first).

Charybdis reference (cloned to /tmp/charybdis-ref, verified)#

  • include/client.h: UMODE_SERVICE 0x0040; IsService(x) = (x)->umodes & UMODE_SERVICE.
  • ircd/s_user.c umode parse switch: case 'S': (with 'Z') just break; — "can only be set on burst". Confirms server-set-only — exactly how leveva already treats +Z Secure.
  • extensions/no_kill_services.c (the can_kill hook): blocks a KILL only when MyClient(killer) (the killing oper is local) and the target IsService; reply ERR_ISCHANSERVICE (484) "KILL %s :Cannot kill a network service", sets approved = 0. An inbound server KILL is NOT blocked (a remote source fails MyClient) — services stay killable by servers (collisions/SQUIT cleanup). So leveva touches only command/kill.rs, NOT s2s/kill.rs.
  • ircd/s_serv.c burst (send_umode(NULL, target_p, 0, ubuf)): iterates the FULL user_modes[] table — no SEND_UMODES subset — so +S rides the UID introduction. +S is a global property (a service is a service network-wide), like leveva's +Z/+B/+W.

Divergences (documented)#

  • Numeric: 481 ERR_NOPRIVILEGES, not 484 ERR_ISCHANSERVICE. leveva's 484 is ErrRestricted (IRCnet meaning); charybdis reassigned 484 to ERR_ISCHANSERVICE. To avoid the collision leveva replies 481 (its existing KILL/privilege numeric) with the charybdis trailing Cannot kill a network service.
  • Bit 0x20000 (next free past +z Operwall 0x10000), not charybdis's 0x0040 (that bit is leveva's native +W Websocket). leveva bit space diverges from the oracle — standard.

Port checklist#

  1. mode.rsUserMode::Service appended last: enum, ALL (17→18), as_char 'S', bit 0x20000, flag_name "FLAGS_SERVICE", from_char, from_bit, Display. Predicate pub fn is_service(modes) -> bool.
  2. command/mode.rs umode — add 'S' to the server-set-only silently-ignored arm ('o' | 'O' | 'r' | 'a' | 'W' | 'Z' | 'S'). NOT in the self-settable group, NOT in umode_diff (server-set-only, like +Z).
  3. command/kill.rs — after the victim UID is resolved (before the remote-route and local-eject branches), if the victim is +S reply 481 "Cannot kill a network service" and eject/route nothing. Read modes from the registry record OR the net mirror (covers local + remote services).
  4. s2s/umode.rs SEND_UMODES — add UserMode::Service (network-visible global property, like +Z/+B). Update send_umodes_excludes_* (Service is in the propagates set, not the excludes matches!) and the SEND_UMODES == 61 | … assertion.
  5. 004 / ISUPPORT — bump isupport.rs::user_modes_string assert + registration.rs myinfo_004 assert: oOiwraWBxsgGZDRQzoOiwraWBxsgGZDRQzS.
  6. snapshots — 5 welcome-burst goldens gain the trailing S on the 004 line; regenerate.
  7. help — a +S row in help/USER_MODES.md (no new command → no help/<CMD>.md).

Tests (RED first)#

  • command/kill.rs units: local +S victim → 481 + not ejected (inverse: -S victim still ejected); remote +S victim → 481 + not routed; the reply trailing.
  • command/mode.rs units: a client/oper MODE self +S is silently ignored (no bit, no echo, no 501); -S likewise a no-op.
  • golden_service.rs: boot one server; a client's MODE +S is silently ignored (221 shows no S); +S cannot be self-set. (KILL immunity is unit-tested — +S needs S2S to set on a real client, untestable in a single-server golden, same constraint as +Z.)
  • service_proptest.rs (FUZZ): is_service matches & 0x20000 over arbitrary words; the bit is independent of neighbours; KILL immunity decided by +S alone; letter/bit uniqueness.

Out of scope (documented follow-ons)#

  • WHOIS servicestring (313 "is a Network Service") + channel-list hiding for services (charybdis m_whois.c) — a separate display slice.
  • +l locops umode + LOCOPS command — needs a new command first.

Gate#

cargo test -p leveva green; cargo clippy -p leveva --tests clean; cargo build --workspace 0 warnings; the 5 welcome-burst snapshots' only diff is the new S letter.