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
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nÜberträgt den Gründer oder ändert eine Kanaleinstellung.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nÜberträgt den Gründer oder ändert eine Kanaleinstellung.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Dein Konto ist ausstehend. Bitte ein bestehendes Mitglied, mit \u0002/msg NickServ VOUCH {account}\u0002 für dich zu bürgen.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Dein Konto ist ausstehend. Bitte ein bestehendes Mitglied, mit \u0002/msg NickServ VOUCH {account}\u0002 für dich zu bürgen.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Du hast für \u0002{account}\u0002 gebürgt; das Konto ist jetzt aktiv.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Du hast für \u0002{account}\u0002 gebürgt; das Konto ist jetzt aktiv.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Dein Gegner hat die Verbindung getrennt. Spiel \u0002#{id}\u0002 ist vorbei."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Dein Gegner hat die Verbindung getrennt. Spiel \u0002#{id}\u0002 ist vorbei.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Du hast dich mit einem TLS-Zertifikat-Fingerabdruck geopert, der nicht in deinem Konto hinterlegt ist. Füge ihn mit \u0002/msg NickServ CERT ADD\u0002 hinzu."
|
||||||
}
|
}
|
||||||
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxis: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfiere el fundador o cambia un ajuste del canal.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxis: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfiere el fundador o cambia un ajuste del canal.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Tu cuenta está pendiente. Pedile a un miembro existente que te avale con \u0002/msg NickServ VOUCH {account}\u0002.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Tu cuenta está pendiente. Pedile a un miembro existente que te avale con \u0002/msg NickServ VOUCH {account}\u0002.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalaste a \u0002{account}\u0002; su cuenta ya está activa.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalaste a \u0002{account}\u0002; su cuenta ya está activa.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Tu oponente se fue. La partida \u0002#{id}\u0002 terminó."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Tu oponente se fue. La partida \u0002#{id}\u0002 terminó.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Te hiciste operador con una huella de certificado TLS que no está en tu cuenta. Agregala con \u0002/msg NickServ CERT ADD\u0002."
|
||||||
}
|
}
|
||||||
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxis: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfiere el fundador o cambia un ajuste del canal.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxis: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfiere el fundador o cambia un ajuste del canal.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Tu cuenta está pendiente. Pide a un miembro existente que te avale con \u0002/msg NickServ VOUCH {account}\u0002.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Tu cuenta está pendiente. Pide a un miembro existente que te avale con \u0002/msg NickServ VOUCH {account}\u0002.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalaste a \u0002{account}\u0002; su cuenta ya está activa.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalaste a \u0002{account}\u0002; su cuenta ya está activa.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Tu oponente se fue. La partida \u0002#{id}\u0002 terminó."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Tu oponente se fue. La partida \u0002#{id}\u0002 terminó.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Te has hecho operador con una huella de certificado TLS que no está en tu cuenta. Añádela con \u0002/msg NickServ CERT ADD\u0002."
|
||||||
}
|
}
|
||||||
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Syntaxe : \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfère le fondateur ou modifie un réglage du salon.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Syntaxe : \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfère le fondateur ou modifie un réglage du salon.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Votre compte est en attente. Demandez à un membre existant de vous parrainer avec \u0002/msg NickServ VOUCH {account}\u0002.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Votre compte est en attente. Demandez à un membre existant de vous parrainer avec \u0002/msg NickServ VOUCH {account}\u0002.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Vous avez parrainé \u0002{account}\u0002 ; son compte est maintenant actif.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Vous avez parrainé \u0002{account}\u0002 ; son compte est maintenant actif.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Ton adversaire est parti. La partie \u0002#{id}\u0002 est terminée."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Ton adversaire est parti. La partie \u0002#{id}\u0002 est terminée.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Vous êtes passé opérateur avec une empreinte de certificat TLS absente de votre compte. Ajoutez-la avec \u0002/msg NickServ CERT ADD\u0002."
|
||||||
}
|
}
|
||||||
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxe: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfere o fundador ou altera uma configuração do canal.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxe: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfere o fundador ou altera uma configuração do canal.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Sua conta está pendente. Peça a um membro existente para avalizar você com \u0002/msg NickServ VOUCH {account}\u0002.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "Sua conta está pendente. Peça a um membro existente para avalizar você com \u0002/msg NickServ VOUCH {account}\u0002.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Você avalizou \u0002{account}\u0002; a conta agora está ativa.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Você avalizou \u0002{account}\u0002; a conta agora está ativa.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Seu oponente saiu. O jogo \u0002#{id}\u0002 acabou."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "Seu oponente saiu. O jogo \u0002#{id}\u0002 acabou.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Você virou operador com uma impressão digital de certificado TLS que não está na sua conta. Adicione-a com \u0002/msg NickServ CERT ADD\u0002."
|
||||||
}
|
}
|
||||||
|
|
@ -1373,5 +1373,6 @@
|
||||||
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxe: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfere o fundador ou altera uma definição do canal.",
|
"Syntax: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfers the founder or changes a channel setting.": "Sintaxe: \u0002SET <#channel> FOUNDER <account> | DESC <text> | URL [address] | EMAIL [address] | SUCCESSOR <account>|OFF | SIGNKICK|PRIVATE|PEACE|SECUREOPS|SECUREVOICES|RESTRICTED|AUTOOP|KEEPTOPIC|TOPICLOCK {ON|OFF}\u0002\nTransfere o fundador ou altera uma definição do canal.",
|
||||||
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "A sua conta está pendente. Peça a um membro existente que o avalize com \u0002/msg NickServ VOUCH {account}\u0002.",
|
"Your account is pending. Ask an existing member to vouch for you with \u0002/msg NickServ VOUCH {account}\u0002.": "A sua conta está pendente. Peça a um membro existente que o avalize com \u0002/msg NickServ VOUCH {account}\u0002.",
|
||||||
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalizou \u0002{account}\u0002; a conta está agora ativa.",
|
"You vouched for \u0002{account}\u0002; their account is now active.": "Avalizou \u0002{account}\u0002; a conta está agora ativa.",
|
||||||
"Your opponent left. Game \u0002#{id}\u0002 is over.": "O teu adversário saiu. O jogo \u0002#{id}\u0002 acabou."
|
"Your opponent left. Game \u0002#{id}\u0002 is over.": "O teu adversário saiu. O jogo \u0002#{id}\u0002 acabou.",
|
||||||
|
"You opered up with a TLS certificate fingerprint that isn't on your account. Add it with \u0002/msg NickServ CERT ADD\u0002.": "Tornou-se operador com uma impressão digital de certificado TLS que não está na sua conta. Adicione-a com \u0002/msg NickServ CERT ADD\u0002."
|
||||||
}
|
}
|
||||||
|
|
@ -1657,7 +1657,21 @@ impl Engine {
|
||||||
}
|
}
|
||||||
NetEvent::OperUp { uid, oper_type } => {
|
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") };
|
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 } => {
|
NetEvent::UserKilled { uid } => {
|
||||||
// A killed service agent (NickServ, ChanServ, …) has a fixed 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
|
// 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).
|
// server a user is on (their uid's SID prefix).
|
||||||
pub fn set_server_name(&mut self, sid: &str, name: String) {
|
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
|
// 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
|
// 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).
|
// connect-time cloak back (or the services vhost, if one is assigned).
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue