X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/9a6d835cfe7761f6a85f84233d9d93722efe6ecc..9322ba2854211794c27fae9468768b80b767c211:/uip/popsbr.c diff --git a/uip/popsbr.c b/uip/popsbr.c index 71011667..ebb9b18f 100644 --- a/uip/popsbr.c +++ b/uip/popsbr.c @@ -15,10 +15,8 @@ #include #define TRM "." -#define TRMLEN (sizeof TRM - 1) static int poprint = 0; -static int pophack = 0; char response[BUFSIZ]; static netsec_context *nsc = NULL; @@ -134,8 +132,8 @@ parse_proxy(char *proxy, char *host) } int -pop_init (char *host, char *port, char *user, char *pass, char *proxy, - int snoop, int sasl, char *mech, int tls, const char *oauth_svc) +pop_init (char *host, char *port, char *user, char *proxy, int snoop, + int sasl, char *mech, int tls, const char *oauth_svc) { int fd1, fd2; char buffer[BUFSIZ]; @@ -146,13 +144,7 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, if (user) netsec_set_userid(nsc, user); - if (tls) { - if (netsec_set_tls(nsc, 1, &errstr) != OK) { - snprintf(response, sizeof(response), "%s", errstr); - free(errstr); - return NOTOK; - } - } + netsec_set_hostname(nsc, host); if (oauth_svc != NULL) { if (netsec_set_oauth_service(nsc, oauth_svc) != OK) { @@ -213,14 +205,21 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, sizeof(response), snoop)) == NOTOK) { return NOTOK; } + fd2 = fd1; } SIGNAL (SIGPIPE, SIG_IGN); - netsec_set_fd(nsc, fd1); + netsec_set_fd(nsc, fd1, fd2); netsec_set_snoop(nsc, snoop); - if (tls) { + 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; + } + if (netsec_negotiate_tls(nsc, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); @@ -229,8 +228,8 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, } 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, + &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; @@ -242,6 +241,8 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, if (poprint) fprintf (stderr, "<--- %s\n", response); if (*response == '+') { + nmh_creds_t creds; + if (sasl) { char server_mechs[256]; if (check_mech(server_mechs, sizeof(server_mechs)) != OK) @@ -254,16 +255,24 @@ pop_init (char *host, char *port, char *user, char *pass, char *proxy, return NOTOK; } return OK; - } else - if (command ("USER %s", user) != NOTOK - && command ("%s %s", (pophack++, "PASS"), - pass) != NOTOK) - return OK; + } + + if (!(creds = nmh_get_credentials(host, user))) + return NOTOK; + if (command ("USER %s", nmh_cred_get_user(creds)) + != NOTOK) { + if (command("PASS %s", nmh_cred_get_password(creds)) + != NOTOK) { + nmh_credentials_free(creds); + return OK; + } + } + nmh_credentials_free(creds); } strncpy (buffer, response, sizeof(buffer)); command ("QUIT"); strncpy (response, buffer, sizeof(response)); - /* and fall */ + /* FALLTHRU */ case NOTOK: case DONE: @@ -289,7 +298,7 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, unsigned int *outdatalen, char **errstr) { - int rc; + int rc, snoopoffset; char *mech, *line; size_t len, b64len; @@ -333,16 +342,22 @@ 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) 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) @@ -362,7 +377,10 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, * and feed it back into the SASL library. */ case NETSEC_SASL_READ: + netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); + snoopoffset = 2; line = netsec_readline(nsc, &len, errstr); + netsec_set_snoop_callback(nsc, NULL, NULL); if (line == NULL) return NOTOK; @@ -375,10 +393,12 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, *outdata = NULL; *outdatalen = 0; } else { - rc = decodeBase64(line + 2, (const char **) outdata, &len, 0, NULL); + rc = decodeBase64(line + 2, outdata, &len, 0, NULL); *outdatalen = len; - if (rc != OK) + if (rc != OK) { + netsec_err(errstr, "Unable to decode base64 response"); return NOTOK; + } } break; @@ -393,7 +413,9 @@ 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); } @@ -402,8 +424,6 @@ pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, if (netsec_flush(nsc, errstr) != OK) return NOTOK; - - return OK; break; /* @@ -415,7 +435,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; } @@ -523,7 +543,7 @@ pop_retr (int msgno, int (*action)(char *)) static int traverse (int (*action)(char *), const char *fmt, ...) { - int result; + int result, snoopstate; va_list ap; char buffer[sizeof(response)]; @@ -535,13 +555,18 @@ traverse (int (*action)(char *), const char *fmt, ...) return NOTOK; strncpy (buffer, response, sizeof(buffer)); + 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; case OK: @@ -662,15 +687,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; - else - strncpy (response, buffer + TRMLEN, sizeof(response)); + strncpy (response, buffer + LEN(TRM), sizeof(response)); } else strncpy (response, buffer, sizeof(response)); @@ -711,7 +735,7 @@ pop_getline (char *s, int n, netsec_context *ns) * someday. */ - destlen = len < ((size_t) (n - 1)) ? len : n - 1; + destlen = len < ((size_t) (n - 1)) ? len : (size_t) (n - 1); memcpy(s, p, destlen); s[destlen] = '\0';