mail_auth/common/
verify.rs1use std::{
8 net::{IpAddr, Ipv4Addr, Ipv6Addr},
9 sync::Arc,
10};
11
12use crate::{
13 dkim::Canonicalization, Error, IprevOutput, IprevResult, MessageAuthenticator, Parameters,
14 ResolverCache, Txt, MX,
15};
16
17use super::{
18 cache::NoCache,
19 crypto::{Algorithm, VerifyingKey},
20};
21
22pub struct DomainKey {
23 pub p: Box<dyn VerifyingKey + Send + Sync>,
24 pub f: u64,
25}
26
27impl MessageAuthenticator {
28 pub async fn verify_iprev<'x, TXT, MXX, IPV4, IPV6, PTR>(
29 &self,
30 params: impl Into<Parameters<'x, IpAddr, TXT, MXX, IPV4, IPV6, PTR>>,
31 ) -> IprevOutput
32 where
33 TXT: ResolverCache<String, Txt> + 'x,
34 MXX: ResolverCache<String, Arc<Vec<MX>>> + 'x,
35 IPV4: ResolverCache<String, Arc<Vec<Ipv4Addr>>> + 'x,
36 IPV6: ResolverCache<String, Arc<Vec<Ipv6Addr>>> + 'x,
37 PTR: ResolverCache<IpAddr, Arc<Vec<String>>> + 'x,
38 {
39 let params = params.into();
40 match self.ptr_lookup(params.params, params.cache_ptr).await {
41 Ok(ptr) => {
42 let mut last_err = None;
43 for host in ptr.iter().take(2) {
44 match ¶ms.params {
45 IpAddr::V4(ip) => match self.ipv4_lookup(host, params.cache_ipv4).await {
46 Ok(ips) => {
47 if ips.iter().any(|cip| cip == ip) {
48 return IprevOutput {
49 result: IprevResult::Pass,
50 ptr: ptr.into(),
51 };
52 }
53 }
54 Err(err) => {
55 last_err = err.into();
56 }
57 },
58 IpAddr::V6(ip) => match self.ipv6_lookup(host, params.cache_ipv6).await {
59 Ok(ips) => {
60 if ips.iter().any(|cip| cip == ip) {
61 return IprevOutput {
62 result: IprevResult::Pass,
63 ptr: ptr.into(),
64 };
65 }
66 }
67 Err(err) => {
68 last_err = err.into();
69 }
70 },
71 }
72 }
73
74 IprevOutput {
75 result: if let Some(err) = last_err {
76 err.into()
77 } else {
78 IprevResult::Fail(Error::NotAligned)
79 },
80 ptr: ptr.into(),
81 }
82 }
83 Err(err) => IprevOutput {
84 result: err.into(),
85 ptr: None,
86 },
87 }
88 }
89}
90
91impl From<IpAddr>
92 for Parameters<
93 '_,
94 IpAddr,
95 NoCache<String, Txt>,
96 NoCache<String, Arc<Vec<MX>>>,
97 NoCache<String, Arc<Vec<Ipv4Addr>>>,
98 NoCache<String, Arc<Vec<Ipv6Addr>>>,
99 NoCache<IpAddr, Arc<Vec<String>>>,
100 >
101{
102 fn from(params: IpAddr) -> Self {
103 Parameters::new(params)
104 }
105}
106
107impl IprevOutput {
108 pub fn result(&self) -> &IprevResult {
109 &self.result
110 }
111}
112
113impl DomainKey {
114 pub(crate) fn verify<'a>(
115 &self,
116 headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
117 input: &impl VerifySignature,
118 canonicalization: Canonicalization,
119 ) -> crate::Result<()> {
120 self.p.verify(
121 headers,
122 input.signature(),
123 canonicalization,
124 input.algorithm(),
125 )
126 }
127}
128
129pub trait VerifySignature {
130 fn selector(&self) -> &str;
131
132 fn domain(&self) -> &str;
133
134 fn signature(&self) -> &[u8];
135
136 fn algorithm(&self) -> Algorithm;
137
138 fn domain_key(&self) -> String {
139 let s = self.selector();
140 let d = self.domain();
141 let mut key = String::with_capacity(s.len() + d.len() + 13);
142 key.push_str(s);
143 key.push_str("._domainkey.");
144 key.push_str(d);
145 key.push('.');
146 key
147 }
148}