]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.3.16 v3.3.16
authorWietse Venema <wietse@porcupine.org>
Sun, 17 Jan 2021 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 18 Jan 2021 07:04:36 +0000 (05:04 -0200)
19 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp.8.html
postfix/makedefs
postfix/man/man5/postconf.5
postfix/man/man8/smtp.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/dns/Makefile.in
postfix/src/dns/dns.h
postfix/src/dns/dns_lookup.c
postfix/src/dns/dns_sec.c [new file with mode: 0644]
postfix/src/dns/test_dns_lookup.c
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.c

index 4d6baafdd501a51cd49184b58d1108e39e1e0c37..67706bcadfff43d88d26db16d817405b585670e2 100644 (file)
@@ -23696,3 +23696,26 @@ Apologies for any names omitted.
 
        Bugfix (introduced: Postfix 2.3): static maps did not free
        their casefolding buffer. File: util/dict_static.c.
+
+20210116
+
+       Feature: when a Postfix program makes a DNS query that
+       requests DNSSEC validation (usually for Postfix DANE support)
+       but the DNS response is not DNSSEC validated, Postfix will
+       send a DNS query configured with the "dnssec_probe" parameter
+       to determine if DNSSEC support is available, and logs a
+       warning if it is not. By default, the probe has type "ns"
+       and domain name ".". The probe is sent once per process
+       lifetime. Files: dns/dns.h, dns/dns_lookup.c, dns/dns_sec.c,
+       test_dns_lookup.c, global/mail_params.[hc], mantools/postlink.
+
+       The makedefs script no longer disables DNSSEC when Postfix
+       is built with libc-musl. Instead Postfix will rely on the
+       new dnssec_probe feature, and will log a warning when Postfix
+       requests DNSSEC validation, but the infrastructure does not
+       validate DNSSEC signatures. File: makedefs.
+
+       The default "smtp_tls_dane_insecure_mx_policy = dane" was
+       causing unnecessary dnssec_probe activity. The default is now
+       "dane" when smtp_tls_security_level is "dane", otherwise it is
+       "may". File: global/mail_params.h.
index f549d5efe738e8966d5df8fafe8a2fe057112e5c..04fbe92150f9b5ef55ddefd46ff56a3563080a2b 100644 (file)
@@ -16,6 +16,47 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 3.1 or earlier, read RELEASE_NOTES-3.2
 before proceeding.
 
+Runtime detection of DNSSEC support
+-----------------------------------
+
+The Postfix build system will no longer automatically disable DNSSEC
+support when it determines that Postfix will use libc-musl. This removes
+the earlier libc-musl workaround for Postfix 3.2.15, 3.3.10, 3.4.12,
+and 3.5.2.
+
+Now, when a Postfix process requests DNSSEC support (typically, for
+Postfix DANE support), the process may do a runtime test to determine if
+DNSSEC validation is available. DNSSEC support may be broken because of
+local configuration, libc incompatibility, or other infrastructure issues.
+
+Background: DNSSEC validation is needed for Postfix DANE support;
+this ensures that Postfix receives TLSA records with secure TLS
+server certificate info. When DNSSEC validation is unavailable,
+mail deliveries using opportunistic DANE will not be protected by
+server certificate info in TLSA records, and mail deliveries using
+mandatory DANE will not be made at all.
+
+The dnssec_probe parameter specifies the DNS query type (default:
+"ns") and DNS query name (default: ".") that Postfix may use to
+determine whether DNSSEC validation is available. Specify an empty
+value to disable this feature.
+
+By default, a Postfix process will send a DNSSEC probe after 1) the
+process made a DNS query that requested DNSSEC validation, 2) the
+process did not receive a DNSSEC validated response to this query
+or to an earlier query, and 3) the process did not already send a
+DNSSEC probe.
+
+When the DNSSEC probe has no response, or when the response is not
+DNSSEC validated, Postfix logs a warning that DNSSEC validation may
+be unavailable. Examples:
+
+warning: DNSSEC validation may be unavailable
+warning: reason: dnssec_probe 'ns:.' received a response that is not DNSSEC validated
+warning: reason: dnssec_probe 'ns:.' received no response: Server failure
+
+This feature was backported from Postfix 3.6.
+
 libc-musl workaround for Postfix 3.2.15, 3.3.10, 3.4.12, and 3.5.2
 ------------------------------------------------------------------
 
index 8e9e825c8f3c352b3da5d76925b2d3923486941c..80c0c992e48010c8a61b237478ef7fcb64360f7a 100644 (file)
@@ -310,6 +310,13 @@ SMTP(8)                                                                SMTP(8)
               IPv6 addresses, ensure that the Postfix SMTP client can try both
               address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
 
+       Available in Postfix 3.3.16 and later:
+
+       <b><a href="postconf.5.html#dnssec_probe">dnssec_probe</a> (ns:.)</b>
+              The DNS query type (default: "ns") and DNS query name  (default:
+              ".") that Postfix may use to determine whether DNSSEC validation
+              is available.
+
 <b>MIME PROCESSING CONTROLS</b>
        Available in Postfix version 2.0 and later:
 
index 1e148cfbe51e4f12160c7181ae18a992ab95e233..3eea6c6c8aa25bbbd059f72045c96cd1a773f707 100644 (file)
@@ -3016,6 +3016,66 @@ service performs DNS white/blacklist lookups. </p>
 <p> This feature is available in Postfix 2.8 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="dnssec_probe">dnssec_probe</a>
+(default: ns:.)</b></DT><DD>
+
+<p> The DNS query type (default: "ns") and DNS query name (default:
+".") that Postfix may use to determine whether DNSSEC validation
+is available.
+</p>
+
+<p> Background: DNSSEC validation is needed for Postfix DANE support;
+this ensures that Postfix receives TLSA records with secure TLS
+server certificate info. When DNSSEC validation is unavailable,
+mail deliveries using <i>opportunistic</i> DANE will not be protected
+by server certificate info in TLSA records, and mail deliveries
+using <i>mandatory</i> DANE will not be made at all. </p>
+
+<p> By default, a Postfix process will send a DNSSEC probe after
+1) the process made a DNS query that requested DNSSEC validation,
+2) the process did not receive a DNSSEC validated response to this
+query or to an earlier query, and 3) the process did not already
+send a DNSSEC probe. <p>
+
+<p> When the DNSSEC probe has no response, or when the response is
+not DNSSEC validated, Postfix logs a warning that DNSSEC validation
+may be unavailable. </p>
+
+<p> Example: </p>
+
+<pre>
+warning: DNSSEC validation may be unavailable
+warning: reason: <a href="postconf.5.html#dnssec_probe">dnssec_probe</a> 'ns:.' received a response that is not DNSSEC validated
+warning: reason: <a href="postconf.5.html#dnssec_probe">dnssec_probe</a> 'ns:.' received no response: Server failure
+</pre>
+
+<p> Possible reasons why DNSSEC validation may be unavailable: </p>
+
+<ul>
+
+<li> The local /etc/resolv.conf file specifies a DNS resolver that
+does not validate DNSSEC signatures (that's
+$<a href="postconf.5.html#queue_directory">queue_directory</a>/etc/resolv.conf when a Postfix daemon runs in a
+chroot jail).
+
+<li> The local system library does not pass on the "DNSSEC validated"
+bit to Postfix, or Postfix does not know how to ask the library to
+do that.
+
+</ul>
+
+<p> By default, the DNSSEC probe asks for the DNS root zone NS
+records, because resolvers should always have that information
+cached. If Postfix runs on a network where the DNS root zone is not
+reachable, specify a different probe, or specify an empty <a href="postconf.5.html#dnssec_probe">dnssec_probe</a>
+value to disable the feature. </p>
+
+<p> This feature was backported from Postfix 3.6 to Postfix versions
+3.5.9, 3.4.19, 3.3.16. 3.2.21. </p>
+
+
 </DD>
 
 <DT><b><a name="dont_remove">dont_remove</a>
@@ -12000,7 +12060,7 @@ and opportunistic TLS always uses "export" or better (i.e. all) ciphers. </p>
 </DD>
 
 <DT><b><a name="smtp_tls_dane_insecure_mx_policy">smtp_tls_dane_insecure_mx_policy</a>
-(default: dane)</b></DT><DD>
+(default: see "postconf -d" output)</b></DT><DD>
 
 <p> The TLS policy for MX hosts with "secure" TLSA records when the
 nexthop destination security level is <b>dane</b>, but the MX
@@ -12024,6 +12084,12 @@ authentication succeeds, it will be logged only as "Trusted", not
 "Verified", because the MX host name could have been forged.  </dd>
 </dl>
 
+<p> The default setting for Postfix &ge; 3.6 is "dane" with
+"<a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> = dane", otherwise "may". This behavior
+was backported to Postfix versions 3.5.9, 3.4.19, 3.3.16. 3.2.21.
+With earlier
+Postfix versions the default setting was always "dane". </p>
+
 <p> Though with "insecure" MX records an active attacker can
 compromise SMTP transport security by returning forged MX records,
 such attacks are "tamper-evident" since any forged MX hostnames
index 8e9e825c8f3c352b3da5d76925b2d3923486941c..80c0c992e48010c8a61b237478ef7fcb64360f7a 100644 (file)
@@ -310,6 +310,13 @@ SMTP(8)                                                                SMTP(8)
               IPv6 addresses, ensure that the Postfix SMTP client can try both
               address types before it runs into the <a href="postconf.5.html#smtp_mx_address_limit">smtp_mx_address_limit</a>.
 
+       Available in Postfix 3.3.16 and later:
+
+       <b><a href="postconf.5.html#dnssec_probe">dnssec_probe</a> (ns:.)</b>
+              The DNS query type (default: "ns") and DNS query name  (default:
+              ".") that Postfix may use to determine whether DNSSEC validation
+              is available.
+
 <b>MIME PROCESSING CONTROLS</b>
        Available in Postfix version 2.0 and later:
 
index eacef30b351f167698cfd13a82916a69fe2cb9c0..a44700e2f2692a18eac2c2813eefc1a3a60caccb 100644 (file)
@@ -226,19 +226,6 @@ case $# in
  *) echo usage: $0 [system release] 1>&2; exit 1;;
 esac
 
-case "$SYSTEM" in
- Linux)
-    case "`PATH=/bin:/usr/bin ldd /bin/sh`" in
-     *-musl-*)
-       case "$CCARGS" in
-        *-DNO_DNSSEC*) ;;
-        *) echo Warning: libc-musl breaks DANE/TLSA security. 1>&2
-           echo This build will not support DANE/TLSA. 1>&2
-           CCARGS="$CCARGS -DNO_DNSSEC";;
-       esac;;
-    esac;;
-esac
-
 case "$SYSTEM.$RELEASE" in
    SCO_SV.3.2) SYSTYPE=SCO5
                # Use the native compiler by default
index cd513529c8a4b0b206e209b075e388620c18dd7b..4e1272f4eb14faf2982616c43cea07d491cc2cda 100644 (file)
@@ -1887,6 +1887,60 @@ The name of the \fBdnsblog\fR(8) service entry in master.cf. This
 service performs DNS white/blacklist lookups.
 .PP
 This feature is available in Postfix 2.8 and later.
+.SH dnssec_probe (default: ns:.)
+The DNS query type (default: "ns") and DNS query name (default:
+".") that Postfix may use to determine whether DNSSEC validation
+is available.
+.PP
+Background: DNSSEC validation is needed for Postfix DANE support;
+this ensures that Postfix receives TLSA records with secure TLS
+server certificate info. When DNSSEC validation is unavailable,
+mail deliveries using \fIopportunistic\fR DANE will not be protected
+by server certificate info in TLSA records, and mail deliveries
+using \fImandatory\fR DANE will not be made at all.
+.PP
+By default, a Postfix process will send a DNSSEC probe after
+1) the process made a DNS query that requested DNSSEC validation,
+2) the process did not receive a DNSSEC validated response to this
+query or to an earlier query, and 3) the process did not already
+send a DNSSEC probe.
+.PP
+When the DNSSEC probe has no response, or when the response is
+not DNSSEC validated, Postfix logs a warning that DNSSEC validation
+may be unavailable.
+.PP
+Example:
+.PP
+.nf
+.na
+.ft C
+warning: DNSSEC validation may be unavailable
+warning: reason: dnssec_probe 'ns:.' received a response that is not DNSSEC validated
+warning: reason: dnssec_probe 'ns:.' received no response: Server failure
+.fi
+.ad
+.ft R
+.PP
+Possible reasons why DNSSEC validation may be unavailable:
+.IP \(bu
+The local /etc/resolv.conf file specifies a DNS resolver that
+does not validate DNSSEC signatures (that's
+$queue_directory/etc/resolv.conf when a Postfix daemon runs in a
+chroot jail).
+.IP \(bu
+The local system library does not pass on the "DNSSEC validated"
+bit to Postfix, or Postfix does not know how to ask the library to
+do that.
+.br
+.PP
+By default, the DNSSEC probe asks for the DNS root zone NS
+records, because resolvers should always have that information
+cached. If Postfix runs on a network where the DNS root zone is not
+reachable, specify a different probe, or specify an empty dnssec_probe
+value to disable the feature.
+.PP
+This feature was backported from Postfix 3.6 to Postfix versions
+3.5.9, 3.4.19, 3.3.16. 3.2.21.
 .SH dont_remove (default: 0)
 Don't remove queue files and save them to the "saved" mail queue.
 This is a debugging aid.  To inspect the envelope information and
@@ -7593,7 +7647,7 @@ ciphers on a per\-destination basis.
 This feature is available in Postfix 2.6 and later. With earlier Postfix
 releases only the smtp_tls_mandatory_ciphers parameter is implemented,
 and opportunistic TLS always uses "export" or better (i.e. all) ciphers.
-.SH smtp_tls_dane_insecure_mx_policy (default: dane)
+.SH smtp_tls_dane_insecure_mx_policy (default: see "postconf \-d" output)
 The TLS policy for MX hosts with "secure" TLSA records when the
 nexthop destination security level is \fBdane\fR, but the MX
 record was found via an "insecure" MX lookup.  The choices are:
@@ -7614,6 +7668,12 @@ authentication succeeds, it will be logged only as "Trusted", not
 "Verified", because the MX host name could have been forged.
 .br
 .br
+The default setting for Postfix >= 3.6 is "dane" with
+"smtp_tls_security_level = dane", otherwise "may". This behavior
+was backported to Postfix versions 3.5.9, 3.4.19, 3.3.16. 3.2.21.
+With earlier
+Postfix versions the default setting was always "dane".
+.PP
 Though with "insecure" MX records an active attacker can
 compromise SMTP transport security by returning forged MX records,
 such attacks are "tamper\-evident" since any forged MX hostnames
index 0d810e5ad540b33880f92c50af517b88ed8da188..9a49d3db0afb944c85925d8d9f423425323c09f4 100644 (file)
@@ -291,6 +291,12 @@ Available in Postfix version 3.3 and later:
 When a remote destination resolves to a combination of IPv4 and
 IPv6 addresses, ensure that the Postfix SMTP client can try both
 address types before it runs into the smtp_mx_address_limit.
+.PP
+Available in Postfix 3.3.16 and later:
+.IP "\fBdnssec_probe (ns:.)\fR"
+The DNS query type (default: "ns") and DNS query name (default:
+".") that Postfix may use to determine whether DNSSEC validation
+is available.
 .SH "MIME PROCESSING CONTROLS"
 .na
 .nf
index 86c6e3740bdaff80ed4a17df0e498e7073536ec2..047002cd2855578ec2db50fee8831abcc76e4eb7 100755 (executable)
@@ -690,6 +690,7 @@ while (<>) {
     s;\bsmtp_per_record_deadline\b;<a href="postconf.5.html#smtp_per_record_deadline">$&</a>;g;
     s;\bsmtp_send_dummy_mail_auth\b;<a href="postconf.5.html#smtp_send_dummy_mail_auth">$&</a>;g;
     s;\bsmtp_balance_inet_protocols\b;<a href="postconf.5.html#smtp_balance_inet_protocols">$&</a>;g;
+    s;\bdnssec_probe\b;<a href="postconf.5.html#dnssec_probe">$&</a>;g;
     s;\bsmtpd_enforce_tls\b;<a href="postconf.5.html#smtpd_enforce_tls">$&</a>;g;
     s;\bsmtpd_sasl_tls_security_options\b;<a href="postconf.5.html#smtpd_sasl_tls_security_options">$&</a>;g;
     s;\bsmtpd_sasl_type\b;<a href="postconf.5.html#smtpd_sasl_type">$&</a>;g;
index d80af287fe8a42d55ab5ba880259896c3ddc0dde..04ea741f108505d62589caac83d19746d71c1624 100644 (file)
@@ -16672,7 +16672,7 @@ clients).  </p>
 This feature is available in Postfix 3.1 and later.
 </p>
 
-%PARAM smtp_tls_dane_insecure_mx_policy dane
+%PARAM smtp_tls_dane_insecure_mx_policy see "postconf -d" output
 
 <p> The TLS policy for MX hosts with "secure" TLSA records when the
 nexthop destination security level is <b>dane</b>, but the MX
@@ -16696,6 +16696,12 @@ authentication succeeds, it will be logged only as "Trusted", not
 "Verified", because the MX host name could have been forged.  </dd>
 </dl>
 
+<p> The default setting for Postfix &ge; 3.6 is "dane" with
+"smtp_tls_security_level = dane", otherwise "may". This behavior
+was backported to Postfix versions 3.5.9, 3.4.19, 3.3.16. 3.2.21.
+With earlier
+Postfix versions the default setting was always "dane". </p>
+
 <p> Though with "insecure" MX records an active attacker can
 compromise SMTP transport security by returning forged MX records,
 such attacks are "tamper-evident" since any forged MX hostnames
@@ -16849,3 +16855,59 @@ environment variable, or from the UNIX password file. </p>
 </ul>
 
 <p> This feature is available in Postfix 3.3 and later. </p>
+
+%PARAM dnssec_probe ns:.
+
+<p> The DNS query type (default: "ns") and DNS query name (default:
+".") that Postfix may use to determine whether DNSSEC validation
+is available.
+</p>
+
+<p> Background: DNSSEC validation is needed for Postfix DANE support;
+this ensures that Postfix receives TLSA records with secure TLS
+server certificate info. When DNSSEC validation is unavailable,
+mail deliveries using <i>opportunistic</i> DANE will not be protected
+by server certificate info in TLSA records, and mail deliveries
+using <i>mandatory</i> DANE will not be made at all. </p>
+
+<p> By default, a Postfix process will send a DNSSEC probe after
+1) the process made a DNS query that requested DNSSEC validation,
+2) the process did not receive a DNSSEC validated response to this
+query or to an earlier query, and 3) the process did not already
+send a DNSSEC probe. <p>
+
+<p> When the DNSSEC probe has no response, or when the response is
+not DNSSEC validated, Postfix logs a warning that DNSSEC validation
+may be unavailable. </p>
+
+<p> Example: </p>
+
+<pre>
+warning: DNSSEC validation may be unavailable
+warning: reason: dnssec_probe 'ns:.' received a response that is not DNSSEC validated
+warning: reason: dnssec_probe 'ns:.' received no response: Server failure
+</pre>
+
+<p> Possible reasons why DNSSEC validation may be unavailable: </p>
+
+<ul>
+
+<li> The local /etc/resolv.conf file specifies a DNS resolver that
+does not validate DNSSEC signatures (that's
+$queue_directory/etc/resolv.conf when a Postfix daemon runs in a
+chroot jail).
+
+<li> The local system library does not pass on the "DNSSEC validated"
+bit to Postfix, or Postfix does not know how to ask the library to
+do that.
+
+</ul>
+
+<p> By default, the DNSSEC probe asks for the DNS root zone NS
+records, because resolvers should always have that information
+cached. If Postfix runs on a network where the DNS root zone is not
+reachable, specify a different probe, or specify an empty dnssec_probe
+value to disable the feature. </p>
+
+<p> This feature was backported from Postfix 3.6 to Postfix versions
+3.5.9, 3.4.19, 3.3.16. 3.2.21. </p>
index 1913bc3f001ffaf9cae66282730f32c639d308d7..0af33f4aba3cbf6fccbfd500f05e5dbc45891cdd 100644 (file)
@@ -1,10 +1,10 @@
 SHELL  = /bin/sh
 SRCS   = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c dns_rr_to_pa.c \
        dns_sa_to_rr.c dns_rr_eq_sa.c dns_rr_to_sa.c dns_strrecord.c \
-       dns_rr_filter.c dns_str_resflags.c
+       dns_rr_filter.c dns_str_resflags.c dns_sec.c
 OBJS   = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o dns_rr_to_pa.o \
        dns_sa_to_rr.o dns_rr_eq_sa.o dns_rr_to_sa.o dns_strrecord.o \
-       dns_rr_filter.o dns_str_resflags.o
+       dns_rr_filter.o dns_str_resflags.o dns_sec.o
 HDRS   = dns.h
 TESTSRC        = test_dns_lookup.c test_alias_token.c
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -76,7 +76,7 @@ update: $(LIB_DIR)/$(LIB) $(HDRS)
        done
        cd $(INC_DIR); chmod 644 $(HDRS)
 
-test_dns_lookup: test_dns_lookup.c $(LIB) $(LIBS)
+test_dns_lookup: test_dns_lookup.c all $(LIB) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
 
 dns_rr_to_pa: $(LIB) $(LIBS)
@@ -354,6 +354,18 @@ dns_sa_to_rr.o: ../../include/vbuf.h
 dns_sa_to_rr.o: ../../include/vstring.h
 dns_sa_to_rr.o: dns.h
 dns_sa_to_rr.o: dns_sa_to_rr.c
+dns_sec.o: ../../include/check_arg.h
+dns_sec.o: ../../include/mail_params.h
+dns_sec.o: ../../include/msg.h
+dns_sec.o: ../../include/myaddrinfo.h
+dns_sec.o: ../../include/mymalloc.h
+dns_sec.o: ../../include/sock_addr.h
+dns_sec.o: ../../include/split_at.h
+dns_sec.o: ../../include/sys_defs.h
+dns_sec.o: ../../include/vbuf.h
+dns_sec.o: ../../include/vstring.h
+dns_sec.o: dns.h
+dns_sec.o: dns_sec.c
 dns_str_resflags.o: ../../include/check_arg.h
 dns_str_resflags.o: ../../include/myaddrinfo.h
 dns_str_resflags.o: ../../include/name_mask.h
index b8c4c4aa5cef911e7ffb124162c56d298c0a22b6..3631d231868b354afb1b44b9192d5687bf99d76b 100644 (file)
@@ -244,7 +244,12 @@ extern int dns_lookup_rv(const char *, unsigned, DNS_RR **, VSTRING *,
        (lflags), (ltype))
 
  /*
-  * Request flags.
+  * The dns_lookup() rflag that requests DNSSEC validation.
+  */
+#define DNS_WANT_DNSSEC_VALIDATION(rflags)     ((rflags) & RES_USE_DNSSEC)
+
+ /*
+  * lflags.
   */
 #define DNS_REQ_FLAG_STOP_OK   (1<<0)
 #define DNS_REQ_FLAG_STOP_INVAL        (1<<1)
@@ -309,6 +314,18 @@ extern int dns_rr_filter_execute(DNS_RR **);
   */
 const char *dns_str_resflags(unsigned long);
 
+ /*
+  * dns_sec.c.
+  */
+#define DNS_SEC_FLAG_AVAILABLE (1<<0)  /* got some DNSSEC validated reply */
+#define DNS_SEC_FLAG_DONT_PROBE        (1<<1)  /* probe already sent, or disabled */
+
+#define DNS_SEC_STATS_SET(flags) (dns_sec_stats |= (flags))
+#define DNS_SEC_STATS_TEST(flags) (dns_sec_stats & (flags))
+
+extern int dns_sec_stats;              /* See DNS_SEC_FLAG_XXX above */
+extern void dns_sec_probe(int);
+
 /* LICENSE
 /* .ad
 /* .fi
index 2ae64836aa287c1f7a97f2698dbf986aa9ac6bf0..68e243ba07c1e8a09e04cac0a433964f280ced71 100644 (file)
 /*     Pointer to storage for the reply RCODE value. This gives
 /*     more detailed information than DNS_FAIL, DNS_RETRY, etc.
 /* DIAGNOSTICS
+/*     If DNSSEC validation is requested but the response is not
+/*     DNSSEC validated, dns_lookup() will send a one-time probe
+/*     query as configured with the \fBdnssec_probe\fR configuration
+/*     parameter, and will log a warning when the probe response
+/*     was not DNSSEC validated.
+/* .PP
 /*     dns_lookup() returns one of the following codes and sets the
 /*     \fIwhy\fR argument accordingly:
 /* .IP DNS_OK
@@ -458,7 +464,7 @@ static int dns_query(const char *name, int type, unsigned flags,
      */
 #define XTRA_FLAGS (RES_USE_EDNS0 | RES_TRUSTAD)
 
-    if (flags & RES_USE_DNSSEC)
+    if (DNS_WANT_DNSSEC_VALIDATION(flags))
        flags |= (RES_USE_EDNS0 | RES_TRUSTAD);
 
     /*
@@ -487,6 +493,8 @@ static int dns_query(const char *name, int type, unsigned flags,
        _res.options |= saved_options;
        reply_header = (HEADER *) reply->buf;
        reply->rcode = reply_header->rcode;
+       if ((reply->dnssec_ad = !!reply_header->ad) != 0)
+           DNS_SEC_STATS_SET(DNS_SEC_FLAG_AVAILABLE);
        if (h_errno != 0) {
            if (why)
                vstring_sprintf(why, "Host or domain name not found. "
@@ -538,13 +546,8 @@ static int dns_query(const char *name, int type, unsigned flags,
 
     /*
      * Initialize the reply structure. Some structure members are filled on
-     * the fly while the reply is being parsed.  Coerce AD bit to boolean.
+     * the fly while the reply is being parsed.
      */
-#if RES_USE_DNSSEC != 0
-    reply->dnssec_ad = (flags & RES_USE_DNSSEC) ? !!reply_header->ad : 0;
-#else
-    reply->dnssec_ad = 0;
-#endif
     SET_HAVE_DNS_REPLY_PACKET(reply, len);
     reply->query_start = reply->buf + sizeof(HEADER);
     reply->answer_start = 0;
@@ -862,7 +865,9 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
            CORRUPT(DNS_RETRY);
        if ((status = dns_get_fixed(pos, &fixed)) != DNS_OK)
            CORRUPT(status);
-       if (!valid_rr_name(rr_name, "resource name", fixed.type, reply))
+       if (strcmp(orig_name, ".") == 0 && *rr_name == 0)
+            /* Allow empty response name for root queries. */ ;
+       else if (!valid_rr_name(rr_name, "resource name", fixed.type, reply))
            CORRUPT(DNS_INVAL);
        if (fqdn)
            vstring_strcpy(fqdn, rr_name);
@@ -950,7 +955,7 @@ int     dns_lookup_x(const char *name, unsigned type, unsigned flags,
     /*
      * The Linux resolver misbehaves when given an invalid domain name.
      */
-    if (!valid_hostname(name, DONT_GRIPE)) {
+    if (strcmp(name, ".") && !valid_hostname(name, DONT_GRIPE)) {
        if (why)
            vstring_sprintf(why,
                   "Name service error for %s: invalid host or domain name",
@@ -987,6 +992,10 @@ int     dns_lookup_x(const char *name, unsigned type, unsigned flags,
                (void) dns_get_answer(orig_name, &reply, T_SOA, rrlist, fqdn,
                                      cname, c_len, &maybe_secure);
            }
+           if (DNS_WANT_DNSSEC_VALIDATION(flags)
+               && !DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE | \
+                                      DNS_SEC_FLAG_DONT_PROBE))
+               dns_sec_probe(flags);           /* XXX Clobbers 'reply' */
            return (status);
        }
 
@@ -996,6 +1005,10 @@ int     dns_lookup_x(const char *name, unsigned type, unsigned flags,
         */
        status = dns_get_answer(orig_name, &reply, type, rrlist, fqdn,
                                cname, c_len, &maybe_secure);
+       if (DNS_WANT_DNSSEC_VALIDATION(flags)
+           && !DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE | \
+                                  DNS_SEC_FLAG_DONT_PROBE))
+           dns_sec_probe(flags);               /* XXX Clobbers 'reply' */
        switch (status) {
        default:
            if (why)
diff --git a/postfix/src/dns/dns_sec.c b/postfix/src/dns/dns_sec.c
new file mode 100644 (file)
index 0000000..849627e
--- /dev/null
@@ -0,0 +1,144 @@
+/*++
+/* NAME
+/*     dns_sec 3
+/* SUMMARY
+/*     DNSSEC validation availability
+/* SYNOPSIS
+/*     #include <dns.h>
+/*
+/*     DNS_SEC_STATS_SET(
+/*     int     flags)
+/*
+/*     DNS_SEC_STATS_TEST(
+/*     int     flags)
+/*
+/*     void    dns_sec_probe(
+/*     int     rflags)
+/* DESCRIPTION
+/*     This module maintains information about the availability of
+/*     DNSSEC validation, in global flags that summarize
+/*     process-lifetime history.
+/* .IP DNS_SEC_FLAG_AVAILABLE
+/*     The process has received at least one DNSSEC validated
+/*     response to a query that requested DNSSEC validation.
+/* .IP DNS_SEC_FLAG_DONT_PROBE
+/*     The process has sent a DNSSEC probe (see below), or DNSSEC
+/*     probing is disabled by configuration.
+/* .PP
+/*     DNS_SEC_STATS_SET() sets one or more DNS_SEC_FLAG_* flags,
+/*     and DNS_SEC_STATS_TEST() returns non-zero if any of the
+/*     specified flags is set.
+/*
+/*     dns_sec_probe() generates a query to the target specified
+/*     with the \fBdnssec_probe\fR configuration parameter. It
+/*     sets the DNS_SEC_FLAG_DONT_PROBE flag, and it calls
+/*     dns_lookup() which sets DNS_SEC_FLAG_AVAILABLE if it receives
+/*     a DNSSEC validated response. Preconditions:
+/* .IP \(bu
+/*     The rflags argument must request DNSSEC validation (in the
+/*     same manner as dns_lookup() rflags argument).
+/* .IP \(bu
+/*     The DNS_SEC_FLAG_AVAILABLE and DNS_SEC_FLAG_DONT_PROBE
+/*     flags must be false.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+#include <sys_defs.h>
+
+ /*
+  * Utility library.
+  */
+#include <msg.h>
+#include <mymalloc.h>
+#include <split_at.h>
+#include <vstring.h>
+
+ /*
+  * Global library.
+  */
+#include <mail_params.h>
+
+ /*
+  * DNS library.
+  */
+#include <dns.h>
+
+int     dns_sec_stats;
+
+/* dns_sec_probe - send a probe to establish DNSSEC viability */
+
+void    dns_sec_probe(int rflags)
+{
+    const char myname[] = "dns_sec_probe";
+    char   *saved_dnssec_probe;
+    char   *qname;
+    int     qtype;
+    DNS_RR *rrlist = 0;
+    int     dns_status;
+    VSTRING *why;
+
+    /*
+     * Sanity checks.
+     */
+    if (!DNS_WANT_DNSSEC_VALIDATION(rflags))
+       msg_panic("%s: DNSSEC is not requested", myname);
+    if (DNS_SEC_STATS_TEST(DNS_SEC_FLAG_DONT_PROBE))
+       msg_panic("%s: DNSSEC probe was already sent, or probing is disabled",
+                 myname);
+    if (DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
+       msg_panic("%s: already have validated DNS response", myname);
+
+    /*
+     * Don't recurse.
+     */
+    DNS_SEC_STATS_SET(DNS_SEC_FLAG_DONT_PROBE);
+
+    /*
+     * Don't probe.
+     */
+    if (*var_dnssec_probe == 0)
+       return;
+
+    /*
+     * Parse the probe spec. Format is type:resource.
+     */
+    saved_dnssec_probe = mystrdup(var_dnssec_probe);
+    if ((qname = split_at(saved_dnssec_probe, ':')) == 0 || *qname == 0
+       || (qtype = dns_type(saved_dnssec_probe)) == 0)
+       msg_fatal("malformed %s value: %s format is qtype:qname",
+                 VAR_DNSSEC_PROBE, var_dnssec_probe);
+
+    why = vstring_alloc(100);
+    dns_status = dns_lookup(qname, qtype, rflags, &rrlist, (VSTRING *) 0, why);
+    if (!DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
+       msg_warn("DNSSEC validation may be unavailable");
+    else if (msg_verbose)
+       msg_info(VAR_DNSSEC_PROBE
+                " '%s' received a response that is DNSSEC validated",
+                var_dnssec_probe);
+    switch (dns_status) {
+    default:
+       if (!DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
+           msg_warn("reason: " VAR_DNSSEC_PROBE
+                    " '%s' received a response that is not DNSSEC validated",
+                    var_dnssec_probe);
+       if (rrlist)
+           dns_rr_free(rrlist);
+       break;
+    case DNS_RETRY:
+    case DNS_FAIL:
+       msg_warn("reason: " VAR_DNSSEC_PROBE " '%s' received no response: %s",
+                var_dnssec_probe, vstring_str(why));
+       break;
+    }
+    myfree(saved_dnssec_probe);
+    vstring_free(why);
+}
index 003fc39928b38498b62d17c1296ed4f458e336b6..8366cf7c048f8c1faad592cf3f32cab04f7cb9d8 100644 (file)
@@ -77,6 +77,9 @@ int     main(int argc, char **argv)
     int     ch;
     int     lflags = DNS_REQ_FLAG_NONE;
 
+    if (var_dnssec_probe == 0)
+       var_dnssec_probe = mystrdup(DEF_DNSSEC_PROBE);
+
     msg_vstream_init(argv[0], VSTREAM_ERR);
     while ((ch = GETOPT(argc, argv, "f:npv")) > 0) {
        switch (ch) {
index f0b0d54093583bb9aaa1968efbe3137670b09fb7..0748aede73b815cbe1f77a8fc9f602b9e6c902f2 100644 (file)
 /*     int     warn_compat_break_relay_domains;
 /*     int     warn_compat_break_flush_domains;
 /*     int     warn_compat_break_mynetworks_style;
+/*
+/*     char    *var_dnssec_probe;
 /* DESCRIPTION
 /*     This module (actually the associated include file) defines
 /*     the names and defaults of all mail configuration parameters.
@@ -348,6 +350,8 @@ int     var_compat_level;
 char   *var_drop_hdrs;
 bool    var_enable_orcpt;
 
+char   *var_dnssec_probe;
+
 const char null_format_string[1] = "";
 
  /*
@@ -670,6 +674,7 @@ void    mail_params_init()
        /* multi_instance_wrapper may have dependencies but not dependents. */
        VAR_MULTI_GROUP, DEF_MULTI_GROUP, &var_multi_group, 0, 0,
        VAR_MULTI_NAME, DEF_MULTI_NAME, &var_multi_name, 0, 0,
+       VAR_DNSSEC_PROBE, DEF_DNSSEC_PROBE, &var_dnssec_probe, 0, 0,
        0,
     };
     static const CONFIG_BOOL_TABLE first_bool_defaults[] = {
index e83ef2a5459c1da88f237b7e7f8d1efb72a52144..66abbf87022aceaf557f80193a66601d2bb67769 100644 (file)
@@ -1602,7 +1602,7 @@ extern bool var_smtp_tls_force_tlsa;
 
  /* SMTP only */
 #define VAR_SMTP_TLS_INSECURE_MX_POLICY "smtp_tls_dane_insecure_mx_policy"
-#define DEF_SMTP_TLS_INSECURE_MX_POLICY "dane"
+#define DEF_SMTP_TLS_INSECURE_MX_POLICY "${{$smtp_tls_security_level} == {dane} ? {dane} : {may}}"
 extern char *var_smtp_tls_insecure_mx_policy;
 
  /*
@@ -4072,6 +4072,13 @@ extern int var_idna2003_compat;
 #define DEF_DNS_NCACHE_TTL_FIX         0
 extern bool var_dns_ncache_ttl_fix;
 
+ /*
+  * DNSSEC probing, to find out if DNSSEC validation is available.
+  */
+#define VAR_DNSSEC_PROBE       "dnssec_probe"
+#define DEF_DNSSEC_PROBE       "ns:."
+extern char *var_dnssec_probe;
+
 /* LICENSE
 /* .ad
 /* .fi
index c2d503293c2522147875b49590865636fd09cb4c..2029314430bca57b0af4fd28c970a0325202a14d 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20201107"
-#define MAIL_VERSION_NUMBER    "3.3.15"
+#define MAIL_RELEASE_DATE      "20210117"
+#define MAIL_VERSION_NUMBER    "3.3.16"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index c9039457ac2fb8e235729d8e0d8d36ebeb3737dc..bf18192284f768103fb6ea8d5b021a71eff90165 100644 (file)
 /*     When a remote destination resolves to a combination of IPv4 and
 /*     IPv6 addresses, ensure that the Postfix SMTP client can try both
 /*     address types before it runs into the smtp_mx_address_limit.
+/* .PP
+/*     Available in Postfix 3.3.16 and later:
+/* .IP "\fBdnssec_probe (ns:.)\fR"
+/*     The DNS query type (default: "ns") and DNS query name (default:
+/*     ".") that Postfix may use to determine whether DNSSEC validation
+/*     is available.
 /* MIME PROCESSING CONTROLS
 /* .ad
 /* .fi