diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 5d709b1a..cfdb9a3d 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -74,7 +74,7 @@ pub const KV_RATE_LIMIT_RCPT: u8 = 2; pub const KV_RATE_LIMIT_SCAN: u8 = 3; pub const KV_RATE_LIMIT_LOITER: u8 = 4; pub const KV_RATE_LIMIT_AUTH: u8 = 5; -pub const KV_RATE_LIMIT_HASH: u8 = 6; +pub const KV_RATE_LIMIT_SMTP: u8 = 6; pub const KV_RATE_LIMIT_CONTACT: u8 = 7; pub const KV_RATE_LIMIT_HTTP_AUTHENTICATED: u8 = 8; pub const KV_RATE_LIMIT_HTTP_ANONYMOUS: u8 = 9; diff --git a/crates/jmap/src/api/management/stores.rs b/crates/jmap/src/api/management/stores.rs index 1c8f716e..cffa9257 100644 --- a/crates/jmap/src/api/management/stores.rs +++ b/crates/jmap/src/api/management/stores.rs @@ -152,7 +152,7 @@ impl ManageStore for Server { Some("rate-scan") => vec![KV_RATE_LIMIT_SCAN].into(), Some("rate-loiter") => vec![KV_RATE_LIMIT_LOITER].into(), Some("rate-auth") => vec![KV_RATE_LIMIT_AUTH].into(), - Some("rate-hash") => vec![KV_RATE_LIMIT_HASH].into(), + Some("rate-smtp") => vec![KV_RATE_LIMIT_SMTP].into(), Some("rate-contact") => vec![KV_RATE_LIMIT_CONTACT].into(), Some("rate-http-authenticated") => { vec![KV_RATE_LIMIT_HTTP_AUTHENTICATED].into() diff --git a/crates/smtp/src/core/throttle.rs b/crates/smtp/src/core/throttle.rs index 2de1952f..0dea9808 100644 --- a/crates/smtp/src/core/throttle.rs +++ b/crates/smtp/src/core/throttle.rs @@ -8,7 +8,7 @@ use common::{ config::smtp::*, expr::{functions::ResolveVariable, *}, listener::SessionStream, - ThrottleKey, KV_RATE_LIMIT_HASH, + ThrottleKey, KV_RATE_LIMIT_SMTP, }; use queue::QueueQuota; use trc::SmtpEvent; @@ -17,11 +17,11 @@ use utils::config::Rate; use super::Session; pub trait NewKey: Sized { - fn new_key(&self, e: &impl ResolveVariable) -> ThrottleKey; + fn new_key(&self, e: &impl ResolveVariable, context: &str) -> ThrottleKey; } impl NewKey for QueueQuota { - fn new_key(&self, e: &impl ResolveVariable) -> ThrottleKey { + fn new_key(&self, e: &impl ResolveVariable, _: &str) -> ThrottleKey { let mut hasher = blake3::Hasher::new(); if (self.keys & THROTTLE_RCPT) != 0 { @@ -72,7 +72,7 @@ impl NewKey for QueueQuota { } impl NewKey for QueueRateLimiter { - fn new_key(&self, e: &impl ResolveVariable) -> ThrottleKey { + fn new_key(&self, e: &impl ResolveVariable, context: &str) -> ThrottleKey { let mut hasher = blake3::Hasher::new(); if (self.keys & THROTTLE_RCPT) != 0 { @@ -129,8 +129,9 @@ impl NewKey for QueueRateLimiter { if (self.keys & THROTTLE_LOCAL_IP) != 0 { hasher.update(e.resolve_variable(V_LOCAL_IP).to_string().as_bytes()); } - hasher.update(&self.rate.period.as_secs().to_ne_bytes()[..]); - hasher.update(&self.rate.requests.to_ne_bytes()[..]); + hasher.update(&self.rate.period.as_secs().to_be_bytes()[..]); + hasher.update(&self.rate.requests.to_be_bytes()[..]); + hasher.update(context.as_bytes()); ThrottleKey { hash: hasher.finalize().into(), @@ -170,7 +171,7 @@ impl Session { } // Build throttle key - let key = t.new_key(self); + let key = t.new_key(self, "inbound"); // Check rate match self @@ -178,7 +179,7 @@ impl Session { .core .storage .lookup - .is_rate_allowed(KV_RATE_LIMIT_HASH, key.hash.as_slice(), &t.rate, false) + .is_rate_allowed(KV_RATE_LIMIT_SMTP, key.hash.as_slice(), &t.rate, false) .await { Ok(Some(_)) => { @@ -220,7 +221,7 @@ impl Session { .storage .lookup .is_rate_allowed( - KV_RATE_LIMIT_HASH, + KV_RATE_LIMIT_SMTP, hasher.finalize().as_bytes(), rate, false, diff --git a/crates/smtp/src/queue/quota.rs b/crates/smtp/src/queue/quota.rs index 73f65380..f701a414 100644 --- a/crates/smtp/src/queue/quota.rs +++ b/crates/smtp/src/queue/quota.rs @@ -129,7 +129,7 @@ impl HasQueueQuota for Server { .await .unwrap_or(false) { - let key = quota.new_key(envelope); + let key = quota.new_key(envelope, ""); if let Some(max_size) = quota.size { let used_size = self .core diff --git a/crates/smtp/src/queue/throttle.rs b/crates/smtp/src/queue/throttle.rs index 51560dd0..9a4dba30 100644 --- a/crates/smtp/src/queue/throttle.rs +++ b/crates/smtp/src/queue/throttle.rs @@ -7,7 +7,7 @@ use std::future::Future; use common::{ - config::smtp::QueueRateLimiter, expr::functions::ResolveVariable, Server, KV_RATE_LIMIT_HASH, + config::smtp::QueueRateLimiter, expr::functions::ResolveVariable, Server, KV_RATE_LIMIT_SMTP, }; use store::write::now; @@ -37,13 +37,13 @@ impl IsAllowed for Server { .await .unwrap_or(false) { - let key = throttle.new_key(envelope); + let key = throttle.new_key(envelope, "outbound"); match self .core .storage .lookup - .is_rate_allowed(KV_RATE_LIMIT_HASH, key.as_ref(), &throttle.rate, false) + .is_rate_allowed(KV_RATE_LIMIT_SMTP, key.as_ref(), &throttle.rate, false) .await { Ok(Some(next_refill)) => { diff --git a/crates/store/src/backend/http/lookup.rs b/crates/store/src/backend/http/lookup.rs index 5d835062..b817eab3 100644 --- a/crates/store/src/backend/http/lookup.rs +++ b/crates/store/src/backend/http/lookup.rs @@ -41,9 +41,19 @@ impl HttpStoreGet for Arc { fn contains(&self, key: &str) -> bool { #[cfg(feature = "test_mode")] { - if key.contains("open") || key.contains("tank") { + if self.config.url.contains("phishtank.com") + || self.config.url.contains("openphish.com") + { return (self.config.url.contains("open") && key.contains("open")) || (self.config.url.contains("tank") && key.contains("tank")); + } else if self.config.url.contains("disposable.github.io") { + return key.ends_with("guerrillamail.com") || key.ends_with("disposable.org"); + } else if self.config.url.contains("free_email_provider_domains.txt") { + return key.ends_with("gmail.com") + || key.ends_with("googlemail.com") + || key.ends_with("yahoomail.com") + || key.ends_with("outlook.com") + || key.ends_with("freemail.org"); } } diff --git a/tests/src/smtp/inbound/antispam.rs b/tests/src/smtp/inbound/antispam.rs index 6526f0a9..f0ce9276 100644 --- a/tests/src/smtp/inbound/antispam.rs +++ b/tests/src/smtp/inbound/antispam.rs @@ -119,8 +119,6 @@ allow-invalid-certs = true "url-redirectors" = {"bit.ly", "redirect.io", "redirect.me", "redirect.org", "redirect.com", "redirect.net", "t.ly", "tinyurl.com"} "spam-traps" = {"spamtrap@*"} "trusted-domains" = {"stalw.art"} -"freemail-providers" = {"gmail.com", "googlemail.com", "yahoomail.com", "outlook.com", "*freemail.org"} -"disposable-providers" = {"guerrillamail.com", "*disposable.org"} "surbl-hashbl" = {"bit.ly", "drive.google.com", "lnkiy.in"} "#;