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.
D\bDe\bel\bli\biv\bve\ber\bri\bin\bng\bg T\bTL\bLS\bSR\bRP\bPT\bT s\bsu\bum\bmm\bma\bar\bri\bie\bes\bs v\bvi\bia\ba e\bem\bma\bai\bil\bl
-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.
-
-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.
+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.
- /etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+Options:
- /etc/postfix/transport:
- smtp-tls-report@example.com allow-plaintext:
- ...
+ * 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:
+ # 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 }
M\bMT\bTA\bA-\b-S\bST\bTS\bS S\bSu\bup\bpp\bpo\bor\brt\bt v\bvi\bia\ba s\bsm\bmt\btp\bp_\b_t\btl\bls\bs_\b_p\bpo\bol\bli\bic\bcy\by_\b_m\bma\bap\bps\bs
-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
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
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
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
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.
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
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
<h2> <a name="delivering"> Delivering TLSRPT summaries via email</a> </h2>
-<p> <a href="https://tools.ietf.org/html/rfc8460">RFC 8460</a> 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. </p>
-
-<p> 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.
-</p>
+<p> <a href="https://datatracker.ietf.org/doc/html/rfc8460#section-3">RFC
+8460 Section 3</a> 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. </p>
+
+<p> Options:
+
+<ul>
+
+<li> <p> 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. </p>
+
+<li> <p> 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): </p>
-<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
- 
-/etc/postfix/transport:
- smtp-tls-report@example.com allow-plaintext:
- ...
+ # Limitation: this setting is overruled with <a href="postconf.5.html#transport_maps">transport_maps</a>.
+ <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> = <a href="DATABASE_README.html#types">inline</a>:{
+ { noreply-smtp-tls-reporting@example.com = allow-plaintext } }
 
/etc/postfix/<a href="master.5.html">master.cf</a>:
# service name type private unpriv chroot wakeup maxproc command
allow-plaintext unix - - n - - smtp
- -o <a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a>=may
- -o <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>=<a href="DATABASE_README.html#types">static</a>:may
+ -o { <a href="postconf.5.html#smtp_tls_security_level">smtp_tls_security_level</a> = may }
+ -o { <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">static</a>:may }
</pre>
-</blockquote>
+
+</ul>
<h2> <a name="mta-sts"> MTA-STS Support via smtp_tls_policy_maps
</a></h2>
-<p> Postfix supports MTA-STS though an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a>
-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 <tt>{
-name = value }</tt> when a value may contain whitespace. </p>
+<p> Postfix supports MTA-STS though an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> 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 <tt>{ name = value
+}</tt> when a value may contain whitespace. </p>
<blockquote>
</blockquote>
<p> The examples in the table apply to the MTA-STS policy example
-given in <a href="https://datatracker.ietf.org/doc/html/rfc8460#section-4.5">https://datatracker.ietf.org/doc/html/rfc8460#section-4.5</a>.
-<p>
+given in <a
+href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
+RFC 8461 Section 3.2</a>: </p>
+
+<blockquote>
+<pre>
+version: STSv1
+mode: enforce
+mx: mail.example.com
+mx: *.example.net
+mx: backupmx.example.com
+max_age: 604800
+</pre>
+</blockquote>
+
+<p> A policy response may contain line breaks. </p>
<ul>
<blockquote>
<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: testing } ...
+{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
</pre>
</blockquote>
<blockquote>
<pre>
-mx_host_pattern=mx1.example.com mx_host_pattern=mx2.example.com ...
+mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
</pre>
</blockquote>
</li>
<a href="master.5.html">master.cf</a>:
<b>.. -o {</b> <i>parameter</i> <b>= .. <a href="cidr_table.5.html">cidr</a>:{ {</b> <i>rule-1</i> <b>}, {</b> <i>rule-2</i> <b>} .. } .. } ..</b>
- Postfix ignores whitespace after '{' and before '}', and writes each
- <i>rule</i> as one text line to an in-memory file:
+ Postfix recursively expands any <i>$parametername</i> instances in the above
+ parameter value, ignores whitespace after '{' and before '}', and
+ writes each <i>rule</i> as one text line to an in-memory file:
in-memory file:
rule-1
Postfix parses the result as if it is a file in /etc/postfix.
- Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
+ Note: if a rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from trying to
do <i>$name</i> expansion as it evaluates a parameter value.
<b><a name="example_smtpd_access_map">EXAMPLE SMTPD ACCESS MAP</a></b>
<a href="master.5.html">master.cf</a>:
<b>.. -o {</b> <i>parameter</i> <b>= .. <a href="pcre_table.5.html">pcre</a>:{ {</b> <i>rule-1</i> <b>}, {</b> <i>rule-2</i> <b>} .. } .. } ..</b>
- Postfix ignores whitespace after '{' and before '}', and writes each
- <i>rule</i> as one text line to an in-memory file:
+ Postfix recursively expands any <i>$parametername</i> instances in the above
+ parameter value, ignores whitespace after '{' and before '}', and
+ writes each <i>rule</i> as one text line to an in-memory file:
in-memory file:
rule-1
Postfix parses the result as if it is a file in /etc/postfix.
- Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
- trying to do <i>$name</i> expansion as it evaluates a parameter value.
-
- Note: when using <i>$name</i> inside an inlined pattern, use \Q<i>$name</i>\E to dis-
- able metacharacters such as '.' in the <i>$name</i> expansion. Otherwise, the
- pattern may have unexpected matches.
+<b><a name="inline_specification_caveats">INLINE SPECIFICATION CAVEATS</a></b>
+ <b>o</b> When using <i>$parametername</i> inside an inlined pattern, use
+ \Q<i>$parametername</i>\E to disable metacharacters such as '.' in the
+ <i>$parametername</i> expansion. Otherwise, the pattern may have unex-
+ pected matches.
+
+ <b>o</b> When an inlined rule must contain <b>$</b>, specify <b>$$</b> to keep Postfix
+ from trying to do <i>$name</i> expansion as it evaluates a parameter
+ value. To check an inline configuration, use the "<b>postconf -x</b>"
+ option as shown below:
+
+ <b>o</b> When a <a href="postconf.5.html">main.cf</a> "<i>parametername = value</i>" setting contains
+ an inline <a href="pcre_table.5.html">pcre</a>: table, use the command "<b>postconf -x</b>
+ <i>parametername</i>". Verify that there are no "undefined
+ parameter" warnings, and that the output has the syntax
+ that one would use in a non-inlined Postfix <a href="pcre_table.5.html">pcre</a>: file.
+
+ <b>o</b> When a <a href="master.5.html">master.cf</a> "<b>-o {</b> <i>parametername = value</i> <b>}</b>" override
+ contains an inline <a href="pcre_table.5.html">pcre</a>: table, use the command "<b>postconf</b>
+ <b>-Px '*/*/</b><i>parametername</i><b>'</b> ". Verify that there are no
+ "undefined parameter" warnings, and that the output has
+ the syntax that one would use in a non-inlined Postfix
+ <a href="pcre_table.5.html">pcre</a>: file.
<b><a name="example_smtpd_access_map">EXAMPLE SMTPD ACCESS MAP</a></b>
# Protect your outgoing majordomo exploders
<b>inet:</b><i>host:port</i> for TCP connections, where the <b>unix:</b> and <b>inet:</b>
prefixes are accepted and ignored for backwards compatibility.
Examples:
- hosts = postgresql://username@example.com/tablename?sslmode=require
+ hosts = postgresql://username@example.com/<i>databasename</i>?sslmode=require
hosts = inet:host1.some.domain inet:host2.some.domain:port
hosts = host1.some.domain host2.some.domain:port
hosts = unix:/file/name
user = someone
password = some_password
- <b>dbname</b> The database name on the servers. Example:
+ <b>dbname</b> (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.
+
<b>encoding</b>
- 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.
<b>idle_interval (default: 60)</b>
- 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.
This feature is available in Postfix 3.9 and later.
- <b>query</b> The SQL query template used to search the database, where <b>%s</b> is
- a substitute for the address Postfix is trying to resolve, e.g.
+ <b>query</b> The SQL query template used to search the database, where <b>%s</b> 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:
<b>%%</b> This is replaced by a literal '%' character. (Postfix 2.2
and later)
- <b>%s</b> This is replaced by the input key. SQL quoting is used
- to make sure that the input key does not add unexpected
+ <b>%s</b> This is replaced by the input key. SQL quoting is used
+ to make sure that the input key does not add unexpected
metacharacters.
<b>%u</b> When the input key is an address of the form user@domain,
- <b>%u</b> is replaced by the SQL quoted local part of the
- address. Otherwise, <b>%u</b> is replaced by the entire search
- string. If the localpart is empty, the query is sup-
+ <b>%u</b> is replaced by the SQL quoted local part of the
+ address. Otherwise, <b>%u</b> is replaced by the entire search
+ string. If the localpart is empty, the query is sup-
pressed and returns no results.
<b>%d</b> When the input key is an address of the form user@domain,
- <b>%d</b> is replaced by the SQL quoted domain part of the
- address. Otherwise, the query is suppressed and returns
+ <b>%d</b> is replaced by the SQL quoted domain part of the
+ address. Otherwise, the query is suppressed and returns
no results.
<b>%[SUD]</b> The upper-case equivalents of the above expansions behave
- in the <b>query</b> parameter identically to their lower-case
- counter-parts. With the <b>result_format</b> parameter (see
- below), they expand the input key rather than the result
+ in the <b>query</b> parameter identically to their lower-case
+ counter-parts. With the <b>result_format</b> 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
- <b>%[1-9]</b> 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 <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> 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 <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. 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 <b>domain</b> parameter described below limits the input keys to
- addresses in matching domains. When the <b>domain</b> parameter is
+ The <b>domain</b> parameter described below limits the input keys to
+ addresses in matching domains. When the <b>domain</b> 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,
<b>select_function</b>, <b>query</b>, <b>select_field</b>, ...
With Postfix 2.2 the <b>query</b> parameter has highest precedence, see
<b>result_format (default: %s</b>)
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:
<b>%%</b> This is replaced by a literal '%' character.
- <b>%s</b> This is replaced by the value of the result attribute.
+ <b>%s</b> This is replaced by the value of the result attribute.
When result is empty it is skipped.
<b>%u</b> When the result attribute value is an address of the form
- user@domain, <b>%u</b> is replaced by the local part of the
- address. When the result has an empty localpart it is
+ user@domain, <b>%u</b> is replaced by the local part of the
+ address. When the result has an empty localpart it is
skipped.
- <b>%d</b> When a result attribute value is an address of the form
- user@domain, <b>%d</b> is replaced by the domain part of the
- attribute value. When the result is unqualified it is
+ <b>%d</b> When a result attribute value is an address of the form
+ user@domain, <b>%d</b> is replaced by the domain part of the
+ attribute value. When the result is unqualified it is
skipped.
<b>%[SUD1-9]</b>
- 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 <b>query</b>, 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 <b>query</b>, 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 = <a href="smtp.8.html">smtp</a>:[%s]" allows one to use
a mailHost attribute as the basis of a <a href="transport.5.html">transport(5)</a> 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 <b>%s</b> specifies that each result value should be
+ The default value <b>%s</b> specifies that each result value should be
used as is.
This parameter is available with Postfix 2.2 and later.
NOTE: DO NOT put quotes around the result format!
<b>domain (default: no domain list)</b>
- This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
+ This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
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, <a href="DATABASE_README.html#types">hash</a>:/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.
the input keys are always unqualified.
<b>expansion_limit (default: 0)</b>
- 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.
<b>OBSOLETE MAIN.CF PARAMETERS</b>
- For compatibility with other Postfix lookup tables, PostgreSQL parame-
- ters can also be defined in <a href="postconf.5.html">main.cf</a>. In order to do that, specify as
+ For compatibility with other Postfix lookup tables, PostgreSQL parame-
+ ters can also be defined in <a href="postconf.5.html">main.cf</a>. 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 "<a href="pgsql_table.5.html">pgsql</a>:<i>pgsqlname</i>", the
+ eter. For example, if the map is specified as "<a href="pgsql_table.5.html">pgsql</a>:<i>pgsqlname</i>", the
parameter "hosts" would be defined in <a href="postconf.5.html">main.cf</a> as "<i>pgsqlname</i>_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 <a href="postconf.5.html">main.cf</a>, which is normally world-readable. Support for this
form will be removed in a future Postfix version.
<b><a name="obsolete_query_interfaces">OBSOLETE QUERY INTERFACES</a></b>
This section describes query interfaces that are deprecated as of Post-
- fix 2.2. Please migrate to the new <b>query</b> interface as the old inter-
+ fix 2.2. Please migrate to the new <b>query</b> interface as the old inter-
faces are slated to be phased out.
<b>select_function</b>
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 <b>query</b> parameter. Starting with Postfix 2.2, the
- <b>query</b> parameter has highest precedence, and the <b>select_function</b>
+ This parameter overrides the legacy table-related fields
+ (described below). With Postfix versions prior to 2.2, it also
+ overrides the <b>query</b> parameter. Starting with Postfix 2.2, the
+ <b>query</b> parameter has highest precedence, and the <b>select_function</b>
parameter is deprecated.
- The following parameters (with lower precedence than the <b>select_func-</b>
- <b>tion</b> interface described above) can be used to build the SQL select
+ The following parameters (with lower precedence than the <b>select_func-</b>
+ <b>tion</b> interface described above) can be used to build the SQL select
statement as follows:
SELECT [<b>select_field</b>]
WHERE [<b>where_field</b>] = '%s'
[<b>additional_conditions</b>]
- 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 <b>query</b> interface described above. If higher precedence the <b>query</b> or
- <b>select_function</b> parameters described above are defined, the parameters
+ <b>select_function</b> parameters described above are defined, the parameters
described here are ignored.
<b>select_field</b>
<a href="master.5.html">master.cf</a>:
<b>.. -o {</b> <i>parameter</i> <b>= .. <a href="regexp_table.5.html">regexp</a>:{ {</b> <i>rule-1</i> <b>}, {</b> <i>rule-2</i> <b>} .. } .. } ..</b>
- Postfix ignores whitespace after '{' and before '}', and writes each
- <i>rule</i> 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 <i>rule</i> as one text line to an in-memory file:
in-memory file:
rule-1
Postfix parses the result as if it is a file in /etc/postfix.
- Note: if an inlined rule contains <b>$</b>, specify <b>$$</b> to keep Postfix from
- trying to do <i>$name</i> expansion as it evaluates a parameter value.
-
- Note: when using <i>$name</i> inside an inlined pattern, this will not disable
- metacharacters such as '.' in the <i>$name</i> expansion. To prevent unex-
- pected matches, use a <a href="pcre_table.5.html">pcre</a>: table, and specify \Q<i>$name</i>\E.
+<b><a name="inline_specification_caveats">INLINE SPECIFICATION CAVEATS</a></b>
+ <b>o</b> Avoid using <i>$parametername</i> inside an inlined <a href="regexp_table.5.html">regexp</a>: pattern.
+ The pattern would have unexpected matches when there are
+ metacharacters such as '.' in the <i>$parametername</i> expansion. To
+ prevent unexpected matches, use a <a href="pcre_table.5.html">pcre</a>: table, and specify
+ \Q<i>$parametername</i>\E.
+
+ <b>o</b> When an inlined rule must contain <b>$</b>, specify <b>$$</b> to keep Postfix
+ from trying to do <i>$name</i> expansion as it evaluates a parameter
+ value. To check an inline configuration, use the "<b>postconf -x</b>"
+ option as shown below:
+
+ <b>o</b> When a <a href="postconf.5.html">main.cf</a> "<i>parametername = value</i>" setting contains
+ an inline <a href="regexp_table.5.html">regexp</a>: table, use the command "<b>postconf -x</b>
+ <i>parametername</i>". Verify that there are no "undefined
+ parameter" warnings, and that the output has the syntax
+ that one would use in a non-inlined Postfix <a href="regexp_table.5.html">regexp</a>: file.
+
+ <b>o</b> When a <a href="master.5.html">master.cf</a> "<b>-o {</b> <i>parametername = value</i> <b>}</b>" override
+ contains an inline <a href="regexp_table.5.html">regexp</a>: table, use the command "<b>post-</b>
+ <b>conf -Px '*/*/</b><i>parametername</i><b>'</b> ". Verify that there are no
+ "undefined parameter" warnings, and that the output has
+ the syntax that one would use in a non-inlined Postfix
+ <a href="regexp_table.5.html">regexp</a>: file.
<b><a name="example_smtpd_access_map">EXAMPLE SMTPD ACCESS MAP</a></b>
# Disallow sender-specified routing. This is a must if you relay mail
\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:
\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:
.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
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
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:
\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:
.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
s;\b(pipe[-</bB>]*\n*[ <bB>]*map):;<a href="DATABASE_README.html#types">$1<\/a>:;g;
s/\b(proxy):/<a href="proxymap.8.html">$1<\/a>:/g;
s/\b(randmap):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
- s/\b(regexp):/<a href="regexp_table.5.html">$1<\/a>:/g;
+ s;\b(reg[-</bB>]*\n*[ <bB>]*exp):;<a href="regexp_table.5.html">$1<\/a>:;g;
s/\b(sdbm):/<a href="DATABASE_README.html#types">$1<\/a>:/g;
s/\b(socketmap):/<a href="socketmap_table.html">$1<\/a>:/g;
s/\b(sqlite):/<a href="sqlite_table.5.html">$1<\/a>:/g;
<h2> <a name="delivering"> Delivering TLSRPT summaries via email</a> </h2>
-<p> 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. </p>
-
-<p> 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.
-</p>
+<p> <a href="https://datatracker.ietf.org/doc/html/rfc8460#section-3">RFC
+8460 Section 3</a> 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. </p>
+
+<p> Options:
+
+<ul>
+
+<li> <p> 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. </p>
+
+<li> <p> 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): </p>
-<blockquote>
<pre>
/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 }
</pre>
-</blockquote>
+
+</ul>
<h2> <a name="mta-sts"> MTA-STS Support via smtp_tls_policy_maps
</a></h2>
-<p> 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 <tt>{
-name = value }</tt> when a value may contain whitespace. </p>
+<p> 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 <tt>{ name = value
+}</tt> when a value may contain whitespace. </p>
<blockquote>
</blockquote>
<p> The examples in the table apply to the MTA-STS policy example
-given in https://datatracker.ietf.org/doc/html/rfc8460#section-4.5.
-<p>
+given in <a
+href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
+RFC 8461 Section 3.2</a>: </p>
+
+<blockquote>
+<pre>
+version: STSv1
+mode: enforce
+mx: mail.example.com
+mx: *.example.net
+mx: backupmx.example.com
+max_age: 604800
+</pre>
+</blockquote>
+
+<p> A policy response may contain line breaks. </p>
<ul>
<blockquote>
<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: testing } ...
+{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
</pre>
</blockquote>
<blockquote>
<pre>
-mx_host_pattern=mx1.example.com mx_host_pattern=mx2.example.com ...
+mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
</pre>
</blockquote>
</li>
# \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:
# \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:
# .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
# 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
# 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:
# \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:
# .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.
tlsrprt
bdefhnoqv
deduplicated
+WS
+isspace
+ws
testfiles
Antonin
Verrier
+unescaped
Qsmtp
Qsts
gmail
+backupmx
+noreply
* 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
/*
* 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);
", 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
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);
}
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 \
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.
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
$(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 \
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 \
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 \
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
/* .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
while (ISSPACE(*cp))
cp++;
}
+ if (flags & EXTPAR_FLAG_NORMAL_WS)
+ normalize_ws(cp);
*bp = cp;
return (err);
}
--- /dev/null
+/*++
+/* NAME
+/* normalize_ws 3
+/* SUMMARY
+/* neutralize isspace()-matching control characters
+/* SYNOPSIS
+/* #include <stringops.h>
+/*
+/* char *normalize_ws(char *str)
+/* DESCRIPTION
+/* normalize_ws() takes a null-terminated string and substitutes
+/* ASCII SPACE for any ASCII control characters that match
+/* isspace(). This neutralizes line break etc. characters in the
+/* value portion of { name = value }. The function substitutes
+/* bytes in place, and returns its str argument.
+/*
+/* This function requires that input is encoded in ASCII or UTF-8.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* normalize_ws - replace isspace() members with space characters */
+
+char *normalize_ws(char *str)
+{
+ char *cp;
+
+ for (cp = str; *(cp += strcspn(cp, "\t\n\v\f\r")); *cp = ' ')
+ /* void */ ;
+ return (str);
+}
+
+#ifdef TEST
+
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+ const char *input;
+ const char *want;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+#define BUFLEN 2
+
+/* if this test fails, isspace() may have changed */
+
+static int normalizes_all_isspace_members(const TEST_CASE *unused)
+{
+ int ch;
+ char input[BUFLEN];
+ char want[BUFLEN];
+ char *got;
+
+ for (ch = 0; ISASCII(ch); ch++) {
+ input[0] = ch;
+ input[1] = 0;
+ want[0] = ISSPACE(ch) ? ' ' : ch;
+ want[1] = 0;
+ got = normalize_ws(input);
+ if (got != input) {
+ msg_warn("got %p, want %p", got, input);
+ return (FAIL);
+ }
+ if (memcmp(got, want, BUFLEN) != 0) {
+ msg_warn("got '{0x%02x 0x%02x}', want '{0x%02x 0x%02x}",
+ got[0], got[1], want[0], want[1]);
+ return (FAIL);
+ }
+ }
+ return (PASS);
+}
+
+static int test_normalize_ws(const TEST_CASE *tp)
+{
+ char *input = mystrdup(tp->input);
+ char *got;
+
+ got = normalize_ws(input);
+ if (strcmp(got, tp->want) != 0) {
+ msg_warn("got '%s', want '%s'", got, tp->want);
+ return (FAIL);
+ }
+ myfree(input);
+ return (PASS);
+}
+
+static const TEST_CASE test_cases[] = {
+ {"normalizes all isspace members", normalizes_all_isspace_members,},
+ {"normalizes_first", test_normalize_ws, "\tfoo", " foo",},
+ {"normalizes_middle", test_normalize_ws, "fo\to", "fo o",},
+ {"normalizes_last", test_normalize_ws, "foo\t", "foo ",},
+ {"normalizes_multiple", test_normalize_ws, "\tfo\to\t", " fo o ",},
+ {0,}
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
+
+#endif
extern char *quote_for_json(VSTRING *, const char *, ssize_t);
extern char *quote_for_json_append(VSTRING *, const char *, ssize_t);
extern const char *mystrerror(int);
+extern char *normalize_ws(char *);
#define EXTPAR_FLAG_NONE (0)
#define EXTPAR_FLAG_STRIP (1<<0) /* "{ text }" -> "text" */
#define EXTPAR_FLAG_EXTRACT (1<<1) /* hint from caller's caller */
+#define EXTPAR_FLAG_NORMAL_WS (1<<2) /* normalize 'isspace' members */
#define CASEF_FLAG_UTF8 (1<<0)
#define CASEF_FLAG_APPEND (1<<1)