NAME

Mail::MIMEDefang::TLSPolicy - MTA-STS and DANE/TLSA policy checks for MIMEDefang

DESCRIPTION

Mail::MIMEDefang::TLSPolicy provides methods to verify outbound TLS policy for recipient domains from mimedefang-filter.

  • MTA-STS (RFC 8461) - retrieve and parse a domain's MTA-STS policy (DNS TXT + HTTPS policy file).

  • DANE/TLSA (RFC 6698 / RFC 7671) - look up TLSA records for a domain and port to verify certificate binding.

Both functions require Net::DNS. md_check_mta_sts additionally requires LWP::UserAgent.

Typical usage:

use Mail::MIMEDefang::TLSPolicy;

# In filter_recipient: fetch the MTA-STS policy for the recipient domain,
# then verify the connecting MX is permitted before requiring TLS.
my $policy = md_check_mta_sts($recipient_domain);
if (defined $policy && $policy->{mode} eq 'enforce') {
    if (!md_verify_sts_mx($rcpt_host, $policy)) {
        action_bounce("MX host $rcpt_host not permitted by MTA-STS policy");
    }
}

# Look up DANE TLSA records for port 25 and validate the peer certificate.
my @tlsa = md_check_dane_tlsa($recipient_domain, 25);
if (@tlsa) {
    unless (md_verify_dane_cert($peer_cert_der, \@tlsa)) {
        # certificate does not match any TLSA record - reject or defer
    }
}

METHODS

md_check_mta_sts($domain [, %opts])

Retrieve and parse the MTA-STS policy for $domain.

The function performs two lookups:

  1. A DNS TXT query for _mta-sts.$domain to confirm the policy exists and extract its id= field.

  2. An HTTPS fetch of https://mta-sts.$domain/.well-known/mta-sts.txt to retrieve the policy document.

Optional key/value pairs in %opts:

timeout

HTTP request timeout in seconds (default: 10).

On success returns a hashref with:

mode

Policy mode: enforce, testing, or none.

max_age

Cache lifetime in seconds.

mx

Arrayref of permitted MX hostname patterns.

id

The policy id from the DNS TXT record.

Returns undef on any error (DNS failure, HTTP error, policy parse failure, or if LWP::UserAgent is not available).

md_check_dane_tlsa($domain, $port)

Look up DANE TLSA records for _$port._tcp.$domain.

Returns a list of hashrefs, one per TLSA record, each containing:

usage

Certificate usage field (0–3).

selector

Selector field (0 = full certificate, 1 = SubjectPublicKeyInfo).

matching_type

Matching type (0 = exact, 1 = SHA-256, 2 = SHA-512).

cert_data

Hex-encoded certificate association data.

Returns an empty list if no TLSA records are found, on lookup error, or if Net::DNS is not available.

md_verify_sts_mx($mx_host, $policy)

Returns true if $mx_host matches at least one MX hostname pattern in $policy-{mx}> (a hashref returned by "md_check_mta_sts").

Matching follows RFC 8461: a pattern beginning with *. matches any single DNS label prepended to the rest of the pattern (e.g. *.example.com matches mail.example.com but not a.b.example.com). All comparisons are case-insensitive.

Returns false if $policy is undefined, has no mx list, or no pattern matches.

md_verify_dane_cert($cert_der, \@tlsa)

Verify a DER-encoded X.509 certificate against a list of DANE TLSA records as returned by "md_check_dane_tlsa".

Returns true if the certificate matches at least one record, false otherwise.

Selector 0 (full certificate) requires only Digest::SHA. Selector 1 (SubjectPublicKeyInfo) additionally requires Crypt::OpenSSL::X509; records with selector 1 are skipped silently if that module is not available.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 199:

Non-ASCII character seen before =encoding in '(0–3).'. Assuming UTF-8