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. */