mail_auth/arc/
mod.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7pub mod builder;
8pub mod headers;
9pub mod parse;
10pub mod seal;
11pub mod verify;
12
13use crate::{
14    common::{
15        crypto::{Algorithm, Sha256, SigningKey},
16        headers::Header,
17        verify::VerifySignature,
18    },
19    dkim::{Canonicalization, NeedDomain},
20    ArcOutput, AuthenticationResults, DkimResult,
21};
22
23#[derive(Debug, PartialEq, Eq, Clone, Default)]
24pub struct ArcSealer<T: SigningKey<Hasher = Sha256>, State = NeedDomain> {
25    _state: std::marker::PhantomData<State>,
26    pub(crate) key: T,
27    pub(crate) signature: Signature,
28    pub(crate) seal: Seal,
29}
30
31#[derive(Debug, PartialEq, Eq, Clone, Default)]
32pub struct Signature {
33    pub i: u32,
34    pub a: Algorithm,
35    pub d: String,
36    pub s: String,
37    pub b: Vec<u8>,
38    pub bh: Vec<u8>,
39    pub h: Vec<String>,
40    pub z: Vec<String>,
41    pub l: u64,
42    pub x: u64,
43    pub t: u64,
44    pub ch: Canonicalization,
45    pub cb: Canonicalization,
46}
47
48#[derive(Debug, PartialEq, Eq, Clone, Default)]
49pub struct Seal {
50    pub i: u32,
51    pub a: Algorithm,
52    pub b: Vec<u8>,
53    pub d: String,
54    pub s: String,
55    pub t: u64,
56    pub cv: ChainValidation,
57}
58
59#[derive(Debug, PartialEq, Eq, Clone)]
60pub struct Results {
61    pub i: u32,
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct ArcSet<'x> {
66    pub signature: Signature,
67    pub seal: Seal,
68    pub results: &'x AuthenticationResults<'x>,
69}
70
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub struct Set<'x> {
73    pub signature: Header<'x, &'x Signature>,
74    pub seal: Header<'x, &'x Seal>,
75    pub results: Header<'x, &'x Results>,
76}
77
78#[derive(Debug, PartialEq, Eq, Clone, Default)]
79pub enum ChainValidation {
80    #[default]
81    None,
82    Fail,
83    Pass,
84}
85
86impl VerifySignature for Signature {
87    fn signature(&self) -> &[u8] {
88        &self.b
89    }
90
91    fn algorithm(&self) -> Algorithm {
92        self.a
93    }
94
95    fn selector(&self) -> &str {
96        &self.s
97    }
98
99    fn domain(&self) -> &str {
100        &self.d
101    }
102}
103
104impl VerifySignature for Seal {
105    fn signature(&self) -> &[u8] {
106        &self.b
107    }
108
109    fn algorithm(&self) -> Algorithm {
110        self.a
111    }
112
113    fn selector(&self) -> &str {
114        &self.s
115    }
116
117    fn domain(&self) -> &str {
118        &self.d
119    }
120}
121
122impl<'x> ArcOutput<'x> {
123    pub fn with_result(mut self, result: DkimResult) -> Self {
124        self.result = result;
125        self
126    }
127
128    pub fn with_set(mut self, set: Set<'x>) -> Self {
129        self.set.push(set);
130        self
131    }
132
133    pub fn can_be_sealed(&self) -> bool {
134        self.set.is_empty() || self.set.last().unwrap().seal.header.cv != ChainValidation::Fail
135    }
136}
137
138impl Default for ArcOutput<'_> {
139    fn default() -> Self {
140        Self {
141            result: DkimResult::None,
142            set: Vec::new(),
143        }
144    }
145}