From: Ken Hornstein Date: Tue, 23 Apr 2019 00:43:47 +0000 (-0400) Subject: Merge branch 'pop-stls' X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/ee412cbd5c0667742a128fb4e1c89801528a9a48?hp=2184c8815e03f092ceb640454ebc40fc10a1ea48 Merge branch 'pop-stls' --- diff --git a/man/inc.man b/man/inc.man index 56764a31..eb1b3911 100644 --- a/man/inc.man +++ b/man/inc.man @@ -38,6 +38,7 @@ inc \- incorporate new mail to an nmh folder .IR mechanism ] .RB [ \-authservice .IR service ] +.RB [ \-tls ] .RB [ \-initialtls ] .RB [ \-notls ] .RB [ \-certverify " | " \-nocertverify ] @@ -286,11 +287,20 @@ for more details. If .B nmh has been compiled with TLS support, the +.B \-tls +and +.B \-initialtls +switches will require the negotiation of TLS when connecting +to the remote POP server. The +.B \-tls +switch will direct +.B inc +to negotiate TLS as part of the normal POP protocol using +the STLS command. The .B \-initialtls -switch will require the negotiation of TLS when connecting -to the remote POP server. +switch will direct .B inc -will negotiate TLS immediately after the connection has taken place, +to negotiate TLS immediately after the connection has taken place, before any POP commands are sent or received. Data encrypted by TLS is labeled `(tls-encrypted)' and `(tls-decrypted)' when viewing the POP transaction with the diff --git a/man/msgchk.man b/man/msgchk.man index 84a40ca9..7669f7a1 100644 --- a/man/msgchk.man +++ b/man/msgchk.man @@ -22,6 +22,7 @@ all/mail/nomail ] .RB [ \-sasl " | " \-nosasl ] .RB [ \-saslmech .IR mechanism ] +.RB [ \-tls ] .RB [ \-initialtls ] .RB [ \-notls ] .RB [ \-certverify " | " \-nocertverify ] @@ -155,9 +156,14 @@ for more details. If .B nmh has been compiled with TLS support, the +.B \-tls +and .B \-initialtls -switch will require the negotiation of TLS when connecting +switches will require the negotiation of TLS when connecting to the remote POP server. The +.B \-tls +switch will negotiate TLS as part of the normal POP protocol using +the STLS command. The .B \-initialtls switch will negotiate TLS immediately after the connection has taken place, before any POP commands are sent or received. Data encrypted by TLS is 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/msgchk.c b/uip/msgchk.c index ca3e3826..82541ec5 100644 --- a/uip/msgchk.c +++ b/uip/msgchk.c @@ -48,6 +48,7 @@ X("nosasl", SASLminc(6), NOSASLSW) \ X("saslmech", SASLminc(5), SASLMECHSW) \ X("authservice", SASLminc(0), AUTHSERVICESW) \ + X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NOTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ @@ -89,7 +90,7 @@ main (int argc, char **argv) int notifysw = NT_ALL; int status = 0; bool sasl = false; - bool tls = false; + int tls = 0; bool noverify = false; bool snoop = false; int vecp = 0; @@ -176,12 +177,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: @@ -232,8 +237,10 @@ main (int argc, char **argv) if (host) { int tlsflag = 0; - 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 *);