Documentation

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-> (a hashref returned by "md_check_mta_sts($domain [, %opts])").

    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($domain, $port)".

    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.