use super::Canonicalization;
use crate::crypto::{Algorithm, VerifyingKey};
pub struct DomainKey {
pub(crate) p: Box<dyn VerifyingKey + Send + Sync>,
pub(crate) f: u64,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DkimReportRecord {
pub(crate) ra: String,
pub(crate) rp: u8,
pub(crate) rr: u8,
pub(crate) rs: Option<String>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct AtpsRecord {
pub(crate) d: Option<String>,
}
pub(crate) const R_SVC_ALL: u64 = 0x04;
pub(crate) const R_SVC_EMAIL: u64 = 0x08;
pub(crate) const R_FLAG_TESTING: u64 = 0x10;
pub(crate) const R_FLAG_MATCH_DOMAIN: u64 = 0x20;
pub(crate) const R_MULTIPLE_RECORDS: u64 = 0x80;
pub(crate) const RR_DNS: u8 = 0x01;
pub(crate) const RR_OTHER: u8 = 0x02;
pub(crate) const RR_POLICY: u8 = 0x04;
pub(crate) const RR_SIGNATURE: u8 = 0x08;
pub(crate) const RR_UNKNOWN_TAG: u8 = 0x10;
pub(crate) const RR_VERIFICATION: u8 = 0x20;
pub(crate) const RR_EXPIRATION: u8 = 0x40;
#[derive(Debug, PartialEq, Eq, Clone)]
#[repr(u64)]
pub(crate) enum Service {
All = R_SVC_ALL,
Email = R_SVC_EMAIL,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[repr(u64)]
pub(crate) enum Flag {
Testing = R_FLAG_TESTING,
MatchDomain = R_FLAG_MATCH_DOMAIN,
}
impl From<Flag> for u64 {
fn from(v: Flag) -> Self {
v as u64
}
}
impl From<Service> for u64 {
fn from(v: Service) -> Self {
v as u64
}
}
impl DomainKey {
pub fn is_testing(&self) -> bool {
(self.f & R_FLAG_TESTING) != 0
}
pub fn requires_strict_identity(&self) -> bool {
(self.f & R_FLAG_MATCH_DOMAIN) != 0
}
pub fn has_multiple_records(&self) -> bool {
(self.f & R_MULTIPLE_RECORDS) != 0
}
pub(crate) fn verify<'a>(
&self,
headers: &mut dyn Iterator<Item = (&'a [u8], &'a [u8])>,
input: &impl VerifySignature,
canonicalization: Canonicalization,
) -> crate::Result<()> {
self.p.verify(
headers,
input.signature(),
canonicalization,
input.algorithm(),
)
}
}
pub trait VerifySignature {
fn selector(&self) -> &str;
fn domain(&self) -> &str;
fn signature(&self) -> &[u8];
fn algorithm(&self) -> Algorithm;
fn domain_key(&self) -> String {
let s = self.selector();
let d = self.domain();
let mut key = String::with_capacity(s.len() + d.len() + 13);
key.push_str(s);
key.push_str("._domainkey.");
key.push_str(d);
key.push('.');
key
}
}