On Wed, Jan 14, 2015 at 06:08:16PM -0500, Wietse Venema wrote:

> I have prelimiary code almost working with little code.

You likely did not patch posttls-finger(1).  Patch below my signature,
sample output:

    $ ./bin/posttls-finger -F ~/capath/bundle.pem -cw -lsecure 
"[smtp.ntlworld.com]:465"
    posttls-finger: smtp.ntlworld.com[62.254.26.221]:465: Matched 
subjectAltName: smtp.ntlworld.com
    posttls-finger: smtp.ntlworld.com[62.254.26.221]:465 CommonName 
smtp.ntlworld.com
    posttls-finger: smtp.ntlworld.com[62.254.26.221]:465: 
subject_CN=smtp.ntlworld.com, issuer_CN=VeriSign Class 3 Secure Server CA - G3, 
fingerprint=C7:05:F7:92:FB:51:FB:A6:4A:BB:42:C3:92:83:A2:E4:85:11:86:96, 
pkey_fingerprint=88:FD:3B:85:89:8A:4F:60:01:01:2E:91:EB:11:20:BB:F3:4C:E8:8F
    posttls-finger: Verified TLS connection established to 
smtp.ntlworld.com[62.254.26.221]:465: TLSv1.1 with cipher RC4-SHA (128/128 bits)

I guess this site's administrators really liked the 1990's, SMTPS
with RC4-SHA forever! :-)

-- 
        Viktor.

diff --git a/src/posttls-finger/posttls-finger.c 
b/src/posttls-finger/posttls-finger.c
index ac4bc87..6841f90 100644
--- a/src/posttls-finger/posttls-finger.c
+++ b/src/posttls-finger/posttls-finger.c
@@ -228,6 +228,12 @@
 /* .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,34 @@ 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,25 +682,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");
+    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");
 
-    resp = response(state, state->pass == 1);
-    if (resp->code / 100 != 2) {
-       msg_info("STARTTLS rejected: %d %s", resp->code, resp->str);
-       return (1);
-    }
+       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);
+       /*
+        * 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 { \
@@ -718,6 +755,10 @@ 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 +784,28 @@ 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
@@ -1531,7 +1558,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 +1621,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 +1631,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 +1720,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
        }
     }

Reply via email to