Files
kay ozaki f2d98eaf62 psl: normalize domains before psl::domain_str / suffix_str lookups
The `psl` crate's domain_str / suffix_str do byte-exact lookups against
the public-suffix list, so uppercase or trailing-dot inputs (e.g.
"Example.COM" or "example.com." from a DNS Name) silently return None.
Several call sites were passing through user- or DNS-supplied domains
unmodified.

Add a small psl-utils crate that wraps the psl crate:

* normalize_domain(&str) -> Cow<str>: strips a single trailing dot and
  lowercases ASCII; borrows when the input is already normalized so
  the hot path (alignment loop) doesn't allocate.
* domain_str / suffix_str: thin re-exports for callers that have
  already normalized.

psl-utils becomes the only workspace crate that directly depends on
the psl crate; kumo-dmarc and mod-string switch to depending on
psl-utils instead.

Updated call sites:

* kumo-dmarc record.rs: is_relaxed_aligned / is_strict_aligned now
  normalize both inputs first. Replaces the prior eq_ignore_ascii_case
  comparisons.
* kumo-dmarc lib.rs: the organizational-domain fallback in
  DmarcContext::check now normalizes from_domain before calling
  domain_str and compares against the normalized form. Previously a
  mixed-case From: header would skip the _dmarc.<org> lookup entirely.
* mod-string lib.rs: the Lua-exposed string.psl_domain and
  string.psl_suffix bindings normalize their input. Behavior change:
  inputs that previously returned nil due to case or trailing dot now
  resolve.

Co-authored-by: Wez Furlong <wez@wezfurlong.org>
Closes: https://github.com/KumoCorp/kumomta/pull/513
2026-05-06 13:34:15 +00:00
..