2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-03 15:45:24 +00:00

postfix-3.4-20181113

This commit is contained in:
Wietse Venema
2018-11-13 00:00:00 -05:00
committed by Viktor Dukhovni
parent 17000226f6
commit 93be1eb79b
20 changed files with 933 additions and 166 deletions

View 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.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_inline.c, util/dict_pcre.c, util/dict_random.c,
util/dict_regexp.c, util/dict_static.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.

View File

@@ -294,7 +294,8 @@ verification status.
* With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1", the Postfix SMTP * 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. 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 postfix/smtp[process-id]: Untrusted TLS connection established
to host.example.com[192.168.0.2]:25: TLSv1 with cipher cipher-name 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 * With "smtpd_tls_received_header = yes", the Postfix SMTP server will record
TLS connection information in the Received: header in the form of comments TLS connection information in the Received: header in the form of comments
(text inside parentheses). The general format depends on the (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]) Received: from host.example.com (host.example.com [192.168.0.2])
(using TLSv1 with cipher cipher-name (using TLSv1 with cipher cipher-name
@@ -320,6 +322,47 @@ verification status.
(actual-key-size/raw-key-size bits)) (actual-key-size/raw-key-size bits))
(No client certificate requested) (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 The next sections will explain what cipher-name, key-size, and peer
verification status information to expect. 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 non-export ciphers, but may they differ for the legacy export ciphers where the
actual key is artificially shortened. 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 aallwwaayyss 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
WWhhaatt ddoo ""AAnnoonnyymmoouuss"",, ""UUnnttrruusstteedd"",, eettcc.. iinn PPoossttffiixx llooggggiinngg mmeeaann?? WWhhaatt ddoo ""AAnnoonnyymmoouuss"",, ""UUnnttrruusstteedd"",, eettcc.. iinn PPoossttffiixx llooggggiinngg mmeeaann??
The verification levels below are subject to man-in-the-middle attacks to The verification levels below are subject to man-in-the-middle attacks to

View File

@@ -1,18 +1,15 @@
Wish list: Wish list:
In dict_db.h, call dbenv->close() before bailing out With DICT_FLAG_RHS_IS_FILE, should dict_update() open a
with a surrogate map. file? base64-encode the value?
In smtpd(8) and postscreen(8), set the ehlo_discard_mask 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 In postscreen, don't fork after 'postfix reload' when
psc_check_queue_length (and psc_post_queue_length?) is zero. 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 With smtpd_reject_footer=$foo in master.cf, and foo defined
in main.cf, postconf complains about an unused setting in in main.cf, postconf complains about an unused setting in
main.cf. Note that "postconf -Px" will expand $name in main.cf. Note that "postconf -Px" will expand $name in

View 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", <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 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> <blockquote>
<pre> <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 <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: server will record TLS connection information in the Received:
header in the form of comments (text inside parentheses). The general 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> <blockquote>
<pre> <pre>
@@ -430,6 +433,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
</pre> </pre>
</blockquote> </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> </ul>
<p> The next sections will explain what <i>cipher-name</i>, <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 differ for the legacy export ciphers where the actual key
is artificially shortened. </p> 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 <h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
Postfix logging mean? </a> </h2> Postfix logging mean? </a> </h2>

View File

@@ -15,10 +15,7 @@ POSTMAP(1) POSTMAP(1)
<b>DESCRIPTION</b> <b>DESCRIPTION</b>
The <a href="postmap.1.html"><b>postmap</b>(1)</a> command creates or queries one or more Postfix lookup 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 tables, or updates an existing one.
are expected to be compatible with:
<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. group and other read permissions as their source file.

View File

@@ -16,12 +16,7 @@ Postfix lookup table management
.ad .ad
.fi .fi
The \fBpostmap\fR(1) command creates or queries one or more Postfix The \fBpostmap\fR(1) command creates or queries one or more Postfix
lookup tables, or updates an existing one. The input and output lookup tables, or updates an existing one.
file formats are expected to be compatible with:
.nf
\fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR
.fi
If the result files do not exist they will be created with the If the result files do not exist they will be created with the
same group and other read permissions as their source file. same group and other read permissions as their source file.

View 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", <li> <p> With "smtp_tls_loglevel = 1" and "smtpd_tls_loglevel = 1",
the Postfix SMTP client and server will log TLS connection information 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> <blockquote>
<pre> <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 <li> <p> With "smtpd_tls_received_header = yes", the Postfix SMTP
server will record TLS connection information in the Received: server will record TLS connection information in the Received:
header in the form of comments (text inside parentheses). The general 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> <blockquote>
<pre> <pre>
@@ -430,6 +433,46 @@ Received: from host.example.com (host.example.com [192.168.0.2])
</pre> </pre>
</blockquote> </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> </ul>
<p> The next sections will explain what <i>cipher-name</i>, <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 differ for the legacy export ciphers where the actual key
is artificially shortened. </p> 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 <h2><a name="status"> What do "Anonymous", "Untrusted", etc. in
Postfix logging mean? </a> </h2> Postfix logging mean? </a> </h2>

View File

@@ -83,6 +83,7 @@ static const NAME_MASK ehlo_mask_table[] = {
"ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES, "ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES,
"DSN", EHLO_MASK_DSN, "DSN", EHLO_MASK_DSN,
"EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8, "EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8,
"SMTPUTF8", EHLO_MASK_SMTPUTF8,
"CHUNKING", EHLO_MASK_CHUNKING, "CHUNKING", EHLO_MASK_CHUNKING,
"SILENT-DISCARD", EHLO_MASK_SILENT, /* XXX In-band signaling */ "SILENT-DISCARD", EHLO_MASK_SILENT, /* XXX In-band signaling */
0, 0,

View File

@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20181105" #define MAIL_RELEASE_DATE "20181113"
#define MAIL_VERSION_NUMBER "3.4" #define MAIL_VERSION_NUMBER "3.4"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View 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) void smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
{ {
ssize_t err; int err;
if (todo < 0) if (todo < 0)
msg_panic("smtp_fputs: negative todo %ld", (long) todo); 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) void smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream)
{ {
ssize_t err; int err;
if (todo < 0) if (todo < 0)
msg_panic("smtp_fwrite: negative todo %ld", (long) todo); msg_panic("smtp_fwrite: negative todo %ld", (long) todo);

View File

@@ -10,12 +10,7 @@
/* [\fIfile_type\fR:]\fIfile_name\fR ... /* [\fIfile_type\fR:]\fIfile_name\fR ...
/* DESCRIPTION /* DESCRIPTION
/* The \fBpostmap\fR(1) command creates or queries one or more Postfix /* The \fBpostmap\fR(1) command creates or queries one or more Postfix
/* lookup tables, or updates an existing one. The input and output /* lookup tables, or updates an existing one.
/* file formats are expected to be compatible with:
/*
/* .nf
/* \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR
/* .fi
/* /*
/* If the result files do not exist they will be created with the /* If the result files do not exist they will be created with the
/* same group and other read permissions as their source file. /* same group and other read permissions as their source file.

View File

@@ -3307,12 +3307,70 @@ static void common_pre_message_handling(SMTPD_STATE *state,
#ifdef USE_TLS #ifdef USE_TLS
if (var_smtpd_tls_received_header && state->tls_context) { if (var_smtpd_tls_received_header && state->tls_context) {
out_fprintf(out_stream, REC_TYPE_NORM, int cont = 0;
"\t(using %s with cipher %s (%d/%d bits))",
vstring_sprintf(state->buffer,
"\t(using %s with cipher %s (%d/%d bits)",
state->tls_context->protocol, state->tls_context->protocol,
state->tls_context->cipher_name, state->tls_context->cipher_name,
state->tls_context->cipher_usebits, state->tls_context->cipher_usebits,
state->tls_context->cipher_algbits); 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)) { if (TLS_CERT_IS_PRESENT(state->tls_context)) {
peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN); peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
comment_sanitize(peer_CN); comment_sanitize(peer_CN);

View File

@@ -112,6 +112,30 @@ extern const char *str_tls_level(int);
/* Backwards compatibility with OpenSSL < 1.1.1 */ /* Backwards compatibility with OpenSSL < 1.1.1 */
#if OPENSSL_VERSION_NUMBER < 0x1010100fUL #if OPENSSL_VERSION_NUMBER < 0x1010100fUL
#define SSL_CTX_set_num_tickets(ctx, num) ((void)0) #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 #endif
/* SSL_CIPHER_get_name() got constified in 0.9.7g */ /* SSL_CIPHER_get_name() got constified in 0.9.7g */
@@ -239,6 +263,17 @@ typedef struct {
const char *cipher_name; const char *cipher_name;
int cipher_usebits; int cipher_usebits;
int cipher_algbits; 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. */ /* Private. */
SSL *con; SSL *con;
char *cache_type; /* tlsmgr(8) cache type if enabled */ char *cache_type; /* tlsmgr(8) cache type if enabled */
@@ -378,7 +413,8 @@ extern void tls_param_init(void);
#endif #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" #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 *, extern const char *tls_set_ciphers(TLS_APPL_STATE *, const char *,
const char *, 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 * tls_client.c

View File

@@ -860,6 +860,62 @@ static void verify_extract_print(TLS_SESS_STATE *TLScontext, X509 *peercert,
TLS_CERT_FLAG_TRUSTED | TLS_CERT_FLAG_MATCHED; 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 * 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, * 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)) && !TLS_NEVER_SECURED(props->tls_level))
TLScontext->peer_status |= TLS_CERT_FLAG_SECURED; TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
/* tls_get_signature_params(TLScontext);
* All the key facts in a single log entry.
*/
if (TLScontext->log_mask & TLS_LOG_SUMMARY) if (TLScontext->log_mask & TLS_LOG_SUMMARY)
msg_info("%s TLS connection established to %s: %s with cipher %s " log_summary(TLScontext, props);
"(%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_int_seed(); tls_int_seed();

View File

@@ -62,6 +62,9 @@
/* int grade; /* int grade;
/* const char *exclusions; /* const char *exclusions;
/* /*
/* void tls_get_signature_params(TLScontext)
/* TLS_SESS_STATE *TLScontext;
/*
/* void tls_print_errors() /* void tls_print_errors()
/* /*
/* void tls_info_callback(ssl, where, ret) /* void tls_info_callback(ssl, where, ret)
@@ -143,6 +146,12 @@
/* When the input is invalid, tls_set_ciphers() logs a warning with /* When the input is invalid, tls_set_ciphers() logs a warning with
/* the specified context, and returns a null pointer result. /* 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, /* tls_print_errors() queries the OpenSSL error stack,
/* logs the error messages, and clears the error stack. /* logs the error messages, and clears the error stack.
/* /*
@@ -362,14 +371,15 @@ static const LONG_NAME_MASK ssl_bug_tweaks[] = {
NAMEBUG(TLSEXT_PADDING), NAMEBUG(TLSEXT_PADDING),
#if 0 #if 0
/* /*
* XXX: New with OpenSSL 1.1.1, this is turned on implicitly in SSL_CTX_new() * XXX: New with OpenSSL 1.1.1, this is turned on implicitly in
* and is not included in SSL_OP_ALL. Allowing users to disable this would * SSL_CTX_new() and is not included in SSL_OP_ALL. Allowing users to
* thus a code change that would clearing bug work-around bits in SSL_CTX, * disable this would thus be a code change that would require clearing
* after setting SSL_OP_ALL. Since this is presumably required for TLS 1.3 on * bug work-around bits in SSL_CTX, after setting SSL_OP_ALL. Since this
* today's Internet, the code change will be done separately later. For now * is presumably required for TLS 1.3 on today's Internet, the code
* this implicit bug work-around cannot be disabled via supported Postfix * change will be done separately later. For now this implicit bug
* mechanisms. * work-around cannot be disabled via supported Postfix mechanisms.
*/ */
#ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT #ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
#define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0 #define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0
@@ -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)); 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_alloc_app_context - allocate TLS application context */
TLS_APPL_STATE *tls_alloc_app_context(SSL_CTX *ssl_ctx, int log_mask) 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->peer_pkey_fprint = 0;
TLScontext->protocol = 0; TLScontext->protocol = 0;
TLScontext->cipher_name = 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->log_mask = log_mask;
TLScontext->namaddr = lowercase(mystrdup(namaddr)); TLScontext->namaddr = lowercase(mystrdup(namaddr));
TLScontext->mdalg = 0; /* Alias for props->mdalg */ TLScontext->mdalg = 0; /* Alias for props->mdalg */

View 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_NAME "cipher_name"
#define TLS_ATTR_CIPHER_USEBITS "cipher_usebits" #define TLS_ATTR_CIPHER_USEBITS "cipher_usebits"
#define TLS_ATTR_CIPHER_ALGBITS "cipher_algbits" #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. * TLS_SERVER_INIT_PROPS attributes.

View File

@@ -80,6 +80,28 @@ int tls_proxy_context_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
tp->cipher_usebits), tp->cipher_usebits),
SEND_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS, SEND_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
tp->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); ATTR_TYPE_END);
/* Do not flush the stream. */ /* Do not flush the stream. */
return (ret); return (ret);

View 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 *peer_pkey_fprint = vstring_alloc(60); /* 60 for SHA-1 */
VSTRING *protocol = vstring_alloc(25); VSTRING *protocol = vstring_alloc(25);
VSTRING *cipher_name = 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) if (msg_verbose)
msg_info("begin tls_proxy_context_scan"); 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), &tls_context->cipher_usebits),
RECV_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS, RECV_ATTR_INT(TLS_ATTR_CIPHER_ALGBITS,
&tls_context->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); ATTR_TYPE_END);
/* Always construct a well-formed structure. */ /* Always construct a well-formed structure. */
tls_context->peer_CN = vstring_export(peer_CN); 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->peer_pkey_fprint = vstring_export(peer_pkey_fprint);
tls_context->protocol = vstring_export(protocol); tls_context->protocol = vstring_export(protocol);
tls_context->cipher_name = vstring_export(cipher_name); 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) { if (ret != 1) {
tls_proxy_context_free(tls_context); tls_proxy_context_free(tls_context);
tls_context = 0; tls_context = 0;
@@ -134,6 +161,22 @@ void tls_proxy_context_free(TLS_SESS_STATE *tls_context)
myfree((void *) tls_context->protocol); myfree((void *) tls_context->protocol);
if (tls_context->cipher_name) if (tls_context->cipher_name)
myfree((void *) 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); myfree((void *) tls_context);
} }

View File

@@ -345,6 +345,60 @@ static int ticket_cb(SSL *con, unsigned char name[], unsigned char iv[],
#endif #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_server_init - initialize the server-side TLS engine */
TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props) TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
@@ -504,17 +558,18 @@ TLS_APPL_STATE *tls_server_init(const TLS_SERVER_INIT_PROPS *props)
} }
if (ticketable) { if (ticketable) {
SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, ticket_cb); 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 * 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 * than one ticket per handshake. While this may be appropriate for
* communication between browsers and webservers, it is not terribly * communication between browsers and webservers, it is not terribly
* useful for MTAs, many of which other than Postfix don't do TLS * useful for MTAs, many of which other than Postfix don't do TLS
* session caching at all, and Postfix has no mechanism for storing * session caching at all, and Postfix has no mechanism for storing
* multiple session tickets, if more than one sent, the second clobbers * multiple session tickets, if more than one sent, the second
* the first. OpenSSL 1.1.1 servers default to issuing two tickets for * clobbers the first. OpenSSL 1.1.1 servers default to issuing two
* non-resumption handshakes, we reduce this to one. Our ticket * tickets for non-resumption handshakes, we reduce this to one. Our
* decryption callback already (since 2.11) asks OpenSSL to avoid * ticket decryption callback already (since 2.11) asks OpenSSL to
* issuing new tickets when the presented ticket is re-usable. * avoid issuing new tickets when the presented ticket is re-usable.
*/ */
SSL_CTX_set_num_tickets(server_ctx, 1); SSL_CTX_set_num_tickets(server_ctx, 1);
} }
@@ -951,15 +1006,16 @@ TLS_SESS_STATE *tls_server_post_accept(TLS_SESS_STATE *TLScontext)
if (TLScontext->stream != 0) if (TLScontext->stream != 0)
tls_stream_start(TLScontext->stream, TLScontext); 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. * All the key facts in a single log entry.
*/ */
if (TLScontext->log_mask & TLS_LOG_SUMMARY) if (TLScontext->log_mask & TLS_LOG_SUMMARY)
msg_info("%s TLS connection established from %s: %s with cipher %s " log_summary(TLScontext);
"(%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_int_seed(); tls_int_seed();

View File

@@ -629,7 +629,7 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
#endif #endif
#if DB_VERSION_MAJOR > 2 #if DB_VERSION_MAJOR > 2
DB_ENV *dbenv; DB_ENV *dbenv = 0;
#endif #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. * db_open() create a non-existent file for us.
*/ */
#define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC)) #define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC))
#if DB_VERSION_MAJOR <= 2
#define FREE_RETURN(e) do { \ #define FREE_RETURN(e) do { \
DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \ DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \
if (lock_fd >= 0) (void) close(lock_fd); \ if (lock_fd >= 0) (void) close(lock_fd); \
if (db_base_buf) vstring_free(db_base_buf); \ if (db_base_buf) vstring_free(db_base_buf); \
if (db_path) myfree(db_path); return (_dict); \ if (db_path) myfree(db_path); return (_dict); \
} while (0) } 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 (dict_flags & DICT_FLAG_LOCK) {
if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) { if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) {