Commit Graph
59 Commits
Author SHA1 Message Date
Wez Furlong 1da468ea9a arc: we can now produce an arc seal
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:32 +00:00
Wez Furlong 4bd42ae57f arc: we can now validate an arc chain
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:32 +00:00
Wez Furlong 823ee09db9 dkim: refactor and improve some of the test logic
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00
Wez Furlong ee4266cd19 WIP: building out ARC processing
This is not fully baked yet, but I want to checkpoint.

refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00
Wez Furlong 93210b8346 dkim: add ARCSealHeader type
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:31 +00:00
Wez Furlong 714abd4910 dkim: add ARCMessageSignature type
This parses an ARC-Message-Signature header field

refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:30 +00:00
Wez Furlong 1f6e4ea72d dkim: refactor: rename HEADER to DKIM_SIGNATURE_HEADER_NAME
refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:30 +00:00
Wez Furlong e9deb2500d dkim: fix subdomain checking issue 2025-10-31 12:16:30 +00:00
Wez Furlong 6ccb337d8f dkim: extract header parsing guts to TaggedHeader struct
This should facilitate the implementation of ARC in a later commit.

refs: https://github.com/KumoCorp/kumomta/issues/16
2025-10-31 12:16:29 +00:00
Wez Furlong b73d81b0fc dns: utilities and plumbing for querying DNSBLs
This commit does some plumbing work to allow defining alternative
resolvers with different names that can be used to query different
upstream DNS servers.

This is most useful when implement DNSBLs where you might have a custom
DNS server configured with one or more RBL zones that is reserved purely
for RBL lookups.

The plumbing introduces a more regular syntax for defining one of the
various implementations of the Resolver trait, as well as a new
Aggregate resolver impl that can query across multiple Resolvers until a
query is satisfied.

This allows some interesting and powerful configurations, such as
loading a static zone file into memory to query it directly, and/or
blending that together with querying either the system or some other
upstream DNS server as a fallback.

The various lookup functions (except for MX!) have been updated to
accept an optional alternate resolver name, so that they work together
with the above.

A new rbl_lookup function is also provided as a convenience for querying
the most common form of RBLS.

ptr_host and reverse_ip are two string utility functions that are likely
not going to be widely used, but are very convenient to have when you
do have a usecase that requires it!

closes: https://github.com/KumoCorp/kumomta/issues/269
2025-10-10 18:45:52 +01:00
Sophia Turner 9c0b7511b1 fix up some lifetime hiding 2025-08-25 23:55:24 -07:00
Wez Furlong a1f4172f4f more clippy 2025-04-09 10:26:12 -07:00
Wez Furlong e3fdcaa628 cargo clippy --fix 2025-04-09 10:26:07 -07:00
Wez Furlong c7fe9489c3 fix: failure to load ed25519 dkim private key
This was probably the casualty of some earlier refactoring
that has gone unnoticed until now.

Since we don't have explicit context on which key format to
parse in this helper function that is used in multiple places,
let's just make it try to parse both rsa and ed25519.

closes: #368
2025-04-03 10:11:24 -07:00
Wez Furlong 501d1f26e5 dkim: support verifying multiple keys
While auditing Answer::as_txt usage as a follow up from the recent
SPF fix, I noticed a TODO in the dkim code (which we forked from
another implementation) to support processing multiple TXT
records.

This commit implements the necessary tweaks to extract multiple
signatures and attempt to verify them against the incoming message.
2025-03-07 09:26:55 -07:00
Wez Furlong 6cf315c37d dkim: extract public key parsing guts
No overall functional change, this is just moving the guts
around a bit to support validating from multiple signatures
in a later commit.
2025-03-07 09:05:02 -07:00
Wez Furlong 054508321b lruttl: drop moka, roll our own cache on top of dashmap
I've been having trouble with moka's eviction policy leading
to some unwanted duplicate work, especially when the system
is under load and the latency is higher.

This commit swaps it out in favor of a relatively simple
implementation on top of dashmap; that gives us a decent
concurrent base and better respects the concurrency
limit and LRU around the contentious insertion case.

For LRU, since dashmap is a concurrent data structure, it
is ~impossible to use the classic doubly linked LRU approach
safely.

The strategy used here is a proabalistic sampling LRU using a technique
similar to that used in redis.

We use atomics to tag read and write entries with a monotonic counter.
Entries with smaller counter numbers are least-recent than entries with
a larger number.

During eviction we take a random sample of 10 entries from the cache
map, remove any that have expired due to TTL, and if we still need space
after that, we'll pick up to half of those to evict.  That guarantees
that we don't pick the most recent entry of the sample, and on aggregate
this should be a reasonable approximation of the "true" LRU.

In the background, every 30s, a maintenance task will remove expired
entries from the caches.  This is primarily to reduce memory utilization
when the cache is otherwise idle.  When a cache is hot, expiration is
performed as part of the eviction logic described above.
2025-03-04 16:23:16 -07:00
Wez Furlong d331df5965 dkim: add separate key cache to signer machinery
The signer cache maps the signer parameters to a pre-made
signing context.

It is essentially a map of (domain, key) -> signer.

Assuming that the (domain,key) tuple is unique, then this is
a good, effective use of that cache.

However, if multiple domains can share the same key then we
can end up re-parsing the same key data for each of them,
which is moderately expensive and a waste of CPU.

This commit introduces an additional cache for the key source to
the resultant compiled key.

This allows sharing of the same compiled key across signing
parameters that otherwise vary, and should help to shave off
some latency.
2025-02-06 16:47:15 -07:00
Wez Furlong f637db6b36 misc: fix some warnings with rust 1.83 2024-12-03 08:44:32 -07:00
Dirkjan Ochtman 603fd50ec5 dns-resolver: improve TestResolver logic 2024-11-07 07:52:37 -07:00
Dirkjan Ochtman 197b73330b dkim: migrate to dns-resolver Resolver trait 2024-10-17 09:46:59 -07:00
Dirkjan Ochtman bf896f5365 Replace once_cell with LazyLock/OnceLock 2024-09-24 06:31:21 -07:00
Wez Furlong 261999bde0 fix: dkim signer must set time before setting expiry
otherwise an error will always be thrown
2024-06-11 06:53:27 -07:00
Wez Furlong bcf30af5c0 remove duplicate quick-error dep; move to thiserror in dkim 2024-05-23 08:31:05 -07:00
Wez Furlong fa1dec61a2 dkim: remove usage of rsa crate
We keep getting asked about
https://rustsec.org/advisories/RUSTSEC-2023-0071.html and how it impacts
kumomta.

The answer to that question is: in the default build configuration, we
use openssl's RSA signing implementation rather than that of the rsa
crate.  The reason for this is that OpenSSL's RSA implementation is due
to the performance gap between the two implementations
(https://github.com/RustCrypto/RSA/issues/339). The result of this is
that the problematic code and attack vector described in the security
advisory does not apply to KumoMTA, because it is not used to compute
any signatures.

In the interest of not raising any false alarms as more and more people
perform security analyses on kumomta, this commit removes the `rsa`
crate from the build graph. In order to do so, we need to port
verification over to the openssl RSA implementation which is what this
commit does.

I look forward to a future version of the `rsa` crate being published
that has this issue resolved, and that closes the performance gap!

refs: https://github.com/RustCrypto/RSA/issues/390
2024-04-10 13:26:49 -07:00
Wez Furlong 78e062ad64 chrono: fixup now-deprecated calls 2024-03-11 07:50:01 -07:00
Wez Furlong 334a19963c deps: base64 -> data_encoding
dependabot wanted to upgrade to base64 0.21, but I resent that
the API for the common case of base64 encoding got more difficult
in the move from 0.13.

So, I'm switching us to data_encoding's implementation instead.

Note that the overall rust ecosystem on which we depend here,
transitively depends on 3 different versions of the base64 crate, so
even though we've removed direct deps on base64 from kumomta, the lock
file still references base64 0.10, 0.13 and 0.21, so that kinda sucks.
2024-02-06 13:56:41 -07:00
Wez Furlong 02cd1ef7bf NEW: dkim over signing by setting over_sign = true in the signer
refs: https://github.com/KumoCorp/kumomta/issues/111
2024-01-18 12:59:41 -07:00
Wez Furlong f979bdc6b0 explicitly wrap dkim h value on colons
My reading of the spec says that we can swap `:` for `:FWS` when
wrapping, so let's try that.

Previously, we'd wrap on the hyphens in header names and that
seems to cause some problems for some verifiers.
2023-11-17 11:30:57 -07:00
Wez Furlong 546237d11c deps: trust-dns -> hickory
The project was rebranded relatively recently; switch
to the new version
2023-11-04 10:26:49 -07:00
Wez Furlong d8bea99caa docs: fixup some rustdoc warnings 2023-09-14 10:29:50 -07:00
Wez Furlong 92332a7a65 dkim: have verification return Vec<AuthenticationResult>
Replaces the dkim result types from this crate with
AuthenticationResults which contain the additional
data required to construct high-quality Authentication-Result
headers.

refs: https://github.com/KumoCorp/kumomta/issues/82
2023-09-14 08:33:10 -07:00
Wez Furlong 10ab7d8f11 mailparsing: conformance: bundle in some message checks
Include line length and non-7-bit-ness checks.
Rename from HeaderConformance to a more general MessageConformance.
2023-08-29 12:44:42 -07:00
Wez Furlong 5b27d4de71 dkim: tidy up verification result type 2023-08-25 08:55:28 -07:00
Wez Furlong 34bae0755c dkim: remove dead code 2023-08-25 08:55:28 -07:00
Wez Furlong 909cc95001 dkim: improve error reporting around message parsing
Use Result rather than Option.
Bubble up non-canonical line endings explicitly as an issue.
2023-08-25 08:55:28 -07:00
Wez Furlong 452bede2e1 dkim: switch to our own mailparsing implementation 2023-08-25 08:55:28 -07:00
Wez Furlong 413566cd94 dkim: simplify building test resolver 2023-08-25 08:55:28 -07:00
Wez Furlong a42d8967cd dkim: remove Arc requirement from verification interface
It seems like this was working around an issue that does
not appear to be an issue any more.
2023-08-25 08:55:28 -07:00
Wez Furlong 05e52d4ce6 message: switch ed25519 dkim signing to cfdkim
With the upgraded ed25519-dalek crate, it's now possible to
pass in either DER or PEM encoded PKCS8 signing keys, which
makes it feasible to remove the mail-auth dep from this crate.

That in turns reduces the amount of code in here, which is nice.
2023-08-22 17:27:06 -07:00
Wez Furlong 4ad227b89e cfdkim: upgrade ed25519-dalek to 2.0.0
This release fixes an API wart that required loading both private
and public keys to create a signer.
2023-08-22 16:59:11 -07:00
Wez Furlong 1123324400 dkim: wrap signature header
The hope is that this will encourage some verification implementations
to pass on headers where they currently fail.
2023-06-20 22:44:47 -07:00
Wez Furlong 1085e4bb19 dkim: move rsa key loading into DkimPrivateKey type
This makes it easy for the message crate to use the faster openssl
functionality if that has been enabled for the dkim crate.
2023-06-16 07:49:15 -07:00
Wez Furlong ffe2fd08e1 dkim: add option to use openssl for RSA signing
This is not on by default, and is not currently enabled
for KumoMTA.

Using openssl is currently about 3x faster than the pure rust
RSA crate, and inline with the perf of the ring crate, which
we could use here instead, but which doesn't support keys of
size 1024 which are currently widely deployed by the industry,
and for which larger sizes do not fit in DNS records.
2023-06-16 07:49:15 -07:00
Wez Furlong 30b8522873 dkim: precompile list of headers to sign during signing
We can exploit eg: knowing that the list of headers is a unique
list (no repeated headers) and save some overhead when using the
same signer multiple times.
2023-06-15 15:18:17 -07:00
Wez Furlong 4805f60837 dkim: avoid allocating a vec when signing headers 2023-06-15 14:45:40 -07:00
Wez Furlong 02d1378495 dkim: avoid re-parsing header list during signing 2023-06-15 14:28:11 -07:00
Wez Furlong e5d03052be dkim: tidy up handling of l= body length tag
We should parse at the edge and pass down the parsed number
2023-06-15 13:23:44 -07:00
Wez Furlong cf11540f84 dkim: remove another extraneous allocation, tidy up canon interface 2023-06-15 13:13:28 -07:00
Wez Furlong 28f0786e42 dkim: update crate deps 2023-06-15 11:37:59 -07:00