From 99eb9c74f3d7dab46ca792257a36d46ccdd16397 Mon Sep 17 00:00:00 2001 From: reverse Date: Mon, 17 Aug 2026 19:06:17 +0000 Subject: [PATCH] relaymsg: gate RELAYMSG on oper (it spoofs an arbitrary source nick), matching InspIRCd --- echoircd.conf.example | 4 ++-- src/modules/relaymsg.rs | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/echoircd.conf.example b/echoircd.conf.example index 2539d35..7a6de0a 100644 --- a/echoircd.conf.example +++ b/echoircd.conf.example @@ -261,8 +261,8 @@ amu_target = both # --- extbanbanlist: no config — adds the matching extban # `b:<#channel>`, so `+b b:#staff` catches everyone banned in #staff (shares a # ban list between channels). -# --- relaymsg (draft/relaymsg): a member whose client negotiated the -# capability can /RELAYMSG <#chan> to speak under a spoofed relay +# --- relaymsg (draft/relaymsg): an OPERATOR whose client negotiated the capability +# and who is in the channel can /RELAYMSG <#chan> to speak under a spoofed relay # nick (for bridges). The nick must contain a separator and not collide. # relaymsg_separators = / # relaymsg_ident = relay diff --git a/src/modules/relaymsg.rs b/src/modules/relaymsg.rs index 88762f6..70a4df7 100644 --- a/src/modules/relaymsg.rs +++ b/src/modules/relaymsg.rs @@ -1,6 +1,8 @@ -//! relaymsg — `RELAYMSG ` (IRCv3 `draft/relaymsg`): a member -//! whose client negotiated the capability sends a channel message under a spoofed -//! "relay" nick (e.g. `discord/alice`), for stateless bridges. The message is +//! relaymsg — `RELAYMSG ` (IRCv3 `draft/relaymsg`): an +//! operator whose client negotiated the capability, and who is in the channel, +//! sends a channel message under a spoofed "relay" nick (e.g. `discord/alice`), for +//! stateless bridges (operator-only, as in InspIRCd — the source nick is spoofed). +//! The message is //! tagged `@draft/relaymsg=` so clients can attribute it. The spoofed nick //! must contain a configured separator and must not collide with a real nick. //! @@ -35,6 +37,16 @@ impl Command for RelayMsg { CmdResult::Fail }; + // RELAYMSG spoofs an arbitrary source nick, so it's operator-only (as in + // InspIRCd, CmdAccess::OPERATOR) — bridges run their relay as an oper. + if !s.is_oper(uid) { + s.numeric( + uid, + ERR_NOPRIVILEGES, + ":Permission Denied- RELAYMSG is for IRC operators", + ); + return CmdResult::Fail; + } if !s.users.get(&uid).map(|u| u.caps.relaymsg).unwrap_or(false) { s.numeric( uid,