Refactor the code that handles the client requests

The functions that send the client requests to the server have been
simplified, as a layer of abstraction has been removed.
This commit is contained in:
Lefteris Chatzimparmpas 2012-02-12 21:57:18 +01:00
parent 2c70382775
commit df1e0c172b
9 changed files with 335 additions and 745 deletions

View File

@ -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

View File

@ -2,7 +2,6 @@
#include <string.h>
#include "imapfilter.h"
#include "session.h"
#ifndef NO_CRAMMD5
#include <openssl/hmac.h>
@ -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 */

View File

@ -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;
}

View File

@ -1,485 +0,0 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#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"));
}

View File

@ -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);
}

View File

@ -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);

View File

@ -1,6 +1,8 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#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;
}

View File

@ -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;
}

View File

@ -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();