20140209 Workaround: the Postfix SMTP client now also falls back to plaintext when TLS fails after the TLS protocol handshake. Files: smtp/smtp.h, smtp/smtp_connect.c, smtp/smtp_trouble.c. diff -cr /var/tmp/postfix-2.12-20140115/src/smtp/Makefile.in src/smtp/Makefile.in *** /var/tmp/postfix-2.12-20140115/src/smtp/Makefile.in Wed Nov 20 17:00:26 2013 --- src/smtp/Makefile.in Sun Feb 9 15:54:25 2014 *************** *** 728,733 **** --- 728,734 ---- smtp_trouble.o: ../../include/vstream.h smtp_trouble.o: ../../include/vstring.h smtp_trouble.o: smtp.h + smtp_trouble.o: smtp_sasl.h smtp_trouble.o: smtp_trouble.c smtp_unalias.o: ../../include/argv.h smtp_unalias.o: ../../include/attr.h diff -cr /var/tmp/postfix-2.12-20140115/src/smtp/smtp.h src/smtp/smtp.h *** /var/tmp/postfix-2.12-20140115/src/smtp/smtp.h Fri Jan 3 20:02:30 2014 --- src/smtp/smtp.h Sun Feb 9 17:46:40 2014 *************** *** 453,458 **** --- 453,481 ---- * Encapsulate the following so that we don't expose details of of * connection management and error handling to the SMTP protocol engine. */ + #ifdef USE_SASL_AUTH + #define HAVE_SASL_CREDENTIALS \ + (var_smtp_sasl_enable \ + && *var_smtp_sasl_passwd \ + && smtp_sasl_passwd_lookup(session)) + #else + #define HAVE_SASL_CREDENTIALS (0) + #endif + + #define PLAINTEXT_FALLBACK_OK_AFTER_STARTTLS_FAILURE \ + (session->tls_context == 0 \ + && session->tls->level == TLS_LEV_MAY \ + && !HAVE_SASL_CREDENTIALS) + + #define PLAINTEXT_FALLBACK_OK_AFTER_TLS_SESSION_FAILURE \ + (session->tls_context != 0 \ + && session->tls->level == TLS_LEV_MAY \ + && !HAVE_SASL_CREDENTIALS) + + /* + * XXX The following will not retry recipients that were deferred while the + * SMTP_MISC_FLAG_FINAL_SERVER flag was already set. + */ #define RETRY_AS_PLAINTEXT do { \ session->tls_retry_plain = 1; \ state->misc_flags &= ~SMTP_MISC_FLAG_FINAL_SERVER; \ Only in src/smtp: smtp__proto.c diff -cr /var/tmp/postfix-2.12-20140115/src/smtp/smtp_connect.c src/smtp/smtp_connect.c *** /var/tmp/postfix-2.12-20140115/src/smtp/smtp_connect.c Fri Jan 3 19:56:24 2014 --- src/smtp/smtp_connect.c Sat Feb 8 07:58:16 2014 *************** *** 1015,1020 **** --- 1015,1033 ---- && next == 0) state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER; smtp_xfer(state); + #ifdef USE_TLS + + /* + * When opportunistic TLS fails after the STARTTLS + * handshake, try the same address again, with TLS + * disabled. See also the RETRY_AS_PLAINTEXT macro. + */ + if ((retry_plain = session->tls_retry_plain) != 0) { + --sess_count; + --addr_count; + next = addr; + } + #endif } smtp_cleanup_session(state); } else { diff -cr /var/tmp/postfix-2.12-20140115/src/smtp/smtp_proto.c src/smtp/smtp_proto.c *** /var/tmp/postfix-2.12-20140115/src/smtp/smtp_proto.c Fri Jan 3 19:56:24 2014 --- src/smtp/smtp_proto.c Sun Feb 9 16:43:48 2014 *************** *** 838,850 **** * plaintext connections, then we don't want delivery to fail with * "relay access denied". */ ! if (session->tls->level == TLS_LEV_MAY ! #ifdef USE_SASL_AUTH ! && !(var_smtp_sasl_enable ! && *var_smtp_sasl_passwd ! && smtp_sasl_passwd_lookup(session)) ! #endif ! ) RETRY_AS_PLAINTEXT; return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "4.7.5"), --- 838,844 ---- * plaintext connections, then we don't want delivery to fail with * "relay access denied". */ ! if (PLAINTEXT_FALLBACK_OK_AFTER_STARTTLS_FAILURE) RETRY_AS_PLAINTEXT; return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "4.7.5"), diff -cr /var/tmp/postfix-2.12-20140115/src/smtp/smtp_trouble.c src/smtp/smtp_trouble.c *** /var/tmp/postfix-2.12-20140115/src/smtp/smtp_trouble.c Mon Jun 11 11:25:02 2012 --- src/smtp/smtp_trouble.c Sun Feb 9 17:03:16 2014 *************** *** 156,161 **** --- 156,162 ---- /* Application-specific. */ #include "smtp.h" + #include "smtp_sasl.h" #define SMTP_THROTTLE 1 #define SMTP_NOTHROTTLE 0 *************** *** 433,442 **** --- 434,447 ---- case SMTP_ERR_EOF: dsb_simple(why, "4.4.2", "lost connection with %s while %s", session->namaddr, description); + if (PLAINTEXT_FALLBACK_OK_AFTER_TLS_SESSION_FAILURE) + RETRY_AS_PLAINTEXT; break; case SMTP_ERR_TIME: dsb_simple(why, "4.4.2", "conversation with %s timed out while %s", session->namaddr, description); + if (PLAINTEXT_FALLBACK_OK_AFTER_TLS_SESSION_FAILURE) + RETRY_AS_PLAINTEXT; break; case SMTP_ERR_DATA: session->error_mask |= MAIL_ERROR_DATA;