diff --git a/src/common/headers.rs b/src/common/headers.rs index 51cdb07..11a0f12 100644 --- a/src/common/headers.rs +++ b/src/common/headers.rs @@ -60,9 +60,9 @@ pub(crate) enum AuthenticatedHeader<'x> { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Header<'x, T> { - pub(crate) name: &'x [u8], - pub(crate) value: &'x [u8], - pub(crate) header: T, + pub name: &'x [u8], + pub value: &'x [u8], + pub header: T, } impl<'x> HeaderParser<'x> { diff --git a/src/dkim/canonicalize.rs b/src/dkim/canonicalize.rs index 92c2c37..7a7a321 100644 --- a/src/dkim/canonicalize.rs +++ b/src/dkim/canonicalize.rs @@ -151,7 +151,7 @@ impl Canonicalization { } impl Signature { - pub(crate) fn canonicalize<'x>( + pub fn canonicalize<'x>( &self, mut message: impl HeaderStream<'x>, ) -> (usize, CanonicalHeaders<'x>, Vec, CanonicalBody<'x>) { diff --git a/src/dkim/mod.rs b/src/dkim/mod.rs index 6c5be8a..c3c5a12 100644 --- a/src/dkim/mod.rs +++ b/src/dkim/mod.rs @@ -33,8 +33,8 @@ pub enum Canonicalization { #[derive(Debug, PartialEq, Eq, Clone, Default)] pub struct DkimSigner { _state: std::marker::PhantomData, - pub(crate) key: T, - pub(crate) template: Signature, + pub key: T, + pub template: Signature, } pub struct NeedDomain; diff --git a/src/dkim/verify.rs b/src/dkim/verify.rs index a590339..31690f9 100644 --- a/src/dkim/verify.rs +++ b/src/dkim/verify.rs @@ -240,6 +240,36 @@ impl Resolver { } impl<'x> AuthenticatedMessage<'x> { + pub async fn get_canonicalized_header(&self) -> Result, Error> { + // Based on verify_dkim_ function + // Iterate through possible DKIM headers + let mut data = Vec::with_capacity(256); + for header in &self.dkim_headers { + // Ensure signature is not obviously invalid + let signature = match &header.header { + Ok(signature) => { + if signature.x == 0 || (signature.x > signature.t) { + signature + } else { + continue; + } + } + Err(_err) => { + continue; + } + }; + + // Get pre-hashed but canonically ordered headers, who's hash is signed + let dkim_hdr_value = header.value.strip_signature(); + let headers = self.signed_headers(&signature.h, header.name, &dkim_hdr_value); + signature.ch.canonicalize_headers(headers, &mut data); + + return Ok(data); + } + // Return not ok + Err(Error::FailedBodyHashMatch) + } + pub fn signed_headers<'z: 'x>( &'z self, headers: &'x [String], diff --git a/src/lib.rs b/src/lib.rs index 60886dc..866647b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -331,18 +331,18 @@ pub struct MX { #[derive(Debug, Clone)] pub struct AuthenticatedMessage<'x> { - pub(crate) headers: Vec<(&'x [u8], &'x [u8])>, - pub(crate) from: Vec, - pub(crate) raw_message: &'x [u8], - pub(crate) body_offset: usize, - pub(crate) body_hashes: Vec<(Canonicalization, HashAlgorithm, u64, Vec)>, - pub(crate) dkim_headers: Vec>>, - pub(crate) ams_headers: Vec>>, - pub(crate) as_headers: Vec>>, - pub(crate) aar_headers: Vec>>, - pub(crate) received_headers_count: usize, - pub(crate) date_header_present: bool, - pub(crate) message_id_header_present: bool, + pub headers: Vec<(&'x [u8], &'x [u8])>, + pub from: Vec, + pub raw_message: &'x [u8], + pub body_offset: usize, + pub body_hashes: Vec<(Canonicalization, HashAlgorithm, u64, Vec)>, + pub dkim_headers: Vec>>, + pub ams_headers: Vec>>, + pub as_headers: Vec>>, + pub aar_headers: Vec>>, + pub received_headers_count: usize, + pub date_header_present: bool, + pub message_id_header_present: bool, } #[derive(Debug, Clone, PartialEq, Eq)]