2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-02 15:15: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,16 +15,13 @@ 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.
While the table update is in progress, signal delivery is postponed, While the table update is in progress, signal delivery is postponed,
and an exclusive, advisory, lock is placed on the entire table, in and an exclusive, advisory, lock is placed on the entire table, in
order to avoid surprises in spectator processes. order to avoid surprises in spectator processes.
<b>INPUT FILE FORMAT</b> <b>INPUT FILE FORMAT</b>
@@ -34,153 +31,153 @@ POSTMAP(1) POSTMAP(1)
<i>key</i> whitespace <i>value</i> <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 `#'. 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. starts with whitespace continues a logical line.
The <i>key</i> and <i>value</i> are processed as is, except that surrounding white 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 space is stripped off. Whitespace in lookup keys is supported as of
Postfix 3.2. Postfix 3.2.
When the <b>-F</b> option is given, the <i>value</i> must specify a filename; 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 <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. 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 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 address localpart that contains ";", or a localpart that starts or ends
with ".". 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 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 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 <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 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> <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. substitutions.
<b>COMMAND-LINE ARGUMENTS</b> <b>COMMAND-LINE ARGUMENTS</b>
<b>-b</b> Enable message body query mode. When reading lookup keys from <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 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 email message in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a> format. Each line of body content
becomes one lookup key. becomes one lookup key.
By default, the <b>-b</b> option starts generating lookup keys at the 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 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 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 parsing with <b>-m</b>. With this, the <b>-b</b> option generates no
body-style lookup keys for attachment MIME headers and for body-style lookup keys for attachment MIME headers and for
attached message/* headers. attached message/* headers.
NOTE: with "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes", the <b>-b</b> option option dis- 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. ables UTF-8 syntax checks on query keys and lookup results.
Specify the <b>-U</b> option to force UTF-8 syntax checks anyway. Specify the <b>-U</b> option to force UTF-8 syntax checks anyway.
This feature is available in Postfix version 2.6 and later. This feature is available in Postfix version 2.6 and later.
<b>-c</b> <i>config</i><b>_</b><i>dir</i> <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. 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. <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 The exit status is zero when the requested information was
found. found.
If a key value of <b>-</b> is specified, the program reads key values 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 from the standard input stream. The exit status is zero when at
least one of the requested keys was found. 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. 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 for regular expression tables. There, case folding is controlled
by appending a flag to a pattern. by appending a flag to a pattern.
<b>-F</b> When creating a map from source file, replace each value with <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 the base64-encoded content of the named file. When querying a
map, or listing a map, base64-decode each value. map, or listing a map, base64-decode each value.
<b>-h</b> Enable message header query mode. When reading lookup keys from <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 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 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 becomes one lookup key. A multi-line header becomes one lookup
key with one or more embedded newline characters. key with one or more embedded newline characters.
By default, the <b>-h</b> option generates lookup keys until the first 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- 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 cessing, enable MIME parsing with <b>-m</b>. With this, the <b>-h</b> option
also generates header-style lookup keys for attachment MIME also generates header-style lookup keys for attachment MIME
headers and for attached message/* headers. 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- 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. ables UTF-8 syntax checks on query keys and lookup results.
Specify the <b>-U</b> option to force UTF-8 syntax checks anyway. Specify the <b>-U</b> option to force UTF-8 syntax checks anyway.
This feature is available in Postfix version 2.6 and later. This feature is available in Postfix version 2.6 and later.
<b>-i</b> Incremental mode. Read entries from standard input and do not <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 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>. new database from the entries in <b>file_name</b>.
<b>-m</b> Enable MIME parsing with "<b>-b</b>" and "<b>-h</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. This feature is available in Postfix version 2.6 and later.
<b>-N</b> Include the terminating null character that terminates lookup <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 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. default for the host operating system.
<b>-n</b> Don't include the terminating null character that terminates <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 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. the default for the host operating system.
<b>-o</b> Do not release root privileges when processing a non-root input <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 file. By default, <a href="postmap.1.html"><b>postmap</b>(1)</a> drops root privileges and runs as
the source file owner instead. the source file owner instead.
<b>-p</b> Do not inherit the file access permissions from the input file <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 when creating a new file. Instead, create a new file with
default access permissions (mode 0644). default access permissions (mode 0644).
<b>-q</b> <i>key</i> Search the specified maps for <i>key</i> and write the first value <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 found to the standard output stream. The exit status is zero
when the requested information was found. when the requested information was found.
Note: this performs a single query with the key as specified, Note: this performs a single query with the key as specified,
and does not make iterative queries with substrings of the key 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> 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. <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 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> 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 output for each key that was found. The exit status is zero when
at least one of the requested keys was found. 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. existing entries, and make those updates anyway.
<b>-s</b> Retrieve all database elements, and write one line of <i>key value</i> <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 output for each element. The elements are printed in database
order, which is not necessarily the same as the original input order, which is not necessarily the same as the original input
order. 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. is not available for all database types.
<b>-u</b> Disable UTF-8 support. UTF-8 support is enabled by default when <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 "<a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> = yes". It requires that keys and values are
valid UTF-8 strings. 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>-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>-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. 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. existing entries, and ignore those attempts.
Arguments: 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 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: 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>. <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- This is available on systems with support for <b>db</b> data-
bases. bases.
<b>cdb</b> The output consists of one file, named <i>file</i><b>_</b><i>name</i><b>.cdb</b>. <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- This is available on systems with support for <b>cdb</b> data-
bases. bases.
<b>dbm</b> The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and <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 <i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>dbm</b> databases. 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>. <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- This is available on systems with support for <b>db</b> data-
bases. bases.
<b>fail</b> A table that reliably fails all requests. The lookup ta- <b>fail</b> A table that reliably fails all requests. The lookup ta-
ble name is used for logging only. This table exists to ble name is used for logging only. This table exists to
simplify Postfix error tests. 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 <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 <i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>sdbm</b> databases. for <b>sdbm</b> databases.
When no <i>file</i><b>_</b><i>type</i> is specified, the software uses the database 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 type specified via the <b><a href="postconf.5.html#default_database_type">default_database_type</a></b> configuration
parameter. parameter.
<i>file</i><b>_</b><i>name</i> <i>file</i><b>_</b><i>name</i>
@@ -226,11 +223,11 @@ POSTMAP(1) POSTMAP(1)
<b>DIAGNOSTICS</b> <b>DIAGNOSTICS</b>
Problems are logged to the standard error stream and to <b>syslogd</b>(8). No 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. 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- <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. status in case of failure.
<b>ENVIRONMENT</b> <b>ENVIRONMENT</b>
@@ -241,12 +238,12 @@ POSTMAP(1) POSTMAP(1)
Enable verbose logging for debugging purposes. Enable verbose logging for debugging purposes.
<b>CONFIGURATION PARAMETERS</b> <b>CONFIGURATION PARAMETERS</b>
The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro- 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> 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. <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> <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. DB hash or btree tables.
<b><a href="postconf.5.html#berkeley_db_read_buffer_size">berkeley_db_read_buffer_size</a> (131072)</b> <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. hash or btree tables.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b> <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. figuration files.
<b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b> <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. 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> <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 The list of environment parameters that a privileged Postfix
process will import from a non-Postfix parent process, or process will import from a non-Postfix parent process, or
name=value environment overrides. name=value environment overrides.
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b> <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. 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> <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging. The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b> <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". records, so that, for example, "smtpd" becomes "prefix/smtpd".
<b>SEE ALSO</b> <b>SEE ALSO</b>

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))",
state->tls_context->protocol, vstring_sprintf(state->buffer,
state->tls_context->cipher_name, "\t(using %s with cipher %s (%d/%d bits)",
state->tls_context->cipher_usebits, state->tls_context->protocol,
state->tls_context->cipher_algbits); 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)) { 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,15 +371,16 @@ 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() /*
* and is not included in SSL_OP_ALL. Allowing users to disable this would * XXX: New with OpenSSL 1.1.1, this is turned on implicitly in
* thus a code change that would clearing bug work-around bits in SSL_CTX, * SSL_CTX_new() and is not included in SSL_OP_ALL. Allowing users to
* after setting SSL_OP_ALL. Since this is presumably required for TLS 1.3 on * disable this would thus be a code change that would require clearing
* today's Internet, the code change will be done separately later. For now * bug work-around bits in SSL_CTX, after setting SSL_OP_ALL. Since this
* this implicit bug work-around cannot be disabled via supported Postfix * is presumably required for TLS 1.3 on today's Internet, the code
* mechanisms. * 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 #ifndef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
#define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0 #define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0
#endif #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)); 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,18 +558,19 @@ 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 /*
* than one ticket per handshake. While this may be appropriate for * OpenSSL 1.1.1 introduces support for TLS 1.3, which can issue more
* communication between browsers and webservers, it is not terribly * than one ticket per handshake. While this may be appropriate for
* useful for MTAs, many of which other than Postfix don't do TLS * communication between browsers and webservers, it is not terribly
* session caching at all, and Postfix has no mechanism for storing * useful for MTAs, many of which other than Postfix don't do TLS
* multiple session tickets, if more than one sent, the second clobbers * session caching at all, and Postfix has no mechanism for storing
* the first. OpenSSL 1.1.1 servers default to issuing two tickets for * multiple session tickets, if more than one sent, the second
* non-resumption handshakes, we reduce this to one. Our ticket * clobbers the first. OpenSSL 1.1.1 servers default to issuing two
* decryption callback already (since 2.11) asks OpenSSL to avoid * tickets for non-resumption handshakes, we reduce this to one. Our
* issuing new tickets when the presented ticket is re-usable. * 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); SSL_CTX_set_num_tickets(server_ctx, 1);
} }
#endif #endif
@@ -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) {