This is an updated version of the patch for Postfix 3.4 and 3.5
that addresses two different tlsproxy problems. I've been running
this code since Friday; it is part of today's Postfix 3.5 snapshot.

The longer-term solution is to allow plaintext output to drain
without having code to whitewash OpenSSL error results. But that
change is too invasive for a stable release.

        Wietse

To enable SMTP/TLS connection reuse on a running system:

    postconf smtp_tls_connection_reuse=yes
    postfix reload

To disable SMTP/TLS connection reuse on a running system:

    postconf smtp_tls_connection_reuse=no
    postfix reload (this also flushes the connection cache)
    manually kill any looping tlsproxy process

Unfortunately, already running SMTP client processes will keep using
"smtp_tls_connection_reuse=yes" and will keep using tlsproxy until
they have exhausted smtp_mx_address_limit or smtp_mx_session_limit.
But the odds of the problem returning will be small.

20190906

        Bugfix (introduced: Postfix 3.4): don't whitewash OpenSSL
        error results after a plaintext output error. The code could
        loop, and with some OpenSSL error results could flood the
        log with error messages (see below for a specific case).
        Problem reported by Andreas Schulze. File: tlsproxy/tlsproxy.c.

        Bitrot: don't invoke SSL_shutdown() when the SSL engine
        thinks it is processing a handshake. As of OpenSSL 1.something
        this returns SSL_ERROR_SSL instead of SSL_ERROR_NONE. File:
        tlsproxy/tlsproxy.c.

diff --exclude=man --exclude=html --exclude=README_FILES --exclude=INSTALL 
--exclude=.indent.pro --exclude=Makefile.in -r -ur 
/var/tmp/postfix-3.5-20190724/src/tlsproxy/tlsproxy.c ./src/tlsproxy/tlsproxy.c
--- /var/tmp/postfix-3.5-20190724/src/tlsproxy/tlsproxy.c       2019-07-23 
18:54:20.000000000 -0400
+++ ./src/tlsproxy/tlsproxy.c   2019-09-06 17:32:36.000000000 -0400
@@ -678,7 +678,8 @@
        /*
         * Allow buffered-up plaintext output to trickle out.
         */
-       if (state->plaintext_buf && NBBIO_WRITE_PEND(state->plaintext_buf))
+       if (state->plaintext_buf && !NBBIO_ERROR_FLAGS(state->plaintext_buf)
+           && NBBIO_WRITE_PEND(state->plaintext_buf))
            return (TLSP_STAT_OK);
        tlsp_state_free(state);
        return (TLSP_STAT_ERR);
@@ -784,9 +785,8 @@
     if (NBBIO_ERROR_FLAGS(plaintext_buf)) {
        if (NBBIO_ACTIVE_FLAGS(plaintext_buf))
            nbbio_disable_readwrite(state->plaintext_buf);
-       ssl_stat = SSL_shutdown(tls_context->con);
-       /* XXX Wait for return value 1 if sessions are to be reused? */
-       if (ssl_stat < 0) {
+       if (!SSL_in_init(tls_context->con)
+           && (ssl_stat = SSL_shutdown(tls_context->con)) < 0) {
            handshake_err = SSL_get_error(tls_context->con, ssl_stat);
            tlsp_eval_tls_error(state, handshake_err);
            /* At this point, state could be a dangling pointer. */

Reply via email to