]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.12-20150118
authorWietse Venema <wietse@porcupine.org>
Sun, 18 Jan 2015 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Mon, 19 Jan 2015 02:06:30 +0000 (21:06 -0500)
12 files changed:
postfix/HISTORY
postfix/README_FILES/COMPATIBILITY_README
postfix/WISHLIST
postfix/html/COMPATIBILITY_README.html
postfix/proto/COMPATIBILITY_README.html
postfix/src/global/mail_version.h
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtp/smtp_tls_policy.c
postfix/src/smtpd/smtpd.c
postfix/src/tls/tls.h
postfix/src/tls/tls_client.c
postfix/src/tls/tls_fprint.c

index 318c8c7542a99fd2b5db5ba9bcf7fd534f2c51cd..950281132c8c91b2130f0bc13b4c612cff218513 100644 (file)
@@ -11196,7 +11196,7 @@ Apologies for any names omitted.
        in the anvil server, TLS request rate error message in the
        smtp server, and documentation, but no changes in code.
        Files: anvil/anvil.c, smtpd/smtpd.c.
+
 20051013
 
        Horror: some systems have basename() and dirname() and some
@@ -19583,8 +19583,8 @@ Apologies for any names omitted.
        smtp/smtp.h, smtp/smtp_rcpt.c.
 
        Logging: the TLS client logged that an "Untrusted" TLS
-       connection was established instead of "Anonymous".
-       Viktor Dukhovni. File: tls/tls_client.c.
+       connection was established instead of "Anonymous".  Viktor
+       Dukhovni. File: tls/tls_client.c.
 
        Documentation: new self-signed certificate example and
        updated private CA example. File: proto/TLS_README.html.
@@ -19662,7 +19662,7 @@ Apologies for any names omitted.
 20140323
 
        Feature: initial merge of Debian-style dynamic linking.
-       Viktor Dukhovni. 
+       Viktor Dukhovni.
 
 20140406
 
@@ -19755,8 +19755,8 @@ Apologies for any names omitted.
 20140508
 
        Cleanup: dynamicmaps.cf is now installed into $daemon_directory
-       because the file is shared among Postfix instances just like
-       postfix-files and other files.  Files: conf/dynamicmaps.cf,
+       because the file is shared among Postfix instances just
+       like postfix-files and other files.  Files: conf/dynamicmaps.cf,
        Makefile.in, conf/postfix-files.
 
        Cleanup: INSTALL is now plain ASCII instead of README format,
@@ -19807,11 +19807,11 @@ Apologies for any names omitted.
        Support for "make shared=yes" and "make dynamicmaps=yes".
        New plugin_directory parameter for the location of the
        dynamicmaps.cf file and for plugins with a relative pathname.
-       See RELEASE_NOTES and INSTALL for details. Files:
-       postfix.c, mail_params.[hc], dynamicmaps.c, mail_dict.c,
-       makedefs, postfix-files, dynamicmaps.cf, Makefile.in,
-       util/Makefile.in, global/Makefile.in, postlink, postconf.proto.
-       INSTALL.html, RELEASE_NOTES.
+       See RELEASE_NOTES and INSTALL for details. Files: postfix.c,
+       mail_params.[hc], dynamicmaps.c, mail_dict.c, makedefs,
+       postfix-files, dynamicmaps.cf, Makefile.in, util/Makefile.in,
+       global/Makefile.in, postlink, postconf.proto.  INSTALL.html,
+       RELEASE_NOTES.
 
 20140523
 
@@ -20243,9 +20243,9 @@ Apologies for any names omitted.
        Cleanup: change extract_addr() API to indicate that an
        address is parsed in SMTPUTF8 context. File: smtpd/smtpd.c.
 
-       Cleanup: shared-library build fixes. Viktor Dukhovni.
-       Files: makedefs, dns/Makefile.in, global/Makefile.in,
-       master/Makefile.in, tls/Makefile.in, util/Makefile.in.
+       Cleanup: shared-library build fixes. Viktor Dukhovni.  Files:
+       makedefs, dns/Makefile.in, global/Makefile.in, master/Makefile.in,
+       tls/Makefile.in, util/Makefile.in.
 
        First general release with SMTPUTF8 support; see RELEASE_NOTES
        for an initial writeup.  The last pre-SMTPUTF8 release is
@@ -20317,8 +20317,8 @@ Apologies for any names omitted.
 
 20140731
 
-       Feature: the Postfix SMTP server now logs at the end of
-       session how many times each SMTP command was successfully
+       Feature: the Postfix SMTP server now logs at the end of a
+       session how many times each SMTP command was successfully
        invoked, followed by the total number of invocations if it
        is different.  File: smtpd/smtpd.c.
 
@@ -20431,7 +20431,7 @@ Apologies for any names omitted.
 
        Cleanup: dict_db and dict_lmdb global settings. Files:
        global/mail_params.c, util/dict_open.c.
-       
+
        Feature: unionmap, based on contribution by Roel van Meer.
        Files: mantools/postlink, postconf/postconf.c (manpage),
        proto/DATABASE_README.html, util/dict_open.c, util/dict_union.[hc].
@@ -20461,9 +20461,9 @@ Apologies for any names omitted.
 
 20140927
 
-       Cleanup: specify { name = value } in per-Milter settings, to support
-       space around the "=" or comma/space within the value. Files:
-       global/attr_over.[hc]. 
+       Cleanup: specify { name = value } in per-Milter settings,
+       to support space around the "=" or comma/space within the
+       value. Files: global/attr_over.[hc].
 
        Cleanup: "postconf -n" now only shows config_directory when
        an override is in effect (environment, -c or -o).
@@ -20504,15 +20504,14 @@ Apologies for any names omitted.
 
        Cleanup: force LANG=C to prevent groff from outputting
        non-ASCII cruft into the HTML-ized manpages.  Files:
-       html/Makefile.in, proto/Makefile.in, many HTML output
-       files.
+       html/Makefile.in, proto/Makefile.in, many HTML output files.
 
 20140929
 
        Cleanup: the table-driven code for per-Milter and per-policy
-       overrides now updates arbitrary variables, so that it can also
-       be used for, say, TLS policies. Files: global/attr_override.[hc],
-       smtpd/smtpd_check.c, milter/milter.c.
+       overrides now updates arbitrary variables, so that it can
+       also be used for, say, TLS policies. Files:
+       global/attr_override.[hc], smtpd/smtpd_check.c, milter/milter.c.
 
        Documentation: support for "{ argument with whitespace }"
        in master(5) and pipe(8). Files: proto/master, src/pipe/pipe.c.
@@ -20524,12 +20523,12 @@ Apologies for any names omitted.
 
 20141001
 
-       Safety: backwards-compatibility safety net that forces Postfix
-       to run with backwards-compatible default settings after an
-       upgrade to a newer Postfix version.  Postfix logs all uses
-       of those backwards-compatible default settings so that the
-       system administator can determine whether or not some
-       backwards-compatible default settings need to be made
+       Safety: backwards-compatibility safety net that forces
+       Postfix to run with backwards-compatible default settings
+       after an upgrade to a newer Postfix version.  Postfix logs
+       all uses of those backwards-compatible default settings so
+       that the system administator can determine whether or not
+       some backwards-compatible default settings need to be made
        permanent in main.cf or master.cf.  All this is controlled
        with a new compatibility_level parameter, default value 0.
        Files: global/mail_params.[hc], trivial-rewrite/rewrite.c,
@@ -20556,9 +20555,9 @@ Apologies for any names omitted.
 
 20141003
 
-       Workaround: kludge for multiple paragraphs of text in indented
-       paragraphs.  Files: mantools/postconf2html, mantools/postconf2man,
-       proto/Makefile.in, proto/postconf.proto
+       Workaround: kludge for multiple paragraphs of text in
+       indented paragraphs.  Files: mantools/postconf2html,
+       mantools/postconf2man, proto/Makefile.in, proto/postconf.proto
 
 20141005
 
@@ -20605,8 +20604,9 @@ Apologies for any names omitted.
        a new COMPATIBILITY_README document. Files: proto/postconf.proto,
        proto/COMPATIBILITY_README.html html/index.html.
 
-       Documentation: update the conf/main.cf compatibility_level setting 
-       for new Postfix installs, and updated a reminder in mail_params.h.
+       Documentation: update the conf/main.cf compatibility_level
+       setting for new Postfix installs, and updated a reminder
+       in mail_params.h.
 
 20141010
 
@@ -20898,7 +20898,7 @@ Apologies for any names omitted.
        about that later.  Files: smtpd/smtpd_check.c, smtp/smtp_addr.c,
        dns/dns.h, dns/dns_lookup.c.
 
-       Cleanup: eliminate TLS state duplication from state->tls 
+       Cleanup: eliminate TLS state duplication from state->tls
        to session->tls. Viktor Dukhovni. Files: src/smtp/smtp.h,
        src/smtp/smtp_connect.c, src/smtp/smtp_proto.c,
        src/smtp/smtp_reuse.c, src/smtp/smtp_session.c.
@@ -21011,8 +21011,8 @@ Apologies for any names omitted.
 
 20141208
 
-       Bugfix (introduced: 20141207): in new #ifdef, && should be ||.
-       File: smtpd.c.
+       Bugfix (introduced: 20141207): in new #ifdef, && should be
+       ||.  File: smtpd.c.
 
 20141210
 
@@ -21180,7 +21180,7 @@ Apologies for any names omitted.
 
        Cleanup: instead of making up new names, use a consistent
        CA_ prefix for macros that implement compile-time argument
-       typechecks for non-protocol attribute-value APIs. This 
+       typechecks for non-protocol attribute-value APIs. This
        transformation and its verification are mechanical.
 
        Bugfix (introduced: Postfix 1.1, but latent before 2.12):
@@ -21204,11 +21204,11 @@ Apologies for any names omitted.
 
 20141228
 
-       Cleanup: the IDNA conversion routines now accept both
-       ASCII and UTF8 inputs. The functions als verify that 
-       either their result is a valid ASCII domain name or that
-       it converts into a valid ASCII domain name. Files:
-       util/midna.c, util/midna_test.in, util/midna_test.ref.
+       Cleanup: the IDNA conversion routines now accept both ASCII
+       and UTF8 inputs. The functions als verify that either their
+       result is a valid ASCII domain name or that it converts
+       into a valid ASCII domain name. Files: util/midna.c,
+       util/midna_test.in, util/midna_test.ref.
 
 20141230
 
@@ -21238,9 +21238,10 @@ Apologies for any names omitted.
        byte values, and UTF-8 case folding. As recommended at
        http://www.w3.org/International/wiki/Case_folding for
        caseless string comparison, this uses the en_US locale to
-       avoid surprises. The implementatin handles
-        the entire RFC 3629 Unicode range (code points U+0000..U+10FFFF
-        including surrogates) and is chroot(2) safe. Files: casefold.c, stringops.h.
+       avoid surprises. The implementatin handles the entire RFC
+       3629 Unicode range (code points U+0000..U+10FFFF including
+       surrogates) and is chroot(2) safe. Files: casefold.c,
+       stringops.h.
 
        Infrastructure: revised the midna_domain_to_ascii and
        midna_domain_to_utf8 domain name conversion functions after
@@ -21412,3 +21413,16 @@ Apologies for any names omitted.
 
        Cleanup: missing " in \%s\" in postscreen(8) fatal error
        messages. Iain Hibbert. File: postconf/postconf_master.c.
+
+20150118
+
+       Bugfix (introduced: 20140731): when a connection timed out
+       before any command was received, the Postfix SMTP server
+       "disconnect from" logging would show the content of the
+       last SMTP server response (421 4.4.2 $myhostname error:
+       timeout exceeded) instead of per-command statistics, because
+       there were no statistics to report.  The Postfix SMTP server
+       now always logs the total number of commands (commands=x/y)
+       even when the client did not send any. This helps logfile
+       analyzers to recognize sessions without commands.  File:
+       smtpd/smtpd.c.
index f3978c15bdadc925eed2d8d7b17b58a24b5029c7..223597d86f7cb2db9810a30f34911cf738f4d9d9 100644 (file)
@@ -151,9 +151,11 @@ provide ETRN service for that domain, then the system administrator should make
 the backwards-compatible setting "relay_domains = $mydestination" permanent in
 main.cf:
 
-    # p\bpo\bos\bst\btc\bco\bon\bnf\br\bre\bel\bla\bay\by_\b_d\bdo\bom\bma\bai\bin\bns\bs=\b=$\b$m\bmy\byd\bde\bes\bst\bti\bin\bna\bat\bti\bio\bon\bn
+    # p\bpo\bos\bst\btc\bco\bon\bnf\b'\b'r\bre\bel\bla\bay\by_\b_d\bdo\bom\bma\bai\bin\bns\bs=\b=$\b$m\bmy\byd\bde\bes\bst\bti\bin\bna\bat\bti\bio\bon\bn'\b'
     # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
 
+Note: quotes are required as indicated above.
+
 Instead of $mydestination, it may be better to specify an explicit list of
 domain names.
 
index b83e5f0f3420bdc2a6dd7d09ec1f7058b6a00d6b..9262c9904d91b733e7e1e9f7be1337ea3f630289 100644 (file)
@@ -8,6 +8,12 @@ Wish list:
 
        Things to do after the stable release:
 
+       postconf -P: emit '{ name = value }' when editing/adding a
+       parameter whose new value contains whitespace.
+
+       In release-notes add commands=x/y logging to the command
+       statistics.
+
        UTF8 DNS[BW]L domain name.
 
        Consolidate maps flags in mail_params.h instead of having
index 4c0cfdb8a0e944584fd3981618fa6d4d68cb495e..87519dd5a6fcb15750bc33edf6026fd61c90b200 100644 (file)
@@ -253,11 +253,13 @@ administrator should make the backwards-compatible setting
 
 <blockquote>
 <pre>
-# <b>postconf <a href="postconf.5.html#relay_domains">relay_domains</a>=$<a href="postconf.5.html#mydestination">mydestination</a></b>
+# <b>postconf '<a href="postconf.5.html#relay_domains">relay_domains</a>=$<a href="postconf.5.html#mydestination">mydestination</a>'</b>
 # <b>postfix reload</b>
 </pre>
 </blockquote>
 
+<p> Note: quotes are required as indicated above. </p>
+
 <p> Instead of $<a href="postconf.5.html#mydestination">mydestination</a>, it may be better to specify an
 explicit list of domain names. </p>
 
index c9032148168b6e4d190a168acb0c4f2dc92ebab8..6b4b9b57b6daf4a4a3f4fb4ec0eeebc1a2c9b176 100644 (file)
@@ -253,11 +253,13 @@ administrator should make the backwards-compatible setting
 
 <blockquote>
 <pre>
-# <b>postconf relay_domains=$mydestination</b>
+# <b>postconf 'relay_domains=$mydestination'</b>
 # <b>postfix reload</b>
 </pre>
 </blockquote>
 
+<p> Note: quotes are required as indicated above. </p>
+
 <p> Instead of $mydestination, it may be better to specify an
 explicit list of domain names. </p>
 
index 14f2f9bb1b9fe2819ce2f997afafe4762fafc632..8205d448d521c77349e17116d8b588b66bf8e56a 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20150117"
+#define MAIL_RELEASE_DATE      "20150118"
 #define MAIL_VERSION_NUMBER    "2.12"
 
 #ifdef SNAPSHOT
index 8be46e40bd1564f54e3b114516d0814ad42af811..81680f176f2fe4fac6b1076bc79991b185f9f078 100644 (file)
 /* .IP "\fB-v\fR"
 /*     Enable verose Postfix logging.  Specify more than once to increase
 /*     the level of verbose logging.
+/* .IP "\fB-w\fR"
+/*     Enable outgoing TLS wrapper mode, or SMTPS support.  This is typically
+/*     provided on port 465 by servers that are compatible with the ad-hoc
+/*     SMTP in SSL protocol, rather than the standard STARTTLS protocol.
+/*     The destination \fIdomain\fR:\fIport\fR should of course provide such
+/*     a service.
 /* .IP "[\fBinet:\fR]\fIdomain\fR[:\fIport\fR]"
 /*     Connect via TCP to domain \fIdomain\fR, port \fIport\fR. The default
 /*     port is \fBsmtp\fR (or 24 with LMTP).  With SMTP an MX lookup is
@@ -421,6 +427,7 @@ typedef struct STATE {
     VSTRING *buffer;                   /* Response buffer */
     VSTREAM *stream;                   /* Open connection */
     int     level;                     /* TLS security level */
+    int     wrapper_mode;              /* SMTPS support */
 #ifdef USE_TLS
     char   *mdalg;                     /* fingerprint digest algorithm */
     char   *CAfile;                    /* Trusted public CAs */
@@ -547,6 +554,33 @@ static char *exception_text(int except)
     }
 }
 
+/* greeting - read server's 220 greeting */
+
+static int greeting(STATE *state)
+{
+    VSTREAM *stream = state->stream;
+    int     except;
+    RESPONSE *resp;
+
+    /*
+     * Prepare for disaster.
+     */
+    smtp_stream_setup(stream, conn_tmout, 1);
+    if ((except = vstream_setjmp(stream)) != 0) {
+       msg_info("%s while reading server greeting", exception_text(except));
+       return (1);
+    }
+
+    /*
+     * Read and parse the server's SMTP greeting banner.
+     */
+    if (((resp = response(state, 1))->code / 100) != 2) {
+       msg_info("SMTP service not available: %d %s", resp->code, resp->str);
+       return (1);
+    }
+    return (0);
+}
+
 /* ehlo - send EHLO/LHLO */
 
 static RESPONSE *ehlo(STATE *state)
@@ -647,26 +681,27 @@ static int starttls(STATE *state)
     VSTREAM *stream = state->stream;
     TLS_CLIENT_START_PROPS tls_props;
 
-    /* SMTP stream with deadline timeouts */
-    smtp_stream_setup(stream, smtp_tmout, 1);
-    if ((except = vstream_setjmp(stream)) != 0) {
-       msg_fatal("%s while sending STARTTLS", exception_text(except));
-       return (1);
-    }
-    command(state, state->pass == 1, "STARTTLS");
-
-    resp = response(state, state->pass == 1);
-    if (resp->code / 100 != 2) {
-       msg_info("STARTTLS rejected: %d %s", resp->code, resp->str);
-       return (1);
-    }
+    if (state->wrapper_mode == 0) {
+       /* SMTP stream with deadline timeouts */
+       smtp_stream_setup(stream, smtp_tmout, 1);
+       if ((except = vstream_setjmp(stream)) != 0) {
+           msg_fatal("%s while sending STARTTLS", exception_text(except));
+           return (1);
+       }
+       command(state, state->pass == 1, "STARTTLS");
 
-    /*
-     * Discard any plain-text data that may be piggybacked after the server's
-     * 220 STARTTLS reply. Should we abort the session instead?
-     */
-    vstream_fpurge(stream, VSTREAM_PURGE_READ);
+       resp = response(state, state->pass == 1);
+       if (resp->code / 100 != 2) {
+           msg_info("STARTTLS rejected: %d %s", resp->code, resp->str);
+           return (1);
+       }
 
+       /*
+        * Discard any plain-text data that may be piggybacked after the
+        * server's 220 STARTTLS reply. Should we abort the session instead?
+        */
+       vstream_fpurge(stream, VSTREAM_PURGE_READ);
+    }
 #define ADD_EXCLUDE(vstr, str) \
     do { \
        if (*(str)) \
@@ -718,6 +753,9 @@ static int starttls(STATE *state)
        state->stream = 0;
        return (1);
     }
+    if (state->wrapper_mode && greeting(state) != 0)
+       return (1);
+
     if (state->pass == 1) {
        ehlo(state);
        if (!TLS_CERT_IS_PRESENT(state->tls_context))
@@ -743,42 +781,27 @@ static int doproto(STATE *state)
     int     except;
     int     n;
     char   *lines;
-    char   *words;
+    char   *words = 0;
     char   *word;
 
-    /*
-     * Prepare for disaster.
-     */
-    smtp_stream_setup(stream, conn_tmout, 1);
-    if ((except = vstream_setjmp(stream)) != 0)
-       msg_fatal("%s while reading server greeting", exception_text(except));
-
-    /*
-     * Read and parse the server's SMTP greeting banner.
-     */
-    if (((resp = response(state, 1))->code / 100) != 2) {
-       msg_info("SMTP service not available: %d %s", resp->code, resp->str);
-       return (1);
-    }
-
-    /*
-     * Send the standard greeting with our hostname
-     */
-    if ((resp = ehlo(state)) == 0)
-       return (1);
+    if (!state->wrapper_mode) {
+       if (greeting(state) != 0)
+           return (1);
+       if ((resp = ehlo(state)) == 0)
+           return (1);
 
-    lines = resp->str;
-    for (n = 0; (words = mystrtok(&lines, "\n")) != 0; ++n) {
-       if ((word = mystrtok(&words, " \t=")) != 0) {
-           if (n == 0)
-               state->helo = mystrdup(word);
-           if (strcasecmp(word, "STARTTLS") == 0)
-               break;
+       lines = resp->str;
+       for (n = 0; (words = mystrtok(&lines, "\n")) != 0; ++n) {
+           if ((word = mystrtok(&words, " \t=")) != 0) {
+               if (n == 0)
+                   state->helo = mystrdup(word);
+               if (strcasecmp(word, "STARTTLS") == 0)
+                   break;
+           }
        }
     }
-
 #ifdef USE_TLS
-    if (words && state->tls_ctx)
+    if ((state->wrapper_mode || words) && state->tls_ctx)
        if (starttls(state))
            return (1);
 #endif
@@ -793,7 +816,6 @@ static int doproto(STATE *state)
     }
     command(state, 1, "QUIT");
     (void) response(state, 1);
-
     return (0);
 }
 
@@ -1191,7 +1213,7 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
     int     level = state->level;
 
 #ifdef USE_TLS
-    if (level == TLS_LEV_DANE) {
+    if (TLS_DANE_BASED(level)) {
        if (state->mx == 0 || state->mx->dnssec_valid) {
            if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
                tls_dane_verbose(1);
@@ -1214,7 +1236,8 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
                           HNAME(addr), ntohs(state->port));
                level = TLS_LEV_INVALID;
            } else if (tls_dane_notfound(state->ddane)
-                      || tls_dane_unusable(state->ddane)) {
+                      || tls_dane_unusable(state->ddane)
+                      || level == TLS_LEV_DANE_ONLY) {
                if (msg_verbose)
                    msg_info("no %sTLSA records found, "
                             "resorting to \"secure\"",
@@ -1223,7 +1246,7 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
                level = TLS_LEV_SECURE;
            } else if (!TLS_DANE_HASTA(state->ddane)
                       && !TLS_DANE_HASEE(state->ddane)) {
-               msg_panic("empty DANE match list");
+               msg_panic("DANE activated with no TLSA records to match");
            } else {
                if (state->match)
                    argv_free(state->match);
@@ -1531,7 +1554,7 @@ static void usage(void)
 #ifdef USE_TLS
     fprintf(stderr, "usage: %s %s \\\n\t%s \\\n\t%s \\\n\t%s"
            " destination [match ...]\n", var_procname,
-           "[-acCfSv] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
+           "[-acCfSvw] [-t conn_tmout] [-T cmd_tmout] [-L logopts]",
         "[-h host_lookup] [-l level] [-d mdalg] [-g grade] [-p protocols]",
            "[-A tafile] [-F CAfile.pem] [-P CApath/] [-m count] [-r delay]",
            "[-o name=value]");
@@ -1594,6 +1617,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
     state->pass = 1;
     state->reconnect = -1;
     state->max_reconnect = 5;
+    state->wrapper_mode = 0;
 #ifdef USE_TLS
     state->protocols = mystrdup("!SSLv2");
     state->grade = mystrdup("medium");
@@ -1603,7 +1627,7 @@ static void parse_options(STATE *state, int argc, char *argv[])
 
 #define OPTS "a:ch:o:St:T:v"
 #ifdef USE_TLS
-#define TLSOPTS "A:Cd:fF:g:l:L:m:p:P:r:"
+#define TLSOPTS "A:Cd:fF:g:l:L:m:p:P:r:w"
 
     state->mdalg = mystrdup("sha1");
     state->CApath = mystrdup("");
@@ -1692,6 +1716,9 @@ static void parse_options(STATE *state, int argc, char *argv[])
        case 'r':
            state->reconnect = atoi(optarg);
            break;
+       case 'w':
+           state->wrapper_mode = 1;
+           break;
 #endif
        }
     }
@@ -1725,10 +1752,9 @@ static void parse_options(STATE *state, int argc, char *argv[])
        state->level = tls_level_lookup(state->options.level);
 
        switch (state->level) {
-       case TLS_LEV_DANE_ONLY:
-           state->level = TLS_LEV_DANE;
-           break;
        case TLS_LEV_NONE:
+           if (state->wrapper_mode)
+               msg_fatal("SSL wrapper mode requires that TLS not be disabled");
            return;
        case TLS_LEV_INVALID:
            msg_fatal("Invalid TLS level \"%s\"", state->options.level);
@@ -1741,8 +1767,8 @@ static void parse_options(STATE *state, int argc, char *argv[])
      * required for DANE support.
      */
     tls_init(state);
-    if (state->level == TLS_LEV_DANE && !tls_dane_avail()) {
-       msg_warn("The \"dane\" TLS security level is not available");
+    if (TLS_DANE_BASED(state->level) && !tls_dane_avail()) {
+       msg_warn("DANE TLS support is not available, resorting to \"secure\"");
        state->level = TLS_LEV_SECURE;
     }
     state->tls_bio = 0;
@@ -1780,6 +1806,7 @@ static void parse_match(STATE *state, int argc, char *argv[])
                                    state->mdalg, *argv++, "");
        break;
     case TLS_LEV_DANE:
+    case TLS_LEV_DANE_ONLY:
        state->match = argv_alloc(2);
        argv_add(state->match, "nexthop", "hostname", ARGV_END);
        break;
index 22b76ab492b0fb51a57e640e9ee1d3812046aee2..deb7e04dbfa6d48c0262fcfa5d2c17822de9f65a 100644 (file)
@@ -437,6 +437,7 @@ static void set_cipher_grade(SMTP_TLS_POLICY *tls)
        break;
 
     case TLS_LEV_DANE:
+    case TLS_LEV_DANE_ONLY:
     case TLS_LEV_FPRINT:
     case TLS_LEV_VERIFY:
     case TLS_LEV_SECURE:
@@ -534,7 +535,7 @@ static void *policy_create(const char *unused_key, void *context)
      * "dane-only" changes to "dane" once we obtain the requisite TLSA
      * records.
      */
-    if (tls->level == TLS_LEV_DANE || tls->level == TLS_LEV_DANE_ONLY)
+    if (TLS_DANE_BASED(tls->level))
        dane_init(tls, iter);
     if (tls->level == TLS_LEV_INVALID)
        return ((void *) tls);
@@ -563,6 +564,7 @@ static void *policy_create(const char *unused_key, void *context)
     case TLS_LEV_MAY:
     case TLS_LEV_ENCRYPT:
     case TLS_LEV_DANE:
+    case TLS_LEV_DANE_ONLY:
        break;
     case TLS_LEV_FPRINT:
        if (tls->dane == 0)
@@ -844,7 +846,6 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
     } else if (!TLS_DANE_HASEE(dane))
        msg_panic("empty DANE match list");
     tls->dane = dane;
-    tls->level = TLS_LEV_DANE;
     return;
 }
 
index 566bc3b2fbc9e5db2b915896e6e4ff86a034fb25..ad58afacb4f516f5789b80155f743f432050e331 100644 (file)
@@ -5132,7 +5132,13 @@ static void smtpd_proto(SMTPD_STATE *state)
 static char *smtpd_format_cmd_stats(VSTRING *buf)
 {
     SMTPD_CMD *cmdp;
+    int     all_success = 0;
+    int     all_total = 0;
 
+    /*
+     * Log the statistics. Note that this loop produces no output when no
+     * command was received. We address that after the loop.
+     */
     VSTRING_RESET(buf);
     for (cmdp = smtpd_cmd_table; /* see below */ ; cmdp++) {
        if (cmdp->total_count > 0) {
@@ -5141,10 +5147,22 @@ static char *smtpd_format_cmd_stats(VSTRING *buf)
                                   cmdp->success_count);
            if (cmdp->success_count != cmdp->total_count)
                vstring_sprintf_append(buf, "/%d", cmdp->total_count);
+           all_success += cmdp->success_count;
+           all_total += cmdp->total_count;
        }
        if (cmdp->name == 0)
            break;
     }
+
+    /*
+     * Log total numbers, so that logfile analyzers will see something even
+     * if the above loop produced no output. When no commands were received
+     * log "0/0" to simplify the identification of abnormal sessions: any
+     * statistics with [0-9]/ indicate that there was a problem.
+     */
+    vstring_sprintf_append(buf, " commands=%d", all_success);
+    if (all_success != all_total || all_total == 0)
+       vstring_sprintf_append(buf, "/%d", all_total);
     return (lowercase(STR(buf)));
 }
 
index 9e5f3dc8bf2a8de839b972cd802022f4fb0e05e2..16e49c58b3261841b127ef9fd6e601c7c241763c 100644 (file)
@@ -53,6 +53,8 @@
 #define TLS_MUST_MATCH(l)      ((l) > TLS_LEV_ENCRYPT)
 #define TLS_MUST_TRUST(l)      ((l) >= TLS_LEV_DANE)
 #define TLS_MUST_PKIX(l)       ((l) >= TLS_LEV_VERIFY)
+#define TLS_OPPORTUNISTIC(l)   ((l) == TLS_LEV_MAY || (l) == TLS_LEV_DANE)
+#define TLS_DANE_BASED(l)      ((l) == TLS_LEV_DANE || (l) == TLS_LEV_DANE_ONLY)
 
 extern const NAME_CODE tls_level_table[];
 
index 8211e2602e837c03db635ecbef002d3b2103008e..fc3d607ca0b8d23cf28809bcb1adb39b15d905af 100644 (file)
@@ -827,10 +827,10 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
     /*
      * When certificate verification is required, log trust chain validation
      * errors even when disabled by default for opportunistic sessions. For
-     * "dane" this only applies when using trust-anchor associations.
+     * DANE this only applies when using trust-anchor associations.
      */
     if (TLS_MUST_TRUST(props->tls_level)
-       && (props->tls_level != TLS_LEV_DANE || TLS_DANE_HASTA(props->dane)))
+      && (!TLS_DANE_BASED(props->tls_level) || TLS_DANE_HASTA(props->dane)))
        log_mask |= TLS_LOG_UNTRUSTED;
 
     if (log_mask & TLS_LOG_VERBOSE)
@@ -849,8 +849,8 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
                 props->namaddr, props->protocols);
        return (0);
     }
-    /* The DANE level requires SSLv3 or later, not SSLv2. */
-    if (props->tls_level == TLS_LEV_DANE)
+    /* DANE requires SSLv3 or later, not SSLv2. */
+    if (TLS_DANE_BASED(props->tls_level))
        protomask |= TLS_PROTOCOL_SSLv2;
 
     /*
@@ -945,7 +945,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
        }
     }
 #ifdef TLSEXT_MAXLEN_host_name
-    if (props->tls_level == TLS_LEV_DANE
+    if (TLS_DANE_BASED(props->tls_level)
        && strlen(props->host) <= TLSEXT_MAXLEN_host_name) {
 
        /*
index abd5ff7d42f6b35acc9809ac38424c99a6dd4363..a03e3cc1e74397736167ff44b4c3d53851f8373d 100644 (file)
@@ -227,7 +227,7 @@ char   *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask,
 #if 0
        digest_dane(props->dane, ee);           /* See above */
 #endif
-       digest_string(props->tls_level == TLS_LEV_DANE ? props->host : "");
+       digest_string(TLS_DANE_BASED(props->tls_level) ? props->host : "");
     }
     checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
     EVP_MD_CTX_destroy(mdctx);