Debug logging: cleanup/cleanup_api.c. tls/tlsrpt_wrapper.c.
proto/TLSRPT_README.html.
- Postfix 3.10 code freeze.
+20250204
+
+ Feature: with "smtpd_hide_client_session = yes", the Postfix
+ SMTP server generates a Received: header without client
+ session info (EHLO, hostname, IP address, TLS session
+ details, SASL login details, SMTP protocol details). Files:
+ conf/master.cf, mantools/postlink, proto/postconf.proto,
+ global/mail_params.h, smtpd/smtpd.c.
+
+20250205
+
+ Documentation: updated TLSRPT_README, added postfix-tlspol
+ policy plugin, deprecated the policy_ttl attribute. File:
+ proto/TLSRPT_README.html.
+
+ Postfix 3.10 code freeze.
TLSRPT report generator produces daily summary reports.
The TLSRPT client library, and the infrastructure to collect, fetch, and report
-TLSRPT information are maintained by sys4 at https://github.com/sys4/libtlsrpt
-and https://github.com/sys4/tlsrpt-reporter, respectively.
+TLSRPT information, are implemented and maintained by sys4 at https://
+github.com/sys4/libtlsrpt and https://github.com/sys4/tlsrpt-reporter,
+respectively.
-The Postfix implementation supports both DANE (Postfix built-in) and MTA-STS
-(through an smtp_tls_policy_maps plug-in).
+The Postfix implementation supports domains with DANE (Postfix built-in) and
+MTA-STS (through an smtp_tls_policy_maps plug-in).
The Postfix smtp(8) client process implements the SMTP client engine. With
"smtp_tls_connection_reuse = no", the smtp(8) client process also implements
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, 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.
+replies with a TLS security level and name=value attributes with certificate
+matching requirements. Postfix 3.10 and later accept additional name=value
+attributes that are needed for TLSRPT.
- Note 1: Postfix 3.10 and later will accept these attributes in an MTA-STS
- response even if TLSRPT support is disabled (at build time or run time).
- With TLSRPT support turned off, Postfix will use the ttl and policy_failure
- attributes, and will ignore the attributes that are used only for TLSRPT.
+Examples of smtp_tls_policy_maps plugins with MTA-STS support are:
- Note 2: It is an error to specify these attributes for a non-STS policy.
+ * postfix-tlspol, supports domains with DANE (using Postfix built-in DANE),
+ and domains with MTA-STS.
-The examples in the table apply to the MTA-STS policy example given in RFC 8461
-Section 3.2:
+ * postfix-mta-sts-resolver, supports domains with MTA-STS.
+
+Both plugins can generate the additional name=value attributes that Postfix
+needs for TLSRPT support (as of February 2025). This is enabled by setting a
+tlsrpt boolean in a plugin configuration file. This setting is safe with
+Postfix 3.10 and later, even if Postfix TLSRPT support is disabled (at build
+time or at run time).
+
+The examples in the text below apply to this MTA-STS policy example given in
+RFC 8461 Section 3.2:
version: STSv1
mode: enforce
mx: backupmx.example.com
max_age: 604800
-A policy response may contain line breaks.
+The list of supported attributes is given below. Instead of name=value, specify
+{ name = value } when a value may contain whitespace. A policy response may
+contain line breaks.
* policy_type=type
The domain that the MTA-STS policy applies to.
- * policy_ttl=time
-
- How long (in seconds) a Postfix SMTP client process will cache the MTA-STS
- plugin response.
+ Example: policy_domain=example.com
* { policy_string = value }
Specify one policy_string instance for each MTA-STS policy feature,
enclosed inside "{" and "}" to protect whitespace in attribute values.
- Example:
-
- { policy_string = version: STSv1 } { policy_string = mode: enforce }
- ...
+ Example: { policy_string = version: STSv1 } { policy_string = mode: enforce
+ } ...
- This form ignores whitespace after the opening "{", around the "=", and
- before the closing "}".
+ The above form ignores whitespace after the opening "{", around the "=",
+ and before the closing "}".
* mx_host_pattern=pattern
Specify one mx_host_pattern instance for each "mx:" feature in the MTA-STS
policy.
- Example:
-
- mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
+ Example: mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
* policy_failure=type
If specified, forces MTA-STS policy enforcement to fail with the indicated
error, even if a server certificate would satisfy conventional PKI
- constraints.
+ constraints. Valid errors are sts-policy-fetch-error, sts-policy-invalid,
+ sts-webpki-invalid, or the less informative validation-failure.
- Valid errors are sts-policy-fetch-error, sts-policy-invalid, sts-webpki-
- invalid, or the less informative validation-failure.
+ Example: policy_failure=sts-webpki-invalid
+
+ * policy_ttl=time
+
+ This attribute is deprecated. The time value is not used, and support for
+ this attribute will eventually be removed from the code.
+
+Notes:
- Example:
+ * Postfix 3.10 and later will accept these additional attributes in an MTA-
+ STS response even if TLSRPT support is disabled (at build time or at run
+ time). With TLSRPT support turned off, Postfix may still use the
+ policy_failure attribute, and will ignore the attributes that are used only
+ for TLSRPT.
- policy_failure=sts-webpki-invalid
+ * It is an error to specify these attributes for a non-STS policy.
L\bLi\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
C\bCr\bre\bed\bdi\bit\bts\bs
- * The TLSRPT client library and report generator are implemented and
- maintained by sys4.
+ * The TLSRPT client library, and the infrastructure to collect, fetch, and
+ report TLSRPT information, are implemented and maintained by sys4.
* Wietse Venema implemented the integration with Postfix.
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_tls_auth_only=yes
# -o local_header_rewrite_clients=static:all
+# -o smtpd_hide_client_session=yes
# -o smtpd_reject_unlisted_recipient=no
# Instead of specifying complex smtpd_<xxx>_restrictions here,
# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o local_header_rewrite_clients=static:all
+# -o smtpd_hide_client_session=yes
# -o smtpd_reject_unlisted_recipient=no
# Instead of specifying complex smtpd_<xxx>_restrictions here,
# specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
</ul>
<p> The TLSRPT client library, and the infrastructure to collect,
-fetch, and report TLSRPT information are maintained by sys4 at
-<a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> and
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4 at <a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> and
<a href="https://github.com/sys4/tlsrpt-reporter">https://github.com/sys4/tlsrpt-reporter</a>, respectively. </p>
-<p> The Postfix implementation supports both DANE (Postfix built-in)
-and MTA-STS (through an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plug-in). </p>
+<p> The Postfix implementation supports domains with DANE (Postfix
+built-in) and MTA-STS (through an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plug-in).
+</p>
<p> The Postfix <a href="smtp.8.html">smtp(8)</a> client process implements the SMTP client
engine. With "<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = no", the <a href="smtp.8.html">smtp(8)</a> client
<p> Below are a few examples of logging from a Postfix SMTP client
or tlsproxy daemon: </p>
-<blockquote>
+<blockquote>
<pre>
TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
<p> Notes: </p>
-<ul>
+<ul>
<li> <p> Postfix logs and reports the TLSRPT status only for TLS
handshakes on a new SMTP connection. There is no TLS handshake, and
</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, 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>
+plugin, which replies with a TLS security level and name=value
+attributes with certificate matching requirements. Postfix 3.10 and
+later accept additional name=value attributes that are needed for
+TLSRPT. </p>
-<blockquote>
+<p> Examples of <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plugins with MTA-STS support
+are: </p>
+
+<ul>
-<p> Note 1: Postfix 3.10 and later will accept these attributes in
-an MTA-STS response even if TLSRPT support is disabled (at build
-time or run time). With TLSRPT support turned off, Postfix
-will use the <tt>ttl</tt> and <tt>policy_failure</tt> attributes,
-and will ignore the attributes that are used only for TLSRPT. </p>
+<li> <p> <a href="https://github.com/Zuplu/postfix-tlspol">
+postfix-tlspol</a>, supports domains with DANE (using Postfix
+built-in DANE), and domains with MTA-STS. </p>
-<p> Note 2: It is an error to specify these attributes for a non-STS
-policy. </p>
+<li> <p> <a href="https://github.com/Snawoot/postfix-mta-sts-resolver">
+postfix-mta-sts-resolver</a>, supports domains with MTA-STS. </p>
-</blockquote>
+</ul>
+
+<p> Both plugins can generate the additional name=value attributes
+that Postfix needs for TLSRPT support (as of February 2025). This
+is enabled by setting a <tt>tlsrpt</tt> boolean in a plugin
+configuration file. This setting is safe with Postfix 3.10 and
+later, even if Postfix TLSRPT support is disabled (at build time
+or at run time). </p>
-<p> The examples in the table apply to the MTA-STS policy example
+<p> The examples in the text below apply to this MTA-STS policy example
given in <a
href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
RFC 8461 Section 3.2</a>: </p>
</pre>
</blockquote>
-<p> A policy response may contain line breaks. </p>
+<p> The list of supported attributes is given below. Instead of
+<tt>name=value</tt>, specify <tt>{ name = value }</tt> when a value
+may contain whitespace. A policy response may contain line breaks.
+</p>
<ul>
-<li> <p> <tt> policy_type=<i>type</i> </tt>
+<li> <p> <tt> policy_type=<i>type</i> </tt> </p>
<p> Specify <tt>sts</tt> or <tt>no-policy-found</tt>. </p> </li>
<li> <p> <tt> policy_domain=<i>name</i> </tt> </p>
-<p> The domain that the MTA-STS policy applies to. </p> </li>
+<p> The domain that the MTA-STS policy applies to. </p>
-<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
-<p> How long (in seconds) a Postfix SMTP client process will cache
-the MTA-STS plugin response. </p> </li>
+<p> Example: <tt>policy_domain=example.com</tt> </p>
+
+</li>
<li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
<p> Specify one <tt>policy_string</tt> instance for each MTA-STS
policy feature, enclosed inside "{" and "}" to protect whitespace
-in attribute values. </p>
+in attribute values. <p>
-<p> Example: </p>
+<p> Example: <tt> { policy_string = version: STSv1 } { policy_string
+= mode: enforce } ...</tt> </p>
-<blockquote>
-<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
-</pre>
-</blockquote>
-
-<p> This form ignores whitespace after the opening "{", around the "=",
-and before the closing "}".</p> </li>
+<p> The above form ignores whitespace after the opening "{", around
+the "=", and before the closing "}".</p> </li>
<li> <p> <tt> mx_host_pattern=<i>pattern</i> </tt> </p>
<p> Specify one <tt>mx_host_pattern</tt> instance for each "mx:" feature
in the MTA-STS policy. </p>
-<p> Example: </p>
-
-<blockquote>
-<pre>
-mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
-</pre>
-</blockquote>
-</li>
+<p> Example: <tt>mx_host_pattern=mail.example.com
+mx_host_pattern=*.example.net ...</tt> </p> </li>
<li> <p> <tt> policy_failure=<i>type</i> </tt> </p>
<p> If specified, forces MTA-STS policy enforcement to fail with
the indicated error, even if a server certificate would satisfy
-conventional PKI constraints. </p>
+conventional PKI constraints. Valid errors are <tt>sts-policy-fetch-error,
+sts-policy-invalid</tt>, <tt>sts-webpki-invalid</tt>, or the less
+informative <tt>validation-failure</tt>. </p>
-<p> Valid errors are <tt>sts-policy-fetch-error, sts-policy-invalid</tt>,
-<tt>sts-webpki-invalid</tt>, or the less informative
-<tt>validation-failure</tt>. </p>
+<p> Example: <tt>policy_failure=sts-webpki-invalid</tt> </p> </li>
-<p> Example: </p>
+<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
-<blockquote>
-<pre>
-policy_failure=sts-webpki-invalid
-</pre>
-</blockquote>
-</li>
+<p> This attribute is deprecated. The <i>time</i> value is not used,
+and support for this attribute will eventually be removed from the
+code. </p> </li>
+
+</ul>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix 3.10 and later will accept these additional
+attributes in an MTA-STS response even if TLSRPT support is disabled
+(at build time or at run time). With TLSRPT support turned off,
+Postfix may still use the <tt>policy_failure</tt>
+attribute, and will ignore the attributes that are used only for
+TLSRPT. </p>
+
+<li> <p> It is an error to specify these attributes for a non-STS
+policy. </p>
</ul>
<ul>
-<li> The TLSRPT client library and report generator are implemented
-and maintained by sys4. </li>
+<li> The TLSRPT client library, and the infrastructure to collect,
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4. </li>
<li> Wietse Venema implemented the integration with Postfix.
</li>
</pre>
+</DD>
+
+<DT><b><a name="smtpd_hide_client_session">smtpd_hide_client_session</a>
+(default: no)</b></DT><DD>
+
+<p> Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header. </p>
+
+<ul>
+
+<li> <p> The default setting, "<a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> = no",
+must be used for the port 25 MTA service. It provides information
+that is required by <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>. </p>
+
+<li> <p> The setting "<a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details. </p>
+
+</ul>
+
+<p> Depending on the number of recipients, a redacted Received:
+header has one of the following forms: </p>
+
+<blockquote>
+<pre>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+ for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+<br>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+ Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+</pre>
+</blockquote>
+
+<p> The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+<a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>. The form does still meet <a href="https://tools.ietf.org/html/rfc5322">RFC 5322</a> requirements. </p>
+
+<p> This feature is available in Postfix ≥ 3.10. </p>
+
+
</DD>
<DT><b><a name="smtpd_history_flush_threshold">smtpd_history_flush_threshold</a>
Lookup tables, indexed by the complete Postfix SMTP server 4xx
or 5xx response, with reject footer templates.
+ Available in Postfix 3.10 and later:
+
+ <b><a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> (no)</b>
+ Do not include SMTP client session information in the Postfix
+ SMTP server's Received: message header.
+
<b><a name="see_also">SEE ALSO</a></b>
<a href="anvil.8.html">anvil(8)</a>, connection/rate limiting
<a href="cleanup.8.html">cleanup(8)</a>, message canonicalization
smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname
.fi
.ad
+.SH smtpd_hide_client_session (default: no)
+Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header.
+.IP \(bu
+The default setting, "smtpd_hide_client_session = no",
+must be used for the port 25 MTA service. It provides information
+that is required by RFC 5321.
+.IP \(bu
+The setting "smtpd_hide_client_session = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details.
+.br
+.PP
+Depending on the number of recipients, a redacted Received:
+header has one of the following forms:
+.sp
+.in +4
+.nf
+.na
+Received: by mail.example.com (Postfix) id postfix\-queue\-id
+ for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz\-offset (zone)
+.br
+Received: by mail.example.com (Postfix) id postfix\-queue\-id
+ Day, dd Mon yyyy hh:mm:ss tz\-offset (zone)
+.fi
+.ad
+.in -4
+.PP
+The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+RFC 5321. The form does still meet RFC 5322 requirements.
+.PP
+This feature is available in Postfix >= 3.10.
.SH smtpd_history_flush_threshold (default: 100)
The maximal number of lines in the Postfix SMTP server command history
before it is flushed upon receipt of EHLO, RSET, or end of DATA.
.IP "\fBsmtpd_reject_footer_maps (empty)\fR"
Lookup tables, indexed by the complete Postfix SMTP server 4xx or
5xx response, with reject footer templates.
+.PP
+Available in Postfix 3.10 and later:
+.IP "\fBsmtpd_hide_client_session (no)\fR"
+Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header.
.SH "SEE ALSO"
.na
.nf
s;\btls_required_enable\b;<a href="postconf.5.html#tls_required_enable">$&</a>;g;
s;\bfull_name_encoding_charset\b;<a href="postconf.5.html#full_name_encoding_charset">$&</a>;g;
+ s;\bsmtpd_hide_client_session\b;<a href="postconf.5.html#smtpd_hide_client_session">$&</a>;g;
# Service-defined parameters...
</ul>
<p> The TLSRPT client library, and the infrastructure to collect,
-fetch, and report TLSRPT information are maintained by sys4 at
-https://github.com/sys4/libtlsrpt and
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4 at https://github.com/sys4/libtlsrpt and
https://github.com/sys4/tlsrpt-reporter, respectively. </p>
-<p> The Postfix implementation supports both DANE (Postfix built-in)
-and MTA-STS (through an smtp_tls_policy_maps plug-in). </p>
+<p> The Postfix implementation supports domains with DANE (Postfix
+built-in) and MTA-STS (through an smtp_tls_policy_maps plug-in).
+</p>
<p> The Postfix smtp(8) client process implements the SMTP client
engine. With "smtp_tls_connection_reuse = no", the smtp(8) client
<p> Below are a few examples of logging from a Postfix SMTP client
or tlsproxy daemon: </p>
-<blockquote>
+<blockquote>
<pre>
TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
<p> Notes: </p>
-<ul>
+<ul>
<li> <p> Postfix logs and reports the TLSRPT status only for TLS
handshakes on a new SMTP connection. There is no TLS handshake, and
</a></h2>
<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>
+plugin, which replies with a TLS security level and name=value
+attributes with certificate matching requirements. Postfix 3.10 and
+later accept additional name=value attributes that are needed for
+TLSRPT. </p>
-<blockquote>
+<p> Examples of smtp_tls_policy_maps plugins with MTA-STS support
+are: </p>
+
+<ul>
-<p> Note 1: Postfix 3.10 and later will accept these attributes in
-an MTA-STS response even if TLSRPT support is disabled (at build
-time or run time). With TLSRPT support turned off, Postfix
-will use the <tt>ttl</tt> and <tt>policy_failure</tt> attributes,
-and will ignore the attributes that are used only for TLSRPT. </p>
+<li> <p> <a href="https://github.com/Zuplu/postfix-tlspol">
+postfix-tlspol</a>, supports domains with DANE (using Postfix
+built-in DANE), and domains with MTA-STS. </p>
-<p> Note 2: It is an error to specify these attributes for a non-STS
-policy. </p>
+<li> <p> <a href="https://github.com/Snawoot/postfix-mta-sts-resolver">
+postfix-mta-sts-resolver</a>, supports domains with MTA-STS. </p>
-</blockquote>
+</ul>
+
+<p> Both plugins can generate the additional name=value attributes
+that Postfix needs for TLSRPT support (as of February 2025). This
+is enabled by setting a <tt>tlsrpt</tt> boolean in a plugin
+configuration file. This setting is safe with Postfix 3.10 and
+later, even if Postfix TLSRPT support is disabled (at build time
+or at run time). </p>
-<p> The examples in the table apply to the MTA-STS policy example
+<p> The examples in the text below apply to this MTA-STS policy example
given in <a
href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
RFC 8461 Section 3.2</a>: </p>
</pre>
</blockquote>
-<p> A policy response may contain line breaks. </p>
+<p> The list of supported attributes is given below. Instead of
+<tt>name=value</tt>, specify <tt>{ name = value }</tt> when a value
+may contain whitespace. A policy response may contain line breaks.
+</p>
<ul>
-<li> <p> <tt> policy_type=<i>type</i> </tt>
+<li> <p> <tt> policy_type=<i>type</i> </tt> </p>
<p> Specify <tt>sts</tt> or <tt>no-policy-found</tt>. </p> </li>
<li> <p> <tt> policy_domain=<i>name</i> </tt> </p>
-<p> The domain that the MTA-STS policy applies to. </p> </li>
+<p> The domain that the MTA-STS policy applies to. </p>
-<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
-<p> How long (in seconds) a Postfix SMTP client process will cache
-the MTA-STS plugin response. </p> </li>
+<p> Example: <tt>policy_domain=example.com</tt> </p>
+
+</li>
<li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
<p> Specify one <tt>policy_string</tt> instance for each MTA-STS
policy feature, enclosed inside "{" and "}" to protect whitespace
-in attribute values. </p>
+in attribute values. <p>
-<p> Example: </p>
+<p> Example: <tt> { policy_string = version: STSv1 } { policy_string
+= mode: enforce } ...</tt> </p>
-<blockquote>
-<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
-</pre>
-</blockquote>
-
-<p> This form ignores whitespace after the opening "{", around the "=",
-and before the closing "}".</p> </li>
+<p> The above form ignores whitespace after the opening "{", around
+the "=", and before the closing "}".</p> </li>
<li> <p> <tt> mx_host_pattern=<i>pattern</i> </tt> </p>
<p> Specify one <tt>mx_host_pattern</tt> instance for each "mx:" feature
in the MTA-STS policy. </p>
-<p> Example: </p>
-
-<blockquote>
-<pre>
-mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
-</pre>
-</blockquote>
-</li>
+<p> Example: <tt>mx_host_pattern=mail.example.com
+mx_host_pattern=*.example.net ...</tt> </p> </li>
<li> <p> <tt> policy_failure=<i>type</i> </tt> </p>
<p> If specified, forces MTA-STS policy enforcement to fail with
the indicated error, even if a server certificate would satisfy
-conventional PKI constraints. </p>
+conventional PKI constraints. Valid errors are <tt>sts-policy-fetch-error,
+sts-policy-invalid</tt>, <tt>sts-webpki-invalid</tt>, or the less
+informative <tt>validation-failure</tt>. </p>
-<p> Valid errors are <tt>sts-policy-fetch-error, sts-policy-invalid</tt>,
-<tt>sts-webpki-invalid</tt>, or the less informative
-<tt>validation-failure</tt>. </p>
+<p> Example: <tt>policy_failure=sts-webpki-invalid</tt> </p> </li>
-<p> Example: </p>
+<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
-<blockquote>
-<pre>
-policy_failure=sts-webpki-invalid
-</pre>
-</blockquote>
-</li>
+<p> This attribute is deprecated. The <i>time</i> value is not used,
+and support for this attribute will eventually be removed from the
+code. </p> </li>
+
+</ul>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix 3.10 and later will accept these additional
+attributes in an MTA-STS response even if TLSRPT support is disabled
+(at build time or at run time). With TLSRPT support turned off,
+Postfix may still use the <tt>policy_failure</tt>
+attribute, and will ignore the attributes that are used only for
+TLSRPT. </p>
+
+<li> <p> It is an error to specify these attributes for a non-STS
+policy. </p>
</ul>
<ul>
-<li> The TLSRPT client library and report generator are implemented
-and maintained by sys4. </li>
+<li> The TLSRPT client library, and the infrastructure to collect,
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4. </li>
<li> Wietse Venema implemented the integration with Postfix.
</li>
message. </p>
<p> This feature is available in Postfix ≥ 3.10. </p>
+
+%PARAM smtpd_hide_client_session no
+
+<p> Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header. </p>
+
+<ul>
+
+<li> <p> The default setting, "smtpd_hide_client_session = no",
+must be used for the port 25 MTA service. It provides information
+that is required by RFC 5321. </p>
+
+<li> <p> The setting "smtpd_hide_client_session = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details. </p>
+
+</ul>
+
+<p> Depending on the number of recipients, a redacted Received:
+header has one of the following forms: </p>
+
+<blockquote>
+<pre>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+ for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+<br>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+ Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+</pre>
+</blockquote>
+
+<p> The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+RFC 5321. The form does still meet RFC 5322 requirements. </p>
+
+<p> This feature is available in Postfix ≥ 3.10. </p>
RequireTLS
requiretls
sendopts
+tz
smtp smtp_proto c smtpd smtpd c verify verify c
operations Files cleanup cleanup h cleanup cleanup_message c
proto postconf proto pipe pipe c
+ bounce bounce c bounce bounce_notify_util c cleanup cleanup c
+ cleanup cleanup_message c smtp smtp c smtp smtp_connect c
+ Documentation edited for clarity Files pipe pipe c
+ global mail_params h smtpd smtpd c
Roessner
bitflags
Schulze
+tlspol
marc
LP
collectd
+Snawoot
+Zuplu
+tlspol
#define DEF_SOCKMAP_MAX_REPLY 100000 /* reply size limit */
extern int var_sockmap_max_reply;
+ /*
+ * Client privacy.
+ */
+#define VAR_SMTPD_HIDE_CLIENT_SESSION "smtpd_hide_client_session"
+#define DEF_SMTPD_HIDE_CLIENT_SESSION "no"
+extern int var_smtpd_hide_client_session;
+
/* LICENSE
/* .ad
/* .fi
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20250202"
+#define MAIL_RELEASE_DATE "20250205"
#define MAIL_VERSION_NUMBER "3.10"
#ifdef SNAPSHOT
/* .IP "\fBsmtpd_reject_footer_maps (empty)\fR"
/* Lookup tables, indexed by the complete Postfix SMTP server 4xx or
/* 5xx response, with reject footer templates.
+/* .PP
+/* Available in Postfix 3.10 and later:
+/* .IP "\fBsmtpd_hide_client_session (no)\fR"
+/* Do not include SMTP client session information in the Postfix
+/* SMTP server's Received: message header.
/* SEE ALSO
/* anvil(8), connection/rate limiting
/* cleanup(8), message canonicalization
int var_smtpd_forbid_bare_lf_code;
static int bare_lf_mask;
static NAMADR_LIST *bare_lf_excl;
+bool var_smtpd_hide_client_session;
/*
* Silly little macros.
{
SMTPD_PROXY *proxy = state->proxy;
char **cpp;
- const char *rfc3848_sess;
- const char *rfc3848_auth;
+ const char *rfc3848_sess = "";
+ const char *rfc3848_auth = "";
+ const char *with_verb = " with ";
const char *with_protocol = (state->flags & SMTPD_FLAG_SMTPUTF8) ?
"UTF8SMTP" : state->protocol;
+ const char *id_verb = state->cleanup ? " id " : "";
+ const char *id_value = state->cleanup ? state->queue_id : "";
#ifdef USE_TLS
VSTRING *peer_CN;
* intermediate proxy.
*/
if (!proxy || state->xforward.flags == 0) {
- out_fprintf(out_stream, REC_TYPE_NORM,
- "Received: from %s (%s [%s])",
- state->helo_name ? state->helo_name : state->name,
- state->name, state->rfc_addr);
+ if (!var_smtpd_hide_client_session) {
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "Received: from %s (%s [%s])",
+ state->helo_name ? state->helo_name : state->name,
+ state->name, state->rfc_addr);
#define VSTRING_STRDUP(s) vstring_strcpy(vstring_alloc(strlen(s) + 1), (s))
#ifdef USE_TLS
- if (var_smtpd_tls_received_header && state->tls_context) {
- int cont = 0;
-
- vstring_sprintf(state->buffer,
- "\t(using %s with cipher %s (%d/%d bits)",
- state->tls_context->protocol,
- state->tls_context->cipher_name,
- state->tls_context->cipher_usebits,
- state->tls_context->cipher_algbits);
- if (state->tls_context->kex_name && *state->tls_context->kex_name) {
- out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
- LEN(state->buffer));
- vstring_sprintf(state->buffer, "\t key-exchange %s",
- state->tls_context->kex_name);
- if (state->tls_context->kex_curve
- && *state->tls_context->kex_curve)
- vstring_sprintf_append(state->buffer, " (%s)",
- state->tls_context->kex_curve);
- else if (state->tls_context->kex_bits > 0)
- vstring_sprintf_append(state->buffer, " (%d bits)",
- state->tls_context->kex_bits);
- cont = 1;
- }
- if (state->tls_context->srvr_sig_name
- && *state->tls_context->srvr_sig_name) {
- if (cont) {
- vstring_sprintf_append(state->buffer, " server-signature %s",
- state->tls_context->srvr_sig_name);
- } else {
+ if (var_smtpd_tls_received_header && state->tls_context) {
+ int cont = 0;
+
+ vstring_sprintf(state->buffer,
+ "\t(using %s with cipher %s (%d/%d bits)",
+ state->tls_context->protocol,
+ state->tls_context->cipher_name,
+ state->tls_context->cipher_usebits,
+ state->tls_context->cipher_algbits);
+ if (state->tls_context->kex_name && *state->tls_context->kex_name) {
out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
LEN(state->buffer));
- vstring_sprintf(state->buffer, "\t server-signature %s",
- state->tls_context->srvr_sig_name);
+ vstring_sprintf(state->buffer, "\t key-exchange %s",
+ state->tls_context->kex_name);
+ if (state->tls_context->kex_curve
+ && *state->tls_context->kex_curve)
+ vstring_sprintf_append(state->buffer, " (%s)",
+ state->tls_context->kex_curve);
+ else if (state->tls_context->kex_bits > 0)
+ vstring_sprintf_append(state->buffer, " (%d bits)",
+ state->tls_context->kex_bits);
+ cont = 1;
}
- if (state->tls_context->srvr_sig_curve
- && *state->tls_context->srvr_sig_curve)
- vstring_sprintf_append(state->buffer, " (%s%s)",
+ if (state->tls_context->srvr_sig_name
+ && *state->tls_context->srvr_sig_name) {
+ if (cont) {
+ vstring_sprintf_append(state->buffer, " server-signature %s",
+ state->tls_context->srvr_sig_name);
+ } else {
+ out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
+ LEN(state->buffer));
+ vstring_sprintf(state->buffer, "\t server-signature %s",
+ state->tls_context->srvr_sig_name);
+ }
+ if (state->tls_context->srvr_sig_curve
+ && *state->tls_context->srvr_sig_curve)
+ vstring_sprintf_append(state->buffer, " (%s%s)",
state->tls_context->srvr_sig_curve,
- state->tls_context->stoc_rpk ?
- " raw public key" : "");
- else if (state->tls_context->srvr_sig_bits > 0)
- vstring_sprintf_append(state->buffer, " (%d bit%s)",
- state->tls_context->srvr_sig_bits,
- state->tls_context->stoc_rpk ?
- " raw public key" : "s");
- if (state->tls_context->srvr_sig_dgst
- && *state->tls_context->srvr_sig_dgst)
- vstring_sprintf_append(state->buffer, " server-digest %s",
+ state->tls_context->stoc_rpk ?
+ " raw public key" : "");
+ else if (state->tls_context->srvr_sig_bits > 0)
+ vstring_sprintf_append(state->buffer, " (%d bit%s)",
+ state->tls_context->srvr_sig_bits,
+ state->tls_context->stoc_rpk ?
+ " raw public key" : "s");
+ if (state->tls_context->srvr_sig_dgst
+ && *state->tls_context->srvr_sig_dgst)
+ vstring_sprintf_append(state->buffer, " server-digest %s",
state->tls_context->srvr_sig_dgst);
- }
- if (state->tls_context->clnt_sig_name
- && *state->tls_context->clnt_sig_name) {
- out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
- LEN(state->buffer));
- vstring_sprintf(state->buffer, "\t client-signature %s",
- state->tls_context->clnt_sig_name);
- if (state->tls_context->clnt_sig_curve
- && *state->tls_context->clnt_sig_curve)
- vstring_sprintf_append(state->buffer, " (%s%s)",
+ }
+ if (state->tls_context->clnt_sig_name
+ && *state->tls_context->clnt_sig_name) {
+ out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
+ LEN(state->buffer));
+ vstring_sprintf(state->buffer, "\t client-signature %s",
+ state->tls_context->clnt_sig_name);
+ if (state->tls_context->clnt_sig_curve
+ && *state->tls_context->clnt_sig_curve)
+ vstring_sprintf_append(state->buffer, " (%s%s)",
state->tls_context->clnt_sig_curve,
- state->tls_context->ctos_rpk ?
- " raw public key" : "");
- else if (state->tls_context->clnt_sig_bits > 0)
- vstring_sprintf_append(state->buffer, " (%d bit%s)",
- state->tls_context->clnt_sig_bits,
- state->tls_context->ctos_rpk ?
- " raw public key" : "s");
- if (state->tls_context->clnt_sig_dgst
- && *state->tls_context->clnt_sig_dgst)
- vstring_sprintf_append(state->buffer, " client-digest %s",
+ state->tls_context->ctos_rpk ?
+ " raw public key" : "");
+ else if (state->tls_context->clnt_sig_bits > 0)
+ vstring_sprintf_append(state->buffer, " (%d bit%s)",
+ state->tls_context->clnt_sig_bits,
+ state->tls_context->ctos_rpk ?
+ " raw public key" : "s");
+ if (state->tls_context->clnt_sig_dgst
+ && *state->tls_context->clnt_sig_dgst)
+ vstring_sprintf_append(state->buffer, " client-digest %s",
state->tls_context->clnt_sig_dgst);
- }
- out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer));
- if (TLS_CERT_IS_PRESENT(state->tls_context)) {
- peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
- comment_sanitize(peer_CN);
- issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
+ }
+ out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer));
+ if (TLS_CERT_IS_PRESENT(state->tls_context)) {
+ peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
+ comment_sanitize(peer_CN);
+ issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
state->tls_context->issuer_CN : "");
- comment_sanitize(issuer_CN);
- out_fprintf(out_stream, REC_TYPE_NORM,
- "\t(Client CN \"%s\", Issuer \"%s\" (%s))",
- STR(peer_CN), STR(issuer_CN),
- TLS_CERT_IS_TRUSTED(state->tls_context) ?
- "verified OK" : "not verified");
- vstring_free(issuer_CN);
- vstring_free(peer_CN);
- } else if (TLS_RPK_IS_PRESENT(state->tls_context)) {
- out_fprintf(out_stream, REC_TYPE_NORM,
- "\t(Client RPK %s digest %s)",
- var_smtpd_tls_fpt_dgst,
- state->tls_context->peer_pkey_fprint);
- } else if (var_smtpd_tls_ask_ccert)
- out_fprintf(out_stream, REC_TYPE_NORM,
- "\t(Client did not present a certificate)");
- else
- out_fprintf(out_stream, REC_TYPE_NORM,
- "\t(No client certificate requested)");
- }
- /* RFC 3848 is defined for ESMTP only. */
- if (state->tls_context != 0
- && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
- rfc3848_sess = "S";
- else
+ comment_sanitize(issuer_CN);
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(Client CN \"%s\", Issuer \"%s\" (%s))",
+ STR(peer_CN), STR(issuer_CN),
+ TLS_CERT_IS_TRUSTED(state->tls_context) ?
+ "verified OK" : "not verified");
+ vstring_free(issuer_CN);
+ vstring_free(peer_CN);
+ } else if (TLS_RPK_IS_PRESENT(state->tls_context)) {
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(Client RPK %s digest %s)",
+ var_smtpd_tls_fpt_dgst,
+ state->tls_context->peer_pkey_fprint);
+ } else if (var_smtpd_tls_ask_ccert)
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(Client did not present a certificate)");
+ else
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(No client certificate requested)");
+ }
+ /* RFC 3848 is defined for ESMTP only. */
+ if (state->tls_context != 0
+ && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
+ rfc3848_sess = "S";
#endif
- rfc3848_sess = "";
#ifdef USE_SASL_AUTH
- if (var_smtpd_sasl_auth_hdr && state->sasl_username) {
- username = VSTRING_STRDUP(state->sasl_username);
- comment_sanitize(username);
- out_fprintf(out_stream, REC_TYPE_NORM,
- "\t(Authenticated sender: %s)", STR(username));
- vstring_free(username);
- }
- /* RFC 3848 is defined for ESMTP only. */
- if (state->sasl_username
- && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
- rfc3848_auth = "A";
- else
+ if (var_smtpd_sasl_auth_hdr && state->sasl_username) {
+ username = VSTRING_STRDUP(state->sasl_username);
+ comment_sanitize(username);
+ out_fprintf(out_stream, REC_TYPE_NORM,
+ "\t(Authenticated sender: %s)", STR(username));
+ vstring_free(username);
+ }
+ /* RFC 3848 is defined for ESMTP only. */
+ if (state->sasl_username
+ && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
+ rfc3848_auth = "A";
#endif
- rfc3848_auth = "";
+ } else {
+ with_verb = "";
+ with_protocol = "";
+ }
if (state->rcpt_count == 1 && state->recipient) {
out_fprintf(out_stream, REC_TYPE_NORM,
- state->cleanup ? "\tby %s (%s) with %s%s%s id %s" :
- "\tby %s (%s) with %s%s%s",
+ "%sby %s (%s)%s%s%s%s%s%s",
+ var_smtpd_hide_client_session ? "Received: " : "\t",
var_myhostname, var_mail_name,
- with_protocol, rfc3848_sess,
- rfc3848_auth, state->queue_id);
+ with_verb, with_protocol, rfc3848_sess,
+ rfc3848_auth, id_verb, id_value);
quote_822_local(state->buffer, state->recipient);
out_fprintf(out_stream, REC_TYPE_NORM,
"\tfor <%s>; %s", STR(state->buffer),
mail_date(state->arrival_time.tv_sec));
} else {
out_fprintf(out_stream, REC_TYPE_NORM,
- state->cleanup ? "\tby %s (%s) with %s%s%s id %s;" :
- "\tby %s (%s) with %s%s%s;",
+ "%sby %s (%s)%s%s%s%s%s%s;",
+ var_smtpd_hide_client_session ? "Received: " : "\t",
var_myhostname, var_mail_name,
- with_protocol, rfc3848_sess,
- rfc3848_auth, state->queue_id);
+ with_verb, with_protocol, rfc3848_sess,
+ rfc3848_auth, id_verb, id_value);
out_fprintf(out_stream, REC_TYPE_NORM,
"\t%s", mail_date(state->arrival_time.tv_sec));
}
static const CONFIG_NBOOL_TABLE nbool_table[] = {
VAR_RELAY_BEFORE_RCPT_CHECKS, DEF_RELAY_BEFORE_RCPT_CHECKS, &var_relay_before_rcpt_checks,
VAR_SMTPD_REQ_DEADLINE, DEF_SMTPD_REQ_DEADLINE, &var_smtpd_req_deadline,
+ VAR_SMTPD_HIDE_CLIENT_SESSION, DEF_SMTPD_HIDE_CLIENT_SESSION, &var_smtpd_hide_client_session,
0,
};
static const CONFIG_STR_TABLE str_table[] = {