]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.10-20240923-nonprod 20240902-nonprod
authorWietse Z Venema <wietse@porcupine.org>
Mon, 23 Sep 2024 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Tue, 24 Sep 2024 02:47:57 +0000 (12:47 +1000)
37 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/AAAREADME
postfix/README_FILES/TLSRPT_README
postfix/TODO-TLSRPT [new file with mode: 0644]
postfix/WISHLIST
postfix/html/TLSRPT_README.html
postfix/html/index.html
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/proto/TLSRPT_README.html
postfix/proto/postconf.proto
postfix/proto/stop
postfix/proto/stop.double-cc
postfix/proto/stop.double-history
postfix/proto/stop.double-proto-html
postfix/proto/stop.spell-proto-html
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_tls_policy.c
postfix/src/smtp/smtp_tlsrpt.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_dh.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_proxy.h
postfix/src/tls/tls_proxy_client_print.c
postfix/src/tls/tls_proxy_client_scan.c
postfix/src/tls/tls_verify.c
postfix/src/tls/tlsrpt_wrapper.c
postfix/src/tls/tlsrpt_wrapper.h
postfix/src/tlsproxy/tlsproxy.c
postfix/src/util/argv.c

index 8ee03dbe70d2992b1a03b756ed67d62e4f81fe1a..d14b89c2277831be00c40c63d3a1c235f447d3f4 100644 (file)
 -TTEST_CASE
 -TTLSMGR_SCACHE
 -TTLSP_STATE
+-TTLSRPT_WRAPPER
 -TTLS_APPL_STATE
 -TTLS_CERTS
 -TTLS_CLIENT_INIT_PROPS
index 1ccada3db96174c1fb4233d61965d73cb3353878..01cd10d2020c824dca8fa58308aea63192a7e87d 100644 (file)
@@ -28241,3 +28241,26 @@ Apologies for any names omitted.
        Minor feature: "postcat -f" option to prepend the filename
        to each output line. This simplifies test data development.
        File: postcat/postcat.c.
+
+20240919
+
+       Bitrot: With OpenSSL 3.0 additional key exchange algorithms
+       can be runtime loaded via "providers", and these don't have
+       short internal numeric ids (nids). We've been using numeric
+       ids to configure key exchange groups, and for logging the
+       negotiated group. We now need to switch to APIs that work
+       directly with string names. OpenSSL 3.0 supports not only
+       (EC)DH key exchange groups but also more general KEMs (Key
+       Encapsulation Mechanisms), in which the response from the
+       server to the client contains no server public key. So we
+       can no longer reliably deduce the negotiated group from a
+       "peer" key, and may need to fall back on the (new with
+       OpenSSL 3.2) SSL_get0_group_name() function. Viktor Dukhovni.
+       Files: src/tls/tls.h, src/tls/tls_dh.c, src/tls/tls_misc.c.
+
+20240923
+
+       Cleanup: No user-visible change. Updated TLSRPT related
+       internal comments and internal identifiers; updated error
+       logging after changes in libtlsrpt error-to-string conversion
+       functions; minor changes to improve robustness.
index 94d552ece498af240de410ab1e8c210a22139f46..d3b0817eac825afa52d3c73fe9bee11223923b5c 100644 (file)
@@ -11,6 +11,7 @@ G\bGe\ben\bne\ber\bra\bal\bl c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
   * SASL_README: SASL Authentication
   * TLS_README: TLS Encryption and authentication
   * FORWARD_SECRECY_README: TLS Forward Secrecy
+  * TLSRPT_README: TLSRPT Protocol Support
   * IPV6_README: IP Version 6 Support
   * SMTPUTF8_README: SMTPUTF8 Support
   * MAILLOG_README: Postfix logging to file or stdout
index 553a09ce901bbaadb474ac1c4ff313021d5e2829..b5a33922a161a3facf4c92976ab942fc4fd99810 100644 (file)
@@ -18,18 +18,28 @@ domain can publish a policy in DNS to request daily summary reports for
 successful and failed TLS connections to that domain. Support for TLSRPT was
 added in Postfix 3.10.
 
-When Postfix TLSRPT support is enabled (with "smtp_tlsrpt_enable = yes"), the
-Postfix SMTP and TLS clients engines will generate "success" and "failure"
-events, and will pass those events to a TLSRPT client library and report
-generator that are maintained by sys4. The Postfix implementation supports both
-DANE (Postfix built-in) and MTA-STS (through an smtp_tls_policy_maps plug-in).
+A policy example looks like this:
 
-The high-level diagram shows how Postfix events are reported to domains that
+    _smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:smtp-tls-
+    report@example.com"
+
+Translation: email sending systems are requested to generate daily summaries of
+successful and failed SMTP over TLS connections to domain example.com, and to
+report those summaries via email to the specified address. Instead of mailto:,
+a policy may specify an https: destination.
+
+The high-level diagram shows how Postfix reports summaries to domains that
 publish a TLSRPT policy.
 
     Postfix SMTP and   --> TLSRPT client --> TLSRPT report --> Email or HTTP
     TLS client engines     library           generator         summary
 
+When Postfix TLSRPT support is enabled (with "smtp_tlsrpt_enable = yes"), the
+Postfix SMTP and TLS clients engines will generate "success" and "failure"
+events, and will pass those events to a TLSRPT client library and report
+generator that are maintained by sys4. The Postfix implementation supports both
+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
 the TLS client engine. With "smtp_tls_connection_reuse = yes", the smtp(8)
@@ -77,23 +87,46 @@ main.cf like this:
 The smtp_tlsrpt_socket_name parameter specifies an absolute pathname, or a
 pathname that is relative to $queue_directory.
 
-A good socket location would be under $queue_directory/run/tlsrpt or
-$queue_directory/var/run/tlsrpt. These can then be configured in Postfix as a
-relative pathname (run/tlsrpt/tlsrpt.sock or var/run/tlsrpt/tlsrpt.sock) so
-that the same name will work with and without Postfix chroot support. Do not
-specify a location under directory that is already used by Postfix programs.
-Only Postfix programs should create sockets there.
+    Note: the socket location is still to be determined. A good socket location
+    would be under $queue_directory, for example: (smtp_tlsrpt_socket_name =
+    run/tlsrpt/tlsrpt.sock or smtp_tlsrpt_socket_name = var/run/tlsrpt/
+    tlsrpt.sock). Such names will work with and without Postfix chroot support.
+    Do not specify a location under a directory (private, public, ...) that is
+    already used by Postfix programs. Only Postfix programs should create
+    sockets there.
+
+For obvious reasons, RFC 8460 suggests not to enforce strict TLS security when
+sending daily success/failure summaries via email. Postfix currently does not
+have a mechanism to request this when submitting an email message. For initial
+tests a transport map may take care of this.
+
+    /etc/postfix/main.cf:
+        transport_maps = hash:/etc/postfix/transport
+
+    /etc/postfix/transport:
+        /^\Qsts-reports@gmail.com\E$/       allow-plaintext
+        /^\Qsmtp-tls-report@sys4.de\E$/     allow-plaintext
+        ...
+
+    /etc/postfix/master.cf:
+        allow-plaintext .. .. .. .. .. .. .. smtp
+            -o smtp_tls_security_level=may
+            -o smtp_tls_policy_maps=
+
+The ^ and $ prevent false matches, and the \Q and \E disable special
+characters.
 
 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
-TLSRPT support expects a response with the usual security level and matching
-requirements, plus any applicable name=value attributes described below.
-Specify { name = value } when a value may contain whitespace.
+expects a response with the usual security level and matching requirements,
+plus any applicable name=value attributes described below. Specify { name =
+value } when a value may contain whitespace.
 
     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),
-    but it will not use most attributes except ttl and policy_failure.
+    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.
 
@@ -150,24 +183,16 @@ datatracker.ietf.org/doc/html/rfc8460#section-4.5.
 
 L\bLi\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
 
-The following limitations exist primarily because some errors may be reported
-by a Postfix smtp(8) client process, and some errors by a Postfix tlsproxy(8)
-process. It is too difficult to propagate TLSRPT client library state between
-processes.
-
-The Postfix TLSRPT client reports one final status (either 'success' or
-'failure') for each MTA that it is able to connect to. It cannot report a final
-status 'success' with some recoverable 'failure'. Specifically:
-
-  * The Postfix TLSRPT client can report either successful TLS policy
-    compliance, or an unrecoverable failure that prevents TLS policy compliance
-    (examples: all TLSA records are unusable, or some PKI error during
-    certificate verification).
+The Postfix TLSRPT implementation reports at most one final TLS handshake
+status (either 'success' or 'failure') per connection. Postfix TLSRPT cannot
+report a failure and then later report a final status of 'success' for that
+same connection. The reason is that it's too complicated to filter TLS errors
+and to report error details from the TLS engine back to the SMTP protocol
+engine. It just is not how Postfix works internally.
 
-  * The Postfix TLSRPT client must not be used to report a potentially
-    recoverable failure such as a non-parsable TLSA record, because some other
-    TLSA record for the same host may still allow successful TLS policy
-    compliance.
+The Postfix TLSRPT implementation reports only TLS handshake success or
+failure. It does not report failure to connect, or connections that break after
+a successful TLS handshake.
 
 C\bCr\bre\bed\bdi\bit\bts\bs
 
diff --git a/postfix/TODO-TLSRPT b/postfix/TODO-TLSRPT
new file mode 100644 (file)
index 0000000..c22ad13
--- /dev/null
@@ -0,0 +1,29 @@
+Functionality
+=============
+
+There needs to be a way to force "smtp_tls_security_level=may"
+for rmail deliveries of daily TLSRPT summaries.
+
+Paranoia
+=========
+
+Should there be a check that the TLSRPT policy for domain FOO 
+has an 'rua' field that contains FOO?
+
+Paranoia: in IPC protocols base64 encode data that is not fully vetted.
+TLSRPT_WRAPPER.rpt_policy
+TLSRPT_WRAPPER.policy strings
+TLSRPT_WRAPPER.ehlo_cmd string.
+
+Code health
+===========
+Remove the trw_report_failure() additional_info argument. This is
+always null.
+
+Need to add a hex_code test for HEX_ENCODE_FLAG_APPEND.
+
+Deduplicate the code in sane_sockaddr_to_hostaddr(). It also appears in
+haproxy_srvr.c, normalize_mailhost_addr.c, and in postscreen_endpt.c.
+
+Need unit tests for smtp_tlsrpt.c and tlstrpd_wrapper.c. This
+requires infrastructure.
index f2112a779ba6c4fa0ac8aa3da179f05141a11c7f..baa23fdd1d1f0bc145cc115a8a9c41c49bb9432f 100644 (file)
@@ -8,6 +8,13 @@ Wish list:
 
        Add tests for Message-ID extraction in the cleanup daemon.
 
+       When debug logging is enabled, dict_db_open() logs a newline
+       character after the version info.
+
+       postsuper fails to write the maillog file while Postfix is down
+       (the fallback to 'direct write' happens after an irreversible
+       set_ugid() call).
+
        The postdrop code should be more explicit about what
        attrributes it will pass through. rec_attr_map() is not
        supposed to be an approver.
index 7c0749daf8cf35345647517f6b93671a57792aa0..c25e474eb2cbedca3ba31684f4dc4ee745403356 100644 (file)
@@ -38,15 +38,22 @@ receiving domain can publish a policy in DNS to request daily summary
 reports for successful and failed TLS connections to that domain.
 Support for TLSRPT was added in Postfix 3.10. </p>
 
-<p> When Postfix TLSRPT support is enabled (with "<a href="postconf.5.html#smtp_tlsrpt_enable">smtp_tlsrpt_enable</a>
-= yes"), the Postfix SMTP and TLS clients engines will generate
-"success" and "failure" events, and will pass those events to a
-TLSRPT client library and report generator that are maintained by
-sys4. 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> A policy example looks like this: </p>
 
-<p> The high-level diagram shows how Postfix events are reported
-to domains that publish a TLSRPT policy.
+<blockquote>
+<pre>
+_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:smtp-tls-report@example.com"
+</pre>
+</blockquote>
+
+<p> Translation: email sending systems are requested to generate daily
+summaries of successful and failed SMTP over TLS connections to domain
+<tt>example.com</tt>, and to report those summaries via email to the
+specified address. Instead of <tt>mailto:</tt>, a policy may specify an
+<tt>https:</tt> destination. </p>
+
+<p> The high-level diagram shows how Postfix reports  summaries to
+domains that publish a TLSRPT policy.
 
 <blockquote>
 
@@ -67,8 +74,15 @@ to domains that publish a TLSRPT policy.
 
 </blockquote>
 
+<p> When Postfix TLSRPT support is enabled (with "<a href="postconf.5.html#smtp_tlsrpt_enable">smtp_tlsrpt_enable</a>
+= yes"), the Postfix SMTP and TLS clients engines will generate
+"success" and "failure" events, and will pass those events to a
+TLSRPT client library and report generator that are maintained by
+sys4. 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 <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
+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
 process also implements the TLS client engine. With
 "<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = yes", the <a href="smtp.8.html">smtp(8)</a> client process
 delegates TLS processing to a Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> process. Either
@@ -130,32 +144,64 @@ support in <a href="postconf.5.html">main.cf</a> like this: </p>
 </pre>
 </blockquote>
 
-<p> The <a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> parameter specifies an absolute
-pathname, or a pathname that is relative to $<a href="postconf.5.html#queue_directory">queue_directory</a>. </p>
+<p> The <tt><a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a></tt> parameter specifies an
+absolute pathname, or a pathname that is relative to
+<tt>$<a href="postconf.5.html#queue_directory">queue_directory</a></tt>. </p>
 
-<p> A good socket location would be under $<a href="postconf.5.html#queue_directory">queue_directory</a>/run/tlsrpt
-or $<a href="postconf.5.html#queue_directory">queue_directory</a>/var/run/tlsrpt. These can then be configured
-in Postfix as a relative pathname (run/tlsrpt/tlsrpt.sock or
-var/run/tlsrpt/tlsrpt.sock) so that the same name will work with
-and without Postfix chroot support. Do not specify a location under
-directory that is already used by Postfix programs. Only Postfix
+<blockquote>
+
+<p> Note: the socket location is still to be determined. A good
+socket location would be under <tt>$<a href="postconf.5.html#queue_directory">queue_directory</a></tt>, for
+example: (<tt><a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> = run/tlsrpt/tlsrpt.sock</tt>
+or <tt><a href="postconf.5.html#smtp_tlsrpt_socket_name">smtp_tlsrpt_socket_name</a> = var/run/tlsrpt/tlsrpt.sock</tt>).
+Such names will work with and without Postfix chroot support. Do
+not specify a location under a directory (<tt>private, public,
+...</tt>) that is already used by Postfix programs. Only Postfix
 programs should create sockets there. </p>
 
+</blockquote>
+
+<p> For obvious reasons, <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. Postfix
+currently does not have a mechanism to request this when submitting
+an email message. For initial tests a transport map may take care
+of this. </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
+&nbsp
+/etc/postfix/transport:
+    /^\Qsts-reports@gmail.com\E$/       allow-plaintext
+    /^\Qsmtp-tls-report@sys4.de\E$/     allow-plaintext
+    ...
+&nbsp
+/etc/postfix/<a href="master.5.html">master.cf</a>:
+    allow-plaintext .. .. .. .. .. .. .. 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>=
+</pre>
+</blockquote>
+
+<p> The <tt>^</tt> and <tt>$</tt> prevent false matches, and the
+<tt>\Q</tt> and <tt>\E</tt> disable special characters. </p>
+
 <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 TLSRPT support expects a response with the usual
-security level and matching requirements, plus any applicable
-name=value attributes described below. Specify { name = value }
-when a value may contain whitespace. </p>
+plugin. Postfix expects a response with the usual security level and
+matching requirements, plus any applicable name=value attributes described
+below. Specify { name = value } when a value may contain whitespace. </p>
 
 <blockquote>
 
 <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), but it will not use most attributes except
-<tt>ttl</tt> and <tt>policy_failure</tt>.  </p>
+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>
 
 <p> Note 2: It is an error to specify these attributes for a non-STS
 policy. </p>
@@ -179,7 +225,7 @@ given in <a href="https://datatracker.ietf.org/doc/html/rfc8460#section-4.5">htt
 <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>
+the MTA-STS plugin response. </p> </li>
 
 <li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
 
@@ -235,29 +281,17 @@ policy_failure=sts-webpki-invalid
 
 <h2> <a name="limitations"> Limitations </a></h2>
 
-<p> The following limitations exist primarily because some errors
-may be reported by a Postfix <a href="smtp.8.html">smtp(8)</a> client process, and some errors
-by a Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> process. It is too difficult to propagate
-TLSRPT client library state between processes.</p>
-
-<p> The Postfix TLSRPT client reports one final status (either
-'success' or 'failure') for each MTA that it is able to connect to.
-It cannot report a final status 'success' with some recoverable
-'failure'. Specifically: </p>
-
-<ul>
-
-<li> <p> The Postfix TLSRPT client can report either successful TLS
-policy compliance, or an unrecoverable failure that prevents TLS
-policy compliance (examples: all TLSA records are unusable, or some
-PKI error during certificate verification). <p> </li>
-
-<li> <p> The Postfix TLSRPT client must not be used to report a
-potentially recoverable failure such as a non-parsable TLSA record,
-because some other TLSA record for the same host may still allow
-successful TLS policy compliance. </p> </li>
-
-</ul>
+<p> The Postfix TLSRPT implementation reports at most one final TLS
+handshake status (either 'success' or 'failure') per connection.
+Postfix TLSRPT cannot report a failure and then later report a final
+status of 'success' for that same connection. The reason is that
+it's too complicated to filter TLS errors and to report error details
+from the TLS engine back to the SMTP protocol engine. It just is
+not how Postfix works internally. </p>
+
+<p> The Postfix TLSRPT implementation reports only TLS handshake
+success or failure. It does not report failure to connect, or
+connections that break after a successful TLS handshake. </p>
 
 <h2> <a name="credits"> Credits </a> </h2>
 
index a7da6cb510c7e57854b419a0069103ea407e8da6..610fac87ce593e2d75909c108ca57e7d20ca1bde 100644 (file)
@@ -45,6 +45,8 @@ configuration examples </a>
 
 <li> <a href="FORWARD_SECRECY_README.html"> TLS Forward Secrecy </a>
 
+<li> <a href="TLSRPT_README.html"> TLSRPT Protocol Support </a>
+
 <li> <a href="IPV6_README.html"> IP Version 6 Support </a>
 
 <li> <a href="SMTPUTF8_README.html"> SMTPUTF8 Support </a>
index c254ab97c754e18e09b07e4c3ba6e11b428d0d37..3f9a53d75f7ff0855a4c43a90d943c132579d171 100644 (file)
@@ -20151,21 +20151,27 @@ be using 0.9.6! </dd>
 <DT><b><a name="tls_eecdh_auto_curves">tls_eecdh_auto_curves</a>
 (default: see "postconf -d" output)</b></DT><DD>
 
-<p> The prioritized list of elliptic curves supported by the Postfix
-SMTP client and server.  These curves are used by the Postfix SMTP
-server when "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = auto".  The selected curves must be
-implemented by OpenSSL and be standardized for use in TLS (<a href="https://tools.ietf.org/html/rfc8422">RFC 8422</a>).
-It is unwise to list only "bleeding-edge" curves supported by a small
-subset of clients.  The default list is suitable for most users. </p>
-
-<p> Postfix skips curve names that are unknown to OpenSSL, or that
-are known but not yet implemented.  This makes it possible to
-"anticipate" support for curves that should be used once they become
-available.  In particular, in some OpenSSL versions, the new <a href="https://tools.ietf.org/html/rfc8031">RFC</a>
-<a href="https://tools.ietf.org/html/rfc8031">8031</a> curves "X25519" and "X448" may be known by name, but ECDH
-support for either or both may be missing.  These curves may appear
-in the default value of this parameter, even though they'll only
-be usable with later versions of OpenSSL.  </p>
+<p> The prioritized list of elliptic curves, that should be enabled in the
+Postfix SMTP client and server.  These are used by the Postfix SMTP server when
+"<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = auto".  The selected curves should be implemented
+by OpenSSL and be standardized for use in the TLS "supported groups" extension
+(<a href="https://tools.ietf.org/html/rfc8422">RFC8422</a>, <a href="https://tools.ietf.org/html/rfc8446">RFC8446</a> and <a href="https://tools.ietf.org/html/rfc8447">RFC8447</a>).  Be sure to include at least "x25519" and
+"prime256v1" (the OpenSSL name for "secp256r1", a.k.a. "P-256").  The default
+list is suitable for most users. </p>
+
+<p> On the client side, the first curve listed will be used to construct the
+client's initial TLS 1.3 "keyshare".  If this is not supported by the server,
+the TLS handshake may require an additional round-trip after the server issues
+a HelloRetryRequest (HRR) indicating a suitable mutually supported curve. </p>
+
+<p> Postfix skips curve names that are unknown to OpenSSL, or that are known
+but not yet implemented.  This makes it possible to "anticipate" support for
+curves that should be used once they become available, or to deploy the same
+setting on a server "farm" where not all servers support the same curves.  </p>
+
+<p> As of Postfix 3.10, when compiled with OpenSSL 3.0 or later, the "curve"
+names can be more general key encapsulation mechanisms (KEMs), and/or may be
+loaded from an external "provider" (via a suitable <a href="postconf.5.html#tls_config_file">tls_config_file</a>).  </p>
 
 <p> See also the "<a href="postconf.5.html#tls_ffdhe_auto_groups">tls_ffdhe_auto_groups</a>" parameter, which supports
 customizing the list of FFDHE groups enabled with TLS 1.3.  That setting
@@ -20320,10 +20326,10 @@ EC key agreement in OpenSSL 3.0 and later.  Note that at least one of
 this is required by OpenSSL 3.0.  If both are inadvertently set empty,
 Postfix will fall back to the compiled-in defaults. </p>
 
-<p> All the default groups and EC curves should sufficiently strong
-to make "pruning" the defaults unwise.  At a minimum, "X25519" and
-"P-256" (a.k.a. "prime256v1") should be among the enabled EC curves,
-while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
+<p> All the default groups and EC curves should sufficiently strong to make
+"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
+OpenSSL name for "secp256r1", a.k.a. "P-256") should be among the enabled EC
+curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
 
 <p> This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later. </p>
index 05bf424aaf93454d354183d8c14785c564289736..571e624bc63355b06283b09dd6812818c4de3499 100644 (file)
@@ -13999,21 +13999,27 @@ Postfix >= 3.4. See \fBSSL_CTX_set_options\fR(3).
 .PP
 This feature is available in Postfix 2.8 and later.
 .SH tls_eecdh_auto_curves (default: see "postconf \-d" output)
-The prioritized list of elliptic curves supported by the Postfix
-SMTP client and server.  These curves are used by the Postfix SMTP
-server when "smtpd_tls_eecdh_grade = auto".  The selected curves must be
-implemented by OpenSSL and be standardized for use in TLS (RFC 8422).
-It is unwise to list only "bleeding\-edge" curves supported by a small
-subset of clients.  The default list is suitable for most users.
-.PP
-Postfix skips curve names that are unknown to OpenSSL, or that
-are known but not yet implemented.  This makes it possible to
-"anticipate" support for curves that should be used once they become
-available.  In particular, in some OpenSSL versions, the new RFC
-8031 curves "X25519" and "X448" may be known by name, but ECDH
-support for either or both may be missing.  These curves may appear
-in the default value of this parameter, even though they'll only
-be usable with later versions of OpenSSL.
+The prioritized list of elliptic curves, that should be enabled in the
+Postfix SMTP client and server.  These are used by the Postfix SMTP server when
+"smtpd_tls_eecdh_grade = auto".  The selected curves should be implemented
+by OpenSSL and be standardized for use in the TLS "supported groups" extension
+(RFC8422, RFC8446 and RFC8447).  Be sure to include at least "x25519" and
+"prime256v1" (the OpenSSL name for "secp256r1", a.k.a. "P\-256").  The default
+list is suitable for most users.
+.PP
+On the client side, the first curve listed will be used to construct the
+client's initial TLS 1.3 "keyshare".  If this is not supported by the server,
+the TLS handshake may require an additional round\-trip after the server issues
+a HelloRetryRequest (HRR) indicating a suitable mutually supported curve.
+.PP
+Postfix skips curve names that are unknown to OpenSSL, or that are known
+but not yet implemented.  This makes it possible to "anticipate" support for
+curves that should be used once they become available, or to deploy the same
+setting on a server "farm" where not all servers support the same curves.
+.PP
+As of Postfix 3.10, when compiled with OpenSSL 3.0 or later, the "curve"
+names can be more general key encapsulation mechanisms (KEMs), and/or may be
+loaded from an external "provider" (via a suitable tls_config_file).
 .PP
 See also the "tls_ffdhe_auto_groups" parameter, which supports
 customizing the list of FFDHE groups enabled with TLS 1.3.  That setting
@@ -14130,10 +14136,10 @@ EC key agreement in OpenSSL 3.0 and later.  Note that at least one of
 this is required by OpenSSL 3.0.  If both are inadvertently set empty,
 Postfix will fall back to the compiled\-in defaults.
 .PP
-All the default groups and EC curves should sufficiently strong
-to make "pruning" the defaults unwise.  At a minimum, "X25519" and
-"P\-256" (a.k.a. "prime256v1") should be among the enabled EC curves,
-while "dhe2048" and "dhe3072" should be among the FFDHE groups.
+All the default groups and EC curves should sufficiently strong to make
+"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
+OpenSSL name for "secp256r1", a.k.a. "P\-256") should be among the enabled EC
+curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups.
 .PP
 This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later.
index f5f9f238e278cfe756c49d84c0cc230078b2095c..e869a2e81f3fd3a5284f3cba84a65c1513f2a3c4 100644 (file)
@@ -38,15 +38,22 @@ receiving domain can publish a policy in DNS to request daily summary
 reports for successful and failed TLS connections to that domain.
 Support for TLSRPT was added in Postfix 3.10. </p>
 
-<p> When Postfix TLSRPT support is enabled (with "smtp_tlsrpt_enable
-= yes"), the Postfix SMTP and TLS clients engines will generate
-"success" and "failure" events, and will pass those events to a
-TLSRPT client library and report generator that are maintained by
-sys4. The Postfix implementation supports both DANE (Postfix built-in)
-and MTA-STS (through an smtp_tls_policy_maps plug-in). </p>
+<p> A policy example looks like this: </p>
 
-<p> The high-level diagram shows how Postfix events are reported
-to domains that publish a TLSRPT policy.
+<blockquote>
+<pre>
+_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:smtp-tls-report@example.com"
+</pre>
+</blockquote>
+
+<p> Translation: email sending systems are requested to generate daily
+summaries of successful and failed SMTP over TLS connections to domain
+<tt>example.com</tt>, and to report those summaries via email to the
+specified address. Instead of <tt>mailto:</tt>, a policy may specify an
+<tt>https:</tt> destination. </p>
+
+<p> The high-level diagram shows how Postfix reports  summaries to
+domains that publish a TLSRPT policy.
 
 <blockquote>
 
@@ -67,8 +74,15 @@ to domains that publish a TLSRPT policy.
 
 </blockquote>
 
+<p> When Postfix TLSRPT support is enabled (with "smtp_tlsrpt_enable
+= yes"), the Postfix SMTP and TLS clients engines will generate
+"success" and "failure" events, and will pass those events to a
+TLSRPT client library and report generator that are maintained by
+sys4. The Postfix implementation supports both 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
+engine. With "smtp_tls_connection_reuse = no", the smtp(8) client
 process also implements the TLS client engine. With
 "smtp_tls_connection_reuse = yes", the smtp(8) client process
 delegates TLS processing to a Postfix tlsproxy(8) process. Either
@@ -130,32 +144,64 @@ smtp_tlsrpt_socket_name = /path/to/socket
 </pre>
 </blockquote>
 
-<p> The smtp_tlsrpt_socket_name parameter specifies an absolute
-pathname, or a pathname that is relative to $queue_directory. </p>
+<p> The <tt>smtp_tlsrpt_socket_name</tt> parameter specifies an
+absolute pathname, or a pathname that is relative to
+<tt>$queue_directory</tt>. </p>
 
-<p> A good socket location would be under $queue_directory/run/tlsrpt
-or $queue_directory/var/run/tlsrpt. These can then be configured
-in Postfix as a relative pathname (run/tlsrpt/tlsrpt.sock or
-var/run/tlsrpt/tlsrpt.sock) so that the same name will work with
-and without Postfix chroot support. Do not specify a location under
-directory that is already used by Postfix programs. Only Postfix
+<blockquote>
+
+<p> Note: the socket location is still to be determined. A good
+socket location would be under <tt>$queue_directory</tt>, for
+example: (<tt>smtp_tlsrpt_socket_name = run/tlsrpt/tlsrpt.sock</tt>
+or <tt>smtp_tlsrpt_socket_name = var/run/tlsrpt/tlsrpt.sock</tt>).
+Such names will work with and without Postfix chroot support. Do
+not specify a location under a directory (<tt>private, public,
+...</tt>) that is already used by Postfix programs. Only Postfix
 programs should create sockets there. </p>
 
+</blockquote>
+
+<p> For obvious reasons, RFC 8460 suggests not to enforce strict
+TLS security when sending daily success/failure summaries via email. Postfix
+currently does not have a mechanism to request this when submitting
+an email message. For initial tests a transport map may take care
+of this. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    transport_maps = hash:/etc/postfix/transport
+&nbsp
+/etc/postfix/transport:
+    /^\Qsts-reports@gmail.com\E$/       allow-plaintext
+    /^\Qsmtp-tls-report@sys4.de\E$/     allow-plaintext
+    ...
+&nbsp
+/etc/postfix/master.cf:
+    allow-plaintext .. .. .. .. .. .. .. smtp
+        -o smtp_tls_security_level=may
+        -o smtp_tls_policy_maps=
+</pre>
+</blockquote>
+
+<p> The <tt>^</tt> and <tt>$</tt> prevent false matches, and the
+<tt>\Q</tt> and <tt>\E</tt> disable special characters. </p>
+
 <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 TLSRPT support expects a response with the usual
-security level and matching requirements, plus any applicable
-name=value attributes described below. Specify { name = value }
-when a value may contain whitespace. </p>
+plugin. Postfix expects a response with the usual security level and
+matching requirements, plus any applicable name=value attributes described
+below. Specify { name = value } when a value may contain whitespace. </p>
 
 <blockquote>
 
 <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), but it will not use most attributes except
-<tt>ttl</tt> and <tt>policy_failure</tt>.  </p>
+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>
 
 <p> Note 2: It is an error to specify these attributes for a non-STS
 policy. </p>
@@ -179,7 +225,7 @@ given in https://datatracker.ietf.org/doc/html/rfc8460#section-4.5.
 <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>
+the MTA-STS plugin response. </p> </li>
 
 <li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
 
@@ -235,29 +281,17 @@ policy_failure=sts-webpki-invalid
 
 <h2> <a name="limitations"> Limitations </a></h2>
 
-<p> The following limitations exist primarily because some errors
-may be reported by a Postfix smtp(8) client process, and some errors
-by a Postfix tlsproxy(8) process. It is too difficult to propagate
-TLSRPT client library state between processes.</p>
-
-<p> The Postfix TLSRPT client reports one final status (either
-'success' or 'failure') for each MTA that it is able to connect to.
-It cannot report a final status 'success' with some recoverable
-'failure'. Specifically: </p>
-
-<ul>
-
-<li> <p> The Postfix TLSRPT client can report either successful TLS
-policy compliance, or an unrecoverable failure that prevents TLS
-policy compliance (examples: all TLSA records are unusable, or some
-PKI error during certificate verification). <p> </li>
-
-<li> <p> The Postfix TLSRPT client must not be used to report a
-potentially recoverable failure such as a non-parsable TLSA record,
-because some other TLSA record for the same host may still allow
-successful TLS policy compliance. </p> </li>
-
-</ul>
+<p> The Postfix TLSRPT implementation reports at most one final TLS
+handshake status (either 'success' or 'failure') per connection.
+Postfix TLSRPT cannot report a failure and then later report a final
+status of 'success' for that same connection. The reason is that
+it's too complicated to filter TLS errors and to report error details
+from the TLS engine back to the SMTP protocol engine. It just is
+not how Postfix works internally. </p>
+
+<p> The Postfix TLSRPT implementation reports only TLS handshake
+success or failure. It does not report failure to connect, or
+connections that break after a successful TLS handshake. </p>
 
 <h2> <a name="credits"> Credits </a> </h2>
 
index c8704c0d02dd6217ed7cc53a6f814ca966febfef..92cdba2c161f402bf37d35bd56a5f46ec4b9ff1c 100644 (file)
@@ -13364,21 +13364,27 @@ parameter. See there for details. </p>
 
 %PARAM tls_eecdh_auto_curves see "postconf -d" output
 
-<p> The prioritized list of elliptic curves supported by the Postfix
-SMTP client and server.  These curves are used by the Postfix SMTP
-server when "smtpd_tls_eecdh_grade = auto".  The selected curves must be
-implemented by OpenSSL and be standardized for use in TLS (RFC 8422).
-It is unwise to list only "bleeding-edge" curves supported by a small
-subset of clients.  The default list is suitable for most users. </p>
-
-<p> Postfix skips curve names that are unknown to OpenSSL, or that
-are known but not yet implemented.  This makes it possible to
-"anticipate" support for curves that should be used once they become
-available.  In particular, in some OpenSSL versions, the new RFC
-8031 curves "X25519" and "X448" may be known by name, but ECDH
-support for either or both may be missing.  These curves may appear
-in the default value of this parameter, even though they'll only
-be usable with later versions of OpenSSL.  </p>
+<p> The prioritized list of elliptic curves, that should be enabled in the
+Postfix SMTP client and server.  These are used by the Postfix SMTP server when
+"smtpd_tls_eecdh_grade = auto".  The selected curves should be implemented
+by OpenSSL and be standardized for use in the TLS "supported groups" extension
+(RFC8422, RFC8446 and RFC8447).  Be sure to include at least "x25519" and
+"prime256v1" (the OpenSSL name for "secp256r1", a.k.a. "P-256").  The default
+list is suitable for most users. </p>
+
+<p> On the client side, the first curve listed will be used to construct the
+client's initial TLS 1.3 "keyshare".  If this is not supported by the server,
+the TLS handshake may require an additional round-trip after the server issues
+a HelloRetryRequest (HRR) indicating a suitable mutually supported curve. </p>
+
+<p> Postfix skips curve names that are unknown to OpenSSL, or that are known
+but not yet implemented.  This makes it possible to "anticipate" support for
+curves that should be used once they become available, or to deploy the same
+setting on a server "farm" where not all servers support the same curves.  </p>
+
+<p> As of Postfix 3.10, when compiled with OpenSSL 3.0 or later, the "curve"
+names can be more general key encapsulation mechanisms (KEMs), and/or may be
+loaded from an external "provider" (via a suitable tls_config_file).  </p>
 
 <p> See also the "tls_ffdhe_auto_groups" parameter, which supports
 customizing the list of FFDHE groups enabled with TLS 1.3.  That setting
@@ -13420,10 +13426,10 @@ EC key agreement in OpenSSL 3.0 and later.  Note that at least one of
 this is required by OpenSSL 3.0.  If both are inadvertently set empty,
 Postfix will fall back to the compiled-in defaults. </p>
 
-<p> All the default groups and EC curves should sufficiently strong
-to make "pruning" the defaults unwise.  At a minimum, "X25519" and
-"P-256" (a.k.a. "prime256v1") should be among the enabled EC curves,
-while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
+<p> All the default groups and EC curves should sufficiently strong to make
+"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
+OpenSSL name for "secp256r1", a.k.a. "P-256") should be among the enabled EC
+curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
 
 <p> This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later. </p>
index 171198f88412bd2da122499af98ea0e7a2f3bdf5..20f62cf10f64751ee4b18513c3fc2b4ad95355aa 100644 (file)
@@ -1615,6 +1615,14 @@ milterfrom
 canonicalization
 Orlitzky
 Typofix
+Deduplicate
+KEM
+HelloRetryRequest
+HRR
+KEMs
+kex
+keyshare
+pkg
 RPT
 TLSRPT
 TLSRPTv
@@ -1640,3 +1648,4 @@ RPC
 datatracker
 webpki
 parsable
+mailto
index 62bac0323649eefad5da84b3e67a6a8c46357111..d0e35864a0e44c9c5381381276782cabddc9978e 100644 (file)
@@ -339,6 +339,6 @@ address  address string length
  policies policy policy type 
  policies policy policy string Ignored if the tls_policy_type
  policies policy policy domain 
-additional_detail  additional_detail 
+additional_info  additional_info 
 ignored  ignored 
 USE_TLSRPT  USE_TLSRPT 
index 3e1bff20c4039871fe8df002ba9e2e7a39773024..70a09313adf692da0e1ccde8b9b572ac02d245c0 100644 (file)
@@ -130,3 +130,4 @@ proto  proto mysql_table proto pgsql_table proto ldap_table
  unimplemented commands in the SMTP server File smtpd smtpd c 
  cleanup cleanup h cleanup cleanup_extracted c 
  File postcat postcat c 
+ Files src tls tls h src tls tls_dh c src tls tls_misc c 
index fbf3bda6bae208b0c92a25e774a9a976bb34578e..0c6b3e7aa8cf523a56f1df73ba1a9b89b9bfbd82 100644 (file)
@@ -359,4 +359,4 @@ Postfix  Postfix can use MongoDB as a source for any of its lookups aliases 5 vi
  CCARGS CCARGS DHAS_MONGODB I usr include libmongoc 1 0 
  dt dt dd 2 Also enable verbose logging in the Postfix TLS
 Postfix  Postfix legacy TLS Support
- A good socket location would be under queue_directory run tlsrpt or queue_directory var run tlsrpt These can then be configured in Postfix as a relative pathname run tlsrpt tlsrpt sock or var run tlsrpt tlsrpt sock so that the same name will
+ Note the socket location is still to be determined A good socket location would be under queue_directory for example smtp_tlsrpt_socket_name run tlsrpt tlsrpt sock or smtp_tlsrpt_socket_name var run tlsrpt tlsrpt sock Such names
index 65f9fa06219907731a9b1732975ce632bf2b6f9a..0bb4f3963e343d49cea36f074042bb65d7e2fe14 100644 (file)
@@ -384,3 +384,6 @@ sts
 STS
 STSv
 Sys
+Qsmtp
+Qsts
+gmail
index 8b52145b0ccdafa6726463ece8b24acdef7c5025..70add837cb51d77bda04d1a4aef03fa915ce9c74 100644 (file)
@@ -3409,13 +3409,13 @@ extern char *var_tls_null_clist;
 #else
 #define DEF_TLS_EECDH_AUTO_3 ""
 #endif
-#if defined(SN_secp521r1) && defined(NID_secp521r1)
-#define DEF_TLS_EECDH_AUTO_4 SN_secp521r1 " "
+#if defined(SN_secp384r1) && defined(NID_secp384r1)
+#define DEF_TLS_EECDH_AUTO_4 SN_secp384r1
 #else
 #define DEF_TLS_EECDH_AUTO_4 ""
 #endif
-#if defined(SN_secp384r1) && defined(NID_secp384r1)
-#define DEF_TLS_EECDH_AUTO_5 SN_secp384r1
+#if defined(SN_secp521r1) && defined(NID_secp521r1)
+#define DEF_TLS_EECDH_AUTO_5 SN_secp521r1 " "
 #else
 #define DEF_TLS_EECDH_AUTO_5 ""
 #endif
index 52a5cc1adf9aeb0bf1998cc7154e97e973ced7e7..95fbd9bfdf18ee3bc1a8af031bc78aadddef70a6 100644 (file)
@@ -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      "20240917"
+#define MAIL_RELEASE_DATE      "20240923"
 #define MAIL_VERSION_NUMBER    "3.10"
 
 #ifdef SNAPSHOT
index 193588ef410802903e9ddd08bb9760e02f46beb8..75571f7f2cc64565720d15cac8b2a687a4f3f6a0 100644 (file)
@@ -836,7 +836,7 @@ static int starttls(STATE *state)
                                     matchargv = state->match,
                                     mdalg = state->mdalg,
                                     tlsrpt = 0,
-                                    fail_type = 0,
+                                    ffail_type = 0,
                                     dane = state->ddane ?
                                     state->ddane : state->dane);
 
@@ -942,7 +942,7 @@ static int starttls(STATE *state)
                             matchargv = state->match,
                             mdalg = state->mdalg,
                             tlsrpt = 0,
-                            fail_type = 0,
+                            ffail_type = 0,
                          dane = state->ddane ? state->ddane : state->dane);
     }                                          /* tlsproxy_mode */
     vstring_free(cipher_exclusions);
index df26d64baa791b6172d46ef5960307c95b41c94c..ea943fe779f71f3b5969accaa3e6d09478c6384f 100644 (file)
@@ -1092,6 +1092,12 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
                session->state = state;
 #ifdef USE_TLS
                session->tls_nexthop = domain;
+
+               /*
+                * Update TLSRPT state even if this is a reused SMTP
+                * connection. If for some unlikely reason we must report a
+                * problem, then we must report correct information.
+                */
 #ifdef USE_TLSRPT
                if (state->tlsrpt && state->tls->level > TLS_LEV_NONE) {
                    smtp_tlsrpt_set_tls_policy(state);
index bdca86ce85622cc6d0b184aa135cc7d816c67beb..976598998e69d84bff444c89eb254206bd26ec2d 100644 (file)
@@ -78,6 +78,9 @@
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
 /*
+/*     Wietse Venema
+/*     porcupine.org
+/*
 /*     Pipelining code in cooperation with:
 /*     Jon Ribbens
 /*     Oaktree Internet Solutions Ltd.,
@@ -481,7 +484,7 @@ int     smtp_helo(SMTP_STATE *state)
 #ifdef USE_TLSRPT
            if (state->tlsrpt
                && (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0)
-               trw_set_ehlo_resp(state->tlsrpt, resp->str);
+               smtp_tlsrpt_set_ehlo_resp(state, resp->str);
 #endif
        }
        if ((session->features & SMTP_FEATURE_ESMTP) == 0) {
@@ -815,7 +818,7 @@ int     smtp_helo(SMTP_STATE *state)
                if (state->tlsrpt)
                    trw_report_failure(state->tlsrpt,
                                       TLSRPT_STARTTLS_NOT_SUPPORTED,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                        /* failure_reason= */ (char *) 0);
 #endif
                return (smtp_site_fail(state, STR(iter->host), resp,
@@ -839,7 +842,7 @@ int     smtp_helo(SMTP_STATE *state)
                if (state->tlsrpt)
                    trw_report_failure(state->tlsrpt,
                                       TLSRPT_STARTTLS_NOT_SUPPORTED,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                        /* failure_reason= */ (char *) 0);
 #endif
                return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
@@ -974,7 +977,7 @@ static int smtp_start_tls(SMTP_STATE *state)
 #else
                                     tlsrpt = 0,
 #endif
-                                    fail_type = 0,
+                                    ffail_type = 0,
                                     dane = state->tls->dane);
 
        /*
@@ -1103,7 +1106,7 @@ static int smtp_start_tls(SMTP_STATE *state)
 #else
                             tlsrpt = 0,
 #endif
-                            fail_type = state->tls->ext_policy_failure,
+                            ffail_type = state->tls->ext_policy_failure,
                             dane = state->tls->dane);
 
        /*
@@ -1175,12 +1178,12 @@ static int smtp_start_tls(SMTP_STATE *state)
                if (!TLS_CERT_IS_TRUSTED(session->tls_context)) {
                    (void) trw_report_failure(state->tlsrpt,
                                              TLSRPT_CERTIFICATE_NOT_TRUSTED,
-                                       /* additional_detail= */ (char *) 0,
+                                         /* additional_info= */ (char *) 0,
                                          /* failure_reason= */ (char *) 0);
                } else {
                    (void) trw_report_failure(state->tlsrpt,
                                           TLSRPT_CERTIFICATE_HOST_MISMATCH,
-                                       /* additional_detail= */ (char *) 0,
+                                         /* additional_info= */ (char *) 0,
                                          /* failure_reason= */ (char *) 0);
                }
            }
@@ -1194,10 +1197,12 @@ static int smtp_start_tls(SMTP_STATE *state)
      * Create a TLSRPT success report only if the TLS engine has not reported
      * a failure (For example, the TLS handshake may be successful, but the
      * security level was downgraded from opportunistic or half "dane" to
-     * "encrypt").
+     * "encrypt"), and only if the TLS session and SMTP connection are new.
      */
 #ifdef USE_TLSRPT
-    if (state->tlsrpt && session->tls_context->rpt_reported == 0)
+    if (state->tlsrpt && session->tls_context->rpt_reported == 0
+       && session->tls_context->session_reused == 0    /* New TLS */
+       && session->reuse_count == 0)           /* New SMTP */
        (void) trw_report_success(state->tlsrpt);
 #endif
 
index f22e51410f99c07944b169538dcbbf7852a23b52..5015094965abe8ca34f5279d0a78a9f7f8146a69 100644 (file)
@@ -454,6 +454,7 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
            tls->ext_policy_type = mystrdup(val);
            continue;
        }
+       /* Only one instance per policy. */
        if (!strcasecmp(name, EXT_POLICY_DOMAIN)) {
            if (tls->ext_policy_domain) {
                msg_warn("%s: attribute \"%s\" is specified multiple times",
index f81f60872fa32ebc041bfac48cb6f363c7691ebd..954bf9298b5e5c8efb853d519ad8dd155c757e7d 100644 (file)
 /*     SMTP_STATE *state,
 /*     const char *ehlo_resp)
 /* DESCRIPTION
-/*     This module collects TLSRPT policy information and selected SMTP
-/*     protocol engine state in a TLSRPT_WRAPPER object. This will be
-/*     passed to (possibly remote) TLS protocol engine, so that it
-/*     can report a TLS error to a TLSRPT library. The SMTP protocol
-/*     engine uses the information to report a TLS error or success.
+/*     This module populates a TLSRPT_WRAPPER object with  a)
+/*     remote TLSRPT policy information, b) remote TLSA or STS policy
+/*     information, and c) selected SMTP connection information. This
+/*     object is passed to a TLS protocol engine, which may run in a
+/*     different process than the SMTP protocol engine. The TLS protocol
+/*     engine uses the TLSRPT_WRAPPER object to report a TLS handshake
+/*     error to a TLSRPT library. The SMTP protocol engine uses the
+/*     object to report a TLS handshake error or success.
 /*
-/*     smtp_tls_post_jail() does configuration sanity checks and
-/*     returns 0 if successful, i.e. TLSRPT support is properly
+/*     smtp_tls_post_jail() does configuration sanity checks and returns
+/*     0 if successful, i.e. TLSRPT support is properly
 /*     configured. Otherwise it returns -1 and logs a warning. Arguments:
 /* .IP sockname_pname
-/*     The name of a configuration parameter for the endpoint that is
-/*     managed by TLSRPT infrastructure. This is used in a diagnostic
-/*     message.
+/*     The name of a configuration parameter for the endpoint that
+/*     is managed by TLSRPT infrastructure. This name is used in a
+/*     diagnostic message.
 /* .IP sockname_pval
 /*     The value of said parameter.
 /* .PP
-/*     smtp_tlsrpt_create_wrapper() destroys any TLSRPT_WRAPPER
-/*     referenced by state->tlsrpt, and looks for a TLSRPT
-/*     policy for the specified domain. If one policy exists,
-/*     smtp_tlsrpt_create_wrapper() attaches a TLSRPT_WRAPPER instance
-/*     to state->tlsrpt. Otherwise, state->tlsrpt will be null, and
-/*     other smtp_tlsrpt_* calls must not be made. The TLSRPT_WRAPPER
-/*     instance may be reused for different SMTP connections with the
-/*     same TLSRPT policy domain. Arguments:
+/*     smtp_tlsrpt_create_wrapper() destroys a TLSRPT_WRAPPER referenced
+/*     by state->tlsrpt, and looks for a TLSRPT policy for the specified
+/*     domain. If one policy exists, smtp_tlsrpt_create_wrapper()
+/*     attaches a TLSRPT_WRAPPER instance to state->tlsrpt. Otherwise,
+/*     state->tlsrpt will be null, and other smtp_tlsrpt_* calls must not
+/*     be made. The TLSRPT_WRAPPER instance may be reused for different
+/*     SMTP connections for the same TLSRPT policy domain. Arguments:
 /* .IP domain
 /*     The name of a domain that may publish a TLSRPT policy. An
 /*     internationalized domain name may be in U-label or A-label form
-/*     (it will be converted to A-label internally).
+/*     (the U-label form will be converted to A-label internally).
 /* .PP
-/*     smtp_tlsrpt_set_tls_policy() updates the TLSRPT_WRAPPER with
-/*     DANE or STS TLS policy information, and clears information
-/*     that was added with smtp_tlsrpt_set_tcp_connection() or
-/*     smtp_tlsrpt_set_ehlo_resp().
+/*     smtp_tlsrpt_set_tls_policy() updates the TLSRPT_WRAPPER
+/*     object with DANE or STS TLS policy information, and clears
+/*     information that was added with smtp_tlsrpt_set_tcp_connection()
+/*     or smtp_tlsrpt_set_ehlo_resp().
 /* .PP
-/*     smtp_tlsrpt_set_tcp_connection() updates the TLSRPT_WRAPPER with
-/*     TCP connection properties.
+/*     smtp_tlsrpt_set_tcp_connection() updates the TLSRPT_WRAPPER
+/*     object with TCP connection properties.
 /* .PP
-/*     smtp_tlsrpt_set_ehlo_resp() updates the TLSRPT_WRAPPER with the
-/*     SMTP server's EHLO response.
+/*     smtp_tlsrpt_set_ehlo_resp() updates the TLSRPT_WRAPPER object
+/*     with the SMTP server's EHLO response.
 /* BUGS
 /*     This module inherits all limitations from tlsrpt_wrapper(3).
 /* SEE ALSO
@@ -118,7 +120,7 @@ int     smtp_tlsrpt_post_jail(const char *sockname_pname,
                                      const char *sockname_pval)
 {
     if (smtp_dns_support == SMTP_DNS_DISABLED) {
-       msg_warn("Cannot enable TLRPT support: DNS is disabled");
+       msg_warn("Cannot enable %s: DNS is disabled", smtp_tlsrpt_support);
        return (-1);
     }
     if (*sockname_pval == 0) {
@@ -152,8 +154,8 @@ static DNS_RR *smtp_tlsrpt_find_policy(const char *adomain)
      * Lexical features: As specified in RFC 8460, a TLSRPT policy record
      * must start with a version field ("v=TLSRPTv1") followed by *WSP;*WSP
      * and at least one other field (we must not assume that the second field
-     * will be "rua"). We leave further validation to the TLSRPT library,
-     * where it belongs.
+     * will be "rua"). We leave further validation to the code that actually
+     * needs it.
      */
 #define TLSRPTv1_MAGIC         "v=TLSRPTv1"
 #define TLSRPTv1_MAGIC_LEN     (sizeof(TLSRPTv1_MAGIC) - 1)
@@ -184,7 +186,7 @@ static DNS_RR *smtp_tlsrpt_find_policy(const char *adomain)
 
            next = rr->next;
            if (strncmp(rr->data, TLSRPTv1_MAGIC, TLSRPTv1_MAGIC_LEN) != 0)
-               /* Ignore non-TLSRPT info. */
+               /* Ignore non-TLSRPTv1 info. */
                continue;
            cp = rr->data + TLSRPTv1_MAGIC_LEN;
 
@@ -197,9 +199,10 @@ static DNS_RR *smtp_tlsrpt_find_policy(const char *adomain)
                continue;
            }
            if (rr_result) {
-               msg_warn("%s: Too many policies for %s",
+               msg_warn("%s: Too many TLSRPT policies for %s",
                         smtp_tlsrpt_support, adomain);
                dns_rr_free(rr_result);
+               rr_result = 0;
                break;
            }
            rr_result = rr;
@@ -383,7 +386,7 @@ void    smtp_tlsrpt_set_tcp_connection(SMTP_STATE *state)
 
     /*
      * Get the IP client address string. The Postfix SMTP_ITERATOR already
-     * contains strings with other connection information.
+     * contains strings with server-side connection information.
      */
     if (getsockname(vstream_fileno(session->stream),
                    (struct sockaddr *) &addr_storage,
index 3d3bf6e293f0fc28c03030d1eaed467668e4bf2f..ce1a37ee9cbd1d812095427646957116438fce10 100644 (file)
@@ -208,6 +208,7 @@ tls_dane.o: ../../include/vstring.h
 tls_dane.o: tls.h
 tls_dane.o: tls_dane.c
 tls_dh.o: ../../include/argv.h
+tls_dh.o: ../../include/been_here.h
 tls_dh.o: ../../include/check_arg.h
 tls_dh.o: ../../include/dns.h
 tls_dh.o: ../../include/mail_params.h
index b3e5b7cb2be92c7fdd6962a0eb5229bae30f32eb..96eb5a4b385956aebb91219d61d6d550e661b4d7 100644 (file)
@@ -123,6 +123,15 @@ extern const char *str_tls_level(int);
 #define TLS_PEEK_PEER_CERT(ssl) SSL_get_peer_certificate(ssl)
 #define TLS_FREE_PEER_CERT(x)   X509_free(x)
 #define tls_set_bio_callback    BIO_set_callback
+#endif
+
+#if OPENSSL_VERSION_PREREQ(3,2)
+#define TLS_GROUP_NAME(ssl) SSL_get0_group_name(ssl)
+#elif OPENSSL_VERSION_PREREQ(3,0)
+#define TLS_GROUP_NAME(ssl) \
+    SSL_group_to_name((ssl), SSL_get_negotiated_group(ssl))
+#else
+#define TLS_GROUP_NAME(ssl) ((const char *)0)
 #endif
 
  /*
@@ -262,7 +271,7 @@ typedef struct {
     int     errorcode;                 /* First error at error depth */
     int     must_fail;                 /* Failed to load trust settings */
     int     rpt_reported;              /* Failure was reported with TLSRPT */
-    char   *fail_type;         /* Doomed by policy */
+    char   *ffail_type;                        /* Forced verification failure */
 } TLS_SESS_STATE;
 
  /*
@@ -496,7 +505,7 @@ typedef struct {
     const char *mdalg;                 /* default message digest algorithm */
     const TLS_DANE *dane;              /* DANE TLSA verification */
     struct TLSRPT_WRAPPER *tlsrpt;     /* RFC 8460 reporting */
-    char   *fail_type;         /* verification must fail by policy */
+    char   *ffail_type;                        /* Forced verification failure */
 } TLS_CLIENT_START_PROPS;
 
 extern TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *);
index 7bf7e5f48b451f07d2dfa80d0906f110895a5077..e35b4e92617753573c071bf3086209a69a62f9cc 100644 (file)
 /*
 /*     Victor Duchovni
 /*     Morgan Stanley
+/*
+/*     Wietse Venema
+/*     porcupine.org
 /*--*/
 
 /* System library. */
@@ -369,7 +372,7 @@ static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
            msg_info("%s: re-using session with untrusted peer credential, "
                     "look for details earlier in the log", props->namaddr);
     }
-    /* TODO(wietse) In the non-reuse case, tlsrprt the root cause? */
+    /* TODO(wietse) Don't log TLSRPT success/failure for reused session. */
 }
 
 /* verify_rpk - process RFC7250 raw public key verification status */
@@ -414,7 +417,7 @@ static void verify_rpk(TLS_SESS_STATE *TLScontext, EVP_PKEY *peerpkey,
            msg_info("%s: re-using session with untrusted certificate, "
                     "look for details earlier in the log", props->namaddr);
     }
-    /* TODO(wietse) In the non-reuse case, tlsrprt the root cause? */
+    /* TODO(wietse) Don't log TLSRPT success/failure for reused session. */
 }
 
 /* add_namechecks - tell OpenSSL what names to check */
@@ -1121,7 +1124,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 #ifdef USE_TLSRPT
                if (props->tlsrpt) {
                    trw_report_failure(props->tlsrpt, TLSRPT_TLSA_INVALID,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                       "all-TLSA-records-unusable");
                }
 #endif
@@ -1135,7 +1138,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 #ifdef USE_TLSRPT
                if (props->tlsrpt) {
                    trw_report_failure(props->tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                       "all-fingerprints-unusable");
                }
 #endif
@@ -1145,7 +1148,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 #ifdef USE_TLSRPT
                if (props->tlsrpt) {
                    trw_report_failure(props->tlsrpt, TLSRPT_TLSA_INVALID,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                       "all-TLSA-records-unusable");
                }
 #endif
@@ -1156,7 +1159,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 #ifdef USE_TLSRPT
                if (props->tlsrpt) {
                    trw_report_failure(props->tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                                       /* additional_detail= */ (char *) 0,
+                                       /* additional_info= */ (char *) 0,
                                       "all-trust-anchors-unusable");
                }
 #endif
@@ -1260,8 +1263,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
      * certificate matches in tls_verify.c. TODO(wietse) how was this handled
      * historically?
      */
-    if (props->fail_type) {
-       TLScontext->fail_type = mystrdup(props->fail_type);
+    if (props->ffail_type) {
+       TLScontext->ffail_type = mystrdup(props->ffail_type);
        TLScontext->must_fail = 1;
     }
 
@@ -1300,7 +1303,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
 #ifdef USE_TLSRPT
        if (props->tlsrpt)
            trw_report_failure(props->tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               "tls-handshake-failure");
 #endif
        uncache_session(app_ctx->ssl_ctx, TLScontext);
index f47b954617271c5adbcb93086e8708da4573583a..6165b9390099cae9847b2759e172fbe584338112 100644 (file)
@@ -75,6 +75,7 @@
  /*
   * Global library
   */
+#include <been_here.h>
 #include <mail_params.h>
 
 /* TLS library. */
@@ -313,68 +314,75 @@ static int setup_auto_groups(SSL_CTX *ctx, const char *origin,
 {
 #ifndef OPENSSL_NO_ECDH
     SSL_CTX *tmpctx;
-    int    *nids;
-    int     space = 10;
-    int     n = 0;
+    BH_TABLE *seen;
     char   *save;
     char   *groups;
     char   *group;
+    static VSTRING *names;
 
     if ((tmpctx = SSL_CTX_new(TLS_method())) == 0) {
        msg_warn("cannot allocate temp SSL_CTX");
        tls_print_errors();
        return (AG_STAT_NO_RETRY);
     }
-    nids = mymalloc(space * sizeof(int));
 
+    if (!names)
+       names = vstring_alloc(sizeof DEF_TLS_EECDH_AUTO +
+                             sizeof DEF_TLS_FFDHE_AUTO);
+    VSTRING_RESET(names);
+    /*
+     * OpenSSL does not tolerate duplicate groups in the requested list.
+     * Deduplicate case-insensitively, just in case OpenSSL some day supports
+     * case-insensitive group lookup.  Users who specify the group name twice
+     * and get the case wrong the first time deserve to be unhappy. :-)
+     *
+     * OpenSSL 3.3 supports "?<name>" as a syntax for optionally ignoring
+     * unsupported groups, so we could skip checking against the throw-away
+     * CTX when linked against 3.3 or higher, but the cost savings don't
+     * justify the #ifdef overhead for now.
+     */
+    seen = been_here_init(0, BH_FLAG_FOLD);
+
+#define GROUPS_SEP CHARS_COMMA_SP ":"
 #define SETUP_AG_RETURN(val) do { \
+       been_here_free(seen); \
        myfree(save); \
-       myfree(nids); \
        SSL_CTX_free(tmpctx); \
        return (val); \
     } while (0)
 
     groups = save = concatenate(eecdh, " ", ffdhe, NULL);
-    if ((group = mystrtok(&groups, CHARS_COMMA_SP)) == 0) {
+    if ((group = mystrtok(&groups, GROUPS_SEP)) == 0) {
        msg_warn("no %s key exchange group - OpenSSL requires at least one",
                 origin);
        SETUP_AG_RETURN(AG_STAT_NO_GROUP);
     }
-    for (; group != 0; group = mystrtok(&groups, CHARS_COMMA_SP)) {
-       int     nid = EC_curve_nist2nid(group);
-
-       if (nid == NID_undef)
-           nid = OBJ_sn2nid(group);
-       if (nid == NID_undef)
-           nid = OBJ_ln2nid(group);
-       if (nid == NID_undef) {
-           msg_warn("ignoring unknown key exchange group \"%s\"", group);
+    for (; group != 0; group = mystrtok(&groups, GROUPS_SEP)) {
+       if (been_here_fixed(seen, group))
            continue;
-       }
-
        /*
-        * Validate the NID by trying it as the group for a throw-away SSL
-        * context. Silently skip unsupported code points. This way, we can
-        * list X25519 and X448 as soon as the nids are assigned, and before
-        * the supporting code is implemented. They'll be silently skipped
-        * when not yet supported.
+        * Validate the group name by trying it as the group for a throw-away
+        * SSL context. This way, we can ask for new groups that may not yet be
+        * supported by the underlying OpenSSL runtime.  Unsupported groups are
+        * silently ignored.
         */
-       if (SSL_CTX_set1_curves(tmpctx, &nid, 1) <= 0) {
-           continue;
+       ERR_set_mark();
+       if (SSL_CTX_set1_curves_list(tmpctx, group) > 0) {
+           if (VSTRING_LEN(names) > 0)
+               VSTRING_ADDCH(names, ':');
+           vstring_strcat(names, group);
        }
-       if (++n > space) {
-           space *= 2;
-           nids = myrealloc(nids, space * sizeof(int));
-       }
-       nids[n - 1] = nid;
+       ERR_pop_to_mark();
     }
 
-    if (n == 0) {
+    if (VSTRING_LEN(names) == 0) {
        /* The names may be case-sensitive */
        msg_warn("none of the %s key exchange groups are supported", origin);
        SETUP_AG_RETURN(AG_STAT_NO_GROUP);
     }
-    if (SSL_CTX_set1_curves(ctx, nids, n) <= 0) {
+    VSTRING_TERMINATE(names);
+
+    if (SSL_CTX_set1_curves_list(ctx, vstring_str(names)) <= 0) {
        msg_warn("failed to set up the %s key exchange groups", origin);
        tls_print_errors();
        SETUP_AG_RETURN(AG_STAT_NO_RETRY);
index 3d31cbbe43d36bdf0372f54b2d9b7c962fc36541..3b699ed5df5881327ecc8c9c637c9e4f8e5d3bee 100644 (file)
@@ -1057,6 +1057,13 @@ void    tls_get_signature_params(TLS_SESS_STATE *TLScontext)
            kex_name = OBJ_nid2sn(EVP_PKEY_type(nid));
            break;
 
+#if defined(EVP_PKEY_KEYMGMT)
+       case EVP_PKEY_KEYMGMT:
+           kex_name = EVP_PKEY_get0_type_name(dh_pkey);
+           TLScontext->kex_bits = 0;
+           break;
+#endif
+
        case EVP_PKEY_DH:
            kex_name = "DHE";
            TLScontext->kex_bits = EVP_PKEY_bits(dh_pkey);
@@ -1072,6 +1079,16 @@ void    tls_get_signature_params(TLS_SESS_STATE *TLScontext)
        EVP_PKEY_free(dh_pkey);
     }
 
+    /*
+     * On the client side, a TLS 1.3 KEM has no server key, just ciphertext to
+     * decapsulate, but, as of OpenSSL 3.0, the client can still obtain the
+     * negotiated group name directly.  We nevertheless still try to get the
+     * group details from the peer key first, which works with OpenSSL 1.1.1
+     * and retains the original output format for the (EC)DH groups.
+     */
+    if (!kex_name)
+       kex_name = TLS_GROUP_NAME(ssl);
+
     /*
      * On the client end, the certificate may be present, but not used, so we
      * check via SSL_get_signature_nid().  This means that local signature
@@ -1347,7 +1364,7 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr)
     TLScontext->errorcode = X509_V_OK;
     TLScontext->errorcert = 0;
     TLScontext->rpt_reported = 0;
-    TLScontext->fail_type = 0;
+    TLScontext->ffail_type = 0;
 
     return (TLScontext);
 }
@@ -1398,8 +1415,8 @@ void    tls_free_context(TLS_SESS_STATE *TLScontext)
        myfree((void *) TLScontext->srvr_sig_dgst);
     if (TLScontext->errorcert)
        X509_free(TLScontext->errorcert);
-    if (TLScontext->fail_type)
-       myfree(TLScontext->fail_type);
+    if (TLScontext->ffail_type)
+       myfree(TLScontext->ffail_type);
 
     myfree((void *) TLScontext);
 }
index 8e0c67088f838ca3f11d5f0438a7951357859e28..ae2a8381c8e17259f0cf4c9b9806ffabbb03e2cc 100644 (file)
@@ -258,7 +258,7 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *);
 #define TLS_ATTR_MDALG         "mdalg"
 #define TLS_ATTR_DANE          "dane"
 #define TLS_ATTR_TLSRPT                "tlsrpt"
-#define FAIL_TYPE      "fail_type"
+#define TLS_ATTR_FFAIL_TYPE    "forced_failure_type"
 
  /*
   * TLS_TLSA attributes.
index b2502ff4345624771bd3f1f9a0fd92493718fe15..ae378cb7ec709931f1e51f2d2b66a8aa6044644e 100644 (file)
@@ -344,8 +344,8 @@ int     tls_proxy_client_start_print(ATTR_PRINT_COMMON_FN print_fn,
                   SEND_ATTR_FUNC(tls_proxy_client_tlsrpt_print,
                                  (const void *) props->tlsrpt),
 #endif
-                  SEND_ATTR_STR(FAIL_TYPE,
-                                 STRING_OR_EMPTY(props->fail_type)),
+                  SEND_ATTR_STR(TLS_ATTR_FFAIL_TYPE,
+                                 STRING_OR_EMPTY(props->ffail_type)),
                   ATTR_TYPE_END);
     /* Do not flush the stream. */
     if (msg_verbose)
index c6f08e80c5af87e6b58060b83248aa95f2f13c75..7b25f71af0c889efdd28f489eaf12cbfe9fff03d 100644 (file)
@@ -337,8 +337,8 @@ void    tls_proxy_client_start_free(TLS_CLIENT_START_PROPS *props)
     if (props->tlsrpt)
        trw_free(props->tlsrpt);
 #endif
-    if (props->fail_type)
-       myfree(props->fail_type);
+    if (props->ffail_type)
+       myfree(props->ffail_type);
     myfree((void *) props);
 }
 
@@ -530,7 +530,7 @@ int     tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
     VSTRING *cipher_grade = vstring_alloc(25);
     VSTRING *cipher_exclusions = vstring_alloc(25);
     VSTRING *mdalg = vstring_alloc(25);
-    VSTRING *fail_type = vstring_alloc(25);
+    VSTRING *ffail_type = vstring_alloc(25);
 
 #ifdef USE_TLSRPT
 #define EXPECT_START_SCAN_RETURN       17
@@ -571,7 +571,7 @@ int     tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
                  RECV_ATTR_FUNC(tls_proxy_client_tlsrpt_scan,
                                 &props->tlsrpt),
 #endif
-                 RECV_ATTR_STR(FAIL_TYPE, fail_type),
+                 RECV_ATTR_STR(TLS_ATTR_FFAIL_TYPE, ffail_type),
                  ATTR_TYPE_END);
     /* Always construct a well-formed structure. */
     props->nexthop = vstring_export(nexthop);
@@ -584,7 +584,7 @@ int     tls_proxy_client_start_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp,
     props->cipher_grade = vstring_export(cipher_grade);
     props->cipher_exclusions = vstring_export(cipher_exclusions);
     props->mdalg = vstring_export(mdalg);
-    EXPORT_OR_NULL(props->fail_type, fail_type);
+    EXPORT_OR_NULL(props->ffail_type, ffail_type);
     ret = (ret == EXPECT_START_SCAN_RETURN ? 1 : -1);
     if (ret != 1) {
        tls_proxy_client_start_free(props);
index a719c2ca9ff92e6b458bd5da62bfaf53a3286648..0f78e24f41fce52fa58b018d584b568d6e92ccfa 100644 (file)
@@ -90,6 +90,9 @@
 /*
 /*     Victor Duchovni
 /*     Morgan Stanley
+/*
+/*     Wietse Venema
+/*     porcupine.org
 /*--*/
 
 /* System library. */
@@ -224,19 +227,19 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
     /*
      * If an external policy flagged an error, report that instead.
      */
-    if (TLScontext->fail_type) {
+    if (TLScontext->ffail_type) {
        msg_info("certificate verification failed for %s: "
-               "external policy failure (%s)",
-                TLScontext->namaddr, TLScontext->fail_type);
+                "external policy failure (%s)",
+                TLScontext->namaddr, TLScontext->ffail_type);
 #ifdef USE_TLSRPT
        if (tlsrpt) {
            tlsrpt_failure_t failure_type;
 
-           if ((failure_type = convert_tlsrpt_policy_failure(TLScontext->fail_type)) < 0)
+           if ((failure_type = convert_tlsrpt_policy_failure(TLScontext->ffail_type)) < 0)
                msg_panic("tls_log_verify_error: unexpected failure_reason: %s",
-                         TLScontext->fail_type);
+                         TLScontext->ffail_type);
            trw_report_failure(tlsrpt, failure_type,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                                /* failure_reason= */ (char *) 0);
        }
 #endif
@@ -258,7 +261,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_CERTIFICATE_NOT_TRUSTED,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                                /* failure_code= */ (char *) 0);
 #endif
        break;
@@ -268,7 +271,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               CERT_ERROR_TO_STRING(err));
 #endif
        break;
@@ -289,7 +292,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               CERT_ERROR_TO_STRING(err));
 #endif
        break;
@@ -300,7 +303,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               CERT_ERROR_TO_STRING(err));
 #endif
        break;
@@ -311,7 +314,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_CERTIFICATE_EXPIRED,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                                /* failure_code= */ (char *) 8);
 #endif
        break;
@@ -321,7 +324,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               CERT_ERROR_TO_STRING(err));
 #endif
        break;
@@ -332,7 +335,7 @@ void    tls_log_verify_error(TLS_SESS_STATE *TLScontext,
 #ifdef USE_TLSRPT
        if (tlsrpt)
            trw_report_failure(tlsrpt, TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               CERT_ERROR_TO_STRING(err));
 #endif
        break;
index 91112cb71f0e282d2d38577c73e378c021afa087..03858fd13c4a658626f1164db5da721b3b6428d5 100644 (file)
@@ -2,7 +2,7 @@
 /* NAME
 /*     tlsrpt_wrapper 3
 /* SUMMARY
-/*     TLSRPT support for the TLS protocol engine
+/*     TLSRPT support for the SMTP and TLS protocol engines
 /* SYNOPSIS
 /*     #include <tlsrpt_wrapper.h>
 /*
@@ -36,7 +36,7 @@
 /*     void    trw_report_failure(
 /*     TLSRPT_WRAPPER *trw,
 /*     tlsrpt_failure_t failure_type,
-/*     const char *additional_detail,
+/*     const char *additional_info,
 /*     const char *failure_reason)
 /*
 /*     void    trw_report_success(
 /*     int     valid_tlsrpt_policy_failure(
 /*     const char *failure_name)
 /*     #endif /* USE_TLS */
-/* ARCHITECTURE, BOTTOM-UP VIEW
-/*     Postfix TLSRPT support uses the TLSRPT client library from
-/*     sys4.de. That library makes the reasonable assumption that
+/* POSTFIX ARCHITECTURE, BOTTOM-UP VIEW
+/* .ad
+/* .fi
+/*     This module encapsulates TLSRPT support for Postfix's
+/*     multi-process and multi-layer architecture. The text that follows
+/*     explains the purpose of this software layer.
+/*
+/*     First, Postfix TLSRPT support uses the TLSRPT client library
+/*     from sys4.de. That library makes the reasonable assumption that
 /*     all calls concerning one SMTP session will be made from within
 /*     one process.
 /*
-/*     With Postfix, the TLS protocol engine may be located in a
-/*     different process than the SMTP protocol engine, and both
-/*     processes need the ability to report a TLS error.
+/*     Second, some TLS errors are detected in the SMTP protocol
+/*     engine (example: a remote SMTP server does not announce STARTTLS
+/*     support), while other TLS errors are detected in the TLS protocol
+/*     engine (example: certificate verification error).
 /*
-/*     To bridge this gap, the SMTP protocol engine forwards SMTP
-/*     session and TLS policy information to the TLS protocol engine in
-/*     the form of a TLSRPT_WRAPPER object that contains SMTP and other
-/*     information that the TLSRPT client library needs.  The TLS engine
-/*     can pass that information to the TLSRPT client library to report
-/*     a TLS error. The SMTP protocol engine can use that same
-/*     information to report a TLS error or success.
-/* IMPLEMENTATION
+/*     Third, the Postfix TLS protocol engine may be located in a
+/*     different process than the SMTP protocol engine. And even if the
+/*     two are located in the same process, the TLS protocol engine knows
+/*     nothing about SMTP. Hence, there needs to be an abstraction that
+/*     isolates the TLS protocol engine from the SMTP-specific details
+/*     of TLSRPT.
+/*
+/*     Fourth, Postfix has a pipelined and layered architecture where
+/*     each process (or architectural layer) handles a problem as it
+/*     runs into it, instead of reporting problem details back to its
+/*     pipeline predecessor (or back to a higher architectural layer).
+/* TLSRPT_WRAPPER IMPLEMENTATION
 /* .ad
 /* .fi
-/*     The Postfix SMTP protocol engine (smtp_proto.c) reports TLS
-/*     errors when TLS support is required but unavailable, or requests
-/*     the Postfix TLS protocol engine to perform a TLS protocol
-/*     handshake over an open SMTP connection. The SMTP protocol engine
-/*     either calls the TLS protocol engine directly, or calls it over
-/*     RPC in a tlsproxy(8) process.
+/*     At a high level, the SMTP protocol engine encapsulates SMTP
+/*     session and TLS policy information in an opaque TLSRPT_WRAPPER
+/*     object, and passes that object to the TLS protocol engine. The
+/*     TLS protocol engine can invoke TLSRPT_WRAPPER methods to report a
+/*     TLS error through the sys4.de TLSRPT client library. In a similar
+/*     manner, the SMTP protocol engine can invoke TLSRPT_WRAPPER object
+/*     methods to report a TLS error or success.
+/*
+/*     At a low level, The Postfix SMTP protocol engine (smtp_proto.c)
+/*     reports TLS errors when TLS support is required but unavailable,
+/*     or requests the Postfix TLS protocol engine to perform a TLS
+/*     protocol handshake over an open SMTP connection. The SMTP
+/*     protocol engine either calls the TLS protocol engine directly,
+/*     or calls it over local IPC in a tlsproxy(8) process.
 /*
-/*     The TLS protocol engine may report a TLS error through the
-/*     tlsrpt_wrapper library, and either returns no TLS session object,
-/*     or a TLS session object for a completed handshake. The TLS
-/*     session object will indicate if the TLS protocol engine reported
-/*     any TLS error through TLSRPT.
+/*     The TLS protocol engine may report a TLS error by invoking
+/*     TLSRPT_WRAPPER methods, and either returns no TLS session object,
+/*     or a TLS session object for a completed handshake. The TLS session
+/*     object will indicate if the TLS protocol engine reported any
+/*     TLS error through TLSRPT (for example an error that resulted in
+/*     a successful TLS handshake with a downgraded TLS security level).
 /*
 /*     The Postfix SMTP protocol engine reports success or failure
-/*     through the tlsrpt_wrapper library, depending on whether all
-/*     matching requirements were satisfied. SMTP protocol engine
-/*     does not report success or failure through the tlsrpt_wrapper
-/*     library if the TLS protocol engine already reported a failure.
-/* WRAPPER API
+/*     by invoking TLSRPT_WRAPPER methods, depending on whether all
+/*     matching requirements were satisfied. The SMTP protocol engine
+/*     does not report success or failure by invoking TLSRPT_WRAPPER
+/*     methods if the TLS protocol engine already reported a failure.
+/* TLSRPT_WRAPPER API
 /* .ad
 /* .fi
 /*     The functions below must be called in a specific order. All
 /*     string inputs are copied. If a required call is missing then
-/*     the request will be ignored, and a warning will be logged.
+/*     the request will be ignored, and a warning will be logged,
+/*     but this not affect email deliveries.
 /* .PP
 /*     trw_create() must be called before other trw_xxx() requests can
 /*     be made. Arguments:
 /*     trw_free() destroys storage allocated with other trw_xxx()
 /*     requests.
 /* .PP
-/*     trw_set_tls_policy() must be called by the SMTP protocol
-/*     engine after it found a DANE, STS, or no policy, and before it
-/*     tries to establish a new SMTP connection. This function clears
-/*     information that was specified earlier with trw_set_tls_policy()
-/*     or trw_set_tcp_connection(), and whether trw_report_failure()
+/*     trw_set_tls_policy() must be called by the SMTP protocol engine
+/*     after it found a DANE, STS, or no policy, and before it tries to
+/*     establish a new SMTP connection. This function clears information
+/*     that was specified earlier with trw_set_tls_policy() or
+/*     trw_set_tcp_connection(), and resets whether trw_report_failure()
 /*     or trw_report_success() were called. Mapping from arguments to
 /*     TLSRPT report fields:
 /* .IP tls_policy_type
 /*     policies[].policy.policy-type.
-/* .IP tls_policy_strings
+/* .IP tls_policy_strings (may be null)
 /*     policies[].policy.policy-string[]. Ignored if the tls_policy_type
 /*     value is TLSRPT_NO_POLICY_FOUND.
-/* .IP tls_policy_domain
+/* .IP tls_policy_domain (may be null)
 /*     policies[].policy.policy-domain.
 /* .IP mx_host_patterns (may be null)
 /*     policies[].policy.mx-host[]. Ignored if the tls_policy_type
 /*     connection. Mapping from arguments to TLSRPT report fields:
 /* .IP failure_type
 /*     policies[].failure-details[].result-type.
-/* .IP additional_detail (may be null)
+/* .IP additional_info (may be null)
 /*     policies[].failure-details[].additional-information.
 /* .IP failure_reason (may be null)
 /*     policies[].failure-details[].failure-reason-code
 /*     module is built with TLSRPT support. This allows the names to
 /*     be used even if TLSRPT is disabled.
 /* DIAGNOSTICS
-/*     Some functions will log a a warning when information is missing,
-/*     but such warnings will not affect the SMTP or TLS protocol engine.
+/*     Some functions will log a warning when information is missing.
+/*     Such warnings will not affect the operation of the SMTP or TLS
+/*     protocol engine.
 /* BUGS
 /*     This implementation is suitable to report successful TLS policy
 /*     compliance, and to report a failure that prevents TLS policy
@@ -405,12 +427,17 @@ static int trw_munge_report_result(int libtlsrpt_errorcode)
     }
 
     /*
-     * Report a libc error. Do not report success if errno was zero.
+     * Report a libc error. Do not report success if errno was zero. When
+     * debug logging is enabled, also log some library-internal info.
      */
     else {
        err = tlsrpt_errno_from_error_code(libtlsrpt_errorcode);
        msg_warn("Could not report TLS handshake result to tlsrpt library:"
                 " %s (errno %d)", mystrerror(err), err);
+       if (msg_verbose)
+           msg_warn("Error location in tlsrpt library: %s (error %d)",
+                    tlsrpt_strerror(libtlsrpt_errorcode),
+                    libtlsrpt_errorcode);
        errno = err;
        return (-1);
     }
@@ -452,7 +479,7 @@ static const char *trw_failure_type_to_string(tlsrpt_failure_t failure_type)
 
 int     trw_report_failure(TLSRPT_WRAPPER *trw,
                                   tlsrpt_failure_t failure_type,
-                                  const char *additional_detail,
+                                  const char *additional_info,
                                   const char *failure_reason)
 {
     const char myname[] = "trw_report_failure";
@@ -514,7 +541,7 @@ int     trw_report_failure(TLSRPT_WRAPPER *trw,
                             /* receiving_mx_hostname= */ trw->rcv_mta_name,
                                 /* receiving_mx_helo= */ trw->rcv_mta_ehlo,
                                      /* receiving_ip= */ trw->rcv_mta_addr,
-                           /* additional_information= */ additional_detail,
+                             /* additional_information= */ additional_info,
                                 /* failure_reason_code= */ failure_reason);
                if (res == 0)
                    res = tlsrpt_finish_policy(dr, TLSRPT_FINAL_FAILURE);
index 2107d3a3d6c03a284ae84f3d5a24809ee8364f4d..57daff16fa90415aab310341573810dad145b509 100644 (file)
@@ -5,7 +5,7 @@
 /* NAME
 /*     tlsrpt_wrapper 3h
 /* SUMMARY
-/*     TLSRPT support for the TLS protocol engine
+/*     TLSRPT support for the SMTP and TLS protocol engines
 /* SYNOPSIS
 /*     #include <tlsrpt_wrapper.h>
 /* DESCRIPTION
@@ -46,7 +46,7 @@ extern void trw_set_ehlo_resp(TLSRPT_WRAPPER *trw,
                                      const char *rcv_mta_ehlo);
 extern int trw_report_failure(TLSRPT_WRAPPER *trw,
                                      tlsrpt_failure_t policy_failure,
-                                     const char *additional_detail,
+                                     const char *additional_info,
                                      const char *failure_reason);
 extern int trw_report_success(TLSRPT_WRAPPER *trw);
 extern int trw_is_reported(const TLSRPT_WRAPPER *trw);
index 346415dafa9c99c5ae8899bd43ca5897cdea276a..1bf449d370c79703e5270b88dbc48a9f8ebf3131 100644 (file)
@@ -743,7 +743,7 @@ static int tlsp_eval_tls_error(TLSP_STATE *state, int err)
            && state->is_server_role == 0)
            trw_report_failure(state->client_start_props->tlsrpt,
                               TLSRPT_VALIDATION_FAILURE,
-                               /* additional_detail= */ (char *) 0,
+                               /* additional_info= */ (char *) 0,
                               "tls-handshake-failure");
 #endif
        tlsp_state_free(state);
index 112603164ecf41bb6948324f48baa923acfaaa6a..0816430bc1bac8210b452eebd3d25d2d544ee84b 100644 (file)
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
+/*     porcupine.org
 /*--*/
 
 /* System libraries. */