From 73f8ff58edcb35e20820a665945c704cea9d1f5b Mon Sep 17 00:00:00 2001 From: reverse Date: Mon, 17 Aug 2026 19:38:58 +0000 Subject: [PATCH] s2s: enforce servprotect on a remote KILL and rank-vs-victim on a remote KICK (matching the local paths) --- src/coremods/core_channel.rs | 14 ++++++++++++++ src/coremods/core_oper.rs | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/coremods/core_channel.rs b/src/coremods/core_channel.rs index 927541d..d0a5281 100644 --- a/src/coremods/core_channel.rs +++ b/src/coremods/core_channel.rs @@ -514,6 +514,20 @@ impl Command for Kick { ); return CmdResult::Fail; } + // can't kick a remote member who out-ranks you (as for local victims) + let vrank = s.channels[&key] + .rmembers + .get(&vuuid) + .map(|m| m.rank()) + .unwrap_or(0); + if s.rank(uid, &key) < vrank { + s.numeric( + uid, + ERR_CHANOPRIVSNEEDED, + &format!("{chan} :You cannot kick a user of higher rank"), + ); + return CmdResult::Fail; + } let kicker = s.users[&uid].nick.clone(); let reason = params.get(2).cloned().unwrap_or(kicker); let prefix = s.users[&uid].prefix(); diff --git a/src/coremods/core_oper.rs b/src/coremods/core_oper.rs index c26b6e9..40b3b2b 100644 --- a/src/coremods/core_oper.rs +++ b/src/coremods/core_oper.rs @@ -182,6 +182,16 @@ impl Command for Kill { let Some(tuid) = s.find_nick(target) else { // remote target: route the KILL toward the server that owns it if let Some((uuid, _)) = s.find_remote(target) { + // servprotect (+k): a network service can't be killed, even remotely + let protected = s.uuid_is_service(&uuid) + || s.remote_users + .get(&uuid) + .map(|r| r.modes.contains('k')) + .unwrap_or(false); + if protected { + s.numeric(uid, ERR_NOPRIVILEGES, ":You cannot KILL a network service"); + return CmdResult::Fail; + } let (killer_uuid, killer) = s .users .get(&uid)