2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-01 14:45:32 +00:00

postfix-3.4-20181118

This commit is contained in:
Wietse Venema
2018-11-18 00:00:00 -05:00
committed by Viktor Dukhovni
parent 5690047582
commit 2cda534f4b
19 changed files with 271 additions and 234 deletions

2
postfix/.indent.pro vendored
View File

@@ -336,7 +336,6 @@
-TSTATE -TSTATE
-TSTRING_LIST -TSTRING_LIST
-TSTRING_TABLE -TSTRING_TABLE
-TSUMMARY_CLASS
-TSYS_EXITS_DETAIL -TSYS_EXITS_DETAIL
-TTLSMGR_SCACHE -TTLSMGR_SCACHE
-TTLSP_STATE -TTLSP_STATE
@@ -356,6 +355,7 @@
-TTLS_SESS_STATE -TTLS_SESS_STATE
-TTLS_TICKET_KEY -TTLS_TICKET_KEY
-TTLS_TLSA -TTLS_TLSA
-TTLS_USAGE
-TTLS_VINFO -TTLS_VINFO
-TTLScontext_t -TTLScontext_t
-TTOK822 -TTOK822

View File

@@ -23770,9 +23770,7 @@ Apologies for any names omitted.
postmap/postmap.c. postmap/postmap.c.
Cleanup: don't use ssize_t for boolean result. File: Cleanup: don't use ssize_t for boolean result. File:
global/smtp_stream.c. Memory leak: the Berkeley DB client global/smtp_stream.c.
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 Cleanup: memory leak caused by missing dbenv->close() call
after failing to open a Berkeley DB table. File: util/dict_db.c. after failing to open a Berkeley DB table. File: util/dict_db.c.
@@ -23794,3 +23792,26 @@ Apologies for any names omitted.
tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c, tls/tls_proxy_context_print.c, tls/tls_proxy_context_scan.c,
tls/tls_client.c, tls/tls_server.c, smtpd/smtpd.c, tls/tls_client.c, tls/tls_server.c, smtpd/smtpd.c,
posttls-finger/posttls-finger.c. posttls-finger/posttls-finger.c.
Cleanup: vstream_memopen() flags handling. File:
util/vstream.c.
Cleanup: the SMTP client now uses 'attr_print_plain'
serialization and 'attr_scan_plain' deserialization for
connection cache lookup keys, which now contain a serialized
version of the TLS context. File: smtp/smtp_session.c.
20181117
The Postfix SMTP client now logs whether an SMTP-over-TLS
connection is newly established ("TLS connection established")
or whether the connection is reused ("TLS connection reused").
Files: smtp/smtp.h, smtp/smtp_proto.c, smtp/smtp_session.c.
20181118
Cleanup, no behavior change: updated comments concerning
connection reuse, and updated some identifiers to reflect
current reality. Files: smtp_reuse.c, smtp_key.c, smtp_proto.c,
smtp_tls_policy.c, smtp.h, smtp_connect.c.

View File

@@ -12,7 +12,6 @@ GGeenneerraall ccoonnffiigguurraattiioonn
* TLS_README: TLS Encryption and authentication * TLS_README: TLS Encryption and authentication
* FORWARD_SECRECY_README: TLS Forward Secrecy * FORWARD_SECRECY_README: TLS Forward Secrecy
* IPV6_README: IP Version 6 Support * IPV6_README: IP Version 6 Support
* IPV6_README: IP Version 6 Support
* SMTPUTF8_README: SMTPUTF8 Support * SMTPUTF8_README: SMTPUTF8 Support
* COMPATIBILITY_README: Backwards-Compatibility Safety Net * COMPATIBILITY_README: Backwards-Compatibility Safety Net
* INSTALL: Installation from source code * INSTALL: Installation from source code

View File

@@ -323,7 +323,7 @@ verification status.
(No client certificate requested) (No client certificate requested)
TLS 1.3 examples. Some of the new attributes may not appear when not 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. applicable or not available in older versions of the OpenSSL library.
Received: from localhost (localhost [127.0.0.1]) Received: from localhost (localhost [127.0.0.1])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256

View File

@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
</blockquote> </blockquote>
<p> TLS 1.3 examples. Some of the new attributes may not appear when not <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> applicable or not available in older versions of the OpenSSL library. </p>
<blockquote> <blockquote>
<pre> <pre>

View File

@@ -46,8 +46,6 @@ configuration examples </a>
<li> <a href="IPV6_README.html"> IP Version 6 Support </a> <li> <a href="IPV6_README.html"> IP Version 6 Support </a>
<li> <a href="IPV6_README.html"> IP Version 6 Support </a>
<li> <a href="SMTPUTF8_README.html"> SMTPUTF8 Support </a> <li> <a href="SMTPUTF8_README.html"> SMTPUTF8 Support </a>
<li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a> <li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a>

View File

@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
</blockquote> </blockquote>
<p> TLS 1.3 examples. Some of the new attributes may not appear when not <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> applicable or not available in older versions of the OpenSSL library. </p>
<blockquote> <blockquote>
<pre> <pre>

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 "20181117" #define MAIL_RELEASE_DATE "20181118"
#define MAIL_VERSION_NUMBER "3.4" #define MAIL_VERSION_NUMBER "3.4"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View File

@@ -192,17 +192,25 @@ typedef struct SMTP_STATE {
} SMTP_STATE; } SMTP_STATE;
/* /*
* TODO: use the new SMTP_ITER name space. * Primitives to enable/disable/test connection caching and reuse based on
* the delivery request next-hop destination (i.e. not smtp_fallback_relay).
*
* Connection cache lookup by the request next-hop destination allows a reuse
* request to skip over bad hosts, and may result in a connection to a
* fall-back relay. Once we have found a 'good' host for a request next-hop,
* clear the request next-hop destination, to avoid caching less-preferred
* connections under that same request next-hop.
*/ */
#define SET_NEXTHOP_STATE(state, nexthop) { \ #define SET_SCACHE_REQUEST_NEXTHOP(state, nexthop) do { \
vstring_strcpy((state)->iterator->request_nexthop, nexthop); \ vstring_strcpy((state)->iterator->request_nexthop, nexthop); \
} } while (0)
#define FREE_NEXTHOP_STATE(state) { \ #define CLEAR_SCACHE_REQUEST_NEXTHOP(state) do { \
STR((state)->iterator->request_nexthop)[0] = 0; \ STR((state)->iterator->request_nexthop)[0] = 0; \
} } while (0)
#define HAVE_NEXTHOP_STATE(state) (STR((state)->iterator->request_nexthop)[0] != 0) #define HAVE_SCACHE_REQUEST_NEXTHOP(state) \
(STR((state)->iterator->request_nexthop)[0] != 0)
/* /*
@@ -229,6 +237,7 @@ typedef struct SMTP_STATE {
#define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */ #define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */
#define SMTP_FEATURE_XFORWARD_IDENT (1<<20) #define SMTP_FEATURE_XFORWARD_IDENT (1<<20)
#define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */ #define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */
#define SMTP_FEATURE_FROM_PROXY (1<<22) /* proxied connection */
/* /*
* Features that passivate under the endpoint. * Features that passivate under the endpoint.
@@ -617,7 +626,7 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
#define SMTP_KEY_FLAG_SERVICE (1<<0) /* service name */ #define SMTP_KEY_FLAG_SERVICE (1<<0) /* service name */
#define SMTP_KEY_FLAG_SENDER (1<<1) /* sender address */ #define SMTP_KEY_FLAG_SENDER (1<<1) /* sender address */
#define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* request nexthop */ #define SMTP_KEY_FLAG_REQ_NEXTHOP (1<<2) /* request nexthop */
#define SMTP_KEY_FLAG_NEXTHOP (1<<3) /* current nexthop */ #define SMTP_KEY_FLAG_CUR_NEXTHOP (1<<3) /* current nexthop */
#define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */ #define SMTP_KEY_FLAG_HOSTNAME (1<<4) /* remote host name */
#define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */ #define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */
#define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */ #define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */
@@ -626,7 +635,7 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
#define SMTP_KEY_MASK_ALL \ #define SMTP_KEY_MASK_ALL \
(SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \ (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \
SMTP_KEY_FLAG_REQ_NEXTHOP | \ SMTP_KEY_FLAG_REQ_NEXTHOP | \
SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \ SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \
SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL) SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
/* /*
@@ -640,14 +649,14 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \ ((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \
SMTP_KEY_FLAG_SENDER : 0) SMTP_KEY_FLAG_SENDER : 0)
#define COND_SASL_SMTP_KEY_FLAG_NEXTHOP \ #define COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
(*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_NEXTHOP : 0) (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
#ifdef USE_TLS #ifdef USE_TLS
#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \ #define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
(TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_NEXTHOP : 0) (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
#else #else
#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \ #define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
(0) (0)
#endif #endif
@@ -655,10 +664,13 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
(*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0) (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0)
/* /*
* Connection-cache destination lookup key. The SENDER attribute is a proxy * Connection-cache destination lookup key, based on the delivery request
* for sender-dependent SASL credentials (or absence thereof), and prevents * nexthop. The SENDER attribute is a proxy for sender-dependent SASL
* false connection sharing when different SASL credentials may be required * credentials (or absence thereof), and prevents false connection sharing
* for different deliveries to the same domain and port. The SERVICE * when different SASL credentials may be required for different deliveries
* to the same domain and port. Likewise, the delivery request nexthop
* (REQ_NEXTHOP) prevents false sharing of TLS identities (the destination
* key links only to appropriate endpoint lookup keys). The SERVICE
* attribute is a proxy for all request-independent configuration details. * attribute is a proxy for all request-independent configuration details.
*/ */
#define SMTP_KEY_MASK_SCACHE_DEST_LABEL \ #define SMTP_KEY_MASK_SCACHE_DEST_LABEL \
@@ -666,15 +678,18 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
| SMTP_KEY_FLAG_REQ_NEXTHOP) | SMTP_KEY_FLAG_REQ_NEXTHOP)
/* /*
* Connection-cache endpoint lookup key. The SENDER, NEXTHOP, and HOSTNAME * Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME,
* attributes are proxies for SASL credentials (or absence thereof), and * PORT and TLS_LEVEL attributes are proxies for SASL credentials and TLS
* prevent false connection sharing when different SASL credentials may be * authentication (or absence thereof), and prevent false connection sharing
* required for different deliveries to the same IP address and port. * when different SASL credentials or TLS identities may be required for
* different deliveries to the same IP address and port. The SERVICE
* attribute is a proxy for all request-independent configuration details.
*/ */
#define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \ #define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \
(SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \ (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
| COND_SASL_SMTP_KEY_FLAG_NEXTHOP | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \ | COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
| COND_TLS_SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_ADDR | \ | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \
| COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR | \
SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL) SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
/* /*
@@ -703,11 +718,6 @@ extern int smtp_mode;
/* 111 8th Avenue /* 111 8th Avenue
/* New York, NY 10011, USA /* New York, NY 10011, USA
/* /*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*
/* TLS support originally by: /* TLS support originally by:
/* Lutz Jaenicke /* Lutz Jaenicke
/* BTU Cottbus /* BTU Cottbus

View File

@@ -417,13 +417,13 @@ static void smtp_cleanup_session(SMTP_STATE *state)
state->session = 0; state->session = 0;
/* /*
* If this session was good, reset the logical next-hop state, so that we * If this session was good, reset the logical next-hop destination, so
* won't cache connections to alternate servers under the logical * that we won't cache connections to less-preferred servers under the
* next-hop destination. Otherwise we could end up skipping over the * logical next-hop destination. Otherwise we could end up skipping over
* available and more preferred servers. * the available and more-preferred servers.
*/ */
if (HAVE_NEXTHOP_STATE(state) && !throttled) if (HAVE_SCACHE_REQUEST_NEXTHOP(state) && !throttled)
FREE_NEXTHOP_STATE(state); CLEAR_SCACHE_REQUEST_NEXTHOP(state);
/* /*
* Clean up the lists with todo and dropped recipients. * Clean up the lists with todo and dropped recipients.
@@ -678,7 +678,7 @@ static int smtp_reuse_session(SMTP_STATE *state, DNS_RR **addr_list,
#endif #endif
SMTP_ITER_SAVE_DEST(state->iterator); SMTP_ITER_SAVE_DEST(state->iterator);
if (*addr_list && SMTP_RCPT_LEFT(state) > 0 if (*addr_list && SMTP_RCPT_LEFT(state) > 0
&& HAVE_NEXTHOP_STATE(state) && HAVE_SCACHE_REQUEST_NEXTHOP(state)
&& (session = smtp_reuse_nexthop(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL)) != 0) { && (session = smtp_reuse_nexthop(state, SMTP_KEY_MASK_SCACHE_DEST_LABEL)) != 0) {
session_count = 1; session_count = 1;
smtp_update_addr_list(addr_list, STR(iter->addr), session_count); smtp_update_addr_list(addr_list, STR(iter->addr), session_count);
@@ -899,7 +899,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)) { if (addr_list && (state->misc_flags & SMTP_MISC_FLAG_FIRST_NEXTHOP)) {
smtp_cache_policy(state, domain); smtp_cache_policy(state, domain);
if (state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE_MASK) if (state->misc_flags & SMTP_MISC_FLAG_CONN_CACHE_MASK)
SET_NEXTHOP_STATE(state, dest); SET_SCACHE_REQUEST_NEXTHOP(state, dest);
} }
/* /*
@@ -1124,8 +1124,8 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop,
/* /*
* Cleanup. * Cleanup.
*/ */
if (HAVE_NEXTHOP_STATE(state)) if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
FREE_NEXTHOP_STATE(state); CLEAR_SCACHE_REQUEST_NEXTHOP(state);
argv_free(sites); argv_free(sites);
} }

View File

@@ -53,7 +53,7 @@
/* .IP SMTP_KEY_FLAG_REQ_NEXTHOP /* .IP SMTP_KEY_FLAG_REQ_NEXTHOP
/* The request nexthop destination. This is a proxy for /* The request nexthop destination. This is a proxy for
/* destination-dependent, but host-independent context. /* destination-dependent, but host-independent context.
/* .IP SMTP_KEY_FLAG_NEXTHOP /* .IP SMTP_KEY_FLAG_CUR_NEXTHOP
/* The current iterator's nexthop destination (request nexthop /* The current iterator's nexthop destination (request nexthop
/* or fallback nexthop, including optional [] and :port). This /* or fallback nexthop, including optional [] and :port). This
/* is the form that users specify in a SASL or TLS lookup /* is the form that users specify in a SASL or TLS lookup
@@ -183,7 +183,7 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na,
*/ */
if (flags & SMTP_KEY_FLAG_REQ_NEXTHOP) if (flags & SMTP_KEY_FLAG_REQ_NEXTHOP)
smtp_key_append_str(buffer, STR(iter->request_nexthop), delim_na); smtp_key_append_str(buffer, STR(iter->request_nexthop), delim_na);
if (flags & SMTP_KEY_FLAG_NEXTHOP) if (flags & SMTP_KEY_FLAG_CUR_NEXTHOP)
smtp_key_append_str(buffer, STR(iter->dest), delim_na); smtp_key_append_str(buffer, STR(iter->dest), delim_na);
/* /*

View File

@@ -899,7 +899,7 @@ static int smtp_start_tls(SMTP_STATE *state)
*/ */
serverid = vstring_alloc(10); serverid = vstring_alloc(10);
smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE smtp_key_prefix(serverid, "&", state->iterator, SMTP_KEY_FLAG_SERVICE
| SMTP_KEY_FLAG_NEXTHOP /* With port */ | SMTP_KEY_FLAG_CUR_NEXTHOP /* With port */
| SMTP_KEY_FLAG_HOSTNAME | SMTP_KEY_FLAG_HOSTNAME
| SMTP_KEY_FLAG_ADDR); | SMTP_KEY_FLAG_ADDR);
@@ -1018,6 +1018,11 @@ static int smtp_start_tls(SMTP_STATE *state)
* context attributes. * context attributes.
*/ */
session->tls_context = tls_proxy_context_receive(session->stream); session->tls_context = tls_proxy_context_receive(session->stream);
if (session->tls_context) {
session->features |= SMTP_FEATURE_FROM_PROXY;
tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_NEW,
session->tls_context);
}
} }
} else { /* state->tls->conn_reuse */ } else { /* state->tls->conn_reuse */

View File

@@ -23,27 +23,26 @@
/* This module implements the SMTP client specific interface to /* This module implements the SMTP client specific interface to
/* the generic session cache infrastructure. /* the generic session cache infrastructure.
/* /*
/* A cached connection is closed when the TLS policy requires /* The caller needs to include additional state in _key_flags
/* that TLS is enabled. /* to avoid false sharing of SASL-authenticated or TLS-authenticated
/* sessions.
/* /*
/* smtp_save_session() stores the current session under the /* smtp_save_session() stores the current session under the
/* next-hop logical destination (if available) and under the /* delivery request next-hop logical destination (if applicable)
/* remote server address. The SMTP_SESSION object is destroyed. /* and under the remote server address. The SMTP_SESSION object
/* is destroyed.
/* /*
/* smtp_reuse_nexthop() looks up a cached session by its logical /* smtp_reuse_nexthop() looks up a cached session by its
/* destination, and verifies that the session is still alive. /* delivery request next-hop destination, and verifies that
/* The restored session information includes the "best MX" bit /* the session is still alive. The restored session information
/* and overrides the iterator dest, host and addr fields. /* includes the "best MX" bit and overrides the iterator dest,
/* The result is null in case of failure. /* host and addr fields. The result is null in case of failure.
/* /*
/* smtp_reuse_addr() looks up a cached session by its server /* smtp_reuse_addr() looks up a cached session by its server
/* address, and verifies that the session is still alive. /* address, and verifies that the session is still alive.
/* The restored session information does not include the "best /* The restored session information does not include the "best
/* MX" bit, and does not override the iterator dest, host and /* MX" bit, and does not override the iterator dest, host and
/* addr fields. /* addr fields. The result is null in case of failure.
/* This function is a NOOP for TLS levels stronger than "encrypt",
/* because stronger levels require certificate checks,
/* The result is null in case of failure.
/* /*
/* Arguments: /* Arguments:
/* .IP state /* .IP state
@@ -116,10 +115,16 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags,
int fd; int fd;
/* /*
* Encode the next-hop logical destination, if available. Reuse storage * Encode the delivery request next-hop destination, if applicable. Reuse
* that is also used for cache lookup queries. * storage that is also used for cache lookup queries.
*
* HAVE_SCACHE_REQUEST_NEXTHOP() controls whether or not to reuse or cache a
* connection by its delivery request next-hop destination. The idea is
* 1) to allow a reuse request to skip over bad hosts, and 2) to avoid
* caching a less-preferred connection when a more-preferred connection
* was possible.
*/ */
if (HAVE_NEXTHOP_STATE(state)) if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA, smtp_key_prefix(state->dest_label, SMTP_REUSE_KEY_DELIM_NA,
state->iterator, name_key_flags); state->iterator, name_key_flags);
@@ -138,16 +143,18 @@ void smtp_save_session(SMTP_STATE *state, int name_key_flags,
state->session = 0; state->session = 0;
/* /*
* Save the session under the next-hop name, if available. * Save the session under the delivery request next-hop name, if
* applicable.
* *
* XXX The logical to physical binding can be kept for as long as the DNS * XXX The logical to physical binding can be kept for as long as the DNS
* allows us to (but that could result in the caching of lots of unused * allows us to (but that could result in the caching of lots of unused
* bindings). The session should be idle for no more than 30 seconds or * bindings). The session should be idle for no more than 30 seconds or
* so. * so.
*/ */
if (HAVE_NEXTHOP_STATE(state)) if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label), scache_save_dest(smtp_scache, var_smtp_cache_conn,
STR(state->dest_prop), STR(state->endp_label)); STR(state->dest_label), STR(state->dest_prop),
STR(state->endp_label));
/* /*
* Save every good session under its physical endpoint address. * Save every good session under its physical endpoint address.
@@ -165,15 +172,6 @@ static SMTP_SESSION *smtp_reuse_common(SMTP_STATE *state, int fd,
SMTP_ITERATOR *iter = state->iterator; SMTP_ITERATOR *iter = state->iterator;
SMTP_SESSION *session; SMTP_SESSION *session;
/*
* Obsolete.
*/
#ifdef notdef
if (state->tls->level > TLS_LEV_NONE)
msg_panic("%s: unexpected plain-text cached session to %s",
myname, label);
#endif
/* /*
* Re-activate the SMTP_SESSION object. * Re-activate the SMTP_SESSION object.
*/ */
@@ -216,15 +214,6 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
SMTP_SESSION *session; SMTP_SESSION *session;
int fd; int fd;
/*
* Obsolete: the TLS level and nexthop are part of the connection cache
* key. TODO(tlsproxy) is the port included in the nexthop?
*/
#ifdef notdef
if (state->tls->level > TLS_LEV_NONE)
return (0);
#endif
/* /*
* Look up the session by its logical name. * Look up the session by its logical name.
*/ */
@@ -250,18 +239,13 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
int fd; int fd;
/* /*
* Allow address-based reuse only for security levels that don't require * Address-based reuse is safe for security levels that require TLS
* certificate checks. Not to be confused with a similar constraint in * certificate checks, as long as the current nexhop is included in the
* the destination label smtp_key pattern, which conditionally includes * cache lookup key (COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP). This is
* the nexthop to prevent the reuse of an authenticated connection to the * sufficient to prevent the reuse of a TLS-authenticated connection to
* same MX hostname and the same IP address, but for a different nexthop * the same MX hostname, IP address, and port, but for a different
* destination (just in case we start to send SNI with the nexthop, and * current nexthop destination with a different TLS policy.
* forget to update connection cache lookup key patterns).
*/ */
#ifdef USE_TLS
if (TLS_MUST_MATCH(state->tls->level))
return (0);
#endif
/* /*
* Look up the session by its IP address. This means that we have no * Look up the session by its IP address. This means that we have no

View File

@@ -113,11 +113,28 @@
#include <debug_peer.h> #include <debug_peer.h>
#include <mail_params.h> #include <mail_params.h>
/* TLS Library. */
#include <tls_proxy.h>
/* Application-specific. */ /* Application-specific. */
#include "smtp.h" #include "smtp.h"
#include "smtp_sasl.h" #include "smtp_sasl.h"
/*
* Local, because these are meaningful only for code in this file.
*/
#define SESS_ATTR_DEST "destination"
#define SESS_ATTR_HOST "host_name"
#define SESS_ATTR_ADDR "host_addr"
#define SESS_ATTR_DEST_FEATURES "destination_features"
#define SESS_ATTR_TLS_LEVEL "tls_level"
#define SESS_ATTR_REUSE_COUNT "reuse_count"
#define SESS_ATTR_ENDP_FEATURES "endpoint_features"
#define SESS_ATTR_EXPIRE_TIME "expire_time"
/* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */ /* smtp_session_alloc - allocate and initialize SMTP_SESSION structure */
SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter, SMTP_SESSION *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter,
@@ -183,7 +200,8 @@ void smtp_session_free(SMTP_SESSION *session)
vstream_fflush(session->stream); vstream_fflush(session->stream);
} }
if (session->tls_context) { if (session->tls_context) {
if (session->state->tls->conn_reuse) if (session->features &
(SMTP_FEATURE_FROM_CACHE | SMTP_FEATURE_FROM_PROXY))
tls_proxy_context_free(session->tls_context); tls_proxy_context_free(session->tls_context);
else else
tls_client_stop(smtp_tls_ctx, session->stream, tls_client_stop(smtp_tls_ctx, session->stream,
@@ -220,6 +238,7 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
VSTRING *endp_prop) VSTRING *endp_prop)
{ {
SMTP_ITERATOR *iter = session->iterator; SMTP_ITERATOR *iter = session->iterator;
VSTREAM *mp;
int fd; int fd;
/* /*
@@ -228,55 +247,61 @@ int smtp_session_passivate(SMTP_SESSION *session, VSTRING *dest_prop,
* destination (this information is needed for loop handling in * destination (this information is needed for loop handling in
* smtp_proto()). * smtp_proto()).
* *
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can
* serialize the properties with attr_print() instead of using ad-hoc,
* non-reusable, code and hard-coded format strings.
*
* TODO(tlsproxy): save TLS_SESS_STATE information so that we can restore
* TLS session properties.
*
* TODO: save SASL username and password information so that we can * TODO: save SASL username and password information so that we can
* correctly save a reused authenticated connection. * correctly save a reused authenticated connection.
* *
* Note: the TLS level field is always present. * These memory writes should never fail.
*/ */
vstring_sprintf(dest_prop, "%s\n%s\n%s\n%u\n%u", if ((mp = vstream_memopen(dest_prop, O_WRONLY)) == 0
STR(iter->dest), STR(iter->host), STR(iter->addr), || attr_print_plain(mp, ATTR_FLAG_NONE,
#ifdef USE_TLS SEND_ATTR_STR(SESS_ATTR_DEST, STR(iter->dest)),
iter->parent->tls->level, SEND_ATTR_STR(SESS_ATTR_HOST, STR(iter->host)),
#else SEND_ATTR_STR(SESS_ATTR_ADDR, STR(iter->addr)),
0, SEND_ATTR_INT(SESS_ATTR_DEST_FEATURES,
#endif session->features & SMTP_FEATURE_DESTINATION_MASK),
session->features & SMTP_FEATURE_DESTINATION_MASK); ATTR_TYPE_END) != 0
|| vstream_fclose(mp) != 0)
msg_fatal("smtp_session_passivate: can't save dest properties: %m");
/* /*
* Encode the physical endpoint properties: all the session properties * Encode the physical endpoint properties: all the session properties
* except for "session from cache", "best MX", or "RSET failure". * except for "session from cache", "best MX", or "RSET failure".
* Plus the TLS level, reuse count, and connection expiration time.
* *
* XXX It would be nice to have a VSTRING to VSTREAM adapter so that we can * XXX Should also record how many non-delivering mail transactions there
* serialize the properties with attr_print() instead of using obscure * were during this session, and perhaps other statistics, so that we
* hard-coded format strings. * don't reuse a session too much.
* *
* XXX Should also record an absolute time when a session must be closed, * TODO: passivate SASL username and password information so that we can
* how many non-delivering mail transactions there were during this * correctly save a reused authenticated connection.
* session, and perhaps other statistics, so that we don't reuse a
* session too much.
* *
* XXX Be sure to use unsigned types in the format string. Sign characters * These memory writes should never fail.
* would be rejected by the alldig() test on the reading end.
*/ */
vstring_sprintf(endp_prop, "%u\n%u\n%lu", if ((mp = vstream_memopen(endp_prop, O_WRONLY)) == 0
session->reuse_count, || attr_print_plain(mp, ATTR_FLAG_NONE,
session->features & SMTP_FEATURE_ENDPOINT_MASK, SEND_ATTR_INT(SESS_ATTR_TLS_LEVEL,
(long) session->expire_time); session->state->tls->level),
SEND_ATTR_INT(SESS_ATTR_REUSE_COUNT,
session->reuse_count),
SEND_ATTR_INT(SESS_ATTR_ENDP_FEATURES,
session->features & SMTP_FEATURE_ENDPOINT_MASK),
SEND_ATTR_LONG(SESS_ATTR_EXPIRE_TIME,
(long) session->expire_time),
ATTR_TYPE_END) != 0
/* /*
* Append the passivated SASL attributes. * Append the passivated TLS context. These memory writes should never
* fail.
*/ */
#ifdef notdef #ifdef USE_TLS
if (smtp_sasl_enable) || (session->tls_context
smtp_sasl_passivate(endp_prop, session); && attr_print_plain(mp, ATTR_FLAG_NONE,
SEND_ATTR_FUNC(tls_proxy_context_print,
(void *) session->tls_context),
ATTR_TYPE_END) != 0)
#endif #endif
|| vstream_fclose(mp) != 0)
msg_fatal("smtp_session_passivate: cannot save TLS context: %m");
/* /*
* Salvage the underlying file descriptor, and destroy the session * Salvage the underlying file descriptor, and destroy the session
@@ -297,50 +322,52 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
VSTRING *endp_prop) VSTRING *endp_prop)
{ {
const char *myname = "smtp_session_activate"; const char *myname = "smtp_session_activate";
VSTREAM *mp;
SMTP_SESSION *session; SMTP_SESSION *session;
char *dest_props; int endp_features; /* server features */
char *endp_props; int dest_features; /* server features */
const char *prop; long expire_time; /* session re-use expiration time */
const char *dest; int reuse_count; /* # times reused */
const char *host; TLS_SESS_STATE *tls_context = 0;
const char *addr;
unsigned features; /* server features */
time_t expire_time; /* session re-use expiration time */
unsigned reuse_count; /* # times reused */
#ifdef USE_TLS #ifdef USE_TLS
SMTP_TLS_POLICY *tls = iter->parent->tls; SMTP_TLS_POLICY *tls = iter->parent->tls;
#endif #endif
#define SMTP_SESSION_ACTIVATE_ERR_RETURN() do { \
if (tls_context) \
tls_proxy_context_free(tls_context); \
return (0); \
} while (0)
/* /*
* XXX it would be nice to have a VSTRING to VSTREAM adapter so that we * Sanity check: if TLS is required, the cached properties must contain a
* can de-serialize the properties with attr_scan(), instead of using * TLS context.
* ad-hoc, non-reusable code.
*
* XXX As a preliminary solution we use mystrtok(), but that function is not
* suitable for zero-length fields.
*/ */
endp_props = STR(endp_prop); if ((mp = vstream_memopen(endp_prop, O_RDONLY)) == 0
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { || attr_scan_plain(mp, ATTR_FLAG_NONE,
msg_warn("%s: bad cached session reuse count property", myname); RECV_ATTR_INT(SESS_ATTR_TLS_LEVEL,
return (0); &tls->level),
} RECV_ATTR_INT(SESS_ATTR_REUSE_COUNT,
reuse_count = atoi(prop); &reuse_count),
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { RECV_ATTR_INT(SESS_ATTR_ENDP_FEATURES,
msg_warn("%s: bad cached session features property", myname); &endp_features),
return (0); RECV_ATTR_LONG(SESS_ATTR_EXPIRE_TIME,
} &expire_time),
features = atoi(prop); ATTR_TYPE_END) != 4
if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) { #ifdef USE_TLS
msg_warn("%s: bad cached session expiration time property", myname); || ((tls->level > TLS_LEV_MAY
return (0); || (tls->level == TLS_LEV_MAY && vstream_peek(mp) > 0))
} && attr_scan_plain(mp, ATTR_FLAG_NONE,
#ifdef MISSING_STRTOUL RECV_ATTR_FUNC(tls_proxy_context_scan,
expire_time = strtol(prop, 0, 10); (void *) &tls_context),
#else ATTR_TYPE_END) != 1)
expire_time = strtoul(prop, 0, 10);
#endif #endif
|| vstream_fclose(mp) != 0) {
msg_warn("smtp_session_activate: bad cached endp properties");
SMTP_SESSION_ACTIVATE_ERR_RETURN();
}
/* /*
* Clobber the iterator's current nexthop, host and address fields with * Clobber the iterator's current nexthop, host and address fields with
@@ -355,36 +382,25 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
* correctly save a reused authenticated connection. * correctly save a reused authenticated connection.
*/ */
if (dest_prop && VSTRING_LEN(dest_prop)) { if (dest_prop && VSTRING_LEN(dest_prop)) {
dest_props = STR(dest_prop); if ((mp = vstream_memopen(dest_prop, O_RDONLY)) == 0
if ((dest = mystrtok(&dest_props, "\n")) == 0) { || attr_scan_plain(mp, ATTR_FLAG_NONE,
msg_warn("%s: missing cached session destination property", myname); RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest),
return (0); RECV_ATTR_STR(SESS_ATTR_HOST, iter->host),
RECV_ATTR_STR(SESS_ATTR_ADDR, iter->addr),
RECV_ATTR_INT(SESS_ATTR_DEST_FEATURES,
&dest_features),
ATTR_TYPE_END) != 4
|| vstream_fclose(mp) != 0) {
msg_warn("smtp_session_passivate: bad cached dest properties");
SMTP_SESSION_ACTIVATE_ERR_RETURN();
} }
if ((host = mystrtok(&dest_props, "\n")) == 0) { } else {
msg_warn("%s: missing cached session hostname property", myname); dest_features = 0;
return (0);
}
if ((addr = mystrtok(&dest_props, "\n")) == 0) {
msg_warn("%s: missing cached session address property", myname);
return (0);
}
/* Note: the TLS level field is always present. */
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached destination TLS level property", myname);
return (0);
} }
#ifdef USE_TLS #ifdef USE_TLS
tls->level = atoi(prop);
if (msg_verbose) if (msg_verbose)
msg_info("%s: tls_level=%d", myname, tls->level); msg_info("%s: tls_level=%d", myname, tls->level);
#endif #endif
if ((prop = mystrtok(&dest_props, "\n")) == 0 || !alldig(prop)) {
msg_warn("%s: bad cached destination features property", myname);
return (0);
}
features |= atoi(prop);
SMTP_ITER_CLOBBER(iter, dest, host, addr);
}
/* /*
* Allright, bundle up what we have sofar. * Allright, bundle up what we have sofar.
@@ -393,7 +409,9 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter, session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter,
(time_t) 0, NO_FLAGS); (time_t) 0, NO_FLAGS);
session->features = (features | SMTP_FEATURE_FROM_CACHE); session->features =
(endp_features | dest_features | SMTP_FEATURE_FROM_CACHE);
session->tls_context = tls_context;
CACHE_THIS_SESSION_UNTIL(expire_time); CACHE_THIS_SESSION_UNTIL(expire_time);
session->reuse_count = ++reuse_count; session->reuse_count = ++reuse_count;
@@ -401,20 +419,15 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, " msg_info("%s: dest=%s host=%s addr=%s port=%u features=0x%x, "
"ttl=%ld, reuse=%d", "ttl=%ld, reuse=%d",
myname, STR(iter->dest), STR(iter->host), myname, STR(iter->dest), STR(iter->host),
STR(iter->addr), ntohs(iter->port), features, STR(iter->addr), ntohs(iter->port),
endp_features | dest_features,
(long) (expire_time - time((time_t *) 0)), (long) (expire_time - time((time_t *) 0)),
reuse_count); reuse_count);
/* #if USE_TLS
* Re-activate the SASL attributes. if (tls_context)
*/ tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_USED,
#ifdef notdef session->tls_context);
if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) {
vstream_fdclose(session->stream);
session->stream = 0;
smtp_session_free(session);
return (0);
}
#endif #endif
return (session); return (session);

View File

@@ -668,7 +668,7 @@ int smtp_tls_policy_cache_query(DSN_BUF *why, SMTP_TLS_POLICY *tls,
* values that also appear in other cache and table search keys. * values that also appear in other cache and table search keys.
*/ */
key = vstring_alloc(100); key = vstring_alloc(100);
smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_NEXTHOP smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_CUR_NEXTHOP
| SMTP_KEY_FLAG_HOSTNAME | SMTP_KEY_FLAG_HOSTNAME
| SMTP_KEY_FLAG_PORT); | SMTP_KEY_FLAG_PORT);
ctable_newcontext(policy_cache, (void *) iter); ctable_newcontext(policy_cache, (void *) iter);

View File

@@ -115,12 +115,12 @@ extern const char *str_tls_level(int);
#endif #endif
/*- /*-
* Backwards compatibility with OpenSSL < 1.1.1a (or some later version). * Backwards compatibility with OpenSSL < 1.1.1a.
* *
* The client-only interface SSL_get_server_tmp_key() is slated to be made to * In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was
* work on both client and server, and renamed to SSL_get_peer_tmp_key(), with * updated to work on both the client and the server, and was renamed to
* the original name left behind as an alias. We use the new name when * SSL_get_peer_tmp_key(), with the original name left behind as an alias. We
* available. * use the new name when available.
*/ */
#if OPENSSL_VERSION_NUMBER < 0x1010101fUL #if OPENSSL_VERSION_NUMBER < 0x1010101fUL
#undef SSL_get_signature_nid #undef SSL_get_signature_nid
@@ -159,9 +159,13 @@ extern const char *str_tls_level(int);
/* /*
* TLS role, presently for logging. * TLS role, presently for logging.
*/ */
typedef enum { TLS_ROLE_CLIENT, TLS_ROLE_SERVER, } TLS_ROLE; typedef enum {
TLS_ROLE_CLIENT, TLS_ROLE_SERVER,
} TLS_ROLE;
typedef enum { TLS_USAGE_NEW, TLS_USAGE_USED, } TLS_USAGE; typedef enum {
TLS_USAGE_NEW, TLS_USAGE_USED,
} TLS_USAGE;
/* /*
* Names of valid tlsmgr(8) session caches. * Names of valid tlsmgr(8) session caches.

View File

@@ -1191,6 +1191,9 @@ 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;
/*
* With the handshake done, extract TLS 1.3 signature metadata.
*/
tls_get_signature_params(TLScontext); tls_get_signature_params(TLScontext);
if (TLScontext->log_mask & TLS_LOG_SUMMARY) if (TLScontext->log_mask & TLS_LOG_SUMMARY)

View File

@@ -14,6 +14,12 @@
/* TLS_USAGE usage; /* TLS_USAGE usage;
/* TLS_SESS_STATE *TLScontext; /* TLS_SESS_STATE *TLScontext;
/* /*
/* const char *tls_compile_version(void)
/*
/* const char *tls_run_version(void)
/*
/* const char **tls_pkey_algorithms(void)
/*
/* .SH Internal functions /* .SH Internal functions
/* .nf /* .nf
/* .na /* .na
@@ -103,12 +109,6 @@
/* /*
/* int tls_validate_digest(dgst) /* int tls_validate_digest(dgst)
/* const char *dgst; /* const char *dgst;
/*
/* const char *tls_compile_version(void)
/*
/* const char *tls_run_version(void)
/*
/* const char **tls_pkey_algorithms(void)
/* DESCRIPTION /* DESCRIPTION
/* This module implements public and internal routines that /* This module implements public and internal routines that
/* support the TLS client and server. /* support the TLS client and server.
@@ -118,6 +118,16 @@
/* connections, or TLS_ROLE_SERVER for incoming server connections, /* connections, or TLS_ROLE_SERVER for incoming server connections,
/* and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED. /* and the "usage" must be TLS_USAGE_NEW or TLS_USAGE_USED.
/* /*
/* tls_compile_version() returns a text string description of
/* the compile-time TLS library.
/*
/* tls_run_version() is just tls_compile_version() but with the runtime
/* version instead of the compile-time version.
/*
/* tls_pkey_algorithms() returns a pointer to null-terminated
/* array of string constants with the names of the supported
/* public-key algorithms.
/*
/* tls_alloc_app_context() creates an application context that /* tls_alloc_app_context() creates an application context that
/* holds the SSL context for the application and related cached state. /* holds the SSL context for the application and related cached state.
/* /*
@@ -190,16 +200,6 @@
/* /*
/* tls_validate_digest() returns non-zero if the named digest /* tls_validate_digest() returns non-zero if the named digest
/* is usable and zero otherwise. /* is usable and zero otherwise.
/*
/* tls_compile_version() returns a text string description of
/* the compile-time TLS library.
/*
/* tls_run_version() is just tls_compile_version() but with the runtime
/* version instead of the compile-time version.
/*
/* tls_pkey_algorithms() returns a pointer to null-terminated
/* array of string constants with the names of the supported
/* public-key algorithms.
/* LICENSE /* LICENSE
/* .ad /* .ad
/* .fi /* .fi

View File

@@ -1714,7 +1714,7 @@ VSTREAM *vstream_memreopen(VSTREAM *stream, VSTRING *string, int flags)
stream->write_fn = 0; stream->write_fn = 0;
stream->vstring = string; stream->vstring = string;
memcpy(&stream->buf, &stream->vstring->vbuf, sizeof(stream->buf)); memcpy(&stream->buf, &stream->vstring->vbuf, sizeof(stream->buf));
stream->buf.flags |= (flags | VSTREAM_FLAG_MEMORY); stream->buf.flags |= VSTREAM_FLAG_MEMORY;
switch (VSTREAM_ACC_MASK(flags)) { switch (VSTREAM_ACC_MASK(flags)) {
case O_RDONLY: case O_RDONLY:
stream->buf.flags |= VSTREAM_FLAG_READ; stream->buf.flags |= VSTREAM_FLAG_READ;