From: Wietse Venema
Date: Sun, 19 Feb 2023 05:00:00 +0000 (-0500)
Subject: postfix-3.8-20230219
X-Git-Tag: v3.8.0-RC1~9
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2047994eeee1dbf0d8c0537ba00acb8986a8a370;p=thirdparty%2Fpostfix.git
postfix-3.8-20230219
---
diff --git a/postfix/HISTORY b/postfix/HISTORY
index d1545c53a..5041f17cf 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -26808,3 +26808,73 @@ Apologies for any names omitted.
Portability: MacOS support for the postfix-env.sh test
script.
+
+20230129
+
+ Documentation: in the postconf(5) manpage, the text for
+ append_dot_mydomain described old default behavior. File:
+ proto/postconf.proto.
+
+ Documentation: in the smtpd(8) manpage, the text for the
+ info_log_address_format parameter was in the wrong place.
+ File: smtpd/smtpd.c.
+
+20230202
+
+ Documentation: fixed a broken HTML tag in SASL_README.html.
+
+20230209
+
+ Cleanup: noise suppression for resolver-related macros.
+ Viktor Dukhovni. Files: dns/dns_str_resflags.c, util/sys_defs.h.
+
+20230212
+
+ Cleanup: valgrind complained about uninitialized padding.
+ File: util/unix_send_fd.c
+
+20230213
+
+ Feature: SRV lookup support in the Postfix SMTP/LMTP client.
+ See https://www.postfix.org/postconf.5.html#use_srv_lookup.
+ Based on code by Tomas Korbar (Red Hat). Files: proto/stop,
+ proto/stop.spell-proto-html, dns/dns.h, dns/dns_lookup.c,
+ dns/dns_rr.c, dns/dns_sa_to_rr.c, dns/dns_strrecord.c,
+ dns/dns_strtype.c, global/mail_params.h, smtp/lmtp_params.c,
+ smtp/smtp_addr.c, smtp/smtp_addr.h, smtp/smtp.c,
+ smtp/smtp_connect.c, smtp/smtp.h, smtp/smtp_params.c,
+ smtp/smtp_session.c, smtpd/smtpd_check.c, util/attr.h,
+ util/unix_send_fd.c, mantools/postlink, proto/postconf.proto.
+
+20230214
+
+ SRV lookup: propagate preference and port information when
+ converting a numerical hostname to IP address. File:
+ smtp/smtp_addr.c.
+
+ SRV lookup: add SRV support to the posttls-finger command.
+ File: posttls-finger/posttls-finger.c.
+
+ SRV lookup: updated documentation examples. File:
+ proto/postconf.proto.
+
+20230219
+
+ Code health: replaced a proliferation of 'bare' zero arguments
+ with named constants: DNS_RR_NOPREF, DNS_RR_NOWEIGHT,
+ DNS_RR_NOPORT, and added convenience wrappers for
+ dns_rr_create(), to simplify code that needs to specify
+ only a subset of all arguments. Files: src/dns/dns.h,
+ src/dns/dns_rr_eq_sa.c, src/dns/dns_sa_to_rr.c,
+ src/smtpd/smtpd_check.c.
+
+ Code health: updated internal documentation. Files:
+ dns/dns_rr.c, smtp/smtp_connect.c.
+
+ Compatibility: downgraded some modernisms to avoid breaking
+ builds on older test systems. File: dns/dns_rr.c.
+
+ Code health: simplified the SRV record priority grouping
+ and record ordering code. Eliminated some special-case
+ handling of zero-weight records (that was already started
+ in the initial implementation). File: dns/dns_rr.c.
diff --git a/postfix/README_FILES/SASL_README b/postfix/README_FILES/SASL_README
index 580a0131d..4ea62d9b3 100644
--- a/postfix/README_FILES/SASL_README
+++ b/postfix/README_FILES/SASL_README
@@ -174,24 +174,23 @@ You can read more about the following topics:
* Cyrus SASL version 2.1.22 and newer additionally search in /etc/sasl2/.
- * li>
- With Postfix 2.5 and later you can explicitly configure the search path via
+ * With Postfix 2.5 and later you can explicitly configure the search path via
the cyrus_sasl_config_path configuration parameter. Specify zero or more
colon-separated directories. If set empty (the default value) the search
path is the one compiled into the Cyrus SASL library.
-Some Postfix distributions employ a non-empty default value for
-cyrus_sasl_config_path to look for the Cyrus SASL configuration file in /etc/
-postfix/sasl/, /var/lib/sasl2/ etc. See the output of postconf
-cyrus_sasl_config_path and/or the distribution-specific documentation to
-determine the expected location.
-
-Some Debian-based Postfix distributions patch Postfix to hardcode a non-default
-search path, making it impossible to set an alternate search path via the
-"cyrus_sasl_config_path" parameter. This is likely to be the case when the
-distribution documents a Postfix-specific path (e.g. /etc/postfix/sasl/) that
-is different from the default value of "cyrus_sasl_config_path" (which then is
-likely to be empty).
+ * Some Postfix distributions employ a non-empty default value for
+ cyrus_sasl_config_path to look for the Cyrus SASL configuration file in /
+ etc/postfix/sasl/, /var/lib/sasl2/ etc. See the output of postconf
+ cyrus_sasl_config_path and/or the distribution-specific documentation to
+ determine the expected location.
+
+ * Some Debian-based Postfix distributions patch Postfix to hardcode a non-
+ default search path, making it impossible to set an alternate search path
+ via the "cyrus_sasl_config_path" parameter. This is likely to be the case
+ when the distribution documents a Postfix-specific path (e.g. /etc/postfix/
+ sasl/) that is different from the default value of "cyrus_sasl_config_path"
+ (which then is likely to be empty).
NNoottee
diff --git a/postfix/WISHLIST b/postfix/WISHLIST
index bee364895..71b1685ca 100644
--- a/postfix/WISHLIST
+++ b/postfix/WISHLIST
@@ -9,7 +9,12 @@ Wish list:
Scan Postfix code with github.com/googleprojectzero/weggli
(depends on "rust").
- In smtpd.c, move the comment block with info_log_address_format.
+ Follow https://github.com/vdukhovni/postfix/commits/rpk
+
+ Multi-recipient support in sender/recipient_bcc_maps and
+ always_bcc.
+
+ Should "postconf -f" pretty-print text inside {}?
Is there any code that calls attr_scan*() and that works
when the number of attributes received < the expected number?
diff --git a/postfix/html/SASL_README.html b/postfix/html/SASL_README.html
index f31391668..1ddd24bb2 100644
--- a/postfix/html/SASL_README.html
+++ b/postfix/html/SASL_README.html
@@ -267,7 +267,7 @@ in /usr/lib/sasl2/.
Cyrus SASL version 2.1.22 and newer additionally search
in /etc/sasl2/.
-li> With Postfix 2.5 and later you can explicitly configure the
+
With Postfix 2.5 and later you can explicitly configure the
search path via the cyrus_sasl_config_path configuration
parameter. Specify zero or more colon-separated directories. If
set empty (the default value) the search path is the one compiled
diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html
index bcdb904b9..696d3bf4c 100644
--- a/postfix/html/lmtp.8.html
+++ b/postfix/html/lmtp.8.html
@@ -152,6 +152,7 @@ SMTP(8) SMTP(8)
RFC 2046 (MIME: Media Types)
RFC 2554 (AUTH command)
RFC 2821 (SMTP protocol)
+ RFC 2782 (SRV resource records)
RFC 2920 (SMTP Pipelining)
RFC 3207 (STARTTLS command)
RFC 3461 (SMTP DSN Extension)
@@ -395,6 +396,21 @@ SMTP(8) SMTP(8)
header_from_format (standard)
The format of the Postfix-generated From: header.
+ Available in Postfix version 3.8 and later:
+
+ use_srv_lookup (empty)
+ Enables discovery for the specified service(s) using DNS SRV
+ records.
+
+ ignore_srv_lookup_error (no)
+ When SRV record lookup fails, fall back to MX or IP address
+ lookup as if SRV record lookups were not enabled.
+
+ allow_srv_lookup_fallback (no)
+ When SRV record lookup fails or no SRV record exists, fall back
+ to MX or IP address lookup as if SRV record lookups were not
+ enabled.
+
MIME PROCESSING CONTROLS
Available in Postfix version 2.0 and later:
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 95c8dca56..722bdc4ec 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -762,6 +762,17 @@ Example:
+
+
+
allow_srv_lookup_fallback
+(default: no)
+
+ When SRV record lookup fails or no SRV record exists, fall back
+to MX or IP address lookup as if SRV record lookup was not enabled.
+
+
This feature is available in Postfix 3.8 and later.
+
+
allow_untrusted_routing
@@ -946,7 +957,7 @@ instead.
-Note 1: this feature is enabled by default. If disabled, users will not be
+Note 1: When disabled (Postfix 3.0 and later), users will not be
able to send mail to "user@partialdomainname" but will have to
specify full domain names instead.
@@ -4017,6 +4028,17 @@ mis-delivery of mail.
+
+
+ignore_srv_lookup_error
+(default: no)
+
+ When SRV record lookup fails, fall back to MX or IP address
+lookup as if SRV record lookup was not enabled. >
+
+
This feature is available in Postfix 3.8 and later.
+
+
import_environment
@@ -21247,6 +21269,103 @@ only if it would otherwise be accepted.
This feature is available in Postfix 2.6 and later.
+
+
+use_srv_lookup
+(default: empty)
+
+ Enables discovery for the specified service(s) using DNS SRV
+records. For example, with "use_srv_lookup = submission" and
+"relayhost = example.com:submission", the Postfix SMTP client will
+look up DNS SRV records for _submission._tcp.example.com, and will
+relay email through the hosts and ports that are specified with
+those records. See RFC 2782 for details of the host selection
+process.
+
+ Specify zero or more service names separated by comma and/or
+whitespace. Any name in the services(5) database may be specified,
+though in practice only submission, submissions, and smtp make
+sense.
+
+ When SRV record lookup is enabled with use_srv_lookup, you can
+enclose a domain name in "[]" to force IP address lookup instead
+of SRV record lookup.
+
+ Example 1: MUA-to-MTA submission using SRV record lookup for
+the "submission" service for domain "example.com". This uses the
+default SMTP delivery agent with STARTTLS, and looks up SRV records
+for "_submission._tcp.example.com".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submission
+ relayhost = example.com:submission
+ smtp_tls_security_level = may
+ ...see SASL_README for sasl configuration...
+
+
+ Example 2: MUA-to-MTA submission using SRV record lookup for
+the "submissions" service for domain "example.org". This uses a
+dedicated SMTP delivery agent (smtp-wraptls) with tls_wrappermode
+turned on, and looks up SRV records for "_submissions._tcp.example.org".
+
+
+ Note: specify the older name "smtps" instead of "submissions"
+when a provider has DNS SRV records like "_smtps._tcp.example.org"
+instead of "_submissions._tcp.example.org".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submissions
+ default_transport = smtp-wraptls:example.org:submissions
+ ...see SASL_README for sasl configuration...
+
+
+
+/etc/postfix/master.cf:
+ smtp-wraptls unix ... ... ... ... ... smtp
+ -o { smtp_tls_wrappermode = yes }
+ -o { smtp_tls_security_level = encrypt }
+
+
+ Example 3: Sender-dependent selection for a combination of
+MUA-to-MTA submission services. This combines examples 1 and 2 with
+examples of how to disable SRV and look up IP address records for
+"smtp-relay.example.net" and "smtp-relay.other.example". Again,
+specify the older name "smtps" instead of "submissions" when a
+provider has DNS SRV records like "_smtps._tcp.example.org" instead
+of "_submissions._tcp.example.org".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submission, submissions
+ sender_dependent_default_transport_maps = inline:{
+ # Destinations that support SRV record lookup.
+ { user1@example.com = smtp:example.com:submission }
+ { user2@example.org = smtp-wraptls:example.org:submissions }
+ # Use [destination] to force IP address lookups.
+ { user3@example.net = smtp:[smtp-relay.example.net]:submission }
+ { user4@other.example =
+ smtp-wraptls:[smtp-relay.other.example]:submissions } }
+ ...see SASL_README for sasl configuration...
+
+
+ Example 4: MTA-to-MTA traffic, using SRV record lookup for the
+SMTP service. This is useful for Postfix tests, and may be useful
+in environments where ports are dynamically assigned to servers.
+
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = smtp
+ # Fall back to MX record lookup when SRV records are unavailable.
+ #allow_srv_lookup_fallback = yes
+ #ignore_srv_lookup_error = yes
+
+
+ This feature is available in Postfix 3.8 and later.
+
+
verp_delimiter_filter
diff --git a/postfix/html/posttls-finger.1.html b/postfix/html/posttls-finger.1.html
index 401ad0726..877a2fa67 100644
--- a/postfix/html/posttls-finger.1.html
+++ b/postfix/html/posttls-finger.1.html
@@ -271,6 +271,8 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1)
the -m option. By default reconnection is disabled, specify a
positive delay to enable this behavior.
+ -R Use SRV lookup instead of MX.
+
-s servername
The server name to send with the TLS Server Name Indication
(SNI) extension. When the server has DANE TLSA records, this
diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html
index bcdb904b9..696d3bf4c 100644
--- a/postfix/html/smtp.8.html
+++ b/postfix/html/smtp.8.html
@@ -152,6 +152,7 @@ SMTP(8) SMTP(8)
RFC 2046 (MIME: Media Types)
RFC 2554 (AUTH command)
RFC 2821 (SMTP protocol)
+ RFC 2782 (SRV resource records)
RFC 2920 (SMTP Pipelining)
RFC 3207 (STARTTLS command)
RFC 3461 (SMTP DSN Extension)
@@ -395,6 +396,21 @@ SMTP(8) SMTP(8)
header_from_format (standard)
The format of the Postfix-generated From: header.
+ Available in Postfix version 3.8 and later:
+
+ use_srv_lookup (empty)
+ Enables discovery for the specified service(s) using DNS SRV
+ records.
+
+ ignore_srv_lookup_error (no)
+ When SRV record lookup fails, fall back to MX or IP address
+ lookup as if SRV record lookups were not enabled.
+
+ allow_srv_lookup_fallback (no)
+ When SRV record lookup fails or no SRV record exists, fall back
+ to MX or IP address lookup as if SRV record lookups were not
+ enabled.
+
MIME PROCESSING CONTROLS
Available in Postfix version 2.0 and later:
diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html
index 965bf11ff..f60ee85d0 100644
--- a/postfix/html/smtpd.8.html
+++ b/postfix/html/smtpd.8.html
@@ -159,32 +159,38 @@ SMTPD(8) SMTPD(8)
smtpd_dns_reply_filter (empty)
Optional filter for Postfix SMTP server DNS lookup results.
+ Available in Postfix 3.5 and later:
+
+ info_log_address_format (external)
+ The email address form that will be used in non-debug logging
+ (info, warning, etc.).
+
Available in Postfix version 3.6 and later:
smtpd_relay_before_recipient_restrictions (see 'postconf -d' output)
- Evaluate smtpd_relay_restrictions before smtpd_recipi-
+ Evaluate smtpd_relay_restrictions before smtpd_recipi-
ent_restrictions.
- known_tcp_ports (lmtp=24, smtp=25, smtps=submissions=465, submis-
+ known_tcp_ports (lmtp=24, smtp=25, smtps=submissions=465, submis-
sion=587)
- Optional setting that avoids lookups in the services(5) data-
+ Optional setting that avoids lookups in the services(5) data-
base.
Available in Postfix version 3.7 and later:
smtpd_per_request_deadline (normal: no, overload: yes)
Change the behavior of the smtpd_timeout and smtpd_start-
- tls_timeout time limits, from a time limit per plaintext or TLS
- read or write call, to a combined time limit for receiving a
- complete SMTP request and for sending a complete SMTP response.
+ tls_timeout time limits, from a time limit per plaintext or TLS
+ read or write call, to a combined time limit for receiving a
+ complete SMTP request and for sending a complete SMTP response.
smtpd_min_data_rate (500)
- The minimum plaintext data transfer rate in bytes/second for
- DATA and BDAT requests, when deadlines are enabled with
+ The minimum plaintext data transfer rate in bytes/second for
+ DATA and BDAT requests, when deadlines are enabled with
smtpd_per_request_deadline.
ADDRESS REWRITING CONTROLS
- See the ADDRESS_REWRITING_README document for a detailed discussion of
+ See the ADDRESS_REWRITING_README document for a detailed discussion of
Postfix address rewriting.
receive_override_options (empty)
@@ -194,34 +200,34 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 2.2 and later:
local_header_rewrite_clients (permit_inet_interfaces)
- Rewrite or add message headers in mail from these clients,
- updating incomplete addresses with the domain name in $myorigin
+ Rewrite or add message headers in mail from these clients,
+ updating incomplete addresses with the domain name in $myorigin
or $mydomain, and adding missing headers.
BEFORE-SMTPD PROXY AGENT
Available in Postfix version 2.10 and later:
smtpd_upstream_proxy_protocol (empty)
- The name of the proxy protocol used by an optional before-smtpd
+ The name of the proxy protocol used by an optional before-smtpd
proxy agent.
smtpd_upstream_proxy_timeout (5s)
- The time limit for the proxy protocol specified with the
+ The time limit for the proxy protocol specified with the
smtpd_upstream_proxy_protocol parameter.
AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
- As of version 1.0, Postfix can be configured to send new mail to an
- external content filter AFTER the mail is queued. This content filter
- is expected to inject mail back into a (Postfix or other) MTA for fur-
+ As of version 1.0, Postfix can be configured to send new mail to an
+ external content filter AFTER the mail is queued. This content filter
+ is expected to inject mail back into a (Postfix or other) MTA for fur-
ther delivery. See the FILTER_README document for details.
content_filter (empty)
- After the message is queued, send the entire message to the
+ After the message is queued, send the entire message to the
specified transport:destination.
BEFORE QUEUE EXTERNAL CONTENT INSPECTION CONTROLS
- As of version 2.1, the Postfix SMTP server can be configured to send
- incoming mail to a real-time SMTP-based content filter BEFORE mail is
+ As of version 2.1, the Postfix SMTP server can be configured to send
+ incoming mail to a real-time SMTP-based content filter BEFORE mail is
queued. This content filter is expected to inject mail back into Post-
fix. See the SMTPD_PROXY_README document for details on how to config-
ure and operate this feature.
@@ -230,40 +236,40 @@ SMTPD(8) SMTPD(8)
The hostname and TCP port of the mail filtering proxy server.
smtpd_proxy_ehlo ($myhostname)
- How the Postfix SMTP server announces itself to the proxy fil-
+ How the Postfix SMTP server announces itself to the proxy fil-
ter.
smtpd_proxy_options (empty)
- List of options that control how the Postfix SMTP server commu-
+ List of options that control how the Postfix SMTP server commu-
nicates with a before-queue content filter.
smtpd_proxy_timeout (100s)
- The time limit for connecting to a proxy filter and for sending
+ The time limit for connecting to a proxy filter and for sending
or receiving information.
BEFORE QUEUE MILTER CONTROLS
As of version 2.3, Postfix supports the Sendmail version 8 Milter (mail
- filter) protocol. These content filters run outside Postfix. They can
- inspect the SMTP command stream and the message content, and can
- request modifications before mail is queued. For details see the MIL-
+ filter) protocol. These content filters run outside Postfix. They can
+ inspect the SMTP command stream and the message content, and can
+ request modifications before mail is queued. For details see the MIL-
TER_README document.
smtpd_milters (empty)
- A list of Milter (mail filter) applications for new mail that
+ A list of Milter (mail filter) applications for new mail that
arrives via the Postfix smtpd(8) server.
milter_protocol (6)
- The mail filter protocol version and optional protocol exten-
- sions for communication with a Milter application; prior to
+ The mail filter protocol version and optional protocol exten-
+ sions for communication with a Milter application; prior to
Postfix 2.6 the default protocol is 2.
milter_default_action (tempfail)
- The default action when a Milter (mail filter) response is
- unavailable (for example, bad Postfix configuration or Milter
+ The default action when a Milter (mail filter) response is
+ unavailable (for example, bad Postfix configuration or Milter
failure).
milter_macro_daemon_name ($myhostname)
- The {daemon_name} macro value for Milter (mail filter) applica-
+ The {daemon_name} macro value for Milter (mail filter) applica-
tions.
milter_macro_v ($mail_name $mail_version)
@@ -274,60 +280,60 @@ SMTPD(8) SMTPD(8)
tion, and for negotiating protocol options.
milter_command_timeout (30s)
- The time limit for sending an SMTP command to a Milter (mail
+ The time limit for sending an SMTP command to a Milter (mail
filter) application, and for receiving the response.
milter_content_timeout (300s)
- The time limit for sending message content to a Milter (mail
+ The time limit for sending message content to a Milter (mail
filter) application, and for receiving the response.
milter_connect_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after completion of an SMTP connection.
milter_helo_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP HELO or EHLO command.
milter_mail_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP MAIL FROM command.
milter_rcpt_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the SMTP RCPT TO command.
milter_data_macros (see 'postconf -d' output)
- The macros that are sent to version 4 or higher Milter (mail
+ The macros that are sent to version 4 or higher Milter (mail
filter) applications after the SMTP DATA command.
milter_unknown_command_macros (see 'postconf -d' output)
- The macros that are sent to version 3 or higher Milter (mail
+ The macros that are sent to version 3 or higher Milter (mail
filter) applications after an unknown SMTP command.
milter_end_of_header_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the end of the message header.
milter_end_of_data_macros (see 'postconf -d' output)
- The macros that are sent to Milter (mail filter) applications
+ The macros that are sent to Milter (mail filter) applications
after the message end-of-data.
Available in Postfix version 3.1 and later:
milter_macro_defaults (empty)
- Optional list of name=value pairs that specify default values
- for arbitrary macros that Postfix may send to Milter applica-
+ Optional list of name=value pairs that specify default values
+ for arbitrary macros that Postfix may send to Milter applica-
tions.
Available in Postfix version 3.2 and later:
smtpd_milter_maps (empty)
- Lookup tables with Milter settings per remote SMTP client IP
+ Lookup tables with Milter settings per remote SMTP client IP
address.
GENERAL CONTENT INSPECTION CONTROLS
- The following parameters are applicable for both built-in and external
+ The following parameters are applicable for both built-in and external
content filters.
Available in Postfix version 2.1 and later:
@@ -337,51 +343,51 @@ SMTPD(8) SMTPD(8)
ing, or address mapping.
EXTERNAL CONTENT INSPECTION CONTROLS
- The following parameters are applicable for both before-queue and
+ The following parameters are applicable for both before-queue and
after-queue content filtering.
Available in Postfix version 2.1 and later:
smtpd_authorized_xforward_hosts (empty)
- What remote SMTP clients are allowed to use the XFORWARD fea-
+ What remote SMTP clients are allowed to use the XFORWARD fea-
ture.
SASL AUTHENTICATION CONTROLS
Postfix SASL support (RFC 4954) can be used to authenticate remote SMTP
- clients to the Postfix SMTP server, and to authenticate the Postfix
- SMTP client to a remote SMTP server. See the SASL_README document for
+ clients to the Postfix SMTP server, and to authenticate the Postfix
+ SMTP client to a remote SMTP server. See the SASL_README document for
details.
broken_sasl_auth_clients (no)
- Enable interoperability with remote SMTP clients that implement
+ Enable interoperability with remote SMTP clients that implement
an obsolete version of the AUTH command (RFC 4954).
smtpd_sasl_auth_enable (no)
Enable SASL authentication in the Postfix SMTP server.
smtpd_sasl_local_domain (empty)
- The name of the Postfix SMTP server's local SASL authentication
+ The name of the Postfix SMTP server's local SASL authentication
realm.
smtpd_sasl_security_options (noanonymous)
Postfix SMTP server SASL security options; as of Postfix 2.3 the
- list of available features depends on the SASL server implemen-
+ list of available features depends on the SASL server implemen-
tation that is selected with smtpd_sasl_type.
smtpd_sender_login_maps (empty)
- Optional lookup table with the SASL login names that own the
+ Optional lookup table with the SASL login names that own the
sender (MAIL FROM) addresses.
Available in Postfix version 2.1 and later:
smtpd_sasl_exceptions_networks (empty)
- What remote SMTP clients the Postfix SMTP server will not offer
+ What remote SMTP clients the Postfix SMTP server will not offer
AUTH support to.
Available in Postfix version 2.1 and 2.2:
smtpd_sasl_application_name (smtpd)
- The application name that the Postfix SMTP server uses for SASL
+ The application name that the Postfix SMTP server uses for SASL
server initialization.
Available in Postfix version 2.3 and later:
@@ -392,11 +398,11 @@ SMTPD(8) SMTPD(8)
smtpd_sasl_path (smtpd)
Implementation-specific information that the Postfix SMTP server
- passes through to the SASL plug-in implementation that is
+ passes through to the SASL plug-in implementation that is
selected with smtpd_sasl_type.
smtpd_sasl_type (cyrus)
- The SASL plug-in type that the Postfix SMTP server should use
+ The SASL plug-in type that the Postfix SMTP server should use
for authentication.
Available in Postfix version 2.5 and later:
@@ -408,7 +414,7 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 2.11 and later:
smtpd_sasl_service (smtp)
- The service name that is passed to the SASL plug-in that is
+ The service name that is passed to the SASL plug-in that is
selected with smtpd_sasl_type and smtpd_sasl_path.
Available in Postfix version 3.4 and later:
@@ -420,20 +426,20 @@ SMTPD(8) SMTPD(8)
Available in Postfix 3.6 and later:
smtpd_sasl_mechanism_filter (!external, static:rest)
- If non-empty, a filter for the SASL mechanism names that the
+ If non-empty, a filter for the SASL mechanism names that the
Postfix SMTP server will announce in the EHLO response.
STARTTLS SUPPORT CONTROLS
- Detailed information about STARTTLS configuration may be found in the
+ Detailed information about STARTTLS configuration may be found in the
TLS_README document.
smtpd_tls_security_level (empty)
- The SMTP TLS security level for the Postfix SMTP server; when a
+ The SMTP TLS security level for the Postfix SMTP server; when a
non-empty value is specified, this overrides the obsolete param-
eters smtpd_use_tls and smtpd_enforce_tls.
smtpd_sasl_tls_security_options ($smtpd_sasl_security_options)
- The SASL authentication security options that the Postfix SMTP
+ The SASL authentication security options that the Postfix SMTP
server uses for TLS encrypted SMTP sessions.
smtpd_starttls_timeout (see 'postconf -d' output)
@@ -441,25 +447,25 @@ SMTPD(8) SMTPD(8)
during TLS startup and shutdown handshake procedures.
smtpd_tls_CAfile (empty)
- A file containing (PEM format) CA certificates of root CAs
+ A file containing (PEM format) CA certificates of root CAs
trusted to sign either remote SMTP client certificates or inter-
mediate CA certificates.
smtpd_tls_CApath (empty)
- A directory containing (PEM format) CA certificates of root CAs
+ A directory containing (PEM format) CA certificates of root CAs
trusted to sign either remote SMTP client certificates or inter-
mediate CA certificates.
smtpd_tls_always_issue_session_ids (yes)
- Force the Postfix SMTP server to issue a TLS session id, even
- when TLS session caching is turned off (smtpd_tls_ses-
+ Force the Postfix SMTP server to issue a TLS session id, even
+ when TLS session caching is turned off (smtpd_tls_ses-
sion_cache_database is empty).
smtpd_tls_ask_ccert (no)
Ask a remote SMTP client for a client certificate.
smtpd_tls_auth_only (no)
- When TLS encryption is optional in the Postfix SMTP server, do
+ When TLS encryption is optional in the Postfix SMTP server, do
not announce or accept SASL authentication over unencrypted con-
nections.
@@ -470,18 +476,18 @@ SMTPD(8) SMTPD(8)
File with the Postfix SMTP server RSA certificate in PEM format.
smtpd_tls_exclude_ciphers (empty)
- List of ciphers or cipher types to exclude from the SMTP server
+ List of ciphers or cipher types to exclude from the SMTP server
cipher list at all TLS security levels.
smtpd_tls_dcert_file (empty)
File with the Postfix SMTP server DSA certificate in PEM format.
smtpd_tls_dh1024_param_file (empty)
- File with DH parameters that the Postfix SMTP server should use
+ File with DH parameters that the Postfix SMTP server should use
with non-export EDH ciphers.
smtpd_tls_dh512_param_file (empty)
- File with DH parameters that the Postfix SMTP server should use
+ File with DH parameters that the Postfix SMTP server should use
with export-grade EDH ciphers.
smtpd_tls_dkey_file ($smtpd_tls_dcert_file)
@@ -494,12 +500,12 @@ SMTPD(8) SMTPD(8)
Enable additional Postfix SMTP server logging of TLS activity.
smtpd_tls_mandatory_ciphers (medium)
- The minimum TLS cipher grade that the Postfix SMTP server will
+ The minimum TLS cipher grade that the Postfix SMTP server will
use with mandatory TLS encryption.
smtpd_tls_mandatory_exclude_ciphers (empty)
- Additional list of ciphers or cipher types to exclude from the
- Postfix SMTP server cipher list at mandatory TLS security lev-
+ Additional list of ciphers or cipher types to exclude from the
+ Postfix SMTP server cipher list at mandatory TLS security lev-
els.
smtpd_tls_mandatory_protocols (see 'postconf -d' output)
@@ -508,21 +514,21 @@ SMTPD(8) SMTPD(8)
smtpd_tls_received_header (no)
Request that the Postfix SMTP server produces Received: message
- headers that include information about the protocol and cipher
- used, as well as the remote SMTP client CommonName and client
+ headers that include information about the protocol and cipher
+ used, as well as the remote SMTP client CommonName and client
certificate issuer CommonName.
smtpd_tls_req_ccert (no)
- With mandatory TLS encryption, require a trusted remote SMTP
+ With mandatory TLS encryption, require a trusted remote SMTP
client certificate in order to allow TLS connections to proceed.
smtpd_tls_wrappermode (no)
- Run the Postfix SMTP server in TLS "wrapper" mode, instead of
+ Run the Postfix SMTP server in TLS "wrapper" mode, instead of
using the STARTTLS command.
tls_daemon_random_bytes (32)
- The number of pseudo-random bytes that an smtp(8) or smtpd(8)
- process requests from the tlsmgr(8) server in order to seed its
+ The number of pseudo-random bytes that an smtp(8) or smtpd(8)
+ process requests from the tlsmgr(8) server in order to seed its
internal pseudo random number generator (PRNG).
tls_high_cipherlist (see 'postconf -d' output)
@@ -538,41 +544,41 @@ SMTPD(8) SMTPD(8)
The OpenSSL cipherlist for "export" or higher grade ciphers.
tls_null_cipherlist (eNULL:!aNULL)
- The OpenSSL cipherlist for "NULL" grade ciphers that provide
+ The OpenSSL cipherlist for "NULL" grade ciphers that provide
authentication without encryption.
Available in Postfix version 2.5 and later:
smtpd_tls_fingerprint_digest (see 'postconf -d' output)
- The message digest algorithm to construct remote SMTP
- client-certificate fingerprints or public key fingerprints
- (Postfix 2.9 and later) for check_ccert_access and per-
+ The message digest algorithm to construct remote SMTP
+ client-certificate fingerprints or public key fingerprints
+ (Postfix 2.9 and later) for check_ccert_access and per-
mit_tls_clientcerts.
Available in Postfix version 2.6 and later:
smtpd_tls_protocols (see postconf -d output)
- TLS protocols accepted by the Postfix SMTP server with oppor-
+ TLS protocols accepted by the Postfix SMTP server with oppor-
tunistic TLS encryption.
smtpd_tls_ciphers (medium)
- The minimum TLS cipher grade that the Postfix SMTP server will
+ The minimum TLS cipher grade that the Postfix SMTP server will
use with opportunistic TLS encryption.
smtpd_tls_eccert_file (empty)
- File with the Postfix SMTP server ECDSA certificate in PEM for-
+ File with the Postfix SMTP server ECDSA certificate in PEM for-
mat.
smtpd_tls_eckey_file ($smtpd_tls_eccert_file)
- File with the Postfix SMTP server ECDSA private key in PEM for-
+ File with the Postfix SMTP server ECDSA private key in PEM for-
mat.
smtpd_tls_eecdh_grade (see 'postconf -d' output)
- The Postfix SMTP server security grade for ephemeral ellip-
+ The Postfix SMTP server security grade for ephemeral ellip-
tic-curve Diffie-Hellman (EECDH) key exchange.
tls_eecdh_strong_curve (prime256v1)
- The elliptic curve used by the Postfix SMTP server for sensibly
+ The elliptic curve used by the Postfix SMTP server for sensibly
strong ephemeral ECDH key exchange.
tls_eecdh_ultra_curve (secp384r1)
@@ -583,7 +589,7 @@ SMTPD(8) SMTPD(8)
tls_preempt_cipherlist (no)
With SSLv3 and later, use the Postfix SMTP server's cipher pref-
- erence order instead of the remote client's cipher preference
+ erence order instead of the remote client's cipher preference
order.
tls_disable_workarounds (see 'postconf -d' output)
@@ -596,7 +602,7 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 3.0 and later:
- tls_session_ticket_cipher (Postfix >= 3.0: aes-256-cbc, Postfix < 3.0:
+ tls_session_ticket_cipher (Postfix >= 3.0: aes-256-cbc, Postfix < 3.0:
aes-128-cbc)
Algorithm used to encrypt RFC5077 TLS session tickets.
@@ -609,26 +615,20 @@ SMTPD(8) SMTPD(8)
Available in Postfix version 3.4 and later:
smtpd_tls_chain_files (empty)
- List of one or more PEM files, each holding one or more private
+ List of one or more PEM files, each holding one or more private
keys directly followed by a corresponding certificate chain.
tls_server_sni_maps (empty)
- Optional lookup tables that map names received from remote SMTP
- clients via the TLS Server Name Indication (SNI) extension to
+ Optional lookup tables that map names received from remote SMTP
+ clients via the TLS Server Name Indication (SNI) extension to
the appropriate keys and certificate chains.
Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later:
tls_fast_shutdown_enable (yes)
- A workaround for implementations that hang Postfix while shut-
+ A workaround for implementations that hang Postfix while shut-
ting down a TLS session, until Postfix times out.
- Available in Postfix 3.5 and later:
-
- info_log_address_format (external)
- The email address form that will be used in non-debug logging
- (info, warning, etc.).
-
Available in Postfix version 3.8 and later:
tls_ffdhe_auto_groups (see 'postconf -d' output)
diff --git a/postfix/man/man1/posttls-finger.1 b/postfix/man/man1/posttls-finger.1
index 54b72aba2..1e22a03d9 100644
--- a/postfix/man/man1/posttls-finger.1
+++ b/postfix/man/man1/posttls-finger.1
@@ -243,6 +243,8 @@ seconds. Report whether the session is re\-used. Retry if a new server
is encountered, up to 5 times or as specified with the \fB\-m\fR option.
By default reconnection is disabled, specify a positive delay to
enable this behavior.
+.IP "\fB\-R\fR"
+Use SRV lookup instead of MX.
.IP "\fB\-s \fIservername\fR"
The server name to send with the TLS Server Name Indication (SNI)
extension. When the server has DANE TLSA records, this parameter
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index a86e73363..3eeb9388f 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -468,6 +468,11 @@ allow_percent_hack = no
.fi
.ad
.ft R
+.SH allow_srv_lookup_fallback (default: no)
+When SRV record lookup fails or no SRV record exists, fall back
+to MX or IP address lookup as if SRV record lookup was not enabled.
+.PP
+This feature is available in Postfix 3.8 and later.
.SH allow_untrusted_routing (default: no)
Forward mail with sender\-specified routing (user[@%!]remote[@%!]site)
from untrusted clients to destinations matching $relay_domains.
@@ -568,7 +573,7 @@ addresses that have no ".domain" information. With remotely submitted
mail, append the string ".$remote_header_rewrite_domain"
instead.
.PP
-Note 1: this feature is enabled by default. If disabled, users will not be
+Note 1: When disabled (Postfix 3.0 and later), users will not be
able to send mail to "user@partialdomainname" but will have to
specify full domain names instead.
.PP
@@ -2543,6 +2548,11 @@ delay. This behavior is required by the SMTP standard.
Specify "ignore_mx_lookup_error = yes" to force a DNS A record
lookup instead. This violates the SMTP standard and can result in
mis\-delivery of mail.
+.SH ignore_srv_lookup_error (default: no)
+When SRV record lookup fails, fall back to MX or IP address
+lookup as if SRV record lookup was not enabled. >
+.PP
+This feature is available in Postfix 3.8 and later.
.SH import_environment (default: see "postconf \-d" output)
The list of environment variables that a privileged Postfix
process will import from a non\-Postfix parent process, or name=value
@@ -14934,6 +14944,115 @@ for opportunities to reject mail, and defers the client request
only if it would otherwise be accepted.
.PP
This feature is available in Postfix 2.6 and later.
+.SH use_srv_lookup (default: empty)
+Enables discovery for the specified service(s) using DNS SRV
+records. For example, with "use_srv_lookup = submission" and
+"relayhost = example.com:submission", the Postfix SMTP client will
+look up DNS SRV records for _submission._tcp.example.com, and will
+relay email through the hosts and ports that are specified with
+those records. See RFC 2782 for details of the host selection
+process.
+.PP
+Specify zero or more service names separated by comma and/or
+whitespace. Any name in the \fBservices\fR(5) database may be specified,
+though in practice only submission, submissions, and smtp make
+sense.
+.PP
+When SRV record lookup is enabled with use_srv_lookup, you can
+enclose a domain name in "[]" to force IP address lookup instead
+of SRV record lookup.
+.PP
+Example 1: MUA\-to\-MTA submission using SRV record lookup for
+the "submission" service for domain "example.com". This uses the
+default SMTP delivery agent with STARTTLS, and looks up SRV records
+for "_submission._tcp.example.com".
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ use_srv_lookup = submission
+ relayhost = example.com:submission
+ smtp_tls_security_level = may
+ ...see SASL_README for sasl configuration...
+.fi
+.ad
+.ft R
+.PP
+Example 2: MUA\-to\-MTA submission using SRV record lookup for
+the "submissions" service for domain "example.org". This uses a
+dedicated SMTP delivery agent (smtp\-wraptls) with tls_wrappermode
+turned on, and looks up SRV records for "_submissions._tcp.example.org".
+.PP
+Note: specify the older name "smtps" instead of "submissions"
+when a provider has DNS SRV records like "_smtps._tcp.example.org"
+instead of "_submissions._tcp.example.org".
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ use_srv_lookup = submissions
+ default_transport = smtp\-wraptls:example.org:submissions
+ ...see SASL_README for sasl configuration...
+.fi
+.ad
+.ft R
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/master.cf:
+ smtp\-wraptls unix ... ... ... ... ... smtp
+ \-o { smtp_tls_wrappermode = yes }
+ \-o { smtp_tls_security_level = encrypt }
+.fi
+.ad
+.ft R
+.PP
+Example 3: Sender\-dependent selection for a combination of
+MUA\-to\-MTA submission services. This combines examples 1 and 2 with
+examples of how to disable SRV and look up IP address records for
+"smtp\-relay.example.net" and "smtp\-relay.other.example". Again,
+specify the older name "smtps" instead of "submissions" when a
+provider has DNS SRV records like "_smtps._tcp.example.org" instead
+of "_submissions._tcp.example.org".
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ use_srv_lookup = submission, submissions
+ sender_dependent_default_transport_maps = inline:{
+ # Destinations that support SRV record lookup.
+ { user1@example.com = smtp:example.com:submission }
+ { user2@example.org = smtp\-wraptls:example.org:submissions }
+ # Use [destination] to force IP address lookups.
+ { user3@example.net = smtp:[smtp\-relay.example.net]:submission }
+ { user4@other.example =
+ smtp\-wraptls:[smtp\-relay.other.example]:submissions } }
+ ...see SASL_README for sasl configuration...
+.fi
+.ad
+.ft R
+.PP
+Example 4: MTA\-to\-MTA traffic, using SRV record lookup for the
+SMTP service. This is useful for Postfix tests, and may be useful
+in environments where ports are dynamically assigned to servers.
+.PP
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+ use_srv_lookup = smtp
+ # Fall back to MX record lookup when SRV records are unavailable.
+ #allow_srv_lookup_fallback = yes
+ #ignore_srv_lookup_error = yes
+.fi
+.ad
+.ft R
+.PP
+This feature is available in Postfix 3.8 and later.
.SH verp_delimiter_filter (default: \-=+)
The characters Postfix accepts as VERP delimiter characters on the
Postfix \fBsendmail\fR(1) command line and in SMTP commands.
diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8
index fa6138d7f..d2a4ce9ba 100644
--- a/postfix/man/man8/smtp.8
+++ b/postfix/man/man8/smtp.8
@@ -164,6 +164,7 @@ RFC 2045 (MIME: Format of Internet Message Bodies)
RFC 2046 (MIME: Media Types)
RFC 2554 (AUTH command)
RFC 2821 (SMTP protocol)
+RFC 2782 (SRV resource records)
RFC 2920 (SMTP Pipelining)
RFC 3207 (STARTTLS command)
RFC 3461 (SMTP DSN Extension)
@@ -378,6 +379,17 @@ The minimum plaintext data transfer rate in bytes/second for
DATA requests, when deadlines are enabled with smtp_per_request_deadline.
.IP "\fBheader_from_format (standard)\fR"
The format of the Postfix\-generated \fBFrom:\fR header.
+.PP
+Available in Postfix version 3.8 and later:
+.IP "\fBuse_srv_lookup (empty)\fR"
+Enables discovery for the specified service(s) using DNS SRV
+records.
+.IP "\fBignore_srv_lookup_error (no)\fR"
+When SRV record lookup fails, fall back to MX or IP address
+lookup as if SRV record lookups were not enabled.
+.IP "\fBallow_srv_lookup_fallback (no)\fR"
+When SRV record lookup fails or no SRV record exists, fall back
+to MX or IP address lookup as if SRV record lookups were not enabled.
.SH "MIME PROCESSING CONTROLS"
.na
.nf
diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8
index bc8ec35a5..460293901 100644
--- a/postfix/man/man8/smtpd.8
+++ b/postfix/man/man8/smtpd.8
@@ -161,6 +161,11 @@ Available in Postfix version 3.0 and later:
.IP "\fBsmtpd_dns_reply_filter (empty)\fR"
Optional filter for Postfix SMTP server DNS lookup results.
.PP
+Available in Postfix 3.5 and later:
+.IP "\fBinfo_log_address_format (external)\fR"
+The email address form that will be used in non\-debug logging
+(info, warning, etc.).
+.PP
Available in Postfix version 3.6 and later:
.IP "\fBsmtpd_relay_before_recipient_restrictions (see 'postconf -d' output)\fR"
Evaluate smtpd_relay_restrictions before smtpd_recipient_restrictions.
@@ -552,11 +557,6 @@ Available in Postfix 3.5, 3.4.6, 3.3.5, 3.2.10, 3.1.13 and later:
A workaround for implementations that hang Postfix while shutting
down a TLS session, until Postfix times out.
.PP
-Available in Postfix 3.5 and later:
-.IP "\fBinfo_log_address_format (external)\fR"
-The email address form that will be used in non\-debug logging
-(info, warning, etc.).
-.PP
Available in Postfix version 3.8 and later:
.IP "\fBtls_ffdhe_auto_groups (see 'postconf -d' output)\fR"
The prioritized list of finite\-field Diffie\-Hellman ephemeral
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index 3e07222a2..39057abe5 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -1157,6 +1157,10 @@ while (<>) {
s;\blocal_login_sender_maps\b;$&;g;
s;\bempty_address_local_login_sender_maps_lookup_key\b;$&;g;
+ s;\buse_srv_lookup\b;$&;g;
+ s;\ballow_srv_lookup_fallback\b;$&;g;
+ s;\bignore_srv_lookup_error\b;$&;g;
+
# Service-defined parameters...
s;\bpolicy_time_limit\b;$&;g;
diff --git a/postfix/proto/SASL_README.html b/postfix/proto/SASL_README.html
index 3e2025a7a..0b33f3009 100644
--- a/postfix/proto/SASL_README.html
+++ b/postfix/proto/SASL_README.html
@@ -267,7 +267,7 @@ in /usr/lib/sasl2/.
Cyrus SASL version 2.1.22 and newer additionally search
in /etc/sasl2/.
-li> With Postfix 2.5 and later you can explicitly configure the
+
With Postfix 2.5 and later you can explicitly configure the
search path via the cyrus_sasl_config_path configuration
parameter. Specify zero or more colon-separated directories. If
set empty (the default value) the search path is the one compiled
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index a130f95fc..be367b427 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -7380,7 +7380,7 @@ instead.
-Note 1: this feature is enabled by default. If disabled, users will not be
+Note 1: When disabled (Postfix 3.0 and later), users will not be
able to send mail to "user@partialdomainname" but will have to
specify full domain names instead.
@@ -18478,3 +18478,110 @@ Postfix SMTP client will continue delivery after logging a warning.
configuration parameter. See there for details.
This feature is available in Postfix 3.7 and later.
+
+%PARAM use_srv_lookup
+
+ Enables discovery for the specified service(s) using DNS SRV
+records. For example, with "use_srv_lookup = submission" and
+"relayhost = example.com:submission", the Postfix SMTP client will
+look up DNS SRV records for _submission._tcp.example.com, and will
+relay email through the hosts and ports that are specified with
+those records. See RFC 2782 for details of the host selection
+process.
+
+ Specify zero or more service names separated by comma and/or
+whitespace. Any name in the services(5) database may be specified,
+though in practice only submission, submissions, and smtp make
+sense.
+
+ When SRV record lookup is enabled with use_srv_lookup, you can
+enclose a domain name in "[]" to force IP address lookup instead
+of SRV record lookup.
+
+ Example 1: MUA-to-MTA submission using SRV record lookup for
+the "submission" service for domain "example.com". This uses the
+default SMTP delivery agent with STARTTLS, and looks up SRV records
+for "_submission._tcp.example.com".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submission
+ relayhost = example.com:submission
+ smtp_tls_security_level = may
+ ...see SASL_README for sasl configuration...
+
+
+ Example 2: MUA-to-MTA submission using SRV record lookup for
+the "submissions" service for domain "example.org". This uses a
+dedicated SMTP delivery agent (smtp-wraptls) with tls_wrappermode
+turned on, and looks up SRV records for "_submissions._tcp.example.org".
+
+
+ Note: specify the older name "smtps" instead of "submissions"
+when a provider has DNS SRV records like "_smtps._tcp.example.org"
+instead of "_submissions._tcp.example.org".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submissions
+ default_transport = smtp-wraptls:example.org:submissions
+ ...see SASL_README for sasl configuration...
+
+
+
+/etc/postfix/master.cf:
+ smtp-wraptls unix ... ... ... ... ... smtp
+ -o { smtp_tls_wrappermode = yes }
+ -o { smtp_tls_security_level = encrypt }
+
+
+ Example 3: Sender-dependent selection for a combination of
+MUA-to-MTA submission services. This combines examples 1 and 2 with
+examples of how to disable SRV and look up IP address records for
+"smtp-relay.example.net" and "smtp-relay.other.example". Again,
+specify the older name "smtps" instead of "submissions" when a
+provider has DNS SRV records like "_smtps._tcp.example.org" instead
+of "_submissions._tcp.example.org".
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = submission, submissions
+ sender_dependent_default_transport_maps = inline:{
+ # Destinations that support SRV record lookup.
+ { user1@example.com = smtp:example.com:submission }
+ { user2@example.org = smtp-wraptls:example.org:submissions }
+ # Use [destination] to force IP address lookups.
+ { user3@example.net = smtp:[smtp-relay.example.net]:submission }
+ { user4@other.example =
+ smtp-wraptls:[smtp-relay.other.example]:submissions } }
+ ...see SASL_README for sasl configuration...
+
+
+ Example 4: MTA-to-MTA traffic, using SRV record lookup for the
+SMTP service. This is useful for Postfix tests, and may be useful
+in environments where ports are dynamically assigned to servers.
+
+
+
+/etc/postfix/main.cf:
+ use_srv_lookup = smtp
+ # Fall back to MX record lookup when SRV records are unavailable.
+ #allow_srv_lookup_fallback = yes
+ #ignore_srv_lookup_error = yes
+
+
+ This feature is available in Postfix 3.8 and later.
+
+%PARAM ignore_srv_lookup_error no
+
+ When SRV record lookup fails, fall back to MX or IP address
+lookup as if SRV record lookup was not enabled. >
+
+
This feature is available in Postfix 3.8 and later.
+
+%PARAM allow_srv_lookup_fallback no
+
+ When SRV record lookup fails or no SRV record exists, fall back
+to MX or IP address lookup as if SRV record lookup was not enabled.
+
+
This feature is available in Postfix 3.8 and later.
diff --git a/postfix/proto/stop b/postfix/proto/stop
index d663ad9c0..d8dbb3a57 100644
--- a/postfix/proto/stop
+++ b/postfix/proto/stop
@@ -1570,3 +1570,4 @@ Bugfix
https
egrep
fgrep
+SRV
diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history
index 072374f68..425aa26bf 100644
--- a/postfix/proto/stop.double-history
+++ b/postfix/proto/stop.double-history
@@ -16,3 +16,11 @@
src tls tls h src tls tls_proxy_client_misc c src tls tls_misc c
src global mail_params h src smtp smtp c
attacks Fix by Viktor Dukhovni Files tls tls h tls_client c
+ proto stop spell proto html dns dns h dns dns_lookup c
+ smtp smtp_addr h smtp smtp c smtp smtp_connect c
+ smtp smtp h smtp smtp_params c smtp smtp_session c
+ File smtpd smtpd c
+ smtp smtp_addr c smtp smtp_addr h smtp smtp c
+ smtp smtp_connect c smtp smtp h smtp smtp_params c
+ arguments Files src dns dns h src dns dns_rr_eq_sa c
+ only a subset of all arguments Files src dns dns h
diff --git a/postfix/proto/stop.double-proto-html b/postfix/proto/stop.double-proto-html
index a7e78243d..c216f9598 100644
--- a/postfix/proto/stop.double-proto-html
+++ b/postfix/proto/stop.double-proto-html
@@ -245,3 +245,4 @@ dt dt b name value b Postfix ge 3 0 dt
dt dt dd 4 Also log the hexadecimal and ASCII dump of complete
parametername stress something something Other
p Note on OpenBSD systems specify dev dev arandom when dev dev urandom
+ user3 example net smtp smtp relay example net submission
diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc
index 9eb8f8a7e..b1fce0d3b 100644
--- a/postfix/proto/stop.spell-cc
+++ b/postfix/proto/stop.spell-cc
@@ -1789,3 +1789,7 @@ deduplicate
digestbyname
mdctxPtr
ffdhe
+Korbar
+ign
+noport
+nopref
diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history
index 56e38baf7..46e64559b 100644
--- a/postfix/proto/stop.spell-history
+++ b/postfix/proto/stop.spell-history
@@ -40,3 +40,7 @@ Typofixes
segfault
Biggs
wordsmithing
+NOPORT
+NOPREF
+NOWEIGHT
+modernisms
diff --git a/postfix/proto/stop.spell-proto-html b/postfix/proto/stop.spell-proto-html
index 7a0806880..6d0cb20c7 100644
--- a/postfix/proto/stop.spell-proto-html
+++ b/postfix/proto/stop.spell-proto-html
@@ -354,3 +354,5 @@ FFDHE
dhe
ffdhe
kDHE
+srv
+wraptls
diff --git a/postfix/src/dns/dns.h b/postfix/src/dns/dns.h
index 5f53dbc8f..acc1fb029 100644
--- a/postfix/src/dns/dns.h
+++ b/postfix/src/dns/dns.h
@@ -158,7 +158,9 @@ typedef struct DNS_RR {
unsigned short class; /* C_IN, etc. */
unsigned int ttl; /* always */
unsigned int dnssec_valid; /* DNSSEC validated */
- unsigned short pref; /* T_MX only */
+ unsigned short pref; /* T_MX and T_SRV record related */
+ unsigned short weight; /* T_SRV related, defined in rfc2782 */
+ unsigned short port; /* T_SRV related, defined in rfc2782 */
struct DNS_RR *next; /* linkage */
size_t data_len; /* actual data size */
char data[1]; /* actually a bunch of data */
@@ -183,14 +185,29 @@ extern char *dns_strrecord(VSTRING *, DNS_RR *);
/*
* dns_rr.c
*/
+#define DNS_RR_NOPREF (0)
+#define DNS_RR_NOWEIGHT (0)
+#define DNS_RR_NOPORT (0)
+
+#define dns_rr_create_noport(qname, rname, type, class, ttl, pref, data, \
+ data_len) \
+ dns_rr_create((qname), (rname), (type), (class), (ttl), \
+ (pref), DNS_RR_NOWEIGHT, DNS_RR_NOPORT, (data), (data_len))
+
+#define dns_rr_create_nopref(qname, rname, type, class, ttl, data, data_len) \
+ dns_rr_create_noport((qname), (rname), (type), (class), (ttl), \
+ DNS_RR_NOPREF, (data), (data_len))
+
extern DNS_RR *dns_rr_create(const char *, const char *,
ushort, ushort,
unsigned, unsigned,
+ unsigned, unsigned,
const char *, size_t);
extern void dns_rr_free(DNS_RR *);
extern DNS_RR *dns_rr_copy(DNS_RR *);
extern DNS_RR *dns_rr_append(DNS_RR *, DNS_RR *);
extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
+extern DNS_RR *dns_srv_rr_sort(DNS_RR *);
extern int dns_rr_compare_pref_ipv6(DNS_RR *, DNS_RR *);
extern int dns_rr_compare_pref_ipv4(DNS_RR *, DNS_RR *);
extern int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *);
@@ -295,8 +312,9 @@ extern int dns_get_h_errno(void);
* Below is the precedence order. The order between DNS_RETRY and DNS_NOTFOUND
* is arbitrary.
*/
-#define DNS_RECURSE (-7) /* internal only: recursion needed */
-#define DNS_NOTFOUND (-6) /* query ok, data not found */
+#define DNS_RECURSE (-8) /* internal only: recursion needed */
+#define DNS_NOTFOUND (-7) /* query ok, data not found */
+#define DNS_NULLSRV (-6) /* query ok, service unavailable */
#define DNS_NULLMX (-5) /* query ok, service unavailable */
#define DNS_FAIL (-4) /* query failed, don't retry */
#define DNS_INVAL (-3) /* query ok, malformed reply */
diff --git a/postfix/src/dns/dns_lookup.c b/postfix/src/dns/dns_lookup.c
index 1c12a889d..d44cae7ee 100644
--- a/postfix/src/dns/dns_lookup.c
+++ b/postfix/src/dns/dns_lookup.c
@@ -234,6 +234,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* SRV Support by
+/* Tomas Korbar
+/* Red Hat, Inc.
/*--*/
/* System library. */
@@ -295,8 +299,8 @@ typedef struct DNS_REPLY {
#define INET6_ADDR_LEN 16 /* XXX */
/*
- * Use the threadsafe resolver API if available, not because it is theadsafe,
- * but because it has more functionality.
+ * Use the threadsafe resolver API if available, not because it is
+ * theadsafe, but because it has more functionality.
*/
#ifdef USE_RES_NCALLS
static struct __res_state dns_res_state;
@@ -740,6 +744,8 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
int comp_len;
ssize_t data_len;
unsigned pref = 0;
+ unsigned weight = 0;
+ unsigned port = 0;
unsigned char *src;
unsigned char *dst;
int ch;
@@ -765,6 +771,18 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
return (DNS_INVAL);
data_len = strlen(temp) + 1;
break;
+ case T_SRV:
+ GETSHORT(pref, pos);
+ GETSHORT(weight, pos);
+ GETSHORT(port, pos);
+ if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
+ return (DNS_RETRY);
+ if (*temp == 0)
+ return (DNS_NULLSRV);
+ if (!valid_rr_name(temp, "resource data", fixed->type, reply))
+ return (DNS_INVAL);
+ data_len = strlen(temp) + 1;
+ break;
case T_MX:
GETSHORT(pref, pos);
if (dn_expand(reply->buf, reply->end, pos, temp, sizeof(temp)) < 0)
@@ -860,7 +878,7 @@ static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
break;
}
*list = dns_rr_create(orig_name, rr_name, fixed->type, fixed->class,
- fixed->ttl, pref, tempbuf, data_len);
+ fixed->ttl, pref, weight, port, tempbuf, data_len);
return (DNS_OK);
}
@@ -960,7 +978,7 @@ static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
resource_found++;
rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
*rrlist = dns_rr_append(*rrlist, rr);
- } else if (status == DNS_NULLMX) {
+ } else if (status == DNS_NULLMX || status == DNS_NULLSRV) {
CORRUPT(status); /* TODO: use better name */
} else if (not_found_status != DNS_RETRY)
not_found_status = status;
@@ -1094,6 +1112,12 @@ int dns_lookup_x(const char *name, unsigned type, unsigned flags,
name);
DNS_SET_H_ERRNO(&dns_res_state, NO_DATA);
return (status);
+ case DNS_NULLSRV:
+ if (why)
+ vstring_sprintf(why, "Domain %s does not support SRV requests",
+ name);
+ DNS_SET_H_ERRNO(&dns_res_state, NO_DATA);
+ return (status);
case DNS_OK:
if (rrlist && dns_rr_filter_maps) {
if (dns_rr_filter_execute(rrlist) < 0) {
diff --git a/postfix/src/dns/dns_rr.c b/postfix/src/dns/dns_rr.c
index b550788b9..803263599 100644
--- a/postfix/src/dns/dns_rr.c
+++ b/postfix/src/dns/dns_rr.c
@@ -7,13 +7,15 @@
/* #include
/*
/* DNS_RR *dns_rr_create(qname, rname, type, class, ttl, preference,
-/* data, data_len)
+/* weight, port, data, data_len)
/* const char *qname;
/* const char *rname;
/* unsigned short type;
/* unsigned short class;
/* unsigned int ttl;
/* unsigned preference;
+/* unsigned weight;
+/* unsigned port;
/* const char *data;
/* size_t data_len;
/*
@@ -49,6 +51,30 @@
/* DNS_RR *dns_rr_remove(list, record)
/* DNS_RR *list;
/* DNS_RR *record;
+/*
+/* DNS_RR *dns_srv_rr_sort(list)
+/* DNS_RR *list;
+/* AUXILIARY FUNCTIONS
+/* DNS_RR *dns_rr_create_nopref(qname, rname, type, class, ttl,
+/* data, data_len)
+/* const char *qname;
+/* const char *rname;
+/* unsigned short type;
+/* unsigned short class;
+/* unsigned int ttl;
+/* const char *data;
+/* size_t data_len;
+/*
+/* DNS_RR *dns_rr_create_noport(qname, rname, type, class, ttl,
+/* preference, data, data_len)
+/* const char *qname;
+/* const char *rname;
+/* unsigned short type;
+/* unsigned short class;
+/* unsigned int ttl;
+/* unsigned preference;
+/* const char *data;
+/* size_t data_len;
/* DESCRIPTION
/* The routines in this module maintain memory for DNS resource record
/* information, and maintain lists of DNS resource records.
@@ -56,10 +82,14 @@
/* dns_rr_create() creates and initializes one resource record.
/* The \fIqname\fR field specifies the query name.
/* The \fIrname\fR field specifies the reply name.
-/* \fIpreference\fR is used for MX records; \fIdata\fR is a null
+/* \fIpreference\fR is used for MX and SRV records; \fIweight\fR
+/* and \fIport\fR are used for SRV records; \fIdata\fR is a null
/* pointer or specifies optional resource-specific data;
/* \fIdata_len\fR is the amount of resource-specific data.
/*
+/* dns_rr_create_nopref() and dns_rr_create_noport() are convenience
+/* wrappers around dns_rr_create() that take fewer arguments.
+/*
/* dns_rr_free() releases the resource used by of zero or more
/* resource records.
/*
@@ -81,6 +111,9 @@
/* dns_rr_remove() removes the specified record from the specified list.
/* The updated list is the result value.
/* The record MUST be a list member.
+/*
+/* dns_srv_rr_sort() sorts a list of SRV records according to
+/* their priority and weight as described in RFC 2782.
/* LICENSE
/* .ad
/* .fi
@@ -90,6 +123,15 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*
+/* SRV Support by
+/* Tomas Korbar
+/* Red Hat, Inc.
/*--*/
/* System library. */
@@ -113,6 +155,7 @@
DNS_RR *dns_rr_create(const char *qname, const char *rname,
ushort type, ushort class,
unsigned int ttl, unsigned pref,
+ unsigned weight, unsigned port,
const char *data, size_t data_len)
{
DNS_RR *rr;
@@ -125,6 +168,8 @@ DNS_RR *dns_rr_create(const char *qname, const char *rname,
rr->ttl = ttl;
rr->dnssec_valid = 0;
rr->pref = pref;
+ rr->weight = weight;
+ rr->port = port;
if (data && data_len > 0)
memcpy(rr->data, data, data_len);
rr->data_len = data_len;
@@ -247,6 +292,12 @@ DNS_RR *dns_rr_sort(DNS_RR *list, int (*compar) (DNS_RR *, DNS_RR *))
int len;
int i;
+ /*
+ * Avoid mymalloc() panic.
+ */
+ if (list == 0)
+ return (list);
+
/*
* Save state and initialize.
*/
@@ -293,6 +344,12 @@ DNS_RR *dns_rr_shuffle(DNS_RR *list)
int i;
int r;
+ /*
+ * Avoid mymalloc() panic.
+ */
+ if (list == 0)
+ return (list);
+
/*
* Build linear array with pointers to each list element.
*/
@@ -345,3 +402,141 @@ DNS_RR *dns_rr_remove(DNS_RR *list, DNS_RR *record)
}
return (list);
}
+
+/* weight_order - sort equal-priority records by weight */
+
+static void weight_order(DNS_RR **array, int count)
+{
+ int unordered_weights;
+ int i;
+
+ /*
+ * Compute the sum of record weights. If weights are not supplied then
+ * this function would be a noop. In fact this would be a noop when all
+ * weights have the same value, whether that weight is zero or not. There
+ * is no need to give special treatment to zero weights.
+ */
+ for (unordered_weights = 0, i = 0; i < count; i++)
+ unordered_weights += array[i]->weight;
+ if (unordered_weights == 0)
+ return;
+
+ /*
+ * The record ordering code below differs from RFC 2782 when the input
+ * contains a mix of zero and non-zero weights: the code below does not
+ * give special treatment to zero weights. Instead, it treats a zero
+ * weight just like any other small weight. Fewer special cases make for
+ * code that is simpler and more robust.
+ */
+ for (i = 0; i < count - 1; i++) {
+ int running_sum;
+ int threshold;
+ int k;
+ DNS_RR *temp;
+
+ /*
+ * Choose a random threshold [0..unordered_weights] inclusive.
+ */
+ threshold = myrand() % (unordered_weights + 1);
+
+ /*
+ * Move the first record with running_sum >= threshold to the ordered
+ * list, and update unordered_weights.
+ */
+ for (running_sum = 0, k = i; k < count; k++) {
+ running_sum += array[k]->weight;
+ if (running_sum >= threshold) {
+ unordered_weights -= array[k]->weight;
+ temp = array[i];
+ array[i] = array[k];
+ array[k] = temp;
+ break;
+ }
+ }
+ }
+}
+
+/* dns_srv_rr_sort - sort resource record list */
+
+DNS_RR *dns_srv_rr_sort(DNS_RR *list)
+{
+ int (*saved_user) (DNS_RR *, DNS_RR *);
+ DNS_RR **rr_array;
+ DNS_RR *rr;
+ int len;
+ int i;
+ int r;
+ int cur_pref;
+ int left_bound; /* inclusive */
+ int right_bound; /* non-inclusive */
+
+ /*
+ * Avoid mymalloc() panic, or rr_array[0] fence-post error.
+ */
+ if (list == 0)
+ return (list);
+
+ /*
+ * Save state and initialize.
+ */
+ saved_user = dns_rr_sort_user;
+ dns_rr_sort_user = dns_rr_compare_pref_any;
+
+ /*
+ * Build linear array with pointers to each list element.
+ */
+ for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
+ /* void */ ;
+ rr_array = (DNS_RR **) mymalloc(len * sizeof(*rr_array));
+ for (len = 0, rr = list; rr != 0; len++, rr = rr->next)
+ rr_array[len] = rr;
+
+ /*
+ * Shuffle resource records. Every element has an equal chance of landing
+ * in slot 0. After that every remaining element has an equal chance of
+ * landing in slot 1, ... This is exactly n! states for n! permutations.
+ */
+ for (i = 0; i < len - 1; i++) {
+ r = i + (myrand() % (len - i)); /* Victor&Son */
+ rr = rr_array[i];
+ rr_array[i] = rr_array[r];
+ rr_array[r] = rr;
+ }
+
+ /* First order the records by preference. */
+ qsort((void *) rr_array, len, sizeof(*rr_array), dns_rr_sort_callback);
+
+ /*
+ * Walk through records and sort the records in every same-preference
+ * partition according to their weight. Note that left_bound is
+ * inclusive, and that right-bound is non-inclusive.
+ */
+ left_bound = 0;
+ cur_pref = rr_array[left_bound]->pref; /* assumes len > 0 */
+
+ for (right_bound = 1; /* see below */ ; right_bound++) {
+ if (right_bound == len || rr_array[right_bound]->pref != cur_pref) {
+ if (right_bound - left_bound > 1)
+ weight_order(rr_array + left_bound, right_bound - left_bound);
+ if (right_bound == len)
+ break;
+ left_bound = right_bound;
+ cur_pref = rr_array[left_bound]->pref;
+ }
+ }
+
+ /*
+ * Fix the links.
+ */
+ for (i = 0; i < len - 1; i++)
+ rr_array[i]->next = rr_array[i + 1];
+ rr_array[i]->next = 0;
+ list = rr_array[0];
+
+ /*
+ * Cleanup.
+ */
+ myfree((void *) rr_array);
+ dns_rr_sort_user = saved_user;
+ return (list);
+}
diff --git a/postfix/src/dns/dns_rr_eq_sa.c b/postfix/src/dns/dns_rr_eq_sa.c
index 8113d6b26..f553a0323 100644
--- a/postfix/src/dns/dns_rr_eq_sa.c
+++ b/postfix/src/dns/dns_rr_eq_sa.c
@@ -122,7 +122,7 @@ int main(int argc, char **argv)
if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0)
msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr));
- if ((rr = dns_sa_to_rr(argv[1], 0, res1->ai_addr)) == 0)
+ if ((rr = dns_sa_to_rr(argv[1], DNS_RR_NOPREF, res1->ai_addr)) == 0)
msg_fatal("dns_sa_to_rr: %m");
freeaddrinfo(res1);
diff --git a/postfix/src/dns/dns_sa_to_rr.c b/postfix/src/dns/dns_sa_to_rr.c
index 6b9efcc17..b5dee2091 100644
--- a/postfix/src/dns/dns_sa_to_rr.c
+++ b/postfix/src/dns/dns_sa_to_rr.c
@@ -55,14 +55,14 @@ DNS_RR *dns_sa_to_rr(const char *hostname, unsigned pref, struct sockaddr *sa)
#define DUMMY_TTL 0
if (sa->sa_family == AF_INET) {
- return (dns_rr_create(hostname, hostname, T_A, C_IN, DUMMY_TTL, pref,
- (char *) &SOCK_ADDR_IN_ADDR(sa),
- sizeof(SOCK_ADDR_IN_ADDR(sa))));
+ return (dns_rr_create_noport(hostname, hostname, T_A, C_IN, DUMMY_TTL,
+ pref, (char *) &SOCK_ADDR_IN_ADDR(sa),
+ sizeof(SOCK_ADDR_IN_ADDR(sa))));
#ifdef HAS_IPV6
} else if (sa->sa_family == AF_INET6) {
- return (dns_rr_create(hostname, hostname, T_AAAA, C_IN, DUMMY_TTL, pref,
- (char *) &SOCK_ADDR_IN6_ADDR(sa),
- sizeof(SOCK_ADDR_IN6_ADDR(sa))));
+ return (dns_rr_create_noport(hostname, hostname, T_AAAA, C_IN, DUMMY_TTL,
+ pref, (char *) &SOCK_ADDR_IN6_ADDR(sa),
+ sizeof(SOCK_ADDR_IN6_ADDR(sa))));
#endif
} else {
errno = EAFNOSUPPORT;
@@ -121,7 +121,7 @@ int main(int argc, char **argv)
resv[len++] = res;
qsort((void *) resv, len, sizeof(*resv), compare_family);
for (n = 0; n < len; n++) {
- if ((rr = dns_sa_to_rr(argv[0], 0, resv[n]->ai_addr)) == 0)
+ if ((rr = dns_sa_to_rr(argv[0], DNS_RR_NOPREF, resv[n]->ai_addr)) == 0)
msg_fatal("dns_sa_to_rr: %m");
if (dns_rr_to_pa(rr, &hostaddr) == 0)
msg_fatal("dns_rr_to_pa: %m");
diff --git a/postfix/src/dns/dns_str_resflags.c b/postfix/src/dns/dns_str_resflags.c
index 472394c3a..793da1c26 100644
--- a/postfix/src/dns/dns_str_resflags.c
+++ b/postfix/src/dns/dns_str_resflags.c
@@ -21,6 +21,8 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Viktor Dukhovni
/*--*/
/*
@@ -52,11 +54,11 @@
static const LONG_NAME_MASK resflag_table[] = {
"RES_INIT", RES_INIT,
"RES_DEBUG", RES_DEBUG,
-#ifdef RES_AAONLY
+#if defined(RES_AAONLY) && !HAVE_GLIBC_API_VERSION_SUPPORT(2, 24)
"RES_AAONLY", RES_AAONLY,
#endif
"RES_USEVC", RES_USEVC,
-#ifdef RES_PRIMARY
+#if defined(RES_PRIMARY) && !HAVE_GLIBC_API_VERSION_SUPPORT(2, 24)
"RES_PRIMARY", RES_PRIMARY,
#endif
"RES_IGNTC", RES_IGNTC,
@@ -77,15 +79,15 @@ static const LONG_NAME_MASK resflag_table[] = {
#ifdef RES_ROTATE
"RES_ROTATE", RES_ROTATE,
#endif
-#ifdef RES_NOCHECKNAME
+#if defined(RES_NOCHECKNAME) && !HAVE_GLIBC_API_VERSION_SUPPORT(2, 24)
"RES_NOCHECKNAME", RES_NOCHECKNAME,
#endif
"RES_USE_EDNS0", RES_USE_EDNS0,
"RES_USE_DNSSEC", RES_USE_DNSSEC,
-#ifdef RES_KEEPTSIG
+#if defined(RES_KEEPTSIG) && !HAVE_GLIBC_API_VERSION_SUPPORT(2, 24)
"RES_KEEPTSIG", RES_KEEPTSIG,
#endif
-#ifdef RES_BLAST
+#if defined(RES_BLAST) && !HAVE_GLIBC_API_VERSION_SUPPORT(2, 24)
"RES_BLAST", RES_BLAST,
#endif
#ifdef RES_USEBSTRING
diff --git a/postfix/src/dns/dns_strrecord.c b/postfix/src/dns/dns_strrecord.c
index 6b8e9893e..1e3b74389 100644
--- a/postfix/src/dns/dns_strrecord.c
+++ b/postfix/src/dns/dns_strrecord.c
@@ -80,6 +80,10 @@ char *dns_strrecord(VSTRING *buf, DNS_RR *rr)
case T_MX:
vstring_sprintf_append(buf, "%u %s.", rr->pref, rr->data);
break;
+ case T_SRV:
+ vstring_sprintf_append(buf, "%u %u %u %s.", rr->pref, rr->weight,
+ rr->port, rr->data);
+ break;
case T_TLSA:
if (rr->data_len >= 3) {
uint8_t *ip = (uint8_t *) rr->data;
diff --git a/postfix/src/dns/dns_strtype.c b/postfix/src/dns/dns_strtype.c
index 70e59acdc..7eebe3c08 100644
--- a/postfix/src/dns/dns_strtype.c
+++ b/postfix/src/dns/dns_strtype.c
@@ -180,6 +180,9 @@ static struct dns_type_map dns_type_map[] = {
#ifdef T_ANY
T_ANY, "ANY",
#endif
+#ifdef T_SRV
+ T_SRV, "SRV",
+#endif
};
/* dns_strtype - translate DNS query type to string */
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 4df9b7b02..b364850c5 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -4364,6 +4364,21 @@ extern char *var_dnssec_probe;
"lmtp=24, smtp=25, smtps=submissions=465, submission=587"
extern char *var_known_tcp_ports;
+ /*
+ * SRV lookup support.
+ */
+#define VAR_USE_SRV_LOOKUP "use_srv_lookup"
+#define DEF_USE_SRV_LOOKUP ""
+extern char *var_use_srv_lookup;
+
+#define VAR_IGN_SRV_LOOKUP_ERR "ignore_srv_lookup_error"
+#define DEF_IGN_SRV_LOOKUP_ERR 0
+extern bool var_ign_srv_lookup_err;
+
+#define VAR_ALLOW_SRV_FALLBACK "allow_srv_lookup_fallback"
+#define DEF_ALLOW_SRV_FALLBACK 0
+extern bool var_allow_srv_fallback;
+
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index fcf78608e..d67ef3aac 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20230128"
+#define MAIL_RELEASE_DATE "20230219"
#define MAIL_VERSION_NUMBER "3.8"
#ifdef SNAPSHOT
diff --git a/postfix/src/posttls-finger/posttls-finger.c b/postfix/src/posttls-finger/posttls-finger.c
index 5526c408d..2a9efe2db 100644
--- a/postfix/src/posttls-finger/posttls-finger.c
+++ b/postfix/src/posttls-finger/posttls-finger.c
@@ -237,6 +237,8 @@
/* is encountered, up to 5 times or as specified with the \fB-m\fR option.
/* By default reconnection is disabled, specify a positive delay to
/* enable this behavior.
+/* .IP "\fB-R\fR"
+/* Use SRV lookup instead of MX.
/* .IP "\fB-s \fIservername\fR"
/* The server name to send with the TLS Server Name Indication (SNI)
/* extension. When the server has DANE TLSA records, this parameter
@@ -469,6 +471,7 @@ typedef struct STATE {
DNS_RR *mx; /* MX RRset qname, rname, valid */
int pass; /* Pass number, 2 for reconnect */
int nochat; /* disable chat logging */
+ int dosrv; /* look up SRV records instead of MX */
char *helo; /* Server name from EHLO reply */
DSN_BUF *why; /* SMTP-style error message */
VSTRING *buffer; /* Response buffer */
@@ -1159,7 +1162,7 @@ static VSTREAM *connect_addr(STATE *state, DNS_RR *addr)
/* addr_one - address lookup for one host name */
static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
- int res_opt, unsigned pref)
+ int res_opt, unsigned pref, unsigned port)
{
static const char *myname = "addr_one";
DSN_BUF *why = state->why;
@@ -1182,6 +1185,8 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
msg_fatal("host %s: conversion error for address family %d: %m",
host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
+ addr->pref = pref;
+ addr->port = port;
addr_list = dns_rr_append(addr_list, addr);
freeaddrinfo(res0);
return (addr_list);
@@ -1198,8 +1203,10 @@ static DNS_RR *addr_one(STATE *state, DNS_RR *addr_list, const char *host,
why->reason, DNS_REQ_FLAG_NONE,
proto_info->dns_atype_list)) {
case DNS_OK:
- for (rr = addr; rr; rr = rr->next)
+ for (rr = addr; rr; rr = rr->next) {
rr->pref = pref;
+ rr->port = port;
+ }
addr_list = dns_rr_append(addr_list, addr);
return (addr_list);
default:
@@ -1286,15 +1293,15 @@ static DNS_RR *mx_addr_list(STATE *state, DNS_RR *mx_names)
#endif
for (rr = mx_names; rr; rr = rr->next) {
- if (rr->type != T_MX)
+ if (rr->type != T_MX && rr->type != T_SRV)
msg_panic("%s: bad resource type: %d", myname, rr->type);
addr_list = addr_one(state, addr_list, (char *) rr->data, res_opt,
- rr->pref);
+ rr->pref, rr->port);
}
return (addr_list);
}
-/* smtp_domain_addr - mail exchanger address lookup */
+/* domain_addr - mail exchanger address lookup */
static DNS_RR *domain_addr(STATE *state, char *domain)
{
@@ -1359,6 +1366,74 @@ static DNS_RR *domain_addr(STATE *state, char *domain)
return (addr_list);
}
+/* service_addr - mail exchanger address lookup */
+
+static DNS_RR *service_addr(STATE *state, const char *domain,
+ const char *service)
+{
+ VSTRING *srv_qname = vstring_alloc(100);
+ char *str_srv_qname;
+ DNS_RR *srv_names;
+ DNS_RR *addr_list = 0;
+ int r = 0; /* Resolver flags */
+ const char *aname;
+
+ dsb_reset(state->why);
+
+#if (RES_USE_DNSSEC != 0) && (RES_USE_EDNS0 != 0)
+ r |= RES_USE_DNSSEC;
+#endif
+
+ vstring_sprintf(srv_qname, "_%s._tcp.%s", service, domain);
+ str_srv_qname = STR(srv_qname);
+
+ /*
+ * IDNA support.
+ */
+#ifndef NO_EAI
+ if (!allascii(str_srv_qname)
+ && (aname = midna_domain_to_ascii(str_srv_qname)) != 0) {
+ msg_info("%s asciified to %s", str_srv_qname, aname);
+ } else
+#endif
+ aname = str_srv_qname;
+
+ switch (dns_lookup(aname, T_SRV, r, &srv_names, (VSTRING *) 0,
+ state->why->reason)) {
+ default:
+ dsb_status(state->why, "4.4.3");
+ break;
+ case DNS_INVAL:
+ dsb_status(state->why, "5.4.4");
+ break;
+ case DNS_NULLMX:
+ dsb_status(state->why, "5.1.0");
+ break;
+ case DNS_FAIL:
+ dsb_status(state->why, "5.4.3");
+ break;
+ case DNS_OK:
+ /* Shuffle then sort the SRV rr records by priority and weight. */
+ srv_names = dns_srv_rr_sort(srv_names);
+ addr_list = mx_addr_list(state, srv_names);
+ state->mx = dns_rr_copy(srv_names);
+ dns_rr_free(srv_names);
+ if (addr_list == 0) {
+ msg_warn("no SRV host for %s has a valid address record",
+ str_srv_qname);
+ break;
+ }
+ /* TODO: sort by priority, weight, and address family preference. */
+ break;
+ case DNS_NOTFOUND:
+ dsb_status(state->why, "5.4.4");
+ break;
+ }
+
+ vstring_free(srv_qname);
+ return (addr_list);
+}
+
/* host_addr - direct host lookup */
static DNS_RR *host_addr(STATE *state, const char *host)
@@ -1385,7 +1460,8 @@ static DNS_RR *host_addr(STATE *state, const char *host)
ahost = host;
#define PREF0 0
- addr_list = addr_one(state, (DNS_RR *) 0, ahost, res_opt, PREF0);
+#define NOPORT 0
+ addr_list = addr_one(state, (DNS_RR *) 0, ahost, res_opt, PREF0, NOPORT);
if (addr_list && addr_list->next) {
addr_list = dns_rr_shuffle(addr_list);
if (inet_proto_info()->ai_family_list[1] != 0)
@@ -1469,7 +1545,8 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
/* parse_destination - parse host/port destination */
static char *parse_destination(char *destination, char *def_service,
- char **hostp, unsigned *portp)
+ char **hostp, char **servicep,
+ unsigned *portp)
{
char *buf = mystrdup(destination);
char *service;
@@ -1485,13 +1562,13 @@ static char *parse_destination(char *destination, char *def_service,
* Parse the host/port information. We're working with a copy of the
* destination argument so the parsing can be destructive.
*/
- if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0)
+ if ((err = host_port(buf, hostp, (char *) 0, servicep, def_service)) != 0)
msg_fatal("%s in server description: %s", err, destination);
/*
* Convert service to port number, network byte order.
*/
- service = (char *) filter_known_tcp_port(service);
+ service = (char *) filter_known_tcp_port(*servicep);
if (alldig(service)) {
if ((port = atoi(service)) >= 65536 || port == 0)
msg_fatal("bad network port: %s for destination: %s",
@@ -1515,15 +1592,18 @@ static void connect_remote(STATE *state, char *dest)
DNS_RR *addr;
char *buf;
char *domain;
+ char *service;
/* When reconnecting use IP address of previous session */
if (state->addr == 0) {
buf = parse_destination(dest, state->smtp ? "smtp" : "24",
- &domain, &state->port);
+ &domain, &service, &state->port);
if (!state->nexthop)
state->nexthop = mystrdup(domain);
if (state->smtp == 0 || *dest == '[')
state->addr = host_addr(state, domain);
+ else if (state->dosrv)
+ state->addr = service_addr(state, domain, service);
else
state->addr = domain_addr(state, domain);
myfree(buf);
@@ -1537,10 +1617,14 @@ static void connect_remote(STATE *state, char *dest)
for (addr = state->addr; addr; addr = addr->next) {
int level = dane_host_level(state, addr);
+ if (addr->port) /* SRV port override */
+ state->port = htons(addr->port);
+
if (level == TLS_LEV_INVALID
|| (state->stream = connect_addr(state, addr)) == 0) {
- msg_info("Failed to establish session to %s via %s: %s",
- dest, HNAME(addr), vstring_str(state->why->reason));
+ msg_info("Failed to establish session to %s:%s via %s:%u: %s",
+ dest, service, HNAME(addr), addr->port,
+ vstring_str(state->why->reason));
continue;
}
/* We have a connection */
@@ -1808,6 +1892,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
state->smtp = 1;
state->pass = 1;
+ state->dosrv = 0;
state->reconnect = -1;
state->max_reconnect = 5;
state->wrapper_mode = 0;
@@ -1818,7 +1903,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
memset((void *) &state->options, 0, sizeof(state->options));
state->options.host_lookup = mystrdup("dns");
-#define OPTS "a:ch:o:St:T:v"
+#define OPTS "a:ch:o:RSt:T:v"
#ifdef USE_TLS
#define TLSOPTS "A:Cd:fF:g:H:k:K:l:L:m:M:p:P:r:s:wX"
@@ -1857,6 +1942,9 @@ static void parse_options(STATE *state, int argc, char *argv[])
case 'o':
override(optarg);
break;
+ case 'R':
+ state->dosrv = 1;
+ break;
case 'S':
state->smtp = 0;
break;
diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c
index cc3364642..bca7cd494 100644
--- a/postfix/src/smtp/lmtp_params.c
+++ b/postfix/src/smtp/lmtp_params.c
@@ -65,6 +65,7 @@
VAR_LMTP_DNS_RE_FILTER, DEF_LMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0,
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0,
+ VAR_USE_SRV_LOOKUP, DEF_USE_SRV_LOOKUP, &var_use_srv_lookup, 0, 0,
0,
};
static const CONFIG_TIME_TABLE lmtp_time_table[] = {
@@ -128,6 +129,8 @@
VAR_LMTP_DUMMY_MAIL_AUTH, DEF_LMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth,
VAR_LMTP_BALANCE_INET_PROTO, DEF_LMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto,
VAR_LMTP_BIND_ADDR_ENFORCE, DEF_LMTP_BIND_ADDR_ENFORCE, &var_smtp_bind_addr_enforce,
+ VAR_IGN_SRV_LOOKUP_ERR, DEF_IGN_SRV_LOOKUP_ERR, &var_ign_srv_lookup_err,
+ VAR_ALLOW_SRV_FALLBACK, DEF_ALLOW_SRV_FALLBACK, &var_allow_srv_fallback,
0,
};
static const CONFIG_NBOOL_TABLE lmtp_nbool_table[] = {
diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c
index a398dc5ae..e865197ab 100644
--- a/postfix/src/smtp/smtp.c
+++ b/postfix/src/smtp/smtp.c
@@ -146,6 +146,7 @@
/* RFC 2046 (MIME: Media Types)
/* RFC 2554 (AUTH command)
/* RFC 2821 (SMTP protocol)
+/* RFC 2782 (SRV resource records)
/* RFC 2920 (SMTP Pipelining)
/* RFC 3207 (STARTTLS command)
/* RFC 3461 (SMTP DSN Extension)
@@ -352,6 +353,17 @@
/* DATA requests, when deadlines are enabled with smtp_per_request_deadline.
/* .IP "\fBheader_from_format (standard)\fR"
/* The format of the Postfix-generated \fBFrom:\fR header.
+/* .PP
+/* Available in Postfix version 3.8 and later:
+/* .IP "\fBuse_srv_lookup (empty)\fR"
+/* Enables discovery for the specified service(s) using DNS SRV
+/* records.
+/* .IP "\fBignore_srv_lookup_error (no)\fR"
+/* When SRV record lookup fails, fall back to MX or IP address
+/* lookup as if SRV record lookups were not enabled.
+/* .IP "\fBallow_srv_lookup_fallback (no)\fR"
+/* When SRV record lookup fails or no SRV record exists, fall back
+/* to MX or IP address lookup as if SRV record lookups were not enabled.
/* MIME PROCESSING CONTROLS
/* .ad
/* .fi
@@ -1095,6 +1107,9 @@ char *var_smtp_dns_re_filter;
bool var_smtp_balance_inet_proto;
bool var_smtp_req_deadline;
int var_smtp_min_data_rate;
+char *var_use_srv_lookup;
+bool var_ign_srv_lookup_err;
+bool var_allow_srv_fallback;
/* Special handling of 535 AUTH errors. */
char *var_smtp_sasl_auth_cache_name;
@@ -1121,6 +1136,7 @@ HBC_CHECKS *smtp_header_checks; /* limited header checks */
HBC_CHECKS *smtp_body_checks; /* limited body checks */
SMTP_CLI_ATTR smtp_cli_attr; /* parsed command-line */
int smtp_hfrom_format; /* postmaster notifications */
+STRING_LIST *smtp_use_srv_lookup;
#ifdef USE_TLS
@@ -1411,6 +1427,14 @@ static void post_init(char *unused_name, char **argv)
* header_from format, for postmaster notifications.
*/
smtp_hfrom_format = hfrom_format_parse(VAR_HFROM_FORMAT, var_hfrom_format);
+
+ /*
+ * Service discovery with SRV record lookup.
+ */
+ if (*var_use_srv_lookup)
+ smtp_use_srv_lookup = string_list_init(VAR_USE_SRV_LOOKUP,
+ MATCH_FLAG_RETURN,
+ var_use_srv_lookup);
}
/* pre_init - pre-jail initialization */
diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h
index 742ed300c..0864313b7 100644
--- a/postfix/src/smtp/smtp.h
+++ b/postfix/src/smtp/smtp.h
@@ -84,6 +84,14 @@ typedef struct SMTP_ITERATOR {
vstring_strcpy((iter)->dest, STR((iter)->saved_dest)); \
} while (0)
+#define SMTP_ITER_UPDATE_HOST(iter, _host, _addr, _rr) do { \
+ vstring_strcpy((iter)->host, (_host)); \
+ vstring_strcpy((iter)->addr, (_addr)); \
+ (iter)->rr = (_rr); \
+ if ((_rr)->port) \
+ (iter)->port = htons((_rr)->port); /* SRV port override */ \
+ } while (0)
+
/*
* TLS Policy support.
*/
@@ -273,6 +281,7 @@ typedef struct SMTP_STATE {
#define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<7)
#define SMTP_MISC_FLAG_PREF_IPV6 (1<<8)
#define SMTP_MISC_FLAG_PREF_IPV4 (1<<9)
+#define SMTP_MISC_FLAG_FALLBACK_SRV_TO_MX (1<<10)
#define SMTP_MISC_FLAG_CONN_CACHE_MASK \
(SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE)
@@ -312,6 +321,8 @@ extern MAPS *smtp_generic_maps; /* make internal address valid */
extern int smtp_ext_prop_mask; /* address extension propagation */
extern unsigned smtp_dns_res_opt; /* DNS query flags */
+extern STRING_LIST *smtp_use_srv_lookup;/* services with SRV record lookup */
+
#ifdef USE_TLS
extern TLS_APPL_STATE *smtp_tls_ctx; /* client-side TLS engine */
diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c
index 2b5c126e5..a31cb38c1 100644
--- a/postfix/src/smtp/smtp_addr.c
+++ b/postfix/src/smtp/smtp_addr.c
@@ -17,6 +17,15 @@
/* char *name;
/* int misc_flags;
/* DSN_BUF *why;
+/*
+/* DNS_RR *smtp_service_addr(name, service, mxrr, misc_flags, why,
+/* found_myself)
+/* const char *name;
+/* const char *service;
+/* DNS_RR **mxrr;
+/* int misc_flags;
+/* DSN_BUF *why;
+/* int *found_myself;
/* DESCRIPTION
/* This module implements Internet address lookups. By default,
/* lookups are done via the Internet domain name service (DNS).
@@ -33,6 +42,8 @@
/* destination. If MX records were found, the rname, qname,
/* and dnssec validation status of the MX RRset are returned
/* via mxrr, which the caller must free with dns_rr_free().
+/* Fallback from MX to address lookups is governed by RFC 2821,
+/* and by local policy (var_ign_mx_lookup_err).
/*
/* When no mail exchanger is listed in the DNS for \fIname\fR, the
/* request is passed to smtp_host_addr().
@@ -44,8 +55,18 @@
/* host. The host can be specified as a numerical Internet network
/* address, or as a symbolic host name.
/*
-/* Results from smtp_domain_addr() or smtp_host_addr() are
-/* destroyed by dns_rr_free(), including null lists.
+/* smtp_service_addr() looks up addresses for hosts specified
+/* in SRV records for the specified domain and service. This
+/* supports the features of smtp_domain_addr() except that
+/* the order of SRV records is determined by RFC 2782, and
+/* that address records are not sorted by IP address family
+/* preference. Fallback from SRV to MX or address lookups is
+/* governed by local policy (var_ign_mx_lookup_err and
+/* var_allow_srv_fallback).
+/*
+/* Results from smtp_domain_addr(), smtp_host_addr(), and
+/* smtp_service_addr() are destroyed by dns_rr_free(), including
+/* null lists.
/* DIAGNOSTICS
/* Panics: interface violations. For example, calling smtp_domain_addr()
/* when DNS lookups are explicitly disabled.
@@ -66,6 +87,10 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* SRV Support by
+/* Tomas Korbar
+/* Red Hat, Inc.
/*--*/
/* System library. */
@@ -130,7 +155,8 @@ static void smtp_print_addr(const char *what, DNS_RR *addr_list)
/* smtp_addr_one - address lookup for one host name */
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
- unsigned pref, DSN_BUF *why)
+ unsigned pref, unsigned port,
+ DSN_BUF *why)
{
const char *myname = "smtp_addr_one";
DNS_RR *addr = 0;
@@ -154,6 +180,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
msg_fatal("host %s: conversion error for address family "
"%d: %m", host, res0->ai_addr->sa_family);
addr_list = dns_rr_append(addr_list, addr);
+ addr->pref = pref;
+ addr->port = port;
if (msg_verbose)
msg_info("%s: using numerical host %s", myname, host);
freeaddrinfo(res0);
@@ -174,8 +202,10 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, const char *host, int res_opt,
why->reason, DNS_REQ_FLAG_NONE,
proto_info->dns_atype_list)) {
case DNS_OK:
- for (rr = addr; rr; rr = rr->next)
+ for (rr = addr; rr; rr = rr->next) {
rr->pref = pref;
+ rr->port = port;
+ }
addr_list = dns_rr_append(addr_list, addr);
return (addr_list);
default:
@@ -293,10 +323,10 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
* tweaking the in-process resolver flags.
*/
for (rr = mx_names; rr; rr = rr->next) {
- if (rr->type != T_MX)
+ if (rr->type != T_MX && rr->type != T_SRV)
msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
addr_list = smtp_addr_one(addr_list, (char *) rr->data, res_opt,
- rr->pref, why);
+ rr->pref, rr->port, why);
}
return (addr_list);
}
@@ -678,7 +708,7 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
* address to internal form. Otherwise, the host is specified by name.
*/
#define PREF0 0
- addr_list = smtp_addr_one((DNS_RR *) 0, ahost, res_opt, PREF0, why);
+ addr_list = smtp_addr_one((DNS_RR *) 0, ahost, res_opt, PREF0, 0, why);
if (addr_list
&& (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
&& smtp_find_self(addr_list) != 0) {
@@ -700,3 +730,129 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
smtp_print_addr(host, addr_list);
return (addr_list);
}
+
+/* smtp_service_addr - service address lookup */
+
+DNS_RR *smtp_service_addr(const char *name, const char *service, DNS_RR **mxrr,
+ int misc_flags, DSN_BUF *why,
+ int *found_myself)
+{
+ static VSTRING *srv_qname = 0;
+ const char *str_srv_qname;
+ DNS_RR *srv_names = 0;
+ DNS_RR *addr_list = 0;
+ DNS_RR *self = 0;
+ unsigned best_pref;
+ unsigned best_found;
+ int r = 0;
+ const char *aname;
+ int allow_non_srv_fallback = var_allow_srv_fallback;
+
+ dsb_reset(why);
+
+ /*
+ * Sanity check.
+ */
+ if (smtp_dns_support == SMTP_DNS_DISABLED)
+ msg_panic("smtp_service_addr: DNS lookup is disabled");
+
+ if (smtp_dns_support == SMTP_DNS_DNSSEC) {
+ r |= RES_USE_DNSSEC;
+ }
+ if (srv_qname == 0)
+ srv_qname = vstring_alloc(100);
+ vstring_sprintf(srv_qname, "_%s._tcp.%s", service, name);
+ str_srv_qname = STR(srv_qname);
+
+ /*
+ * IDNA support.
+ */
+#ifndef NO_EAI
+ if (!allascii(str_srv_qname)
+ && (aname = midna_domain_to_ascii(str_srv_qname)) != 0) {
+ if (msg_verbose)
+ msg_info("%s asciified to %s", str_srv_qname, aname);
+ } else
+#endif
+ aname = str_srv_qname;
+
+ switch (dns_lookup(aname, T_SRV, r, &srv_names, (VSTRING *) 0,
+ why->reason)) {
+ default:
+ dsb_status(why, "4.4.3");
+ allow_non_srv_fallback |= var_ign_srv_lookup_err;
+ break;
+ case DNS_INVAL:
+ dsb_status(why, "5.4.4");
+ allow_non_srv_fallback |= var_ign_srv_lookup_err;
+ break;
+ case DNS_POLICY:
+ dsb_status(why, "4.7.0");
+ break;
+ case DNS_FAIL:
+ dsb_status(why, "5.4.3");
+ allow_non_srv_fallback |= var_ign_srv_lookup_err;
+ break;
+ case DNS_NULLSRV:
+ dsb_status(why, "5.1.0");
+ break;
+ case DNS_OK:
+ /* Shuffle then sort the SRV rr records by priority and weight. */
+ srv_names = dns_srv_rr_sort(srv_names);
+ best_pref = (srv_names ? srv_names->pref : IMPOSSIBLE_PREFERENCE);
+ addr_list = smtp_addr_list(srv_names, why);
+ if (mxrr)
+ *mxrr = dns_rr_copy(srv_names); /* copies one record! */
+ dns_rr_free(srv_names);
+ if (addr_list == 0) {
+ msg_warn("no SRV host for %s has a valid address record",
+ str_srv_qname);
+ break;
+ }
+ /* Optional loop prevention, similar to smtp_domain_addr(). */
+ best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);
+ if (msg_verbose)
+ smtp_print_addr(aname, addr_list);
+ if ((misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
+ && (self = smtp_find_self(addr_list)) != 0) {
+ addr_list = smtp_truncate_self(addr_list, self->pref);
+ if (addr_list == 0) {
+ if (best_pref != best_found) {
+ dsb_simple(why, "4.4.4",
+ "unable to find primary relay for %s",
+ str_srv_qname);
+ } else {
+ dsb_simple(why, "5.4.6", "mail for %s loops back to myself",
+ str_srv_qname);
+ }
+ }
+ }
+ /* TODO: sort by priority, weight, and address family preference. */
+
+ /* Optional address family balancing, as in smtp_domain_addr(). */
+ if (addr_list && addr_list->next) {
+ if (var_smtp_mxaddr_limit > 0 && var_smtp_balance_inet_proto)
+ addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
+ var_smtp_mxaddr_limit);
+ }
+ break;
+ case DNS_NOTFOUND:
+ dsb_status(why, "5.4.4");
+ break;
+ }
+ *found_myself |= (self != 0);
+
+ /*
+ * If permitted, fall back to non-SRV record lookups.
+ */
+ if (addr_list == 0 && allow_non_srv_fallback) {
+ msg_info("skipping SRV lookup for %s: %s",
+ str_srv_qname, STR(why->reason));
+ if (misc_flags & SMTP_MISC_FLAG_FALLBACK_SRV_TO_MX)
+ addr_list = smtp_domain_addr(name, mxrr, misc_flags, why,
+ found_myself);
+ else
+ addr_list = smtp_host_addr(name, misc_flags, why);
+ }
+ return (addr_list);
+}
diff --git a/postfix/src/smtp/smtp_addr.h b/postfix/src/smtp/smtp_addr.h
index 8f20961e5..60ea2b47e 100644
--- a/postfix/src/smtp/smtp_addr.h
+++ b/postfix/src/smtp/smtp_addr.h
@@ -18,6 +18,7 @@
*/
extern DNS_RR *smtp_host_addr(const char *, int, DSN_BUF *);
extern DNS_RR *smtp_domain_addr(const char *, DNS_RR **, int, DSN_BUF *, int *);
+extern DNS_RR *smtp_service_addr(const char *, const char *, DNS_RR **, int, DSN_BUF *, int *);
/* LICENSE
/* .ad
@@ -28,4 +29,9 @@ extern DNS_RR *smtp_domain_addr(const char *, DNS_RR **, int, DSN_BUF *, int *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c
index ed58180f6..68faca18e 100644
--- a/postfix/src/smtp/smtp_connect.c
+++ b/postfix/src/smtp/smtp_connect.c
@@ -28,7 +28,8 @@
/* destinations may be specified as "unix:pathname", "inet:host"
/* or "inet:host:port".
/*
-/* With SMTP, the Internet domain name service is queried for mail
+/* With SMTP, or with SRV record lookup enabled, the Internet
+/* domain name service is queried for mail
/* exchanger hosts. Quote the domain name with `[' and `]' to
/* suppress mail exchanger lookups.
/*
@@ -357,7 +358,8 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr *sa,
/* smtp_parse_destination - parse host/port destination */
static char *smtp_parse_destination(char *destination, char *def_service,
- char **hostp, unsigned *portp)
+ char **hostp, char **servicep,
+ unsigned *portp)
{
char *buf = mystrdup(destination);
char *service;
@@ -373,13 +375,13 @@ static char *smtp_parse_destination(char *destination, char *def_service,
* Parse the host/port information. We're working with a copy of the
* destination argument so the parsing can be destructive.
*/
- if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0)
+ if ((err = host_port(buf, hostp, (char *) 0, servicep, def_service)) != 0)
msg_fatal("%s in server description: %s", err, destination);
/*
* Convert service to port number, network byte order.
*/
- service = (char *) filter_known_tcp_port(service);
+ service = (char *) filter_known_tcp_port(*servicep);
if (alldig(service)) {
if ((port = atoi(service)) >= 65536 || port == 0)
msg_fatal("bad network port: %s for destination: %s",
@@ -661,6 +663,9 @@ static void smtp_update_addr_list(DNS_RR **addr_list, const char *server_addr,
* XXX Extend the SMTP_SESSION structure with sockaddr information so that
* we can avoid repeated string->binary transformations for the same
* address.
+ *
+ * XXX SRV support: this should match the port, too, otherwise we may
+ * eliminate too many list entries.
*/
if ((aierr = hostaddr_to_sockaddr(server_addr, (char *) 0, 0, &res0)) != 0) {
msg_warn("hostaddr_to_sockaddr %s: %s",
@@ -691,6 +696,18 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list,
DSN_BUF *why = state->why;
/*
+ * This code is called after server address/port lookup, before
+ * iter->host, iter->addr, iter->rr and iter->mx are assigned concrete
+ * values, and while iter->port still corresponds to the nexthop service,
+ * or the default service configured with smtp_tcp_port or lmtp_tcp_port.
+ *
+ * When a connection is reused by nexthop/service or by server address/port,
+ * iter->host, iter->addr and iter->port are updated with actual values
+ * from the cached session. Additionally, when a connection is searched
+ * by nexthop/service, iter->rr remains null, and when a connection is
+ * searched by server address/port, iter->rr is updated with an actual
+ * server address/port before the search is made.
+ *
* First, search the cache by delivery request nexthop. We truncate the
* server address list when all the sessions for this destination are
* used up, to reduce the number of variables that need to be checked
@@ -757,9 +774,7 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list,
/* XXX Assume there is no code at the end of this loop. */
continue;
}
- vstring_strcpy(iter->addr, hostaddr.buf);
- vstring_strcpy(iter->host, SMTP_HNAME(addr));
- iter->rr = addr;
+ SMTP_ITER_UPDATE_HOST(iter, SMTP_HNAME(addr), hostaddr.buf, addr);
#ifdef USE_TLS
if (!smtp_tls_policy_cache_query(why, state->tls, iter)) {
msg_warn("TLS policy lookup error for %s/%s: %s",
@@ -844,6 +859,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
char *dest_buf;
char *domain;
unsigned port;
+ char *service;
DNS_RR *addr_list;
DNS_RR *addr;
DNS_RR *next;
@@ -851,6 +867,8 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
int sess_count;
SMTP_SESSION *session;
int lookup_mx;
+ int non_dns_or_literal;
+ int i_am_mx;
unsigned domain_best_pref;
MAI_HOSTADDR_STR hostaddr;
@@ -860,8 +878,28 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
/*
* Parse the destination. If no TCP port is specified, use the port
* that is reserved for the protocol (SMTP or LMTP).
+ *
+ * The 'service' variable corresponds to the remote service specified
+ * with the nexthop, or the default service configured with
+ * smtp_tcp_port or lmtp_tcp_port. The 'port' variable and
+ * SMTP_ITERATOR.port initially correspond to that service. This
+ * determines what loop prevention will be in effect.
+ *
+ * The SMTP_ITERATOR.port will be overwritten after SRV record lookup.
+ * This guarantees that the connection cache key contains the correct
+ * port value when caching and retrieving a connection by its server
+ * address (and port).
+ *
+ * By design, the connection cache key contains NO port information when
+ * caching or retrieving a connection by its nexthop destination.
+ * Instead, the cache key contains the master.cf service name (a
+ * proxy for all the parameter settings including the default service
+ * from smtp_tcp_port or lmtp_tcp_port), together with the nexthop
+ * destination and sender-dependent info. This should be sufficient
+ * to avoid cross talk between mail streams that should be separated.
*/
- dest_buf = smtp_parse_destination(dest, def_service, &domain, &port);
+ dest_buf = smtp_parse_destination(dest, def_service, &domain,
+ &service, &port);
if (var_helpful_warnings && var_smtp_tls_wrappermode == 0
&& ntohs(port) == 465) {
msg_info("SMTPS wrappermode (TCP port 465) requires setting "
@@ -874,32 +912,48 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
SMTP_ITER_INIT(iter, dest, NO_HOST, NO_ADDR, port, state);
/*
- * Resolve an SMTP or LMTP server. In the case of SMTP, skip mail
- * exchanger lookups when a quoted host is specified or when DNS
- * lookups are disabled.
+ * Resolve an SMTP or LMTP server. Skip MX or SRV lookups when a
+ * quoted domain is specified or when DNS lookups are disabled.
*/
if (msg_verbose)
- msg_info("connecting to %s port %d", domain, ntohs(port));
+ msg_info("connecting to %s service %s", domain, service);
+ non_dns_or_literal = (smtp_dns_support == SMTP_DNS_DISABLED
+ || *dest == '[');
if (smtp_mode) {
if (ntohs(port) == IPPORT_SMTP)
state->misc_flags |= SMTP_MISC_FLAG_LOOP_DETECT;
else
state->misc_flags &= ~SMTP_MISC_FLAG_LOOP_DETECT;
- lookup_mx = (smtp_dns_support != SMTP_DNS_DISABLED && *dest != '[');
+ lookup_mx = !non_dns_or_literal;
} else
lookup_mx = 0;
- if (!lookup_mx) {
+
+ /*
+ * Look up SRV and address records and fall back to non-SRV lookups
+ * if permitted by configuration settings, or look up MX and address
+ * records, or look up address records only.
+ */
+ i_am_mx = 0;
+ addr_list = 0;
+ if (!non_dns_or_literal && smtp_use_srv_lookup
+ && string_list_match(smtp_use_srv_lookup, service)) {
+ if (lookup_mx)
+ state->misc_flags |= SMTP_MISC_FLAG_FALLBACK_SRV_TO_MX;
+ else
+ state->misc_flags &= ~SMTP_MISC_FLAG_FALLBACK_SRV_TO_MX;
+ addr_list = smtp_service_addr(domain, service, &iter->mx,
+ state->misc_flags, why, &i_am_mx);
+ } else if (!lookup_mx) {
+ /* Non-DNS, literal, or non-SMTP service */
addr_list = smtp_host_addr(domain, state->misc_flags, why);
/* XXX We could be an MX host for this destination... */
} else {
- int i_am_mx = 0;
-
addr_list = smtp_domain_addr(domain, &iter->mx, state->misc_flags,
why, &i_am_mx);
- /* If we're MX host, don't connect to non-MX backups. */
- if (i_am_mx)
- state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
}
+ /* If we're MX host, don't connect to non-MX backups. */
+ if (i_am_mx)
+ state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
/*
* Don't try fall-back hosts if mail loops to myself. That would just
@@ -992,9 +1046,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
/* XXX Assume there is no code at the end of this loop. */
continue;
}
- vstring_strcpy(iter->addr, hostaddr.buf);
- vstring_strcpy(iter->host, SMTP_HNAME(addr));
- iter->rr = addr;
+ SMTP_ITER_UPDATE_HOST(iter, SMTP_HNAME(addr), hostaddr.buf, addr);
#ifdef USE_TLS
if (!smtp_tls_policy_cache_query(why, state->tls, iter)) {
msg_warn("TLS policy lookup for %s/%s: %s",
diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c
index cd54f8fcb..22f4709c1 100644
--- a/postfix/src/smtp/smtp_params.c
+++ b/postfix/src/smtp/smtp_params.c
@@ -66,6 +66,7 @@
VAR_SMTP_DNS_RE_FILTER, DEF_SMTP_DNS_RE_FILTER, &var_smtp_dns_re_filter, 0, 0,
VAR_TLSPROXY_SERVICE, DEF_TLSPROXY_SERVICE, &var_tlsproxy_service, 1, 0,
VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0,
+ VAR_USE_SRV_LOOKUP, DEF_USE_SRV_LOOKUP, &var_use_srv_lookup, 0, 0,
0,
};
static const CONFIG_TIME_TABLE smtp_time_table[] = {
@@ -132,6 +133,8 @@
VAR_SMTP_DUMMY_MAIL_AUTH, DEF_SMTP_DUMMY_MAIL_AUTH, &var_smtp_dummy_mail_auth,
VAR_SMTP_BALANCE_INET_PROTO, DEF_SMTP_BALANCE_INET_PROTO, &var_smtp_balance_inet_proto,
VAR_SMTP_BIND_ADDR_ENFORCE, DEF_SMTP_BIND_ADDR_ENFORCE, &var_smtp_bind_addr_enforce,
+ VAR_IGN_SRV_LOOKUP_ERR, DEF_IGN_SRV_LOOKUP_ERR, &var_ign_srv_lookup_err,
+ VAR_ALLOW_SRV_FALLBACK, DEF_ALLOW_SRV_FALLBACK, &var_allow_srv_fallback,
0,
};
static const CONFIG_NBOOL_TABLE smtp_nbool_table[] = {
diff --git a/postfix/src/smtp/smtp_reuse.c b/postfix/src/smtp/smtp_reuse.c
index f93ba296a..288483f76 100644
--- a/postfix/src/smtp/smtp_reuse.c
+++ b/postfix/src/smtp/smtp_reuse.c
@@ -172,6 +172,11 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
SMTP_ITERATOR *iter = state->iterator;
SMTP_SESSION *session;
+ if (msg_verbose) {
+ msg_info("%s: dest_prop='%s'", myname, STR(state->dest_prop));
+ msg_info("%s: endp_prop='%s'", myname, STR(state->endp_prop));
+ }
+
/*
* Re-activate the SMTP_SESSION object.
*/
@@ -211,6 +216,7 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
{
+ const char *myname = "smtp_reuse_nexthop";
SMTP_SESSION *session;
int fd;
@@ -219,6 +225,8 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
*/
smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA,
state->iterator, name_key_flags);
+ if (msg_verbose)
+ msg_info("%s: dest_label='%s'", myname, STR(state->dest_label));
if ((fd = scache_find_dest(smtp_scache, STR(state->dest_label),
state->dest_prop, state->endp_prop)) < 0)
return (0);
@@ -235,6 +243,7 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
{
+ const char *myname = "smtp_reuse_addr";
SMTP_SESSION *session;
int fd;
@@ -253,6 +262,8 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
*/
smtp_key_prefix(state->endp_label, SMTP_REUSE_KEY_DELIM_NA,
state->iterator, endp_key_flags);
+ if (msg_verbose)
+ msg_info("%s: endp_label='%s'", myname, STR(state->endp_label));
if ((fd = scache_find_endp(smtp_scache, STR(state->endp_label),
state->endp_prop)) < 0)
return (0);
diff --git a/postfix/src/smtp/smtp_session.c b/postfix/src/smtp/smtp_session.c
index 9f1397843..90a0ff1e1 100644
--- a/postfix/src/smtp/smtp_session.c
+++ b/postfix/src/smtp/smtp_session.c
@@ -129,6 +129,7 @@
#define SESS_ATTR_DEST "destination"
#define SESS_ATTR_HOST "host_name"
#define SESS_ATTR_ADDR "host_addr"
+#define SESS_ATTR_PORT "host_port"
#define SESS_ATTR_DEST_FEATURES "destination_features"
#define SESS_ATTR_TLS_LEVEL "tls_level"
@@ -259,6 +260,7 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
SEND_ATTR_STR(SESS_ATTR_DEST, STR(iter->dest)),
SEND_ATTR_STR(SESS_ATTR_HOST, STR(iter->host)),
SEND_ATTR_STR(SESS_ATTR_ADDR, STR(iter->addr)),
+ SEND_ATTR_UINT(SESS_ATTR_PORT, iter->port),
SEND_ATTR_INT(SESS_ATTR_DEST_FEATURES,
session->features & SMTP_FEATURE_DESTINATION_MASK),
ATTR_TYPE_END) != 0
@@ -398,9 +400,10 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest),
RECV_ATTR_STR(SESS_ATTR_HOST, iter->host),
RECV_ATTR_STR(SESS_ATTR_ADDR, iter->addr),
+ RECV_ATTR_UINT(SESS_ATTR_PORT, &iter->port),
RECV_ATTR_INT(SESS_ATTR_DEST_FEATURES,
&dest_features),
- ATTR_TYPE_END) != 4
+ ATTR_TYPE_END) != 5
|| vstream_fclose(mp) != 0) {
msg_warn("smtp_session_passivate: bad cached dest properties");
SMTP_SESSION_ACTIVATE_ERR_RETURN();
diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
index b8d2c52e6..143d44171 100644
--- a/postfix/src/smtpd/smtpd.c
+++ b/postfix/src/smtpd/smtpd.c
@@ -145,6 +145,11 @@
/* .IP "\fBsmtpd_dns_reply_filter (empty)\fR"
/* Optional filter for Postfix SMTP server DNS lookup results.
/* .PP
+/* Available in Postfix 3.5 and later:
+/* .IP "\fBinfo_log_address_format (external)\fR"
+/* The email address form that will be used in non-debug logging
+/* (info, warning, etc.).
+/* .PP
/* Available in Postfix version 3.6 and later:
/* .IP "\fBsmtpd_relay_before_recipient_restrictions (see 'postconf -d' output)\fR"
/* Evaluate smtpd_relay_restrictions before smtpd_recipient_restrictions.
@@ -518,11 +523,6 @@
/* A workaround for implementations that hang Postfix while shutting
/* down a TLS session, until Postfix times out.
/* .PP
-/* Available in Postfix 3.5 and later:
-/* .IP "\fBinfo_log_address_format (external)\fR"
-/* The email address form that will be used in non-debug logging
-/* (info, warning, etc.).
-/* .PP
/* Available in Postfix version 3.8 and later:
/* .IP "\fBtls_ffdhe_auto_groups (see 'postconf -d' output)\fR"
/* The prioritized list of finite-field Diffie-Hellman ephemeral
diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c
index 29e8671a4..b6a2aced6 100644
--- a/postfix/src/smtpd/smtpd_check.c
+++ b/postfix/src/smtpd/smtpd_check.c
@@ -3065,8 +3065,8 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
|| type == T_AAAA
#endif
) {
- server_list = dns_rr_create(domain, domain, T_MX, C_IN, 0, 0,
- domain, strlen(domain) + 1);
+ server_list = dns_rr_create_nopref(domain, domain, T_MX, C_IN, 0,
+ domain, strlen(domain) + 1);
} else {
dns_status = dns_lookup(domain, type, 0, &server_list,
(VSTRING *) 0, (VSTRING *) 0);
@@ -3074,8 +3074,8 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
return (SMTPD_CHECK_DUNNO);
if (dns_status == DNS_NOTFOUND /* Not: h_errno == NO_DATA */ ) {
if (type == T_MX) {
- server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
- domain, strlen(domain) + 1);
+ server_list = dns_rr_create_nopref(domain, domain, type, C_IN,
+ 0, domain, strlen(domain) + 1);
dns_status = DNS_OK;
} else if (type == T_NS /* && h_errno == NO_DATA */ ) {
while ((domain = strchr(domain, '.')) != 0 && domain[1]) {
diff --git a/postfix/src/util/attr.h b/postfix/src/util/attr.h
index 067405f58..7cd0cf285 100644
--- a/postfix/src/util/attr.h
+++ b/postfix/src/util/attr.h
@@ -62,6 +62,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, const
* for documentation.
*/
#define SEND_ATTR_INT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_VAL(ATTR, int, (val))
+#define SEND_ATTR_UINT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_VAL(ATTR, unsigned, (val))
#define SEND_ATTR_STR(name, val) ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val))
#define SEND_ATTR_HASH(val) ATTR_TYPE_HASH, CHECK_CPTR(ATTR, HTABLE, (val))
#define SEND_ATTR_NV(val) ATTR_TYPE_NV, CHECK_CPTR(ATTR, NVTABLE, (val))
@@ -70,6 +71,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, const
#define SEND_ATTR_FUNC(func, val) ATTR_TYPE_FUNC, CHECK_VAL(ATTR, ATTR_PRINT_CUSTOM_FN, (func)), CHECK_CPTR(ATTR, void, (val))
#define RECV_ATTR_INT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, int, (val))
+#define RECV_ATTR_UINT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, unsigned, (val))
#define RECV_ATTR_STR(name, val) ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, VSTRING, (val))
#define RECV_ATTR_STREQ(name, val) ATTR_TYPE_STREQ, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val))
#define RECV_ATTR_HASH(val) ATTR_TYPE_HASH, CHECK_PTR(ATTR, HTABLE, (val))
@@ -81,9 +83,11 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, const
CHECK_VAL_HELPER_DCL(ATTR, ssize_t);
CHECK_VAL_HELPER_DCL(ATTR, long);
CHECK_VAL_HELPER_DCL(ATTR, int);
+CHECK_VAL_HELPER_DCL(ATTR, unsigned);
CHECK_PTR_HELPER_DCL(ATTR, void);
CHECK_PTR_HELPER_DCL(ATTR, long);
CHECK_PTR_HELPER_DCL(ATTR, int);
+CHECK_PTR_HELPER_DCL(ATTR, unsigned);
CHECK_PTR_HELPER_DCL(ATTR, VSTRING);
CHECK_PTR_HELPER_DCL(ATTR, NVTABLE);
CHECK_PTR_HELPER_DCL(ATTR, HTABLE);
diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h
index 37e460f9c..924718531 100644
--- a/postfix/src/util/sys_defs.h
+++ b/postfix/src/util/sys_defs.h
@@ -748,6 +748,17 @@ extern int initgroups(const char *, int);
#define PIPES_CANT_FIONREAD
#endif
+ /*
+ * GLIBC, mainly, but not exclusively Linux
+ */
+#ifdef __GLIBC_PREREQ
+#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) __GLIBC_PREREQ(maj, min)
+#else
+#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) \
+ (defined(__GLIBC__) && \
+ ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)))
+#endif
+
/*
* LINUX.
*/
@@ -782,13 +793,6 @@ extern int initgroups(const char *, int);
#define NATIVE_NEWALIAS_PATH "/usr/bin/newaliases"
#define NATIVE_COMMAND_DIR "/usr/sbin"
#define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
-#ifdef __GLIBC_PREREQ
-#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) __GLIBC_PREREQ(maj, min)
-#else
-#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) \
- (defined(__GLIBC__) && \
- ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)))
-#endif
#if HAVE_GLIBC_API_VERSION_SUPPORT(2, 1)
#define SOCKADDR_SIZE socklen_t
#define SOCKOPT_SIZE socklen_t
diff --git a/postfix/src/util/unix_send_fd.c b/postfix/src/util/unix_send_fd.c
index 1998a7c20..15cc4df60 100644
--- a/postfix/src/util/unix_send_fd.c
+++ b/postfix/src/util/unix_send_fd.c
@@ -29,6 +29,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
/*--*/
/* System library. */
@@ -75,6 +80,7 @@ int unix_send_fd(int fd, int sendfd)
struct cmsghdr *cmptr;
memset((void *) &msg, 0, sizeof(msg)); /* Fix 200512 */
+ memset((void *) &control_un, 0, sizeof(control_un)); /* Fix 202302 */
msg.msg_control = control_un.control;
if (unix_pass_fd_fix & UNIX_PASS_FD_FIX_CMSG_LEN) {
msg.msg_controllen = CMSG_LEN(sizeof(sendfd)); /* Fix 200506 */