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