Viktor Dukhovni: > On Wed, Jan 14, 2015 at 06:08:16PM -0500, Wietse Venema wrote: > > > > The security level for "smtps" should be at least "encrypt" or > > > ideally "secure", though "fingerprint" and "dane-only" might also > > > options. We'd need to rule out "may" so as to avoid plaintext > > > fallback. > > > > That does not seem to be a problem - in "port 465" mode > > the SMTP client can always skip the plaintext handshake. > > I think I'll understand the code better than the above sentence... > > > I have prelimiary code almost working with little code. > > It certainly does not look too scary. Just add a flag to still > expect a 220 banner after TLS, and require a security level of at > least "encrypt", then, as you note, jump right into smtp_start_tls() > bypassing the outer smtp_helo().
This proof-of-concept version minimizes scar tissue, by patching into the existing code path. Things that I might want to change: - Move the new smtp_start_tls() call + flags twiddling ito a new function smtp_smtps() that is at the same level as smtp_helo(). - Add an smtp_tls_wrapper_mode parameter, instead of the hard-coded port 465 heuristic. The main take-away from this exercise is that SMTPS support does not require any invasive changes to existing code. Also, there is no need for smtp_tls_security_level=encrypt since the client will not send plaintext anyway. Any smtp_tls_security_level that is not "none" will suffice. Wietse diff --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in --exclude=INSTALL -ur /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp.h src/smtp/smtp.h --- /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp.h 2014-12-28 10:11:50.000000000 -0500 +++ src/smtp/smtp.h 2015-01-14 17:31:14.000000000 -0500 @@ -248,6 +248,7 @@ #define SMTP_MISC_FLAG_COMPLETE_SESSION (1<<7) #define SMTP_MISC_FLAG_PREF_IPV6 (1<<8) #define SMTP_MISC_FLAG_PREF_IPV4 (1<<9) +#define SMTP_MISC_FLAG_SMTPS (1<<10) #define SMTP_MISC_FLAG_CONN_CACHE_MASK \ (SMTP_MISC_FLAG_CONN_LOAD | SMTP_MISC_FLAG_CONN_STORE) diff --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in --exclude=INSTALL -ur /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp_connect.c src/smtp/smtp_connect.c --- /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp_connect.c 2014-12-06 20:35:33.000000000 -0500 +++ src/smtp/smtp_connect.c 2015-01-14 17:53:06.000000000 -0500 @@ -820,9 +820,14 @@ * specified, or when DNS lookups are disabled. */ dest_buf = smtp_parse_destination(dest, def_service, &domain, &port); - if (var_helpful_warnings && ntohs(port) == 465) { - msg_info("CLIENT wrappermode (port smtps/465) is unimplemented"); - msg_info("instead, send to (port submission/587) with STARTTLS"); + if (ntohs(port) == 465) { + if (smtp_tls_ctx == 0) { + msg_warn("destination %s requires TLS support, " + "but %s appears to be disabled", + dest, VAR_SMTP_TLS_LEVEL); + continue; + } + state->misc_flags |= SMTP_MISC_FLAG_SMTPS; } #define NO_HOST "" /* safety */ #define NO_ADDR "" /* safety */ diff --exclude=man --exclude=html --exclude=README_FILES --exclude=.indent.pro --exclude=Makefile.in --exclude=INSTALL -ur /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp_proto.c src/smtp/smtp_proto.c --- /var/tmp/postfix-2.12-20150113-nonprod/src/smtp/smtp_proto.c 2014-12-28 13:22:09.000000000 -0500 +++ src/smtp/smtp_proto.c 2015-01-14 19:09:18.000000000 -0500 @@ -325,6 +325,18 @@ const char *NOCLOBBER where; /* + * Skip the initial handshake in SMTPS mode. + */ + if ((state->misc_flags & SMTP_MISC_FLAG_SMTPS) + && (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) { + /* XXX Mix-up of per-session and per-request flags. */ + state->misc_flags |= SMTP_MISC_FLAG_IN_STARTTLS; + tls_helo_status = smtp_start_tls(state); + state->misc_flags &= ~SMTP_MISC_FLAG_IN_STARTTLS; + return (tls_helo_status); + } + + /* * Prepare for disaster. */ smtp_stream_setup(state->session->stream, var_smtp_helo_tmout, @@ -336,7 +348,8 @@ * If not recursing after STARTTLS, examine the server greeting banner * and decide if we are going to send EHLO as the next command. */ - if ((state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) { + if ((state->misc_flags & SMTP_MISC_FLAG_SMTPS) + || (state->misc_flags & SMTP_MISC_FLAG_IN_STARTTLS) == 0) { /* * Read and parse the server's SMTP greeting banner.