diff --git a/src/Makefile b/src/Makefile index c754aca..5a283c5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,8 +15,8 @@ LUA = common.lua set.lua regex.lua account.lua mailbox.lua message.lua \ options.lua auxiliary.lua deprecated.lua BIN = imapfilter -OBJ = auth.o buffer.o cert.o core.o file.o imap.o imapfilter.o list.o log.o \ - lua.o memory.o misc.o namespace.o pcre.o regexp.o request.o response.o \ +OBJ = auth.o buffer.o cert.o core.o file.o imapfilter.o list.o log.o lua.o \ + memory.o misc.o namespace.o pcre.o regexp.o request.o response.o \ session.o signal.o socket.o system.o all: $(BIN) @@ -29,11 +29,9 @@ $(BIN): $(OBJ) $(CC) -o $(BIN) $(LDFLAGS) $(OBJ) $(LIBS) $(OBJ): imapfilter.h -auth.o: session.h buffer.o: buffer.h cert.o: pathnames.h session.h file.o: pathnames.h -imap.o: buffer.h session.h imapfilter.o: buffer.h list.h pathnames.h regexp.h session.h version.h list.o: list.h log.o: list.h pathnames.h session.h diff --git a/src/auth.c b/src/auth.c index e2c8775..ce2b1e8 100644 --- a/src/auth.c +++ b/src/auth.c @@ -2,7 +2,6 @@ #include #include "imapfilter.h" -#include "session.h" #ifndef NO_CRAMMD5 #include @@ -14,60 +13,49 @@ * Mechanism (CRAM). The authentication type associated with CRAM is * "CRAM-MD5". */ -int -auth_cram_md5(session *ssn, const char *user, const char *pass) +unsigned char * +auth_cram_md5(const char *user, const char *pass, unsigned char *chal) { - int t; size_t n; unsigned int i; - unsigned char *chal, *resp, *out, *buf; + unsigned char *resp, *buf, *out; unsigned char md[EVP_MAX_MD_SIZE], mdhex[EVP_MAX_MD_SIZE * 2 + 1]; unsigned int mdlen; HMAC_CTX hmac; - if ((t = imap_authenticate(ssn, "CRAM-MD5")) == -1) - return -1; + n = strlen((char *)(chal)) * 3 / 4 + 1; + resp = (unsigned char *)xmalloc(n * sizeof(char)); + memset(resp, 0, n); - if (response_authenticate(ssn, t, &chal) == - STATUS_RESPONSE_CONTINUE) { - n = strlen((char *)(chal)) * 3 / 4 + 1; - resp = (unsigned char *)xmalloc(n * sizeof(char)); - memset(resp, 0, n); + EVP_DecodeBlock(resp, chal, strlen((char *)(chal))); - EVP_DecodeBlock(resp, chal, strlen((char *)(chal))); + HMAC_Init(&hmac, (const unsigned char *)pass, strlen(pass), + EVP_md5()); + HMAC_Update(&hmac, resp, strlen((char *)(resp))); + HMAC_Final(&hmac, md, &mdlen); - HMAC_Init(&hmac, (const unsigned char *)pass, strlen(pass), - EVP_md5()); - HMAC_Update(&hmac, resp, strlen((char *)(resp))); - HMAC_Final(&hmac, md, &mdlen); + xfree(chal); + xfree(resp); - xfree(chal); - xfree(resp); + for (i = 0; i < mdlen; i++) + snprintf((char *)(mdhex) + i * 2, mdlen * 2 - i * 2 + 1, + "%02x", md[i]); + mdhex[mdlen * 2] = '\0'; - for (i = 0; i < mdlen; i++) - snprintf((char *)(mdhex) + i * 2, mdlen * 2 - i * 2 + 1, - "%02x", md[i]); - mdhex[mdlen * 2] = '\0'; + n = strlen(user) + 1 + strlen((char *)(mdhex)) + 1; + buf = (unsigned char *)xmalloc(n * sizeof(unsigned char)); + memset(buf, 0, n); - n = strlen(user) + 1 + strlen((char *)(mdhex)) + 1; - buf = (unsigned char *)xmalloc(n * sizeof(unsigned char)); - memset(buf, 0, n); + snprintf((char *)(buf), n, "%s %s", user, mdhex); - snprintf((char *)(buf), n, "%s %s", user, mdhex); + n = (strlen((char *)(buf)) + 3) * 4 / 3 + 1; + out = (unsigned char *)xmalloc(n * sizeof(unsigned char)); + memset(out, 0, n); - n = (strlen((char *)(buf)) + 3) * 4 / 3 + 1; - out = (unsigned char *)xmalloc(n * sizeof(unsigned char)); - memset(out, 0, n); + EVP_EncodeBlock(out, buf, strlen((char *)(buf))); - EVP_EncodeBlock(out, buf, strlen((char *)(buf))); + xfree(buf); - imap_continuation(ssn, (char *)(out), strlen((char *)(out))); - - xfree(buf); - xfree(out); - } else - return -1; - - return response_generic(ssn, t); + return out; } #endif /* NO_CRAMMD5 */ diff --git a/src/core.c b/src/core.c index 80831ca..cf7f361 100644 --- a/src/core.c +++ b/src/core.c @@ -110,7 +110,7 @@ ifcore_noop(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -145,8 +145,8 @@ ifcore_login(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK || - r == STATUS_RESPONSE_PREAUTH)); + lua_pushboolean(lua, (r == STATUS_OK || + r == STATUS_PREAUTH)); return 1; } @@ -179,7 +179,7 @@ ifcore_logout(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -219,7 +219,7 @@ ifcore_status(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); lua_pushnumber(lua, (lua_Number) (exists)); lua_pushnumber(lua, (lua_Number) (recent)); lua_pushnumber(lua, (lua_Number) (unseen)); @@ -259,7 +259,7 @@ ifcore_select(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -292,7 +292,7 @@ ifcore_close(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -325,7 +325,7 @@ ifcore_expunge(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -366,7 +366,7 @@ ifcore_list(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!mboxs && !folders) return 1; @@ -416,7 +416,7 @@ ifcore_lsub(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!mboxs) return 1; @@ -462,7 +462,7 @@ ifcore_search(lua_State *lua) lua_pop(lua, 3); - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!mesgs) return 1; @@ -509,7 +509,7 @@ ifcore_fetchfast(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!flags || !date || !size) return 1; @@ -559,7 +559,7 @@ ifcore_fetchflags(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!flags) return 1; @@ -605,7 +605,7 @@ ifcore_fetchdate(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!date) return 1; @@ -648,7 +648,7 @@ ifcore_fetchsize(lua_State *lua) lua_pop(lua, 2); - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!size) return 1; @@ -694,7 +694,7 @@ ifcore_fetchstructure(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!structure) return 1; @@ -740,7 +740,7 @@ ifcore_fetchheader(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!header) return 1; @@ -786,7 +786,7 @@ ifcore_fetchtext(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!text) return 1; @@ -834,7 +834,7 @@ ifcore_fetchfields(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!fields) return 1; @@ -882,7 +882,7 @@ ifcore_fetchpart(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); if (!part) return 1; @@ -926,7 +926,7 @@ ifcore_store(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -963,7 +963,7 @@ ifcore_copy(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1012,7 +1012,7 @@ ifcore_append(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1048,7 +1048,7 @@ ifcore_create(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1084,7 +1084,7 @@ ifcore_delete(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1121,7 +1121,7 @@ ifcore_rename(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1157,7 +1157,7 @@ ifcore_subscribe(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1193,7 +1193,7 @@ ifcore_unsubscribe(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } @@ -1226,7 +1226,7 @@ ifcore_idle(lua_State *lua) if (r == -1) return 0; - lua_pushboolean(lua, (r == STATUS_RESPONSE_OK)); + lua_pushboolean(lua, (r == STATUS_OK)); return 1; } diff --git a/src/imap.c b/src/imap.c deleted file mode 100644 index 6f6a97b..0000000 --- a/src/imap.c +++ /dev/null @@ -1,485 +0,0 @@ -#include -#include -#include -#include -#include - -#include "imapfilter.h" -#include "session.h" -#include "buffer.h" - - -extern options opts; - -buffer obuf; /* Output buffer. */ - -static int tag = 0x1000; /* Every IMAP command is prefixed with a - * unique [:alnum:] string. */ - - -int send_command(session *ssn, char *cmd, char *alt); -void prepare_command(const char *fmt,...); - - -/* - * Sends to server data; a command. - */ -int -send_command(session *ssn, char *cmd, char *alt) -{ - int t = tag; - - if (ssn->socket == -1) - return -1; - - debug("sending command (%d):\n\n%s\n", ssn->socket, alt ? alt : cmd); - - verbose("C (%d): %s", ssn->socket, (alt ? alt : cmd)); - - if (socket_write(ssn, cmd, strlen(cmd)) == -1) - return -1; - - if (tag == 0xFFFF) /* Tag always between 0x1000 and 0xFFFF. */ - tag = 0x0FFF; - tag++; - - return t; -} - - -/* - * Prepares data for sending and check that the output buffer size is - * sufficient. - */ -void -prepare_command(const char *fmt,...) -{ - int n; - va_list args; - - va_start(args, fmt); - - buffer_reset(&obuf); - n = vsnprintf(obuf.data, obuf.size + 1, fmt, args); - if (n > (int)obuf.size) { - buffer_check(&obuf, n); - vsnprintf(obuf.data, obuf.size + 1, fmt, args); - } - va_end(args); -} - - -/* - * Sends a response to a command continuation request. - */ -int -imap_continuation(session *ssn, const char *cont, size_t len) -{ - - if (ssn->socket == -1) - return -1; - - - if (socket_write(ssn, cont, len) == -1 || - socket_write(ssn, "\r\n", strlen("\r\n")) == -1) - return -1; - - if (opts.debug) { - unsigned int i; - - debug("sending continuation data (%d):\n\n", ssn->socket); - - for (i = 0; i < len; i++) - debugc(cont[i]); - - debug("\r\n\n"); - - } - - return 0; -} - - -/* - * IMAP CAPABILITY: requests listing of capabilities that the server supports. - */ -int -imap_capability(session *ssn) -{ - - prepare_command("%04X CAPABILITY\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP NOOP: does nothing always succeeds. - */ -int -imap_noop(session *ssn) -{ - - prepare_command("%04X NOOP\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP LOGOUT: informs server that client is done. - */ -int -imap_logout(session *ssn) -{ - - prepare_command("%04X LOGOUT\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP STARTTLS: begins TLS negotiation. - */ -int -imap_starttls(session *ssn) -{ - - prepare_command("%04X STARTTLS\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -#ifndef NO_CRAMMD5 -/* - * IMAP AUTHENTICATE: indicates authentication mechanism and performs an - * authentication protocol exchange. - */ -int -imap_authenticate(session *ssn, const char *auth) -{ - - prepare_command("%04X AUTHENTICATE %s\r\n", tag, auth); - - return send_command(ssn, obuf.data, NULL); -} -#endif - - -/* - * IMAP LOGIN: identifies client to server. - */ -int -imap_login(session *ssn, const char *user, const char *pass) -{ - int n, r; - char c; - char *s; - - /* Command to send to server. */ - prepare_command("%04X LOGIN \"%s\" \"%s\"\r\n", tag, user, pass); - - /* Alternate command with password shrouded for safe printing. */ - n = snprintf(&c, 1, "%04X LOGIN \"%s\" *\r\n", tag, user); - s = (char *)xmalloc((n + 1) * sizeof(char)); - snprintf(s, n + 1, "%04X LOGIN \"%s\" *\r\n", tag, user); - - r = send_command(ssn, obuf.data, s); - - xfree(s); - - return r; -} - - -/* - * IMAP SELECT: accesses a mailbox in READ-WRITE mode. - */ -int -imap_select(session *ssn, const char *mbox) -{ - - prepare_command("%04X SELECT \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP EXAMINE: accesses a mailbox in READ-ONLY mode. - */ -int -imap_examine(session *ssn, const char *mbox) -{ - - prepare_command("%04X EXAMINE \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP CREATE: creates mailbox. - */ -int -imap_create(session *ssn, const char *mbox) -{ - - prepare_command("%04X CREATE \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP DELETE: deletes mailbox. - */ -int -imap_delete(session *ssn, const char *mbox) -{ - - prepare_command("%04X DELETE \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP RENAME: renames mailbox. - */ -int -imap_rename(session *ssn, char *oldmbox, char *newmbox) -{ - - prepare_command("%04X RENAME \"%s\" \"%s\"\r\n", tag, oldmbox, newmbox); - xfree(oldmbox); - xfree(newmbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP SUBSCRIBE: adds the specified mailbox name to the server's set of - * "active" or "subscribed" mailboxes. - */ -int -imap_subscribe(session *ssn, const char *mbox) -{ - - prepare_command("%04X SUBSCRIBE \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP UNSUBSCRIBE: removes the specified mailbox name to the server's set of - * "active" or "subscribed" mailboxes. - */ -int -imap_unsubscribe(session *ssn, const char *mbox) -{ - - prepare_command("%04X UNSUBSCRIBE \"%s\"\r\n", tag, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - - -/* - * IMAP LIST: returns a subset of names from the complete set of all names - * available. - */ -int -imap_list(session *ssn, const char *refer, const char *name) -{ - - prepare_command("%04X LIST \"%s\" \"%s\"\r\n", tag, refer, name); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP LSUB: returns a subset of names from the set of names that the user has - * declared as being "active" or "subscribed". - */ -int -imap_lsub(session *ssn, const char *refer, const char *name) -{ - - prepare_command("%04X LSUB \"%s\" \"%s\"\r\n", tag, refer, name); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP STATUS: requests status of the indicated mailbox. - */ -int -imap_status(session *ssn, const char *mbox, const char *items) -{ - - prepare_command("%04X STATUS \"%s\" (%s)\r\n", tag, mbox, items); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP APPEND: append message to the end of a mailbox. - */ -int -imap_append(session *ssn, const char *mbox, const char *flags, - const char *date, unsigned int size) -{ - - prepare_command("%04X APPEND \"%s\"%s%s%s%s%s%s {%d}\r\n", tag, mbox, - (flags ? " (" : ""), (flags ? flags : ""), (flags ? ")" : ""), - (date ? " \"" : ""), (date ? date : ""), (date ? "\"" : ""), size); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP CHECK: requests a checkpoint of the currently selected mailbox. - */ -int -imap_check(session *ssn) -{ - - prepare_command("%04X CHECK\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP CLOSE: deletes messages and returns to authenticated state. - */ -int -imap_close(session *ssn) -{ - - prepare_command("%04X CLOSE\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP EXPUNGE: permanently removes any messages with the \Deleted flag set. - */ -int -imap_expunge(session *ssn) -{ - - prepare_command("%04X EXPUNGE\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP SEARCH: searches the mailbox for messages that match certain criteria. - */ -int -imap_search(session *ssn, const char *charset, const char *criteria) -{ - - if (charset != NULL && *charset != '\0') - prepare_command("%04X UID SEARCH CHARSET \"%s\" %s\r\n", tag, - charset, criteria); - else - prepare_command("%04X UID SEARCH %s\r\n", tag, - criteria); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP FETCH: retrieves data associated with a message. - */ -int -imap_fetch(session *ssn, const char *mesg, const char *items) -{ - - prepare_command("%04X UID FETCH %s %s\r\n", tag, mesg, items); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP STORE: alters data associated with a message. - */ -int -imap_store(session *ssn, const char *mesg, const char *mode, - const char *flags) -{ - - prepare_command("%04X UID STORE %s %sFLAGS.SILENT (%s)\r\n", tag, - mesg, (!strncasecmp(mode, "add", 3) ? "+" : - !strncasecmp(mode, "remove", 6) ? "-" : ""), flags); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP COPY: copy messages to mailbox. - */ -int -imap_copy(session *ssn, const char *mesg, const char *mbox) -{ - - prepare_command("%04X UID COPY %s \"%s\"\r\n", tag, mesg, mbox); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP NAMESPACE: discovers the prefix and delimeter of namespaces used by the - * server for mailboxes (RFC 2342). - */ -int -imap_namespace(session *ssn) -{ - - prepare_command("%04X NAMESPACE\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP IDLE: enter the idle state and waits for mailbox updates, as specified - * in the IMAP IDLE extension (RFC 2177). - */ -int -imap_idle(session *ssn) -{ - prepare_command("%04X IDLE\r\n", tag); - - return send_command(ssn, obuf.data, NULL); -} - - -/* - * IMAP DONE: ends the idle state entered through the IMAP IDLE command - * (RFC 2177). - */ -int -imap_done(session *ssn) -{ - - return imap_continuation(ssn, "DONE", strlen("DONE")); -} diff --git a/src/imapfilter.c b/src/imapfilter.c index 78d4c37..c0e3b27 100644 --- a/src/imapfilter.c +++ b/src/imapfilter.c @@ -121,7 +121,7 @@ main(int argc, char *argv[]) s = l->data; l = l->next; - response_generic(s, imap_logout(s)); + request_logout(s->server, s->username, s->password); close_connection(s); session_destroy(s); } diff --git a/src/imapfilter.h b/src/imapfilter.h index 660a1ce..ea18b2a 100644 --- a/src/imapfilter.h +++ b/src/imapfilter.h @@ -37,17 +37,17 @@ #define CAPABILITY_IDLE 0x10 /* Status responses and response codes. */ -#define STATUS_RESPONSE_NONE 0 -#define STATUS_RESPONSE_OK 1 -#define STATUS_RESPONSE_NO 2 -#define STATUS_RESPONSE_BAD 3 -#define STATUS_RESPONSE_UNTAGGED 4 -#define STATUS_RESPONSE_CONTINUE 5 -#define STATUS_RESPONSE_BYE 6 -#define STATUS_RESPONSE_PREAUTH 7 -#define STATUS_RESPONSE_READONLY 8 -#define STATUS_RESPONSE_TRYCREATE 9 -#define STATUS_RESPONSE_TIMEOUT 10 +#define STATUS_NONE 0 +#define STATUS_OK 1 +#define STATUS_NO 2 +#define STATUS_BAD 3 +#define STATUS_UNTAGGED 4 +#define STATUS_CONTINUE 5 +#define STATUS_BYE 6 +#define STATUS_PREAUTH 7 +#define STATUS_READONLY 8 +#define STATUS_TRYCREATE 9 +#define STATUS_TIMEOUT 10 /* Initial buffer size for input, output and namespace buffers. */ #define INPUT_BUF 4096 @@ -80,7 +80,8 @@ typedef struct environment { /* auth.c */ #ifndef NO_CRAMMD5 -int auth_cram_md5(session *ssn, const char *user, const char *pass); +unsigned char *auth_cram_md5(const char *user, const char *pass, + unsigned char *chal); #endif /* cert.c */ @@ -99,40 +100,6 @@ int create_file(char *fname, mode_t mode); int get_pathmax(void); char *get_filepath(char *fname); -/* imap.c */ -int imap_continuation(session *ssn, const char *cont, size_t len); -int imap_capability(session *ssn); -int imap_noop(session *ssn); -int imap_logout(session *ssn); -#ifndef NO_SSLTLS -int imap_starttls(session *ssn); -#endif -int imap_authenticate(session *ssn, const char *auth); -int imap_login(session *ssn, const char *user, const char *pass); -int imap_select(session *ssn, const char *mbox); -int imap_examine(session *ssn, const char *mbox); -int imap_create(session *ssn, const char *mbox); -int imap_delete(session *ssn, const char *mbox); -int imap_rename(session *ssn, char *oldmbox, char *newmbox); -int imap_subscribe(session *ssn, const char *mbox); -int imap_unsubscribe(session *ssn, const char *mbox); -int imap_list(session *ssn, const char *refer, const char *name); -int imap_lsub(session *ssn, const char *refer, const char *name); -int imap_status(session *ssn, const char *mbox, const char *items); -int imap_append(session *ssn, const char *mbox, const char *flags, - const char *date, unsigned int size); -int imap_check(session *ssn); -int imap_close(session *ssn); -int imap_expunge(session *ssn); -int imap_search(session *ssn, const char *charset, const char *criteria); -int imap_fetch(session *ssn, const char *mesg, const char *items); -int imap_store(session *ssn, const char *mesg, const char *mode, - const char *flags); -int imap_copy(session *ssn, const char *mesg, const char *mbox); -int imap_namespace(session *ssn); -int imap_idle(session *ssn); -int imap_done(session *ssn); - /* log.c */ void verbose(const char *info,...); void debug(const char *debug,...); @@ -236,7 +203,6 @@ int request_unsubscribe(const char *server, const char *port, const char *user, const char *mbox); int request_idle(const char *server, const char *port, const char *user); - /* response.c */ int response_generic(session *ssn, int tag); int response_continuation(session *ssn); diff --git a/src/request.c b/src/request.c index 1e244d4..ae0d252 100644 --- a/src/request.c +++ b/src/request.c @@ -1,6 +1,8 @@ #include +#include #include #include +#include #include "imapfilter.h" #include "session.h" @@ -9,6 +11,15 @@ extern options opts; +buffer obuf; /* Output buffer. */ + +static int tag = 0x1000; /* Every IMAP command is prefixed with a + * unique [:alnum:] string. */ + + +int send_request(session *s, const char *fmt,...); +int send_continuation(session *s, const char *data, size_t len); + #define TRY(F) \ switch ((F)) { \ @@ -22,12 +33,86 @@ extern options opts; else \ return -1; \ break; \ - case STATUS_RESPONSE_BYE: \ + case STATUS_BYE: \ close_connection(s); \ session_destroy(s); \ return -1; \ break; \ + } \ + + +/* + * Sends to server data; a command. + */ +int +send_request(session *s, const char *fmt,...) +{ + int n; + va_list args; + int t = tag; + + if (s->socket == -1) + return -1; + + buffer_reset(&obuf); + obuf.len = snprintf(obuf.data, obuf.size + 1, "%04X ", tag); + + va_start(args, fmt); + n = vsnprintf(obuf.data + obuf.len, obuf.size - obuf.len - + strlen("\r\n") + 1, fmt, args); + if (n > (int)obuf.size) { + buffer_check(&obuf, n); + vsnprintf(obuf.data + obuf.len, obuf.size - obuf.len - + strlen("\r\n") + 1, fmt, args); } + obuf.len = strlen(obuf.data); + va_end(args); + + snprintf(obuf.data + obuf.len, obuf.size - obuf.len + 1, "\r\n"); + obuf.len = strlen(obuf.data); + + debug("sending command (%d):\n\n%s\n", s->socket, obuf.data); + + verbose("C (%d): %s", s->socket, obuf.data); + + if (socket_write(s, obuf.data, obuf.len) == -1) + return -1; + + if (tag == 0xFFFF) /* Tag always between 0x1000 and 0xFFFF. */ + tag = 0x0FFF; + tag++; + + return t; +} + +/* + * Sends a response to a command continuation request. + */ +int +send_continuation(session *s, const char *data, size_t len) +{ + + if (s->socket == -1) + return -1; + + if (socket_write(s, data, len) == -1 || + socket_write(s, "\r\n", strlen("\r\n")) == -1) + return -1; + + if (opts.debug) { + unsigned int i; + + debug("sending continuation data (%d):\n\n", s->socket); + + for (i = 0; i < len; i++) + debugc(data[i]); + + debug("\r\n\n"); + + } + + return 0; +} /* @@ -42,7 +127,7 @@ request_noop(const char *server, const char *port, const char *user) if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_noop(s)); + TRY(t = send_request(s, "NOOP")); TRY(r = response_generic(s, t)); return r; @@ -57,11 +142,11 @@ int request_login(const char *server, const char *port, const char *ssl, const char *user, const char *pass) { - int r = -1, rg = -1; + int t, r = -1, rg = -1; session *s = NULL; if ((s = session_find(server, port, user)) && s->socket != -1) - return STATUS_RESPONSE_NONE; + return STATUS_NONE; if (!s) { s = session_new(); @@ -83,60 +168,87 @@ request_login(const char *server, const char *port, const char *ssl, if ((rg = response_greeting(s)) == -1) goto fail; - if (opts.debug) - if (response_generic(s, imap_noop(s)) == -1) + if (opts.debug) { + t = send_request(s, "NOOP"); + if (response_generic(s, t) == -1) goto fail; + } - if (response_capability(s, imap_capability(s)) == -1) + t = send_request(s, "CAPABILITY"); + if (response_capability(s, t) == -1) goto fail; #ifndef NO_SSLTLS if (!ssl && s->capabilities & CAPABILITY_STARTTLS && - get_option_boolean("starttls")) - switch (response_generic(s, imap_starttls(s))) { - case STATUS_RESPONSE_OK: + get_option_boolean("starttls")) { + t = send_request(s, "STARTTLS"); + switch (response_generic(s, t)) { + case STATUS_OK: if (open_secure_connection(s) == -1) goto fail; - if (response_capability(s, imap_capability(s)) == -1) + t = send_request(s, "CAPABILITY"); + if (response_capability(s, t) == -1) goto fail; break; case -1: goto fail; break; } + } #endif - if (rg != STATUS_RESPONSE_PREAUTH) { + if (rg != STATUS_PREAUTH) { #ifndef NO_CRAMMD5 if (s->capabilities & CAPABILITY_CRAMMD5 && - get_option_boolean("crammd5")) - if ((r = auth_cram_md5(s, user, pass)) == -1) + get_option_boolean("crammd5")) { + unsigned char *in, *out; + if ((t = send_request(s, "AUTHENTICATE CRAM-MD5")) + == -1) goto fail; + if (response_authenticate(s, t, &in) == + STATUS_CONTINUE) { + if ((out = auth_cram_md5(user, pass, in)) == NULL) + goto fail; + send_continuation(s, (char *)(out), + strlen((char *)(out))); + xfree(out); + if ((r = response_generic(s, t)) == -1) + goto fail; + } else + goto fail; + } #endif - if (r != STATUS_RESPONSE_OK && - (r = response_generic(s, imap_login(s, user, pass))) == -1) - goto fail; + if (r != STATUS_OK) { + t = send_request(s, "LOGIN \"%s\" \"%s\"", user, pass); + if ((r = response_generic(s, t)) == -1) + goto fail; + } - if (r == STATUS_RESPONSE_NO) { + if (r == STATUS_NO) { error("username %s or password rejected at %s\n", user, server); goto fail; } } else { - r = STATUS_RESPONSE_PREAUTH; + r = STATUS_PREAUTH; } - if (response_capability(s, imap_capability(s)) == -1) + t = send_request(s, "CAPABILITY"); + if (response_capability(s, t) == -1) goto fail; if (s->capabilities & CAPABILITY_NAMESPACE && - get_option_boolean("namespace")) - if (response_namespace(s, imap_namespace(s)) == -1) + get_option_boolean("namespace")) { + t = send_request(s, "NAMESPACE"); + if (response_namespace(s, t) == -1) goto fail; + } - if (s->selected) - if (response_select(s, imap_select(s, s->selected)) == -1) + if (s->selected) { + t = send_request(s, "SELECT \"%s\"", s->selected); + if (response_select(s, t) == -1) goto fail; + } return r; fail: @@ -153,13 +265,14 @@ fail: int request_logout(const char *server, const char *port, const char *user) { - int r; + int t, r; session *s; if (!(s = session_find(server, port, user))) return -1; - r = response_generic(s, imap_logout(s)); + t = send_request(s, "LOGOUT"); + r = response_generic(s, t); close_connection(s); session_destroy(s); @@ -186,10 +299,11 @@ request_status(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); if (s->protocol == PROTOCOL_IMAP4REV1) { - TRY(t = imap_status(s, m, "MESSAGES RECENT UNSEEN UIDNEXT")); + TRY(t = send_request(s, + "STATUS \"%s\" (MESSAGES RECENT UNSEEN UIDNEXT)", m)); TRY(r = response_status(s, t, exists, recent, unseen, uidnext)); } else { - TRY(t = imap_examine(s, m)); + TRY(t = send_request(s, "EXAMINE \"%s\"", m)); TRY(r = response_examine(s, t, exists, recent)); } @@ -213,10 +327,10 @@ request_select(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); - TRY(t = imap_select(s, m)); + TRY(t = send_request(s, "SELECT \"%s\"", m)); TRY(r = response_select(s, t)); - if (r == STATUS_RESPONSE_OK) { + if (r == STATUS_OK) { if (s && s->selected) xfree(s->selected); s->selected = xstrdup(m); @@ -238,10 +352,10 @@ request_close(const char *server, const char *port, const char *user) if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_close(s)); + TRY(t = send_request(s, "CLOSE")); TRY(r = response_generic(s, t)); - if (r == STATUS_RESPONSE_OK && s->selected) { + if (r == STATUS_OK && s->selected) { xfree(s->selected); s->selected = NULL; } @@ -262,7 +376,7 @@ request_expunge(const char *server, const char *port, const char *user) if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_expunge(s)); + TRY(t = send_request(s, "EXPUNGE")); TRY(r = response_generic(s, t)); return r; @@ -285,7 +399,7 @@ request_list(const char *server, const char *port, const char *user, n = apply_namespace(name, s->ns.prefix, s->ns.delim); - TRY(t = imap_list(s, refer, n)); + TRY(t = send_request(s, "LIST \"%s\" \"%s\"", refer, n)); TRY(r = response_list(s, t, mboxs, folders)); return r; @@ -308,7 +422,7 @@ request_lsub(const char *server, const char *port, const char *user, n = apply_namespace(name, s->ns.prefix, s->ns.delim); - TRY(t = imap_lsub(s, refer, n)); + TRY(t = send_request(s, "LSUB \"%s\" \"%s\"", refer, n)); TRY(r = response_list(s, t, mboxs, folders)); return r; @@ -328,7 +442,12 @@ request_search(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_search(s, charset, criteria)); + if (charset != NULL && *charset != '\0') { + TRY(t = send_request(s, "UID SEARCH CHARSET \"%s\" %s", charset, + criteria)); + } else { + TRY(t = send_request(s, "UID SEARCH %s", criteria)); + } TRY(r = response_search(s, t, mesgs)); return r; @@ -348,7 +467,7 @@ request_fetchfast(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "FAST")); + TRY(t = send_request(s, "UID FETCH %s FAST", mesg)); TRY(r = response_fetchfast(s, t, flags, date, size)); return r; @@ -368,7 +487,7 @@ request_fetchflags(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "FLAGS")); + TRY(t = send_request(s, "UID FETCH %s FLAGS", mesg)); TRY(r = response_fetchflags(s, t, flags)); return r; @@ -388,7 +507,7 @@ request_fetchdate(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "INTERNALDATE")); + TRY(t = send_request(s, "UID FETCH %s INTERNALDATE", mesg)); TRY(r = response_fetchdate(s, t, date)); return r; @@ -406,7 +525,7 @@ request_fetchsize(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "RFC822.SIZE")); + TRY(t = send_request(s, "UID FETCH %s RFC822.SIZE", mesg)); TRY(r = response_fetchsize(s, t, size)); return r; @@ -426,7 +545,7 @@ request_fetchstructure(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "BODYSTRUCTURE")); + TRY(t = send_request(s, "UID FETCH %s BODYSTRUCTURE", mesg)); TRY(r = response_fetchstructure(s, t, structure)); return r; @@ -446,7 +565,7 @@ request_fetchheader(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "BODY.PEEK[HEADER]")); + TRY(t = send_request(s, "UID FETCH %s BODY.PEEK[HEADER]", mesg)); TRY(r = response_fetchbody(s, t, header, len)); return r; @@ -466,7 +585,7 @@ request_fetchtext(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_fetch(s, mesg, "BODY.PEEK[TEXT]")); + TRY(t = send_request(s, "UID FETCH %s BODY.PEEK[TEXT]", mesg)); TRY(r = response_fetchbody(s, t, text, len)); return r; @@ -494,7 +613,7 @@ request_fetchfields(const char *server, const char *port, const char *user, snprintf(f, n, "%s%s%s", "BODY.PEEK[HEADER.FIELDS (", headerfields, ")]"); - TRY(t = imap_fetch(s, mesg, f)); + TRY(t = send_request(s, "UID FETCH %s %s", mesg, f)); } TRY(r = response_fetchbody(s, t, fields, len)); @@ -521,7 +640,7 @@ request_fetchpart(const char *server, const char *port, const char *user, char f[n]; snprintf(f, n, "%s%s%s", "BODY.PEEK[", part, "]"); - TRY(t = imap_fetch(s, mesg, f)); + TRY(t = send_request(s, "UID FETCH %s %s", mesg, f)); } TRY(r = response_fetchbody(s, t, bodypart, len)); @@ -542,11 +661,13 @@ request_store(const char *server, const char *port, const char *user, if (!(s = session_find(server, port, user))) return -1; - TRY(t = imap_store(s, mesg, mode, flags)); + TRY(t = send_request(s, "UID STORE %s %sFLAGS.SILENT (%s)", mesg, + (!strncasecmp(mode, "add", 3) ? "+" : + !strncasecmp(mode, "remove", 6) ? "-" : ""), flags)); TRY(r = response_generic(s, t)); if (xstrcasestr(flags, "\\Deleted") && get_option_boolean("expunge")) { - TRY(t = imap_expunge(s)); + TRY(t = send_request(s, "EXPUNGE")); TRY(response_generic(s, t)); } @@ -571,15 +692,15 @@ request_copy(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); do { - TRY(t = imap_copy(s, mesg, m)); + TRY(t = send_request(s, "UID COPY %s \"%s\"", mesg, m)); TRY(r = response_generic(s, t)); switch (r) { - case STATUS_RESPONSE_TRYCREATE: - TRY(t = imap_create(s, m)); + case STATUS_TRYCREATE: + TRY(t = send_request(s, "CREATE \"%s\"", m)); TRY(response_generic(s, t)); if (get_option_boolean("subscribe")) { - TRY(t = imap_subscribe(s, m)); + TRY(t = send_request(s, "SUBSCRIBE \"%s\"", m)); TRY(response_generic(s, t)); } break; @@ -587,7 +708,7 @@ request_copy(const char *server, const char *port, const char *user, return -1; break; } - } while (r == STATUS_RESPONSE_TRYCREATE); + } while (r == STATUS_TRYCREATE); return r; } @@ -611,20 +732,23 @@ request_append(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); do { - TRY(t = imap_append(s, m, flags, date, mesglen)); + TRY(t = send_request(s, "APPEND \"%s\"%s%s%s%s%s%s {%d}", m, + (flags ? " (" : ""), (flags ? flags : ""), + (flags ? ")" : ""), (date ? " \"" : ""), + (date ? date : ""), (date ? "\"" : ""), mesglen)); TRY(r = response_continuation(s)); switch (r) { - case STATUS_RESPONSE_CONTINUE: - TRY(imap_continuation(s, mesg, mesglen)); + case STATUS_CONTINUE: + TRY(send_continuation(s, mesg, mesglen)); TRY(r = response_generic(s, t)); break; - case STATUS_RESPONSE_TRYCREATE: - TRY(t = imap_create(s, m)); + case STATUS_TRYCREATE: + TRY(t = send_request(s, "CREATE \"%s\"", m)); TRY(response_generic(s, t)); if (get_option_boolean("subscribe")) { - TRY(t = imap_subscribe(s, m)); + TRY(t = send_request(s, "SUBSCRIBE \"%s\"", m)); TRY(response_generic(s, t)); } break; @@ -632,7 +756,7 @@ request_append(const char *server, const char *port, const char *user, return -1; break; } - } while (r == STATUS_RESPONSE_TRYCREATE); + } while (r == STATUS_TRYCREATE); return r; } @@ -654,7 +778,7 @@ request_create(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); - TRY(t = imap_create(s, m)); + TRY(t = send_request(s, "CREATE \"%s\"", m)); TRY(r = response_generic(s, t)); return r; @@ -677,7 +801,7 @@ request_delete(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); - TRY(t = imap_delete(s, m)); + TRY(t = send_request(s, "DELETE \"%s\"", m)); TRY(r = response_generic(s, t)); return r; @@ -701,7 +825,7 @@ request_rename(const char *server, const char *port, const char *user, o = xstrdup(apply_namespace(oldmbox, s->ns.prefix, s->ns.delim)); n = xstrdup(apply_namespace(newmbox, s->ns.prefix, s->ns.delim)); - TRY(t = imap_rename(s, o, n)); + TRY(t = send_request(s, "RENAME \"%s\" \"%s\"", o, n)); TRY(r = response_generic(s, t)); return r; @@ -724,7 +848,7 @@ request_subscribe(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); - TRY(t = imap_subscribe(s, m)); + TRY(t = send_request(s, "SUBSCRIBE \"%s\"", m)); TRY(r = response_generic(s, t)); return r; @@ -747,7 +871,7 @@ request_unsubscribe(const char *server, const char *port, const char *user, m = apply_namespace(mbox, s->ns.prefix, s->ns.delim); - TRY(t = imap_unsubscribe(s, m)); + TRY(t = send_request(s, "UNSUBSCRIBE \"%s\"", m)); TRY(r = response_generic(s, t)); return r; @@ -763,21 +887,20 @@ request_idle(const char *server, const char *port, const char *user) if (!(s = session_find(server, port, user))) return -1; - if (!(s->capabilities & CAPABILITY_IDLE)) return -1; do { ri = 0; - TRY(t = imap_idle(s)); + TRY(t = send_request(s, "IDLE")); TRY(r = response_continuation(s)); - if (r == STATUS_RESPONSE_CONTINUE) { + if (r == STATUS_CONTINUE) { TRY(ri = response_idle(s, t)); - TRY(imap_done(s)); + TRY(send_continuation(s, "DONE", strlen("DONE"))); TRY(r = response_generic(s, t)); } - } while (ri == STATUS_RESPONSE_TIMEOUT); + } while (ri == STATUS_TIMEOUT); return r; } diff --git a/src/response.c b/src/response.c index cbc3da6..d411412 100644 --- a/src/response.c +++ b/src/response.c @@ -16,26 +16,26 @@ extern options opts; buffer ibuf; /* Input buffer. */ enum { /* Server data responses to be parsed; * regular expressions index. */ - DATA_RESPONSE_TAGGED, - DATA_RESPONSE_CAPABILITY, - DATA_RESPONSE_AUTHENTICATE, - DATA_RESPONSE_NAMESPACE, - DATA_RESPONSE_STATUS, - DATA_RESPONSE_STATUS_MESSAGES, - DATA_RESPONSE_STATUS_RECENT, - DATA_RESPONSE_STATUS_UNSEEN, - DATA_RESPONSE_STATUS_UIDNEXT, - DATA_RESPONSE_EXAMINE_EXISTS, - DATA_RESPONSE_EXAMINE_RECENT, - DATA_RESPONSE_LIST, - DATA_RESPONSE_SEARCH, - DATA_RESPONSE_FETCH, - DATA_RESPONSE_FETCH_FLAGS, - DATA_RESPONSE_FETCH_DATE, - DATA_RESPONSE_FETCH_SIZE, - DATA_RESPONSE_FETCH_STRUCTURE, - DATA_RESPONSE_FETCH_BODY, - DATA_RESPONSE_IDLE, + RESPONSE_TAGGED, + RESPONSE_CAPABILITY, + RESPONSE_AUTHENTICATE, + RESPONSE_NAMESPACE, + RESPONSE_STATUS, + RESPONSE_STATUS_MESSAGES, + RESPONSE_STATUS_RECENT, + RESPONSE_STATUS_UNSEEN, + RESPONSE_STATUS_UIDNEXT, + RESPONSE_EXAMINE_EXISTS, + RESPONSE_EXAMINE_RECENT, + RESPONSE_LIST, + RESPONSE_SEARCH, + RESPONSE_FETCH, + RESPONSE_FETCH_FLAGS, + RESPONSE_FETCH_DATE, + RESPONSE_FETCH_SIZE, + RESPONSE_FETCH_STRUCTURE, + RESPONSE_FETCH_BODY, + RESPONSE_IDLE, }; regexp responses[] = { /* Server data responses to be parsed; * regular expressions patterns. */ @@ -114,31 +114,31 @@ check_tag(char *buf, session *ssn, int tag) char t[4 + 1]; regexp *re; - r = STATUS_RESPONSE_NONE; + r = STATUS_NONE; snprintf(t, sizeof(t), "%04X", tag); - re = &responses[DATA_RESPONSE_TAGGED]; + re = &responses[RESPONSE_TAGGED]; if (!regexec(re->preg, buf, re->nmatch, re->pmatch, 0)) { if (!strncasecmp(buf + re->pmatch[1].rm_so, t, strlen(t))) { if (!strncasecmp(buf + re->pmatch[2].rm_so, "OK", strlen("OK"))) - r = STATUS_RESPONSE_OK; + r = STATUS_OK; else if (!strncasecmp(buf + re->pmatch[2].rm_so, "NO", strlen("NO"))) - r = STATUS_RESPONSE_NO; + r = STATUS_NO; else if (!strncasecmp(buf + re->pmatch[2].rm_so, "BAD", strlen("BAD"))) - r = STATUS_RESPONSE_BAD; + r = STATUS_BAD; } } - if (r != STATUS_RESPONSE_NONE) + if (r != STATUS_NONE) verbose("S (%d): %s", ssn->socket, buf + re->pmatch[0].rm_so); - if (r == STATUS_RESPONSE_NO || r == STATUS_RESPONSE_BAD) + if (r == STATUS_NO || r == STATUS_BAD) error("IMAP (%d): %s", ssn->socket, buf + re->pmatch[0].rm_so); return r; @@ -224,12 +224,12 @@ response_generic(session *ssn, int tag) ibuf.len += n; if (check_bye(ibuf.data)) - return STATUS_RESPONSE_BYE; - } while ((r = check_tag(ibuf.data, ssn, tag)) == STATUS_RESPONSE_NONE); + return STATUS_BYE; + } while ((r = check_tag(ibuf.data, ssn, tag)) == STATUS_NONE); - if (r == STATUS_RESPONSE_NO && + if (r == STATUS_NO && (check_trycreate(ibuf.data) || get_option_boolean("create"))) - return STATUS_RESPONSE_TRYCREATE; + return STATUS_TRYCREATE; return r; } @@ -252,10 +252,10 @@ response_continuation(session *ssn) ibuf.len += n; if (check_bye(ibuf.data)) - return STATUS_RESPONSE_BYE; + return STATUS_BYE; } while (!check_continuation(ibuf.data)); - return STATUS_RESPONSE_CONTINUE; + return STATUS_CONTINUE; } @@ -274,12 +274,12 @@ response_greeting(session *ssn) verbose("S (%d): %s", ssn->socket, ibuf.data); if (check_bye(ibuf.data)) - return STATUS_RESPONSE_BYE; + return STATUS_BYE; if (check_preauth(ibuf.data)) - return STATUS_RESPONSE_PREAUTH; + return STATUS_PREAUTH; - return STATUS_RESPONSE_NONE; + return STATUS_NONE; } @@ -298,7 +298,7 @@ response_capability(session *ssn, int tag) ssn->protocol = PROTOCOL_NONE; - re = &responses[DATA_RESPONSE_CAPABILITY]; + re = &responses[RESPONSE_CAPABILITY]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, @@ -349,9 +349,9 @@ response_authenticate(session *ssn, int tag, unsigned char **cont) int r; regexp *re; - re = &responses[DATA_RESPONSE_AUTHENTICATE]; + re = &responses[RESPONSE_AUTHENTICATE]; - if ((r = response_continuation(ssn)) == STATUS_RESPONSE_CONTINUE && + if ((r = response_continuation(ssn)) == STATUS_CONTINUE && !regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *cont = (unsigned char *)xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -376,7 +376,7 @@ response_namespace(session *ssn, int tag) ssn->ns.prefix = NULL; ssn->ns.delim = '\0'; - re = &responses[DATA_RESPONSE_NAMESPACE]; + re = &responses[RESPONSE_NAMESPACE]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { n = re->pmatch[2].rm_eo - re->pmatch[2].rm_so; @@ -406,25 +406,25 @@ response_status(session *ssn, int tag, unsigned int *exist, if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_STATUS]; + re = &responses[RESPONSE_STATUS]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_STATUS_MESSAGES]; + re = &responses[RESPONSE_STATUS_MESSAGES]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *exist = strtol(s + re->pmatch[1].rm_so, NULL, 10); - re = &responses[DATA_RESPONSE_STATUS_RECENT]; + re = &responses[RESPONSE_STATUS_RECENT]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *recent = strtol(s + re->pmatch[1].rm_so, NULL, 10); - re = &responses[DATA_RESPONSE_STATUS_UNSEEN]; + re = &responses[RESPONSE_STATUS_UNSEEN]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *unseen = strtol(s + re->pmatch[1].rm_so, NULL, 10); - re = &responses[DATA_RESPONSE_STATUS_UIDNEXT]; + re = &responses[RESPONSE_STATUS_UIDNEXT]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *uidnext = strtol(s + re->pmatch[1].rm_so, NULL, 10); @@ -448,11 +448,11 @@ response_examine(session *ssn, int tag, unsigned int *exist, if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_EXAMINE_EXISTS]; + re = &responses[RESPONSE_EXAMINE_EXISTS]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *exist = strtol(ibuf.data + re->pmatch[1].rm_so, NULL, 10); - re = &responses[DATA_RESPONSE_EXAMINE_RECENT]; + re = &responses[RESPONSE_EXAMINE_RECENT]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) *recent = strtol(ibuf.data + re->pmatch[1].rm_so, NULL, 10); @@ -472,7 +472,7 @@ response_select(session *ssn, int tag) return -1; if (xstrcasestr(ibuf.data, "[READ-ONLY]")) - return STATUS_RESPONSE_READONLY; + return STATUS_READONLY; return r; } @@ -497,7 +497,7 @@ response_list(session *ssn, int tag, char **mboxs, char **folders) f = *folders = (char *)xmalloc((ibuf.len + 1) * sizeof(char)); *m = *f = '\0'; - re = &responses[DATA_RESPONSE_LIST]; + re = &responses[RESPONSE_LIST]; b = ibuf.data; while (!regexec(re->preg, b, re->nmatch, re->pmatch, 0)) { @@ -560,7 +560,7 @@ response_search(session *ssn, int tag, char **mesgs) if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_SEARCH]; + re = &responses[RESPONSE_SEARCH]; b = ibuf.data; m = NULL; @@ -600,22 +600,22 @@ response_fetchfast(session *ssn, int tag, char **flags, char **date, if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_FETCH]; + re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_FLAGS]; + re = &responses[RESPONSE_FETCH_FLAGS]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *flags = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_DATE]; + re = &responses[RESPONSE_FETCH_DATE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *date = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_SIZE]; + re = &responses[RESPONSE_FETCH_SIZE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *size = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -640,12 +640,12 @@ response_fetchflags(session *ssn, int tag, char **flags) if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_FETCH]; + re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_FLAGS]; + re = &responses[RESPONSE_FETCH_FLAGS]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *flags = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -671,12 +671,12 @@ response_fetchdate(session *ssn, int tag, char **date) if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_FETCH]; + re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_DATE]; + re = &responses[RESPONSE_FETCH_DATE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *date = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -702,12 +702,12 @@ response_fetchsize(session *ssn, int tag, char **size) if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_FETCH]; + re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_SIZE]; + re = &responses[RESPONSE_FETCH_SIZE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) *size = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -733,12 +733,12 @@ response_fetchstructure(session *ssn, int tag, char **structure) if ((r = response_generic(ssn, tag)) == -1) return -1; - re = &responses[DATA_RESPONSE_FETCH]; + re = &responses[RESPONSE_FETCH]; if (!regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)) { s = xstrndup(ibuf.data + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); - re = &responses[DATA_RESPONSE_FETCH_STRUCTURE]; + re = &responses[RESPONSE_FETCH_STRUCTURE]; if (!regexec(re->preg, s, re->nmatch, re->pmatch, 0)) { *structure = xstrndup(s + re->pmatch[1].rm_so, re->pmatch[1].rm_eo - re->pmatch[1].rm_so); @@ -771,7 +771,7 @@ response_fetchbody(session *ssn, int tag, char **body, size_t *len) match = -1; offset = 0; - re = &responses[DATA_RESPONSE_FETCH_BODY]; + re = &responses[RESPONSE_FETCH_BODY]; do { buffer_check(&ibuf, ibuf.len + INPUT_BUF); @@ -793,10 +793,10 @@ response_fetchbody(session *ssn, int tag, char **body, size_t *len) if (offset != 0 && ibuf.len >= offset) { if (check_bye(ibuf.data + offset)) - return STATUS_RESPONSE_BYE; + return STATUS_BYE; } } while (ibuf.len < offset || (r = check_tag(ibuf.data + offset, ssn, - tag)) == STATUS_RESPONSE_NONE); + tag)) == STATUS_NONE); if (match == 0) { if (re->pmatch[2].rm_so != -1 && @@ -823,7 +823,7 @@ response_idle(session *ssn, int tag) if (tag == -1) return -1; - re = &responses[DATA_RESPONSE_IDLE]; + re = &responses[RESPONSE_IDLE]; do { buffer_reset(&ibuf); @@ -834,16 +834,16 @@ response_idle(session *ssn, int tag) return -1; break; /* NOTREACHED */ case 0: - return STATUS_RESPONSE_TIMEOUT; + return STATUS_TIMEOUT; break; /* NOTREACHED */ } verbose("S (%d): %s", ssn->socket, ibuf.data); if (check_bye(ibuf.data)) - return STATUS_RESPONSE_BYE; + return STATUS_BYE; } while (regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0)); - return STATUS_RESPONSE_UNTAGGED; + return STATUS_UNTAGGED; } diff --git a/src/socket.c b/src/socket.c index 32d7c9e..8166483 100644 --- a/src/socket.c +++ b/src/socket.c @@ -101,8 +101,8 @@ open_secure_connection(session *ssn) method = NULL; - if (!strncasecmp(ssn->ssl, "ssl3", 4) || - !strncasecmp(ssn->ssl, "ssl2", 4)) + if (ssn->ssl && (!strncasecmp(ssn->ssl, "ssl3", 4) || + !strncasecmp(ssn->ssl, "ssl2", 4))) method = SSLv23_client_method(); else method = TLSv1_client_method();