aboutsummaryrefslogtreecommitdiff
path: root/contrib/sendmail/cf
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/cf')
-rw-r--r--contrib/sendmail/cf/README79
-rw-r--r--contrib/sendmail/cf/cf/Makefile29
-rw-r--r--contrib/sendmail/cf/cf/submit.cf39
-rw-r--r--contrib/sendmail/cf/cf/submit.mc3
-rw-r--r--contrib/sendmail/cf/feature/check_cert_altnames.m42
-rw-r--r--contrib/sendmail/cf/feature/check_other.m446
-rw-r--r--contrib/sendmail/cf/feature/delay_checks.m42
-rw-r--r--contrib/sendmail/cf/feature/dnsbl.m42
-rw-r--r--contrib/sendmail/cf/feature/enhdnsbl.m42
-rw-r--r--contrib/sendmail/cf/feature/nopercenthack.m42
-rw-r--r--contrib/sendmail/cf/feature/nouucp.m42
-rw-r--r--contrib/sendmail/cf/feature/sts.m419
-rw-r--r--contrib/sendmail/cf/m4/cfhead.m48
-rw-r--r--contrib/sendmail/cf/m4/proto.m4338
-rw-r--r--contrib/sendmail/cf/m4/version.m42
-rw-r--r--contrib/sendmail/cf/mailer/local.m42
16 files changed, 462 insertions, 115 deletions
diff --git a/contrib/sendmail/cf/README b/contrib/sendmail/cf/README
index 983aa2821a1a..cfabe5eefe45 100644
--- a/contrib/sendmail/cf/README
+++ b/contrib/sendmail/cf/README
@@ -1120,9 +1120,8 @@ local_procmail Use procmail or another delivery agent as the local mailer.
setreuid() call, you may need to add -f $f to the procmail
argument vector to pass the proper sender to procmail.
- For example, this allows it to use the maildrop
- (http://www.flounder.net/~mrsam/maildrop/) mailer instead
- by specifying:
+ For example, this allows it to use the maildrop mailer
+ instead by specifying:
FEATURE(`local_procmail', `/usr/local/bin/maildrop',
`maildrop -d $u')
@@ -1132,7 +1131,7 @@ local_procmail Use procmail or another delivery agent as the local mailer.
FEATURE(`local_procmail', `/usr/local/bin/scanmails')
WARNING: This feature sets LOCAL_MAILER_FLAGS unconditionally,
- i.e., without respecting any definitions in an OSTYPE setting.
+ i.e., without respecting any definitions in an OSTYPE setting.
bestmx_is_local Accept mail as though locally addressed for any host that
lists us as the best possible MX record. This generates
@@ -1267,6 +1266,12 @@ delay_checks The rulesets check_mail and check_relay will not be called
section. Note: this feature is incompatible to the versions
in 8.10 and 8.11.
+check_other Enable a default check_other ruleset which terminates
+ an SMTP session when it encounters a command which matches
+ a regular expression given as argument. If no argument
+ is given, then the default (to match potential headers) is:
+ ^[[:print:]]+ *:
+
use_client_ptr If this feature is enabled then check_relay will override
its first argument with $&{client_ptr}. This is useful for
rejections based on the unverified hostname of client,
@@ -1578,9 +1583,9 @@ require_rdns Reject mail from connecting SMTP clients without proper
Entries such as
Connect:1.2.3.4 OK
- Connect:1.2 RELAY
- will allowlist IP address 1.2.3.4, so that the rDNS
- blocking does apply to that IP address
+ Connect:1.3 RELAY
+ will allowlist IP address 1.2.3.4 and IP net 1.3.*
+ so that the rDNS blocking does apply not to those IPs.
Entries such as
Connect:1.2.3.4 REJECT
@@ -1603,6 +1608,14 @@ badmx Reject envelope sender addresses (MAIL) whose domain part
has been compiled with the options MAP_REGEX and
DNSMAP.
+sts Experimental support for Strict Transport Security
+ (MTA-STS, see RFC 8461). It sets the option
+ StrictTransportSecurity and takes one optional
+ argument: the socket map specification to access
+ postfix-mta-sts-resolver (see feature/sts.m4
+ for the default value).
+ For more information see doc/op/op.me.
+
+-------+
| HACKS |
+-------+
@@ -2581,7 +2594,7 @@ top level domain TLD, 192.168.212.* network, and the IPv6 address
2002:c0a8:02c7::/48.
Entries in the access map should be tagged according to their type.
-Three tags are available:
+These tags are applicable:
Connect: connection information (${client_addr}, ${client_name})
From: envelope sender
@@ -2818,7 +2831,7 @@ regex map:
# check address against various regex checks
R$* $: $>Parse0 $>3 $1
R$+ < @ bigisp.com. > $* $: $(allnumbers $1 $)
- R@MATCH $#error $: 553 Header Error
+ R@MATCH $#error $: 553 Address Error
These rules are called with the original arguments of the corresponding
check_* ruleset. If the local ruleset returns $#OK, no further checking
@@ -3081,8 +3094,8 @@ Darth+20Mail+20+28Cert+29/emailAddress=darth+2Bcert@endmail.org
(line breaks have been inserted for readability).
-The macros which are subject to this encoding are ${cert_subject},
-${cert_issuer}, ${cn_subject}, and ${cn_issuer}.
+The macros which are subject to this encoding are ${cert_subject},
+${cert_issuer}, ${cn_subject}, and ${cn_issuer}.
Examples:
@@ -3223,13 +3236,13 @@ options:
- CertFile, KeyFile: {Server,Client}{Cert,Key}File
- Flags: see doc/op/op.me for details.
-If FEATURE(`tls_session_features') is used, then default rulesets
-are activated which look up entries in the access map with the tags
-TLS_Srv_features and TLS_Clt_features, respectively.
-For example, these entries:
+If FEATURE(`tls_session_features') and FEATURE(`access_db') are
+used, then default rulesets are activated which look up entries in
+the access map with the tags TLS_Srv_features and TLS_Clt_features,
+respectively. For example, these entries:
- TLS_Srv_features:10.0.2.4 CipherList=MEDIUM+aRSA;
- TLS_Clt_features:10.1.0.1 Options=SSL_OP_NO_TLSv1_2; CipherList=ALL:-EXPORT
+TLS_Srv_features:10.0.2.4 CipherList=MEDIUM+aRSA;
+TLS_Clt_features:10.1.0.1 Options=SSL_OP_NO_TLSv1_2; CipherList=ALL:-EXPORT
specify a cipherlist with MEDIUM strength ciphers that use RSA
certificates only for the client with the IP address 10.0.2.4,
@@ -3240,21 +3253,23 @@ their own rulesets which must return the appropriate data.
If the rulesets are not defined or do not return a value, the
default TLS options are not modified.
-About 2): the ruleset try_tls (srv_features) can be used together
-with the access map. Entries for the access map must be tagged
-with Try_TLS (Srv_Features) and refer to the hostname or IP address
-of the connecting system. A default case can be specified by using
-just the tag. For example, the following entries in the access map:
+About 2): the rulesets try_tls, srv_features, and clt_features can
+be used together with the access map. Entries for the access map
+must be tagged with Try_TLS, Srv_Features, Clt_Features and refer
+to the hostname or IP address of the connecting system. A default
+case can be specified by using just the tag. For example, the
+following entries in the access map:
Try_TLS:broken.server NO
Srv_Features:my.domain v
Srv_Features: V
+ Clt_Features:broken.sts M
will turn off STARTTLS when sending to broken.server (or any host
-in that domain), and request a client certificate during the TLS
-handshake only for hosts in my.domain. The valid entries on the RHS
-for Srv_Features are listed in the Sendmail Installation and
-Operations Guide.
+in that domain), request a client certificate during the TLS handshake
+only for hosts in my.domain, and disable MTA-STS for broken.sts.
+The valid entries on the RHS for Srv_Features and Clt_Features are
+listed in the Sendmail Installation and Operations Guide.
Received: Header
@@ -3377,11 +3392,11 @@ LOCAL_RULESETS respectively. For example:
Smyruleset
...
-Local additions for the rulesets srv_features, try_tls, tls_rcpt,
-tls_client, and tls_server can be made using LOCAL_SRV_FEATURES,
-LOCAL_TRY_TLS, LOCAL_TLS_RCPT, LOCAL_TLS_CLIENT, and LOCAL_TLS_SERVER,
-respectively. For example, to add a local ruleset that decides
-whether to try STARTTLS in a sendmail client, use:
+Local additions for the rulesets srv_features, clt_features, try_tls,
+tls_rcpt, tls_client, and tls_server can be made using LOCAL_SRV_FEATURES,
+LOCAL_CLT_FEATURES, LOCAL_TRY_TLS, LOCAL_TLS_RCPT, LOCAL_TLS_CLIENT,
+and LOCAL_TLS_SERVER, respectively. For example, to add a local
+ruleset that decides whether to try STARTTLS in a sendmail client, use:
LOCAL_TRY_TLS
R...
@@ -4288,7 +4303,7 @@ confXF_BUFFER_SIZE XScriptFileBufferSize
memory-buffered transcript (xf)
file before a disk-based file is
used.
-confAUTH_MECHANISMS AuthMechanisms [GSSAPI KERBEROS_V4 DIGEST-MD5
+confAUTH_MECHANISMS AuthMechanisms [EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5
CRAM-MD5] List of authentication
mechanisms for AUTH (separated by
spaces). The advertised list of
diff --git a/contrib/sendmail/cf/cf/Makefile b/contrib/sendmail/cf/cf/Makefile
index bf6f031b2f11..bdb9f9e9b426 100644
--- a/contrib/sendmail/cf/cf/Makefile
+++ b/contrib/sendmail/cf/cf/Makefile
@@ -100,23 +100,36 @@ M4FILES=\
${CFDIR}/feature/access_db.m4 \
${CFDIR}/feature/allmasquerade.m4 \
${CFDIR}/feature/always_add_domain.m4 \
+ ${CFDIR}/feature/authinfo.m4 \
+ ${CFDIR}/feature/badmx.m4 \
${CFDIR}/feature/bcc.m4 \
${CFDIR}/feature/bestmx_is_local.m4 \
${CFDIR}/feature/bitdomain.m4 \
+ ${CFDIR}/feature/block_bad_helo.m4 \
${CFDIR}/feature/blocklist_recipients.m4 \
+ ${CFDIR}/feature/check_cert_altnames.m4 \
+ ${CFDIR}/feature/check_other.m4 \
+ ${CFDIR}/feature/compat_check.m4 \
${CFDIR}/feature/conncontrol.m4 \
+ ${CFDIR}/feature/delay_checks.m4 \
${CFDIR}/feature/dnsbl.m4 \
${CFDIR}/feature/domaintable.m4 \
+ ${CFDIR}/feature/enhdnsbl.m4 \
${CFDIR}/feature/generics_entire_domain.m4 \
${CFDIR}/feature/genericstable.m4 \
+ ${CFDIR}/feature/greet_pause.m4 \
${CFDIR}/feature/ldap_routing.m4 \
${CFDIR}/feature/limited_masquerade.m4 \
${CFDIR}/feature/local_lmtp.m4 \
+ ${CFDIR}/feature/local_no_masquerade.m4 \
${CFDIR}/feature/local_procmail.m4 \
+ ${CFDIR}/feature/lookupdotdomain.m4 \
${CFDIR}/feature/loose_relay_check.m4 \
${CFDIR}/feature/mailertable.m4 \
${CFDIR}/feature/masquerade_entire_domain.m4 \
${CFDIR}/feature/masquerade_envelope.m4 \
+ ${CFDIR}/feature/msp.m4 \
+ ${CFDIR}/feature/mtamark.m4 \
${CFDIR}/feature/no_default_msa.m4 \
${CFDIR}/feature/nocanonify.m4 \
${CFDIR}/feature/nopercenthack.m4 \
@@ -124,17 +137,24 @@ M4FILES=\
${CFDIR}/feature/nouucp.m4 \
${CFDIR}/feature/nullclient.m4 \
${CFDIR}/feature/prefixmod.m4 \
+ ${CFDIR}/feature/preserve_local_plus_detail.m4 \
+ ${CFDIR}/feature/preserve_luser_host.m4 \
${CFDIR}/feature/promiscuous_relay.m4 \
- ${CFDIR}/feature/redirect.m4 \
+ ${CFDIR}/feature/queuegroup.m4 \
${CFDIR}/feature/ratecontrol.m4 \
+ ${CFDIR}/feature/redirect.m4 \
${CFDIR}/feature/relay_based_on_MX.m4 \
${CFDIR}/feature/relay_entire_domain.m4 \
${CFDIR}/feature/relay_hosts_only.m4 \
${CFDIR}/feature/relay_local_from.m4 \
${CFDIR}/feature/relay_mail_from.m4 \
+ ${CFDIR}/feature/require_rdns.m4 \
${CFDIR}/feature/smrsh.m4 \
${CFDIR}/feature/stickyhost.m4 \
+ ${CFDIR}/feature/sts.m4 \
+ ${CFDIR}/feature/tls_failures.m4 \
${CFDIR}/feature/tls_session_features.m4 \
+ ${CFDIR}/feature/use_client_ptr.m4 \
${CFDIR}/feature/use_ct_file.m4 \
${CFDIR}/feature/use_cw_file.m4 \
${CFDIR}/feature/uucpdomain.m4 \
@@ -147,6 +167,7 @@ M4FILES=\
${CFDIR}/m4/proto.m4 \
${CFDIR}/m4/version.m4 \
${CFDIR}/mailer/cyrus.m4 \
+ ${CFDIR}/mailer/cyrusv2.m4 \
${CFDIR}/mailer/fax.m4 \
${CFDIR}/mailer/local.m4 \
${CFDIR}/mailer/mail11.m4 \
@@ -159,6 +180,7 @@ M4FILES=\
${CFDIR}/mailer/uucp.m4 \
${CFDIR}/ostype/aix3.m4 \
${CFDIR}/ostype/aix4.m4 \
+ ${CFDIR}/ostype/aix5.m4 \
${CFDIR}/ostype/altos.m4 \
${CFDIR}/ostype/amdahl-uts.m4 \
${CFDIR}/ostype/a-ux.m4 \
@@ -167,6 +189,7 @@ M4FILES=\
${CFDIR}/ostype/bsdi.m4 \
${CFDIR}/ostype/bsdi1.0.m4 \
${CFDIR}/ostype/bsdi2.0.m4 \
+ ${CFDIR}/ostype/darwin.m4 \
${CFDIR}/ostype/dgux.m4 \
${CFDIR}/ostype/domainos.m4 \
${CFDIR}/ostype/dragonfly.m4 \
@@ -200,10 +223,14 @@ M4FILES=\
${CFDIR}/ostype/solaris2.ml.m4 \
${CFDIR}/ostype/solaris2.pre5.m4 \
${CFDIR}/ostype/solaris8.m4 \
+ ${CFDIR}/ostype/solaris11.m4 \
${CFDIR}/ostype/sunos3.5.m4 \
${CFDIR}/ostype/sunos4.1.m4 \
${CFDIR}/ostype/svr4.m4 \
${CFDIR}/ostype/ultrix4.m4 \
+ ${CFDIR}/ostype/unicos.m4 \
+ ${CFDIR}/ostype/unicosmk.m4 \
+ ${CFDIR}/ostype/unicosmp.m4 \
${CFDIR}/ostype/unixware7.m4 \
${CFDIR}/ostype/unknown.m4 \
${CFDIR}/ostype/uxpds.m4
diff --git a/contrib/sendmail/cf/cf/submit.cf b/contrib/sendmail/cf/cf/submit.cf
index 63d7cb720eb7..1faab23e9e39 100644
--- a/contrib/sendmail/cf/cf/submit.cf
+++ b/contrib/sendmail/cf/cf/submit.cf
@@ -16,8 +16,8 @@
#####
##### SENDMAIL CONFIGURATION FILE
#####
-##### built by ca@lab.smi.sendmail.com on Thu Jul 2 22:41:57 PDT 2020
-##### in /var/tmp/ca/sm8.git/sendmail/OpenSource/sendmail-8.16.1/cf/cf
+##### built by ca@lab.smi.sendmail.com on Sun Aug 15 23:05:00 PDT 2021
+##### in /var/tmp/ca/sm8.head/sendmail/OpenSource/sendmail-8.17.1/cf/cf
##### using ../ as configuration include directory
#####
######################################################################
@@ -88,6 +88,7 @@ C{ResOk}OKR
# Hosts for which relaying is permitted ($=R)
FR-o /etc/mail/relay-domains
+
# arithmetic map
Karith arith
@@ -114,7 +115,7 @@ D{MTAHost}[127.0.0.1]
# Configuration version number
-DZ8.16.1/Submit
+DZ8.17.1/Submit
###############
@@ -362,7 +363,7 @@ O TimeZoneSpec=
# maximum number of new connections per second
#O ConnectionRateThrottle=0
-# Width of the window
+# Width of the window
#O ConnectionRateWindowSize=60s
# work recipient factor
@@ -536,7 +537,7 @@ O PidFile=/var/spool/clientmqueue/sm-client.pid
#O ClientCertFile
# Client private key
#O ClientKeyFile
-# File containing certificate revocation lists
+# File containing certificate revocation lists
#O CRLFile
# Directory containing hashes pointing to certificate revocation status files
#O CRLPath
@@ -802,7 +803,7 @@ R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ...
R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here
R< @ $+ > $#error $@ 5.1.3 $: "553 User address required"
R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ...
-R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo"
+R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo"
R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required"
R$* $=O $* < @ *LOCAL* >
$@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ...
@@ -896,7 +897,7 @@ R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 >
SMailerToTriple=95
R< > $* $@ $1 strip off null relay
-R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
+R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
R< error : $- : $+ > $* $#error $@ $(dequote $1 $) $: $2
R< error : $+ > $* $#error $: $1
R< local : $* > $* $>CanonLocal < $1 > $2
@@ -926,7 +927,7 @@ R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 >
# handle local:user syntax
R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1
-R< $+ > $* $#local $@ $2 $: $1
+R< $+ > $* $#local $@ $2 $: $1
###################################################################
### Ruleset 93 -- convert header names to masqueraded form ###
@@ -1189,7 +1190,7 @@ R<FORGED> $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $
R<FAIL> $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name}
R$* $: <@> $&{client_name}
# pass to name server to make hostname canonical
-R<@> $* $=P $:<?> $1 $2
+R<@> $* $=P $:<?> $1 $2
R<@> $+ $:<?> $[ $1 $]
R$* . $1 strip trailing dots
R<?> $=w $@ RELAY
@@ -1233,12 +1234,20 @@ Ssrv_features
######################################################################
+### clt_features: which features to use with a server?
+### (done in client)
+######################################################################
+Sclt_features
+
+
+######################################################################
### try_tls: try to use STARTTLS?
### (done in client)
######################################################################
Stry_tls
+
######################################################################
### tls_rcpt: is connection with server "good" enough?
### (done in client, per recipient)
@@ -1278,8 +1287,12 @@ R$* $@ $>"TLS_connection" $1
### Requirement: RHS from access map, may be ? for none.
######################################################################
STLS_connection
-RSOFTWARE $#error $@ 4.7.0 $: "403 TLS handshake."
-RDANE_FAIL $#error $@ 4.7.0 $: "403 DANE check failed."
+RSOFTWARE $#error $@ 4.7.0 $: "454 TLS handshake failed."
+RDANE_FAIL $#error $@ 4.7.0 $: "454 DANE check failed."
+RPROTOCOL $#error $@ 4.7.0 $: "454 STARTTLS failed."
+RCONFIG $#error $@ 4.7.0 $: "454 STARTTLS temporarily not possible."
+
+
@@ -1478,6 +1491,7 @@ Mrelay, P=[IPC], F=mDFMuXa8k, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=
T=DNS/RFC822/SMTP,
A=TCP $h
+
### submit.mc ###
# divert(-1)
# #
@@ -1505,3 +1519,6 @@ Mrelay, P=[IPC], F=mDFMuXa8k, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=
# dnl
# dnl If you use IPv6 only, change [127.0.0.1] to [IPv6:0:0:0:0:0:0:0:1]
# FEATURE(`msp', `[127.0.0.1]')dnl
+# dnl enable this for SMTPUTF8 support
+# dnl LOCAL_CONFIG
+# dnl O SMTPUTF8=true
diff --git a/contrib/sendmail/cf/cf/submit.mc b/contrib/sendmail/cf/cf/submit.mc
index fc3cceec6b8f..99e58ac2629c 100644
--- a/contrib/sendmail/cf/cf/submit.mc
+++ b/contrib/sendmail/cf/cf/submit.mc
@@ -24,3 +24,6 @@ define(`confDONT_INIT_GROUPS', `True')dnl
dnl
dnl If you use IPv6 only, change [127.0.0.1] to [IPv6:0:0:0:0:0:0:0:1]
FEATURE(`msp', `[127.0.0.1]')dnl
+dnl enable this for SMTPUTF8 support
+dnl LOCAL_CONFIG
+dnl O SMTPUTF8=true
diff --git a/contrib/sendmail/cf/feature/check_cert_altnames.m4 b/contrib/sendmail/cf/feature/check_cert_altnames.m4
index 9fae74ef0a3c..baa10697fd95 100644
--- a/contrib/sendmail/cf/feature/check_cert_altnames.m4
+++ b/contrib/sendmail/cf/feature/check_cert_altnames.m4
@@ -10,7 +10,7 @@ divert(-1)
#
divert(0)dnl
-VERSIONID(`$Id: block_bad_helo.m4,v 1.2 2013-11-22 20:51:11 ca Exp $')
+VERSIONID(`$Id: check_cert_altnames.m4 1.0 2019-01-01 01:01:01 ca Exp $')
divert(-1)
define(`_FFR_TLS_ALTNAMES', `1')
divert(6)dnl
diff --git a/contrib/sendmail/cf/feature/check_other.m4 b/contrib/sendmail/cf/feature/check_other.m4
new file mode 100644
index 000000000000..fa792243e137
--- /dev/null
+++ b/contrib/sendmail/cf/feature/check_other.m4
@@ -0,0 +1,46 @@
+divert(-1)
+#
+# Copyright (c) 2021 Proofpoint, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+dnl bogus Id, just here to show up in the generated cf file
+divert(0)
+VERSIONID(`$Id: check_other.m4,v 1.0 2021-04-30 00:01:11 ca Exp $')
+divert(-1)
+dnl
+dnl Options:
+dnl first arg:
+dnl empty: use default regex
+dnl else: use as regex
+dnl [not implemented: NOREGEX: do not use any regex]
+dnl
+dnl Possible enhancements:
+dnl select which SMTP reply type(s) should be allowed to match?
+dnl maybe add "exceptions":
+dnl - via an "OK" regex?
+dnl - access map lookup for clients to be "ok" (Connect:... {ok,relay})
+dnl more args? possible matches for rejections:
+dnl does not seem to worth the effort: too inflexible.
+dnl
+dnl Note: sendmail removes whitespace before ':' ("tokenization")
+ifelse(
+ defn(`_ARG_'), `', `define(`CHKORX', `^[[:print:]]+ *:')',
+ dnl defn(`_ARG_'), `NOREGEX', `define(`CHKORX', `')',
+ `define(`CHKORX', defn(`_ARG_'))')
+LOCAL_CONFIG
+ifelse(defn(`CHKORX'), `', `', `dnl
+Kbadcmd regex -m -a<BADCMD> defn(`CHKORX')')
+LOCAL_RULESETS
+Scheck_other
+dnl accept anything that will be accepted by the MTA
+R$* $| 2 $@ ok
+ifelse(defn(`CHKORX'), `', `', `dnl
+R$+ $| 5 $: $(badcmd $1 $)
+R$*<BADCMD> $#error $@ 4.7.0 $: 421 bad command')
+dnl terminate on any bad command?
+dnl R$* $| 5 $#error $@ 4.7.0 $: 421 bad command
diff --git a/contrib/sendmail/cf/feature/delay_checks.m4 b/contrib/sendmail/cf/feature/delay_checks.m4
index 368057c991a8..630f94072922 100644
--- a/contrib/sendmail/cf/feature/delay_checks.m4
+++ b/contrib/sendmail/cf/feature/delay_checks.m4
@@ -21,5 +21,5 @@ ifelse(defn(`_ARG_'), `', `',
')
')
-dnl be backward compatible by default
+dnl be backward compatible by default
ifelse(len(X`'_ARG2_), `1', `define(`_DELAY_COMPAT_8_10_', 1)', `')
diff --git a/contrib/sendmail/cf/feature/dnsbl.m4 b/contrib/sendmail/cf/feature/dnsbl.m4
index dd8fd52583f9..4a6969687b0b 100644
--- a/contrib/sendmail/cf/feature/dnsbl.m4
+++ b/contrib/sendmail/cf/feature/dnsbl.m4
@@ -14,7 +14,7 @@ divert(0)
ifdef(`_DNSBL_R_',`dnl',`dnl
VERSIONID(`$Id: dnsbl.m4,v 8.34 2013-11-22 20:51:11 ca Exp $')
define(`_DNSBL_R_',`')
-ifelse(defn(`_ARG_'), `',
+ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(`dnsbl')')')
LOCAL_CONFIG
# map for DNS based blocklist lookups
diff --git a/contrib/sendmail/cf/feature/enhdnsbl.m4 b/contrib/sendmail/cf/feature/enhdnsbl.m4
index f0ba5c50d482..a1f5f62a004b 100644
--- a/contrib/sendmail/cf/feature/enhdnsbl.m4
+++ b/contrib/sendmail/cf/feature/enhdnsbl.m4
@@ -9,7 +9,7 @@ divert(-1)
#
#
-ifelse(defn(`_ARG_'), `',
+ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(`enhdnsbl')')')
divert(0)
ifdef(`_EDNSBL_R_',`dnl',`dnl
diff --git a/contrib/sendmail/cf/feature/nopercenthack.m4 b/contrib/sendmail/cf/feature/nopercenthack.m4
index f6c9621c970d..7f5c7485fef0 100644
--- a/contrib/sendmail/cf/feature/nopercenthack.m4
+++ b/contrib/sendmail/cf/feature/nopercenthack.m4
@@ -16,7 +16,7 @@ divert(0)
VERSIONID(`$Id: nopercenthack.m4,v 8.14 2013/01/31 15:07:00 ca Exp $')
divert(-1)
-ifelse(defn(`_ARG_'), `',
+ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(nopercenthack):
use `reject' or `nospecial'. See cf/README.
')define(`_NO_PERCENTHACK_', `e')',
diff --git a/contrib/sendmail/cf/feature/nouucp.m4 b/contrib/sendmail/cf/feature/nouucp.m4
index 5d1ee76f4dd7..98a9d69d2efb 100644
--- a/contrib/sendmail/cf/feature/nouucp.m4
+++ b/contrib/sendmail/cf/feature/nouucp.m4
@@ -16,7 +16,7 @@ divert(0)
VERSIONID(`$Id: nouucp.m4,v 8.14 2013-11-22 20:51:11 ca Exp $')
divert(-1)
-ifelse(defn(`_ARG_'), `',
+ifelse(defn(`_ARG_'), `',
`errprint(`*** ERROR: missing argument for FEATURE(nouucp):
use `reject' or `nospecial'. See cf/README.
')define(`_NO_UUCP_', `e')',
diff --git a/contrib/sendmail/cf/feature/sts.m4 b/contrib/sendmail/cf/feature/sts.m4
new file mode 100644
index 000000000000..54ffb96a9b9c
--- /dev/null
+++ b/contrib/sendmail/cf/feature/sts.m4
@@ -0,0 +1,19 @@
+divert(-1)
+#
+# Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+
+divert(-1)
+define(`_MTA_STS_', `')
+define(`_NEED_MACRO_MAP_', `1')
+ifelse(_ARG2_,`NO_SAN_TST',`',`define(`_STS_SAN', `1')')
+LOCAL_CONFIG
+O StrictTransportSecurity=true
+ifelse(_ARG2_,`NO_SAN_TST',`',`O SetCertAltnames=true')
+Ksts ifelse(defn(`_ARG_'), `', socket -d5 -T<TMPF> inet:5461@127.0.0.1,
+ defn(`_NARG_'), `', `_ARG_', `_NARG_')
diff --git a/contrib/sendmail/cf/m4/cfhead.m4 b/contrib/sendmail/cf/m4/cfhead.m4
index 7e5fa99e0ef5..64981a94f867 100644
--- a/contrib/sendmail/cf/m4/cfhead.m4
+++ b/contrib/sendmail/cf/m4/cfhead.m4
@@ -171,6 +171,12 @@ ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be before LOCA
')')
divert(9)
SLocal_srv_features')
+define(`LOCAL_CLT_FEATURES',
+`define(`_LOCAL_CLT_FEATURES_')
+ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be before LOCAL_CLT_FEATURES
+')')
+divert(9)
+SLocal_clt_features')
define(`LOCAL_TRY_TLS',
`define(`_LOCAL_TRY_TLS_')
ifdef(`_MAILER_DEFINED_',,`errprint(`*** WARNING: MAILER() should be before LOCAL_TRY_TLS
@@ -213,7 +219,7 @@ define(`SITE', `ifelse(CONCAT($'2`, $3), SU,
sinclude(_CF_DIR_`'siteconfig/$1.m4)')
define(`EXPOSED_USER', `PUSHDIVERT(5)C{E}$1
POPDIVERT`'dnl`'')
-define(`EXPOSED_USER_FILE', `PUSHDIVERT(5)F{E}$1
+define(`EXPOSED_USER_FILE', `PUSHDIVERT(5)F{E}$1
POPDIVERT`'dnl`'')
define(`LOCAL_USER', `PUSHDIVERT(5)C{L}$1
POPDIVERT`'dnl`'')
diff --git a/contrib/sendmail/cf/m4/proto.m4 b/contrib/sendmail/cf/m4/proto.m4
index 618dde00e24a..cfd71b3f9cad 100644
--- a/contrib/sendmail/cf/m4/proto.m4
+++ b/contrib/sendmail/cf/m4/proto.m4
@@ -183,16 +183,20 @@ ifdef(`confCR_FILE', `dnl
FR`'confCR_FILE',
`dnl')
+ifdef(`_ACCESS_TABLE_', `dnl
+define(`_FULL_TLS_CONNECTION_CHECK_', `1')', `dnl
+ifdef(`_MTA_STS_', `define(`_FULL_TLS_CONNECTION_CHECK_', `1')')')
define(`TLS_SRV_TAG', `"TLS_Srv"')dnl
define(`TLS_CLT_TAG', `"TLS_Clt"')dnl
define(`TLS_RCPT_TAG', `"TLS_Rcpt"')dnl
define(`TLS_TRY_TAG', `"Try_TLS"')dnl
define(`SRV_FEAT_TAG', `"Srv_Features"')dnl
+define(`CLT_FEAT_TAG', `"Clt_Features"')dnl
dnl this may be useful in other contexts too
ifdef(`_ARITH_MAP_', `', `# arithmetic map
define(`_ARITH_MAP_', `1')dnl
Karith arith')
-ifdef(`_ACCESS_TABLE_', `dnl
+ifdef(`_FULL_TLS_CONNECTION_CHECK_', `dnl
ifdef(`_MACRO_MAP_', `', `# macro storage map
define(`_MACRO_MAP_', `1')dnl
Kmacro macro')
@@ -206,6 +210,13 @@ KCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl')
ifdef(`_CERT_REGEX_SUBJECT_', `dnl
# extract relevant part from cert subject
KCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl')
+ifdef(`_MTA_STS_', `dnl
+Kstsxsni regex -a: -s3 (.*)(servername=)(.*)
+Kstsxsni2 regex -a: -s2 (.*)(servername=.*)
+Kstsxmatch regex -a: -s2 (match=)(.*)
+# flag d: turn off DANE
+Kstsxnodaneflag regex -a@ -s3 (.*)(flags=)([^;]*d)(.*)
+', `dnl')
ifdef(`LOCAL_RELAY', `dnl
# who I send unqualified names to if `FEATURE(stickyhost)' is used
@@ -502,7 +513,7 @@ _OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `0')
# maximum number of new connections per second
_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0')
-# Width of the window
+# Width of the window
_OPTION(ConnectionRateWindowSize, `confCONNECTION_RATE_WINDOW_SIZE', `60s')
# work recipient factor
@@ -688,7 +699,7 @@ _OPTION(ServerKeyFile, `confSERVER_KEY', `')
_OPTION(ClientCertFile, `confCLIENT_CERT', `')
# Client private key
_OPTION(ClientKeyFile, `confCLIENT_KEY', `')
-# File containing certificate revocation lists
+# File containing certificate revocation lists
_OPTION(CRLFile, `confCRL', `')
# Directory containing hashes pointing to certificate revocation status files
_OPTION(CRLPath, `confCRL_PATH', `')
@@ -868,7 +879,7 @@ R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr
ifdef(`_DOMAIN_TABLE_', `dnl
# look up domains in the domain table
-R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl')
+R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl')
undivert(2)dnl LOCAL_RULE_3
@@ -953,14 +964,14 @@ ifdef(`_MASQUERADE_ENTIRE_DOMAIN_',
ifdef(`_VIRTUSER_TABLE_', `dnl
dnl virtual hosts are also canonical
ifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
-`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4',
-`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')',
+`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4',
+`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')',
`dnl')
ifdef(`_GENERICS_TABLE_', `dnl
dnl hosts for genericstable are also canonical
ifdef(`_GENERICS_ENTIRE_DOMAIN_',
-`R$* < @ $* $=G > $* $: $1 < @ $2 $3 . > $4',
-`R$* < @ $=G > $* $: $1 < @ $2 . > $3')',
+`R$* < @ $* $=G > $* $: $1 < @ $2 $3 . > $4',
+`R$* < @ $=G > $* $: $1 < @ $2 . > $3')',
`dnl')
dnl remove superfluous dots (maybe repeatedly) which may have been added
dnl by one of the rules before
@@ -1062,7 +1073,7 @@ R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ...
R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here
R< @ $+ > $#error $@ 5.1.3 $: "_CODE553 User address required"
R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ...
-R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo"
+R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo"
R< @ *LOCAL* > $#error $@ 5.1.3 $: "_CODE553 User address required"
R$* $=O $* < @ *LOCAL* >
$@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ...
@@ -1105,17 +1116,17 @@ dnl are identical, i.e., if address A is mapped to A.
dnl it does not deal with multi-level recursion
# handle full domains in RHS of virtusertable
R$+ < @ $+ > $: $(macro {RecipientAddress} $) $1 < @ $2 >
-R$+ < @ $+ > $: <?> $1 < @ $2 > $| $>final $1 < @ $2 >
+R$+ < @ $+ > $: <?> $1 < @ $2 > $| $>final $1 < @ $2 >
R<?> $+ $| $+ $: $1 $(macro {RecipientAddress} $@ $2 $)
R<?> $+ $| $* $: $1',
`dnl')
R$+ $: <!> $1 Mark for lookup
dnl input: <!> local<@domain>
ifdef(`_VIRTUSER_ENTIRE_DOMAIN_',
-`R<!> $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >',
-`R<!> $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >')
+`R<!> $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >',
+`R<!> $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >')
dnl input: <result-of-lookup | @> local<@domain> | <!> local<@domain>
-R<!> $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
+R<!> $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
dnl if <@> local<@domain>: no match but try lookup
dnl user+detail: try user++@domain if detail not empty
R<@> $+ + $+ < @ $* . >
@@ -1140,14 +1151,14 @@ dnl no match
R<@> $+ $: $1
dnl remove mark
R<!> $+ $: $1
-R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
-R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2
+R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
+R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2
ifdef(`_VIRTUSER_STOP_ONE_LEVEL_RECURSION_',`dnl
# check virtuser input address against output address, if same, skip recursion
R< $+ > $+ < @ $+ > $: < $1 > $2 < @ $3 > $| $1
# it is the same: stop now
R< $+ > $+ < @ $+ > $| $&{RecipientAddress} $: $>ParseLocal $>Parse0 $>canonify $1
-R< $+ > $+ < @ $+ > $| $* $: < $1 > $2 < @ $3 >
+R< $+ > $+ < @ $+ > $| $* $: < $1 > $2 < @ $3 >
dnl', `dnl')
dnl this is not a documented option
dnl it performs no looping at all for virtusertable
@@ -1176,7 +1187,7 @@ R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name
R< $+ . > $* $: < $1 > $2 strip trailing dot
R< $+ > $* $: < $(mailertable $1 $) > $2 lookup
dnl it is $~[ instead of $- to avoid matches on IPv6 addresses
-R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved?
+R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved?
R< $+ > $* $: $>Mailertable <$1> $2 try domain',
`dnl')
undivert(4)dnl UUCP rules from `MAILER(uucp)'
@@ -1285,7 +1296,7 @@ R< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+
R< > $+ $: < ? $L > < > $(user $1 $) look up user
R< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L
R< ? $* > < $* > $+ $: < $1 > $3 $2 not found', `
-R< > $+ $: < $L > $(user $1 $) look up user
+R< > $+ $: < $L > $(user $1 $) look up user
R< $* > $+ <> $: < > $2 found; strip $L')
ifdef(`_PRESERVE_LUSER_HOST_', `dnl
R< $+ > $+ $: < $1 > $2 $&{Host}')
@@ -1336,7 +1347,7 @@ R< $+ > $* $#_RELAY_ $@ $1 $: $2 not found, direct relay',
`dnl')
###################################################################
-### Ruleset 90 -- try domain part of mailertable entry ###
+### Ruleset 90 -- try domain part of mailertable entry ###
dnl input: LeftPartOfDomain <RightPartOfDomain> FullAddress
###################################################################
@@ -1346,7 +1357,7 @@ dnl %2 is not documented in cf/README
R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
dnl it is $~[ instead of $- to avoid matches on IPv6 addresses
R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved?
-R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again
+R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again
dnl is $2 always empty?
R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "."
R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found?
@@ -1369,7 +1380,7 @@ dnl <host> address -> relay host address
SMailerToTriple=95
R< > $* $@ $1 strip off null relay
-R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
+R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4
R< error : $- : $+ > $* $#error $@ $(dequote $1 $) $: $2
R< error : $+ > $* $#error $: $1
R< local : $* > $* $>CanonLocal < $1 > $2
@@ -1408,7 +1419,7 @@ R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 >
# handle local:user syntax
R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1
-R< $+ > $* $#_LOCAL_ $@ $2 $: $1
+R< $+ > $* $#_LOCAL_ $@ $2 $: $1
###################################################################
### Ruleset 93 -- convert header names to masqueraded form ###
@@ -1440,9 +1451,9 @@ dnl no match, try @domain for exceptions
R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . >
dnl workspace: ... or <match> user <@domain>
dnl no match, try local part
-R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 >
-R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 >
-R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 >
+R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 >
+R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 >
+R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 >
R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified
R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified
R< > $* $: $1 not found',
@@ -1594,7 +1605,7 @@ dnl must not be empty
### + does lookup with and without tag
### <$4> -- passthru (additional data passed unchanged through)
dnl returns: <default> <passthru>
-dnl <result> <passthru>
+dnl <result> <passthru>
######################################################################
SD
@@ -2183,10 +2194,10 @@ R$* $| $* $: $1
dnl workspace: localpart<@domain> | localpart
ifelse(defn(`_NO_UUCP_'), `r',
`R$* ! $* < @ $* > $: <REMOTE> $2 < @ BANG_PATH >
-R$* ! $* $: <REMOTE> $2 < @ BANG_PATH >', `dnl')
+R$* ! $* $: <REMOTE> $2 < @ BANG_PATH >', `dnl')
ifelse(defn(`_NO_PERCENTHACK_'), `r',
`R$* % $* < @ $* > $: <REMOTE> $1 < @ PERCENT_HACK >
-R$* % $* $: <REMOTE> $1 < @ PERCENT_HACK >', `dnl')
+R$* % $* $: <REMOTE> $1 < @ PERCENT_HACK >', `dnl')
# anything terminating locally is ok
ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl
R$+ < @ $* $=m > $@ RELAY', `dnl')
@@ -2273,13 +2284,13 @@ RIPv6:::1 $@ RELAY originated locally
R$=R $* $@ RELAY relayable IP address
ifdef(`_ACCESS_TABLE_', `dnl
R$* $: $>A <$1> <?> <+ Connect> <$1>
-R<RELAY> $* $@ RELAY relayable IP address
+R<RELAY> $* $@ RELAY relayable IP address
ifdef(`_FFR_REJECT_IP_IN_CHECK_RCPT_',`dnl
dnl this will cause rejections in cases like:
dnl Connect:My.Host.Domain RELAY
dnl Connect:My.Net REJECT
dnl since in check_relay client_name is checked before client_addr
-R<REJECT> $* $@ REJECT rejected IP address')
+R<REJECT> $* $@ REJECT rejected IP address')
ifdef(`_ATMPF_', `R<_ATMPF_> $* $#TEMP $@ 4.3.0 $: _TMPFMSG_(`YOK1')', `dnl')
R<$*> <$*> $: $2', `dnl')
R$* $: [ $1 ] put brackets around it...
@@ -2326,7 +2337,7 @@ dnl nevertheless, removing the rule doesn't hurt.
dnl R<@> $@ RELAY
dnl workspace: <@> ${client_name} (not empty)
# pass to name server to make hostname canonical
-R<@> $* $=P $:<?> $1 $2
+R<@> $* $=P $:<?> $1 $2
R<@> $+ $:<?> $[ $1 $]
dnl workspace: <?> ${client_name} (canonified)
R$* . $1 strip trailing dots
@@ -2471,7 +2482,7 @@ dnl must not be empty
### + does lookup with and without tag
### <$4> -- passthru (additional data passed unchanged through)
dnl returns: <default> <passthru>
-dnl <result> <passthru>
+dnl <result> <passthru>
######################################################################
SF
@@ -2520,7 +2531,7 @@ dnl must not be empty
### + does lookup with and without tag
### <$4> -- passthru (additional data passed unchanged through)
dnl returns: <default> <passthru>
-dnl <result> <passthru>
+dnl <result> <passthru>
######################################################################
SE
@@ -2554,7 +2565,7 @@ dnl must not be empty
### + does lookup with and without tag
### <$4> -- passthru (additional data passed unchanged through)
dnl returns: <default> <passthru>
-dnl <result> <passthru>
+dnl <result> <passthru>
######################################################################
SU
@@ -2686,6 +2697,24 @@ R<$* _ATMPF_>$* $#temp', `dnl')
R<$+>$* $# $1')
######################################################################
+### clt_features: which features to use with a server?
+### (done in client)
+######################################################################
+Sclt_features
+ifdef(`_LOCAL_CLT_FEATURES_', `dnl
+R$* $: $1 $| $>"Local_clt_features" $1
+R$* $| $#$* $#$2
+R$* $| $* $: $1', `dnl')
+ifdef(`_ACCESS_TABLE_', `dnl
+R$* $: $>D <$&{client_name}> <?> <! CLT_FEAT_TAG> <>
+R<?>$* $: $>A <$&{client_addr}> <?> <! CLT_FEAT_TAG> <>
+R<?>$* $: <$(access CLT_FEAT_TAG`'_TAG_DELIM_ $: ? $)>
+R<?>$* $@ OK
+ifdef(`_ATMPF_', `dnl tempfail?
+R<$* _ATMPF_>$* $#temp', `dnl')
+R<$+>$* $# $1')
+
+######################################################################
### try_tls: try to use STARTTLS?
### (done in client)
######################################################################
@@ -2703,6 +2732,76 @@ ifdef(`_ATMPF_', `dnl tempfail?
R<$* _ATMPF_>$* $#error $@ 4.3.0 $: _TMPFMSG_(`TT')', `dnl')
R<NO>$* $#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]"')
+ifdef(`_MTA_STS_', `dnl
+STLS_NameInList
+R$* :$&{TLS_Name}: $* $@ ok
+R$* $@ $1
+
+dnl check SAN for STS
+SSTS_SAN
+ifdef(`_STS_SAN', `dnl
+R$* $: $&{server_name}
+dnl exact match
+R$={cert_altnames} $@ ok
+# strip only one level (no recursion!)
+R$-.$+ $: $2
+dnl wildcard: *. or just .?
+R *.$={cert_altnames} $@ ok
+dnl R .$={cert_altnames} $@ ok
+dnl always temporary error? make it an option (of the feature)?
+R$* $#error $@ 4.7.0 $: 450 $&{server_name} not listed in SANs', `dnl')
+
+dnl input: ${verify}
+dnl output: $# error ... (from TLS_connection)
+dnl everything else: ok
+SSTS_secure
+R$* $: $&{rcpt_addr} $| $1
+# no {rcpt_addr}, no STS check
+R $| $* $@ ok
+dnl canonify to extract domain part?
+R$*@$+ $| $* $2 $| $3
+R$+. $| $* $1 $| $2
+R$+ $| $* $: $(sts $1 $: none $) $| $2
+R$* <TMPF> $| $* $#error $@ 4.7.0 $: 450 STS lookup temp fail
+dnl check whether connection is "secure"
+dnl always temporary error? make it an option (of the feature)?
+R$* secure $* $| $* $@ $>"TLS_connection" $3 $| <TEMP+VERIFY:128>
+R$* $| $* $: $2
+
+dnl check STS policy: secure and match? if so, check list
+SSTS_Check
+R$* $: $&{rcpt_addr} $| $1
+# no {rcpt_addr}, no STS check
+R $| $* $@ ok
+# use the original argument for the test, not {rcpt_addr}
+R$* $| $* $: $2 $| $2
+dnl canonify to extract domain part?
+R$*@$+ $| $* $2 $| $3
+R$+. $| $* $1 $| $2
+R$* $| $* $: $(sts $1 $: none $) $| mark
+R$* <TMPF> $| $* $#error $@ 4.7.0 $: 450 STS lookup temp fail
+dnl STS check only for "secure"
+dnl do this only if {sts_sni} is set?
+dnl workspace: result of sts lookup $| mark
+R$* secure $* $| mark $: $2 $| trmatch
+dnl not "secure": no check
+R$* $| mark $@ ok
+dnl remove servername=hostname, keep match=
+R$* servername=hostname $| trmatch $: $1 $| trmatch
+dnl extra list of matches, i.e., remove match=
+R$+ $| trmatch $: : $(stsxmatch $1 $: : $)
+dnl no match= data
+R$* $| trmatch $@ $>STS_SAN
+dnl Remove trailing dots from each entry in the list;
+dnl those should not be there, but better safe than sorry.
+R$*:$+.:$* $1:$2:$3
+R:$+: $: $(macro {TLS_Name} $@ $&{server_name} $) $>TLS_NameInList :$1:
+R$* ok $@ $>STS_SAN
+R$* $: $1 $| $&{server_name}
+R:$* $| $-.$+ $: $(macro {TLS_Name} $@ .$3 $) $>TLS_NameInList :$1
+R$* ok $@ $>STS_SAN
+R:$*: $#error $@ 4.7.0 $: 450 $&{server_name} not found in " "$1', `dnl')
+
######################################################################
### tls_rcpt: is connection with server "good" enough?
### (done in client, per recipient)
@@ -2716,6 +2815,10 @@ ifdef(`_LOCAL_TLS_RCPT_', `dnl
R$* $: $1 $| $>"Local_tls_rcpt" $1
R$* $| $#$* $#$2
R$* $| $* $: $1', `dnl')
+ifdef(`_MTA_STS_', `dnl
+R$* $: $1 $| $>"STS_Check" $1
+R$* $| $#$* $#$2
+R$* $| $* $: $1', `dnl')
ifdef(`_ACCESS_TABLE_', `dnl
dnl store name of other side
R$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1
@@ -2783,6 +2886,10 @@ R$* $| $#$* $#$2
R$* $| $* $: $1', `dnl')
ifdef(`_TLS_FAILURES_',`dnl
R$* $: $(macro {saved_verify} $@ $1 $) $1')
+ifdef(`_MTA_STS_', `dnl
+R$* $: $1 $| $>"STS_secure" $1
+R$* $| $#$* $#$2
+R$* $| $* $: $1', `dnl')
ifdef(`_ACCESS_TABLE_', `dnl
dnl store name of other side
R$* $: $(macro {TLS_Name} $@ $&{server_name} $) $1
@@ -2808,11 +2915,22 @@ dnl [(PERM|TEMP)+] (VERIFY[:bits]|ENCR:bits) [+extensions]
dnl extensions: could be a list of further requirements
dnl for now: CN:string {cn_subject} == string
######################################################################
+ifdef(`TLS_PERM_ERR', `dnl
+define(`TLS_DSNCODE', `5.7.0')dnl
+define(`TLS_ERRCODE', `554')',`dnl
+define(`TLS_DSNCODE', `4.7.0')dnl
+define(`TLS_ERRCODE', `454')')dnl
+define(`SW_MSG', `TLS handshake failed.')dnl
+define(`DANE_MSG', `DANE check failed.')dnl
+define(`PROT_MSG', `STARTTLS failed.')dnl
+define(`CNF_MSG', `STARTTLS temporarily not possible.')dnl
STLS_connection
-ifdef(`_ACCESS_TABLE_', `dnl', `dnl use default error
+ifdef(`_FULL_TLS_CONNECTION_CHECK_', `dnl', `dnl use default error
dnl deal with TLS handshake failures: abort
-RSOFTWARE $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake."
-RDANE_FAIL $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') DANE check failed."
+RSOFTWARE $#error $@ TLS_DSNCODE $: "TLS_ERRCODE SW_MSG"
+RDANE_FAIL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_MSG"
+RPROTOCOL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE PROT_MSG"
+RCONFIG $#error $@ TLS_DSNCODE $: "TLS_ERRCODE CNF_MSG"
divert(-1)')
dnl common ruleset for tls_{client|server}
dnl input: ${verify} $| <ResultOfLookup> [<>]
@@ -2824,23 +2942,21 @@ dnl permanent or temporary error?
R$* $| <PERM + $={Tls} $*> $: $1 $| <503:5.7.0> <$2 $3>
R$* $| <TEMP + $={Tls} $*> $: $1 $| <403:4.7.0> <$2 $3>
dnl default case depends on TLS_PERM_ERR
-R$* $| <$={Tls} $*> $: $1 $| <ifdef(`TLS_PERM_ERR', `503:5.7.0', `403:4.7.0')> <$2 $3>
+R$* $| <$={Tls} $*> $: $1 $| <TLS_ERRCODE:TLS_DSNCODE> <$2 $3>
dnl workspace: ${verify} $| [<SMTP:ESC>] <ResultOfLookup>
-# deal with TLS handshake failures: abort
-RSOFTWARE $| <$-:$+> $* $#error $@ $2 $: $1 " TLS handshake failed."
+define(`TLS_ERRORS', `dnl
+R`'$1 $| <$-:$+> $`'* $`'#error $`'@ $`'2 $: $`'1 " $2"
dnl no <reply:dns> i.e. no requirements in the access map
dnl use default error
-RSOFTWARE $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed."
+R`'$1 $| $`'* $`'#error $`'@ TLS_DSNCODE $: "TLS_ERRCODE $2"')dnl
+# deal with TLS handshake failures: abort
+TLS_ERRORS(SOFTWARE,SW_MSG)
# deal with TLS protocol errors: abort
-RPROTOCOL $| <$-:$+> $* $#error $@ $2 $: $1 " STARTTLS failed."
-dnl no <reply:dns> i.e. no requirements in the access map
-dnl use default error
-RPROTOCOL $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') STARTTLS failed."
+TLS_ERRORS(PROTOCOL,PROT_MSG)
# deal with DANE errors: abort
-RDANE_FAIL $| <$-:$+> $* $#error $@ $2 $: $1 " DANE check failed."
-dnl no <reply:dns> i.e. no requirements in the access map
-dnl use default error
-RDANE_FAIL $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') DANE check failed."
+TLS_ERRORS(DANE_FAIL,DANE_MSG)
+# deal with CONFIG (tls_clt_features) errors: abort
+TLS_ERRORS(CONFIG,CNF_MSG)
R$* $| <$*> <VERIFY> $: <$2> <VERIFY> <> $1
dnl separate optional requirements
R$* $| <$*> <VERIFY + $+> $: <$2> <VERIFY> <$3> $1
@@ -2958,25 +3074,116 @@ R$-:$-:$- $: $2
dnl endif _ACCESS_TABLE_
divert(0)
+dnl this must also be activated without _TLS_SESSION_FEATURES_
+ifdef(`_MTA_STS_', `dnl
+dnl caller preserves workspace
+SSet_SNI
+R$* $: <$&{rcpt_addr}>
+# no {rcpt_addr}, no STS check
+R<> $@ ""
+dnl canonify to extract domain part?
+R<$*@$+> $2
+R$+. $1
+R$+ $: $(sts $1 $: none $)
+R$* <TMPF> $#error $@ 4.7.0 $: 450 STS lookup temp fail
+Rnone $@ ""
+dnl get servername=sni and store it in {sts_sni}
+dnl stsxsni extracts the value of servername= (sni)
+dnl stsxsni2 extracts servername=sni so it can be returned to the caller
+R$* secure $* $: $(stsxsni $2 $: : $) $| sts=secure; $(stsxsni2 $2 $: : $)
+dnl store {server_addr} as sni if there was a match
+dnl Note: this implies that only servername=hostname (literally!)
+dnl is only ever returned.
+R$+: $| $+ : $: $(macro {sts_sni} $@ $&{server_name} $) set $| $2
+R$* $| $* $@ $2
+R$* $@ ""
+dnl', `dnl')
+
ifdef(`_TLS_SESSION_FEATURES_', `dnl
+define(`_NEED_TLS_CLT_FEATURES')
Stls_srv_features
ifdef(`_ACCESS_TABLE_', `dnl
R$* $| $* $: $>D <$1> <?> <! TLS_Srv_Features> <$2>
-R<?> <$*> $: $>A <$1> <?> <! TLS_Srv_Features> <$1>
-R<?> <$*> $@ ""
-R<$+> <$*> $@ $1
+R<?> <$*> $: $>A <$1> <?> <! TLS_Srv_Features> <$1>
+R<?> <$*> $@ ""
+R<$+> <$*> $@ $1
+', `dnl
+R$* $@ ""')
', `dnl
-R$* $@ ""')
+ifdef(`_MTA_STS_',`define(`_NEED_TLS_CLT_FEATURES')')dnl
+')dnl
-Stls_clt_features
+ifdef(`_NEED_TLS_CLT_FEATURES', `dnl
ifdef(`_ACCESS_TABLE_', `dnl
+Stls_clt_feat_acc
R$* $| $* $: $>D <$1> <?> <! TLS_Clt_Features> <$2>
-R<?> <$*> $: $>A <$1> <?> <! TLS_Clt_Features> <$1>
-R<?> <$*> $@ ""
-R<$+> <$*> $@ $1
-', `dnl
-R$* $@ ""')
-')
+R<?> <$*> $: $>A <$1> <?> <! TLS_Clt_Features> <$1>
+R<?> <$*> $@ ""
+R<$+> <$*> $@ $1')
+
+SDANE_disabled
+dnl Note: most of this is handled in the binary.
+dnl input: access map lookup for tls_clt_features
+dnl output:
+dnl <>: disabled
+dnl <DANE>: enabled
+R$+ $: < $(stsxnodaneflag $1 $: NOFLAGS $) >
+R<$* @> $@ <>
+R$* $: < $&{sts_sni} >
+R<> $@ <>
+# check this too?
+# R$* $: $&{client_flags}
+# R$* DD $* $@ <>
+R$* $@ <DANE>
+
+SSTS_disabled
+dnl input: ignored
+dnl output:
+dnl <>: disabled
+dnl <STS>: enabled
+R$* $: $&{client_flags}
+R$* MM $* $@ <>
+dnl
+R$* $: $&{rcpt_addr} $| $1
+# no {rcpt_addr}, no STS check
+R $| $* $@ <>
+R$* $@ <STS>
+
+Stls_clt_features
+dnl host $| ip
+R$* $: $1 $| <>
+ifdef(`_ACCESS_TABLE_', `dnl
+R$* $| <> $: $1 $| $>"tls_clt_feat_acc" $1
+R$* $| $* $| $* $: $1 $| $2 $| <$3>', `dnl')
+ifdef(`_MTA_STS_', `dnl
+dnl host $| ip $| <acc result - might be empty>
+R$* $| $* $| <$*> $: $1 $| $2 $| <$3> $| $>"STS_disabled" sts
+dnl host $| ip $| <acc result - might be empty> $| STS_disabled result
+dnl disable STS check? return access result
+R$* $| $* $| <$*> $| <> $@ $3
+dnl host $| ip $| <acc result - might be empty> $| STS_disabled result
+R$* $| $* $| <$*> $| $* $: $1 $| $2 $| <$3> $| $>"DANE_disabled" $3
+dnl DANE enabled: return access result; take care of empty return
+R$* $| $* $| <$+> $| <DANE> $@ $3
+R$* $| $* $| <> $| <DANE> $@ ""
+dnl host $| ip $| <acc result - might be empty> $| <DANE_disabled result>
+R$* $| $* $| <$*> $| <$*> $: $1 $| $2 $| <$3> $| $>"Set_SNI" $1
+dnl host $| ip $| <acc result - might be empty> $| sni result
+dnl return sni result if not empty but acc is
+R$* $| $* $| <""> $| $+ $@ $3
+dnl return acc + sni result if not empty
+R$* $| $* $| <$+;> $| $+ $@ $3 ; $4
+dnl return acc + sni result if not empty
+R$* $| $* $| <$+> $| $+ $@ $3 ; $4
+dnl return sni result if not empty
+R$* $| $* $| <> $| $+ $@ $3
+dnl remove sni result
+R$* $| $* $| $* $| $* $: $1 $| $2 $| $3
+', `dnl')
+dnl host $| ip $| <acc result - might be empty>
+R$* $| $* $| <""> $@ ""
+R$* $| $* $| <$+> $@ $3
+R$* $@ ""')
######################################################################
### RelayTLS: allow relaying based on TLS authentication
@@ -3046,7 +3253,7 @@ dnl', `dnl')')
ifdef(`_RATE_CONTROL_',`dnl
######################################################################
-### RateControl:
+### RateControl:
### Parameters: ignored
### return: $#error or OK
######################################################################
@@ -3068,7 +3275,7 @@ R<$+> $| TRUE $#error $@ 4.3.2 $: _RATE_CONTROL_REPLY Connection rate limit exce
ifdef(`_CONN_CONTROL_',`dnl
######################################################################
-### ConnControl:
+### ConnControl:
### Parameters: ignored
### return: $#error or OK
######################################################################
@@ -3108,3 +3315,10 @@ _MAIL_FILTERS_
######################################################################
undivert(7)dnl MAILER_DEFINITIONS
+
+dnl Helper ruleset for -bt mode to invoke rulesets
+dnl which take two arguments separated by $|
+dnl For example:
+dnl Start,check_relay host.name $| I.P.V.4
+dnl SStart
+dnl R$* $$| $* $: $1 $| $2
diff --git a/contrib/sendmail/cf/m4/version.m4 b/contrib/sendmail/cf/m4/version.m4
index dadff627bb2e..3942ca1a0691 100644
--- a/contrib/sendmail/cf/m4/version.m4
+++ b/contrib/sendmail/cf/m4/version.m4
@@ -15,4 +15,4 @@ VERSIONID(`$Id: version.m4,v 8.237 2014-01-27 12:55:17 ca Exp $')
#
divert(0)
# Configuration version number
-DZ8.16.1`'ifdef(`confCF_VERSION', `/confCF_VERSION')
+DZ8.17.1`'ifdef(`confCF_VERSION', `/confCF_VERSION')
diff --git a/contrib/sendmail/cf/mailer/local.m4 b/contrib/sendmail/cf/mailer/local.m4
index 85d24f32a2a6..1a9e4a3a1309 100644
--- a/contrib/sendmail/cf/mailer/local.m4
+++ b/contrib/sendmail/cf/mailer/local.m4
@@ -79,7 +79,7 @@ R$* $: $>MasqHdr $1 do all-masquerading')',
#
SAddDomain
ifdef(`_ALWAYS_ADD_DOMAIN_', `dnl
-R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified
+R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified
ifelse(len(X`'_ALWAYS_ADD_DOMAIN_),`1',`
R$+ $@ $1 < @ *LOCAL* > add local qualification',
`R$+ $@ $1 < @ _ALWAYS_ADD_DOMAIN_ > add qualification')',