]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.1.10-RC3 v3.1.10-RC3
authorWietse Venema <wietse@porcupine.org>
Sat, 17 Nov 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sun, 18 Nov 2018 00:17:07 +0000 (19:17 -0500)
16 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/FORWARD_SECRECY_README
postfix/html/FORWARD_SECRECY_README.html
postfix/proto/FORWARD_SECRECY_README.html
postfix/src/global/ehlo_mask.c
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_proxy_clnt.c
postfix/src/tls/tls_proxy_print.c
postfix/src/tls/tls_proxy_scan.c
postfix/src/tls/tls_server.c

index 5502f64db306cf54471f4173d96e9c7c8b52ae88..13c628c342a10b8c086af83bbc46ff44f888ec6e 100644 (file)
 -TTLS_PKEYS
 -TTLS_PRNG_SEED_INFO
 -TTLS_PRNG_SRC
+-TTLS_ROLE
 -TTLS_SCACHE
 -TTLS_SCACHE_ENTRY
 -TTLS_SERVER_INIT_PROPS
 -TTLS_SESS_STATE
 -TTLS_TICKET_KEY
 -TTLS_TLSA
+-TTLS_USAGE
 -TTLS_VINFO
 -TTLScontext_t
 -TTOK822
index c8181dcb0efd93cba831be4d8640a61f9947044d..e143546f946492e76111d11cfaaec46fd040db1b 100644 (file)
@@ -22438,7 +22438,23 @@ Apologies for any names omitted.
        proto/TLS_README.html, tls/tls.h, tls/tls_server.c,
        tls/tls_misc.c.
 
+20181106
+
+       Bugfix (introduced: 3.0): smtpd_discard_ehlo_keywords could
+       not disable "SMTPUTF8". because the lookup table was using
+       "EHLO_MASK_SMTPUTF8" instead. File: global/ehlo_mask.c.
+
 20181110
 
        Documentation: update documentation for Postfix versions
        that support disabling TLS 1.3. File: proto/postconf.proto.
+
+20181117
+
+       Improved logging of TLS 1.3 summary information, and improved
+       reporting of the same info in Received: message headers.
+       Viktor Dukhovni. Files: proto/FORWARD_SECRECY_README.html,
+       posttls-finger/posttls-finger.c, smtpd/smtpd.c, tls/tls.h,
+       tls/tls_client.c, tls/tls_misc.c, tls/tls_proxy.h,
+       tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c,
+       tls/tls_server.c.
index fb40e4d5809a5f65b6c91fe6ac24c17dfcfaa0a7..88066f87d91fee0e00764b5d696a58c625995f13 100644 (file)
@@ -14,7 +14,7 @@ is easily subverted by a state-funded adversary.
 O\bOv\bve\ber\brv\bvi\bie\bew\bw
 
 Postfix supports forward secrecy of TLS network communication since version
-2.2. This support was adopted from Lutz Jänicke's "Postfix TLS patch" for
+2.2. This support was adopted from Lutz Ja"nicke's "Postfix TLS patch" for
 earlier Postfix versions. This document will focus on TLS Forward Secrecy in
 the Postfix SMTP client and server. See TLS_README for a general description of
 Postfix TLS support.
@@ -279,7 +279,8 @@ verification status.
 
   * With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP
     client and server will log TLS connection information to the maillog file.
-    The general logfile format is:
+    The general logfile format is shown below. With TLS 1.3 there may be
+    additional properties logged after the cipher name and bits.
 
         postfix/smtp[process-id]: Untrusted TLS connection established
         to host.example.com[192.168.0.2]:25: TLSv1 with cipher cipher-name
@@ -292,7 +293,8 @@ verification status.
   * With "smtpd_tls_received_header = yes", the Postfix SMTP server will record
     TLS connection information in the Received: header in the form of comments
     (text inside parentheses). The general format depends on the
-    smtpd_tls_ask_ccert setting:
+    smtpd_tls_ask_ccert setting. With TLS 1.3 there may be additional
+    properties logged after the cipher name and bits.
 
         Received: from host.example.com (host.example.com [192.168.0.2])
                 (using TLSv1 with cipher cipher-name
@@ -305,6 +307,47 @@ verification status.
                 (actual-key-size/raw-key-size bits))
                 (No client certificate requested)
 
+    TLS 1.3 examples. Some of the new attributes may not appear when not
+    applicable or not available in older versions of the OpenSSL library.
+
+        Received: from localhost (localhost [127.0.0.1])
+                (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256
+        bits)
+                 key-exchange X25519 server-signature RSA-PSS (2048 bits)
+        server-digest SHA256)
+                (No client certificate requested)
+
+        Received: from localhost (localhost [127.0.0.1])
+                (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256
+        bits)
+                 key-exchange X25519 server-signature RSA-PSS (2048 bits)
+        server-digest SHA256
+                 client-signature ECDSA (P-256) client-digest SHA256)
+                (Client CN "example.org", Issuer "example.org" (not verified))
+
+      o The "key-exchange" attribute records the type of "Diffie-Hellman" group
+        used for key agreement. Possible values include "DHE", "ECDHE",
+        "X25519" and "X448". With "DHE", the bit size of the prime will be
+        reported in parentheses after the algorithm name, with "ECDHE", the
+        curve name.
+
+      o The "server-signature" attribute shows the public key signature
+        algorithm used by the server. With "RSA-PSS", the bit size of the
+        modulus will be reported in parentheses. With "ECDSA", the curve name.
+        If, for example, the server has both an RSA and an ECDSA private key
+        and certificate, it will be possible to track which one was used for a
+        given connection.
+
+      o The new "server-digest" attribute records the digest algorithm used by
+        the server to prepare handshake messages for signing. The Ed25519 and
+        Ed448 signature algorithms do not make use of such a digest, so no
+        "server-digest" will be shown for these signature algorithms.
+
+      o When a client certificate is requested with "smtpd_tls_ask_ccert" and
+        the client uses a TLS client-certificate, the "client-signature" and
+        "client-digest" attributes will record the corresponding properties of
+        the client's TLS handshake signature.
+
 The next sections will explain what cipher-name, key-size, and peer
 verification status information to expect.
 
@@ -346,6 +389,51 @@ The actual key length and raw algorithm key length are generally the same with
 non-export ciphers, but may they differ for the legacy export ciphers where the
 actual key is artificially shortened.
 
+Starting with TLS 1.3 the cipher name no longer contains enough information to
+determine which forward-secrecy scheme was employed, but TLS 1.3 a\bal\blw\bwa\bay\bys\bs uses
+forward-secrecy. On the client side, up-to-date Postfix releases log additional
+information for TLS 1.3 connections, reporting the signature and key exchange
+algorithms. Two examples below (the long single line messages are folded across
+multiple lines for readability):
+
+    postfix/smtp[process-id]:
+      Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+      TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+      key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest
+    SHA256
+      client-signature ECDSA (P-256) client-digest SHA256
+
+    postfix/smtp[process-id]:
+      Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+      TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+      key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest
+    SHA256
+
+In the above connections, the "key-exchange" value records the "Diffie-Hellman"
+algorithm used for key agreement. The "server-signature" value records the
+public key algoritm used by the server to sign the key exchange. The "server-
+digest" value records any hash algorithm used to prepare the data for signing.
+With "ED25519" and "ED448", no separate hash algorithm is used.
+
+Examples of Postfix SMTP server logging:
+
+    postfix/smtpd[process-id]:
+      Untrusted TLS connection established from localhost[127.0.0.1]:25:
+      TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+      key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest
+    SHA256
+      client-signature ECDSA (P-256) client-digest SHA256
+
+    postfix/smtpd[process-id]:
+      Anonymous TLS connection established from localhost[127.0.0.1]:
+      TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+      server-signature RSA-PSS (2048 bits) server-digest SHA256
+
+    postfix/smtpd[process-id]:
+      Anonymous TLS connection established from localhost[127.0.0.1]:
+      TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+      server-signature ED25519
+
 W\bWh\bha\bat\bt d\bdo\bo "\b"A\bAn\bno\bon\bny\bym\bmo\bou\bus\bs"\b",\b, "\b"U\bUn\bnt\btr\bru\bus\bst\bte\bed\bd"\b",\b, e\bet\btc\bc.\b. i\bin\bn P\bPo\bos\bst\btf\bfi\bix\bx l\blo\bog\bgg\bgi\bin\bng\bg m\bme\bea\ban\bn?\b?
 
 The verification levels below are subject to man-in-the-middle attacks to
@@ -421,8 +509,8 @@ peer certificate with expected public-key or certificate fingerprint)
 
 C\bCr\bre\bed\bdi\bit\bts\bs
 
-  * TLS support for Postfix was originally developed by Lutz Jänicke at Cottbus
-    Technical University.
+  * TLS support for Postfix was originally developed by Lutz Ja"nicke at
+    Cottbus Technical University.
   * Wietse Venema adopted and restructured the code and documentation.
   * Viktor Dukhovni implemented support for many subsequent TLS features,
     including EECDH, and authored the initial version of this document.
index d1364ef542daf1255dc36e24995f69c9c17095f8..55da1464b3efb88a945575b2c90d0c5a5bb2441e 100644 (file)
@@ -378,7 +378,9 @@ peer certificate or public-key verification status.  </p>
 
 <li> <p> With "<a href="postconf.5.html#smtp_tls_loglevel">smtp_tls_loglevel</a> = 1" and "<a href="postconf.5.html#smtpd_tls_loglevel">smtpd_tls_loglevel</a> = 1",
 the Postfix SMTP client and server will log TLS connection information
-to the maillog file. The general logfile format is: </p>
+to the maillog file. The general logfile format is shown below.
+With TLS 1.3 there may be additional properties logged after the
+cipher name and bits. </p>
 
 <blockquote>
 <pre>
@@ -395,7 +397,8 @@ from host.example.com[192.168.0.2]: TLSv1 with cipher <i>cipher-name</i>
 <li> <p> With "<a href="postconf.5.html#smtpd_tls_received_header">smtpd_tls_received_header</a> = yes", the Postfix SMTP
 server will record TLS connection information in the Received:
 header in the form of comments (text inside parentheses). The general
-format depends on the <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> setting:
+format depends on the <a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a> setting. With TLS 1.3 there
+may be additional properties logged after the cipher name and bits. </p>
 
 <blockquote>
 <pre>
@@ -411,6 +414,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
 </pre>
 </blockquote>
 
+<p> TLS 1.3 examples.  Some of the new attributes may not appear when not
+applicable or not available in older versions of the OpenSSL library.  </p>
+
+<blockquote>
+<pre>
+Received: from localhost (localhost [127.0.0.1])
+        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
+        (No client certificate requested)
+
+Received: from localhost (localhost [127.0.0.1])
+        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+         client-signature ECDSA (P-256) client-digest SHA256)
+        (Client CN "example.org", Issuer "example.org" (not verified))
+</pre>
+</blockquote>
+
+<ul>
+<li> <p> The "key-exchange" attribute records the type of "Diffie-Hellman"
+group used for key agreement.  Possible values include "DHE", "ECDHE", "X25519"
+and "X448".  With "DHE", the bit size of the prime will be reported in
+parentheses after the algorithm name, with "ECDHE", the curve name. </p>
+
+<li> <p> The "server-signature" attribute shows the public key signature
+algorithm used by the server.  With "RSA-PSS", the bit size of the modulus will
+be reported in parentheses.  With "ECDSA", the curve name.  If, for example,
+the server has both an RSA and an ECDSA private key and certificate, it will be
+possible to track which one was used for a given connection. </p>
+
+<li> <p> The new "server-digest" attribute records the digest algorithm used by
+the server to prepare handshake messages for signing.  The Ed25519 and Ed448
+signature algorithms do not make use of such a digest, so no "server-digest"
+will be shown for these signature algorithms. </p>
+
+<li> <p> When a client certificate is requested with "<a href="postconf.5.html#smtpd_tls_ask_ccert">smtpd_tls_ask_ccert</a>" and
+the client uses a TLS client-certificate, the "client-signature" and
+"client-digest" attributes will record the corresponding properties of the
+client's TLS handshake signature.  </p> </ul>
+
 </ul>
 
 <p> The next sections will explain what <i>cipher-name</i>,
@@ -462,6 +505,58 @@ are generally the same with non-export ciphers, but may they
 differ for the legacy export ciphers where the actual key 
 is artificially shortened. </p>
 
+<p> Starting with TLS 1.3 the cipher name no longer contains enough
+information to determine which forward-secrecy scheme was employed,
+but TLS 1.3 <b>always</b> uses forward-secrecy.  On the client side,
+up-to-date Postfix releases log additional information for TLS 1.3
+connections, reporting the signature and key exchange algorithms.
+Two examples below (the long single line messages are folded across
+multiple lines for readability): </p>
+
+<blockquote>
+<pre>
+postfix/smtp[<i>process-id</i>]:
+  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+  client-signature ECDSA (P-256) client-digest SHA256
+
+postfix/smtp[<i>process-id</i>]:
+  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest SHA256
+</pre>
+</blockquote>
+
+<p> In the above connections, the "key-exchange" value records the
+"Diffie-Hellman" algorithm used for key agreement.  The "server-signature" value
+records the public key algoritm used by the server to sign the key exchange.
+The "server-digest" value records any hash algorithm used to prepare the data
+for signing.  With "ED25519" and "ED448", no separate hash algorithm is used.
+</p>
+
+<p> Examples of Postfix SMTP server logging: </p>
+
+<blockquote>
+<pre>
+postfix/smtpd[<i>process-id</i>]:
+  Untrusted TLS connection established from localhost[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+  client-signature ECDSA (P-256) client-digest SHA256
+
+postfix/smtpd[<i>process-id</i>]:
+  Anonymous TLS connection established from localhost[127.0.0.1]:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  server-signature RSA-PSS (2048 bits) server-digest SHA256
+
+postfix/smtpd[<i>process-id</i>]:
+  Anonymous TLS connection established from localhost[127.0.0.1]:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  server-signature ED25519
+</pre>
+</blockquote>
+
 <h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
 Postfix logging mean? </a> </h2>
 
index 3db4ee843afc310b5309a8b823c78b8dc0b1bd55..a57486c658ea8bdb11a8d673b7c3f67e6e392625 100644 (file)
@@ -378,7 +378,9 @@ peer certificate or public-key verification status.  </p>
 
 <li> <p> With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1",
 the Postfix SMTP client and server will log TLS connection information
-to the maillog file. The general logfile format is: </p>
+to the maillog file. The general logfile format is shown below.
+With TLS 1.3 there may be additional properties logged after the
+cipher name and bits. </p>
 
 <blockquote>
 <pre>
@@ -395,7 +397,8 @@ from host.example.com[192.168.0.2]: TLSv1 with cipher <i>cipher-name</i>
 <li> <p> With "smtpd_tls_received_header = yes", the Postfix SMTP
 server will record TLS connection information in the Received:
 header in the form of comments (text inside parentheses). The general
-format depends on the smtpd_tls_ask_ccert setting:
+format depends on the smtpd_tls_ask_ccert setting. With TLS 1.3 there
+may be additional properties logged after the cipher name and bits. </p>
 
 <blockquote>
 <pre>
@@ -411,6 +414,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
 </pre>
 </blockquote>
 
+<p> TLS 1.3 examples.  Some of the new attributes may not appear when not
+applicable or not available in older versions of the OpenSSL library.  </p>
+
+<blockquote>
+<pre>
+Received: from localhost (localhost [127.0.0.1])
+        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256)
+        (No client certificate requested)
+
+Received: from localhost (localhost [127.0.0.1])
+        (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+         key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+         client-signature ECDSA (P-256) client-digest SHA256)
+        (Client CN "example.org", Issuer "example.org" (not verified))
+</pre>
+</blockquote>
+
+<ul>
+<li> <p> The "key-exchange" attribute records the type of "Diffie-Hellman"
+group used for key agreement.  Possible values include "DHE", "ECDHE", "X25519"
+and "X448".  With "DHE", the bit size of the prime will be reported in
+parentheses after the algorithm name, with "ECDHE", the curve name. </p>
+
+<li> <p> The "server-signature" attribute shows the public key signature
+algorithm used by the server.  With "RSA-PSS", the bit size of the modulus will
+be reported in parentheses.  With "ECDSA", the curve name.  If, for example,
+the server has both an RSA and an ECDSA private key and certificate, it will be
+possible to track which one was used for a given connection. </p>
+
+<li> <p> The new "server-digest" attribute records the digest algorithm used by
+the server to prepare handshake messages for signing.  The Ed25519 and Ed448
+signature algorithms do not make use of such a digest, so no "server-digest"
+will be shown for these signature algorithms. </p>
+
+<li> <p> When a client certificate is requested with "smtpd_tls_ask_ccert" and
+the client uses a TLS client-certificate, the "client-signature" and
+"client-digest" attributes will record the corresponding properties of the
+client's TLS handshake signature.  </p> </ul>
+
 </ul>
 
 <p> The next sections will explain what <i>cipher-name</i>,
@@ -462,6 +505,58 @@ are generally the same with non-export ciphers, but may they
 differ for the legacy export ciphers where the actual key 
 is artificially shortened. </p>
 
+<p> Starting with TLS 1.3 the cipher name no longer contains enough
+information to determine which forward-secrecy scheme was employed,
+but TLS 1.3 <b>always</b> uses forward-secrecy.  On the client side,
+up-to-date Postfix releases log additional information for TLS 1.3
+connections, reporting the signature and key exchange algorithms.
+Two examples below (the long single line messages are folded across
+multiple lines for readability): </p>
+
+<blockquote>
+<pre>
+postfix/smtp[<i>process-id</i>]:
+  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+  client-signature ECDSA (P-256) client-digest SHA256
+
+postfix/smtp[<i>process-id</i>]:
+  Untrusted TLS connection established to 127.0.0.1[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange ECDHE (P-256) server-signature ECDSA (P-256) server-digest SHA256
+</pre>
+</blockquote>
+
+<p> In the above connections, the "key-exchange" value records the
+"Diffie-Hellman" algorithm used for key agreement.  The "server-signature" value
+records the public key algoritm used by the server to sign the key exchange.
+The "server-digest" value records any hash algorithm used to prepare the data
+for signing.  With "ED25519" and "ED448", no separate hash algorithm is used.
+</p>
+
+<p> Examples of Postfix SMTP server logging: </p>
+
+<blockquote>
+<pre>
+postfix/smtpd[<i>process-id</i>]:
+  Untrusted TLS connection established from localhost[127.0.0.1]:25:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
+  client-signature ECDSA (P-256) client-digest SHA256
+
+postfix/smtpd[<i>process-id</i>]:
+  Anonymous TLS connection established from localhost[127.0.0.1]:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  server-signature RSA-PSS (2048 bits) server-digest SHA256
+
+postfix/smtpd[<i>process-id</i>]:
+  Anonymous TLS connection established from localhost[127.0.0.1]:
+  TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
+  server-signature ED25519
+</pre>
+</blockquote>
+
 <h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
 Postfix logging mean? </a> </h2>
 
index 1671beb3ec0121bacbc02a93906e396852385576..d5cb67b0a7bd51d2ef4c29f51c2da36a3211b035 100644 (file)
@@ -77,6 +77,7 @@ static const NAME_MASK ehlo_mask_table[] = {
     "ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES,
     "DSN", EHLO_MASK_DSN,
     "EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8,
+    "SMTPUTF8", EHLO_MASK_SMTPUTF8,
     "SILENT-DISCARD", EHLO_MASK_SILENT,        /* XXX In-band signaling */
     0,
 };
index 1e427975a272990da0060fad60565e861b0b8116..6e541864bd63fd4ffad25034d7c6b82de330fa48 100644 (file)
@@ -291,6 +291,18 @@ extern char *mail_pathname(const char *, const char *);
 #define MAIL_ATTR_CIPHER_NAME  "cipher_name"
 #define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits"
 #define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits"
+#define MAIL_ATTR_KEX_NAME     "key_exchange"
+#define MAIL_ATTR_KEX_CURVE    "key_exchange_curve"
+#define MAIL_ATTR_KEX_BITS     "key_exchange_bits"
+#define MAIL_ATTR_CLNT_SIG_NAME        "clnt_signature"
+#define MAIL_ATTR_CLNT_SIG_CURVE       "clnt_signature_curve"
+#define MAIL_ATTR_CLNT_SIG_BITS        "clnt_signature_bits"
+#define MAIL_ATTR_CLNT_SIG_DGST        "clnt_signature_digest"
+#define MAIL_ATTR_SRVR_SIG_NAME        "srvr_signature"
+#define MAIL_ATTR_SRVR_SIG_CURVE       "srvr_signature_curve"
+#define MAIL_ATTR_SRVR_SIG_BITS        "srvr_signature_bits"
+#define MAIL_ATTR_SRVR_SIG_DGST        "srvr_signature_digest"
+#define MAIL_ATTR_NAMADDR      "namaddr"
 #define MAIL_ATTR_SERVER_ID    "server_id"
 
  /*
index 2aff2d3f972d0cbfcbea47b33462e77610d1b825..4d98162a29813f0ba4bdc9c70cfc3affb6a7894f 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20181110"
-#define MAIL_VERSION_NUMBER    "3.1.10-RC2"
+#define MAIL_RELEASE_DATE      "20181117"
+#define MAIL_VERSION_NUMBER    "3.1.10-RC3"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index 38fa90205860e40487769edb40eb7c65db32b3b6..b54a7f0943831b9df5e78a049aa92f22461ffd1d 100644 (file)
@@ -3207,12 +3207,70 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
 
 #ifdef USE_TLS
        if (var_smtpd_tls_received_header && state->tls_context) {
-           out_fprintf(out_stream, REC_TYPE_NORM,
-                       "\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);
+           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 {
+                   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)",
+                                       state->tls_context->srvr_sig_curve);
+               else if (state->tls_context->srvr_sig_bits > 0)
+                   vstring_sprintf_append(state->buffer, " (%d bits)",
+                                        state->tls_context->srvr_sig_bits);
+               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)",
+                                       state->tls_context->clnt_sig_curve);
+               else if (state->tls_context->clnt_sig_bits > 0)
+                   vstring_sprintf_append(state->buffer, " (%d bits)",
+                                        state->tls_context->clnt_sig_bits);
+               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);
index 200e3485d897799af3737c1d45825c81ec9eb4d5..9232a1c11de904c8b502553300a7b5f8023bd66f 100644 (file)
@@ -109,6 +109,22 @@ extern const char *str_tls_level(int);
  /* Backwards compatibility with OpenSSL < 1.1.1 */
 #if OPENSSL_VERSION_NUMBER < 0x1010100fUL
 #define SSL_CTX_set_num_tickets(ctx, num) ((void)0)
+#endif
+
+ /*-
+  * Backwards compatibility with OpenSSL < 1.1.1a.
+  *
+  * In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was
+  * updated to work on both the client and the server, and was renamed to
+  * SSL_get_peer_tmp_key(), with the original name left behind as an alias.  We
+  * use the new name when available.
+  */
+#if OPENSSL_VERSION_NUMBER < 0x1010101fUL
+#undef SSL_get_signature_nid
+#define SSL_get_signature_nid(ssl, pnid) (NID_undef)
+#define tls_get_peer_dh_pubkey SSL_get_server_tmp_key
+#else
+#define tls_get_peer_dh_pubkey SSL_get_peer_tmp_key
 #endif
 
 /* SSL_CIPHER_get_name() got constified in 0.9.7g */
@@ -137,6 +153,17 @@ extern const char *str_tls_level(int);
   */
 #include <dns.h>
 
+ /*
+  * TLS role, presently for logging.
+  */
+typedef enum {
+    TLS_ROLE_CLIENT, TLS_ROLE_SERVER,
+} TLS_ROLE;
+
+typedef enum {
+    TLS_USAGE_NEW, TLS_USAGE_USED,
+} TLS_USAGE;
+
  /*
   * Names of valid tlsmgr(8) session caches.
   */
@@ -236,6 +263,17 @@ typedef struct {
     const char *cipher_name;
     int     cipher_usebits;
     int     cipher_algbits;
+    const char *kex_name;              /* shared key-exchange algorithm */
+    const char *kex_curve;             /* shared key-exchange ECDHE curve */
+    int     kex_bits;                  /* shared FFDHE key exchange bits */
+    const char *clnt_sig_name;         /* client's signature key algorithm */
+    const char *clnt_sig_curve;                /* client's ECDSA curve name */
+    int     clnt_sig_bits;             /* client's RSA signature key bits */
+    const char *clnt_sig_dgst;         /* client's signature digest */
+    const char *srvr_sig_name;         /* server's signature key algorithm */
+    const char *srvr_sig_curve;                /* server's ECDSA curve name */
+    int     srvr_sig_bits;             /* server's RSA signature key bits */
+    const char *srvr_sig_dgst;         /* server's signature digest */
     /* Private. */
     SSL    *con;
     char   *cache_type;                        /* tlsmgr(8) cache type if enabled */
@@ -431,7 +469,12 @@ extern const NAME_CODE tls_cipher_grade_table[];
 extern const char *tls_set_ciphers(TLS_APPL_STATE *, const char *,
                                           const char *, const char *);
 
-#endif
+ /*
+  * Populate TLS context with TLS 1.3-related signature parameters.
+  */
+extern void tls_get_signature_params(TLS_SESS_STATE *);
+
+#endif                                 /* TLS_INTERNAL */
 
  /*
   * tls_client.c
@@ -559,6 +602,7 @@ extern void tls_session_stop(TLS_APPL_STATE *, VSTREAM *, int, int, TLS_SESS_STA
 extern const char *tls_compile_version(void);
 extern const char *tls_run_version(void);
 extern const char **tls_pkey_algorithms(void);
+extern void tls_log_summary(TLS_ROLE, TLS_USAGE, TLS_SESS_STATE *);
 
 #ifdef TLS_INTERNAL
 
index deb24f5eebde9db0653bf5e59a48b2a88f38b587..a006484b4a203e96ddceb821270ed1f6dfaa1f25 100644 (file)
@@ -1141,16 +1141,12 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
        TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
 
     /*
-     * All the key facts in a single log entry.
+     * With the handshake done, extract TLS 1.3 signature metadata.
      */
+    tls_get_signature_params(TLScontext);
+
     if (log_mask & TLS_LOG_SUMMARY)
-       msg_info("%s TLS connection established to %s: %s with cipher %s "
-                "(%d/%d bits)",
-                !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" :
-                TLS_CERT_IS_SECURED(TLScontext) ? "Verified" :
-                TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
-             props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
-                TLScontext->cipher_usebits, TLScontext->cipher_algbits);
+       tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW, TLScontext);
 
     tls_int_seed();
 
index 1f1dc24f21fb1fc15561a01170ad374a769bb06a..5774175af09898da6e4333c0cb14f6183d754f5f 100644 (file)
@@ -4,6 +4,25 @@
 /* SUMMARY
 /*     miscellaneous TLS support routines
 /* SYNOPSIS
+/* .SH Public functions
+/* .nf
+/* .na
+/*     #include <tls.h>
+/*
+/*     void tls_log_summary(role, usage, TLScontext)
+/*     TLS_ROLE role;
+/*     TLS_USAGE usage;
+/*     TLS_SESS_STATE *TLScontext;
+/*
+/*     const char *tls_compile_version(void)
+/*
+/*     const char *tls_run_version(void)
+/*
+/*     const char **tls_pkey_algorithms(void)
+/*
+/* .SH Internal functions
+/* .nf
+/* .na
 /*     #define TLS_INTERNAL
 /*     #include <tls.h>
 /*
@@ -61,6 +80,9 @@
 /*     int     grade;
 /*     const char *exclusions;
 /*
+/*     void tls_get_signature_params(TLScontext)
+/*     TLS_SESS_STATE *TLScontext;
+/*
 /*     void    tls_print_errors()
 /*
 /*     void    tls_info_callback(ssl, where, ret)
 /*
 /*     int     tls_validate_digest(dgst)
 /*     const char *dgst;
+/* DESCRIPTION
+/*     This module implements public and internal routines that
+/*     support the TLS client and server.
 /*
-/*     const char *tls_compile_version(void)
+/*     tls_log_summary() logs a summary of a completed TLS connection.
+/*     The "role" argument must be TLS_ROLE_CLIENT for outgoing client
+/*     connections, or TLS_ROLE_SERVER for incoming server connections,
+/*     and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED.
 /*
-/*     const char *tls_run_version(void)
+/*     tls_compile_version() returns a text string description of
+/*     the compile-time TLS library.
 /*
-/*     const char **tls_pkey_algorithms(void)
-/* DESCRIPTION
-/*     This module implements routines that support the TLS client
-/*     and server internals.
+/*     tls_run_version() is just tls_compile_version() but with the runtime
+/*     version instead of the compile-time version.
+/*
+/*     tls_pkey_algorithms() returns a pointer to null-terminated
+/*     array of string constants with the names of the supported
+/*     public-key algorithms.
 /*
 /*     tls_alloc_app_context() creates an application context that
 /*     holds the SSL context for the application and related cached state.
 /*     When the input is invalid, tls_set_ciphers() logs a warning with
 /*     the specified context, and returns a null pointer result.
 /*
+/*     tls_get_signature_params() updates the "TLScontext" with handshake
+/*     signature parameters pertaining to TLS 1.3, where the ciphersuite
+/*     no longer describes the asymmetric algorithms employed in the
+/*     handshake, which are negotiated separately.  This function
+/*     has no effect for TLS 1.2 and earlier.
+/*
 /*     tls_print_errors() queries the OpenSSL error stack,
 /*     logs the error messages, and clears the error stack.
 /*
 /*
 /*     tls_validate_digest() returns non-zero if the named digest
 /*     is usable and zero otherwise.
-/*
-/*     tls_compile_version() returns a text string description of
-/*     the compile-time TLS library.
-/*
-/*     tls_run_version() is just tls_compile_version() but with the runtime
-/*     version instead of the compile-time version.
-/*
-/*     tls_pkey_algorithms() returns a pointer to null-terminated
-/*     array of string constants with the names of the supported
-/*     public-key algorithms.
 /* LICENSE
 /* .ad
 /* .fi
@@ -364,11 +391,11 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = {
     /*
      * XXX: New with OpenSSL 1.1.1, this is turned on implicitly in
      * SSL_CTX_new() and is not included in SSL_OP_ALL.  Allowing users to
-     * disable this would thus a code change that would clearing bug
-     * work-around bits in SSL_CTX, after setting SSL_OP_ALL.  Since this is
-     * presumably required for TLS 1.3 on today's Internet, the code change
-     * will be done separately later.  For now this implicit bug work-around
-     * cannot be disabled via supported Postfix mechanisms.
+     * disable this would thus be a code change that would require clearing
+     * bug work-around bits in SSL_CTX, after setting SSL_OP_ALL.  Since this
+     * is presumably required for TLS 1.3 on today's Internet, the code
+     * change will be done separately later. For now this implicit bug
+     * work-around cannot be disabled via supported Postfix mechanisms.
      */
 #ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
 #define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0
@@ -811,6 +838,224 @@ const char *tls_set_ciphers(TLS_APPL_STATE *app_ctx, const char *context,
     return (app_ctx->cipher_list = mystrdup(new_list));
 }
 
+/* tls_get_signature_params - TLS 1.3 signature details */
+
+void    tls_get_signature_params(TLS_SESS_STATE *TLScontext)
+{
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fUL && defined(TLS1_3_VERSION)
+    const char *kex_name = 0;
+    const char *kex_curve = 0;
+    const char *locl_sig_name = 0;
+    const char *locl_sig_curve = 0;
+    const char *locl_sig_dgst = 0;
+    const char *peer_sig_name = 0;
+    const char *peer_sig_curve = 0;
+    const char *peer_sig_dgst = 0;
+    int     nid;
+    int     got_kex_key;
+    SSL    *ssl = TLScontext->con;
+    int     srvr = SSL_is_server(ssl);
+    X509   *cert;
+    EVP_PKEY *pkey = 0;
+
+#ifndef OPENSSL_NO_EC
+    EC_KEY *eckey;
+
+#endif
+
+#define SIG_PROP(c, s, p) (*((s) ? &c->srvr_sig_##p : &c->clnt_sig_##p))
+
+    if (SSL_version(ssl) < TLS1_3_VERSION)
+       return;
+
+    if (tls_get_peer_dh_pubkey(ssl, &pkey)) {
+       switch (nid = EVP_PKEY_id(pkey)) {
+       default:
+           kex_name = OBJ_nid2sn(EVP_PKEY_type(nid));
+           break;
+
+       case EVP_PKEY_DH:
+           kex_name = "DHE";
+           TLScontext->kex_bits = EVP_PKEY_bits(pkey);
+           break;
+
+#ifndef OPENSSL_NO_EC
+       case EVP_PKEY_EC:
+           kex_name = "ECDHE";
+           eckey = EVP_PKEY_get0_EC_KEY(pkey);
+           nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+           kex_curve = EC_curve_nid2nist(nid);
+           if (!kex_curve)
+               kex_curve = OBJ_nid2sn(nid);
+           break;
+#endif
+       }
+       EVP_PKEY_free(pkey);
+    }
+
+    /*
+     * On the client end, the certificate may be preset, but not used, so we
+     * check via SSL_get_signature_nid().  This means that local signature
+     * data on clients requires at least 1.1.1a.
+     */
+    if (srvr || SSL_get_signature_nid(ssl, &nid))
+       cert = SSL_get_certificate(ssl);
+    else
+       cert = 0;
+
+    /* Signature algorithms for the local end of the connection */
+    if (cert) {
+       pkey = X509_get0_pubkey(cert);
+
+       /*
+        * Override the built-in name for the "ECDSA" algorithms OID, with
+        * the more familiar name.  For "RSA" keys report "RSA-PSS", which
+        * must be used with TLS 1.3.
+        */
+       if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) {
+           switch (nid) {
+           default:
+               locl_sig_name = OBJ_nid2sn(nid);
+               break;
+
+           case EVP_PKEY_RSA:
+               /* For RSA, TLS 1.3 mandates PSS signatures */
+               locl_sig_name = "RSA-PSS";
+               SIG_PROP(TLScontext, srvr, bits) = EVP_PKEY_bits(pkey);
+               break;
+
+#ifndef OPENSSL_NO_EC
+           case EVP_PKEY_EC:
+               locl_sig_name = "ECDSA";
+               eckey = EVP_PKEY_get0_EC_KEY(pkey);
+               nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+               locl_sig_curve = EC_curve_nid2nist(nid);
+               if (!locl_sig_curve)
+                   locl_sig_curve = OBJ_nid2sn(nid);
+               break;
+#endif
+           }
+       }
+
+       /*
+        * With Ed25519 and Ed448 there is no pre-signature digest, but the
+        * accessor does not fail, rather we get NID_undef.
+        */
+       if (SSL_get_signature_nid(ssl, &nid) && nid != NID_undef)
+           locl_sig_dgst = OBJ_nid2sn(nid);
+    }
+    /* Signature algorithms for the peer end of the connection */
+    if ((cert = SSL_get_peer_certificate(ssl)) != 0) {
+       pkey = X509_get0_pubkey(cert);
+
+       /*
+        * Override the built-in name for the "ECDSA" algorithms OID, with
+        * the more familiar name.  For "RSA" keys report "RSA-PSS", which
+        * must be used with TLS 1.3.
+        */
+       if ((nid = EVP_PKEY_type(EVP_PKEY_id(pkey))) != NID_undef) {
+           switch (nid) {
+           default:
+               peer_sig_name = OBJ_nid2sn(nid);
+               break;
+
+           case EVP_PKEY_RSA:
+               /* For RSA, TLS 1.3 mandates PSS signatures */
+               peer_sig_name = "RSA-PSS";
+               SIG_PROP(TLScontext, !srvr, bits) = EVP_PKEY_bits(pkey);
+               break;
+
+#ifndef OPENSSL_NO_EC
+           case EVP_PKEY_EC:
+               peer_sig_name = "ECDSA";
+               eckey = EVP_PKEY_get0_EC_KEY(pkey);
+               nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey));
+               peer_sig_curve = EC_curve_nid2nist(nid);
+               if (!peer_sig_curve)
+                   peer_sig_curve = OBJ_nid2sn(nid);
+               break;
+#endif
+           }
+       }
+
+       /*
+        * With Ed25519 and Ed448 there is no pre-signature digest, but the
+        * accessor does not fail, rather we get NID_undef.
+        */
+       if (SSL_get_peer_signature_nid(ssl, &nid) && nid != NID_undef)
+           peer_sig_dgst = OBJ_nid2sn(nid);
+    }
+    if (kex_name) {
+       TLScontext->kex_name = mystrdup(kex_name);
+       if (kex_curve)
+           TLScontext->kex_curve = mystrdup(kex_curve);
+    }
+    if (locl_sig_name) {
+       SIG_PROP(TLScontext, srvr, name) = mystrdup(locl_sig_name);
+       if (locl_sig_curve)
+           SIG_PROP(TLScontext, srvr, curve) = mystrdup(locl_sig_curve);
+       if (locl_sig_dgst)
+           SIG_PROP(TLScontext, srvr, dgst) = mystrdup(locl_sig_dgst);
+    }
+    if (peer_sig_name) {
+       SIG_PROP(TLScontext, !srvr, name) = mystrdup(peer_sig_name);
+       if (peer_sig_curve)
+           SIG_PROP(TLScontext, !srvr, curve) = mystrdup(peer_sig_curve);
+       if (peer_sig_dgst)
+           SIG_PROP(TLScontext, !srvr, dgst) = mystrdup(peer_sig_dgst);
+    }
+#endif                                         /* OPENSSL_VERSION_NUMBER ... */
+}
+
+/* tls_log_summary - TLS loglevel 1 one-liner, embellished with TLS 1.3 details */
+
+void    tls_log_summary(TLS_ROLE role, TLS_USAGE usage, TLS_SESS_STATE *ctx)
+{
+    VSTRING *msg = vstring_alloc(100);
+    const char *direction = (role == TLS_ROLE_CLIENT) ? "to" : "from";
+
+    vstring_sprintf(msg, "%s TLS connection %s %s %s: %s"
+                   " with cipher %s (%d/%d bits)",
+                   !TLS_CERT_IS_PRESENT(ctx) ? "Anonymous" :
+                   TLS_CERT_IS_SECURED(ctx) ? "Verified" :
+                   TLS_CERT_IS_TRUSTED(ctx) ? "Trusted" : "Untrusted",
+                   usage == TLS_USAGE_NEW ? "established" : "reused",
+                   direction, ctx->namaddr, ctx->protocol, ctx->cipher_name,
+                   ctx->cipher_usebits, ctx->cipher_algbits);
+
+    if (ctx->kex_name && *ctx->kex_name) {
+       vstring_sprintf_append(msg, " key-exchange %s", ctx->kex_name);
+       if (ctx->kex_curve && *ctx->kex_curve)
+           vstring_sprintf_append(msg, " (%s)", ctx->kex_curve);
+       else if (ctx->kex_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)", ctx->kex_bits);
+    }
+    if (ctx->srvr_sig_name && *ctx->srvr_sig_name) {
+       vstring_sprintf_append(msg, " server-signature %s",
+                              ctx->srvr_sig_name);
+       if (ctx->srvr_sig_curve && *ctx->srvr_sig_curve)
+           vstring_sprintf_append(msg, " (%s)", ctx->srvr_sig_curve);
+       else if (ctx->srvr_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)", ctx->srvr_sig_bits);
+       if (ctx->srvr_sig_dgst && *ctx->srvr_sig_dgst)
+           vstring_sprintf_append(msg, " server-digest %s",
+                                  ctx->srvr_sig_dgst);
+    }
+    if (ctx->clnt_sig_name && *ctx->clnt_sig_name) {
+       vstring_sprintf_append(msg, " client-signature %s",
+                              ctx->clnt_sig_name);
+       if (ctx->clnt_sig_curve && *ctx->clnt_sig_curve)
+           vstring_sprintf_append(msg, " (%s)", ctx->clnt_sig_curve);
+       else if (ctx->clnt_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)", ctx->clnt_sig_bits);
+       if (ctx->clnt_sig_dgst && *ctx->clnt_sig_dgst)
+           vstring_sprintf_append(msg, " client-digest %s",
+                                  ctx->clnt_sig_dgst);
+    }
+    msg_info("%s", vstring_str(msg));
+    vstring_free(msg);
+}
+
 /* tls_alloc_app_context - allocate TLS application context */
 
 TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask)
@@ -878,6 +1123,14 @@ TLS_SESS_STATE *tls_alloc_sess_context(int log_mask, const char *namaddr)
     TLScontext->peer_pkey_fprint = 0;
     TLScontext->protocol = 0;
     TLScontext->cipher_name = 0;
+    TLScontext->kex_name = 0;
+    TLScontext->kex_curve = 0;
+    TLScontext->clnt_sig_name = 0;
+    TLScontext->clnt_sig_curve = 0;
+    TLScontext->clnt_sig_dgst = 0;
+    TLScontext->srvr_sig_name = 0;
+    TLScontext->srvr_sig_curve = 0;
+    TLScontext->srvr_sig_dgst = 0;
     TLScontext->log_mask = log_mask;
     TLScontext->namaddr = lowercase(mystrdup(namaddr));
     TLScontext->mdalg = 0;                     /* Alias for props->mdalg */
index ea10fbda409531d847ab8b035677fae869b58f9e..62f37992cb38207937919cd3901e05a784ab9dc4 100644 (file)
@@ -239,6 +239,24 @@ void    tls_proxy_context_free(TLS_SESS_STATE *tls_context)
        myfree((void *) tls_context->protocol);
     if (tls_context->cipher_name)
        myfree((void *) tls_context->cipher_name);
+    if (tls_context->kex_name)
+       myfree((void *) tls_context->kex_name);
+    if (tls_context->kex_curve)
+       myfree((void *) tls_context->kex_curve);
+    if (tls_context->clnt_sig_name)
+       myfree((void *) tls_context->clnt_sig_name);
+    if (tls_context->clnt_sig_curve)
+       myfree((void *) tls_context->clnt_sig_curve);
+    if (tls_context->clnt_sig_dgst)
+       myfree((void *) tls_context->clnt_sig_dgst);
+    if (tls_context->srvr_sig_name)
+       myfree((void *) tls_context->srvr_sig_name);
+    if (tls_context->srvr_sig_curve)
+       myfree((void *) tls_context->srvr_sig_curve);
+    if (tls_context->srvr_sig_dgst)
+       myfree((void *) tls_context->srvr_sig_dgst);
+    if (tls_context->namaddr)
+       myfree((void *) tls_context->namaddr);
     myfree((void *) tls_context);
 }
 
index e30e8be88beea626dd26ef4e108f98ebed450354..ed08ed8b12dadf35024fd2a954c2c7281b336a20 100644 (file)
@@ -79,6 +79,30 @@ int     tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
                                 tp->cipher_usebits),
                   SEND_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS,
                                 tp->cipher_algbits),
+                  SEND_ATTR_STR(MAIL_ATTR_KEX_NAME,
+                                STRING_OR_EMPTY(tp->kex_name)),
+                  SEND_ATTR_STR(MAIL_ATTR_KEX_CURVE,
+                                STRING_OR_EMPTY(tp->kex_curve)),
+                  SEND_ATTR_INT(MAIL_ATTR_KEX_BITS,
+                                tp->kex_bits),
+                  SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_NAME,
+                                STRING_OR_EMPTY(tp->clnt_sig_name)),
+                  SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_CURVE,
+                                STRING_OR_EMPTY(tp->clnt_sig_curve)),
+                  SEND_ATTR_INT(MAIL_ATTR_CLNT_SIG_BITS,
+                                tp->clnt_sig_bits),
+                  SEND_ATTR_STR(MAIL_ATTR_CLNT_SIG_DGST,
+                                STRING_OR_EMPTY(tp->clnt_sig_dgst)),
+                  SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_NAME,
+                                STRING_OR_EMPTY(tp->srvr_sig_name)),
+                  SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_CURVE,
+                                STRING_OR_EMPTY(tp->srvr_sig_curve)),
+                  SEND_ATTR_INT(MAIL_ATTR_SRVR_SIG_BITS,
+                                tp->srvr_sig_bits),
+                  SEND_ATTR_STR(MAIL_ATTR_SRVR_SIG_DGST,
+                                STRING_OR_EMPTY(tp->srvr_sig_dgst)),
+                  SEND_ATTR_STR(MAIL_ATTR_NAMADDR,
+                                STRING_OR_EMPTY(tp->namaddr)),
                   ATTR_TYPE_END);
     return (ret);
 }
index 29a0cd9f97ebaa5101f00f339915f4a5e670641c..256781fa816e8e37e92d36d4b00f72dd07f99c8e 100644 (file)
@@ -63,6 +63,15 @@ int     tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
     VSTRING *peer_pkey_fprint = vstring_alloc(60);     /* 60 for SHA-1 */
     VSTRING *protocol = vstring_alloc(25);
     VSTRING *cipher_name = vstring_alloc(25);
+    VSTRING *kex_name = vstring_alloc(25);
+    VSTRING *kex_curve = vstring_alloc(25);
+    VSTRING *clnt_sig_name = vstring_alloc(25);
+    VSTRING *clnt_sig_curve = vstring_alloc(25);
+    VSTRING *clnt_sig_dgst = vstring_alloc(25);
+    VSTRING *srvr_sig_name = vstring_alloc(25);
+    VSTRING *srvr_sig_curve = vstring_alloc(25);
+    VSTRING *srvr_sig_dgst = vstring_alloc(25);
+    VSTRING *namaddr = vstring_alloc(100);
 
     /*
      * Note: memset() is not a portable way to initialize non-integer types.
@@ -81,6 +90,18 @@ int     tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
                                &tls_context->cipher_usebits),
                  RECV_ATTR_INT(MAIL_ATTR_CIPHER_ALGBITS,
                                &tls_context->cipher_algbits),
+                 RECV_ATTR_STR(MAIL_ATTR_KEX_NAME, kex_name),
+                 RECV_ATTR_STR(MAIL_ATTR_KEX_CURVE, kex_curve),
+                 RECV_ATTR_INT(MAIL_ATTR_KEX_BITS, &tls_context->kex_bits),
+                 RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_NAME, clnt_sig_name),
+                 RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_CURVE, clnt_sig_curve),
+       RECV_ATTR_INT(MAIL_ATTR_CLNT_SIG_BITS, &tls_context->clnt_sig_bits),
+                 RECV_ATTR_STR(MAIL_ATTR_CLNT_SIG_DGST, clnt_sig_dgst),
+                 RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_NAME, srvr_sig_name),
+                 RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_CURVE, srvr_sig_curve),
+       RECV_ATTR_INT(MAIL_ATTR_SRVR_SIG_BITS, &tls_context->srvr_sig_bits),
+                 RECV_ATTR_STR(MAIL_ATTR_SRVR_SIG_DGST, srvr_sig_dgst),
+                 RECV_ATTR_STR(MAIL_ATTR_NAMADDR, namaddr),
                  ATTR_TYPE_END);
     tls_context->peer_CN = vstring_export(peer_CN);
     tls_context->issuer_CN = vstring_export(issuer_CN);
@@ -88,7 +109,16 @@ int     tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
     tls_context->peer_pkey_fprint = vstring_export(peer_pkey_fprint);
     tls_context->protocol = vstring_export(protocol);
     tls_context->cipher_name = vstring_export(cipher_name);
-    return (ret == 9 ? 1 : -1);
+    tls_context->kex_name = vstring_export(kex_name);
+    tls_context->kex_curve = vstring_export(kex_curve);
+    tls_context->clnt_sig_name = vstring_export(clnt_sig_name);
+    tls_context->clnt_sig_curve = vstring_export(clnt_sig_curve);
+    tls_context->clnt_sig_dgst = vstring_export(clnt_sig_dgst);
+    tls_context->srvr_sig_name = vstring_export(srvr_sig_name);
+    tls_context->srvr_sig_curve = vstring_export(srvr_sig_curve);
+    tls_context->srvr_sig_dgst = vstring_export(srvr_sig_dgst);
+    tls_context->namaddr = vstring_export(namaddr);
+    return (ret == 21 ? 1 : -1);
 }
 
 #endif
index 4bc6c08c7b011111d2ddc515a211ef08e35b65c4..5a38704035e487650c6f833638bb5431f55027ca 100644 (file)
@@ -961,14 +961,12 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
        tls_stream_start(TLScontext->stream, TLScontext);
 
     /*
-     * All the key facts in a single log entry.
+     * With the handshake done, extract TLS 1.3 signature metadata.
      */
+    tls_get_signature_params(TLScontext);
+
     if (TLScontext->log_mask & TLS_LOG_SUMMARY)
-       msg_info("%s TLS connection established from %s: %s with cipher %s "
-             "(%d/%d bits)", !TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous"
-                : TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
-        TLScontext->namaddr, TLScontext->protocol, TLScontext->cipher_name,
-                TLScontext->cipher_usebits, TLScontext->cipher_algbits);
+       tls_log_summary(TLS_ROLE_SERVER, TLS_USAGE_NEW, TLScontext);
 
     tls_int_seed();