Browse Source

factor out imap_server

wip/server-refactor
Oswald Buddenhagen 9 years ago
parent
commit
f06691c8d9
  1. 298
      src/drv_imap.c

298
src/drv_imap.c

@ -94,22 +94,14 @@ typedef struct parse_list_state {
struct imap_cmd;
typedef struct imap_store {
store_t gen;
const char *label; /* foreign */
const char *prefix;
const char *name;
int ref_count;
enum { SST_BAD, SST_HALF, SST_GOOD } state;
/* trash folder's existence is not confirmed yet */
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
uint got_namespace:1;
char delimiter[2]; /* hierarchy delimiter */
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
message_t **msgapp; /* FETCH results */
typedef struct imap_server {
int got_namespace;
uint caps; /* CAPABILITY results */
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
string_list_t *auth_mechs;
parse_list_state_t parse_list_sts;
/* command queue */
int nexttag, num_in_progress;
struct imap_cmd *pending, **pending_append;
@ -121,17 +113,37 @@ typedef struct imap_store {
int expectBYE; /* LOGOUT is in progress */
int expectEOF; /* received LOGOUT's OK or unsolicited BYE */
int canceling; /* imap_cancel() is in progress */
union {
void (*imap_open)( int sts, void *aux );
void (*imap_cancel)( void *aux );
} callbacks;
void *callback_aux;
#ifdef HAVE_LIBSASL
sasl_conn_t *sasl;
int sasl_cont;
#endif
conn_t conn; /* this is BIG, so put it last */
} imap_server_t;
typedef struct imap_store {
store_t gen;
imap_server_t *server;
const char *label; /* foreign */
const char *prefix;
const char *name;
int ref_count;
/* XXX this doesn't really make sense in the new world:
bad: bad server
half: good server
good: good server+store
*/
enum { SST_BAD, SST_HALF, SST_GOOD } state;
/* trash folder's existence is not confirmed yet */
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
char delimiter[2]; /* hierarchy delimiter */
message_t **msgapp; /* FETCH results */
union {
void (*imap_open)( int, void *aux );
void (*imap_cancel)( void *aux );
} callbacks;
void *callback_aux;
} imap_store_t;
struct imap_cmd {
@ -189,7 +201,7 @@ struct imap_cmd_refcounted {
struct imap_cmd_refcounted_state *state;
};
#define CAP(cap) (ctx->caps & (1 << (cap)))
#define CAP(cap) (ctx->server->caps & (1 << (cap)))
enum CAPABILITY {
NOLOGIN = 0,
@ -262,7 +274,7 @@ done_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, int response )
cmd->param.done( ctx, cmd, response );
if (cmd->param.data) {
free( cmd->param.data );
ctx->buffer_mem -= cmd->param.data_len;
ctx->server->buffer_mem -= cmd->param.data_len;
}
free( cmd->cmd );
free( cmd );
@ -276,7 +288,7 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
conn_iovec_t iov[3];
char buf[1024];
cmd->tag = ++ctx->nexttag;
cmd->tag = ++ctx->server->nexttag;
if (!cmd->param.data) {
buffmt = "%d %s\r\n";
litplus = 0;
@ -290,8 +302,8 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
bufl = nfsnprintf( buf, sizeof(buf), buffmt,
cmd->tag, cmd->cmd, cmd->param.data_len );
if (DFlags & DEBUG_NET) {
if (ctx->num_in_progress)
printf( "(%d in progress) ", ctx->num_in_progress );
if (ctx->server->num_in_progress)
printf( "(%d in progress) ", ctx->server->num_in_progress );
if (starts_with( cmd->cmd, -1, "LOGIN", 5 ))
printf( "%s>>> %d LOGIN <user> <pass>\n", ctx->label, cmd->tag );
else if (starts_with( cmd->cmd, -1, "AUTHENTICATE PLAIN", 18 ))
@ -308,20 +320,20 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
iov[1].len = cmd->param.data_len;
iov[1].takeOwn = GiveOwn;
cmd->param.data = 0;
ctx->buffer_mem -= cmd->param.data_len;
ctx->server->buffer_mem -= cmd->param.data_len;
iov[2].buf = "\r\n";
iov[2].len = 2;
iov[2].takeOwn = KeepOwn;
iovcnt = 3;
}
socket_write( &ctx->conn, iov, iovcnt );
socket_write( &ctx->server->conn, iov, iovcnt );
if (cmd->param.to_trash && ctx->trashnc == TrashUnknown)
ctx->trashnc = TrashChecking;
cmd->next = 0;
*ctx->in_progress_append = cmd;
ctx->in_progress_append = &cmd->next;
ctx->num_in_progress++;
socket_expect_read( &ctx->conn, 1 );
*ctx->server->in_progress_append = cmd;
ctx->server->in_progress_append = &cmd->next;
ctx->server->num_in_progress++;
socket_expect_read( &ctx->server->conn, 1 );
}
static int
@ -329,13 +341,13 @@ cmd_sendable( imap_store_t *ctx, struct imap_cmd *cmd )
{
struct imap_cmd *cmdp;
return !ctx->conn.write_buf &&
!(ctx->in_progress &&
(cmdp = (struct imap_cmd *)((char *)ctx->in_progress_append -
return !ctx->server->conn.write_buf &&
!(ctx->server->in_progress &&
(cmdp = (struct imap_cmd *)((char *)ctx->server->in_progress_append -
offsetof(struct imap_cmd, next)), 1) &&
(cmdp->param.cont || cmdp->param.data)) &&
!(cmd->param.to_trash && ctx->trashnc == TrashChecking) &&
ctx->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress;
ctx->server->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress;
}
static void
@ -343,9 +355,9 @@ flush_imap_cmds( imap_store_t *ctx )
{
struct imap_cmd *cmd;
if ((cmd = ctx->pending) && cmd_sendable( ctx, cmd )) {
if (!(ctx->pending = cmd->next))
ctx->pending_append = &ctx->pending;
if ((cmd = ctx->server->pending) && cmd_sendable( ctx, cmd )) {
if (!(ctx->server->pending = cmd->next))
ctx->server->pending_append = &ctx->server->pending;
send_imap_cmd( ctx, cmd );
}
}
@ -355,9 +367,9 @@ cancel_pending_imap_cmds( imap_store_t *ctx )
{
struct imap_cmd *cmd;
while ((cmd = ctx->pending)) {
if (!(ctx->pending = cmd->next))
ctx->pending_append = &ctx->pending;
while ((cmd = ctx->server->pending)) {
if (!(ctx->server->pending = cmd->next))
ctx->server->pending_append = &ctx->server->pending;
done_imap_cmd( ctx, cmd, RESP_CANCEL );
}
}
@ -367,9 +379,9 @@ cancel_sent_imap_cmds( imap_store_t *ctx )
{
struct imap_cmd *cmd;
socket_expect_read( &ctx->conn, 0 );
while ((cmd = ctx->in_progress)) {
ctx->in_progress = cmd->next;
socket_expect_read( &ctx->server->conn, 0 );
while ((cmd = ctx->server->in_progress)) {
ctx->server->in_progress = cmd->next;
/* don't update num_in_progress and in_progress_append - store is dead */
done_imap_cmd( ctx, cmd, RESP_CANCEL );
}
@ -383,14 +395,14 @@ submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd )
assert( cmd );
assert( cmd->param.done );
if ((ctx->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) {
if (ctx->pending && cmd->param.high_prio) {
cmd->next = ctx->pending;
ctx->pending = cmd;
if ((ctx->server->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) {
if (ctx->server->pending && cmd->param.high_prio) {
cmd->next = ctx->server->pending;
ctx->server->pending = cmd;
} else {
cmd->next = 0;
*ctx->pending_append = cmd;
ctx->pending_append = &cmd->next;
*ctx->server->pending_append = cmd;
ctx->server->pending_append = &cmd->next;
}
} else {
send_imap_cmd( ctx, cmd );
@ -729,10 +741,10 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
s[cur->len] = 0;
getbytes:
n = socket_read( &ctx->conn, s, bytes );
n = socket_read( &ctx->server->conn, s, bytes );
if (n < 0) {
badeof:
error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name );
error( "IMAP error: unexpected EOF from %s\n", ctx->server->conn.name );
goto bail;
}
bytes -= n;
@ -747,7 +759,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
}
getline:
if (!(s = socket_read_line( &ctx->conn )))
if (!(s = socket_read_line( &ctx->server->conn )))
goto postpone;
if (s == (void *)~0)
goto badeof;
@ -821,10 +833,10 @@ parse_list_continue( imap_store_t *ctx, char *s )
{
list_t *list;
int resp;
if ((resp = parse_imap_list( ctx, &s, &ctx->parse_list_sts )) != LIST_PARTIAL) {
list = (resp == LIST_BAD) ? 0 : ctx->parse_list_sts.head;
ctx->parse_list_sts.head = 0;
resp = ctx->parse_list_sts.callback( ctx, list, s );
if ((resp = parse_imap_list( ctx, &s, &ctx->server->parse_list_sts )) != LIST_PARTIAL) {
list = (resp == LIST_BAD) ? 0 : ctx->server->parse_list_sts.head;
ctx->server->parse_list_sts.head = 0;
resp = ctx->server->parse_list_sts.callback( ctx, list, s );
}
return resp;
}
@ -832,8 +844,8 @@ parse_list_continue( imap_store_t *ctx, char *s )
static int
parse_list( imap_store_t *ctx, char *s, int (*cb)( imap_store_t *ctx, list_t *list, char *s ) )
{
parse_list_init( &ctx->parse_list_sts );
ctx->parse_list_sts.callback = cb;
parse_list_init( &ctx->server->parse_list_sts );
ctx->server->parse_list_sts.callback = cb;
return parse_list_continue( ctx, s );
}
@ -850,7 +862,7 @@ parse_namespace_rsp_fail( void )
static int
parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
{
if (!(ctx->ns_personal = list))
if (!(ctx->server->ns_personal = list))
return parse_namespace_rsp_fail();
return parse_list( ctx, s, parse_namespace_rsp_p2 );
}
@ -858,7 +870,7 @@ parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s )
static int
parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
{
if (!(ctx->ns_other = list))
if (!(ctx->server->ns_other = list))
return parse_namespace_rsp_fail();
return parse_list( ctx, s, parse_namespace_rsp_p3 );
}
@ -866,7 +878,7 @@ parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s )
static int
parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
{
if (!(ctx->ns_shared = list))
if (!(ctx->server->ns_shared = list))
return parse_namespace_rsp_fail();
return LIST_OK;
}
@ -982,7 +994,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED )
}
if (body) {
for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next)
for (cmdp = ctx->server->in_progress; cmdp; cmdp = cmdp->next)
if (cmdp->param.uid == uid)
goto gotuid;
error( "IMAP error: unexpected FETCH response (UID %d)\n", uid );
@ -1024,21 +1036,21 @@ parse_capability( imap_store_t *ctx, char *cmd )
char *arg;
uint i;
free_string_list( ctx->auth_mechs );
ctx->auth_mechs = 0;
ctx->caps = 0x80000000;
free_string_list( ctx->server->auth_mechs );
ctx->server->auth_mechs = 0;
ctx->server->caps = 0x80000000;
while ((arg = next_arg( &cmd ))) {
if (starts_with( arg, -1, "AUTH=", 5 )) {
add_string_list( &ctx->auth_mechs, arg + 5 );
add_string_list( &ctx->server->auth_mechs, arg + 5 );
} else {
for (i = 0; i < as(cap_list); i++)
if (!strcmp( cap_list[i], arg ))
ctx->caps |= 1 << i;
ctx->server->caps |= 1 << i;
}
}
ctx->caps &= ~((imap_store_conf_t *)ctx->gen.conf)->server->cap_mask;
ctx->server->caps &= ~((imap_store_conf_t *)ctx->gen.conf)->server->cap_mask;
if (!CAP(NOLOGIN))
add_string_list( &ctx->auth_mechs, "LOGIN" );
add_string_list( &ctx->server->auth_mechs, "LOGIN" );
}
static int
@ -1218,7 +1230,7 @@ imap_socket_read( void *aux )
conn_iovec_t iov[2];
for (;;) {
if (ctx->parse_list_sts.level) {
if (ctx->server->parse_list_sts.level) {
resp = parse_list_continue( ctx, 0 );
listret:
if (resp == LIST_PARTIAL)
@ -1227,11 +1239,11 @@ imap_socket_read( void *aux )
break;
continue;
}
if (!(cmd = socket_read_line( &ctx->conn )))
if (!(cmd = socket_read_line( &ctx->server->conn )))
return;
if (cmd == (void *)~0) {
if (!ctx->expectEOF)
error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name );
if (!ctx->server->expectEOF)
error( "IMAP error: unexpected EOF from %s\n", ctx->server->conn.name );
/* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */
break;
}
@ -1252,9 +1264,9 @@ imap_socket_read( void *aux )
break;
}
if (ctx->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) {
if (ctx->server->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) {
parse_response_code( ctx, 0, cmd );
ctx->greeting = GreetingPreauth;
ctx->server->greeting = GreetingPreauth;
dogreet:
imap_ref( ctx );
imap_open_store_greeted( ctx );
@ -1262,20 +1274,20 @@ imap_socket_read( void *aux )
return;
} else if (!strcmp( "OK", arg )) {
parse_response_code( ctx, 0, cmd );
if (ctx->greeting == GreetingPending) {
ctx->greeting = GreetingOk;
if (ctx->server->greeting == GreetingPending) {
ctx->server->greeting = GreetingOk;
goto dogreet;
}
} else if (!strcmp( "BYE", arg )) {
if (!ctx->expectBYE) {
ctx->greeting = GreetingBad;
if (!ctx->server->expectBYE) {
ctx->server->greeting = GreetingBad;
error( "IMAP error: unexpected BYE response: %s\n", cmd );
/* We just wait for the server to close the connection now. */
ctx->expectEOF = 1;
ctx->server->expectEOF = 1;
} else {
/* We still need to wait for the LOGOUT's tagged OK. */
}
} else if (ctx->greeting == GreetingPending) {
} else if (ctx->server->greeting == GreetingPending) {
error( "IMAP error: bogus greeting response %s\n", arg );
break;
} else if (!strcmp( "NO", arg )) {
@ -1304,14 +1316,14 @@ imap_socket_read( void *aux )
break; /* this may mean anything, so prefer not to spam the log */
}
continue;
} else if (!ctx->in_progress) {
} else if (!ctx->server->in_progress) {
error( "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" );
break; /* this may mean anything, so prefer not to spam the log */
} else if (*arg == '+') {
socket_expect_read( &ctx->conn, 0 );
socket_expect_read( &ctx->server->conn, 0 );
/* There can be any number of commands in flight, but only the last
* one can require a continuation, as it enforces a round-trip. */
cmdp = (struct imap_cmd *)((char *)ctx->in_progress_append -
cmdp = (struct imap_cmd *)((char *)ctx->server->in_progress_append -
offsetof(struct imap_cmd, next));
if (cmdp->param.data) {
if (cmdp->param.to_trash)
@ -1320,11 +1332,11 @@ imap_socket_read( void *aux )
iov[0].len = cmdp->param.data_len;
iov[0].takeOwn = GiveOwn;
cmdp->param.data = 0;
ctx->buffer_mem -= cmdp->param.data_len;
ctx->server->buffer_mem -= cmdp->param.data_len;
iov[1].buf = "\r\n";
iov[1].len = 2;
iov[1].takeOwn = KeepOwn;
socket_write( &ctx->conn, iov, 2 );
socket_write( &ctx->server->conn, iov, 2 );
} else if (cmdp->param.cont) {
if (cmdp->param.cont( ctx, cmdp, cmd ))
return;
@ -1332,19 +1344,19 @@ imap_socket_read( void *aux )
error( "IMAP error: unexpected command continuation request\n" );
break;
}
socket_expect_read( &ctx->conn, 1 );
socket_expect_read( &ctx->server->conn, 1 );
} else {
tag = atoi( arg );
for (pcmdp = &ctx->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next)
for (pcmdp = &ctx->server->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next)
if (cmdp->tag == tag)
goto gottag;
error( "IMAP error: unexpected tag %s\n", arg );
break;
gottag:
if (!(*pcmdp = cmdp->next))
ctx->in_progress_append = pcmdp;
if (!--ctx->num_in_progress)
socket_expect_read( &ctx->conn, 0 );
ctx->server->in_progress_append = pcmdp;
if (!--ctx->server->num_in_progress)
socket_expect_read( &ctx->server->conn, 0 );
arg = next_arg( &cmd );
if (!arg) {
error( "IMAP error: malformed tagged response\n" );
@ -1388,8 +1400,8 @@ imap_socket_read( void *aux )
done_imap_cmd( ctx, cmdp, resp );
if (imap_deref( ctx ))
return;
if (ctx->canceling && !ctx->in_progress) {
ctx->canceling = 0;
if (ctx->server->canceling && !ctx->server->in_progress) {
ctx->server->canceling = 0;
ctx->callbacks.imap_cancel( ctx->callback_aux );
return;
}
@ -1421,10 +1433,11 @@ get_cmd_result_p2( imap_store_t *ctx, struct imap_cmd *cmd, int response )
static void
imap_cleanup_store( imap_store_t *ctx )
imap_cancel_store_only( imap_store_t *ctx )
{
free_generic_messages( ctx->gen.msgs );
free_string_list( ctx->gen.boxes );
imap_deref( ctx );
}
static void
@ -1433,17 +1446,16 @@ imap_cancel_store( store_t *gctx )
imap_store_t *ctx = (imap_store_t *)gctx;
#ifdef HAVE_LIBSASL
sasl_dispose( &ctx->sasl );
sasl_dispose( &ctx->server->sasl );
#endif
socket_close( &ctx->conn );
socket_close( &ctx->server->conn );
cancel_sent_imap_cmds( ctx );
cancel_pending_imap_cmds( ctx );
free_list( ctx->ns_personal );
free_list( ctx->ns_other );
free_list( ctx->ns_shared );
free_string_list( ctx->auth_mechs );
imap_cleanup_store( ctx );
imap_deref( ctx );
free_list( ctx->server->ns_personal );
free_list( ctx->server->ns_other );
free_list( ctx->server->ns_shared );
free_string_list( ctx->server->auth_mechs );
imap_cancel_store_only( ctx );
}
static int
@ -1502,7 +1514,7 @@ imap_cleanup( void )
nctx = ctx->next;
set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx );
if (((imap_store_t *)ctx)->state != SST_BAD) {
((imap_store_t *)ctx)->expectBYE = 1;
((imap_store_t *)ctx)->server->expectBYE = 1;
imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" );
} else {
imap_cancel_store( ctx );
@ -1517,7 +1529,7 @@ imap_cleanup_p2( imap_store_t *ctx,
if (response == RESP_NO)
imap_cancel_store( &ctx->gen );
else if (response == RESP_OK)
ctx->expectEOF = 1;
ctx->server->expectEOF = 1;
}
/******************* imap_open_store *******************/
@ -1554,6 +1566,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
imap_store_conf_t *cfg = (imap_store_conf_t *)conf;
imap_server_conf_t *srvc = cfg->server;
imap_store_t *ctx;
imap_server_t *server = 0;
store_t **ctxp;
/* First try to recycle a whole store. */
@ -1568,7 +1581,8 @@ imap_alloc_store( store_conf_t *conf, const char *label )
for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next)
if (ctx->state != SST_BAD && ((imap_store_conf_t *)ctx->gen.conf)->server == srvc) {
*ctxp = ctx->gen.next;
imap_cleanup_store( ctx );
server = ctx->server;
imap_cancel_store_only( ctx );
/* One could ping the server here, but given that the idle timeout
* is at least 30 minutes, this sounds pretty pointless. */
ctx->state = SST_HALF;
@ -1576,15 +1590,17 @@ imap_alloc_store( store_conf_t *conf, const char *label )
}
/* Finally, schedule opening a new server connection. */
ctx = nfcalloc( sizeof(*ctx) );
socket_init( &ctx->conn, &srvc->sconf,
server = nfcalloc( sizeof(*server) );
socket_init( &server->conn, &srvc->sconf,
(void (*)( void * ))imap_invoke_bad_callback,
imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx );
ctx->in_progress_append = &ctx->in_progress;
ctx->pending_append = &ctx->pending;
server->in_progress_append = &server->in_progress;
server->pending_append = &server->pending;
gotsrv:
ctx = nfcalloc( sizeof(*ctx) );
ctx->gen.conf = conf;
ctx->server = server;
ctx->label = label;
ctx->ref_count = 1;
return &ctx->gen;
@ -1604,7 +1620,7 @@ imap_connect_store( store_t *gctx,
if (ctx->state == SST_HALF)
imap_open_store_namespace( ctx );
else
socket_connect( &ctx->conn, imap_open_store_connected );
socket_connect( &ctx->server->conn, imap_open_store_connected );
}
}
@ -1621,10 +1637,10 @@ imap_open_store_connected( int ok, void *aux )
imap_open_store_bail( ctx, FAIL_WAIT );
#ifdef HAVE_LIBSSL
else if (srvc->ssl_type == SSL_IMAPS)
socket_start_tls( &ctx->conn, imap_open_store_tlsstarted1 );
socket_start_tls( &ctx->server->conn, imap_open_store_tlsstarted1 );
#endif
else
socket_expect_read( &ctx->conn, 1 );
socket_expect_read( &ctx->server->conn, 1 );
}
#ifdef HAVE_LIBSSL
@ -1636,15 +1652,15 @@ imap_open_store_tlsstarted1( int ok, void *aux )
if (!ok)
imap_open_store_ssl_bail( ctx );
else
socket_expect_read( &ctx->conn, 1 );
socket_expect_read( &ctx->server->conn, 1 );
}
#endif
static void
imap_open_store_greeted( imap_store_t *ctx )
{
socket_expect_read( &ctx->conn, 0 );
if (!ctx->caps)
socket_expect_read( &ctx->server->conn, 0 );
if (!ctx->server->caps)
imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" );
else
imap_open_store_authenticate( ctx );
@ -1667,7 +1683,7 @@ imap_open_store_authenticate( imap_store_t *ctx )
imap_server_conf_t *srvc = cfg->server;
#endif
if (ctx->greeting != GreetingPreauth) {
if (ctx->server->greeting != GreetingPreauth) {
#ifdef HAVE_LIBSSL
if (srvc->ssl_type == SSL_STARTTLS) {
if (CAP(STARTTLS)) {
@ -1700,7 +1716,7 @@ imap_open_store_authenticate_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UN
if (response == RESP_NO)
imap_open_store_bail( ctx, FAIL_FINAL );
else if (response == RESP_OK)
socket_start_tls( &ctx->conn, imap_open_store_tlsstarted2 );
socket_start_tls( &ctx->server->conn, imap_open_store_tlsstarted2 );
}
static void
@ -1836,14 +1852,14 @@ process_sasl_step( imap_store_t *ctx, int rc, const char *in, uint in_len,
while (rc == SASL_INTERACT) {
if (process_sasl_interact( interact, srvc ) < 0)
return -1;
rc = sasl_client_step( ctx->sasl, in, in_len, &interact, out, out_len );
rc = sasl_client_step( ctx->server->sasl, in, in_len, &interact, out, out_len );
}
if (rc == SASL_CONTINUE) {
ctx->sasl_cont = 1;
ctx->server->sasl_cont = 1;
} else if (rc == SASL_OK) {
ctx->sasl_cont = 0;
ctx->server->sasl_cont = 0;
} else {
error( "Error: %s\n", sasl_errdetail( ctx->sasl ) );
error( "Error: %s\n", sasl_errdetail( ctx->server->sasl ) );
return -1;
}
return 0;
@ -1895,13 +1911,13 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char *
sasl_interact_t *interact = NULL;
conn_iovec_t iov[2];
if (!ctx->sasl_cont) {
if (!ctx->server->sasl_cont) {
error( "Error: IMAP wants more steps despite successful SASL authentication.\n" );
goto bail;
}
if (decode_sasl_data( prompt, &in, &in_len ) < 0)
goto bail;
rc = sasl_client_step( ctx->sasl, in, in_len, &interact, &out, &out_len );
rc = sasl_client_step( ctx->server->sasl, in, in_len, &interact, &out, &out_len );
ret = process_sasl_step( ctx, rc, in, in_len, interact, &out, &out_len );
free( in );
if (ret < 0)
@ -1930,7 +1946,7 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char *
iov[iovcnt].len = 2;
iov[iovcnt].takeOwn = KeepOwn;
iovcnt++;
socket_write( &ctx->conn, iov, iovcnt );
socket_write( &ctx->server->conn, iov, iovcnt );
return 0;
bail:
@ -1941,11 +1957,11 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char *
static void
done_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response )
{
if (response == RESP_OK && ctx->sasl_cont) {
if (response == RESP_OK && ctx->server->sasl_cont) {
sasl_interact_t *interact = NULL;
const char *out;
uint out_len;
int rc = sasl_client_step( ctx->sasl, NULL, 0, &interact, &out, &out_len );
int rc = sasl_client_step( ctx->server->sasl, NULL, 0, &interact, &out, &out_len );
if (process_sasl_step( ctx, rc, NULL, 0, interact, &out, &out_len ) < 0)
warn( "Warning: SASL reported failure despite successful IMAP authentication. Ignoring...\n" );
else if (out)
@ -1971,11 +1987,11 @@ imap_open_store_authenticate2( imap_store_t *ctx )
info( "Logging in...\n" );
for (mech = srvc->auth_mechs; mech; mech = mech->next) {
int any = !strcmp( mech->string, "*" );
for (cmech = ctx->auth_mechs; cmech; cmech = cmech->next) {
for (cmech = ctx->server->auth_mechs; cmech; cmech = cmech->next) {
if (any || !strcasecmp( mech->string, cmech->string )) {
if (!strcasecmp( cmech->string, "LOGIN" )) {
#ifdef HAVE_LIBSSL
if (ctx->conn.ssl || !any)
if (ctx->server->conn.ssl || !any)
#endif
auth_login = 1;
} else {
@ -2014,15 +2030,15 @@ imap_open_store_authenticate2( imap_store_t *ctx )
sasl_inited = 1;
}
rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->sasl );
rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->server->sasl );
if (rc != SASL_OK) {
if (!ctx->sasl)
if (!ctx->server->sasl)
goto saslbail;
error( "Error: %s\n", sasl_errdetail( ctx->sasl ) );
error( "Error: %s\n", sasl_errdetail( ctx->server->sasl ) );
goto bail;
}
rc = sasl_client_start( ctx->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech );
rc = sasl_client_start( ctx->server->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech );
if (gotmech)
info( "Authenticating with SASL mechanism %s...\n", gotmech );
/* Technically, we are supposed to loop over sasl_client_start(),
@ -2047,7 +2063,7 @@ imap_open_store_authenticate2( imap_store_t *ctx )
if (!ensure_user( srvc ) || !ensure_password( srvc ))
goto bail;
#ifdef HAVE_LIBSSL
if (!ctx->conn.ssl)
if (!ctx->server->conn.ssl)
#endif
warn( "*** IMAP Warning *** Password is being sent in the clear\n" );
imap_exec( ctx, 0, imap_open_store_authenticate2_p2,
@ -2089,7 +2105,7 @@ imap_open_store_compress_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED
/* We already reported an error, but it's not fatal to us. */
imap_open_store_namespace( ctx );
} else if (response == RESP_OK) {
socket_start_deflate( &ctx->conn );
socket_start_deflate( &ctx->server->conn );
imap_open_store_namespace( ctx );
}
}
@ -2105,7 +2121,7 @@ imap_open_store_namespace( imap_store_t *ctx )
ctx->delimiter[0] = cfg->delimiter ? cfg->delimiter : 0;
if (((!ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) {
/* get NAMESPACE info */
if (!ctx->got_namespace)
if (!ctx->server->got_namespace)
imap_exec( ctx, 0, imap_open_store_namespace_p2, "NAMESPACE" );
else
imap_open_store_namespace2( ctx );
@ -2120,7 +2136,7 @@ imap_open_store_namespace_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSE
if (response == RESP_NO) {
imap_open_store_bail( ctx, FAIL_FINAL );
} else if (response == RESP_OK) {
ctx->got_namespace = 1;
ctx->server->got_namespace = 1;
imap_open_store_namespace2( ctx );
}
}
@ -2132,7 +2148,7 @@ imap_open_store_namespace2( imap_store_t *ctx )
list_t *nsp, *nsp_1st, *nsp_1st_ns, *nsp_1st_dl;
/* XXX for now assume 1st personal namespace */
if (is_list( (nsp = ctx->ns_personal) ) &&
if (is_list( (nsp = ctx->server->ns_personal) ) &&
is_list( (nsp_1st = nsp->child) ) &&
is_atom( (nsp_1st_ns = nsp_1st->child) ) &&
is_atom( (nsp_1st_dl = nsp_1st_ns->next) ))
@ -2162,7 +2178,7 @@ static void
imap_open_store_ssl_bail( imap_store_t *ctx )
{
/* This avoids that we try to send LOGOUT to an unusable socket. */
socket_close( &ctx->conn );
socket_close( &ctx->server->conn );
imap_open_store_bail( ctx, FAIL_FINAL );
}
#endif
@ -2545,7 +2561,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
flagstr[d] = 0;
INIT_IMAP_CMD(imap_cmd_out_uid, cmd, cb, aux)
ctx->buffer_mem += data->len;
ctx->server->buffer_mem += data->len;
cmd->gen.param.data_len = data->len;
cmd->gen.param.data = data->data;
cmd->out_uid = -2;
@ -2642,8 +2658,8 @@ imap_cancel_cmds( store_t *gctx,
imap_store_t *ctx = (imap_store_t *)gctx;
cancel_pending_imap_cmds( ctx );
if (ctx->in_progress) {
ctx->canceling = 1;
if (ctx->server->in_progress) {
ctx->server->canceling = 1;
ctx->callbacks.imap_cancel = cb;
ctx->callback_aux = aux;
} else {
@ -2666,7 +2682,7 @@ imap_memory_usage( store_t *gctx )
{
imap_store_t *ctx = (imap_store_t *)gctx;
return ctx->buffer_mem + ctx->conn.buffer_mem;
return ctx->server->buffer_mem + ctx->server->conn.buffer_mem;
}
/******************* imap_fail_state *******************/

Loading…
Cancel
Save