OperServ: DEFCON network defence levels
DEFCON [1-5] reads or sets a network-wide defence posture, each level
adding a restriction the engine and services enforce:
- 4: channel registrations frozen (ChanServ REGISTER)
- 3: all registrations frozen (the pre_register_check choke-point, covering
NickServ and the IRCv3 relay, plus channels)
- 2: sessions additionally capped to one per host
- 1: full lockdown — new connections are turned away on connect
Setting a level announces it to the whole network. Node-local level on the
db so services can read the derived freezes; admin-only.
This commit is contained in:
parent
85d01b3ebf
commit
4c899d80b0
6 changed files with 165 additions and 4 deletions
40
operserv/src/defcon.rs
Normal file
40
operserv/src/defcon.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use fedserv_api::{Priv, Sender, ServiceCtx, Store};
|
||||
|
||||
// DEFCON [1-5]: read or set the network defence level. 5 is normal; each lower
|
||||
// level adds a restriction — 4 freezes channel registrations, 3 freezes all
|
||||
// registrations, 2 also caps everyone to one session, 1 is a full lockdown that
|
||||
// turns away new connections. Changing it announces the level to the network.
|
||||
// Admin-only.
|
||||
pub fn handle(me: &str, from: &Sender, args: &[&str], ctx: &mut ServiceCtx, db: &mut dyn Store) {
|
||||
if !from.privs.has(Priv::Admin) {
|
||||
ctx.notice(me, from.uid, "Access denied — DEFCON needs the \x02admin\x02 privilege.");
|
||||
return;
|
||||
}
|
||||
match args.get(1) {
|
||||
None => ctx.notice(me, from.uid, format!("The network is at \x02DEFCON {}\x02 — {}.", db.defcon(), describe(db.defcon()))),
|
||||
Some(&arg) => match arg.parse::<u8>() {
|
||||
Ok(level) if (1..=5).contains(&level) => {
|
||||
db.set_defcon(level);
|
||||
ctx.notice(me, from.uid, format!("DEFCON set to \x02{level}\x02 — {}.", describe(level)));
|
||||
// Let everyone know the posture changed.
|
||||
let msg = if level == 5 {
|
||||
"The network is back to normal operations (DEFCON 5).".to_string()
|
||||
} else {
|
||||
format!("Network defence level is now \x02DEFCON {level}\x02: {}.", describe(level))
|
||||
};
|
||||
ctx.global(me, msg);
|
||||
}
|
||||
_ => ctx.notice(me, from.uid, "Syntax: DEFCON [1-5] (5 = normal, 1 = lockdown)"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn describe(level: u8) -> &'static str {
|
||||
match level {
|
||||
5 => "normal operations",
|
||||
4 => "channel registrations frozen",
|
||||
3 => "all registrations frozen",
|
||||
2 => "registrations frozen and sessions capped to one per host",
|
||||
_ => "full lockdown, no new connections",
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,8 @@ mod jupe;
|
|||
mod chankill;
|
||||
#[path = "logsearch.rs"]
|
||||
mod logsearch;
|
||||
#[path = "defcon.rs"]
|
||||
mod defcon;
|
||||
|
||||
pub struct OperServ {
|
||||
pub uid: String,
|
||||
|
|
@ -80,6 +82,7 @@ impl Service for OperServ {
|
|||
Some(cmd) if cmd.eq_ignore_ascii_case("JUPE") => jupe::handle(me, from, args, ctx, db),
|
||||
Some(cmd) if cmd.eq_ignore_ascii_case("CHANKILL") => chankill::handle(me, from, args, ctx, net, db),
|
||||
Some(cmd) if cmd.eq_ignore_ascii_case("LOGSEARCH") => logsearch::handle(me, from, args, ctx, net),
|
||||
Some(cmd) if cmd.eq_ignore_ascii_case("DEFCON") => defcon::handle(me, from, args, ctx, db),
|
||||
Some(cmd) if cmd.eq_ignore_ascii_case("HELP") => help(me, from, ctx),
|
||||
None => help(me, from, ctx),
|
||||
Some(other) => ctx.notice(me, from.uid, format!("I don't know \x02{other}\x02. Try \x02HELP\x02.")),
|
||||
|
|
@ -88,5 +91,5 @@ impl Service for OperServ {
|
|||
}
|
||||
|
||||
fn help(me: &str, from: &Sender, ctx: &mut ServiceCtx) {
|
||||
ctx.notice(me, from.uid, "OperServ holds network operator tools (Priv::Admin): \x02AKILL\x02 ADD|DEL|LIST (user@host bans), \x02SQLINE\x02 ADD|DEL|LIST (nick bans), \x02SNLINE\x02 ADD|DEL|LIST (realname bans), \x02SHUN\x02 ADD|DEL|LIST (silence a host), \x02CBAN\x02 ADD|DEL|LIST (ban a channel name), \x02CHANKILL\x02 <#chan> (clear a channel), \x02GLOBAL\x02 <message> (announce to everyone), \x02KILL\x02 <nick> [reason] (disconnect a user), \x02KICK\x02 <#chan> <nick> [reason], \x02MODE\x02 <#chan> <modes> [params], \x02IGNORE\x02 ADD|DEL|LIST (silence a user from services), \x02STATS\x02 (enforcement overview), \x02SVSNICK\x02 <nick> <newnick>, \x02SVSJOIN\x02 <nick> <#chan> [key], \x02INFO\x02 ADD|DEL <target> (staff notes), \x02NEWS\x02 ADD|DEL|LIST <LOGON|OPER> (announcements), \x02OPER\x02 ADD|DEL|LIST (runtime operators), \x02SESSION\x02 LIST|VIEW + \x02EXCEPTION\x02 ADD|DEL|LIST (per-IP session limits), \x02JUPE\x02 <server> | DEL | LIST, \x02LOGSEARCH\x02 [pattern] (search the action log).");
|
||||
ctx.notice(me, from.uid, "OperServ holds network operator tools (Priv::Admin): \x02AKILL\x02 ADD|DEL|LIST (user@host bans), \x02SQLINE\x02 ADD|DEL|LIST (nick bans), \x02SNLINE\x02 ADD|DEL|LIST (realname bans), \x02SHUN\x02 ADD|DEL|LIST (silence a host), \x02CBAN\x02 ADD|DEL|LIST (ban a channel name), \x02CHANKILL\x02 <#chan> (clear a channel), \x02GLOBAL\x02 <message> (announce to everyone), \x02KILL\x02 <nick> [reason] (disconnect a user), \x02KICK\x02 <#chan> <nick> [reason], \x02MODE\x02 <#chan> <modes> [params], \x02IGNORE\x02 ADD|DEL|LIST (silence a user from services), \x02STATS\x02 (enforcement overview), \x02SVSNICK\x02 <nick> <newnick>, \x02SVSJOIN\x02 <nick> <#chan> [key], \x02INFO\x02 ADD|DEL <target> (staff notes), \x02NEWS\x02 ADD|DEL|LIST <LOGON|OPER> (announcements), \x02OPER\x02 ADD|DEL|LIST (runtime operators), \x02SESSION\x02 LIST|VIEW + \x02EXCEPTION\x02 ADD|DEL|LIST (per-IP session limits), \x02JUPE\x02 <server> | DEL | LIST, \x02LOGSEARCH\x02 [pattern] (search the action log), \x02DEFCON\x02 [1-5] (network defence level).");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue