]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.4-20181113
authorWietse Venema <wietse@porcupine.org>
Tue, 13 Nov 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Wed, 14 Nov 2018 01:56:43 +0000 (20:56 -0500)
20 files changed:
postfix/HISTORY
postfix/README_FILES/FORWARD_SECRECY_README
postfix/WISHLIST
postfix/html/FORWARD_SECRECY_README.html
postfix/html/postmap.1.html
postfix/man/man1/postmap.1
postfix/proto/FORWARD_SECRECY_README.html
postfix/src/global/ehlo_mask.c
postfix/src/global/mail_version.h
postfix/src/global/smtp_stream.c
postfix/src/postmap/postmap.c
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.h
postfix/src/tls/tls_proxy_context_print.c
postfix/src/tls/tls_proxy_context_scan.c
postfix/src/tls/tls_server.c
postfix/src/util/dict_db.c

index ad085d635156fba94b6b0c7370a6a1b0ac304a0b..79936f2cbaea93c4ad8bac4f448ac7c1379044ac 100644 (file)
@@ -23758,3 +23758,30 @@ Apologies for any names omitted.
        util/dict.c, util/dict.h, util/dict_cidr.c, util/dict_file.c,
        util/dict_inline.c, util/dict_pcre.c, util/dict_random.c,
        util/dict_regexp.c, util/dict_static.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.
+
+       Documentation: the postmap(1) manpage no longer refers to
+       compatibility with Sendmail's makemap command. File:
+       postmap/postmap.c.
+
+       Cleanup: don't use ssize_t for boolean result. File:
+       global/smtp_stream.c. Memory leak: the Berkeley DB client
+       leaked a small amount of memory asfter failing to open a
+       table. File: util/dict_db.c.
+
+       Cleanup: memory leak caused by missing dbenv->close() call
+       after failing to open a Berkeley DB table. File: util/dict_db.c.
+
+20181112
+
+       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,
+       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 13c161832f33e872818ddeb4ab7b433cf6a1828c..2b58e4828252d98c3a1c24aa021a547b0b902e60 100644 (file)
@@ -294,7 +294,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
@@ -307,7 +308,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
@@ -320,6 +322,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 an 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.
 
@@ -361,6 +404,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
index 840ab68430890fa3a87617f4b0d85bc10c2d2f06..6b78d3f2f5089831fe9ab64ddc6732e2c17f3939 100644 (file)
@@ -1,18 +1,15 @@
 Wish list:
 
-       In dict_db.h, call dbenv->close() before bailing out
-       with a surrogate map.
+       With DICT_FLAG_RHS_IS_FILE, should dict_update() open a
+       file? base64-encode the value?
 
        In smtpd(8) and postscreen(8), set the ehlo_discard_mask
-       to ~0 so that STARTTLS, BDAT, DSN, etc. won't work.
+       to ~0 so that STARTTLS, BDAT, DSN, etc. work only for clients
+       that send EHLO.
 
        In postscreen, don't fork after 'postfix reload' when
        psc_check_queue_length (and psc_post_queue_length?) is zero.
 
-       In smtp_stream.c, replace `ssize_t err' with `int err'.
-
-       In ehlo_mask.c, replace "EHLO_MASK_SMTPUTF8" with "SMTPUTF8".
-
        With smtpd_reject_footer=$foo in master.cf, and foo defined
        in main.cf, postconf complains about an unused setting in
        main.cf. Note that "postconf -Px" will expand $name in
index eb183c10eb63981b39351a78a9b7e54b52b0356b..3fa0e78c5d8190ed4e08f29a5f93fd697d43f02a 100644 (file)
@@ -397,7 +397,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>
@@ -414,7 +416,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>
@@ -430,6 +433,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 an 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>,
@@ -481,6 +524,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 6ff8246f89fe31fb2b95f693db44d83f44cb2869..d7a2056609c872c805bb88267c0a2f6bf72ae73f 100644 (file)
@@ -15,16 +15,13 @@ POSTMAP(1)                                                          POSTMAP(1)
 
 <b>DESCRIPTION</b>
        The  <a href="postmap.1.html"><b>postmap</b>(1)</a>  command  creates or queries one or more Postfix lookup
-       tables, or updates an existing one. The input and output  file  formats
-       are expected to be compatible with:
+       tables, or updates an existing one.
 
-           <b>makemap</b> <i>file</i><b>_</b><i>type file</i><b>_</b><i>name</i> &lt; <i>file</i><b>_</b><i>name</i>
-
-       If  the  result  files  do not exist they will be created with the same
+       If the result files do not exist they will be  created  with  the  same
        group and other read permissions as their source file.
 
-       While the table update is in progress, signal  delivery  is  postponed,
-       and  an  exclusive,  advisory,  lock  is placed on the entire table, in
+       While  the  table  update is in progress, signal delivery is postponed,
+       and an exclusive, advisory, lock is placed  on  the  entire  table,  in
        order to avoid surprises in spectator processes.
 
 <b>INPUT FILE FORMAT</b>
@@ -34,153 +31,153 @@ POSTMAP(1)                                                          POSTMAP(1)
 
                    <i>key</i> whitespace <i>value</i>
 
-       <b>o</b>      Empty lines and whitespace-only lines are ignored, as are  lines
+       <b>o</b>      Empty  lines and whitespace-only lines are ignored, as are lines
               whose first non-whitespace character is a `#'.
 
-       <b>o</b>      A  logical  line  starts  with  non-whitespace text. A line that
+       <b>o</b>      A logical line starts with  non-whitespace  text.  A  line  that
               starts with whitespace continues a logical line.
 
-       The <i>key</i> and <i>value</i> are processed as is, except  that  surrounding  white
-       space  is  stripped  off.  Whitespace in lookup keys is supported as of
+       The  <i>key</i>  and  <i>value</i> are processed as is, except that surrounding white
+       space is stripped off. Whitespace in lookup keys  is  supported  as  of
        Postfix 3.2.
 
-       When the <b>-F</b> option  is  given,  the  <i>value</i>  must  specify  a  filename;
-       <a href="postmap.1.html"><b>postmap</b>(1)</a>  will  store the base64-encoded content of that file instead
+       When  the  <b>-F</b>  option  is  given,  the  <i>value</i>  must specify a filename;
+       <a href="postmap.1.html"><b>postmap</b>(1)</a> will store the base64-encoded content of that  file  instead
        of the <i>value</i> itself.
 
-       When the <i>key</i> specifies email address information, the localpart  should
+       When  the <i>key</i> specifies email address information, the localpart should
        be enclosed with double quotes if required by <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>. For example, an
        address localpart that contains ";", or a localpart that starts or ends
        with ".".
 
-       By  default  the  lookup key is mapped to lowercase to make the lookups
+       By default the lookup key is mapped to lowercase to  make  the  lookups
        case insensitive; as of Postfix 2.3 this case folding happens only with
        tables whose lookup keys are fixed-case strings such as <a href="DATABASE_README.html#types">btree</a>:, <a href="DATABASE_README.html#types">dbm</a>: or
        <a href="DATABASE_README.html#types">hash</a>:. With earlier versions, the lookup key is folded even with tables
-       where  a lookup field can match both upper and lower case text, such as
-       <a href="regexp_table.5.html">regexp</a>: and <a href="pcre_table.5.html">pcre</a>:. This resulted in loss of  information  with  $<i>number</i>
+       where a lookup field can match both upper and lower case text, such  as
+       <a href="regexp_table.5.html">regexp</a>:  and  <a href="pcre_table.5.html">pcre</a>:.  This resulted in loss of information with $<i>number</i>
        substitutions.
 
 <b>COMMAND-LINE ARGUMENTS</b>
-       <b>-b</b>     Enable  message  body  query mode. When reading lookup keys from
-              standard input with "<b>-q -</b>", process the input as  if  it  is  an
-              email  message  in  <a href="http://tools.ietf.org/html/rfc5322">RFC  5322</a> format.  Each line of body content
+       <b>-b</b>     Enable message body query mode. When reading  lookup  keys  from
+              standard  input  with  "<b>-q  -</b>", process the input as if it is an
+              email message in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> format.  Each  line  of  body  content
               becomes one lookup key.
 
-              By default, the <b>-b</b> option starts generating lookup keys  at  the
-              first  non-header line, and stops when the end of the message is
-              reached.  To simulate  <a href="header_checks.5.html"><b>body_checks</b>(5)</a>  processing,  enable  MIME
-              parsing   with  <b>-m</b>.  With  this,  the  <b>-b</b>  option  generates  no
-              body-style lookup keys  for  attachment  MIME  headers  and  for
+              By  default,  the <b>-b</b> option starts generating lookup keys at the
+              first non-header line, and stops when the end of the message  is
+              reached.   To  simulate  <a href="header_checks.5.html"><b>body_checks</b>(5)</a>  processing, enable MIME
+              parsing  with  <b>-m</b>.  With  this,  the  <b>-b</b>  option  generates   no
+              body-style  lookup  keys  for  attachment  MIME  headers and for
               attached message/* headers.
 
-              NOTE:  with  "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>  = yes", the <b>-b</b> option option dis-
-              ables UTF-8 syntax checks on  query  keys  and  lookup  results.
+              NOTE: with "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes", the <b>-b</b>  option  option  dis-
+              ables  UTF-8  syntax  checks  on  query keys and lookup results.
               Specify the <b>-U</b> option to force UTF-8 syntax checks anyway.
 
               This feature is available in Postfix version 2.6 and later.
 
        <b>-c</b> <i>config</i><b>_</b><i>dir</i>
-              Read  the  <a href="postconf.5.html"><b>main.cf</b></a>  configuration  file  in  the named directory
+              Read the <a href="postconf.5.html"><b>main.cf</b></a>  configuration  file  in  the  named  directory
               instead of the default configuration directory.
 
-       <b>-d</b> <i>key</i> Search the specified maps for <i>key</i> and remove one entry per  map.
-              The  exit  status  is  zero  when  the requested information was
+       <b>-d</b> <i>key</i> Search  the specified maps for <i>key</i> and remove one entry per map.
+              The exit status is  zero  when  the  requested  information  was
               found.
 
-              If a key value of <b>-</b> is specified, the program reads  key  values
-              from  the standard input stream. The exit status is zero when at
+              If  a  key value of <b>-</b> is specified, the program reads key values
+              from the standard input stream. The exit status is zero when  at
               least one of the requested keys was found.
 
-       <b>-f</b>     Do not fold the lookup key  to  lower  case  while  creating  or
+       <b>-f</b>     Do  not  fold  the  lookup  key  to lower case while creating or
               querying a table.
 
-              With  Postfix  version  2.3 and later, this option has no effect
+              With Postfix version 2.3 and later, this option  has  no  effect
               for regular expression tables. There, case folding is controlled
               by appending a flag to a pattern.
 
-       <b>-F</b>     When  creating  a  map from source file, replace each value with
-              the base64-encoded content of the named file.  When  querying  a
+       <b>-F</b>     When creating a map from source file, replace  each  value  with
+              the  base64-encoded  content of the named file.  When querying a
               map, or listing a map, base64-decode each value.
 
-       <b>-h</b>     Enable  message header query mode. When reading lookup keys from
-              standard input with "<b>-q -</b>", process the input as  if  it  is  an
-              email  message  in  <a href="http://tools.ietf.org/html/rfc5322">RFC  5322</a>  format.  Each logical header line
-              becomes one lookup key. A multi-line header becomes  one  lookup
+       <b>-h</b>     Enable message header query mode. When reading lookup keys  from
+              standard  input  with  "<b>-q  -</b>", process the input as if it is an
+              email message in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>  format.   Each  logical  header  line
+              becomes  one  lookup key. A multi-line header becomes one lookup
               key with one or more embedded newline characters.
 
-              By  default, the <b>-h</b> option generates lookup keys until the first
-              non-header line is reached.  To simulate  <a href="header_checks.5.html"><b>header_checks</b>(5)</a>  pro-
-              cessing,  enable  MIME parsing with <b>-m</b>. With this, the <b>-h</b> option
-              also generates header-style  lookup  keys  for  attachment  MIME
+              By default, the <b>-h</b> option generates lookup keys until the  first
+              non-header  line  is reached.  To simulate <a href="header_checks.5.html"><b>header_checks</b>(5)</a> pro-
+              cessing, enable MIME parsing with <b>-m</b>. With this, the  <b>-h</b>  option
+              also  generates  header-style  lookup  keys  for attachment MIME
               headers and for attached message/* headers.
 
-              NOTE:  with  "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>  = yes", the <b>-b</b> option option dis-
-              ables UTF-8 syntax checks on  query  keys  and  lookup  results.
+              NOTE: with "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes", the <b>-b</b>  option  option  dis-
+              ables  UTF-8  syntax  checks  on  query keys and lookup results.
               Specify the <b>-U</b> option to force UTF-8 syntax checks anyway.
 
               This feature is available in Postfix version 2.6 and later.
 
-       <b>-i</b>     Incremental  mode.  Read  entries from standard input and do not
-              truncate an existing database. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> creates  a
+       <b>-i</b>     Incremental mode. Read entries from standard input  and  do  not
+              truncate  an existing database. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> creates a
               new database from the entries in <b>file_name</b>.
 
        <b>-m</b>     Enable MIME parsing with "<b>-b</b>" and "<b>-h</b>".
 
               This feature is available in Postfix version 2.6 and later.
 
-       <b>-N</b>     Include  the  terminating  null character that terminates lookup
-              keys and values. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a>  does  whatever  is  the
+       <b>-N</b>     Include the terminating null character  that  terminates  lookup
+              keys  and  values.  By  default, <a href="postmap.1.html"><b>postmap</b>(1)</a> does whatever is the
               default for the host operating system.
 
-       <b>-n</b>     Don't  include  the  terminating  null character that terminates
-              lookup keys and values. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> does whatever  is
+       <b>-n</b>     Don't include the terminating  null  character  that  terminates
+              lookup  keys and values. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> does whatever is
               the default for the host operating system.
 
-       <b>-o</b>     Do  not release root privileges when processing a non-root input
-              file. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> drops root privileges and  runs  as
+       <b>-o</b>     Do not release root privileges when processing a non-root  input
+              file.  By  default, <a href="postmap.1.html"><b>postmap</b>(1)</a> drops root privileges and runs as
               the source file owner instead.
 
-       <b>-p</b>     Do  not  inherit the file access permissions from the input file
-              when creating a new file.   Instead,  create  a  new  file  with
+       <b>-p</b>     Do not inherit the file access permissions from the  input  file
+              when  creating  a  new  file.   Instead,  create a new file with
               default access permissions (mode 0644).
 
-       <b>-q</b> <i>key</i> Search  the  specified  maps  for  <i>key</i> and write the first value
-              found to the standard output stream. The  exit  status  is  zero
+       <b>-q</b> <i>key</i> Search the specified maps for <i>key</i>  and  write  the  first  value
+              found  to  the  standard  output stream. The exit status is zero
               when the requested information was found.
 
-              Note:  this  performs  a single query with the key as specified,
-              and does not make iterative queries with substrings of  the  key
-              as  described  for  <a href="access.5.html">access(5)</a>,  <a href="canonical.5.html">canonical(5)</a>, <a href="transport.5.html">transport(5)</a>, <a href="virtual.5.html">vir-</a>
+              Note: this performs a single query with the  key  as  specified,
+              and  does  not make iterative queries with substrings of the key
+              as described for  <a href="access.5.html">access(5)</a>,  <a href="canonical.5.html">canonical(5)</a>,  <a href="transport.5.html">transport(5)</a>,  <a href="virtual.5.html">vir-</a>
               <a href="virtual.5.html">tual(5)</a> and other Postfix table-driven features.
 
-              If a key value of <b>-</b> is specified, the program reads  key  values
-              from  the standard input stream and writes one line of <i>key value</i>
+              If  a  key value of <b>-</b> is specified, the program reads key values
+              from the standard input stream and writes one line of <i>key  value</i>
               output for each key that was found. The exit status is zero when
               at least one of the requested keys was found.
 
-       <b>-r</b>     When  updating a table, do not complain about attempts to update
+       <b>-r</b>     When updating a table, do not complain about attempts to  update
               existing entries, and make those updates anyway.
 
-       <b>-s</b>     Retrieve all database elements, and write one line of <i>key  value</i>
-              output  for  each  element. The elements are printed in database
-              order, which is not necessarily the same as the  original  input
+       <b>-s</b>     Retrieve  all database elements, and write one line of <i>key value</i>
+              output for each element. The elements are  printed  in  database
+              order,  which  is not necessarily the same as the original input
               order.
 
-              This  feature is available in Postfix version 2.2 and later, and
+              This feature is available in Postfix version 2.2 and later,  and
               is not available for all database types.
 
-       <b>-u</b>     Disable UTF-8 support. UTF-8 support is enabled by default  when
-              "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a>  =  yes".  It requires that keys and values are
+       <b>-u</b>     Disable  UTF-8 support. UTF-8 support is enabled by default when
+              "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes". It requires that keys  and  values  are
               valid UTF-8 strings.
 
        <b>-U</b>     With "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes", force UTF-8 syntax checks with the
               <b>-b</b> and <b>-h</b> options.
 
-       <b>-v</b>     Enable  verbose  logging  for  debugging  purposes.  Multiple <b>-v</b>
+       <b>-v</b>     Enable verbose  logging  for  debugging  purposes.  Multiple  <b>-v</b>
               options make the software increasingly verbose.
 
-       <b>-w</b>     When updating a table, do not complain about attempts to  update
+       <b>-w</b>     When  updating a table, do not complain about attempts to update
               existing entries, and ignore those attempts.
 
        Arguments:
@@ -192,32 +189,32 @@ POSTMAP(1)                                                          POSTMAP(1)
               The <a href="postmap.1.html"><b>postmap</b>(1)</a> command can query any supported file type, but it
               can create only the following file types:
 
-              <b>btree</b>  The  output  file  is  a  btree file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
-                     This is available on systems with support  for  <b>db</b>  data-
+              <b>btree</b>  The output file is  a  btree  file,  named  <i>file</i><b>_</b><i>name</i><b>.db</b>.
+                     This  is  available  on systems with support for <b>db</b> data-
                      bases.
 
-              <b>cdb</b>    The  output  consists  of  one file, named <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
-                     This is available on systems with support for  <b>cdb</b>  data-
+              <b>cdb</b>    The output consists of  one  file,  named  <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
+                     This  is  available on systems with support for <b>cdb</b> data-
                      bases.
 
               <b>dbm</b>    The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
                      <i>file</i><b>_</b><i>name</i><b>.dir</b>.  This is available on systems with support
                      for <b>dbm</b> databases.
 
-              <b>hash</b>   The  output  file  is  a hashed file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
-                     This is available on systems with support  for  <b>db</b>  data-
+              <b>hash</b>   The output file is a  hashed  file,  named  <i>file</i><b>_</b><i>name</i><b>.db</b>.
+                     This  is  available  on systems with support for <b>db</b> data-
                      bases.
 
-              <b>fail</b>   A  table that reliably fails all requests. The lookup ta-
-                     ble name is used for logging only. This table  exists  to
+              <b>fail</b>   A table that reliably fails all requests. The lookup  ta-
+                     ble  name  is used for logging only. This table exists to
                      simplify Postfix error tests.
 
               <b>sdbm</b>   The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
                      <i>file</i><b>_</b><i>name</i><b>.dir</b>.  This is available on systems with support
                      for <b>sdbm</b> databases.
 
-              When  no  <i>file</i><b>_</b><i>type</i> is specified, the software uses the database
-              type  specified  via  the  <b><a href="postconf.5.html#default_database_type">default_database_type</a></b>   configuration
+              When no <i>file</i><b>_</b><i>type</i> is specified, the software uses  the  database
+              type   specified  via  the  <b><a href="postconf.5.html#default_database_type">default_database_type</a></b>  configuration
               parameter.
 
        <i>file</i><b>_</b><i>name</i>
@@ -226,11 +223,11 @@ POSTMAP(1)                                                          POSTMAP(1)
 
 <b>DIAGNOSTICS</b>
        Problems are logged to the standard error stream and to <b>syslogd</b>(8).  No
-       output  means  that  no  problems  were detected. Duplicate entries are
+       output means that no problems  were  detected.  Duplicate  entries  are
        skipped and are flagged with a warning.
 
        <a href="postmap.1.html"><b>postmap</b>(1)</a> terminates with zero exit status in case of success (includ-
-       ing  successful  "<b>postmap -q</b>" lookup) and terminates with non-zero exit
+       ing successful "<b>postmap -q</b>" lookup) and terminates with  non-zero  exit
        status in case of failure.
 
 <b>ENVIRONMENT</b>
@@ -241,12 +238,12 @@ POSTMAP(1)                                                          POSTMAP(1)
               Enable verbose logging for debugging purposes.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to  this  pro-
-       gram.   The  text  below  provides  only a parameter summary. See <a href="postconf.5.html"><b>post-</b></a>
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
+       gram.  The text below provides only  a  parameter  summary.  See  <a href="postconf.5.html"><b>post-</b></a>
        <a href="postconf.5.html"><b>conf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#berkeley_db_create_buffer_size">berkeley_db_create_buffer_size</a> (16777216)</b>
-              The per-table I/O buffer size for programs that create  Berkeley
+              The  per-table I/O buffer size for programs that create Berkeley
               DB hash or btree tables.
 
        <b><a href="postconf.5.html#berkeley_db_read_buffer_size">berkeley_db_read_buffer_size</a> (131072)</b>
@@ -254,7 +251,7 @@ POSTMAP(1)                                                          POSTMAP(1)
               hash or btree tables.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of the Postfix <a href="postconf.5.html">main.cf</a> and  <a href="master.5.html">master.cf</a>  con-
+              The  default  location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
               figuration files.
 
        <b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
@@ -262,19 +259,19 @@ POSTMAP(1)                                                          POSTMAP(1)
               and <a href="postmap.1.html"><b>postmap</b>(1)</a> commands.
 
        <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
-              The list of environment parameters  that  a  privileged  Postfix
-              process  will  import  from  a  non-Postfix  parent  process, or
+              The  list  of  environment  parameters that a privileged Postfix
+              process will  import  from  a  non-Postfix  parent  process,  or
               name=value environment overrides.
 
        <b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
-              Enable preliminary SMTPUTF8 support for the protocols  described
+              Enable  preliminary SMTPUTF8 support for the protocols described
               in <a href="http://tools.ietf.org/html/rfc6531">RFC 6531</a>..6533.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
-              A  prefix  that  is  prepended  to  the  process  name in syslog
+              A prefix that  is  prepended  to  the  process  name  in  syslog
               records, so that, for example, "smtpd" becomes "prefix/smtpd".
 
 <b>SEE ALSO</b>
index c8d33aeee0f5a2a97318f62378295ba27c1f3a52..a6f32c4dbb3d49c1a1373b2fd417dc2d379a5b4c 100644 (file)
@@ -16,12 +16,7 @@ Postfix lookup table management
 .ad
 .fi
 The \fBpostmap\fR(1) command creates or queries one or more Postfix
-lookup tables, or updates an existing one. The input and output
-file formats are expected to be compatible with:
-
-.nf
-    \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR
-.fi
+lookup tables, or updates an existing one.
 
 If the result files do not exist they will be created with the
 same group and other read permissions as their source file.
index b0d96bd9e1247083e7cc7d3f5d93ea94712516a9..abeb31e0a7a5980ade16f09d5a7ca00c9f7f91f3 100644 (file)
@@ -397,7 +397,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>
@@ -414,7 +416,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>
@@ -430,6 +433,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 an 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>,
@@ -481,6 +524,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 4a84718ad80488b94be01a98e8b497708072ac32..df905e13f01de72c9c970944e74e530e3d4446da 100644 (file)
@@ -83,6 +83,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,
     "CHUNKING", EHLO_MASK_CHUNKING,
     "SILENT-DISCARD", EHLO_MASK_SILENT,        /* XXX In-band signaling */
     0,
index c7ad236440fc3988fb41881a4c6bdc2cc2a36ceb..7248c6591388bafa2d05ab7710fbcf7807b6b6c8 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      "20181105"
+#define MAIL_RELEASE_DATE      "20181113"
 #define MAIL_VERSION_NUMBER    "3.4"
 
 #ifdef SNAPSHOT
index 93d66f2530edd7a285f2322d4e3500abb87854ad..b72e20d31ec3d8406286aaec104bffd2268113c8 100644 (file)
@@ -429,7 +429,7 @@ int     smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags
 
 void    smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
 {
-    ssize_t err;
+    int     err;
 
     if (todo < 0)
        msg_panic("smtp_fputs: negative todo %ld", (long) todo);
@@ -454,7 +454,7 @@ void    smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
 
 void    smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream)
 {
-    ssize_t err;
+    int     err;
 
     if (todo < 0)
        msg_panic("smtp_fwrite: negative todo %ld", (long) todo);
index 382f3c4baeee4e0a917ae753dc3e6df8eeb521d6..16bbef942d7ec79d5413be971ee0502988ee1d98 100644 (file)
 /*             [\fIfile_type\fR:]\fIfile_name\fR ...
 /* DESCRIPTION
 /*     The \fBpostmap\fR(1) command creates or queries one or more Postfix
-/*     lookup tables, or updates an existing one. The input and output
-/*     file formats are expected to be compatible with:
-/*
-/* .nf
-/*         \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR
-/* .fi
+/*     lookup tables, or updates an existing one.
 /*
 /*     If the result files do not exist they will be created with the
 /*     same group and other read permissions as their source file.
index 009f77f5d8c35ef40005daf41b52b234001f58b2..8065c19d5d36b903e209e0ee631c33e632b4f6ee 100644 (file)
@@ -3307,12 +3307,70 @@ static void common_pre_message_handling(SMTPD_STATE *state,
 
 #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->locl_sig_name
+               && *state->tls_context->locl_sig_name) {
+               if (cont) {
+                   vstring_sprintf_append(state->buffer, " server-signature %s",
+                                        state->tls_context->locl_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->locl_sig_name);
+               }
+               if (state->tls_context->locl_sig_curve
+                   && *state->tls_context->locl_sig_curve)
+                   vstring_sprintf_append(state->buffer, " (%s)",
+                                       state->tls_context->locl_sig_curve);
+               else if (state->tls_context->locl_sig_bits > 0)
+                   vstring_sprintf_append(state->buffer, " (%d bits)",
+                                        state->tls_context->locl_sig_bits);
+               if (state->tls_context->locl_sig_dgst
+                   && *state->tls_context->locl_sig_dgst)
+                   vstring_sprintf_append(state->buffer, " server-digest %s",
+                                        state->tls_context->locl_sig_dgst);
+           }
+           if (state->tls_context->peer_sig_name
+               && *state->tls_context->peer_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->peer_sig_name);
+               if (state->tls_context->peer_sig_curve
+                   && *state->tls_context->peer_sig_curve)
+                   vstring_sprintf_append(state->buffer, " (%s)",
+                                       state->tls_context->peer_sig_curve);
+               else if (state->tls_context->peer_sig_bits > 0)
+                   vstring_sprintf_append(state->buffer, " (%d bits)",
+                                        state->tls_context->peer_sig_bits);
+               if (state->tls_context->peer_sig_dgst
+                   && *state->tls_context->peer_sig_dgst)
+                   vstring_sprintf_append(state->buffer, " client-digest %s",
+                                        state->tls_context->peer_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 9c7561828b1e98a0f6cba0a03b26a97b89e5594b..17362cd31208b8e0ba9da9f070d30c2b38edd581 100644 (file)
@@ -112,6 +112,30 @@ 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 (or some later version).
+  *
+  * The client-only interface SSL_get_server_tmp_key() is slated to be made to
+  * work on both client and server, and renamed to SSL_get_peer_tmp_key(), with
+  * the original name left behind as an alias.  We'll use the new name if/when
+  * available.
+  *
+  * XXX: Set corresponding OpenSSL version floor below when OpenSSL pull
+  * request:
+  *
+  *   <https://github.com/openssl/openssl/pull/7608>
+  *
+  * is merged, perhaps in the upcoming 1.1.1a release (at which point the XXX
+  * part of this comment can be deleted).
+  */
+#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 */
@@ -239,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 *locl_sig_name;         /* local signature key algorithm */
+    const char *locl_sig_curve;                /* local ECDSA curve name */
+    int     locl_sig_bits;             /* local RSA signature key bits */
+    const char *locl_sig_dgst;         /* local signature digest */
+    const char *peer_sig_name;         /* peer's signature key algorithm */
+    const char *peer_sig_curve;                /* peer's ECDSA curve name */
+    int     peer_sig_bits;             /* peer's RSA signature key bits */
+    const char *peer_sig_dgst;         /* peer's signature digest */
     /* Private. */
     SSL    *con;
     char   *cache_type;                        /* tlsmgr(8) cache type if enabled */
@@ -378,7 +413,8 @@ extern void tls_param_init(void);
 #endif
 
  /*
-  * OpenSSL 1.1.1 does not define a TXT macro for TLS 1.3, so we roll our own.
+  * OpenSSL 1.1.1 does not define a TXT macro for TLS 1.3, so we roll our
+  * own.
   */
 #define TLS_PROTOCOL_TXT_TLSV1_3       "TLSv1.3"
 
@@ -433,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
index 6b4dfda71dbfc7c21ee5ae099dbdc9710dcdc37c..6b3777d10e7ad4dab6338b98c1602b7fec2dd320 100644 (file)
@@ -860,6 +860,62 @@ static void verify_extract_print(TLS_SESS_STATE *TLScontext, X509 *peercert,
            TLS_CERT_FLAG_TRUSTED | TLS_CERT_FLAG_MATCHED;
 }
 
+/* log_summary - TLS loglevel 1 one-liner, embellished with TLS 1.3 details */
+
+static void log_summary(TLS_SESS_STATE *TLScontext,
+                               const TLS_CLIENT_START_PROPS *props)
+{
+    VSTRING *msg = vstring_alloc(100);
+
+    vstring_sprintf(msg, "%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);
+
+    if (TLScontext->kex_name && *TLScontext->kex_name) {
+       vstring_sprintf_append(msg, " key-exchange %s",
+                              TLScontext->kex_name);
+       if (TLScontext->kex_curve && *TLScontext->kex_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->kex_curve);
+       else if (TLScontext->kex_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->kex_bits);
+    }
+    if (TLScontext->peer_sig_name && *TLScontext->peer_sig_name) {
+       vstring_sprintf_append(msg, " server-signature %s",
+                              TLScontext->peer_sig_name);
+       if (TLScontext->peer_sig_curve && *TLScontext->peer_sig_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->peer_sig_curve);
+       else if (TLScontext->peer_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->peer_sig_bits);
+       if (TLScontext->peer_sig_dgst && *TLScontext->peer_sig_dgst)
+           vstring_sprintf_append(msg, " server-digest %s",
+                                  TLScontext->peer_sig_dgst);
+    }
+    if (TLScontext->locl_sig_name && *TLScontext->locl_sig_name) {
+       vstring_sprintf_append(msg, " client-signature %s",
+                              TLScontext->locl_sig_name);
+       if (TLScontext->locl_sig_curve && *TLScontext->locl_sig_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->locl_sig_curve);
+       else if (TLScontext->locl_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->locl_sig_bits);
+       if (TLScontext->locl_sig_dgst && *TLScontext->locl_sig_dgst)
+           vstring_sprintf_append(msg, " client-digest %s",
+                                  TLScontext->locl_sig_dgst);
+    }
+    msg_info("%s", vstring_str(msg));
+    vstring_free(msg);
+}
+
  /*
   * This is the actual startup routine for the connection. We expect that the
   * buffers are flushed and the "220 Ready to start TLS" was received by us,
@@ -1191,17 +1247,10 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
        && !TLS_NEVER_SECURED(props->tls_level))
        TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
 
-    /*
-     * All the key facts in a single log entry.
-     */
+    tls_get_signature_params(TLScontext);
+
     if (TLScontext->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);
+       log_summary(TLScontext, props);
 
     tls_int_seed();
 
index c131a5c9775818bb94175e7ed8ff79b18042def8..9550a37bea4f49cc4dd1c4ff64dc80e1cbdf0248 100644 (file)
@@ -62,6 +62,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)
 /*     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.
 /*
@@ -362,15 +371,16 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = {
     NAMEBUG(TLSEXT_PADDING),
 
 #if 0
- /*
-  * 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.
-  */
+
+    /*
+     * 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 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
 #endif
@@ -825,6 +835,175 @@ 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)
+{
+    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;
+
+#if OPENSSL_VERSION_NUMBER >= 0x1010100fUL && defined(TLS1_3_VERSION)
+#ifndef OPENSSL_NO_EC
+    EC_KEY *eckey;
+
+#endif
+    int     nid;
+    int     got_kex_key;
+    SSL    *ssl = TLScontext->con;
+    X509   *cert;
+    EVP_PKEY *pkey = 0;
+
+    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 (SSL_is_server(ssl) || 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";
+               TLScontext->locl_sig_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";
+               TLScontext->peer_sig_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);
+    }
+#endif                                         /* OPENSSL_VERSION_NUMBER >=
+                                                * 0x1010100fUL &&
+                                                * defined(TLS1_3_VERSION) */
+
+    if (kex_name) {
+       TLScontext->kex_name = mystrdup(kex_name);
+       if (kex_curve)
+           TLScontext->kex_curve = mystrdup(kex_curve);
+    }
+    if (locl_sig_name) {
+       TLScontext->locl_sig_name = mystrdup(locl_sig_name);
+       if (locl_sig_curve)
+           TLScontext->locl_sig_curve = mystrdup(locl_sig_curve);
+       if (locl_sig_dgst)
+           TLScontext->locl_sig_dgst = mystrdup(locl_sig_dgst);
+    }
+    if (peer_sig_name) {
+       TLScontext->peer_sig_name = mystrdup(peer_sig_name);
+       if (peer_sig_curve)
+           TLScontext->peer_sig_curve = mystrdup(peer_sig_curve);
+       if (peer_sig_dgst)
+           TLScontext->peer_sig_dgst = mystrdup(peer_sig_dgst);
+    }
+}
+
 /* tls_alloc_app_context - allocate TLS application context */
 
 TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask)
@@ -892,6 +1071,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->locl_sig_name = 0;
+    TLScontext->locl_sig_curve = 0;
+    TLScontext->locl_sig_dgst = 0;
+    TLScontext->peer_sig_name = 0;
+    TLScontext->peer_sig_curve = 0;
+    TLScontext->peer_sig_dgst = 0;
     TLScontext->log_mask = log_mask;
     TLScontext->namaddr = lowercase(mystrdup(namaddr));
     TLScontext->mdalg = 0;                     /* Alias for props->mdalg */
index cdfdf6388470d22f67d2e51a799e7e4a5c7e1f92..ddeeba6fadc2c37208c69bad0ad512351ba14056 100644 (file)
@@ -106,6 +106,17 @@ extern void tls_proxy_server_start_free(TLS_SERVER_START_PROPS *);
 #define TLS_ATTR_CIPHER_NAME   "cipher_name"
 #define TLS_ATTR_CIPHER_USEBITS        "cipher_usebits"
 #define TLS_ATTR_CIPHER_ALGBITS        "cipher_algbits"
+#define TLS_ATTR_KEX_NAME      "key_exchange"
+#define TLS_ATTR_KEX_CURVE     "key_exchange_curve"
+#define TLS_ATTR_KEX_BITS      "key_exchange_bits"
+#define TLS_ATTR_LOCL_SIG_NAME "locl_signature"
+#define TLS_ATTR_LOCL_SIG_CURVE        "locl_signature_curve"
+#define TLS_ATTR_LOCL_SIG_BITS "locl_signature_bits"
+#define TLS_ATTR_LOCL_SIG_DGST "locl_signature_digest"
+#define TLS_ATTR_PEER_SIG_NAME "peer_signature"
+#define TLS_ATTR_PEER_SIG_CURVE        "peer_signature_curve"
+#define TLS_ATTR_PEER_SIG_BITS "peer_signature_bits"
+#define TLS_ATTR_PEER_SIG_DGST "peer_signature_digest"
 
  /*
   * TLS_SERVER_INIT_PROPS attributes.
index a597024b2bbbf8440e2a0974ac0cb73c9ec7e626..634a3c02ca7afd1ae13041c1027fff397514c95d 100644 (file)
@@ -80,6 +80,28 @@ int     tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
                                 tp->cipher_usebits),
                   SEND_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
                                 tp->cipher_algbits),
+                  SEND_ATTR_STR(TLS_ATTR_KEX_NAME,
+                                STRING_OR_EMPTY(tp->kex_name)),
+                  SEND_ATTR_STR(TLS_ATTR_KEX_CURVE,
+                                STRING_OR_EMPTY(tp->kex_curve)),
+                  SEND_ATTR_INT(TLS_ATTR_KEX_BITS,
+                                tp->kex_bits),
+                  SEND_ATTR_STR(TLS_ATTR_LOCL_SIG_NAME,
+                                STRING_OR_EMPTY(tp->locl_sig_name)),
+                  SEND_ATTR_STR(TLS_ATTR_LOCL_SIG_CURVE,
+                                STRING_OR_EMPTY(tp->locl_sig_curve)),
+                  SEND_ATTR_INT(TLS_ATTR_LOCL_SIG_BITS,
+                                tp->locl_sig_bits),
+                  SEND_ATTR_STR(TLS_ATTR_LOCL_SIG_DGST,
+                                STRING_OR_EMPTY(tp->locl_sig_dgst)),
+                  SEND_ATTR_STR(TLS_ATTR_PEER_SIG_NAME,
+                                STRING_OR_EMPTY(tp->peer_sig_name)),
+                  SEND_ATTR_STR(TLS_ATTR_PEER_SIG_CURVE,
+                                STRING_OR_EMPTY(tp->peer_sig_curve)),
+                  SEND_ATTR_INT(TLS_ATTR_PEER_SIG_BITS,
+                                tp->peer_sig_bits),
+                  SEND_ATTR_STR(TLS_ATTR_PEER_SIG_DGST,
+                                STRING_OR_EMPTY(tp->peer_sig_dgst)),
                   ATTR_TYPE_END);
     /* Do not flush the stream. */
     return (ret);
index 74f109b3177ce89366a4f8b92893cb3119a36921..0c1060404fedb2d2e13acab56c0b41e743acb0e4 100644 (file)
@@ -78,6 +78,14 @@ 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 *locl_sig_name = vstring_alloc(25);
+    VSTRING *locl_sig_curve = vstring_alloc(25);
+    VSTRING *locl_sig_dgst = vstring_alloc(25);
+    VSTRING *peer_sig_name = vstring_alloc(25);
+    VSTRING *peer_sig_curve = vstring_alloc(25);
+    VSTRING *peer_sig_dgst = vstring_alloc(25);
 
     if (msg_verbose)
        msg_info("begin tls_proxy_context_scan");
@@ -99,6 +107,17 @@ int     tls_proxy_context_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
                                &tls_context->cipher_usebits),
                  RECV_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
                                &tls_context->cipher_algbits),
+                 RECV_ATTR_STR(TLS_ATTR_KEX_NAME, kex_name),
+                 RECV_ATTR_STR(TLS_ATTR_KEX_CURVE, kex_curve),
+                 RECV_ATTR_INT(TLS_ATTR_KEX_BITS, &tls_context->kex_bits),
+                 RECV_ATTR_STR(TLS_ATTR_LOCL_SIG_NAME, locl_sig_name),
+                 RECV_ATTR_STR(TLS_ATTR_LOCL_SIG_CURVE, locl_sig_curve),
+        RECV_ATTR_INT(TLS_ATTR_LOCL_SIG_BITS, &tls_context->locl_sig_bits),
+                 RECV_ATTR_STR(TLS_ATTR_LOCL_SIG_DGST, locl_sig_dgst),
+                 RECV_ATTR_STR(TLS_ATTR_PEER_SIG_NAME, peer_sig_name),
+                 RECV_ATTR_STR(TLS_ATTR_PEER_SIG_CURVE, peer_sig_curve),
+        RECV_ATTR_INT(TLS_ATTR_PEER_SIG_BITS, &tls_context->peer_sig_bits),
+                 RECV_ATTR_STR(TLS_ATTR_PEER_SIG_DGST, peer_sig_dgst),
                  ATTR_TYPE_END);
     /* Always construct a well-formed structure. */
     tls_context->peer_CN = vstring_export(peer_CN);
@@ -107,7 +126,15 @@ 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);
-    ret = (ret == 9 ? 1 : -1);
+    tls_context->kex_name = vstring_export(kex_name);
+    tls_context->kex_curve = vstring_export(kex_curve);
+    tls_context->locl_sig_name = vstring_export(locl_sig_name);
+    tls_context->locl_sig_curve = vstring_export(locl_sig_curve);
+    tls_context->locl_sig_dgst = vstring_export(locl_sig_dgst);
+    tls_context->peer_sig_name = vstring_export(peer_sig_name);
+    tls_context->peer_sig_curve = vstring_export(peer_sig_curve);
+    tls_context->peer_sig_dgst = vstring_export(peer_sig_dgst);
+    ret = (ret == 20 ? 1 : -1);
     if (ret != 1) {
        tls_proxy_context_free(tls_context);
        tls_context = 0;
@@ -134,6 +161,22 @@ 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->locl_sig_name)
+       myfree((void *) tls_context->locl_sig_name);
+    if (tls_context->locl_sig_curve)
+       myfree((void *) tls_context->locl_sig_curve);
+    if (tls_context->locl_sig_dgst)
+       myfree((void *) tls_context->locl_sig_dgst);
+    if (tls_context->peer_sig_name)
+       myfree((void *) tls_context->peer_sig_name);
+    if (tls_context->peer_sig_curve)
+       myfree((void *) tls_context->peer_sig_curve);
+    if (tls_context->peer_sig_dgst)
+       myfree((void *) tls_context->peer_sig_dgst);
     myfree((void *) tls_context);
 }
 
index 19abedb967fb25d7b89d23d1e28f67d955df1be4..88cb015c025bd141e415af56849f98223fec913a 100644 (file)
@@ -345,6 +345,60 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
 
 #endif
 
+/* log_summary - TLS loglevel 1 one-liner, embellished with TLS 1.3 details */
+
+static void log_summary(TLS_SESS_STATE *TLScontext)
+{
+    VSTRING *msg = vstring_alloc(100);
+
+    vstring_sprintf(msg, "%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);
+
+    if (TLScontext->kex_name && *TLScontext->kex_name) {
+       vstring_sprintf_append(msg, " key-exchange %s",
+                              TLScontext->kex_name);
+       if (TLScontext->kex_curve && *TLScontext->kex_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->kex_curve);
+       else if (TLScontext->kex_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->kex_bits);
+    }
+    if (TLScontext->locl_sig_name && *TLScontext->locl_sig_name) {
+       vstring_sprintf_append(msg, " server-signature %s",
+                              TLScontext->locl_sig_name);
+       if (TLScontext->locl_sig_curve && *TLScontext->locl_sig_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->locl_sig_curve);
+       else if (TLScontext->locl_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->locl_sig_bits);
+       if (TLScontext->locl_sig_dgst && *TLScontext->locl_sig_dgst)
+           vstring_sprintf_append(msg, " server-digest %s",
+                                  TLScontext->locl_sig_dgst);
+    }
+    if (TLScontext->peer_sig_name && *TLScontext->peer_sig_name) {
+       vstring_sprintf_append(msg, " client-signature %s",
+                              TLScontext->peer_sig_name);
+       if (TLScontext->peer_sig_curve && *TLScontext->peer_sig_curve)
+           vstring_sprintf_append(msg, " (%s)",
+                                  TLScontext->peer_sig_curve);
+       else if (TLScontext->peer_sig_bits > 0)
+           vstring_sprintf_append(msg, " (%d bits)",
+                                  TLScontext->peer_sig_bits);
+       if (TLScontext->peer_sig_dgst && *TLScontext->peer_sig_dgst)
+           vstring_sprintf_append(msg, " client-digest %s",
+                                  TLScontext->peer_sig_dgst);
+    }
+    msg_info("%s", vstring_str(msg));
+    vstring_free(msg);
+}
+
 /* tls_server_init - initialize the server-side TLS engine */
 
 TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
@@ -504,18 +558,19 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
     }
     if (ticketable) {
        SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, ticket_cb);
-        /*
-         * OpenSSL 1.1.1 introduces support for TLS 1.3, which can issue more
-         * than one ticket per handshake.  While this may be appropriate for
-         * communication between browsers and webservers, it is not terribly
-         * useful for MTAs, many of which other than Postfix don't do TLS
-         * session caching at all, and Postfix has no mechanism for storing
-         * multiple session tickets, if more than one sent, the second clobbers
-         * the first.  OpenSSL 1.1.1 servers default to issuing two tickets for
-         * non-resumption handshakes, we reduce this to one.  Our ticket
-         * decryption callback already (since 2.11) asks OpenSSL to avoid
-         * issuing new tickets when the presented ticket is re-usable.
-         */
+
+       /*
+        * OpenSSL 1.1.1 introduces support for TLS 1.3, which can issue more
+        * than one ticket per handshake.  While this may be appropriate for
+        * communication between browsers and webservers, it is not terribly
+        * useful for MTAs, many of which other than Postfix don't do TLS
+        * session caching at all, and Postfix has no mechanism for storing
+        * multiple session tickets, if more than one sent, the second
+        * clobbers the first.  OpenSSL 1.1.1 servers default to issuing two
+        * tickets for non-resumption handshakes, we reduce this to one.  Our
+        * ticket decryption callback already (since 2.11) asks OpenSSL to
+        * avoid issuing new tickets when the presented ticket is re-usable.
+        */
        SSL_CTX_set_num_tickets(server_ctx, 1);
     }
 #endif
@@ -951,15 +1006,16 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
     if (TLScontext->stream != 0)
        tls_stream_start(TLScontext->stream, TLScontext);
 
+    /*
+     * With the handshake done, extract TLS 1.3 signature metadata.
+     */
+    tls_get_signature_params(TLScontext);
+
     /*
      * All the key facts in a single log entry.
      */
     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);
+       log_summary(TLScontext);
 
     tls_int_seed();
 
index 112211de40f6696b40e706450ed0987bf23fa9a1..706d397a0f215b13bc24a06392fca8fa7c3ec378 100644 (file)
@@ -629,7 +629,7 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
 
 #endif
 #if DB_VERSION_MAJOR > 2
-    DB_ENV *dbenv;
+    DB_ENV *dbenv = 0;
 
 #endif
 
@@ -674,12 +674,22 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
      * db_open() create a non-existent file for us.
      */
 #define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC))
+#if DB_VERSION_MAJOR <= 2
 #define FREE_RETURN(e) do { \
        DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \
        if (lock_fd >= 0) (void) close(lock_fd); \
        if (db_base_buf) vstring_free(db_base_buf); \
        if (db_path) myfree(db_path); return (_dict); \
     } while (0)
+#else
+#define FREE_RETURN(e) do { \
+       DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \
+       if (dbenv) dbenv->close(dbenv, 0); \
+       if (lock_fd >= 0) (void) close(lock_fd); \
+       if (db_base_buf) vstring_free(db_base_buf); \
+       if (db_path) myfree(db_path); return (_dict); \
+    } while (0)
+#endif
 
     if (dict_flags & DICT_FLAG_LOCK) {
        if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) {