]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.4-20181118
authorWietse Venema <wietse@porcupine.org>
Sun, 18 Nov 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sun, 18 Nov 2018 21:30:23 +0000 (16:30 -0500)
19 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/AAAREADME
postfix/README_FILES/FORWARD_SECRECY_README
postfix/html/FORWARD_SECRECY_README.html
postfix/html/index.html
postfix/proto/FORWARD_SECRECY_README.html
postfix/src/global/mail_version.h
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_key.c
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_reuse.c
postfix/src/smtp/smtp_session.c
postfix/src/smtp/smtp_tls_policy.c
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_misc.c
postfix/src/util/vstream.c

index 8f3031c8957569e9dee80af30cfc627508bc8a05..6488e500cdef9a32b808a40f073c747cd0f3edc9 100644 (file)
 -TSTATE
 -TSTRING_LIST
 -TSTRING_TABLE
--TSUMMARY_CLASS
 -TSYS_EXITS_DETAIL
 -TTLSMGR_SCACHE
 -TTLSP_STATE
 -TTLS_SESS_STATE
 -TTLS_TICKET_KEY
 -TTLS_TLSA
+-TTLS_USAGE
 -TTLS_VINFO
 -TTLScontext_t
 -TTOK822
index 0ed7db882a1064f6a586c542e46265fbb4210ec2..ac502c1a56ff4229a16a32d98c869b6d3e2b92bc 100644 (file)
@@ -23770,9 +23770,7 @@ Apologies for any names omitted.
        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.
+       global/smtp_stream.c.
 
        Cleanup: memory leak caused by missing dbenv->close() call
        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_client.c, tls/tls_server.c, smtpd/smtpd.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.
+
index d4e10f0706824aac4dffe91bc345e67b6830c60c..7d72787cb3e7f1bffceb097539703b1091f26e0c 100644 (file)
@@ -12,7 +12,6 @@ G\bGe\ben\bne\ber\bra\bal\bl c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
   * TLS_README: TLS Encryption and authentication
   * FORWARD_SECRECY_README: TLS Forward Secrecy
   * IPV6_README: IP Version 6 Support
-  * IPV6_README: IP Version 6 Support
   * SMTPUTF8_README: SMTPUTF8 Support
   * COMPATIBILITY_README: Backwards-Compatibility Safety Net
   * INSTALL: Installation from source code
index 2b58e4828252d98c3a1c24aa021a547b0b902e60..d59b99e92e5a7861c9893472e98c6f5e6b0a3743 100644 (file)
@@ -323,7 +323,7 @@ verification status.
                 (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.
+    applicable or not available in older versions of the OpenSSL library.
 
         Received: from localhost (localhost [127.0.0.1])
                 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256
index 3fa0e78c5d8190ed4e08f29a5f93fd697d43f02a..18a83818b7845d52ed337d43b110ac3821d61c4e 100644 (file)
@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
 </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>
+applicable or not available in older versions of the OpenSSL library.  </p>
 
 <blockquote>
 <pre>
index edf9019e7f784c466e7772c9901e48079118af0c..2989177a625437eb9ecf2db2cbc0746b7a67f8c8 100644 (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="SMTPUTF8_README.html"> SMTPUTF8 Support </a>
 
 <li> <a href="COMPATIBILITY_README.html"> Backwards-Compatibility Safety Net</a>
index abeb31e0a7a5980ade16f09d5a7ca00c9f7f91f3..f549e4a1c89174c962ed7d727f05365b665c2fc7 100644 (file)
@@ -434,7 +434,7 @@ Received: from host.example.com (host.example.com [192.168.0.2])
 </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>
+applicable or not available in older versions of the OpenSSL library.  </p>
 
 <blockquote>
 <pre>
index cbb12745901ab9f275ecf8e3d4ae325e3b27f24d..ba90a1ddf2a04304d678aee95372decd1a39d6af 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20181117"
+#define MAIL_RELEASE_DATE      "20181118"
 #define MAIL_VERSION_NUMBER    "3.4"
 
 #ifdef SNAPSHOT
index 778a3d5245b69c6f1c054978ae267278a2d1b8d7..effc658a1327d1d94fffda3c99215d9f461f3a79 100644 (file)
@@ -192,17 +192,25 @@ typedef struct 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); \
-    }
+    } while (0)
 
-#define FREE_NEXTHOP_STATE(state) { \
+#define CLEAR_SCACHE_REQUEST_NEXTHOP(state) do { \
        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_XFORWARD_IDENT    (1<<20)
 #define SMTP_FEATURE_SMTPUTF8          (1<<21) /* RFC 6531 */
+#define SMTP_FEATURE_FROM_PROXY                (1<<22) /* proxied connection */
 
  /*
   * 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_SENDER           (1<<1)  /* sender address */
 #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_ADDR             (1<<5)  /* remote address */
 #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 \
        (SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \
        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)
 
  /*
@@ -640,14 +649,14 @@ char   *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
        ((var_smtp_sender_auth && *var_smtp_sasl_passwd) ? \
            SMTP_KEY_FLAG_SENDER : 0)
 
-#define COND_SASL_SMTP_KEY_FLAG_NEXTHOP \
-       (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_NEXTHOP : 0)
+#define COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
+       (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
 
 #ifdef USE_TLS
-#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
-       (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_NEXTHOP : 0)
+#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
+       (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_CUR_NEXTHOP : 0)
 #else
-#define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
+#define COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP \
        (0)
 #endif
 
@@ -655,10 +664,13 @@ char   *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
        (*var_smtp_sasl_passwd ? SMTP_KEY_FLAG_HOSTNAME : 0)
 
  /*
-  * Connection-cache destination lookup key. The SENDER attribute is a proxy
-  * for sender-dependent SASL credentials (or absence thereof), and prevents
-  * false connection sharing when different SASL credentials may be required
-  * for different deliveries to the same domain and port. The SERVICE
+  * Connection-cache destination lookup key, based on the delivery request
+  * nexthop. The SENDER attribute is a proxy for sender-dependent SASL
+  * credentials (or absence thereof), and prevents false connection sharing
+  * 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.
   */
 #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)
 
  /*
-  * Connection-cache endpoint lookup key. The SENDER, NEXTHOP, and HOSTNAME
-  * attributes are proxies for SASL credentials (or absence thereof), and
-  * prevent false connection sharing when different SASL credentials may be
-  * required for different deliveries to the same IP address and port.
+  * Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME,
+  * PORT and TLS_LEVEL attributes are proxies for SASL credentials and TLS
+  * authentication (or absence thereof), and prevent false connection sharing
+  * 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 \
        (SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
-       | COND_SASL_SMTP_KEY_FLAG_NEXTHOP | COND_SASL_SMTP_KEY_FLAG_HOSTNAME \
-       | COND_TLS_SMTP_KEY_FLAG_NEXTHOP | SMTP_KEY_FLAG_ADDR | \
+       | COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
+       | 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)
 
  /*
@@ -703,11 +718,6 @@ extern int smtp_mode;
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
 /*
-/*     Wietse Venema
-/*     Google, Inc.
-/*     111 8th Avenue
-/*     New York, NY 10011, USA
-/*
 /*     TLS support originally by:
 /*     Lutz Jaenicke
 /*     BTU Cottbus
index b218b2a01829d0c8a91b2175b300574d6b19da95..d5693c7c896a05fe7fb3e53b5d450afdf0603ba2 100644 (file)
@@ -417,13 +417,13 @@ static void smtp_cleanup_session(SMTP_STATE *state)
     state->session = 0;
 
     /*
-     * If this session was good, reset the logical next-hop state, so that we
-     * won't cache connections to alternate servers under the logical
-     * next-hop destination. Otherwise we could end up skipping over the
-     * available and more preferred servers.
+     * If this session was good, reset the logical next-hop destination, so
+     * that we won't cache connections to less-preferred servers under the
+     * logical next-hop destination. Otherwise we could end up skipping over
+     * the available and more-preferred servers.
      */
-    if (HAVE_NEXTHOP_STATE(state) && !throttled)
-       FREE_NEXTHOP_STATE(state);
+    if (HAVE_SCACHE_REQUEST_NEXTHOP(state) && !throttled)
+       CLEAR_SCACHE_REQUEST_NEXTHOP(state);
 
     /*
      * 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
     SMTP_ITER_SAVE_DEST(state->iterator);
     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_count = 1;
        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)) {
            smtp_cache_policy(state, domain);
            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.
      */
-    if (HAVE_NEXTHOP_STATE(state))
-       FREE_NEXTHOP_STATE(state);
+    if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
+       CLEAR_SCACHE_REQUEST_NEXTHOP(state);
     argv_free(sites);
 }
 
index 6f72b803e65dc3bc41543cee8f7a70c50bd33588..8b5db76a21872b3c4c62c603fe11552e9b2b029d 100644 (file)
@@ -53,7 +53,7 @@
 /* .IP SMTP_KEY_FLAG_REQ_NEXTHOP
 /*     The request nexthop destination. This is a proxy for
 /*     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
 /*     or fallback nexthop, including optional [] and :port). This
 /*     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)
        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);
 
     /*
index 0169f1716a4a3a4c783ded63471dd52b7c113c74..0bac85aba6c48255947ec3fd74e69bec7b84a6a0 100644 (file)
@@ -899,7 +899,7 @@ static int smtp_start_tls(SMTP_STATE *state)
      */
     serverid = vstring_alloc(10);
     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_ADDR);
 
@@ -1018,6 +1018,11 @@ static int smtp_start_tls(SMTP_STATE *state)
             * context attributes.
             */
            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 */
 
index f4b4996c50b715c11af918594a642c9b55bb39da..f93ba296a0fe5b43170d2c33234b466cd5706539 100644 (file)
 /*     This module implements the SMTP client specific interface to
 /*     the generic session cache infrastructure.
 /*
-/*     A cached connection is closed when the TLS policy requires
-/*     that TLS is enabled.
+/*     The caller needs to include additional state in _key_flags
+/*     to avoid false sharing of SASL-authenticated or TLS-authenticated
+/*     sessions.
 /*
 /*     smtp_save_session() stores the current session under the
-/*     next-hop logical destination (if available) and under the
-/*     remote server address.  The SMTP_SESSION object is destroyed.
+/*     delivery request next-hop logical destination (if applicable)
+/*     and under the remote server address. The SMTP_SESSION object
+/*     is destroyed.
 /*
-/*     smtp_reuse_nexthop() looks up a cached session by its logical
-/*     destination, and verifies that the session is still alive.
-/*     The restored session information includes the "best MX" bit
-/*     and overrides the iterator dest, host and addr fields.
-/*     The result is null in case of failure.
+/*     smtp_reuse_nexthop() looks up a cached session by its
+/*     delivery request next-hop destination, and verifies that
+/*     the session is still alive. The restored session information
+/*     includes the "best MX" bit and overrides the iterator dest,
+/*     host and addr fields. The result is null in case of failure.
 /*
 /*     smtp_reuse_addr() looks up a cached session by its server
 /*     address, and verifies that the session is still alive.
 /*     The restored session information does not include the "best
 /*     MX" bit, and does not override the iterator dest, host and
-/*     addr fields.
-/*     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.
+/*     addr fields. The result is null in case of failure.
 /*
 /*     Arguments:
 /* .IP state
@@ -116,10 +115,16 @@ void    smtp_save_session(SMTP_STATE *state, int name_key_flags,
     int     fd;
 
     /*
-     * Encode the next-hop logical destination, if available. Reuse storage
-     * that is also used for cache lookup queries.
+     * Encode the delivery request next-hop destination, if applicable. Reuse
+     * 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,
                        state->iterator, name_key_flags);
 
@@ -138,16 +143,18 @@ void    smtp_save_session(SMTP_STATE *state, int name_key_flags,
     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
      * 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
      * so.
      */
-    if (HAVE_NEXTHOP_STATE(state))
-       scache_save_dest(smtp_scache, var_smtp_cache_conn, STR(state->dest_label),
-                        STR(state->dest_prop), STR(state->endp_label));
+    if (HAVE_SCACHE_REQUEST_NEXTHOP(state))
+       scache_save_dest(smtp_scache, var_smtp_cache_conn,
+                        STR(state->dest_label), STR(state->dest_prop),
+                        STR(state->endp_label));
 
     /*
      * 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_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.
      */
@@ -216,15 +214,6 @@ SMTP_SESSION *smtp_reuse_nexthop(SMTP_STATE *state, int name_key_flags)
     SMTP_SESSION *session;
     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.
      */
@@ -250,18 +239,13 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
     int     fd;
 
     /*
-     * Allow address-based reuse only for security levels that don't require
-     * certificate checks. Not to be confused with a similar constraint in
-     * the destination label smtp_key pattern, which conditionally includes
-     * the nexthop to prevent the reuse of an authenticated connection to the
-     * same MX hostname and the same IP address, but for a different nexthop
-     * destination (just in case we start to send SNI with the nexthop, and
-     * forget to update connection cache lookup key patterns).
+     * Address-based reuse is safe for security levels that require TLS
+     * certificate checks, as long as the current nexhop is included in the
+     * cache lookup key (COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP). This is
+     * sufficient to prevent the reuse of a TLS-authenticated connection to
+     * the same MX hostname, IP address, and port, but for a different
+     * current nexthop destination with a different TLS policy.
      */
-#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
index 2b4ce8675ca638e34893334af8aa895a38916c49..7ae9afd0c2474d6ce4cb135efe0024d3195e5584 100644 (file)
 #include <debug_peer.h>
 #include <mail_params.h>
 
+/* TLS Library. */
+
+#include <tls_proxy.h>
+
 /* Application-specific. */
 
 #include "smtp.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 *smtp_session_alloc(VSTREAM *stream, SMTP_ITERATOR *iter,
@@ -183,7 +200,8 @@ void    smtp_session_free(SMTP_SESSION *session)
        vstream_fflush(session->stream);
     }
     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);
        else
            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)
 {
     SMTP_ITERATOR *iter = session->iterator;
+    VSTREAM *mp;
     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
      * 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
      * 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",
-                   STR(iter->dest), STR(iter->host), STR(iter->addr),
-#ifdef USE_TLS
-                   iter->parent->tls->level,
-#else
-                   0,
-#endif
-                   session->features & SMTP_FEATURE_DESTINATION_MASK);
+    if ((mp = vstream_memopen(dest_prop, O_WRONLY)) == 0
+       || attr_print_plain(mp, ATTR_FLAG_NONE,
+                           SEND_ATTR_STR(SESS_ATTR_DEST, STR(iter->dest)),
+                           SEND_ATTR_STR(SESS_ATTR_HOST, STR(iter->host)),
+                           SEND_ATTR_STR(SESS_ATTR_ADDR, STR(iter->addr)),
+                           SEND_ATTR_INT(SESS_ATTR_DEST_FEATURES,
+                        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
      * 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
-     * serialize the properties with attr_print() instead of using obscure
-     * hard-coded format strings.
+     * XXX Should also record how many non-delivering mail transactions there
+     * were during this session, and perhaps other statistics, so that we
+     * don't reuse a session too much.
      * 
-     * XXX Should also record an absolute time when a session must be closed,
-     * how many non-delivering mail transactions there were during this
-     * session, and perhaps other statistics, so that we don't reuse a
-     * session too much.
+     * TODO: passivate SASL username and password information so that we can
+     * correctly save a reused authenticated connection.
      * 
-     * XXX Be sure to use unsigned types in the format string. Sign characters
-     * would be rejected by the alldig() test on the reading end.
+     * These memory writes should never fail.
      */
-    vstring_sprintf(endp_prop, "%u\n%u\n%lu",
-                   session->reuse_count,
-                   session->features & SMTP_FEATURE_ENDPOINT_MASK,
-                   (long) session->expire_time);
+    if ((mp = vstream_memopen(endp_prop, O_WRONLY)) == 0
+       || attr_print_plain(mp, ATTR_FLAG_NONE,
+                           SEND_ATTR_INT(SESS_ATTR_TLS_LEVEL,
+                                         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
-    if (smtp_sasl_enable)
-       smtp_sasl_passivate(endp_prop, session);
+#ifdef USE_TLS
+       || (session->tls_context
+           && attr_print_plain(mp, ATTR_FLAG_NONE,
+                               SEND_ATTR_FUNC(tls_proxy_context_print,
+                                            (void *) session->tls_context),
+                               ATTR_TYPE_END) != 0)
 #endif
+       || vstream_fclose(mp) != 0)
+       msg_fatal("smtp_session_passivate: cannot save TLS context: %m");
 
     /*
      * 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)
 {
     const char *myname = "smtp_session_activate";
+    VSTREAM *mp;
     SMTP_SESSION *session;
-    char   *dest_props;
-    char   *endp_props;
-    const char *prop;
-    const char *dest;
-    const char *host;
-    const char *addr;
-    unsigned features;                 /* server features */
-    time_t  expire_time;               /* session re-use expiration time */
-    unsigned reuse_count;              /* # times reused */
+    int     endp_features;             /* server features */
+    int     dest_features;             /* server features */
+    long    expire_time;               /* session re-use expiration time */
+    int     reuse_count;               /* # times reused */
+    TLS_SESS_STATE *tls_context = 0;
 
 #ifdef USE_TLS
     SMTP_TLS_POLICY *tls = iter->parent->tls;
 
 #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
-     * can de-serialize the properties with attr_scan(), instead of using
-     * ad-hoc, non-reusable code.
-     * 
-     * XXX As a preliminary solution we use mystrtok(), but that function is not
-     * suitable for zero-length fields.
+     * Sanity check: if TLS is required, the cached properties must contain a
+     * TLS context.
      */
-    endp_props = STR(endp_prop);
-    if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
-       msg_warn("%s: bad cached session reuse count property", myname);
-       return (0);
-    }
-    reuse_count = atoi(prop);
-    if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
-       msg_warn("%s: bad cached session features property", myname);
-       return (0);
-    }
-    features = atoi(prop);
-    if ((prop = mystrtok(&endp_props, "\n")) == 0 || !alldig(prop)) {
-       msg_warn("%s: bad cached session expiration time property", myname);
-       return (0);
-    }
-#ifdef MISSING_STRTOUL
-    expire_time = strtol(prop, 0, 10);
-#else
-    expire_time = strtoul(prop, 0, 10);
+    if ((mp = vstream_memopen(endp_prop, O_RDONLY)) == 0
+       || attr_scan_plain(mp, ATTR_FLAG_NONE,
+                          RECV_ATTR_INT(SESS_ATTR_TLS_LEVEL,
+                                        &tls->level),
+                          RECV_ATTR_INT(SESS_ATTR_REUSE_COUNT,
+                                        &reuse_count),
+                          RECV_ATTR_INT(SESS_ATTR_ENDP_FEATURES,
+                                        &endp_features),
+                          RECV_ATTR_LONG(SESS_ATTR_EXPIRE_TIME,
+                                         &expire_time),
+                          ATTR_TYPE_END) != 4
+#ifdef USE_TLS
+       || ((tls->level > TLS_LEV_MAY
+            || (tls->level == TLS_LEV_MAY && vstream_peek(mp) > 0))
+           && attr_scan_plain(mp, ATTR_FLAG_NONE,
+                              RECV_ATTR_FUNC(tls_proxy_context_scan,
+                                             (void *) &tls_context),
+                              ATTR_TYPE_END) != 1)
 #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
@@ -355,36 +382,25 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
      * correctly save a reused authenticated connection.
      */
     if (dest_prop && VSTRING_LEN(dest_prop)) {
-       dest_props = STR(dest_prop);
-       if ((dest = mystrtok(&dest_props, "\n")) == 0) {
-           msg_warn("%s: missing cached session destination property", myname);
-           return (0);
-       }
-       if ((host = mystrtok(&dest_props, "\n")) == 0) {
-           msg_warn("%s: missing cached session hostname property", myname);
-           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);
+       if ((mp = vstream_memopen(dest_prop, O_RDONLY)) == 0
+           || attr_scan_plain(mp, ATTR_FLAG_NONE,
+                              RECV_ATTR_STR(SESS_ATTR_DEST, iter->dest),
+                              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();
        }
+    } else {
+       dest_features = 0;
+    }
 #ifdef USE_TLS
-       tls->level = atoi(prop);
-       if (msg_verbose)
-           msg_info("%s: tls_level=%d", myname, tls->level);
+    if (msg_verbose)
+       msg_info("%s: tls_level=%d", myname, tls->level);
 #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.
@@ -393,7 +409,9 @@ SMTP_SESSION *smtp_session_activate(int fd, SMTP_ITERATOR *iter,
 
     session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR), iter,
                                 (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);
     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, "
                 "ttl=%ld, reuse=%d",
                 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)),
                 reuse_count);
 
-    /*
-     * Re-activate the SASL attributes.
-     */
-#ifdef notdef
-    if (smtp_sasl_enable && smtp_sasl_activate(session, endp_props) < 0) {
-       vstream_fdclose(session->stream);
-       session->stream = 0;
-       smtp_session_free(session);
-       return (0);
-    }
+#if USE_TLS
+    if (tls_context)
+       tls_log_summary(TLS_ROLE_CLIENT, TLS_USAGE_USED,
+                       session->tls_context);
 #endif
 
     return (session);
index 13735b21056922be82f0c88254df573a86c47ea1..6415e032e4b9132d32700060bcd53d190292636b 100644 (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.
      */
     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_PORT);
     ctable_newcontext(policy_cache, (void *) iter);
index e49567562716849909f9a1dda1ef72297973a3fc..0f3c5be12f33d9102710810ad8286a89d7c5cebb 100644 (file)
@@ -115,12 +115,12 @@ extern const char *str_tls_level(int);
 #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
-  * work on both client and server, and renamed to SSL_get_peer_tmp_key(), with
-  * the original name left behind as an alias.  We use the new name when
-  * available.
+  * In OpenSSL 1.1.1a the client-only interface SSL_get_server_tmp_key() was
+  * updated to work on both the client and the server, and was renamed to
+  * SSL_get_peer_tmp_key(), with the original name left behind as an alias.  We
+  * use the new name when available.
   */
 #if OPENSSL_VERSION_NUMBER < 0x1010101fUL
 #undef SSL_get_signature_nid
@@ -159,9 +159,13 @@ extern const char *str_tls_level(int);
  /*
   * 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.
index f485389737096f41b21858b6b459b3ee26685a94..3d771a494caf448e160bd99657f987446206806f 100644 (file)
@@ -1191,6 +1191,9 @@ TLS_SESS_STATE *tls_client_post_connect(TLS_SESS_STATE *TLScontext,
        && !TLS_NEVER_SECURED(props->tls_level))
        TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
 
+    /*
+     * With the handshake done, extract TLS 1.3 signature metadata.
+     */
     tls_get_signature_params(TLScontext);
 
     if (TLScontext->log_mask & TLS_LOG_SUMMARY)
index 0ca919f52f1e695221bf7aeb4329062a4a7c3e54..9460d9fd605f1f8876977c39d4141434be25a3a5 100644 (file)
 /*     TLS_USAGE usage;
 /*     TLS_SESS_STATE *TLScontext;
 /*
+/*     const char *tls_compile_version(void)
+/*
+/*     const char *tls_run_version(void)
+/*
+/*     const char **tls_pkey_algorithms(void)
+/*
 /* .SH Internal functions
 /* .nf
 /* .na
 /*
 /*     int     tls_validate_digest(dgst)
 /*     const char *dgst;
-/*
-/*     const char *tls_compile_version(void)
-/*
-/*     const char *tls_run_version(void)
-/*
-/*     const char **tls_pkey_algorithms(void)
 /* DESCRIPTION
 /*     This module implements public and internal routines that
 /*     support the TLS client and server.
 /*     connections, or TLS_ROLE_SERVER for incoming server connections,
 /*     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
 /*     holds the SSL context for the application and related cached state.
 /*
 /*
 /*     tls_validate_digest() returns non-zero if the named digest
 /*     is usable and zero otherwise.
-/*
-/*     tls_compile_version() returns a text string description of
-/*     the compile-time TLS library.
-/*
-/*     tls_run_version() is just tls_compile_version() but with the runtime
-/*     version instead of the compile-time version.
-/*
-/*     tls_pkey_algorithms() returns a pointer to null-terminated
-/*     array of string constants with the names of the supported
-/*     public-key algorithms.
 /* LICENSE
 /* .ad
 /* .fi
index 674e79604ff574b836400df3bef77b42d4d8f234..7af288271cd78f08bf99a6676f73c1b34d2c6757 100644 (file)
@@ -1714,7 +1714,7 @@ VSTREAM *vstream_memreopen(VSTREAM *stream, VSTRING *string, int flags)
     stream->write_fn = 0;
     stream->vstring = string;
     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)) {
     case O_RDONLY:
        stream->buf.flags |= VSTREAM_FLAG_READ;