diff options
Diffstat (limited to '')
| -rw-r--r-- | src/imap/ngx_imap.h | 2 | ||||
| -rw-r--r-- | src/imap/ngx_imap_auth_http_module.c | 23 | ||||
| -rw-r--r-- | src/imap/ngx_imap_core_module.c | 4 | ||||
| -rw-r--r-- | src/imap/ngx_imap_handler.c | 84 | ||||
| -rw-r--r-- | src/imap/ngx_imap_parse.c | 55 | ||||
| -rw-r--r-- | src/imap/ngx_imap_proxy_module.c | 4 | ||||
| -rw-r--r-- | src/imap/ngx_imap_ssl_module.c | 14 |
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; } |
