From b34ae037f6c73dbd94662552f47b694b5a897538 Mon Sep 17 00:00:00 2001 From: Jean Date: Sun, 19 Jul 2026 20:28:24 +0000 Subject: [PATCH] Validate SCRAM cost floor, saturate expiry math, hide-oper service default --- src/config.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/config.rs b/src/config.rs index 2a0e3ec..a306197 100644 --- a/src/config.rs +++ b/src/config.rs @@ -146,14 +146,14 @@ pub struct Expire { impl Expire { // The thresholds in seconds, or None where that kind is disabled (zero days). pub fn account_ttl(&self) -> Option { - (self.accounts_days > 0).then(|| self.accounts_days * 86_400) + (self.accounts_days > 0).then(|| self.accounts_days.saturating_mul(86_400)) } pub fn channel_ttl(&self) -> Option { - (self.channels_days > 0).then(|| self.channels_days * 86_400) + (self.channels_days > 0).then(|| self.channels_days.saturating_mul(86_400)) } // The warning lead time in seconds, or None if warnings are off. pub fn warn_ttl(&self) -> Option { - (self.warn_days > 0).then(|| self.warn_days * 86_400) + (self.warn_days > 0).then(|| self.warn_days.saturating_mul(86_400)) } } @@ -400,7 +400,7 @@ fn default_services_channel() -> String { } fn default_service_modes() -> String { - "ikBT".to_string() + "iHkBT".to_string() // invisible, hideoper, servprotect, bot, block-CTCP (matches the doc above) } fn default_service_oper_type() -> String { @@ -440,6 +440,11 @@ impl Config { if self.uplink.host.trim().is_empty() { anyhow::bail!("uplink.host must not be empty"); } + // A too-low PBKDF2 cost (notably a stray 0) would silently mint near-plaintext + // SCRAM verifiers for every new registration; refuse it loudly. + if self.server.scram_iterations < 1000 { + anyhow::bail!("server.scram_iterations = {} is too low (use at least 1000; default {})", self.server.scram_iterations, default_scram_iterations()); + } Ok(()) } }