]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.4-20180624
authorWietse Venema <wietse@porcupine.org>
Sun, 24 Jun 2018 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Mon, 16 Jul 2018 14:27:32 +0000 (10:27 -0400)
14 files changed:
postfix/HISTORY
postfix/README_FILES/CONNECTION_CACHE_README
postfix/README_FILES/TLS_README
postfix/RELEASE_NOTES
postfix/html/CONNECTION_CACHE_README.html
postfix/html/TLS_README.html
postfix/proto/CONNECTION_CACHE_README.html
postfix/proto/TLS_README.html
postfix/src/global/mail_version.h
postfix/src/master/event_server.c
postfix/src/master/single_server.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_reuse.c
postfix/src/tlsproxy/tlsproxy.c

index ff2cd9c4e7ff8296c31fd5c315dcdec703ef4510..8a85899c0f680783668ff396d54a6f5f9e5ab046 100644 (file)
@@ -23572,3 +23572,18 @@ Apologies for any names omitted.
        nexthops, by making the nexthop part of the endpoint-based
        connection cache lookup key. File: smtp/smtp.h.
 
+20180623
+
+       TLS connection reuse: replaced random logic with TLS_MUST_MATCH()
+       when deciding under what conditions an authenticated
+       connection may be reused.  Files: smtp/smtp_proto.c,
+       smtp/smtp.h.
+
+       TLS connection reuse: a tlsproxy(8) process will retire
+       after max_idle*max_use, or some sane constant if either is
+       set to zero.  Files: master/event_server.c, tlsproxy/tlsproxy.c.
+
+       Documentation: automatic retirement. File: master/single_server.c.
+
+       Documentation: the connection caching limitation for SMTP
+       over TLS is now obsolete. File: proto/CONNECTION_CACHE_README.html.
index 408d3b54d15e4865c16d21efe228277660d615e6..bd2fd03084e0a2b65f7db2a1a4f1a9a6719aaa49 100644 (file)
@@ -159,7 +159,6 @@ mechanisms:
     MTAs, the slowest inbound MTA will attract most connections from Postfix to
     that destination).
 
-    .
     Postfix 2.3 logs the use count of multiply-used connections, as shown in
     the following example:
 
@@ -177,12 +176,11 @@ C\bCo\bon\bnn\bne\bec\bct\bti\bio\bon\bn c\bca\bac\bch\bhe\be l\bli\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
 
 Postfix SMTP connection caching conflicts with certain applications:
 
-  * The Postfix shared connection cache cannot be used with TLS, because saved
-    TLS session information can be used only when a new connection is created
-    (this limitation does not exist in connection caching implementations that
-    reuse a connection only in the process that creates it). For this reason,
-    the Postfix smtp(8) client always closes the connection after completing an
-    attempt to deliver mail over TLS.
+  * With Postfix versions < 3.4, the Postfix shared connection cache cannot be
+    used with TLS, because an open TLS connection can be reused only in the
+    process that creates it. For this reason, the Postfix smtp(8) client
+    historically always closed the connection after completing an attempt to
+    deliver mail over TLS.
 
   * Postfix connection caching currently does not support multiple SASL
     accounts per mail server. Specifically, Postfix connection caching assumes
index 37622d38371088bb5804f1699cdbe0f8f70552af..68e0157d1320dcc4f916961f035ce539562fdc6b 100644 (file)
@@ -1468,7 +1468,7 @@ Cached SMTP/TLS connection:
     scache(8) -> tlsproxy(8) -> remote SMTP server
 
 As of Postfix 3.4, TLS connection reuse is disabled by default. This may change
-once the impact on over-all performance is undestood.
+once the impact on over-all performance is understood.
 
 C\bCl\bli\bie\ben\bnt\bt-\b-s\bsi\bid\bde\be T\bTL\bLS\bS s\bse\bes\bss\bsi\bio\bon\bn c\bca\bac\bch\bhe\be
 
index daf6a00f76a9331327a44b20a3869de5df016c22..1020af982c42e32f9043cc8cc38a7075396218ba 100644 (file)
@@ -63,7 +63,3 @@ There are a few refinements planned:
 
 - Log the TLS properties every time a connection is reused.
   Currently, the properties are logged when a TLS session is created.
-
-- Retire a tlsproxy(8) process after max_idle*max_use seconds, even
-  if it is not idle. This limits the impact of memory leaks in
-  libraries or in Postfix itself.
index e808180a76a33dcd0c08c130b4b41968c8a5d629..c2bf8b6faad69c0872fa0b9d76d2c56bf3857dee 100644 (file)
@@ -236,7 +236,7 @@ the <a href="postconf.5.html#smtp_connection_reuse_time_limit">smtp_connection_r
 times a connection may be reused, but this feature is unsafe as it
 introduces a "fatal attractor" failure mode (when a destination has
 multiple inbound MTAs, the slowest inbound MTA will attract most
-connections from Postfix to that destination).  </p>.
+connections from Postfix to that destination). </p>
 
 <p> Postfix 2.3 logs the use count of multiply-used connections,
 as shown in the following example: </p>
@@ -264,13 +264,11 @@ This prevents mis-delivery of mail. </p>
 
 <ul>
 
-<li> <p> The Postfix shared connection cache cannot be used with
-TLS, because saved TLS session information can be used only when a
-new connection is created (this limitation does not exist in
-connection caching implementations that reuse a connection only in
-the process that creates it).  For this reason, the Postfix <a href="smtp.8.html">smtp(8)</a>
-client always closes the connection after completing an attempt to
-deliver mail over TLS.  </p>
+<li> <p> With Postfix versions &lt; 3.4, the Postfix shared connection
+cache cannot be used with TLS, because an open TLS connection can
+be reused only in the process that creates it.  For this reason,
+the Postfix <a href="smtp.8.html">smtp(8)</a> client historically always closed the connection
+after completing an attempt to deliver mail over TLS.</p>
 
 <li> <p> Postfix connection caching currently does not support
 multiple SASL accounts per mail server.  Specifically, Postfix
index fecd87884549d79565301bd8a8857c1b71dd7fc7..e51923961915b6b836bd70545caeab6a42560701 100644 (file)
@@ -1950,7 +1950,7 @@ infrastructure.  </p>
 <pre>    <a href="scache.8.html">scache(8)</a> -&gt; <a href="tlsproxy.8.html">tlsproxy(8)</a> -&gt; remote SMTP server</pre>
 
 <p> As of Postfix 3.4, TLS connection reuse is disabled by default.
-This may change once the impact on over-all performance is undestood.
+This may change once the impact on over-all performance is understood.
 </p>
 
 <h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3>
index 7dd80c7137f95eb954176ea9bcc6c63026e9ae94..7ffd7bb04db03108732165f1388e060eb294ac58 100644 (file)
@@ -236,7 +236,7 @@ the smtp_connection_reuse_time_limit parameter. In addition, Postfix
 times a connection may be reused, but this feature is unsafe as it
 introduces a "fatal attractor" failure mode (when a destination has
 multiple inbound MTAs, the slowest inbound MTA will attract most
-connections from Postfix to that destination).  </p>.
+connections from Postfix to that destination). </p>
 
 <p> Postfix 2.3 logs the use count of multiply-used connections,
 as shown in the following example: </p>
@@ -264,13 +264,11 @@ This prevents mis-delivery of mail. </p>
 
 <ul>
 
-<li> <p> The Postfix shared connection cache cannot be used with
-TLS, because saved TLS session information can be used only when a
-new connection is created (this limitation does not exist in
-connection caching implementations that reuse a connection only in
-the process that creates it).  For this reason, the Postfix smtp(8)
-client always closes the connection after completing an attempt to
-deliver mail over TLS.  </p>
+<li> <p> With Postfix versions &lt; 3.4, the Postfix shared connection
+cache cannot be used with TLS, because an open TLS connection can
+be reused only in the process that creates it.  For this reason,
+the Postfix smtp(8) client historically always closed the connection
+after completing an attempt to deliver mail over TLS.</p>
 
 <li> <p> Postfix connection caching currently does not support
 multiple SASL accounts per mail server.  Specifically, Postfix
index 4a1c6b8b111f7d3cdd32b941ba4c712a3ca85a98..0aa8fbe834181824f38a6a5f61e4615f30f54321 100644 (file)
@@ -1950,7 +1950,7 @@ infrastructure.  </p>
 <pre>    scache(8) -&gt; tlsproxy(8) -&gt; remote SMTP server</pre>
 
 <p> As of Postfix 3.4, TLS connection reuse is disabled by default.
-This may change once the impact on over-all performance is undestood.
+This may change once the impact on over-all performance is understood.
 </p>
 
 <h3><a name="client_tls_cache">Client-side TLS session cache</a> </h3>
index ae5a7366d7f9e9171ff9e64a95a79387eddb6ac0..0fff4fc05593f20e5d3abee2c553a7e554eb735b 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      "20180620"
+#define MAIL_RELEASE_DATE      "20180624"
 #define MAIL_VERSION_NUMBER    "3.4"
 
 #ifdef SNAPSHOT
index 184ff65e57b498eb9f309d93921ba31ff2e0726d..a1c0d246a5b21f2b9b6e857d318abc0b979d6d82 100644 (file)
@@ -17,7 +17,7 @@
 /*
 /*     void    event_server_drain()
 /* DESCRIPTION
-/*     This module implements a skeleton for multi-threaded
+/*     This module implements a skeleton for event-driven
 /*     mail subsystems: mail subsystem programs that service multiple
 /*     clients at the same time. The resulting program expects to be run
 /*     from the \fBmaster\fR process.
 /* .IP "CA_MAIL_SERVER_BOUNCE_INIT(const char *, const char **)"
 /*     Initialize the DSN filter for the bounce/defer service
 /*     clients with the specified map source and map names.
+/* .IP "CA_MAIL_SERVER_RETIRE_ME"
+/*     Prevent a process from being reused indefinitely. After
+/*     (var_max_use * var_max_idle) seconds or some sane constant,
+/*     stop accepting new connections and terminate voluntarily
+/*     when the process becomes idle.
 /* .PP
 /*     event_server_disconnect() should be called by the application
 /*     to close a client connection.
 /*     result means this call should be tried again later.
 /*
 /*     The var_use_limit variable limits the number of clients
-/*     that a server can service before it commits suicide.  This
+/*     that a server can service before it commits suicide. This
 /*     value is taken from the global \fBmain.cf\fR configuration
 /*     file. Setting \fBvar_use_limit\fR to zero disables the
 /*     client limit.
@@ -278,12 +283,27 @@ static NORETURN event_server_exit(void)
     exit(0);
 }
 
+/* event_server_retire - retire when idle */
+
+static void event_server_retire(int unused_event, void *unused_context)
+{
+    if (msg_verbose)
+       msg_info("time to retire -- %s", event_server_slow_exit ?
+                "draining" : "exiting");
+    event_disable_readwrite(MASTER_STATUS_FD);
+    if (event_server_slow_exit)
+       event_server_slow_exit(event_server_name, event_server_argv);
+    else
+       event_server_exit();
+}
+
 /* event_server_abort - terminate after abnormal master exit */
 
 static void event_server_abort(int unused_event, void *unused_context)
 {
     if (msg_verbose)
-       msg_info("master disconnect -- exiting");
+       msg_info("master disconnect -- %s", event_server_slow_exit ?
+                "draining" : "exiting");
     event_disable_readwrite(MASTER_STATUS_FD);
     if (event_server_slow_exit)
        event_server_slow_exit(event_server_name, event_server_argv);
@@ -567,6 +587,8 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
     int     redo_syslog_init = 0;
     const char *dsn_filter_title;
     const char **dsn_filter_maps;
+    int     retire_me_from_flags = 0;
+    int     retire_me = 0;
 
     /*
      * Process environment options as early as we can.
@@ -624,7 +646,7 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
      * stderr, because no-one is going to see them.
      */
     opterr = 0;
-    while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:St:uvVz")) > 0) {
+    while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:r:s:St:uvVz")) > 0) {
        switch (c) {
        case 'c':
            root_dir = "setme";
@@ -656,6 +678,10 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
                redo_syslog_init = 1;
            myfree(oname_val);
            break;
+       case 'r':
+           if ((retire_me_from_flags = atoi(optarg)) <= 0)
+               msg_fatal("invalid retirement time: %s", optarg);
+           break;
        case 's':
            if ((socket_count = atoi(optarg)) <= 0)
                msg_fatal("invalid socket_count: %s", optarg);
@@ -784,6 +810,15 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
            dsn_filter_maps = va_arg(ap, const char **);
            bounce_client_init(dsn_filter_title, *dsn_filter_maps);
            break;
+       case MAIL_SERVER_RETIRE_ME:
+           if (retire_me_from_flags > 0)
+               retire_me = retire_me_from_flags;
+           else if (var_idle_limit == 0 || var_use_limit == 0
+                    || var_idle_limit > 18000 / var_use_limit)
+               retire_me = 18000;
+           else
+               retire_me = var_idle_limit * var_use_limit;
+           break;
        default:
            msg_panic("%s: unknown argument type: %d", myname, key);
        }
@@ -907,6 +942,8 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
      */
     if (var_idle_limit > 0)
        event_request_timer(event_server_timeout, (void *) 0, var_idle_limit);
+    if (retire_me)
+       event_request_timer(event_server_retire, (void *) 0, retire_me);
     for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) {
        event_enable_read(fd, event_server_accept, CAST_INT_TO_VOID_PTR(fd));
        close_on_exec(fd, CLOSE_ON_EXEC);
index 3562e7b14c9ac54bd67711e6c0e78a711381a858..7ef4ca0cc3bef1e8cb69fa90de2f2d7cac574989 100644 (file)
 /*     Initialize the DSN filter for the bounce/defer service
 /*     clients with the specified map source and map names.
 /* .IP "CA_MAIL_SERVER_RETIRE_ME"
-/*     Terminate voluntarily when idle after (max_use * max_idle)
-/*     seconds. This setting prevents a process from being reused
-/*     indefinitely when var_use_limit is set to zero.
+/*     Prevent a process from being reused indefinitely. After
+/*     (var_max_use * var_max_idle) seconds or some sane constant,
+/*     terminate voluntarily when the process becomes idle.
 /* .PP
-/*     The var_use_limit variable limits the number of clients that
-/*     a server can service before it commits suicide.
-/*     Do not change this setting before calling single_server_main().
-/*     This value is taken from the global \fBmain.cf\fR configuration
-/*     file. Setting \fBvar_use_limit\fR to zero disables the client limit.
-/*     Specify CA_MAIL_SERVER_RETIRE_ME (see above) to limit the total
-/*     process lifetime.
+/*     The var_use_limit variable limits the number of clients
+/*     that a server can service before it commits suicide. This
+/*     value is taken from the global \fBmain.cf\fR configuration
+/*     file. Setting \fBvar_use_limit\fR to zero disables the
+/*     client limit.
 /*
 /*     The var_idle_limit variable limits the time that a service
 /*     receives no client connection requests before it commits suicide.
@@ -249,7 +247,7 @@ static NORETURN single_server_exit(void)
 static NORETURN single_server_retire(int unused_event, void *unused_context)
 {
     if (msg_verbose)
-        msg_info("time to retire -- exiting");
+       msg_info("time to retire -- exiting");
     single_server_exit();
 }
 
@@ -458,6 +456,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
     int     redo_syslog_init = 0;
     const char *dsn_filter_title;
     const char **dsn_filter_maps;
+    int     retire_me_from_flags = 0;
     int     retire_me = 0;
 
     /*
@@ -516,7 +515,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
      * stderr, because no-one is going to see them.
      */
     opterr = 0;
-    while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:s:St:uvVz")) > 0) {
+    while ((c = GETOPT(argc, argv, "cdDi:lm:n:o:r:s:St:uvVz")) > 0) {
        switch (c) {
        case 'c':
            root_dir = "setme";
@@ -548,6 +547,10 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
                redo_syslog_init = 1;
            myfree(oname_val);
            break;
+       case 'r':
+           if ((retire_me_from_flags = atoi(optarg)) <= 0)
+               msg_fatal("invalid retirement time: %s", optarg);
+           break;
        case 's':
            if ((socket_count = atoi(optarg)) <= 0)
                msg_fatal("invalid socket_count: %s", optarg);
@@ -668,9 +671,11 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
            bounce_client_init(dsn_filter_title, *dsn_filter_maps);
            break;
        case MAIL_SERVER_RETIRE_ME:
-           if (var_idle_limit == 0 || var_use_limit == 0 
-               || var_idle_limit > 86400 / var_use_limit)
-               retire_me = 86400;
+           if (retire_me_from_flags > 0)
+               retire_me = retire_me_from_flags;
+           else if (var_idle_limit == 0 || var_use_limit == 0
+                    || var_idle_limit > 18000 / var_use_limit)
+               retire_me = 18000;
            else
                retire_me = var_idle_limit * var_use_limit;
            break;
index a09abb7111935006724bfdd5c84ebfd58f479328..778a3d5245b69c6f1c054978ae267278a2d1b8d7 100644 (file)
@@ -645,7 +645,7 @@ char   *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int);
 
 #ifdef USE_TLS
 #define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
-       (state->tls->level > TLS_LEV_ENCRYPT ? SMTP_KEY_FLAG_NEXTHOP : 0)
+       (TLS_MUST_MATCH(state->tls->level) ? SMTP_KEY_FLAG_NEXTHOP : 0)
 #else
 #define COND_TLS_SMTP_KEY_FLAG_NEXTHOP \
        (0)
index 2bc5c5ed0ec07c98ce6f33c74f1eb7329aae2452..f4b4996c50b715c11af918594a642c9b55bb39da 100644 (file)
@@ -251,10 +251,15 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, int endp_key_flags)
 
     /*
      * Allow address-based reuse only for security levels that don't require
-     * certificate checks.
+     * 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).
      */
 #ifdef USE_TLS
-    if (state->tls->level > TLS_LEV_ENCRYPT)
+    if (TLS_MUST_MATCH(state->tls->level))
        return (0);
 #endif
 
index 5858ad298a0a687d6e51f1f6705eea4c13841a60..dfcf3e0ce7b94aae39083d842f7b98a1f55ae8dd 100644 (file)
@@ -1329,6 +1329,7 @@ int     main(int argc, char **argv)
                      CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
                      CA_MAIL_SERVER_POST_INIT(post_jail_init),
                      CA_MAIL_SERVER_SLOW_EXIT(tlsp_drain),
+                     CA_MAIL_SERVER_RETIRE_ME,
                      CA_MAIL_SERVER_WATCHDOG(&var_tlsp_watchdog),
                      0);
 }