From 516d745f004846e9ff6659f70fb15c00d1063dce Mon Sep 17 00:00:00 2001 From: Malte Meiboom Date: Wed, 27 May 2026 10:53:02 +0200 Subject: [PATCH] Code polish - Fix some typos. - Added more comments (and documentation) to the code. --- src/commands/locals/remove.rs | 2 +- src/common/crypto.rs | 2 +- src/common/escape.rs | 7 +++++++ src/config.rs | 4 +--- src/mail.rs | 6 +----- src/types/errors.rs | 2 +- src/types/husk_context.rs | 23 +++++++++++++++++------ src/types/introducer.rs | 1 + src/types/mail_context.rs | 3 +++ 9 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/commands/locals/remove.rs b/src/commands/locals/remove.rs index 4320c69..85ac4f8 100644 --- a/src/commands/locals/remove.rs +++ b/src/commands/locals/remove.rs @@ -24,7 +24,7 @@ pub async fn dispatch(cmd: LocalsRemoveCommand, config: HuskConfigContainer) -> .map_err(|_| CommandError::CertNotFound(fpr.clone()))?; // Filter out valid certificates. If the certificate is not - // valid according to the policy, it is already no introducer. + // valid according to the policy, it is already no local. let certs: Vec = certs.iter() .filter_map(|c| c.with_policy(policy, None).ok() diff --git a/src/common/crypto.rs b/src/common/crypto.rs index f72326c..51e9aa8 100644 --- a/src/common/crypto.rs +++ b/src/common/crypto.rs @@ -450,7 +450,7 @@ pub fn authenticate(context: &HuskContext, cert: &ValidCert, role: Role, activat .next() { Some(k) => k.key(), None => { - return Err(HuskError::DamangedLocalTrustRoot( + return Err(HuskError::DamagedLocalTrustRoot( "missing certification capability".to_string()) .into()); } diff --git a/src/common/escape.rs b/src/common/escape.rs index 8a76ba4..6501e51 100644 --- a/src/common/escape.rs +++ b/src/common/escape.rs @@ -8,20 +8,27 @@ const REGEX_CONTROL_CHARS: &[&str] const REGEX_ESCAPED_CHARS: &[&str] = &[ "\\\\", "\\.", "\\|", "\\(", "\\)", "\\*", "\\+", "\\?", "\\^", "\\$", "\\[", "\\]" ]; +/// Escape characters in `value` which have a special meaning in regular +/// expressions. pub fn regex_ctrl_escape(value: &str) -> Result { let r = AhoCorasick::new(REGEX_CONTROL_CHARS)?; Ok(r.replace_all(value, REGEX_ESCAPED_CHARS)) } +/// Unescape characters in `value` which have a special meaning in regular +/// expressions. This is the reverse of `regex_ctrl_escape`. pub fn regex_ctrl_unescape(value: &str) -> Result { let r = AhoCorasick::new(REGEX_ESCAPED_CHARS)?; Ok(r.replace_all(value, REGEX_CONTROL_CHARS)) } +/// Create a regular expression for a domain name, including escaping +/// control characters. pub fn regex_domain_escape(value: &str) -> Result { regex_ctrl_escape(format!("<[^>]+[@.]{}>$", value).as_str()) } +/// Unescape a regular expression made by `regex_domain_escape`. pub fn regex_domain_unescape(value: &str) -> Result { let value = regex_ctrl_unescape(value)?; diff --git a/src/config.rs b/src/config.rs index 88d6711..46311ba 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,4 @@ -// -// Parsing the config file -// +//! Parsing the config file use anyhow; diff --git a/src/mail.rs b/src/mail.rs index b29e80c..b7b209a 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -1,8 +1,4 @@ -// -// Husk milter -// -// mail functions -// +//! mail functions use std::ffi::CString; use sequoia_openpgp::packet::UserID; diff --git a/src/types/errors.rs b/src/types/errors.rs index 8e270d4..7ccf040 100644 --- a/src/types/errors.rs +++ b/src/types/errors.rs @@ -11,7 +11,7 @@ pub enum HuskError { #[error("Cannot find the local trust root")] NoLocalTrustRoot, #[error("The local trust root is damaged - {0}")] - DamangedLocalTrustRoot(String), + DamagedLocalTrustRoot(String), #[error("Cannot access cert store")] NoCertStore, #[error("No encryption keys found")] diff --git a/src/types/husk_context.rs b/src/types/husk_context.rs index f124801..310a2bc 100644 --- a/src/types/husk_context.rs +++ b/src/types/husk_context.rs @@ -1,6 +1,12 @@ //! HuskContext //! -//! Keep data in HuskContext while processing a mail. +//! Keep data in `HuskContext` while processing emails. The HuskContext +//! lives for a complete session with the MTA. A session might contain +//! more than one email (the session is reused). +//! +//! The context of a single mail is stored in a `MailContext`. The +//! `HuskContext` has a reference to the `MailContext` of the current +//! email. use anyhow; use sequoia_openpgp::policy::StandardPolicy; @@ -26,7 +32,7 @@ pub struct HuskContext<'hc> { impl<'hc> HuskContext<'hc> { - /// Create a new HuskContext instance + /// Create a new HuskContext instance. pub fn new(config: &HuskConfig) -> anyhow::Result> { let sequoia_home = Home::new(PathBuf::from(&config.sequoia_home))?; @@ -48,14 +54,19 @@ impl<'hc> HuskContext<'hc> { }) } - pub fn set_sender(&mut self, sender: String) { - self.mail.set_sender(sender); - } - + /// If the `HuskContext` is reused for another email, `reset_mail` + /// creates the neccessary context for it. pub fn reset_mail(&mut self) { self.mail = MailContext::new(); } + /// Store the sender of an email in the current `MailContext`. + pub fn set_sender(&mut self, sender: String) { + self.mail.set_sender(sender); + } + + /// Add a recipient to the current `MailContext`, try to fetch the + /// corresponding certificate(s). pub async fn add_recipient(&mut self, rcpt: String) { let certs = crypto::get_certificates(self, rcpt.as_str()).await; diff --git a/src/types/introducer.rs b/src/types/introducer.rs index 6113138..a0c1a1e 100644 --- a/src/types/introducer.rs +++ b/src/types/introducer.rs @@ -108,6 +108,7 @@ use std::fmt::{Display, Formatter}; impl Display for Introducer { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // XXX: This is unsafe as ANSI control chars are not handled. let uids = self.cert.userids() .map(|u| String::from_utf8_lossy(u.userid().value()).to_string()) .collect::>() diff --git a/src/types/mail_context.rs b/src/types/mail_context.rs index b622f6f..9f16827 100644 --- a/src/types/mail_context.rs +++ b/src/types/mail_context.rs @@ -1,4 +1,7 @@ //! Mail Context +//! +//! As a mail gets processed by the milter, the `MailContext` is used +//! to keep the bits and pieces together. use std::sync::Arc; use bytes::{Bytes, BytesMut};