From: Ken Hornstein Date: Mon, 22 Apr 2019 23:46:17 +0000 (-0400) Subject: Add basic support for the STLS command in POP X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/ec173fd2c897f148b4a8e4b9d81743099f1e3b50?ds=sidebyside;hp=77ce4cf16b51da4e873519978a9808bfd83febaa Add basic support for the STLS command in POP Add support for the STLS command in POP (sometimes called STARTTLS). Functionality not yet complete. --- diff --git a/uip/inc.c b/uip/inc.c index fecef370..dc49337d 100644 --- 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; diff --git a/uip/popsbr.c b/uip/popsbr.c index 9ccf6dcc..237e80cc 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -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) diff --git a/uip/popsbr.h b/uip/popsbr.h index 36ba404e..3e70fe75 100644 --- a/uip/popsbr.h +++ b/uip/popsbr.h @@ -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 *);