usermodes: gate the oper-only flags (+W showwhois, +H hideoper, +h helpop, +s snomask) behind is_oper — a non-oper who tries to set one now gets 481 instead of the mode silently sticking or failing without a reason
This commit is contained in:
parent
40d868f4cf
commit
370b7bc57a
1 changed files with 49 additions and 40 deletions
89
src/mode.rs
89
src/mode.rs
|
|
@ -1165,7 +1165,7 @@ static HIDECHANS: UFlag = UFlag {
|
||||||
ch: 'I',
|
ch: 'I',
|
||||||
set: set_hidechans,
|
set: set_hidechans,
|
||||||
};
|
};
|
||||||
static HIDEOPER: UFlag = UFlag {
|
static HIDEOPER: OperFlag = OperFlag {
|
||||||
ch: 'H',
|
ch: 'H',
|
||||||
set: set_hideoper,
|
set: set_hideoper,
|
||||||
};
|
};
|
||||||
|
|
@ -1181,7 +1181,7 @@ static CALLERID: UFlag = UFlag {
|
||||||
ch: 'g',
|
ch: 'g',
|
||||||
set: set_callerid,
|
set: set_callerid,
|
||||||
};
|
};
|
||||||
static SHOWWHOIS: UFlag = UFlag {
|
static SHOWWHOIS: OperFlag = OperFlag {
|
||||||
ch: 'W',
|
ch: 'W',
|
||||||
set: set_showwhois,
|
set: set_showwhois,
|
||||||
};
|
};
|
||||||
|
|
@ -1204,6 +1204,43 @@ impl UserMode for UFlag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_helpop(f: &mut UserFlags, v: bool) {
|
||||||
|
f.helpop = v;
|
||||||
|
}
|
||||||
|
fn set_snomask(f: &mut UserFlags, v: bool) {
|
||||||
|
f.snomask = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An oper-only boolean flag (+H / +W / +h / +s): only an operator may **set** it;
|
||||||
|
/// anyone may clear it. A non-oper who tries to set it is told they aren't an
|
||||||
|
/// operator (`ERR_NOPRIVILEGES`) and the flag is left off — it never silently
|
||||||
|
/// "sticks" with no effect.
|
||||||
|
struct OperFlag {
|
||||||
|
ch: char,
|
||||||
|
set: fn(&mut UserFlags, bool),
|
||||||
|
}
|
||||||
|
impl UserMode for OperFlag {
|
||||||
|
fn letter(&self) -> char {
|
||||||
|
self.ch
|
||||||
|
}
|
||||||
|
fn apply(&self, s: &mut Server, uid: Uid, adding: bool) -> bool {
|
||||||
|
if adding && !s.is_oper(uid) {
|
||||||
|
s.numeric(
|
||||||
|
uid,
|
||||||
|
ERR_NOPRIVILEGES,
|
||||||
|
":Permission Denied- You're not an IRC operator",
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if let Some(u) = s.users.get_mut(&uid) {
|
||||||
|
(self.set)(&mut u.flags, adding);
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// `+o` is granted only by OPER; a user may `-o` (de-oper) themselves.
|
/// `+o` is granted only by OPER; a user may `-o` (de-oper) themselves.
|
||||||
struct OperMode;
|
struct OperMode;
|
||||||
static OPER: OperMode = OperMode;
|
static OPER: OperMode = OperMode;
|
||||||
|
|
@ -1227,26 +1264,12 @@ impl UserMode for OperMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `+h` — helpop: marks a user as available for help (shown in WHOIS). Only opers
|
/// `+h` — helpop: marks a user as available for help (shown in WHOIS). Oper-only to
|
||||||
/// may set it on themselves; anyone may clear it.
|
/// set; anyone may clear it.
|
||||||
struct HelpMode;
|
static HELPOP: OperFlag = OperFlag {
|
||||||
static HELPOP: HelpMode = HelpMode;
|
ch: 'h',
|
||||||
impl UserMode for HelpMode {
|
set: set_helpop,
|
||||||
fn letter(&self) -> char {
|
};
|
||||||
'h'
|
|
||||||
}
|
|
||||||
fn apply(&self, s: &mut Server, uid: Uid, adding: bool) -> bool {
|
|
||||||
if adding && !s.is_oper(uid) {
|
|
||||||
return false; // only opers may declare themselves a helpop
|
|
||||||
}
|
|
||||||
if let Some(u) = s.users.get_mut(&uid) {
|
|
||||||
u.flags.helpop = adding;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `+x` — host cloaking. The cloak string is computed once at connect by
|
/// `+x` — host cloaking. The cloak string is computed once at connect by
|
||||||
/// [`crate::modules::cloak`]; this handler only toggles whether it's shown.
|
/// [`crate::modules::cloak`]; this handler only toggles whether it's shown.
|
||||||
|
|
@ -1312,24 +1335,10 @@ impl UserMode for RegisteredMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `+s` — server-notice (snomask) receiver. Oper-only to set; anyone may drop it.
|
/// `+s` — server-notice (snomask) receiver. Oper-only to set; anyone may drop it.
|
||||||
struct SnoMode;
|
static SNOMASK: OperFlag = OperFlag {
|
||||||
static SNOMASK: SnoMode = SnoMode;
|
ch: 's',
|
||||||
impl UserMode for SnoMode {
|
set: set_snomask,
|
||||||
fn letter(&self) -> char {
|
};
|
||||||
's'
|
|
||||||
}
|
|
||||||
fn apply(&self, s: &mut Server, uid: Uid, adding: bool) -> bool {
|
|
||||||
if adding && !s.is_oper(uid) {
|
|
||||||
return false; // only operators receive server notices
|
|
||||||
}
|
|
||||||
if let Some(u) = s.users.get_mut(&uid) {
|
|
||||||
u.flags.snomask = adding;
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue