summaryrefslogtreecommitdiffhomepage
path: root/src/imap
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/imap/ngx_imap.h2
-rw-r--r--src/imap/ngx_imap_auth_http_module.c23
-rw-r--r--src/imap/ngx_imap_core_module.c4
-rw-r--r--src/imap/ngx_imap_handler.c84
-rw-r--r--src/imap/ngx_imap_parse.c55
-rw-r--r--src/imap/ngx_imap_proxy_module.c4
-rw-r--r--src/imap/ngx_imap_ssl_module.c14
7 files changed, 149 insertions, 37 deletions
diff --git a/src/imap/ngx_imap.h b/src/imap/ngx_imap.h
index 7bee2adf3..c42324cf7 100644
--- a/src/imap/ngx_imap.h
+++ b/src/imap/ngx_imap.h
@@ -101,6 +101,8 @@ typedef struct {
unsigned quit:1;
unsigned protocol:1;
unsigned quoted:1;
+ unsigned backslash:1;
+ unsigned no_sync_literal:1;
ngx_str_t login;
ngx_str_t passwd;
diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c
index 1e2bc4c04..616222755 100644
--- a/src/imap/ngx_imap_auth_http_module.c
+++ b/src/imap/ngx_imap_auth_http_module.c
@@ -150,7 +150,8 @@ ngx_imap_auth_http_init(ngx_imap_session_t *s)
rc = ngx_event_connect_peer(&ctx->peer);
- if (rc == NGX_ERROR || rc == NGX_CONNECT_ERROR) {
+ if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
+ ngx_close_connection(ctx->peer.connection);
ngx_imap_session_internal_server_error(s);
return;
}
@@ -448,6 +449,7 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s,
p = ngx_pcalloc(s->connection->pool, size);
if (p == NULL) {
+ ngx_close_connection(ctx->peer.connection);
ngx_imap_session_internal_server_error(s);
return;
}
@@ -641,8 +643,9 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s,
static void
ngx_imap_auth_sleep_handler(ngx_event_t *rev)
{
- ngx_connection_t *c;
- ngx_imap_session_t *s;
+ ngx_connection_t *c;
+ ngx_imap_session_t *s;
+ ngx_imap_core_srv_conf_t *cscf;
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap auth sleep handler");
@@ -662,6 +665,18 @@ ngx_imap_auth_sleep_handler(ngx_event_t *rev)
s->connection->read->handler = ngx_imap_auth_state;
}
+ c->log->action = "in auth state";
+
+ ngx_imap_send(s->connection->write);
+
+ if (c->closed) {
+ return;
+ }
+
+ cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
+
+ ngx_add_timer(rev, cscf->timeout);
+
if (rev->ready) {
s->connection->read->handler(rev);
return;
@@ -671,8 +686,6 @@ ngx_imap_auth_sleep_handler(ngx_event_t *rev)
ngx_imap_close_connection(s->connection);
}
- ngx_imap_send(s->connection->write);
-
return;
}
diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c
index 0203f44f1..9d6629859 100644
--- a/src/imap/ngx_imap_core_module.c
+++ b/src/imap/ngx_imap_core_module.c
@@ -418,7 +418,9 @@ ngx_imap_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ls->ctx = cf->ctx;
/* STUB */
- ls->log = cf->cycle->new_log;
+ ls->log = *cf->cycle->new_log;
+ ls->log.data = &ls->addr_text;
+ ls->log.handler = ngx_accept_log_error;
/**/
return NGX_CONF_OK;
diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c
index 0ddf51f61..6497ced0b 100644
--- a/src/imap/ngx_imap_handler.c
+++ b/src/imap/ngx_imap_handler.c
@@ -33,6 +33,7 @@ static ngx_str_t internal_server_errors[] = {
static u_char pop3_ok[] = "+OK" CRLF;
static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF;
+static u_char imap_star[] = "* ";
static u_char imap_ok[] = "OK completed" CRLF;
static u_char imap_next[] = "+ OK" CRLF;
static u_char imap_bye[] = "* BYE" CRLF;
@@ -42,26 +43,48 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF;
void
ngx_imap_init_connection(ngx_connection_t *c)
{
- ngx_imap_log_ctx_t *ctx;
+ ngx_imap_log_ctx_t *lctx;
+#if (NGX_IMAP_SSL)
+ ngx_imap_conf_ctx_t *ctx;
+ ngx_imap_ssl_conf_t *sslcf;
+#endif
ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap init connection");
- ctx = ngx_palloc(c->pool, sizeof(ngx_imap_log_ctx_t));
- if (ctx == NULL) {
+ lctx = ngx_palloc(c->pool, sizeof(ngx_imap_log_ctx_t));
+ if (lctx == NULL) {
ngx_imap_close_connection(c);
return;
}
- ctx->client = &c->addr_text;
- ctx->session = NULL;
+ lctx->client = &c->addr_text;
+ lctx->session = NULL;
c->log->connection = c->number;
c->log->handler = ngx_imap_log_error;
- c->log->data = ctx;
+ c->log->data = lctx;
c->log->action = "sending client greeting line";
c->log_error = NGX_ERROR_INFO;
+#if (NGX_IMAP_SSL)
+
+ ctx = c->ctx;
+ sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module);
+
+ if (sslcf->enable) {
+ if (ngx_ssl_create_connection(sslcf->ssl_ctx, c, 0) == NGX_ERROR) {
+ ngx_imap_close_connection(c);
+ return;
+ }
+
+ c->recv = ngx_ssl_recv;
+ c->send = ngx_ssl_write;
+ c->send_chain = ngx_ssl_send_chain;
+ }
+
+#endif
+
ngx_imap_init_session(c->read);
}
@@ -76,27 +99,15 @@ ngx_imap_init_session(ngx_event_t *rev)
ngx_imap_core_srv_conf_t *cscf;
#if (NGX_IMAP_SSL)
ngx_int_t rc;
- ngx_imap_ssl_conf_t *sslcf;
#endif
c = rev->data;
-
ctx = c->ctx;
-
cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module);
#if (NGX_IMAP_SSL)
- sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module);
-
- if (sslcf->enable) {
-
- if (ngx_ssl_create_session(sslcf->ssl_ctx, c, NGX_SSL_BUFFER)
- == NGX_ERROR)
- {
- ngx_imap_close_connection(c);
- return;
- }
+ if (c->ssl) {
rc = ngx_ssl_handshake(c);
@@ -116,9 +127,6 @@ ngx_imap_init_session(ngx_event_t *rev)
return;
}
- c->recv = ngx_ssl_recv;
- c->send = ngx_ssl_write;
- c->send_chain = ngx_ssl_send_chain;
}
#endif
@@ -275,11 +283,11 @@ ngx_imap_init_protocol(ngx_event_t *rev)
void
ngx_imap_auth_state(ngx_event_t *rev)
{
- u_char *text, *last, *p;
+ u_char *text, *last, *p, *dst, *src, *end;
ssize_t text_len, last_len;
ngx_str_t *arg;
ngx_int_t rc;
- ngx_uint_t tag;
+ ngx_uint_t tag, i;
ngx_connection_t *c;
ngx_imap_session_t *s;
ngx_imap_core_srv_conf_t *cscf;
@@ -324,6 +332,27 @@ ngx_imap_auth_state(ngx_event_t *rev)
ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth command: %i",
s->command);
+ if (s->backslash) {
+
+ arg = s->args.elts;
+
+ for (i = 0; i < s->args.nelts; i++) {
+ dst = arg[i].data;
+ end = dst + arg[i].len;
+
+ for (src = dst; src < end; dst++) {
+ *dst = *src;
+ if (*src++ == '\\') {
+ *dst = *src++;
+ }
+ }
+
+ arg[i].len = dst - arg[i].data;
+ }
+
+ s->backslash = 0;
+ }
+
switch (s->command) {
case NGX_IMAP_LOGIN:
@@ -405,6 +434,11 @@ ngx_imap_auth_state(ngx_event_t *rev)
}
if (tag) {
+ if (s->tag.len == 0) {
+ s->tag.len = sizeof(imap_star) - 1;
+ s->tag.data = (u_char *) imap_star;
+ }
+
if (s->tagged_line.len < s->tag.len + text_len + last_len) {
s->tagged_line.len = s->tag.len + text_len + last_len;
s->tagged_line.data = ngx_palloc(c->pool, s->tagged_line.len);
@@ -693,6 +727,8 @@ ngx_imap_close_connection(ngx_connection_t *c)
#endif
+ c->closed = 1;
+
pool = c->pool;
ngx_close_connection(c);
diff --git a/src/imap/ngx_imap_parse.c b/src/imap/ngx_imap_parse.c
index 374605ec5..473825c92 100644
--- a/src/imap/ngx_imap_parse.c
+++ b/src/imap/ngx_imap_parse.c
@@ -20,7 +20,9 @@ ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s)
sw_command,
sw_spaces_before_argument,
sw_argument,
+ sw_backslash,
sw_literal,
+ sw_no_sync_literal_argument,
sw_start_literal_argument,
sw_literal_argument,
sw_end_literal_argument,
@@ -225,6 +227,22 @@ ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s)
goto done;
}
break;
+ case '\\':
+ if (s->quoted) {
+ s->backslash = 1;
+ state = sw_backslash;
+ }
+ break;
+ }
+ break;
+
+ case sw_backslash:
+ switch (ch) {
+ case CR:
+ case LF:
+ goto invalid;
+ default:
+ state = sw_argument;
}
break;
@@ -237,6 +255,18 @@ ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s)
state = sw_start_literal_argument;
break;
}
+ if (ch == '+') {
+ state = sw_no_sync_literal_argument;
+ break;
+ }
+ goto invalid;
+
+ case sw_no_sync_literal_argument:
+ if (ch == '}') {
+ s->no_sync_literal = 1;
+ state = sw_start_literal_argument;
+ break;
+ }
goto invalid;
case sw_start_literal_argument:
@@ -246,10 +276,17 @@ ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s)
case LF:
s->buffer->pos = p + 1;
s->arg_start = p + 1;
- s->state = sw_literal_argument;
- return NGX_IMAP_NEXT;
+ if (s->no_sync_literal == 0) {
+ s->state = sw_literal_argument;
+ return NGX_IMAP_NEXT;
+ }
+ state = sw_literal_argument;
+ s->no_sync_literal = 0;
+ break;
+ default:
+ goto invalid;
}
- goto invalid;
+ break;
case sw_literal_argument:
if (s->literal_len && --s->literal_len) {
@@ -312,9 +349,11 @@ done:
}
arg->len = s->arg_end - s->arg_start;
arg->data = s->arg_start;
+
s->arg_start = NULL;
s->cmd_start = NULL;
s->quoted = 0;
+ s->no_sync_literal = 0;
s->literal_len = 0;
}
@@ -326,6 +365,7 @@ invalid:
s->state = sw_start;
s->quoted = 0;
+ s->no_sync_literal = 0;
s->literal_len = 0;
return NGX_IMAP_PARSE_INVALID_COMMAND;
@@ -432,7 +472,14 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s)
case sw_argument:
switch (ch) {
- case ' ':
+
+ /*
+ * the space should be considered part of the at username
+ * or password, but not of argument in other commands
+ *
+ * case ' ':
+ */
+
case CR:
case LF:
arg = ngx_array_push(&s->args);
diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c
index 5502dc617..86a4ff8a9 100644
--- a/src/imap/ngx_imap_proxy_module.c
+++ b/src/imap/ngx_imap_proxy_module.c
@@ -111,8 +111,8 @@ ngx_imap_proxy_init(ngx_imap_session_t *s, ngx_peers_t *peers)
rc = ngx_event_connect_peer(&p->upstream);
- if (rc == NGX_ERROR || rc == NGX_CONNECT_ERROR) {
- ngx_imap_session_internal_server_error(s);
+ if (rc == NGX_ERROR || rc == NGX_BUSY || rc == NGX_DECLINED) {
+ ngx_imap_proxy_internal_server_error(s);
return;
}
diff --git a/src/imap/ngx_imap_ssl_module.c b/src/imap/ngx_imap_ssl_module.c
index b072d9194..bd4579e68 100644
--- a/src/imap/ngx_imap_ssl_module.c
+++ b/src/imap/ngx_imap_ssl_module.c
@@ -76,6 +76,9 @@ ngx_module_t ngx_imap_ssl_module = {
};
+static u_char ngx_imap_session_id_ctx[] = "IMAP";
+
+
static void *
ngx_imap_ssl_create_conf(ngx_conf_t *cf)
{
@@ -176,7 +179,16 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
- SSL_CTX_set_verify(conf->ssl_ctx, SSL_VERIFY_NONE, NULL);
+ SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL);
+
+ SSL_CTX_set_mode(conf->ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+
+ SSL_CTX_set_read_ahead(conf->ssl_ctx, 1);
+
+ SSL_CTX_set_session_cache_mode(conf->ssl_ctx, SSL_SESS_CACHE_SERVER);
+
+ SSL_CTX_set_session_id_context(conf->ssl_ctx, ngx_imap_session_id_ctx,
+ sizeof(ngx_imap_session_id_ctx) - 1);
return NGX_CONF_OK;
}