base.m4, config.m4: Add DKIM signing machinery.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 4 May 2024 14:44:00 +0000 (15:44 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Mon, 6 May 2024 03:21:32 +0000 (04:21 +0100)
base.m4
config.m4

diff --git a/base.m4 b/base.m4
index 21f774b..8bcf0a4 100644 (file)
--- a/base.m4
+++ b/base.m4
@@ -419,6 +419,50 @@ m4_define(<:APPLY_HEADER_CHANGES:>,
                <:${if def:acl_m_hdrrm{$acl_m_hdrrm:}}\
                $2:>):>)
 
+m4_define(<:DKIM_SIGN_P:>,
+       <:and {{exists{CONF_sysconf_dir/dkim-sign.conf}} \
+              {!def:h_DKIM-Signature:} \
+              {!def:h_List-ID:} \
+              {or {{def:authenticated_id} \
+                   {def:authenticated_sender}}}}:>)
+
+m4_define(<:DKIM_KEYS_INSTANCE:>,
+       <:${lookup {${domain:$h_From:}} partial0-lsearch \
+                       {CONF_sysconf_dir/dkim-sign.conf} \
+               _LOOKUP_ARGS(<:$1:>, <:$2:>)}:>)
+m4_define(<:DKIM_KEYS_STATE:>, <:${lookup {$1} lsearch \
+               {DKIM_KEYS_INSTANCE(<:{CONF_dkim_keys_dir/$value/active/dkim-keys.state}:>)} \
+       _LOOKUP_ARGS(<:$2:>, <:$3:>, <:fail:>)}:>)
+m4_define(<:DKIM_KEYS_INFO:>, <:DKIM_KEYS_STATE(<:params:>,
+       <:{${if and {{>={$tod_epoch}{KV(t0)}} \
+                   {<{$tod_epoch}{${eval:KV(t0) + KV(n)*KV(step)}}}} \
+               {DKIM_KEYS_STATE(<:info.${eval:($tod_epoch - KV(t0))/KV(step)}:>,
+                       <:$1:>, <:$2:>)} \
+               m4_ifelse(<:$2:>, <::>, <:fail:>, <:$2:>)}}:>,
+       m4_ifelse(<:$2:>, <::>, <:fail:>, <:$2:>)):>)
+
+m4_define(<:DKIM_SIGN:>,
+       <:dkim_domain = \
+               ${if DKIM_SIGN_P \
+                       {DKIM_KEYS_INSTANCE({${domain:$h_From:}})}}
+       dkim_selector = DKIM_KEYS_INFO(<:{KV(k)}:>)
+       dkim_private_key = \
+               DKIM_KEYS_INSTANCE(<:m4_dnl
+                       CONF_dkim_keys_dir/$value/active/$dkim_selector.priv:>)
+       dkim_canon = relaxed
+       dkim_strict = true
+       dkim_sign_headers = CONF_dkim_headers : \
+               X-CONF_header_token-DKIM-Key-Publication
+       headers_add = \
+               ${if DKIM_SIGN_P \
+                       {DKIM_KEYS_INFO(<:m4_dnl
+                               {X-CONF_header_token-DKIM-Key-Publication: \
+                                       DKIM signature not suitable for \
+                                       as evidence after delivery; \
+                                       DKIM private key KV(k) will be \
+                                       published at KV(u) on or before \
+                                       KV(tpub)}:>)}}:>)
+
 m4_define(<:SMTP_DELIVERY:>,
        <:## Prevent sending messages with overly long lines.  The use of
        ## `message_size_limit' here is somewhat misleading.
@@ -435,6 +479,7 @@ smtp:
        driver = smtp
        SMTP_DELIVERY
        APPLY_HEADER_CHANGES
+       DKIM_SIGN
        tls_require_ciphers = CONF_acceptable_ciphers
        tls_dh_min_bits = 508
        tls_tempfail_tryclear = true
@@ -443,6 +488,7 @@ m4_define(<:SMTP_TRANS_DHBITS:>,
        <:driver = smtp
        SMTP_DELIVERY
        APPLY_HEADER_CHANGES
+       DKIM_SIGN
        hosts_try_auth = *
        hosts_require_tls = DOMKV(tls-peer-ca, {*}{})
        hosts_require_auth = \
index 10fd4e0..5e3cc9b 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -67,6 +67,7 @@ DEFCONF(sysconf_dir, /etc/mail)
 DEFCONF(userconf_dir, $home/.mail)
 DEFCONF(alias_file, /etc/aliases)
 DEFCONF(ca_dir, /etc/ca)
+DEFCONF(dkim_keys_dir, /var/lib/dkim-keys)
 
 ## User address suffix handling.
 DEFCONF(user_suffix_list, +* : -*)
@@ -79,6 +80,18 @@ DEFCONF(relay_clients, <m4_dnl
 ; 172.29.198.161 ; 2001:8b0:c92:a000::1:1 m4_dnl national
 )
 
+## DKIM headers list.
+DEFCONF(dkim_headers, m4_dnl
+References : In-Reply-To : Subject : To : Date : Message-ID : m4_dnl
+From : Sender : Reply-To : Cc : m4_dnl
+Resent-Date : Resent-From : Resent-Sender : Resent-To : Resent-Cc : m4_dnl
+Resent-Message-ID : m4_dnl
+Content-Transfer-Encoding : Content-Type : MIME-Version : m4_dnl
+Content-ID : Content-Description : m4_dnl
+List-Id : List-Help : List-Unsubscribe : List-Subscribe : m4_dnl
+List-Post : List-Owner : List-Archive m4_dnl
+)
+
 ## TLS certificate list.
 DEFCONF(certlist,
 <:m4_ifelse(t, m4_ifelse(MODE, hub, nil, MODE, srv, nil, t),