Warn an oper whose TLS cert fingerprint isn't on their account
All checks were successful
CI / check (push) Successful in 5m31s
All checks were successful
CI / check (push) Successful in 5m31s
This commit is contained in:
parent
cb552c04b0
commit
45f45a46b9
9 changed files with 50 additions and 7 deletions
|
|
@ -1657,7 +1657,21 @@ impl Engine {
|
|||
}
|
||||
NetEvent::OperUp { uid, oper_type } => {
|
||||
let what = if oper_type.is_empty() { "opered up".to_string() } else { format!("opered up as \x02{oper_type}\x02") };
|
||||
self.notify_line('o', &uid, None, &what).into_iter().collect()
|
||||
let mut out: Vec<NetAction> = self.notify_line('o', &uid, None, &what).into_iter().collect();
|
||||
// #556: once linked (not on the burst), warn an oper who authed with a
|
||||
// TLS cert that isn't on their account — the ircd only checks the oper
|
||||
// block, never the account's own cert list.
|
||||
if self.synced {
|
||||
if let (Some(ns), Some(account), Some(fp)) = (self.nick_service.clone(), self.network.account_of(&uid).map(str::to_string), self.network.fingerprint_of(&uid).map(|f| f.to_ascii_lowercase())) {
|
||||
let certs = self.db.certfps(&account);
|
||||
if !certs.is_empty() && !certs.contains(&fp) {
|
||||
let lang = self.lang_for_uid(&uid);
|
||||
let text = echo_api::render(&lang, "You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \x02/msg NickServ CERT ADD\x02.", &[]);
|
||||
out.push(NetAction::Notice { from: ns, to: uid.clone(), text });
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
NetEvent::UserKilled { uid } => {
|
||||
// A killed service agent (NickServ, ChanServ, …) has a fixed uid;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,11 @@ impl Network {
|
|||
}
|
||||
}
|
||||
|
||||
// A user's TLS cert fingerprint, if they presented one on connect.
|
||||
pub fn fingerprint_of(&self, uid: &str) -> Option<&str> {
|
||||
self.users.get(uid).map(|u| u.fingerprint.as_str()).filter(|f| !f.is_empty())
|
||||
}
|
||||
|
||||
// Record a server's name for its SID, so the `server` extban can resolve which
|
||||
// server a user is on (their uid's SID prefix).
|
||||
pub fn set_server_name(&mut self, sid: &str, name: String) {
|
||||
|
|
|
|||
|
|
@ -5318,6 +5318,24 @@
|
|||
}
|
||||
|
||||
// Logging out reverses a services vhost, restoring the connect-time host (the
|
||||
// On oper-up, echo warns a user whose TLS cert isn't on their account's list —
|
||||
// but only after the burst, and not when the cert is registered.
|
||||
#[test]
|
||||
fn oper_up_warns_on_a_certfp_not_on_the_account() {
|
||||
let mut e = engine_with("certwarn", "alice", "sesame");
|
||||
e.db.certfp_add("alice", &"a".repeat(64)).unwrap();
|
||||
e.handle(NetEvent::EndBurst); // arm the warning (synced)
|
||||
e.handle(NetEvent::UserConnect { uid: "000AAAAAB".into(), nick: "alice".into(), host: "h".into(), ip: "0.0.0.0".into() });
|
||||
e.handle(NetEvent::Privmsg { msgid: None, from: "000AAAAAB".into(), to: "42SAAAAAA".into(), text: "IDENTIFY sesame".into() });
|
||||
e.handle(NetEvent::UserCert { uid: "000AAAAAB".into(), fp: "b".repeat(64) });
|
||||
let out = e.handle(NetEvent::OperUp { uid: "000AAAAAB".into(), oper_type: "NetAdmin".into() });
|
||||
assert!(out.iter().any(|a| matches!(a, NetAction::Notice { to, text, .. } if to == "000AAAAAB" && text.contains("isn't on your account"))), "warns on a mismatched cert: {out:?}");
|
||||
// With the registered cert, no warning.
|
||||
e.handle(NetEvent::UserCert { uid: "000AAAAAB".into(), fp: "a".repeat(64) });
|
||||
let out = e.handle(NetEvent::OperUp { uid: "000AAAAAB".into(), oper_type: "NetAdmin".into() });
|
||||
assert!(!out.iter().any(|a| matches!(a, NetAction::Notice { text, .. } if text.contains("isn't on your account"))), "no warning with a registered cert: {out:?}");
|
||||
}
|
||||
|
||||
// When an oper deopers, the ircd leaves the oper vhost in place; echo puts the
|
||||
// connect-time cloak back (or the services vhost, if one is assigned).
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue