]> diplodocus.org Git - nmh/commitdiff
Add basic support for the STLS command in POP
authorKen Hornstein <kenh@pobox.com>
Mon, 22 Apr 2019 23:46:17 +0000 (19:46 -0400)
committerKen Hornstein <kenh@pobox.com>
Mon, 22 Apr 2019 23:46:17 +0000 (19:46 -0400)
Add support for the STLS command in POP (sometimes called STARTTLS).
Functionality not yet complete.

uip/inc.c
uip/popsbr.c
uip/popsbr.h

index fecef370c96cafb80eb791e29fe3e5a46c5dd3a3..dc49337d25dfc7371be1059493d0d8f7fdae5b50 100644 (file)
--- a/uip/inc.c
+++ b/uip/inc.c
@@ -96,6 +96,7 @@
     X("sasl", 0, SASLSW) \
     X("nosasl", 0, NOSASLSW) \
     X("saslmech", 0, SASLMECHSW) \
+    X("tls", TLSminc(-3), TLSSW) \
     X("initialtls", TLSminc(-10), INITTLSSW) \
     X("notls", TLSminc(-5), NOTLSSW) \
     X("certverify", TLSminc(-10), CERTVERSW) \
@@ -205,7 +206,8 @@ main (int argc, char **argv)
     int width = -1;
     int hghnum = 0, msgnum = 0;
     FILE *pf = NULL;
-    bool sasl, tls, noverify;
+    bool sasl, noverify;
+    int tls = 0;
     int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */
     char *cp, *maildir = NULL, *folder = NULL;
     char *format = NULL, *form = NULL;
@@ -368,12 +370,16 @@ main (int argc, char **argv)
                    die("missing argument to %s", argp[-2]);
                continue;
 
+           case TLSSW:
+               tls = 1;
+               continue;
+
            case INITTLSSW:
-                tls = true;
+                tls = 2;
                continue;
 
            case NOTLSSW:
-                tls = false;
+                tls = 0;
                continue;
 
            case CERTVERSW:
@@ -434,8 +440,10 @@ main (int argc, char **argv)
            }
        }
 
-       if (tls)
-           tlsflag |= P_INITTLS;
+       if (tls == 1)
+           tlsflag = P_STARTTLS;
+       else if (tls == 2)
+           tlsflag = P_INITTLS;
 
        if (noverify)
            tlsflag |= P_NOVERIFY;
index 9ccf6dcc749238e603366c54f05d28e9c46ad25e..237e80cc4b562ec6d2641e4485ca05780a294989 100644 (file)
@@ -80,6 +80,58 @@ check_mech(char *server_mechs, size_t server_mechs_size)
     return OK;
 }
 
+/*
+ * If capable, issue the STLS command and start the TLS negotiation
+ */
+
+static int
+pop_start_tls(void)
+{
+    int status;
+    bool stls = false;
+    char *errstr;
+
+    /*
+     * Issue the CAPA command and see if we have the STLS capability
+     */
+
+    if (command("CAPA") == NOTOK) {
+       snprintf(response, sizeof(response),
+                "The POP CAPA command failed; POP server does not "
+                "support STLS");
+       return NOTOK;
+    }
+
+    while ((status = multiline()) != DONE) {
+        if (status == NOTOK)
+           return NOTOK;
+
+       if (strcasecmp(response, "STLS") == 0)
+           stls = true;
+    }
+
+    if (!stls) {
+       snprintf(response, sizeof(response), "POP server does not support "
+                "STLS");
+       return NOTOK;
+    }
+
+    /*
+     * Issue STLS and then start the actual TLS negotiation
+     */
+
+    if (command("STLS") == NOTOK)
+       return NOTOK;
+
+    if (netsec_negotiate_tls(nsc, &errstr) != OK) {
+       snprintf(response, sizeof(response), "%s", errstr);
+       free(errstr);
+       return NOTOK;
+    }
+
+    return OK;
+}
+
 /*
  * Split string containing proxy command into an array of arguments
  * suitable for passing to exec. Returned array must be freed. Shouldn't
@@ -211,17 +263,19 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop,
     netsec_set_fd(nsc, fd1, fd2);
     netsec_set_snoop(nsc, snoop);
 
-    if (tls & P_INITTLS) {
+    if (tls & P_TLSENABLEMASK) {
        if (netsec_set_tls(nsc, 1, tls & P_NOVERIFY, &errstr) != OK) {
            snprintf(response, sizeof(response), "%s", errstr);
            free(errstr);
            return NOTOK;
        }
 
-       if (netsec_negotiate_tls(nsc, &errstr) != OK) {
-           snprintf(response, sizeof(response), "%s", errstr);
-           free(errstr);
-           return NOTOK;
+       if (tls & P_INITTLS) {
+           if (netsec_negotiate_tls(nsc, &errstr) != OK) {
+               snprintf(response, sizeof(response), "%s", errstr);
+               free(errstr);
+               return NOTOK;
+           }
        }
     }
 
@@ -241,6 +295,10 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop,
            if (*response == '+') {
                 nmh_creds_t creds;
 
+               if (tls & P_STARTTLS)
+                   if (pop_start_tls() != OK)
+                       return NOTOK;
+
                if (sasl) {
                    char server_mechs[256];
                    if (check_mech(server_mechs, sizeof(server_mechs)) != OK)
index 36ba404ef5e28f23aaab34b6be086731e55561b9..3e70fe7572c0a160c1841021c4af0649a2408215 100644 (file)
@@ -5,8 +5,10 @@
  * complete copyright information. */
 
 /* TLS flags */
-#define P_INITTLS 0x01
-#define P_NOVERIFY 0x02
+#define P_STARTTLS 0x01
+#define P_INITTLS 0x02
+#define P_TLSENABLEMASK 0x03
+#define P_NOVERIFY 0x04
 
 int pop_init(char *, char *, char *, char *, int, int, char *, int, const char *);
 int pop_stat(int *, int *);