Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support wasm #38

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ doctest = false
default = ["ring", "rustls-pemfile"]
rust-crypto = ["ed25519-dalek", "rsa", "sha1", "sha2"]
generate = ["rsa", "rand"]
resolver = ["hickory-resolver"]
test = []

[dependencies]
Expand All @@ -27,7 +28,7 @@ ed25519-dalek = { version = "2.0", optional = true }
flate2 = "1.0.25"
lru-cache = "0.1.2"
mail-parser = { version = "0.9", features = ["ludicrous_mode", "full_encoding"] }
mail-builder = { version = "0.3", features = ["ludicrous_mode"] }
mail-builder = { version = "0.3", features = ["ludicrous_mode"], default-features = false }
parking_lot = "0.12.0"
quick-xml = "0.36"
ring = { version = "0.17", optional = true }
Expand All @@ -37,8 +38,8 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sha1 = { version = "0.10", features = ["oid"], optional = true }
sha2 = { version = "0.10.6", features = ["oid"], optional = true }
hickory-resolver = { version = "0.24", features = ["dns-over-rustls", "dnssec-ring"] }
zip = "2.1.1"
hickory-resolver = { version = "0.24", features = ["dns-over-rustls", "dnssec-ring"], optional = true }
zip = { version = "2.1.1", default-features = false }
rand = { version = "0.8.5", optional = true }

[dev-dependencies]
Expand Down
5 changes: 3 additions & 2 deletions src/arc/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ use crate::{
verify::{DomainKey, VerifySignature},
},
dkim::{verify::Verifier, Canonicalization},
ArcOutput, AuthenticatedMessage, DkimResult, Error, Resolver,
ArcOutput, AuthenticatedMessage, DkimResult, Error,
};

use super::{ChainValidation, Set};

impl Resolver {
#[cfg(feature = "resolver")]
impl crate::Resolver {
/// Verifies ARC headers of an RFC5322 message.
pub async fn verify_arc<'x>(&self, message: &'x AuthenticatedMessage<'x>) -> ArcOutput<'x> {
let arc_headers = message.ams_headers.len();
Expand Down
1 change: 1 addition & 0 deletions src/common/auth_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ impl AsAuthResult for Error {
Error::IncompatibleAlgorithms => "incompatible record/signature algorithms",
Error::SignatureExpired => "signature error",
Error::DnsError(_) => "dns error",
#[cfg(feature = "resolver")]
Error::DnsRecordNotFound(_) => "dns record not found",
Error::ArcInvalidInstance(i) => {
write!(header, "invalid ARC instance {i})").ok();
Expand Down
1 change: 1 addition & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub mod headers;
pub mod lru;
pub mod message;
pub mod parse;
#[cfg(feature = "resolver")]
pub mod resolver;
pub mod verify;

Expand Down
5 changes: 3 additions & 2 deletions src/common/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use std::net::IpAddr;

use crate::{dkim::Canonicalization, Error, IprevOutput, IprevResult, Resolver};
use crate::{dkim::Canonicalization, Error, IprevOutput, IprevResult};

use super::crypto::{Algorithm, VerifyingKey};

Expand All @@ -19,7 +19,8 @@ pub struct DomainKey {
pub f: u64,
}

impl Resolver {
#[cfg(feature = "resolver")]
impl crate::Resolver {
pub async fn verify_iprev(&self, addr: IpAddr) -> IprevOutput {
match self.ptr_lookup(addr).await {
Ok(ptr) => {
Expand Down
7 changes: 4 additions & 3 deletions src/dkim/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ use crate::{
headers::Writer,
verify::{DomainKey, VerifySignature},
},
is_within_pct, AuthenticatedMessage, DkimOutput, DkimResult, Error, Resolver,
is_within_pct, AuthenticatedMessage, DkimOutput, DkimResult, Error,
};

use super::{
Atps, DomainKeyReport, Flag, HashAlgorithm, Signature, RR_DNS, RR_EXPIRATION, RR_OTHER,
RR_SIGNATURE, RR_VERIFICATION,
};

impl Resolver {
#[cfg(feature = "resolver")]
impl crate::Resolver {
/// Verifies DKIM headers of an RFC5322 message.
#[inline(always)]
pub async fn verify_dkim<'x>(
Expand Down Expand Up @@ -241,7 +242,7 @@ impl Resolver {
}

impl<'x> AuthenticatedMessage<'x> {
pub async fn get_canonicalized_header(&self) -> Result<Vec<u8>, Error> {
pub fn get_canonicalized_header(&self) -> Result<Vec<u8>, Error> {
// Based on verify_dkim_ function
// Iterate through possible DKIM headers
let mut data = Vec::with_capacity(256);
Expand Down
5 changes: 3 additions & 2 deletions src/dmarc/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
use std::sync::Arc;

use crate::{
AuthenticatedMessage, DkimOutput, DkimResult, DmarcOutput, DmarcResult, Error, Resolver,
AuthenticatedMessage, DkimOutput, DkimResult, DmarcOutput, DmarcResult, Error,
SpfOutput, SpfResult,
};

use super::{Alignment, Dmarc, URI};

impl Resolver {
#[cfg(feature = "resolver")]
impl crate::Resolver {
/// Verifies the DMARC policy of an RFC5321.MailFrom domain
pub async fn verify_dmarc(
&self,
Expand Down
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use arc::Set;
use common::{crypto::HashAlgorithm, headers::Header, lru::LruCache, verify::DomainKey};
use dkim::{Atps, Canonicalization, DomainKeyReport};
use dmarc::Dmarc;
#[cfg(feature = "resolver")]
use hickory_resolver::{
proto::{error::ProtoError, op::ResponseCode},
TokioAsyncResolver,
Expand All @@ -40,9 +41,11 @@ pub mod report;
pub mod spf;

pub use flate2;
#[cfg(feature = "resolver")]
pub use hickory_resolver;
pub use zip;

#[cfg(feature = "resolver")]
pub struct Resolver {
pub(crate) resolver: TokioAsyncResolver,
pub(crate) cache_txt: LruCache<String, Txt>,
Expand Down Expand Up @@ -216,6 +219,7 @@ pub enum Error {
SignatureExpired,
SignatureLength,
DnsError(String),
#[cfg(feature = "resolver")]
DnsRecordNotFound(ResponseCode),
ArcChainTooLong,
ArcInvalidInstance(u32),
Expand Down Expand Up @@ -268,6 +272,7 @@ impl Display for Error {
Error::ArcChainTooLong => write!(f, "Too many ARC headers"),
Error::InvalidRecordType => write!(f, "Invalid record"),
Error::DnsError(err) => write!(f, "DNS resolution error: {err}"),
#[cfg(feature = "resolver")]
Error::DnsRecordNotFound(code) => write!(f, "DNS record not found: {code}"),
Error::NotAligned => write!(f, "Policy not aligned"),
}
Expand Down Expand Up @@ -331,6 +336,7 @@ impl From<io::Error> for Error {
}
}

#[cfg(feature = "resolver")]
impl From<ProtoError> for Error {
fn from(err: ProtoError) -> Self {
Error::DnsError(err.to_string())
Expand Down Expand Up @@ -380,6 +386,7 @@ pub(crate) fn is_within_pct(pct: u8) -> bool {
< pct as u64
}

#[cfg(feature = "resolver")]
impl Clone for Resolver {
fn clone(&self) -> Self {
Self {
Expand Down
6 changes: 4 additions & 2 deletions src/spf/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ use std::{
time::Instant,
};

use crate::{Error, Resolver, SpfOutput, SpfResult};
use crate::{Error, SpfOutput, SpfResult};

use super::{Macro, Mechanism, Qualifier, Spf, Variables};

#[allow(clippy::iter_skip_zero)]
impl Resolver {
#[cfg(feature = "resolver")]
impl crate::Resolver {
/// Verifies the SPF EHLO identity
pub async fn verify_spf_helo(
&self,
Expand Down Expand Up @@ -468,6 +469,7 @@ impl From<&Qualifier> for SpfResult {
impl From<Error> for SpfResult {
fn from(err: Error) -> Self {
match err {
#[cfg(feature = "resolver")]
Error::DnsRecordNotFound(_) | Error::InvalidRecordType => SpfResult::None,
Error::ParseError => SpfResult::PermError,
_ => SpfResult::TempError,
Expand Down