Report failed IDENTIFY against a password-less account to the auth feed
All checks were successful
CI / check (push) Successful in 4m10s

This commit is contained in:
Jean Chevronnet 2026-07-19 05:00:12 +00:00
parent 876bc55e2b
commit 1ecb76affb
No known key found for this signature in database
3 changed files with 38 additions and 0 deletions

View file

@ -485,6 +485,21 @@ pub struct ServiceCtx {
// engine drains these to the log channel, prefixing the sender's nick/host —
// e.g. a blocked look-alike registration attempt.
pub alerts: Vec<(String, String)>,
// Login-attempt outcomes for the auth audit feed. The engine drains these
// through its own auth_report (which resolves the client's source), so a
// module can report a reject the engine's verify path never sees — e.g. a
// failed IDENTIFY against a cert-only account with no password verifier.
pub auth_reports: Vec<AuthReport>,
}
// A login-attempt outcome a module hands back for the auth audit feed.
#[derive(Default)]
pub struct AuthReport {
pub ok: bool,
pub account: Option<String>,
pub mech: String,
pub client: String,
pub reason: Option<String>,
}
impl ServiceCtx {
@ -536,6 +551,19 @@ impl ServiceCtx {
self.alerts.push((category.into(), text.into()));
}
// Report a login-attempt outcome to the auth audit feed. For a reject the
// engine's own verify path won't produce (a failed IDENTIFY against an account
// with no password verifier), so operators see it like any other failed login.
pub fn auth_report(&mut self, ok: bool, account: Option<&str>, mech: &str, client: &str, reason: Option<&str>) {
self.auth_reports.push(AuthReport {
ok,
account: account.map(String::from),
mech: mech.to_string(),
client: client.to_string(),
reason: reason.map(String::from),
});
}
// A channel/target message sourced from one of our pseudo-clients (e.g. a
// bot answering a fantasy command, or BotServ SAY).
pub fn privmsg(&mut self, from: &str, to: &str, text: impl Into<String>) {