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.

Reply via email to