Source channel mode changes from ChanServ
Channel modes (+r, mode lock, auto-op, enforcement) are sent from the ChanServ pseudoclient instead of the services server, so users see ChanServ as the setter. The engine locates the channel-managing service; the FMODE filter now ignores anything under our SID prefix (server and pseudoclients) so enforcement can't loop on our own changes.
This commit is contained in:
parent
e785c9d8ac
commit
f15c9998be
5 changed files with 47 additions and 22 deletions
|
|
@ -122,7 +122,8 @@ impl Protocol for InspIrcd {
|
|||
"FMODE" => {
|
||||
let a: Vec<&str> = tokens.collect();
|
||||
match (source.as_deref(), a.first(), a.get(2)) {
|
||||
(Some(src), Some(chan), Some(modes)) if src != self.sid && chan.starts_with('#') => {
|
||||
// Our own uids (server SID + pseudoclients) share our SID prefix.
|
||||
(Some(src), Some(chan), Some(modes)) if !src.starts_with(self.sid.as_str()) && chan.starts_with('#') => {
|
||||
vec![NetEvent::ChannelModeChange { channel: chan.to_string(), modes: modes.to_string() }]
|
||||
}
|
||||
_ => vec![],
|
||||
|
|
@ -218,10 +219,16 @@ impl Protocol for InspIrcd {
|
|||
vec![self.from_us(format!("SVSNICK {} {} {}", uid, nick, now))]
|
||||
}
|
||||
// FMODE <chan> <ts> <modes>. The ircd drops an FMODE whose TS is newer
|
||||
// than the channel's, so we send TS 1 to guarantee it applies to the
|
||||
// existing channel. Sourced from our server, which +r requires.
|
||||
NetAction::ChannelMode { channel, modes } => {
|
||||
vec![self.from_us(format!("FMODE {} 1 {}", channel, modes))]
|
||||
// than the channel's, so we send TS 1 to guarantee it applies. Sourced
|
||||
// from the given pseudoclient (e.g. ChanServ) so users see who set it,
|
||||
// or from the services server when `from` is empty.
|
||||
NetAction::ChannelMode { from, channel, modes } => {
|
||||
let cmd = format!("FMODE {} 1 {}", channel, modes);
|
||||
if from.is_empty() {
|
||||
vec![self.from_us(cmd)]
|
||||
} else {
|
||||
vec![format!(":{} {}", from, cmd)]
|
||||
}
|
||||
}
|
||||
NetAction::Raw(s) => vec![s.clone()],
|
||||
// Internal: the link layer handles this before serialization.
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@ pub enum NetAction {
|
|||
// Force a user's nick (SVSNICK), e.g. renaming to a guest nick on logout.
|
||||
// The protocol stamps the new nick's timestamp.
|
||||
ForceNick { uid: String, nick: String },
|
||||
// Set channel modes from services, e.g. +r on a registered channel. The
|
||||
// Set channel modes from services, e.g. +r on a registered channel. `from` is
|
||||
// the pseudoclient uid to source it from (empty = the services server). The
|
||||
// protocol stamps a timestamp the ircd will accept.
|
||||
ChannelMode { channel: String, modes: String },
|
||||
ChannelMode { from: String, channel: String, modes: String },
|
||||
Raw(String),
|
||||
// Internal only, never serialized to the wire: a registration whose password
|
||||
// still needs its (expensive) key derivation. The link layer runs the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue