From 398878dc721e0d37150542a90c9816448cbaf057 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Wed, 14 Sep 2022 18:43:46 +0200 Subject: [PATCH 1/4] Disable sending at compile time if honeypot feature flag is set --- Cargo.lock | 1 + crates/erooster/Cargo.toml | 1 + crates/erooster_smtp/Cargo.toml | 5 ++ crates/erooster_smtp/src/commands/data.rs | 56 ++++++++++++----------- crates/erooster_smtp/src/servers/mod.rs | 16 +++++-- 5 files changed, 49 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34d1e851..9b335e27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1166,6 +1166,7 @@ version = "0.1.0" dependencies = [ "base64", "cfdkim", + "cfg-if 1.0.0", "color-eyre", "convert_case 0.6.0", "criterion 0.4.0", diff --git a/crates/erooster/Cargo.toml b/crates/erooster/Cargo.toml index 69ef7d70..62c5c775 100644 --- a/crates/erooster/Cargo.toml +++ b/crates/erooster/Cargo.toml @@ -37,6 +37,7 @@ auditable = "0.2" [features] default = [] jaeger = ["dep:opentelemetry-jaeger"] +honeypot = ["erooster_smtp/honeypot"] [build-dependencies] clap = { version = "3.1", features = ["derive", "color", "suggestions","env"] } diff --git a/crates/erooster_smtp/Cargo.toml b/crates/erooster_smtp/Cargo.toml index 9d4fa3b0..e98592c5 100644 --- a/crates/erooster_smtp/Cargo.toml +++ b/crates/erooster_smtp/Cargo.toml @@ -42,6 +42,11 @@ cfdkim = {version = "0.2.3", git = "https://github.com/erooster-mail/dkim"} time = {version = "0.3.13", features = ["formatting"]} reqwest = {version = "0.11.11", features = ["json","rustls-tls","trust-dns"]} serde_json = "1.0.85" +cfg-if = "1.0.0" + +[features] +default = [] +honeypot = [] [[bench]] name = "smtp_bench" diff --git a/crates/erooster_smtp/src/commands/data.rs b/crates/erooster_smtp/src/commands/data.rs index d315cfe0..647875d9 100644 --- a/crates/erooster_smtp/src/commands/data.rs +++ b/crates/erooster_smtp/src/commands/data.rs @@ -1,15 +1,8 @@ -use crate::{ - commands::Data, - servers::{ - sending::{send_email_job, EmailPayload}, - state::State, - }, - utils::rspamd::Response, -}; +use crate::{commands::Data, servers::state::State, utils::rspamd::Response}; use color_eyre::eyre::ContextCompat; use erooster_core::{ backend::{ - database::{Database, DB}, + database::DB, storage::{MailStorage, Storage}, }, config::{Config, Rspamd}, @@ -19,6 +12,11 @@ use std::{collections::HashMap, path::Path, sync::Arc, time::Duration}; use time::{macros::format_description, OffsetDateTime}; use tracing::{debug, instrument}; +#[cfg(not(feature = "honeypot"))] +use crate::servers::sending::{send_email_job, EmailPayload}; +#[cfg(not(feature = "honeypot"))] +use erooster_core::backend::database::Database; + #[allow(clippy::module_name_repetitions)] pub struct DataCommand<'a> { pub data: &'a Data, @@ -112,24 +110,28 @@ impl DataCommand<'_> { data }; - let email_payload = EmailPayload { - to, - from: write_lock - .sender - .clone() - .context("Missing sender in internal state")?, - body: data, - sender_domain: config.mail.hostname.clone(), - dkim_key_path: config.mail.dkim_key_path.clone(), - dkim_key_selector: config.mail.dkim_key_selector.clone(), - }; - let pool = database.get_pool(); - send_email_job - .builder() - .set_json(&email_payload)? - .spawn(pool) - .await?; - debug!("Email added to queue"); + cfg_if::cfg_if! { + if #[cfg(not(feature = "honeypot"))] { + let email_payload = EmailPayload { + to, + from: write_lock + .sender + .clone() + .context("Missing sender in internal state")?, + body: data, + sender_domain: config.mail.hostname.clone(), + dkim_key_path: config.mail.dkim_key_path.clone(), + dkim_key_selector: config.mail.dkim_key_selector.clone(), + }; + let pool = database.get_pool(); + send_email_job + .builder() + .set_json(&email_payload)? + .spawn(pool) + .await?; + debug!("Email added to queue"); + } + } } lines.send(String::from("250 OK")).await?; diff --git a/crates/erooster_smtp/src/servers/mod.rs b/crates/erooster_smtp/src/servers/mod.rs index a0ef63a5..ded697ce 100644 --- a/crates/erooster_smtp/src/servers/mod.rs +++ b/crates/erooster_smtp/src/servers/mod.rs @@ -1,4 +1,3 @@ -use crate::servers::sending::send_email_job; use erooster_core::{ backend::{ database::{Database, DB}, @@ -12,10 +11,15 @@ use std::error::Error; use std::sync::Arc; use tracing::instrument; +#[cfg(not(feature = "honeypot"))] +use crate::servers::sending::send_email_job; + pub(crate) mod encrypted; -pub(crate) mod sending; pub(crate) mod state; +#[cfg(not(feature = "honeypot"))] +pub(crate) mod sending; + // TODO make this only pub for benches and tests #[allow(missing_docs)] pub mod unencrypted; @@ -74,7 +78,13 @@ pub async fn start( let pool = database.get_pool(); // Construct a job registry from our job. - let mut registry = JobRegistry::new(&[send_email_job]); + cfg_if::cfg_if! { + if #[cfg(not(feature = "honeypot"))] { + let mut registry = JobRegistry::new(&[send_email_job]); + } else { + let mut registry = JobRegistry::new(&[]); + } + } // Here is where you can configure the registry registry.set_error_handler(|name: &str, error: Box| { tracing::error!("Job `{}` failed: {}", name, error); From 03570dbced1d2123433cb7833b7ff4b760af7088 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Wed, 14 Sep 2022 18:45:09 +0200 Subject: [PATCH 2/4] Dont verify if a user exists in honeypot mode. We literally dont care as we want things to go through --- crates/erooster_smtp/src/commands/rcpt.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/erooster_smtp/src/commands/rcpt.rs b/crates/erooster_smtp/src/commands/rcpt.rs index c0cb70d1..727e0f2b 100644 --- a/crates/erooster_smtp/src/commands/rcpt.rs +++ b/crates/erooster_smtp/src/commands/rcpt.rs @@ -36,10 +36,14 @@ impl Rcpt<'_> { { let mut write_lock = self.data.con_state.write().await; if matches!(&write_lock.state, State::NotAuthenticated) { - for receipt in &receipts { - if !database.user_exists(&receipt.to_lowercase()).await { - lines.send(String::from("550 No such user here")).await?; - return Ok(()); + cfg_if::cfg_if! { + if #[cfg(not(feature = "honeypot"))] { + for receipt in &receipts { + if !database.user_exists(&receipt.to_lowercase()).await { + lines.send(String::from("550 No such user here")).await?; + return Ok(()); + } + } } } } From 902c0b07900b79cd1642eb1cc76da2a338b5091e Mon Sep 17 00:00:00 2001 From: MTRNord Date: Wed, 14 Sep 2022 18:46:34 +0200 Subject: [PATCH 3/4] Add a todo --- crates/erooster_smtp/src/commands/data.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/erooster_smtp/src/commands/data.rs b/crates/erooster_smtp/src/commands/data.rs index 647875d9..eff88484 100644 --- a/crates/erooster_smtp/src/commands/data.rs +++ b/crates/erooster_smtp/src/commands/data.rs @@ -138,6 +138,7 @@ impl DataCommand<'_> { State::Authenticated(username.clone()) } else if matches!(write_lock.state, State::ReceivingData(None)) { + // TODO rewrite to also have some extra honeypot info logging and make it not pass into inbox but into top level of the address debug!("No authenticated user"); for receipt in receipts { let folder = "INBOX".to_string(); From a114d89bfe28aa39bf1235e4f38cb670a7630c17 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Wed, 14 Sep 2022 19:20:34 +0200 Subject: [PATCH 4/4] Feature flag another import --- crates/erooster_smtp/src/commands/rcpt.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/erooster_smtp/src/commands/rcpt.rs b/crates/erooster_smtp/src/commands/rcpt.rs index 727e0f2b..63d89020 100644 --- a/crates/erooster_smtp/src/commands/rcpt.rs +++ b/crates/erooster_smtp/src/commands/rcpt.rs @@ -3,10 +3,13 @@ use crate::{ servers::state::State, }; use color_eyre::eyre::bail; -use erooster_core::backend::database::{Database, DB}; +use erooster_core::backend::database::DB; use futures::{channel::mpsc::SendError, Sink, SinkExt}; use tracing::{info, instrument}; +#[cfg(not(feature = "honeypot"))] +use erooster_core::backend::database::Database; + pub struct Rcpt<'a> { pub data: &'a Data, }