]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.4-20181117-nonprod 20181117-nonprod
authorWietse Venema <wietse@porcupine.org>
Sat, 17 Nov 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 17 Nov 2018 22:35:56 +0000 (17:35 -0500)
postfix/.indent.pro
postfix/HISTORY
postfix/makedefs
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_session.c
postfix/src/util/vstream.c

index 8f3031c8957569e9dee80af30cfc627508bc8a05..b57603810b79c21f1c590f119e2014c47364b6e8 100644 (file)
 -TSTATE
 -TSTRING_LIST
 -TSTRING_TABLE
--TSUMMARY_CLASS
 -TSYS_EXITS_DETAIL
 -TTLSMGR_SCACHE
 -TTLSP_STATE
 -TTLS_PKEYS
 -TTLS_PRNG_SEED_INFO
 -TTLS_PRNG_SRC
--TTLS_ROLE
 -TTLS_SCACHE
 -TTLS_SCACHE_ENTRY
 -TTLS_SERVER_INIT_PROPS
index 0ed7db882a1064f6a586c542e46265fbb4210ec2..feb8ea0d6f7fdae219efc34fec44fc63fd364efe 100644 (file)
@@ -23794,3 +23794,13 @@ 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.
+
+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.
index c3efa42c6f28af47bf943401ed9d09904dd6b38e..049848e8bac830c2ebcd779ddb04d35a7d70c346 100644 (file)
@@ -880,7 +880,7 @@ CCARGS="$CCARGS -DSNAPSHOT"
 
 # Non-production: needs thorough testing, or major changes are still
 # needed before the code stabilizes.
-#CCARGS="$CCARGS -DNONPROD"
+CCARGS="$CCARGS -DNONPROD"
 
 # Workaround: prepend Postfix include files before other include files.
 CCARGS="-I. -I../../include $CCARGS"
index 778a3d5245b69c6f1c054978ae267278a2d1b8d7..623633e14dd4cea16adbd282a32a58e4948102f2 100644 (file)
@@ -229,6 +229,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.
index 0169f1716a4a3a4c783ded63471dd52b7c113c74..7f9a3a8cf8e715550f0bb4b7bb345757b1bb3148 100644 (file)
@@ -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 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 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;