X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/d20cac6971c9e649cc88e6533e7fa1367e488e14..1e03ea3338cc5ccd9ddf4feaaacfeda1998689cc:/uip/popsbr.c diff --git a/uip/popsbr.c b/uip/popsbr.c index 54fd24ff..02e10e6e 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -1,21 +1,23 @@ -/* - * popsbr.c -- POP client subroutines +/* popsbr.c -- POP client subroutines * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ -#include -#include -#include -#include +#include "h/mh.h" +#include "sbr/credentials.h" +#include "sbr/client.h" +#include "sbr/error.h" +#include "h/utils.h" +#include "h/oauth.h" +#include "h/netsec.h" -#include -#include +#include "h/popsbr.h" +#include "h/signals.h" +#include "sbr/base64.h" #define TRM "." -#define TRMLEN (sizeof TRM - 1) static int poprint = 0; @@ -26,20 +28,22 @@ static netsec_context *nsc = NULL; * static prototypes */ -static int command(const char *, ...); +static int command(const char *, ...) CHECK_PRINTF(1, 2); static int multiline(void); -static int traverse (int (*)(char *), const char *, ...); -static int vcommand(const char *, va_list); +static int traverse(int (*)(void *, char *), void *closure, + const char *, ...) CHECK_PRINTF(3, 4); +static int vcommand(const char *, va_list) CHECK_PRINTF(1, 0); static int pop_getline (char *, int, netsec_context *); static int pop_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, - char **); + void *, char **); static int check_mech(char *server_mechs, size_t server_mechs_size) { - int status, sasl_capability = 0; + int status; + bool sasl_capability = false; /* * First off, we're going to send the CAPA command to see if we can @@ -56,23 +60,16 @@ check_mech(char *server_mechs, size_t server_mechs_size) return NOTOK; } - while ((status = multiline()) != DONE) - switch (status) { - case NOTOK: + while ((status = multiline()) != DONE) { + if (status == NOTOK) return NOTOK; - break; - case DONE: /* Shouldn't be possible, but just in case */ - break; - case OK: - if (strncasecmp(response, "SASL ", 5) == 0) { - /* - * We've seen the SASL capability. Grab the mech list - */ - sasl_capability++; - strncpy(server_mechs, response + 5, server_mechs_size); - } - break; - } + + if (strncasecmp(response, "SASL ", 5) == 0) { + /* We've seen the SASL capability. Grab the mech list. */ + sasl_capability = true; + strncpy(server_mechs, response + 5, server_mechs_size); + } + } if (!sasl_capability) { snprintf(response, sizeof(response), "POP server does not support " @@ -115,7 +112,7 @@ parse_proxy(char *proxy, char *host) /* put together list of arguments */ p = pargv = mh_xmalloc(pargc * sizeof(char *)); - c = *pargv = mh_xmalloc(plen * sizeof(char)); + c = *pargv = mh_xmalloc(plen); for (cur = pro; *cur; cur++) { if (isspace(*cur) && cur[1] && !isspace(cur[1])) { *c++ = '\0'; @@ -145,6 +142,8 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, if (user) netsec_set_userid(nsc, user); + netsec_set_hostname(nsc, host); + if (oauth_svc != NULL) { if (netsec_set_oauth_service(nsc, oauth_svc) != OK) { snprintf(response, sizeof(response), "OAuth2 not supported"); @@ -187,7 +186,7 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, close(1); free(*argv); free(argv); - exit(10); + exit(1); } /* okay in the parent we do some stuff */ @@ -212,8 +211,8 @@ 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) { - if (netsec_set_tls(nsc, 1, &errstr) != OK) { + if (tls & P_INITTLS) { + if (netsec_set_tls(nsc, 1, tls & P_NOVERIFY, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; @@ -227,8 +226,8 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, } if (sasl) { - if (netsec_set_sasl_params(nsc, host, "pop", mech, - pop_sasl_callback, &errstr) != OK) { + if (netsec_set_sasl_params(nsc, "pop", mech, pop_sasl_callback, + NULL, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; @@ -271,13 +270,15 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, strncpy (buffer, response, sizeof(buffer)); command ("QUIT"); strncpy (response, buffer, sizeof(response)); - /* and fall */ + /* FALLTHRU */ case NOTOK: case DONE: - if (poprint) - fprintf (stderr, "%s\n", response); - netsec_shutdown(nsc, 1); + if (poprint) { + fputs(response, stderr); + putc('\n', stderr); + } + netsec_shutdown(nsc); nsc = NULL; return NOTOK; } @@ -295,11 +296,12 @@ pop_init (char *host, char *port, char *user, char *proxy, int snoop, static int pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, - unsigned int *outdatalen, char **errstr) + unsigned int *outdatalen, void *context, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len, b64len; + NMH_UNUSED(context); switch (mtype) { case NETSEC_SASL_START: @@ -341,25 +343,27 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, "for initial challenge response"); return NOTOK; } - netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); - netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); if (rc != OK) return NOTOK; - if (netsec_flush(nsc, errstr) != OK) + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); + rc = netsec_flush(nsc, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); + if (rc != OK) return NOTOK; } else { - netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, - &snoopoffset); - snoopoffset = 6 + strlen(mech); rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data); free(b64data); - netsec_set_snoop_callback(nsc, NULL, NULL); if (rc != OK) return NOTOK; - if (netsec_flush(nsc, errstr) != OK) + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, + &snoopoffset); + snoopoffset = 6 + strlen(mech); + rc = netsec_flush(nsc, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); + if (rc != OK) return NOTOK; } } else { @@ -412,16 +416,18 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, b64data); - netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); - netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); } if (rc != OK) return NOTOK; - if (netsec_flush(nsc, errstr) != OK) + if (indatalen > 0) + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); + rc = netsec_flush(nsc, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); + if (rc != OK) return NOTOK; break; @@ -434,7 +440,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, if (line == NULL) return NOTOK; - if (strncmp(line, "+OK", 3) != 0) { + if (!has_prefix(line, "+OK")) { netsec_err(errstr, "Authentication failed: %s", line); return NOTOK; } @@ -481,66 +487,14 @@ pop_stat (int *nmsgs, int *nbytes) int -pop_list (int msgno, int *nmsgs, int *msgs, int *bytes) -{ - int i; - int *ids = NULL; - - if (msgno) { - if (command ("LIST %d", msgno) == NOTOK) - return NOTOK; - *msgs = *bytes = 0; - if (ids) { - *ids = 0; - sscanf (response, "+OK %d %d %d", msgs, bytes, ids); - } - else - sscanf (response, "+OK %d %d", msgs, bytes); - return OK; - } - - if (command ("LIST") == NOTOK) - return NOTOK; - - for (i = 0; i < *nmsgs; i++) - switch (multiline ()) { - case NOTOK: - return NOTOK; - case DONE: - *nmsgs = ++i; - return OK; - case OK: - *msgs = *bytes = 0; - if (ids) { - *ids = 0; - sscanf (response, "%d %d %d", - msgs++, bytes++, ids++); - } - else - sscanf (response, "%d %d", msgs++, bytes++); - break; - } - for (;;) - switch (multiline ()) { - case NOTOK: - return NOTOK; - case DONE: - return OK; - case OK: - break; - } -} - - -int -pop_retr (int msgno, int (*action)(char *)) +pop_retr (int msgno, int (*action)(void *, char *), void *closure) { - return traverse (action, "RETR %d", msgno); + return traverse (action, closure, "RETR %d", msgno); } static int -traverse (int (*action)(char *), const char *fmt, ...) +traverse (int (*action)(void *, char *), void *closure, const char *fmt, ...) { int result, snoopstate; va_list ap; @@ -557,21 +511,21 @@ traverse (int (*action)(char *), const char *fmt, ...) if ((snoopstate = netsec_get_snoop(nsc))) netsec_set_snoop(nsc, 0); - for (;;) - switch (multiline ()) { - case NOTOK: - netsec_set_snoop(nsc, snoopstate); - return NOTOK; - - case DONE: - strncpy (response, buffer, sizeof(response)); - netsec_set_snoop(nsc, snoopstate); - return OK; + for (;;) { + result = multiline(); + if (result == OK) { + result = (*action)(closure, response); + if (result == OK) + continue; + } else if (result == DONE) { + strncpy(response, buffer, sizeof(response)); + result = OK; + } + break; + } - case OK: - (*action) (response); - break; - } + netsec_set_snoop(nsc, snoopstate); + return result; } @@ -582,27 +536,6 @@ pop_dele (int msgno) } -int -pop_noop (void) -{ - return command ("NOOP"); -} - - -int -pop_rset (void) -{ - return command ("RSET"); -} - - -int -pop_top (int msgno, int lines, int (*action)(char *)) -{ - return traverse (action, "TOP %d %d", msgno, lines); -} - - int pop_quit (void) { @@ -619,7 +552,7 @@ int pop_done (void) { if (nsc) - netsec_shutdown(nsc, 1); + netsec_shutdown(nsc); return OK; } @@ -670,12 +603,14 @@ vcommand (const char *fmt, va_list ap) case OK: if (poprint) fprintf (stderr, "<--- %s\n", response); - return (*response == '+' ? OK : NOTOK); + return *response == '+' ? OK : NOTOK; case NOTOK: case DONE: - if (poprint) - fprintf (stderr, "%s\n", response); + if (poprint) { + fputs(response, stderr); + putc('\n', stderr); + } return NOTOK; } @@ -686,14 +621,14 @@ vcommand (const char *fmt, va_list ap) int multiline (void) { - char buffer[BUFSIZ + TRMLEN]; + char buffer[BUFSIZ + LEN(TRM)]; if (pop_getline (buffer, sizeof buffer, nsc) != OK) return NOTOK; - if (strncmp (buffer, TRM, TRMLEN) == 0) { - if (buffer[TRMLEN] == 0) + if (has_prefix(buffer, TRM)) { + if (buffer[LEN(TRM)] == 0) return DONE; - strncpy (response, buffer + TRMLEN, sizeof(response)); + strncpy (response, buffer + LEN(TRM), sizeof(response)); } else strncpy (response, buffer, sizeof(response)); @@ -730,11 +665,11 @@ pop_getline (char *s, int n, netsec_context *ns) * * We get a length back from netsec_readline, but the rest of the POP * code doesn't handle it; the assumptions are that everything from - * the network can be respresented as C strings. That should get fixed + * the network can be represented as C strings. That should get fixed * someday. */ - destlen = len < ((size_t) (n - 1)) ? len : (size_t) (n - 1); + destlen = min(len, (size_t)(n - 1)); memcpy(s, p, destlen); s[destlen] = '\0';