From e9deb2500d515f4e331e5f88f30ae0c8d84e33c3 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Wed, 29 Oct 2025 14:06:21 +0000 Subject: [PATCH] dkim: fix subdomain checking issue --- crates/dkim/src/header.rs | 12 ++++++++++-- crates/dkim/src/lib.rs | 7 +++++++ docs/changelog/main.md | 2 ++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/dkim/src/header.rs b/crates/dkim/src/header.rs index acf4f00d..7c2bad25 100644 --- a/crates/dkim/src/header.rs +++ b/crates/dkim/src/header.rs @@ -1,4 +1,5 @@ use crate::{parser, DKIMError, HeaderList}; +use dns_resolver::Name; use indexmap::map::IndexMap; use std::str::FromStr; use textwrap::core::Word; @@ -192,8 +193,15 @@ impl DKIMHeader { // of the "i=" tag if let Some(user) = header.get_tag("i") { let signing_domain = header.get_required_tag("d"); - // TODO: naive check, should switch to parsing the domains/email - if !user.ends_with(&signing_domain) { + let Some((_local, domain)) = user.split_once('@') else { + return Err(DKIMError::DomainMismatch); + }; + + let i_domain = Name::from_str_relaxed(domain).map_err(|_| DKIMError::DomainMismatch)?; + let d_domain = + Name::from_str_relaxed(signing_domain).map_err(|_| DKIMError::DomainMismatch)?; + + if !d_domain.zone_of(&i_domain) { return Err(DKIMError::DomainMismatch); } } diff --git a/crates/dkim/src/lib.rs b/crates/dkim/src/lib.rs index e910a400..59bbca4e 100644 --- a/crates/dkim/src/lib.rs +++ b/crates/dkim/src/lib.rs @@ -406,6 +406,13 @@ b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ DKIMHeader::parse(header).unwrap_err(), DKIMError::DomainMismatch ); + + let header = r#"v=1; a=rsa-sha256; d=example.net; s=brisbane.net; i=foo@fexample.net; h=headers; bh=hash; b=hash + "#; + assert_eq!( + DKIMHeader::parse(header).unwrap_err(), + DKIMError::DomainMismatch + ); } #[test] diff --git a/docs/changelog/main.md b/docs/changelog/main.md index c60459ff..2ba6e459 100644 --- a/docs/changelog/main.md +++ b/docs/changelog/main.md @@ -104,3 +104,5 @@ * [keysource](../reference/keysource.md) now supports callback/event based data loading, which is similar to inline `key_data`, but allows for more efficient cache keys that use less RAM. + * dkim verification would incorrectly treat `i=@fexample.net` as a valid + subdomain of `d=example.net`.