diff --git a/postfix/HISTORY b/postfix/HISTORY index 277752d35..e30ce59cc 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -28918,4 +28918,19 @@ Apologies for any names omitted. 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. diff --git a/postfix/README_FILES/TLSRPT_README b/postfix/README_FILES/TLSRPT_README index 94f011ebe..fe26e3b04 100644 --- a/postfix/README_FILES/TLSRPT_README +++ b/postfix/README_FILES/TLSRPT_README @@ -48,11 +48,12 @@ are collected and processed into daily summary reports. 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 @@ -228,19 +229,25 @@ Options: MMTTAA--SSTTSS SSuuppppoorrtt vviiaa ssmmttpp__ttllss__ppoolliiccyy__mmaappss 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 @@ -249,7 +256,9 @@ Section 3.2: 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 @@ -259,45 +268,49 @@ A policy response may contain line breaks. 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: + Example: { policy_string = version: STSv1 } { policy_string = mode: enforce + } ... - { 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 - Example: + * policy_ttl=time - policy_failure=sts-webpki-invalid + This attribute is deprecated. The time value is not used, and support for + this attribute will eventually be removed from the code. + +Notes: + + * 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. + + * It is an error to specify these attributes for a non-STS policy. LLiimmiittaattiioonnss @@ -314,7 +327,7 @@ SMTP protocol engine. It just is not how Postfix works internally. CCrreeddiittss - * 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. diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index dc038d0d1..5abe06cbd 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -23,6 +23,7 @@ smtp inet n - n - - smtpd # -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__restrictions here, # specify "smtpd__restrictions=$mua__restrictions" @@ -42,6 +43,7 @@ smtp inet n - n - - smtpd # -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__restrictions here, # specify "smtpd__restrictions=$mua__restrictions" diff --git a/postfix/html/TLSRPT_README.html b/postfix/html/TLSRPT_README.html index 95acfb7b7..cef622abd 100644 --- a/postfix/html/TLSRPT_README.html +++ b/postfix/html/TLSRPT_README.html @@ -98,12 +98,13 @@ and a central 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 +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.

-

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 @@ -215,7 +216,7 @@ queue, but it will also log a visible record to the mail logfile.

Below are a few examples of logging from a Postfix SMTP client or tlsproxy daemon:

-
+
 TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
  
@@ -229,7 +230,7 @@ TLSRPT: status=failure, domain=example.net, receiving_mx=mail.example.net[ipaddr
 
 

Notes:

-
    +
    • Postfix logs and reports the TLSRPT status only for TLS handshakes on a new SMTP connection. There is no TLS handshake, and @@ -332,25 +333,33 @@ generator's sender address):

      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.

      +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.

      -
      +

      Examples of smtp_tls_policy_maps plugins with MTA-STS support +are:

      -

      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.

      +
        -

        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.

        -
      +
    • +postfix-mta-sts-resolver, supports domains with MTA-STS.

      -

      The examples in the table apply to the MTA-STS policy example +

    + +

    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:

    @@ -366,72 +375,77 @@ 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 +

  • policy_type=type

    Specify sts or no-policy-found.

  • policy_domain=name

    -

    The domain that the MTA-STS policy applies to.

  • +

    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.

    +in attribute values.

    -

    Example:

    +

    Example: { policy_string = version: STSv1 } { policy_string += mode: enforce } ...

    -
    -
    -{ 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.

    +conventional PKI 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

  • -

    Example:

    +
  • policy_ttl=time

    -
    -
    -policy_failure=sts-webpki-invalid
    -
    -
    -
  • +

    This attribute is deprecated. The time value is not used, +and support for this attribute will eventually be removed from the +code.

    + +
+ +

Notes:

+ +
    + +
  • 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.

    + +
  • It is an error to specify these attributes for a non-STS +policy.

@@ -453,8 +467,9 @@ engine. It just is not how Postfix works internally.

    -
  • 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.
  • diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index e67cfb18e..f61e58ed4 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -16550,6 +16550,47 @@ Examples: + + +
    smtpd_hide_client_session +(default: no)
    + +

    Do not include SMTP client session information in the Postfix +SMTP server's Received: message header.

    + +
      + +
    • 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.

      + +
    • 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.

      + +
    + +

    Depending on the number of recipients, a redacted Received: +header has one of the following forms:

    + +
    +
    +Received: by mail.example.com (Postfix) id postfix-queue-id
    +        for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
    +
    +Received: by mail.example.com (Postfix) id postfix-queue-id + Day, dd Mon yyyy hh:mm:ss tz-offset (zone) +
    +
    + +

    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.

    + +

    This feature is available in Postfix ≥ 3.10.

    + +
    smtpd_history_flush_threshold diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 83776ac55..47be68d07 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -1431,6 +1431,12 @@ SMTPD(8) SMTPD(8) Lookup tables, indexed by the complete Postfix SMTP server 4xx or 5xx response, with reject footer templates. + Available in Postfix 3.10 and later: + + smtpd_hide_client_session (no) + 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 diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 060983545..14cbf0155 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -11187,6 +11187,40 @@ smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname 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 ; 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. diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index c68e32598..a671d476b 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -1232,6 +1232,11 @@ Available in Postfix 3.4 and later: .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 diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 2a6558538..b06c2d00f 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -1188,6 +1188,7 @@ while (<>) { s;\btls_required_enable\b;$&;g; s;\bfull_name_encoding_charset\b;$&;g; + s;\bsmtpd_hide_client_session\b;$&;g; # Service-defined parameters... diff --git a/postfix/proto/TLSRPT_README.html b/postfix/proto/TLSRPT_README.html index 11bdc5510..7468b6fb1 100644 --- a/postfix/proto/TLSRPT_README.html +++ b/postfix/proto/TLSRPT_README.html @@ -98,12 +98,13 @@ and a central 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 +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.

-

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 @@ -215,7 +216,7 @@ queue, but it will also log a visible record to the mail logfile.

Below are a few examples of logging from a Postfix SMTP client or tlsproxy daemon:

-
+
 TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
  
@@ -229,7 +230,7 @@ TLSRPT: status=failure, domain=example.net, receiving_mx=mail.example.net[ipaddr
 
 

Notes:

-
    +
    • Postfix logs and reports the TLSRPT status only for TLS handshakes on a new SMTP connection. There is no TLS handshake, and @@ -332,25 +333,33 @@ generator's sender address):

      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.

      +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.

      -
      +

      Examples of smtp_tls_policy_maps plugins with MTA-STS support +are:

      -

      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.

      +
        -

        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.

        -
      +
    • +postfix-mta-sts-resolver, supports domains with MTA-STS.

      -

      The examples in the table apply to the MTA-STS policy example +

    + +

    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:

    @@ -366,72 +375,77 @@ 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 +

  • policy_type=type

    Specify sts or no-policy-found.

  • policy_domain=name

    -

    The domain that the MTA-STS policy applies to.

  • +

    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.

    +in attribute values.

    -

    Example:

    +

    Example: { policy_string = version: STSv1 } { policy_string += mode: enforce } ...

    -
    -
    -{ 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.

    +conventional PKI 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

  • -

    Example:

    +
  • policy_ttl=time

    -
    -
    -policy_failure=sts-webpki-invalid
    -
    -
    -
  • +

    This attribute is deprecated. The time value is not used, +and support for this attribute will eventually be removed from the +code.

    + +
+ +

Notes:

+ +
    + +
  • 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.

    + +
  • It is an error to specify these attributes for a non-STS +policy.

@@ -453,8 +467,9 @@ engine. It just is not how Postfix works internally.

    -
  • 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.
  • diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index abb606368..25eef4da9 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -19486,3 +19486,40 @@ will add that header to a delivery status notification for that message.

    This feature is available in Postfix ≥ 3.10.

    + +%PARAM smtpd_hide_client_session no + +

    Do not include SMTP client session information in the Postfix +SMTP server's Received: message header.

    + +
      + +
    • 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.

      + +
    • 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.

      + +
    + +

    Depending on the number of recipients, a redacted Received: +header has one of the following forms:

    + +
    +
    +Received: by mail.example.com (Postfix) id postfix-queue-id
    +        for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
    +
    +Received: by mail.example.com (Postfix) id postfix-queue-id + Day, dd Mon yyyy hh:mm:ss tz-offset (zone) +
    +
    + +

    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.

    + +

    This feature is available in Postfix ≥ 3.10.

    diff --git a/postfix/proto/stop b/postfix/proto/stop index c1a080d87..a8b5522a5 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1664,3 +1664,4 @@ REQUIRETLS RequireTLS requiretls sendopts +tz diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index 15d98a3c3..870135f2b 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -160,3 +160,7 @@ proto proto socketmap_table 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 diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index 74e0858b7..d358e3614 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -99,3 +99,4 @@ CLOSEFROM Roessner bitflags Schulze +tlspol diff --git a/postfix/proto/stop.spell-proto-html b/postfix/proto/stop.spell-proto-html index 1a487be5f..b5bd4adf3 100644 --- a/postfix/proto/stop.spell-proto-html +++ b/postfix/proto/stop.spell-proto-html @@ -397,3 +397,6 @@ dtd marc LP collectd +Snawoot +Zuplu +tlspol diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 8b54490f5..aa2f294bf 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -4502,6 +4502,13 @@ extern char *var_full_name_encoding_charset; #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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 825bcae3d..27e83993c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20250202" +#define MAIL_RELEASE_DATE "20250205" #define MAIL_VERSION_NUMBER "3.10" #ifdef SNAPSHOT diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 962b361c7..9c11b18ca 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -1174,6 +1174,11 @@ /* .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 @@ -1558,6 +1563,7 @@ char *var_smtpd_forbid_bare_lf_excl; 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. @@ -3434,10 +3440,13 @@ static void common_pre_message_handling(SMTPD_STATE *state, { 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; @@ -3483,152 +3492,153 @@ static void common_pre_message_handling(SMTPD_STATE *state, * 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; + 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 { + 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)); } @@ -6790,6 +6800,7 @@ int main(int argc, char **argv) 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[] = {