snoop: connect notice includes port, sni and account (present fields only)

This commit is contained in:
Jean Chevronnet 2026-08-25 00:06:22 +00:00
parent a587d25873
commit 6e8d6c31fb
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
6 changed files with 28 additions and 6 deletions

View file

@ -2828,6 +2828,7 @@ mod tests {
secure: false, secure: false,
certfp: None, certfp: None,
tls_info: None, tls_info: None,
sni: None,
brand_server: None, brand_server: None,
brand_network: None, brand_network: None,
account: None, account: None,
@ -2920,6 +2921,7 @@ mod tests {
secure: false, secure: false,
certfp: None, certfp: None,
tls_info: None, tls_info: None,
sni: None,
brand_server: None, brand_server: None,
brand_network: None, brand_network: None,
account: None, account: None,

View file

@ -375,6 +375,7 @@ mod tests {
secure: false, secure: false,
certfp: None, certfp: None,
tls_info: None, tls_info: None,
sni: None,
brand_server: None, brand_server: None,
brand_network: None, brand_network: None,
account: Some("reverse".into()), account: Some("reverse".into()),

View file

@ -12,15 +12,30 @@ impl Module for Snoop {
"snoop" "snoop"
} }
fn on_user_connect(&mut self, srv: &mut Server, uid: Uid) { fn on_user_connect(&mut self, srv: &mut Server, uid: Uid) {
let info = srv let info = srv.users.get(&uid).map(|u| {
.users (
.get(&uid) u.nick.clone(),
.map(|u| (u.nick.clone(), u.ident.clone(), u.host.clone())); u.ident.clone(),
if let Some((nick, ident, host)) = info { u.host.clone(),
u.port,
u.sni.clone(),
u.account.clone(),
)
});
if let Some((nick, ident, host, port, sni, account)) = info {
if srv.conf_bool("snoop_stderr", false) { if srv.conf_bool("snoop_stderr", false) {
eprintln!("[snoop] connect {nick} ({ident}@{host})"); eprintln!("[snoop] connect {nick} ({ident}@{host})");
} }
srv.snotice_c('c', &format!("Client connecting: {nick} ({ident}@{host})")); // port is always shown; sni/account only when present, so plaintext or
// anonymous connects don't carry empty fields.
let mut extra = format!(", port: {port}");
if let Some(sni) = &sni {
extra.push_str(&format!(", sni: {sni}"));
}
if let Some(acct) = &account {
extra.push_str(&format!(", account: {acct}"));
}
srv.snotice_c('c', &format!("Client connecting: {nick} ({ident}@{host}){extra}"));
} }
} }
fn on_join(&mut self, srv: &mut Server, uid: Uid, chan: &str) { fn on_join(&mut self, srv: &mut Server, uid: Uid, chan: &str) {

View file

@ -75,6 +75,7 @@ impl Node {
secure: false, secure: false,
certfp: None, certfp: None,
tls_info: None, tls_info: None,
sni: None,
brand_server: None, brand_server: None,
brand_network: None, brand_network: None,
account: None, account: None,

View file

@ -412,6 +412,7 @@ impl Server {
secure, secure,
certfp, certfp,
tls_info, tls_info,
sni,
brand_server, brand_server,
brand_network, brand_network,
account: None, account: None,
@ -1585,6 +1586,7 @@ mod tests {
secure: false, secure: false,
certfp: None, certfp: None,
tls_info: None, tls_info: None,
sni: None,
brand_server: None, brand_server: None,
brand_network: None, brand_network: None,
account: None, account: None,

View file

@ -231,6 +231,7 @@ pub struct User {
pub secure: bool, // connected over TLS (drives WHOIS 671 / sslinfo) pub secure: bool, // connected over TLS (drives WHOIS 671 / sslinfo)
pub certfp: Option<String>, // TLS client-cert fingerprint (SASL EXTERNAL / CertFP) pub certfp: Option<String>, // TLS client-cert fingerprint (SASL EXTERNAL / CertFP)
pub tls_info: Option<String>, // negotiated TLS version/group/cipher (WHOIS 671) pub tls_info: Option<String>, // negotiated TLS version/group/cipher (WHOIS 671)
pub sni: Option<String>, // TLS SNI hostname the client requested (connect notice)
pub brand_server: Option<String>, // per-SNI display server name (None = global) pub brand_server: Option<String>, // per-SNI display server name (None = global)
pub brand_network: Option<String>, // per-SNI display network name (None = global) pub brand_network: Option<String>, // per-SNI display network name (None = global)
pub account: Option<String>, // logged-in account name (set by services) pub account: Option<String>, // logged-in account name (set by services)