diff --git a/postfix/HISTORY b/postfix/HISTORY index a92edce61..133488489 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -28394,3 +28394,48 @@ Apologies for any names omitted. util/stream_recv_fd.c, util/stream_test.c, util/unix_dgram_connect.c, util/unix_dgram_listen.c, util/vbuf.c. + +20241015 + + Documentation: updated the TLSRPT_README text and example + for section "Delivering TLSRPT summaries via email". File: + proto/TLSRPT_README.html. + +20241021 + + Bugfix (defect introduced: postfix 3.0): the default master.cf + syslog_name setting for the relay service did not preserve + multi-instance information. File: conf/master.cf. + +20241022 + + Documentation: updated the TLSRPT_README examples for + MTA-STS. File: proto/TLSRPT_README.html. + + Documentation: add explicit guidance to use "postconf -x" + when checking an inline pcre or regexp table for unescaped + '$' characters. Files: mantools/postlink, proto/pcre_table, + proto/regexp_table. + + Documentation: be explicit about when Postfix expands $name + in inline pcre, regexp, and cidr lookup tables. Files: + proto/cidr_table, proto/pcre_table, proto/regexp_table. + + Safety: replace ASCII control characters that match isspace() + with space characters. This prevents line breaks etc. in + smtp_tls_policy attribute values that use the long form "{ + name = value }". This form was introduced with Postfix 3.10 + TLSRPT support. Files: smtp/smtp_tls_policy.c, util/extpar.c, + util/Makefile.in, util/normalize_ws.c, util/stringops.h. + +20241023 + + Logging: Postfix SMTP server 'reject' logging now shows the + sasl_method, sasl_username, and sasl_sender if available. + Viktor Dukhovni. Files: smtpd/smtpd_check.c. + +20241024 + + Documentation: in a pgsql: client configuration, the setting + "dbname" is required, but ignored when the setting "hosts" + contains an URI with a database name. File: proto/pgsql_table. diff --git a/postfix/README_FILES/TLSRPT_README b/postfix/README_FILES/TLSRPT_README index 9b797d2a7..c84309897 100644 --- a/postfix/README_FILES/TLSRPT_README +++ b/postfix/README_FILES/TLSRPT_README @@ -175,37 +175,39 @@ Notes: DDeelliivveerriinngg TTLLSSRRPPTT ssuummmmaarriieess vviiaa eemmaaiill -RFC 8460 suggests not to enforce strict TLS security when sending daily -success/failure summaries via email, to avoid delivery delays caused by a -failure to enforce TLS security. Postfix currently does not have a mechanism to -disable TLS security enforcement when submitting an email message; this section -provides a workaround. +RFC 8460 Section 3 specifies that an MTA must not enforce TLS security when +sending failure reports via email. However, Postfix currently has no way to +request that TLS enforcement will be disabled when submitting an email message. -By design, TLSRPT is not a real-time notification system; it takes on average -12 hours before a failure is reported in a daily success/failure summary. If a -TLS-related delay of a day or more is undesirable, one could set up a transport -map to make TLS security optional for specific TLSRPT email notification email -addresses. +Options: + + * Do nothing. When TLS security enforcement is required, a persistent + enforcement failure will delay the delivery of a TLSRPT summary until the + problem is addressed, or until the message expires in the mail queue. Keep + in mind that TLSRPT is not a real-time monitoring service; it takes on + average 12 hours before a failure is reported through TLSRPT. + + * Exclude the sender of TLSRPT summaries from TLS enforcement. Implement the + configuration below on outbound MTA instances (replace noreply-smtp-tls- + reporting@example.com with your actual report generator's sender address): /etc/postfix/main.cf: - transport_maps = hash:/etc/postfix/transport - - /etc/postfix/transport: - smtp-tls-report@example.com allow-plaintext: - ... + # Limitation: this setting is overruled with transport_maps. + sender_dependent_default_transport_maps = inline:{ + { noreply-smtp-tls-reporting@example.com = allow-plaintext } } /etc/postfix/master.cf: # service name type private unpriv chroot wakeup maxproc command allow-plaintext unix - - n - - smtp - -o smtp_tls_security_level=may - -o smtp_tls_policy_maps=static:may + -o { smtp_tls_security_level = may } + -o { smtp_tls_policy_maps = static:may } MMTTAA--SSTTSS SSuuppppoorrtt vviiaa ssmmttpp__ttllss__ppoolliiccyy__mmaappss -Postfix supports MTA-STS though an smtp_tls_policy_maps policy plugin. Postfix -3.10 and later expect a policy response with the usual security level and -matching requirements, plus any applicable name=value attributes described +Postfix supports MTA-STS though an smtp_tls_policy_maps policy plugin, which +replies with a TLS security level and optional matching requirements. Postfix +3.10 and later optionally also accept the name=value attributes described below. Specify { name = value } when a value may contain whitespace. Note 1: Postfix 3.10 and later will accept these attributes in an MTA-STS @@ -215,8 +217,17 @@ below. Specify { name = value } when a value may contain whitespace. Note 2: It is an error to specify these attributes for a non-STS policy. -The examples in the table apply to the MTA-STS policy example given in https:// -datatracker.ietf.org/doc/html/rfc8460#section-4.5. +The examples in the table apply to the MTA-STS policy example given in RFC 8461 +Section 3.2: + + version: STSv1 + mode: enforce + mx: mail.example.com + mx: *.example.net + mx: backupmx.example.com + max_age: 604800 + +A policy response may contain line breaks. * policy_type=type @@ -238,7 +249,7 @@ datatracker.ietf.org/doc/html/rfc8460#section-4.5. Example: - { policy_string = version: STSv1 } { policy_string = mode: testing } + { policy_string = version: STSv1 } { policy_string = mode: enforce } ... This form ignores whitespace after the opening "{", around the "=", and @@ -251,7 +262,7 @@ datatracker.ietf.org/doc/html/rfc8460#section-4.5. Example: - mx_host_pattern=mx1.example.com mx_host_pattern=mx2.example.com ... + mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ... * policy_failure=type diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 506cb7c3e..c84db73bb 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -6,6 +6,19 @@ Wish list: Disable -DSNAPSHOT and -DNONPROD in makedefs. + Add a mail_version chek to each pluggable database client. + + Add an option for a built-in JSON generator. This would + simplify TLSRPT adoption by eliminating a build-time and + run-time dependency on the libtlsrpt client library. Prior + art: this approach was previously used to implement Postfix + Milter support. + + Make TLSRPT support pluggable (postfix-tlsrpt.so, like + postfix-ldap.so, postfix-mysql.so and so on). This avods a + hard install-time dependency on sys4 libtlsrpt. The sys4 + code would still be a build-time dependency. + Add smtp_tlsrpt_allow_list feature (default: static:all) to limit the domains for which Postfix generates TLSRPT daily summaries. @@ -13,6 +26,8 @@ Wish list: Add unit tests for smtp_tlsrpt.c, tlstrpd_wrapper.c, ... + Add unit test for extpar.c + Add tests for Message-ID extraction in the cleanup daemon. When debug logging is enabled, dict_db_open() logs a newline diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index e5e14e449..17b7551af 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -69,7 +69,7 @@ proxymap unix - - n - - proxymap proxywrite unix - - n - 1 proxymap smtp unix - - n - - smtp relay unix - - n - - smtp - -o syslog_name=postfix/$service_name + -o syslog_name=${multi_instance_name?{$multi_instance_name}:{postfix}}/$service_name # -o smtp_helo_timeout=5 -o smtp_connect_timeout=5 showq unix n - n - - showq error unix - - n - - error diff --git a/postfix/html/TLSRPT_README.html b/postfix/html/TLSRPT_README.html index 6edf95d50..a1fc10f24 100644 --- a/postfix/html/TLSRPT_README.html +++ b/postfix/html/TLSRPT_README.html @@ -266,44 +266,51 @@ have the details for why TLS authentication failed.
RFC 8460 suggests not to enforce strict TLS security when sending -daily success/failure summaries via email, to avoid delivery delays -caused by a failure to enforce TLS security. Postfix currently does -not have a mechanism to disable TLS security enforcement when -submitting an email message; this section provides a workaround.
+RFC +8460 Section 3 specifies that an MTA must not enforce TLS +security when sending failure reports via email. However, Postfix +currently has no way to request that TLS enforcement will be disabled +when submitting an email message.
-By design, TLSRPT is not a real-time notification system; it -takes on average 12 hours before a failure is reported in a daily -success/failure summary. If a TLS-related delay of a day or more -is undesirable, one could set up a transport map to make TLS security -optional for specific TLSRPT email notification email addresses. -
+Options: + +
Do nothing. When TLS security enforcement is required, a +persistent enforcement failure will delay the delivery of a TLSRPT +summary until the problem is addressed, or until the message expires +in the mail queue. Keep in mind that TLSRPT is not a real-time +monitoring service; it takes on average 12 hours before a failure +is reported through TLSRPT.
+ +Exclude the sender of TLSRPT summaries from TLS enforcement. +Implement the configuration below on outbound MTA instances (replace +noreply-smtp-tls-reporting@example.com with your actual report +generator's sender address):
-+ +/etc/postfix/main.cf: - transport_maps = hash:/etc/postfix/transport -  -/etc/postfix/transport: - smtp-tls-report@example.com allow-plaintext: - ... + # Limitation: this setting is overruled with transport_maps. + sender_dependent_default_transport_maps = inline:{ + { noreply-smtp-tls-reporting@example.com = allow-plaintext } }   /etc/postfix/master.cf: # service name type private unpriv chroot wakeup maxproc command allow-plaintext unix - - n - - smtp - -o smtp_tls_security_level=may - -o smtp_tls_policy_maps=static:may + -o { smtp_tls_security_level = may } + -o { smtp_tls_policy_maps = static:may }-
Postfix supports MTA-STS though an smtp_tls_policy_maps -policy plugin. Postfix 3.10 and later expect a policy response with -the usual security level and matching requirements, plus any -applicable name=value attributes described below. Specify { -name = value } when a value may contain whitespace.
+Postfix supports MTA-STS though an smtp_tls_policy_maps policy +plugin, which replies with a TLS security level and optional matching +requirements. Postfix 3.10 and later optionally also accept the +name=value attributes described below. Specify { name = value +} when a value may contain whitespace.
@@ -319,8 +326,22 @@ policy.
The examples in the table apply to the MTA-STS policy example -given in https://datatracker.ietf.org/doc/html/rfc8460#section-4.5. -
+given in +RFC 8461 Section 3.2:
+ +++ ++version: STSv1 +mode: enforce +mx: mail.example.com +mx: *.example.net +mx: backupmx.example.com +max_age: 604800 ++
A policy response may contain line breaks.
@@ -363,7 +384,7 @@ in the MTA-STS policy.-{ policy_string = version: STSv1 } { policy_string = mode: testing } ... +{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
diff --git a/postfix/html/cidr_table.5.html b/postfix/html/cidr_table.5.html index 94982018c..b85167e1e 100644 --- a/postfix/html/cidr_table.5.html +++ b/postfix/html/cidr_table.5.html @@ -109,8 +109,9 @@ CIDR_TABLE(5) CIDR_TABLE(5) master.cf: .. -o { parameter = .. cidr:{ { rule-1 }, { rule-2 } .. } .. } .. - Postfix ignores whitespace after '{' and before '}', and writes each - rule as one text line to an in-memory file: + Postfix recursively expands any $parametername instances in the above + parameter value, ignores whitespace after '{' and before '}', and + writes each rule as one text line to an in-memory file: in-memory file: rule-1 @@ -119,7 +120,7 @@ CIDR_TABLE(5) CIDR_TABLE(5) Postfix parses the result as if it is a file in /etc/postfix. - Note: if a rule contains $, specify $$ to keep Postfix from trying to + Note: if a rule contains $, specify $$ to keep Postfix from trying to do $name expansion as it evaluates a parameter value. EXAMPLE SMTPD ACCESS MAP diff --git a/postfix/html/pcre_table.5.html b/postfix/html/pcre_table.5.html index d2da2b2cd..304b9b2c9 100644 --- a/postfix/html/pcre_table.5.html +++ b/postfix/html/pcre_table.5.html @@ -181,8 +181,9 @@ PCRE_TABLE(5) PCRE_TABLE(5) master.cf: .. -o { parameter = .. pcre:{ { rule-1 }, { rule-2 } .. } .. } .. - Postfix ignores whitespace after '{' and before '}', and writes each - rule as one text line to an in-memory file: + Postfix recursively expands any $parametername instances in the above + parameter value, ignores whitespace after '{' and before '}', and + writes each rule as one text line to an in-memory file: in-memory file: rule-1 @@ -191,12 +192,29 @@ PCRE_TABLE(5) PCRE_TABLE(5) Postfix parses the result as if it is a file in /etc/postfix. - Note: if an inlined rule contains $, specify $$ to keep Postfix from - trying to do $name expansion as it evaluates a parameter value. +INLINE SPECIFICATION CAVEATS + o When using $parametername inside an inlined pattern, use + \Q$parametername\E to disable metacharacters such as '.' in the + $parametername expansion. Otherwise, the pattern may have unex- + pected matches. - Note: when using $name inside an inlined pattern, use \Q$name\E to dis- - able metacharacters such as '.' in the $name expansion. Otherwise, the - pattern may have unexpected matches. + o When an inlined rule must contain $, specify $$ to keep Postfix + from trying to do $name expansion as it evaluates a parameter + value. To check an inline configuration, use the "postconf -x" + option as shown below: + + o When a main.cf "parametername = value" setting contains + an inline pcre: table, use the command "postconf -x + parametername". Verify that there are no "undefined + parameter" warnings, and that the output has the syntax + that one would use in a non-inlined Postfix pcre: file. + + o When a master.cf "-o { parametername = value }" override + contains an inline pcre: table, use the command "postconf + -Px '*/*/parametername' ". Verify that there are no + "undefined parameter" warnings, and that the output has + the syntax that one would use in a non-inlined Postfix + pcre: file. EXAMPLE SMTPD ACCESS MAP # Protect your outgoing majordomo exploders diff --git a/postfix/html/pgsql_table.5.html b/postfix/html/pgsql_table.5.html index 14db55e30..e300bcb8d 100644 --- a/postfix/html/pgsql_table.5.html +++ b/postfix/html/pgsql_table.5.html @@ -48,7 +48,7 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) inet:host:port for TCP connections, where the unix: and inet: prefixes are accepted and ignored for backwards compatibility. Examples: - hosts = postgresql://username@example.com/tablename?sslmode=require + hosts = postgresql://username@example.com/databasename?sslmode=require hosts = inet:host1.some.domain inet:host2.some.domain:port hosts = host1.some.domain host2.some.domain:port hosts = unix:/file/name @@ -71,21 +71,25 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) user = someone password = some_password - dbname The database name on the servers. Example: + dbname (required) + The database name on the servers. Example: dbname = customer_database + This setting is required, but ignored when a postgresql:// URI + specifies a database name. + encoding - The encoding used by the database client. The default setting + The encoding used by the database client. The default setting is: encoding = UTF8 - Historically, the database client was hard coded to use LATIN1 + Historically, the database client was hard coded to use LATIN1 in an attempt to disable multibyte character support. This feature is available in Postfix 3.8 and later. idle_interval (default: 60) - The number of seconds after which an idle database connection + The number of seconds after which an idle database connection will be closed. This feature is available in Postfix 3.9 and later. @@ -96,8 +100,8 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) This feature is available in Postfix 3.9 and later. - query The SQL query template used to search the database, where %s is - a substitute for the address Postfix is trying to resolve, e.g. + query The SQL query template used to search the database, where %s is + a substitute for the address Postfix is trying to resolve, e.g. query = SELECT replacement FROM aliases WHERE mailbox = '%s' This parameter supports the following '%' expansions: @@ -105,48 +109,48 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) %% This is replaced by a literal '%' character. (Postfix 2.2 and later) - %s This is replaced by the input key. SQL quoting is used - to make sure that the input key does not add unexpected + %s This is replaced by the input key. SQL quoting is used + to make sure that the input key does not add unexpected metacharacters. %u When the input key is an address of the form user@domain, - %u is replaced by the SQL quoted local part of the - address. Otherwise, %u is replaced by the entire search - string. If the localpart is empty, the query is sup- + %u is replaced by the SQL quoted local part of the + address. Otherwise, %u is replaced by the entire search + string. If the localpart is empty, the query is sup- pressed and returns no results. %d When the input key is an address of the form user@domain, - %d is replaced by the SQL quoted domain part of the - address. Otherwise, the query is suppressed and returns + %d is replaced by the SQL quoted domain part of the + address. Otherwise, the query is suppressed and returns no results. %[SUD] The upper-case equivalents of the above expansions behave - in the query parameter identically to their lower-case - counter-parts. With the result_format parameter (see - below), they expand the input key rather than the result + in the query parameter identically to their lower-case + counter-parts. With the result_format parameter (see + below), they expand the input key rather than the result value. - The above %S, %U and %D expansions are available with + The above %S, %U and %D expansions are available with Postfix 2.2 and later - %[1-9] The patterns %1, %2, ... %9 are replaced by the corre- - sponding most significant component of the input key's - domain. If the input key is user@mail.example.com, then + %[1-9] The patterns %1, %2, ... %9 are replaced by the corre- + sponding most significant component of the input key's + domain. If the input key is user@mail.example.com, then %1 is com, %2 is example and %3 is mail. If the input key - is unqualified or does not have enough domain components - to satisfy all the specified patterns, the query is sup- + is unqualified or does not have enough domain components + to satisfy all the specified patterns, the query is sup- pressed and returns no results. - The above %1, ... %9 expansions are available with Post- + The above %1, ... %9 expansions are available with Post- fix 2.2 and later - The domain parameter described below limits the input keys to - addresses in matching domains. When the domain parameter is + The domain parameter described below limits the input keys to + addresses in matching domains. When the domain parameter is non-empty, SQL queries for unqualified addresses or addresses in non-matching domains are suppressed and return no results. - The precedence of this parameter has changed with Postfix 2.2, - in prior releases the precedence was, from highest to lowest, + The precedence of this parameter has changed with Postfix 2.2, + in prior releases the precedence was, from highest to lowest, select_function, query, select_field, ... With Postfix 2.2 the query parameter has highest precedence, see @@ -156,42 +160,42 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) result_format (default: %s) Format template applied to result attributes. Most commonly used - to append (or prepend) text to the result. This parameter sup- + to append (or prepend) text to the result. This parameter sup- ports the following '%' expansions: %% This is replaced by a literal '%' character. - %s This is replaced by the value of the result attribute. + %s This is replaced by the value of the result attribute. When result is empty it is skipped. %u When the result attribute value is an address of the form - user@domain, %u is replaced by the local part of the - address. When the result has an empty localpart it is + user@domain, %u is replaced by the local part of the + address. When the result has an empty localpart it is skipped. - %d When a result attribute value is an address of the form - user@domain, %d is replaced by the domain part of the - attribute value. When the result is unqualified it is + %d When a result attribute value is an address of the form + user@domain, %d is replaced by the domain part of the + attribute value. When the result is unqualified it is skipped. %[SUD1-9] - The upper-case and decimal digit expansions interpolate - the parts of the input key rather than the result. Their - behavior is identical to that described with query, and - in fact because the input key is known in advance, - queries whose key does not contain all the information - specified in the result template are suppressed and + The upper-case and decimal digit expansions interpolate + the parts of the input key rather than the result. Their + behavior is identical to that described with query, and + in fact because the input key is known in advance, + queries whose key does not contain all the information + specified in the result template are suppressed and return no results. For example, using "result_format = smtp:[%s]" allows one to use a mailHost attribute as the basis of a transport(5) table. After - applying the result format, multiple values are concatenated as + applying the result format, multiple values are concatenated as comma separated strings. The expansion_limit and parameter - explained below allows one to restrict the number of values in + explained below allows one to restrict the number of values in the result, which is especially useful for maps that must return at most one value. - The default value %s specifies that each result value should be + The default value %s specifies that each result value should be used as is. This parameter is available with Postfix 2.2 and later. @@ -199,15 +203,15 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) NOTE: DO NOT put quotes around the result format! domain (default: no domain list) - This is a list of domain names, paths to files, or "type:table" + This is a list of domain names, paths to files, or "type:table" databases. When specified, only fully qualified search keys with - a *non-empty* localpart and a matching domain are eligible for + a *non-empty* localpart and a matching domain are eligible for lookup: 'user' lookups, bare domain lookups and "@domain" - lookups are not performed. This can significantly reduce the + lookups are not performed. This can significantly reduce the query load on the PostgreSQL server. domain = postfix.org, hash:/etc/postfix/searchdomains - It is best not to use SQL to store the domains eligible for SQL + It is best not to use SQL to store the domains eligible for SQL lookups. This parameter is available with Postfix 2.2 and later. @@ -216,28 +220,28 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) the input keys are always unqualified. expansion_limit (default: 0) - A limit on the total number of result elements returned (as a + A limit on the total number of result elements returned (as a comma separated list) by a lookup against the map. A setting of - zero disables the limit. Lookups fail with a temporary error if - the limit is exceeded. Setting the limit to 1 ensures that + zero disables the limit. Lookups fail with a temporary error if + the limit is exceeded. Setting the limit to 1 ensures that lookups do not return multiple values. OBSOLETE MAIN.CF PARAMETERS - For compatibility with other Postfix lookup tables, PostgreSQL parame- - ters can also be defined in main.cf. In order to do that, specify as + For compatibility with other Postfix lookup tables, PostgreSQL parame- + ters can also be defined in main.cf. In order to do that, specify as PostgreSQL source a name that doesn't begin with a slash or a dot. The - PostgreSQL parameters will then be accessible as the name you've given + PostgreSQL parameters will then be accessible as the name you've given the source in its definition, an underscore, and the name of the param- - eter. For example, if the map is specified as "pgsql:pgsqlname", the + eter. For example, if the map is specified as "pgsql:pgsqlname", the parameter "hosts" would be defined in main.cf as "pgsqlname_hosts". - Note: with this form, the passwords for the PostgreSQL sources are + Note: with this form, the passwords for the PostgreSQL sources are written in main.cf, which is normally world-readable. Support for this form will be removed in a future Postfix version. OBSOLETE QUERY INTERFACES This section describes query interfaces that are deprecated as of Post- - fix 2.2. Please migrate to the new query interface as the old inter- + fix 2.2. Please migrate to the new query interface as the old inter- faces are slated to be phased out. select_function @@ -247,14 +251,14 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) This is equivalent to: query = SELECT my_lookup_user_alias('%s') - This parameter overrides the legacy table-related fields - (described below). With Postfix versions prior to 2.2, it also - overrides the query parameter. Starting with Postfix 2.2, the - query parameter has highest precedence, and the select_function + This parameter overrides the legacy table-related fields + (described below). With Postfix versions prior to 2.2, it also + overrides the query parameter. Starting with Postfix 2.2, the + query parameter has highest precedence, and the select_function parameter is deprecated. - The following parameters (with lower precedence than the select_func- - tion interface described above) can be used to build the SQL select + The following parameters (with lower precedence than the select_func- + tion interface described above) can be used to build the SQL select statement as follows: SELECT [select_field] @@ -262,13 +266,13 @@ PGSQL_TABLE(5) PGSQL_TABLE(5) WHERE [where_field] = '%s' [additional_conditions] - The specifier %s is replaced with each lookup by the lookup key and is - escaped so if it contains single quotes or other odd characters, it + The specifier %s is replaced with each lookup by the lookup key and is + escaped so if it contains single quotes or other odd characters, it will not cause a parse error, or worse, a security problem. Starting with Postfix 2.2, this interface is obsoleted by the more gen- eral query interface described above. If higher precedence the query or - select_function parameters described above are defined, the parameters + select_function parameters described above are defined, the parameters described here are ignored. select_field diff --git a/postfix/html/regexp_table.5.html b/postfix/html/regexp_table.5.html index ec617280a..4f65ee66f 100644 --- a/postfix/html/regexp_table.5.html +++ b/postfix/html/regexp_table.5.html @@ -138,8 +138,9 @@ REGEXP_TABLE(5) REGEXP_TABLE(5) master.cf: .. -o { parameter = .. regexp:{ { rule-1 }, { rule-2 } .. } .. } .. - Postfix ignores whitespace after '{' and before '}', and writes each - rule as one text line to an in-memory file: + Postfix recursively expands any $parametername instances in the above + parameter value, ignores whitespace after '{' and before '}', and + writes each rule as one text line to an in-memory file: in-memory file: rule-1 @@ -148,12 +149,30 @@ REGEXP_TABLE(5) REGEXP_TABLE(5) Postfix parses the result as if it is a file in /etc/postfix. - Note: if an inlined rule contains $, specify $$ to keep Postfix from - trying to do $name expansion as it evaluates a parameter value. +INLINE SPECIFICATION CAVEATS + o Avoid using $parametername inside an inlined regexp: pattern. + The pattern would have unexpected matches when there are + metacharacters such as '.' in the $parametername expansion. To + prevent unexpected matches, use a pcre: table, and specify + \Q$parametername\E. - Note: when using $name inside an inlined pattern, this will not disable - metacharacters such as '.' in the $name expansion. To prevent unex- - pected matches, use a pcre: table, and specify \Q$name\E. + o When an inlined rule must contain $, specify $$ to keep Postfix + from trying to do $name expansion as it evaluates a parameter + value. To check an inline configuration, use the "postconf -x" + option as shown below: + + o When a main.cf "parametername = value" setting contains + an inline regexp: table, use the command "postconf -x + parametername". Verify that there are no "undefined + parameter" warnings, and that the output has the syntax + that one would use in a non-inlined Postfix regexp: file. + + o When a master.cf "-o { parametername = value }" override + contains an inline regexp: table, use the command "post- + conf -Px '*/*/parametername' ". Verify that there are no + "undefined parameter" warnings, and that the output has + the syntax that one would use in a non-inlined Postfix + regexp: file. EXAMPLE SMTPD ACCESS MAP # Disallow sender-specified routing. This is a must if you relay mail diff --git a/postfix/man/man5/cidr_table.5 b/postfix/man/man5/cidr_table.5 index 6722123d7..66a7a59c1 100644 --- a/postfix/man/man5/cidr_table.5 +++ b/postfix/man/man5/cidr_table.5 @@ -127,9 +127,10 @@ master.cf: \fB.. \-o { \fIparameter\fR \fB= .. cidr:{ { \fIrule\-1\fB }, { \fIrule\-2\fB } .. } .. } ..\fR .fi -Postfix ignores whitespace after '{' and before '}', and -writes each \fIrule\fR as one text line to an in\-memory -file: +Postfix recursively expands any \fI$parametername\fR instances +in the above parameter value, ignores whitespace after '{' +and before '}', and writes each \fIrule\fR as one text line to +an in\-memory file: .nf in\-memory file: diff --git a/postfix/man/man5/pcre_table.5 b/postfix/man/man5/pcre_table.5 index b5adb94f3..a112e7f68 100644 --- a/postfix/man/man5/pcre_table.5 +++ b/postfix/man/man5/pcre_table.5 @@ -193,9 +193,10 @@ master.cf: \fB.. \-o { \fIparameter\fR \fB= .. pcre:{ { \fIrule\-1\fB }, { \fIrule\-2\fB } .. } .. } ..\fR .fi -Postfix ignores whitespace after '{' and before '}', and -writes each \fIrule\fR as one text line to an in\-memory -file: +Postfix recursively expands any \fI$parametername\fR instances +in the above parameter value, ignores whitespace after '{' +and before '}', and writes each \fIrule\fR as one text line to +an in\-memory file: .nf in\-memory file: @@ -205,15 +206,35 @@ in\-memory file: .fi Postfix parses the result as if it is a file in /etc/postfix. - -Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +.SH "INLINE SPECIFICATION CAVEATS" +.na +.nf +.ad +.fi +.IP \(bu +When using \fI$parametername\fR inside an inlined pattern, +use \eQ\fI$parametername\fR\eE to disable metacharacters such as +\&'.' in the \fI$parametername\fR expansion. Otherwise, the pattern +may have unexpected matches. +.IP \(bu +When an inlined rule must contain \fB$\fR, specify \fB$$\fR to keep Postfix from trying to do \fI$name\fR expansion as -it evaluates a parameter value. - -Note: when using \fI$name\fR inside an inlined pattern, use -\eQ\fI$name\fR\eE to disable metacharacters such as '.' in -the \fI$name\fR expansion. Otherwise, the pattern may have -unexpected matches. +it evaluates a parameter value. To check an inline configuration, +use the "\fBpostconf \-x\fR" option as shown below: +.RS +.IP \(bu +When a main.cf "\fIparametername = \fI value\fR" setting contains +an inline pcre: table, use the command "\fBpostconf \-x +\fIparametername\fR". Verify that there are no "undefined +parameter" warnings, and that the output has the syntax that +one would use in a non\-inlined Postfix pcre: file. +.IP \(bu +When a master.cf "\fB\-o { \fIparametername = value\fB }\fR" +override contains an inline pcre: table, use the command +"\fBpostconf \-Px '*/*/\fIparametername\fB' \fR". Verify that there +are no "undefined parameter" warnings, and that the output has +the syntax that one would use in a non\-inlined Postfix pcre: file. +.RE .SH "EXAMPLE SMTPD ACCESS MAP" .na .nf diff --git a/postfix/man/man5/pgsql_table.5 b/postfix/man/man5/pgsql_table.5 index 4b4ecb12e..6d9df55fd 100644 --- a/postfix/man/man5/pgsql_table.5 +++ b/postfix/man/man5/pgsql_table.5 @@ -62,7 +62,7 @@ connections, where the \fBunix:\fR and \fBinet:\fR prefixes are accepted and ignored for backwards compatibility. Examples: .nf - hosts = postgresql://username@example.com/tablename?sslmode=require + hosts = postgresql://username@example.com/\fIdatabasename\fR?sslmode=require hosts = inet:host1.some.domain inet:host2.some.domain:port hosts = host1.some.domain host2.some.domain:port hosts = unix:/file/name @@ -85,11 +85,14 @@ Example: user = someone password = some_password .fi -.IP "\fBdbname\fR" +.IP "\fBdbname\fR (required)" The database name on the servers. Example: .nf dbname = customer_database .fi +.sp +This setting is required, but ignored when a postgresql:// +URI specifies a database name. .IP "\fBencoding\fR" The encoding used by the database client. The default setting is: diff --git a/postfix/man/man5/regexp_table.5 b/postfix/man/man5/regexp_table.5 index e9698210b..91c6f23a3 100644 --- a/postfix/man/man5/regexp_table.5 +++ b/postfix/man/man5/regexp_table.5 @@ -150,9 +150,10 @@ master.cf: \fB.. \-o { \fIparameter\fR \fB= .. regexp:{ { \fIrule\-1\fB }, { \fIrule\-2\fB } .. } .. } ..\fR .fi -Postfix ignores whitespace after '{' and before '}', and -writes each \fIrule\fR as one text line to an in\-memory -file: +Postfix recursively expands any \fi$parametername\fR instances +in the above parameter value, ignores whitespace after '{' +and before '}', and writes each \fIrule\fR as one text line to +an in\-memory file: .nf in\-memory file: @@ -162,15 +163,37 @@ in\-memory file: .fi Postfix parses the result as if it is a file in /etc/postfix. - -Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +.SH "INLINE SPECIFICATION CAVEATS" +.na +.nf +.ad +.fi +.IP \(bu +Avoid using \fI$parametername\fR inside an inlined regexp: +pattern. The pattern would have unexpected matches when there +are metacharacters such as '.' in the \fI$parametername\fR +expansion. To prevent unexpected matches, use a pcre: table, +and specify \eQ\fI$parametername\fR\eE. +.IP \(bu +When an inlined rule must contain \fB$\fR, specify \fB$$\fR to keep Postfix from trying to do \fI$name\fR expansion as -it evaluates a parameter value. - -Note: when using \fI$name\fR inside an inlined pattern, -this will not disable metacharacters such as '.' in the -\fI$name\fR expansion. To prevent unexpected matches, use -a pcre: table, and specify \eQ\fI$name\fR\eE. +it evaluates a parameter value. To check an inline configuration, +use the "\fBpostconf \-x\fR" option as shown below: +.RS +.IP \(bu +When a main.cf "\fIparametername = \fI value\fR" setting +contains an inline regexp: table, use the command "\fBpostconf +\-x \fIparametername\fR". Verify that there are no "undefined +parameter" warnings, and that the output has the syntax that +one would use in a non\-inlined Postfix regexp: file. +.IP \(bu +When a master.cf "\fB\-o { \fIparametername = value\fB }\fR" +override contains an inline regexp: table, use the command +"\fBpostconf \-Px '*/*/\fIparametername\fB' \fR". Verify that there +are no "undefined parameter" warnings, and that the output has +the syntax that one would use in a non\-inlined Postfix regexp: +file. +.RE .SH "EXAMPLE SMTPD ACCESS MAP" .na .nf diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 7ee74fba2..f5ec3f4f8 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -1267,7 +1267,7 @@ while (<>) { s;\b(pipe[-]*\n*[-mx_host_pattern=mx1.example.com mx_host_pattern=mx2.example.com ... +mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
RFC 8460 suggests not to enforce strict TLS security when sending -daily success/failure summaries via email, to avoid delivery delays -caused by a failure to enforce TLS security. Postfix currently does -not have a mechanism to disable TLS security enforcement when -submitting an email message; this section provides a workaround.
+RFC +8460 Section 3 specifies that an MTA must not enforce TLS +security when sending failure reports via email. However, Postfix +currently has no way to request that TLS enforcement will be disabled +when submitting an email message.
-By design, TLSRPT is not a real-time notification system; it -takes on average 12 hours before a failure is reported in a daily -success/failure summary. If a TLS-related delay of a day or more -is undesirable, one could set up a transport map to make TLS security -optional for specific TLSRPT email notification email addresses. -
+Options: + +
Do nothing. When TLS security enforcement is required, a +persistent enforcement failure will delay the delivery of a TLSRPT +summary until the problem is addressed, or until the message expires +in the mail queue. Keep in mind that TLSRPT is not a real-time +monitoring service; it takes on average 12 hours before a failure +is reported through TLSRPT.
+ +Exclude the sender of TLSRPT summaries from TLS enforcement. +Implement the configuration below on outbound MTA instances (replace +noreply-smtp-tls-reporting@example.com with your actual report +generator's sender address):
-+ +/etc/postfix/main.cf: - transport_maps = hash:/etc/postfix/transport -  -/etc/postfix/transport: - smtp-tls-report@example.com allow-plaintext: - ... + # Limitation: this setting is overruled with transport_maps. + sender_dependent_default_transport_maps = inline:{ + { noreply-smtp-tls-reporting@example.com = allow-plaintext } }   /etc/postfix/master.cf: # service name type private unpriv chroot wakeup maxproc command allow-plaintext unix - - n - - smtp - -o smtp_tls_security_level=may - -o smtp_tls_policy_maps=static:may + -o { smtp_tls_security_level = may } + -o { smtp_tls_policy_maps = static:may }-
Postfix supports MTA-STS though an smtp_tls_policy_maps -policy plugin. Postfix 3.10 and later expect a policy response with -the usual security level and matching requirements, plus any -applicable name=value attributes described below. Specify { -name = value } when a value may contain whitespace.
+Postfix supports MTA-STS though an smtp_tls_policy_maps policy +plugin, which replies with a TLS security level and optional matching +requirements. Postfix 3.10 and later optionally also accept the +name=value attributes described below. Specify { name = value +} when a value may contain whitespace.
@@ -319,8 +326,22 @@ policy.
The examples in the table apply to the MTA-STS policy example -given in https://datatracker.ietf.org/doc/html/rfc8460#section-4.5. -
+given in +RFC 8461 Section 3.2:
+ +++ ++version: STSv1 +mode: enforce +mx: mail.example.com +mx: *.example.net +mx: backupmx.example.com +max_age: 604800 ++
A policy response may contain line breaks.
@@ -363,7 +384,7 @@ in the MTA-STS policy.-{ policy_string = version: STSv1 } { policy_string = mode: testing } ... +{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
diff --git a/postfix/proto/cidr_table b/postfix/proto/cidr_table index 9eed9ce63..5dad4dc45 100644 --- a/postfix/proto/cidr_table +++ b/postfix/proto/cidr_table @@ -113,9 +113,10 @@ # \fB.. -o { \fIparameter\fR \fB= .. cidr:{ { \fIrule-1\fB }, { \fIrule-2\fB } .. } .. } ..\fR # .fi # -# Postfix ignores whitespace after '{' and before '}', and -# writes each \fIrule\fR as one text line to an in-memory -# file: +# Postfix recursively expands any \fI$parametername\fR instances +# in the above parameter value, ignores whitespace after '{' +# and before '}', and writes each \fIrule\fR as one text line to +# an in-memory file: # # .nf # in-memory file: diff --git a/postfix/proto/pcre_table b/postfix/proto/pcre_table index e4c6607f5..8b59cc2dc 100644 --- a/postfix/proto/pcre_table +++ b/postfix/proto/pcre_table @@ -177,9 +177,10 @@ # \fB.. -o { \fIparameter\fR \fB= .. pcre:{ { \fIrule-1\fB }, { \fIrule-2\fB } .. } .. } ..\fR # .fi # -# Postfix ignores whitespace after '{' and before '}', and -# writes each \fIrule\fR as one text line to an in-memory -# file: +# Postfix recursively expands any \fI$parametername\fR instances +# in the above parameter value, ignores whitespace after '{' +# and before '}', and writes each \fIrule\fR as one text line to +# an in-memory file: # # .nf # in-memory file: @@ -189,15 +190,33 @@ # .fi # # Postfix parses the result as if it is a file in /etc/postfix. -# -# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +# INLINE SPECIFICATION CAVEATS +# .ad +# .fi +# .IP \(bu +# When using \fI$parametername\fR inside an inlined pattern, +# use \eQ\fI$parametername\fR\eE to disable metacharacters such as +# '.' in the \fI$parametername\fR expansion. Otherwise, the pattern +# may have unexpected matches. +# .IP \(bu +# When an inlined rule must contain \fB$\fR, specify \fB$$\fR # to keep Postfix from trying to do \fI$name\fR expansion as -# it evaluates a parameter value. -# -# Note: when using \fI$name\fR inside an inlined pattern, use -# \eQ\fI$name\fR\eE to disable metacharacters such as '.' in -# the \fI$name\fR expansion. Otherwise, the pattern may have -# unexpected matches. +# it evaluates a parameter value. To check an inline configuration, +# use the "\fBpostconf -x\fR" option as shown below: +# .RS +# .IP \(bu +# When a main.cf "\fIparametername = \fI value\fR" setting contains +# an inline pcre: table, use the command "\fBpostconf -x +# \fIparametername\fR". Verify that there are no "undefined +# parameter" warnings, and that the output has the syntax that +# one would use in a non-inlined Postfix pcre: file. +# .IP \(bu +# When a master.cf "\fB-o { \fIparametername = value\fB }\fR" +# override contains an inline pcre: table, use the command +# "\fBpostconf -Px '*/*/\fIparametername\fB' \fR". Verify that there +# are no "undefined parameter" warnings, and that the output has +# the syntax that one would use in a non-inlined Postfix pcre: file. +# .RE # EXAMPLE SMTPD ACCESS MAP # # Protect your outgoing majordomo exploders # /^(?!owner-)(.*)-outgoing@(.*)/ 550 Use ${1}@${2} instead diff --git a/postfix/proto/pgsql_table b/postfix/proto/pgsql_table index 31f6661e1..6bc797b5b 100644 --- a/postfix/proto/pgsql_table +++ b/postfix/proto/pgsql_table @@ -52,7 +52,7 @@ # are accepted and ignored for backwards compatibility. # Examples: # .nf -# hosts = postgresql://username@example.com/tablename?sslmode=require +# hosts = postgresql://username@example.com/\fIdatabasename\fR?sslmode=require # hosts = inet:host1.some.domain inet:host2.some.domain:port # hosts = host1.some.domain host2.some.domain:port # hosts = unix:/file/name @@ -75,11 +75,14 @@ # user = someone # password = some_password # .fi -# .IP "\fBdbname\fR" +# .IP "\fBdbname\fR (required)" # The database name on the servers. Example: # .nf # dbname = customer_database # .fi +# .sp +# This setting is required, but ignored when a postgresql:// +# URI specifies a database name. # .IP "\fBencoding\fR" # The encoding used by the database client. The default setting # is: diff --git a/postfix/proto/regexp_table b/postfix/proto/regexp_table index 5e8c15f85..c8e738f2a 100644 --- a/postfix/proto/regexp_table +++ b/postfix/proto/regexp_table @@ -134,9 +134,10 @@ # \fB.. -o { \fIparameter\fR \fB= .. regexp:{ { \fIrule-1\fB }, { \fIrule-2\fB } .. } .. } ..\fR # .fi # -# Postfix ignores whitespace after '{' and before '}', and -# writes each \fIrule\fR as one text line to an in-memory -# file: +# Postfix recursively expands any \fi$parametername\fR instances +# in the above parameter value, ignores whitespace after '{' +# and before '}', and writes each \fIrule\fR as one text line to +# an in-memory file: # # .nf # in-memory file: @@ -146,15 +147,35 @@ # .fi # # Postfix parses the result as if it is a file in /etc/postfix. -# -# Note: if an inlined rule contains \fB$\fR, specify \fB$$\fR +# INLINE SPECIFICATION CAVEATS +# .ad +# .fi +# .IP \(bu +# Avoid using \fI$parametername\fR inside an inlined regexp: +# pattern. The pattern would have unexpected matches when there +# are metacharacters such as '.' in the \fI$parametername\fR +# expansion. To prevent unexpected matches, use a pcre: table, +# and specify \eQ\fI$parametername\fR\eE. +# .IP \(bu +# When an inlined rule must contain \fB$\fR, specify \fB$$\fR # to keep Postfix from trying to do \fI$name\fR expansion as -# it evaluates a parameter value. -# -# Note: when using \fI$name\fR inside an inlined pattern, -# this will not disable metacharacters such as '.' in the -# \fI$name\fR expansion. To prevent unexpected matches, use -# a pcre: table, and specify \eQ\fI$name\fR\eE. +# it evaluates a parameter value. To check an inline configuration, +# use the "\fBpostconf -x\fR" option as shown below: +# .RS +# .IP \(bu +# When a main.cf "\fIparametername = \fI value\fR" setting +# contains an inline regexp: table, use the command "\fBpostconf +# -x \fIparametername\fR". Verify that there are no "undefined +# parameter" warnings, and that the output has the syntax that +# one would use in a non-inlined Postfix regexp: file. +# .IP \(bu +# When a master.cf "\fB-o { \fIparametername = value\fB }\fR" +# override contains an inline regexp: table, use the command +# "\fBpostconf -Px '*/*/\fIparametername\fB' \fR". Verify that there +# are no "undefined parameter" warnings, and that the output has +# the syntax that one would use in a non-inlined Postfix regexp: +# file. +# .RE # EXAMPLE SMTPD ACCESS MAP # # Disallow sender-specified routing. This is a must if you relay mail # # for other domains. diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc index e2d5861e3..d10fe2354 100644 --- a/postfix/proto/stop.spell-cc +++ b/postfix/proto/stop.spell-cc @@ -1847,3 +1847,6 @@ sts tlsrprt bdefhnoqv deduplicated +WS +isspace +ws diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index 45d00e6c2..383098cfd 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -85,3 +85,4 @@ pkgconf testfiles Antonin Verrier +unescaped diff --git a/postfix/proto/stop.spell-proto-html b/postfix/proto/stop.spell-proto-html index 0bb4f3963..504363680 100644 --- a/postfix/proto/stop.spell-proto-html +++ b/postfix/proto/stop.spell-proto-html @@ -387,3 +387,5 @@ Sys Qsmtp Qsts gmail +backupmx +noreply diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 8cbe85dff..02a818a0f 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 "20241010" +#define MAIL_RELEASE_DATE "20241024" #define MAIL_VERSION_NUMBER "3.10" #ifdef SNAPSHOT diff --git a/postfix/src/smtp/smtp_tls_policy.c b/postfix/src/smtp/smtp_tls_policy.c index 501509496..6122c2d78 100644 --- a/postfix/src/smtp/smtp_tls_policy.c +++ b/postfix/src/smtp/smtp_tls_policy.c @@ -285,12 +285,17 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, /* * Errors in attributes may have security consequences, don't ignore * errors that can degrade security. + * + * Caution: normalize whitespace, to neutralize line break etc. characters + * inside the value portion of { name = value }. */ while ((tok = mystrtokq(&policy, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { const char *err; +#define EXTPAR_OPT (EXTPAR_FLAG_STRIP | EXTPAR_FLAG_NORMAL_WS) + if ((tok[0] == CHARS_BRACE[0] - && (err = free_me = extpar(&tok, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) + && (err = free_me = extpar(&tok, CHARS_BRACE, EXTPAR_OPT)) != 0) || (err = split_nameval(tok, &name, &val)) != 0) { msg_warn("%s: malformed attribute/value pair \"%s\": %s", WHERE, tok, err); diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index e7164da78..0c2c64019 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -2389,6 +2389,7 @@ static int mail_open_stream(SMTPD_STATE *state) ", sasl_method=", state->sasl_method), PRINT2_OR_NULL(state->sasl_username, ", sasl_username=", state->sasl_username), + /* This is safe because state->sasl_sender is xtext-encoded. */ PRINT2_OR_NULL(state->sasl_sender, ", sasl_sender=", state->sasl_sender), #else diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 41b91a1d9..ae122e336 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1016,6 +1016,15 @@ void log_whatsup(SMTPD_STATE *state, const char *whatsup, vstring_sprintf_append(buf, " proto=%s", state->protocol); if (state->helo_name) vstring_sprintf_append(buf, " helo=<%s>", state->helo_name); +#ifdef USE_SASL_AUTH + if (state->sasl_method) + vstring_sprintf_append(buf, " sasl_method=%s", state->sasl_method); + if (state->sasl_username) + vstring_sprintf_append(buf, " sasl_username=%s", state->sasl_username); + /* This is safe because state->sasl_sender is xtext-encoded. */ + if (state->sasl_sender) + vstring_sprintf_append(buf, " sasl_sender=%s", state->sasl_sender); +#endif msg_info("%s", STR(buf)); vstring_free(buf); } diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 67bdc3ec7..531b786bf 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -46,7 +46,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \ mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c inet_prefix_top.c \ inet_addr_sizes.c quote_for_json.c mystrerror.c \ - sane_sockaddr_to_hostaddr.c + sane_sockaddr_to_hostaddr.c normalize_ws.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -93,7 +93,8 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \ sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \ mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o \ - quote_for_json.o mystrerror.o sane_sockaddr_to_hostaddr.o + quote_for_json.o mystrerror.o sane_sockaddr_to_hostaddr.o \ + normalize_ws.o # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -147,7 +148,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \ vbuf_print split_qnameval vstream msg_logger byte_mask \ known_tcp_ports dict_stream find_inet binhash hash_fnv argv \ - clean_env inet_prefix_top printable readlline quote_for_json + clean_env inet_prefix_top printable readlline quote_for_json \ + normalize_ws PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \ $(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX) HTABLE_FIX = NORANDOMIZE=1 @@ -611,6 +613,11 @@ quote_for_json: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +normalize_ws: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + tests: all valid_hostname_test mac_expand_test dict_test unescape_test \ hex_quote_test ctable_test inet_addr_list_test base64_code_test \ attr_scan64_test attr_scan0_test host_port_test dict_tests \ @@ -621,7 +628,8 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \ miss_endif_regexp_test split_qnameval_test vstring_test \ vstream_test byte_mask_tests mystrtok_test known_tcp_ports_test \ binhash_test argv_test inet_prefix_top_test printable_test \ - valid_utf8_string_test readlline_test quote_for_json_test + valid_utf8_string_test readlline_test quote_for_json_test \ + normalize_ws_test dict_tests: all dict_test \ dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \ @@ -1098,6 +1106,9 @@ inet_prefix_top_test: inet_prefix_top quote_for_json_test: quote_for_json $(SHLIB_ENV) ${VALGRIND} ./quote_for_json +normalize_ws_test: normalize_ws + $(SHLIB_ENV) ${VALGRIND} ./normalize_ws + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -2495,6 +2506,16 @@ non_blocking.o: iostuff.h non_blocking.o: msg.h non_blocking.o: non_blocking.c non_blocking.o: sys_defs.h +normalize_ws.o: check_arg.h +normalize_ws.o: msg.h +normalize_ws.o: msg_vstream.h +normalize_ws.o: mymalloc.h +normalize_ws.o: normalize_ws.c +normalize_ws.o: stringops.h +normalize_ws.o: sys_defs.h +normalize_ws.o: vbuf.h +normalize_ws.o: vstream.h +normalize_ws.o: vstring.h nvtable.o: htable.h nvtable.o: mymalloc.h nvtable.o: nvtable.c diff --git a/postfix/src/util/extpar.c b/postfix/src/util/extpar.c index 0b106bac8..2ee317f65 100644 --- a/postfix/src/util/extpar.c +++ b/postfix/src/util/extpar.c @@ -31,6 +31,10 @@ /* .IP EXTPAR_FLAG_STRIP /* Skip whitespace after the opening parenthesis, and trim /* whitespace before the closing parenthesis. +/* .IP EXTPAR_FLAG_NORMAL_WS +/* Substitute SPACE for control characters (newline etc.) that +/* match isspace(). This neutralizes line break etc. characters in +/* the value portion of { name = value }. /* .RE /* DIAGNOSTICS /* In case of error the result value is a dynamically-allocated @@ -104,6 +108,8 @@ char *extpar(char **bp, const char *parens, int flags) while (ISSPACE(*cp)) cp++; } + if (flags & EXTPAR_FLAG_NORMAL_WS) + normalize_ws(cp); *bp = cp; return (err); } diff --git a/postfix/src/util/normalize_ws.c b/postfix/src/util/normalize_ws.c new file mode 100644 index 000000000..f41de4e82 --- /dev/null +++ b/postfix/src/util/normalize_ws.c @@ -0,0 +1,144 @@ +/*++ +/* NAME +/* normalize_ws 3 +/* SUMMARY +/* neutralize isspace()-matching control characters +/* SYNOPSIS +/* #include-mx_host_pattern=mx1.example.com mx_host_pattern=mx2.example.com ... +mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...