diff options
Diffstat (limited to 'src/imap')
| -rw-r--r-- | src/imap/ngx_imap.h | 12 | ||||
| -rw-r--r-- | src/imap/ngx_imap_auth_http_module.c | 7 | ||||
| -rw-r--r-- | src/imap/ngx_imap_core_module.c | 10 | ||||
| -rw-r--r-- | src/imap/ngx_imap_handler.c | 287 | ||||
| -rw-r--r-- | src/imap/ngx_imap_proxy_module.c | 91 | ||||
| -rw-r--r-- | src/imap/ngx_imap_ssl_module.c | 174 | ||||
| -rw-r--r-- | src/imap/ngx_imap_ssl_module.h | 30 |
7 files changed, 476 insertions, 135 deletions
diff --git a/src/imap/ngx_imap.h b/src/imap/ngx_imap.h index 8a506db64..5e037743b 100644 --- a/src/imap/ngx_imap.h +++ b/src/imap/ngx_imap.h @@ -13,6 +13,11 @@ #include <ngx_event.h> #include <ngx_event_connect.h> +#if (NGX_IMAP_SSL) +#include <ngx_imap_ssl_module.h> +#endif + + typedef struct { void **main_conf; @@ -32,7 +37,6 @@ typedef struct { ngx_msec_t timeout; size_t imap_client_buffer_size; - size_t proxy_buffer_size; ngx_uint_t protocol; @@ -82,8 +86,8 @@ typedef struct { ngx_connection_t *connection; - ngx_buf_t *buffer; ngx_str_t out; + ngx_buf_t *buffer; void **ctx; void **main_conf; @@ -93,6 +97,8 @@ typedef struct { ngx_uint_t imap_state; + unsigned blocked:1; + unsigned quit:1; unsigned protocol:1; unsigned quoted:1; @@ -100,6 +106,7 @@ typedef struct { ngx_str_t passwd; ngx_str_t tag; + ngx_str_t tagged_line; ngx_uint_t command; ngx_array_t args; @@ -167,6 +174,7 @@ typedef struct { void ngx_imap_init_connection(ngx_connection_t *c); +void ngx_imap_send(ngx_event_t *wev); void ngx_imap_auth_state(ngx_event_t *rev); void ngx_pop3_auth_state(ngx_event_t *rev); void ngx_imap_close_connection(ngx_connection_t *c); diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c index e66593a4a..2bf0cc96c 100644 --- a/src/imap/ngx_imap_auth_http_module.c +++ b/src/imap/ngx_imap_auth_http_module.c @@ -516,13 +516,14 @@ ngx_imap_auth_http_process_headers(ngx_imap_session_t *s, ngx_close_connection(ctx->peer.connection); if (ctx->err.len) { - (void) ngx_send(s->connection, ctx->err.data, ctx->err.len); + s->out = ctx->err; if (ctx->sleep == 0) { - ngx_imap_close_connection(s->connection); - return; + s->quit = 1; } + ngx_imap_send(s->connection->write); + ngx_add_timer(s->connection->read, ctx->sleep * 1000); s->connection->read->handler = ngx_imap_auth_sleep_handler; diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c index e5d7a2050..8225574ec 100644 --- a/src/imap/ngx_imap_core_module.c +++ b/src/imap/ngx_imap_core_module.c @@ -75,13 +75,6 @@ static ngx_command_t ngx_imap_core_commands[] = { offsetof(ngx_imap_core_srv_conf_t, imap_client_buffer_size), NULL }, - { ngx_string("proxy_buffer"), - NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, - NGX_IMAP_SRV_CONF_OFFSET, - offsetof(ngx_imap_core_srv_conf_t, proxy_buffer_size), - NULL }, - { ngx_string("timeout"), NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -157,7 +150,6 @@ ngx_imap_core_create_srv_conf(ngx_conf_t *cf) } cscf->imap_client_buffer_size = NGX_CONF_UNSET_SIZE; - cscf->proxy_buffer_size = NGX_CONF_UNSET_SIZE; cscf->timeout = NGX_CONF_UNSET_MSEC; cscf->protocol = NGX_CONF_UNSET_UINT; @@ -191,8 +183,6 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_size_value(conf->imap_client_buffer_size, prev->imap_client_buffer_size, (size_t) ngx_pagesize); - ngx_conf_merge_size_value(conf->proxy_buffer_size, prev->proxy_buffer_size, - (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); ngx_conf_merge_unsigned_value(conf->protocol, prev->protocol, NGX_IMAP_IMAP_PROTOCOL); diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c index 25509b2fe..03dedaf34 100644 --- a/src/imap/ngx_imap_handler.c +++ b/src/imap/ngx_imap_handler.c @@ -13,6 +13,10 @@ static void ngx_imap_init_session(ngx_event_t *rev); static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s); +#if (NGX_IMAP_SSL) +static void ngx_imap_ssl_close_handler(ngx_event_t *ev); +#endif + static ngx_str_t greetings[] = { ngx_string("+OK POP3 ready" CRLF), @@ -36,8 +40,12 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF; void ngx_imap_init_connection(ngx_connection_t *c) { - ssize_t size; + ngx_imap_session_t *s; ngx_imap_conf_ctx_t *ctx; +#if (NGX_IMAP_SSL) + ngx_int_t rc; + ngx_imap_ssl_conf_t *sslcf; +#endif ngx_imap_core_srv_conf_t *cscf; ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap init connection"); @@ -45,26 +53,123 @@ ngx_imap_init_connection(ngx_connection_t *c) c->log_error = NGX_ERROR_INFO; ctx = c->ctx; - cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); - size = greetings[cscf->protocol].len; +#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; + } + + rc = ngx_ssl_handshake(c); + + if (rc == 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; + } - if (ngx_send(c, greetings[cscf->protocol].data, size) < size) { - /* - * we treat the incomplete sending as NGX_ERROR - * because it is very strange here - */ +#endif + + s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t)); + if (s == NULL) { ngx_imap_close_connection(c); return; } + c->data = s; + s->connection = c; + + cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); + s->protocol = cscf->protocol; + + s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module); + if (s->ctx == NULL) { + ngx_imap_session_internal_server_error(s); + return; + } + + s->main_conf = ctx->main_conf; + s->srv_conf = ctx->srv_conf; + + s->out = greetings[s->protocol]; + c->read->handler = ngx_imap_init_session; + c->write->handler = ngx_imap_send; + ngx_add_timer(c->write, cscf->timeout); ngx_add_timer(c->read, cscf->timeout); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { ngx_imap_close_connection(c); } + + ngx_imap_send(c->write); +} + + +void +ngx_imap_send(ngx_event_t *wev) +{ + ngx_int_t n; + ngx_connection_t *c; + ngx_imap_session_t *s; + + c = wev->data; + s = c->data; + + if (wev->timedout) { + ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); + ngx_imap_close_connection(c); + return; + } + + if (s->out.len == 0) { + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + ngx_imap_close_connection(c); + } + + return; + } + + n = c->send(c, s->out.data, s->out.len); + + if (n > 0) { + s->out.len -= n; + + if (s->quit) { + ngx_imap_close_connection(c); + return; + } + + if (s->blocked) { + c->read->handler(c->read); + } + + return; + } + + if (n == NGX_ERROR) { + ngx_imap_close_connection(c); + return; + } + + /* n == NGX_AGAIN */ + + if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { + ngx_imap_close_connection(c); + return; + } } @@ -74,7 +179,6 @@ ngx_imap_init_session(ngx_event_t *rev) size_t size; ngx_connection_t *c; ngx_imap_session_t *s; - ngx_imap_conf_ctx_t *ctx; ngx_imap_core_srv_conf_t *cscf; c = rev->data; @@ -85,40 +189,20 @@ ngx_imap_init_session(ngx_event_t *rev) return; } - s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t)); - if (s == NULL) { - ngx_imap_session_internal_server_error(s); - return; - } - - c->data = s; - s->connection = c; - - s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module); - if (s->ctx == NULL) { - ngx_imap_session_internal_server_error(s); - return; - } - - ctx = c->ctx; - s->main_conf = ctx->main_conf; - s->srv_conf = ctx->srv_conf; + s = c->data; if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) { ngx_imap_session_internal_server_error(s); return; } - cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); - - s->protocol = cscf->protocol; - - if (cscf->protocol == NGX_IMAP_POP3_PROTOCOL) { + if (s->protocol == NGX_IMAP_POP3_PROTOCOL) { size = 128; s->imap_state = ngx_pop3_start; c->read->handler = ngx_pop3_auth_state; } else { + cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); size = cscf->imap_client_buffer_size; s->imap_state = ngx_imap_start; c->read->handler = ngx_imap_auth_state; @@ -137,11 +221,11 @@ ngx_imap_init_session(ngx_event_t *rev) void ngx_imap_auth_state(ngx_event_t *rev) { - u_char *text, *last, *out, *p; - ssize_t size, text_len, last_len; + u_char *text, *last, *p; + ssize_t text_len, last_len; ngx_str_t *arg; ngx_int_t rc; - ngx_uint_t quit, tag; + ngx_uint_t tag; ngx_connection_t *c; ngx_imap_session_t *s; ngx_imap_core_srv_conf_t *cscf; @@ -157,6 +241,14 @@ ngx_imap_auth_state(ngx_event_t *rev) return; } + if (s->out.len) { + ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap send handler busy"); + s->blocked = 1; + return; + } + + s->blocked = 0; + rc = ngx_imap_read_command(s); ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth: %i", rc); @@ -165,7 +257,6 @@ ngx_imap_auth_state(ngx_event_t *rev) return; } - quit = 0; tag = 1; text = NULL; @@ -235,9 +326,9 @@ ngx_imap_auth_state(ngx_event_t *rev) break; case NGX_IMAP_LOGOUT: + s->quit = 1; text = imap_bye; text_len = sizeof(imap_bye) - 1; - quit = 1; break; case NGX_IMAP_NOOP: @@ -260,18 +351,19 @@ ngx_imap_auth_state(ngx_event_t *rev) } if (tag) { - if (s->out.len < text_len + s->tag.len + last_len) { - - s->out.len = text_len + s->tag.len + last_len; - s->out.data = ngx_palloc(c->pool, s->out.len); - if (s->out.data == NULL) { + 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); + if (s->tagged_line.data == NULL) { ngx_imap_close_connection(c); return; } } - out = s->out.data; - p = out; + s->out.data = s->tagged_line.data; + s->out.len = s->tag.len + text_len + last_len; + + p = s->out.data; if (text) { p = ngx_cpymem(p, text, text_len); @@ -279,35 +371,20 @@ ngx_imap_auth_state(ngx_event_t *rev) p = ngx_cpymem(p, s->tag.data, s->tag.len); ngx_memcpy(p, last, last_len); - size = text_len + s->tag.len + last_len; } else { - out = last; - size = last_len; + s->out.data = last; + s->out.len = last_len; } - if (ngx_send(c, out, size) < size) { - /* - * we treat the incomplete sending as NGX_ERROR - * because it is very strange here - */ - ngx_imap_close_connection(c); - return; + if (rc != NGX_IMAP_NEXT) { + s->args.nelts = 0; + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + s->tag.len = 0; } - if (rc == NGX_IMAP_NEXT) { - return; - } - - if (quit) { - ngx_imap_close_connection(c); - return; - } - - s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; - s->tag.len = 0; + ngx_imap_send(c->write); } @@ -317,7 +394,6 @@ ngx_pop3_auth_state(ngx_event_t *rev) u_char *text; ssize_t size; ngx_int_t rc; - ngx_uint_t quit; ngx_str_t *arg; ngx_connection_t *c; ngx_imap_session_t *s; @@ -334,13 +410,20 @@ ngx_pop3_auth_state(ngx_event_t *rev) return; } + if (s->out.len) { + ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap send handler busy"); + s->blocked = 1; + return; + } + + s->blocked = 0; + rc = ngx_imap_read_command(s); if (rc == NGX_AGAIN || rc == NGX_ERROR) { return; } - quit = 0; text = pop3_ok; size = sizeof(pop3_ok) - 1; @@ -381,7 +464,7 @@ ngx_pop3_auth_state(ngx_event_t *rev) break; case NGX_POP3_QUIT: - quit = 1; + s->quit = 1; break; case NGX_POP3_NOOP: @@ -441,7 +524,7 @@ ngx_pop3_auth_state(ngx_event_t *rev) break; case NGX_POP3_QUIT: - quit = 1; + s->quit = 1; break; case NGX_POP3_NOOP: @@ -466,23 +549,14 @@ ngx_pop3_auth_state(ngx_event_t *rev) size = sizeof(pop3_invalid_command) - 1; } - if (ngx_send(c, text, size) < size) { - /* - * we treat the incomplete sending as NGX_ERROR - * because it is very strange here - */ - ngx_imap_close_connection(c); - return; - } - - if (quit) { - ngx_imap_close_connection(c); - return; - } - s->args.nelts = 0; s->buffer->pos = s->buffer->start; s->buffer->last = s->buffer->start; + + s->out.data = text; + s->out.len = size; + + ngx_imap_send(c->write); } @@ -492,8 +566,8 @@ ngx_imap_read_command(ngx_imap_session_t *s) ssize_t n; ngx_int_t rc; - n = ngx_recv(s->connection, s->buffer->last, - s->buffer->end - s->buffer->last); + n = s->connection->recv(s->connection, s->buffer->last, + s->buffer->end - s->buffer->last); if (n == NGX_ERROR || n == 0) { ngx_imap_close_connection(s->connection); @@ -538,10 +612,10 @@ ngx_imap_read_command(ngx_imap_session_t *s) void ngx_imap_session_internal_server_error(ngx_imap_session_t *s) { - (void) ngx_send(s->connection, internal_server_errors[s->protocol].data, - internal_server_errors[s->protocol].len); + s->out = internal_server_errors[s->protocol]; + s->quit = 1; - ngx_imap_close_connection(s->connection); + ngx_imap_send(s->connection->write); } @@ -553,9 +627,42 @@ ngx_imap_close_connection(ngx_connection_t *c) ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "close imap connection: %d", c->fd); +#if (NGX_IMAP_SSL) + + if (c->ssl) { + if (ngx_ssl_shutdown(c) == NGX_AGAIN) { + c->read->handler = ngx_imap_ssl_close_handler; + c->write->handler = ngx_imap_ssl_close_handler; + return; + } + } + +#endif + pool = c->pool; ngx_close_connection(c); ngx_destroy_pool(pool); } + + +#if (NGX_IMAP_SSL) + +static void +ngx_imap_ssl_close_handler(ngx_event_t *ev) +{ + ngx_connection_t *c; + + c = ev->data; + + ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, "http ssl close handler"); + + if (ngx_ssl_shutdown(c) == NGX_AGAIN) { + return; + } + + ngx_imap_close_connection(c); +} + +#endif diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c index be32e6fe2..f9a84ce55 100644 --- a/src/imap/ngx_imap_proxy_module.c +++ b/src/imap/ngx_imap_proxy_module.c @@ -13,6 +13,8 @@ typedef struct { ngx_flag_t enable; + size_t buffer_size; + ngx_msec_t timeout; } ngx_imap_proxy_conf_t; @@ -35,6 +37,7 @@ static char *ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, static ngx_command_t ngx_imap_proxy_commands[] = { + { ngx_string("proxy"), NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -42,6 +45,20 @@ static ngx_command_t ngx_imap_proxy_commands[] = { offsetof(ngx_imap_proxy_conf_t, enable), NULL }, + { ngx_string("proxy_buffer"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_proxy_conf_t, buffer_size), + NULL }, + + { ngx_string("proxy_timeout"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_proxy_conf_t, timeout), + NULL }, + ngx_null_command }; @@ -131,12 +148,12 @@ ngx_imap_proxy_block_read(ngx_event_t *rev) static void ngx_imap_proxy_imap_handler(ngx_event_t *rev) { - u_char *p; - ngx_int_t rc; - ngx_str_t line; - ngx_connection_t *c; - ngx_imap_session_t *s; - ngx_imap_core_srv_conf_t *cscf; + u_char *p; + ngx_int_t rc; + ngx_str_t line; + ngx_connection_t *c; + ngx_imap_session_t *s; + ngx_imap_proxy_conf_t *pcf; ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy imap auth handler"); @@ -152,10 +169,9 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) } if (s->proxy->buffer == NULL) { - cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); - s->proxy->buffer = ngx_create_temp_buf(c->pool, - cscf->proxy_buffer_size); + s->proxy->buffer = ngx_create_temp_buf(c->pool, pcf->buffer_size); if (s->proxy->buffer == NULL) { ngx_imap_proxy_internal_server_error(s); return; @@ -247,7 +263,7 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) break; } - if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) { + if (c->send(c, line.data, line.len) < (ssize_t) line.len) { /* * we treat the incomplete sending as NGX_ERROR * because it is very strange here @@ -265,6 +281,8 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) rev->handler = ngx_imap_proxy_handler; c->write->handler = ngx_imap_proxy_handler; + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); ngx_del_timer(c->read); } } @@ -273,12 +291,12 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) static void ngx_imap_proxy_pop3_handler(ngx_event_t *rev) { - u_char *p; - ngx_int_t rc; - ngx_str_t line; - ngx_connection_t *c; - ngx_imap_session_t *s; - ngx_imap_core_srv_conf_t *cscf; + u_char *p; + ngx_int_t rc; + ngx_str_t line; + ngx_connection_t *c; + ngx_imap_session_t *s; + ngx_imap_proxy_conf_t *pcf; ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, "imap proxy pop3 auth handler"); @@ -294,10 +312,9 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev) } if (s->proxy->buffer == NULL) { - cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); - s->proxy->buffer = ngx_create_temp_buf(c->pool, - cscf->proxy_buffer_size); + s->proxy->buffer = ngx_create_temp_buf(c->pool, pcf->buffer_size); if (s->proxy->buffer == NULL) { ngx_imap_proxy_internal_server_error(s); return; @@ -369,7 +386,7 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev) break; } - if (ngx_send(c, line.data, line.len) < (ssize_t) line.len) { + if (c->send(c, line.data, line.len) < (ssize_t) line.len) { /* * we treat the incomplete sending as NGX_ERROR * because it is very strange here @@ -387,6 +404,8 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev) rev->handler = ngx_imap_proxy_handler; c->write->handler = ngx_imap_proxy_handler; + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); ngx_del_timer(c->read); } } @@ -408,7 +427,8 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) b = s->proxy->buffer; - n = ngx_recv(s->proxy->upstream.connection, b->last, b->end - b->last); + n = s->proxy->upstream.connection->recv(s->proxy->upstream.connection, + b->last, b->end - b->last); if (n == NGX_ERROR || n == 0) { return NGX_ERROR; @@ -475,12 +495,13 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) static void ngx_imap_proxy_handler(ngx_event_t *ev) { - size_t size; - ssize_t n; - ngx_buf_t *b; - ngx_uint_t again, do_write; - ngx_connection_t *c, *src, *dst; - ngx_imap_session_t *s; + size_t size; + ssize_t n; + ngx_buf_t *b; + ngx_uint_t again, do_write; + ngx_connection_t *c, *src, *dst; + ngx_imap_session_t *s; + ngx_imap_proxy_conf_t *pcf; c = ev->data; s = c->data; @@ -537,7 +558,7 @@ ngx_imap_proxy_handler(ngx_event_t *ev) size = b->last - b->pos; if (size && dst->write->ready) { - n = ngx_send(dst, b->pos, size); + n = dst->send(dst, b->pos, size); if (n == NGX_ERROR) { ngx_imap_proxy_close_session(s); @@ -568,7 +589,7 @@ ngx_imap_proxy_handler(ngx_event_t *ev) size = b->end - b->last; if (size && src->read->ready) { - n = ngx_recv(src, b->last, size); + n = src->recv(src, b->last, size); if (n == NGX_ERROR || n == 0) { ngx_imap_proxy_close_session(s); @@ -587,6 +608,11 @@ ngx_imap_proxy_handler(ngx_event_t *ev) return; } } + + if (c == s->connection) { + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(c->read, pcf->timeout); + } } } while (again); @@ -634,6 +660,8 @@ ngx_imap_proxy_create_conf(ngx_conf_t *cf) } pcf->enable = NGX_CONF_UNSET; + pcf->buffer_size = NGX_CONF_UNSET_SIZE; + pcf->timeout = NGX_CONF_UNSET_MSEC; return pcf; } @@ -645,7 +673,10 @@ ngx_imap_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_imap_proxy_conf_t *prev = parent; ngx_imap_proxy_conf_t *conf = child; - ngx_conf_merge_msec_value(conf->enable, prev->enable, 0); + ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, + (size_t) ngx_pagesize); + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 24 * 60 * 60000); return NGX_CONF_OK; } diff --git a/src/imap/ngx_imap_ssl_module.c b/src/imap/ngx_imap_ssl_module.c new file mode 100644 index 000000000..e5834a631 --- /dev/null +++ b/src/imap/ngx_imap_ssl_module.c @@ -0,0 +1,174 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_imap.h> + + +#define NGX_DEFLAUT_CERTIFICATE "cert.pem" +#define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem" + + +static void *ngx_imap_ssl_create_conf(ngx_conf_t *cf); +static char *ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child); + + +static ngx_command_t ngx_imap_ssl_commands[] = { + + { ngx_string("ssl"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, enable), + NULL }, + + { ngx_string("ssl_certificate"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, certificate), + NULL }, + + { ngx_string("ssl_certificate_key"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, certificate_key), + NULL }, + + { ngx_string("ssl_ciphers"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, ciphers), + NULL }, + + ngx_null_command +}; + + +static ngx_imap_module_t ngx_imap_ssl_module_ctx = { + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + ngx_imap_ssl_create_conf, /* create server configuration */ + ngx_imap_ssl_merge_conf /* merge server configuration */ +}; + + +ngx_module_t ngx_imap_ssl_module = { + NGX_MODULE_V1, + &ngx_imap_ssl_module_ctx, /* module context */ + ngx_imap_ssl_commands, /* module directives */ + NGX_IMAP_MODULE, /* module type */ + NULL, /* init module */ + NULL /* init process */ +}; + + +static void * +ngx_imap_ssl_create_conf(ngx_conf_t *cf) +{ + ngx_imap_ssl_conf_t *scf; + + scf = ngx_pcalloc(cf->pool, sizeof(ngx_imap_ssl_conf_t)); + if (scf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * scf->certificate.len = 0; + * scf->certificate.data = NULL; + * scf->certificate_key.len = 0; + * scf->certificate_key.data = NULL; + * scf->ciphers.len = 0; + * scf->ciphers.data = NULL; + */ + + scf->enable = NGX_CONF_UNSET; + + return scf; +} + + +static char * +ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_imap_ssl_conf_t *prev = parent; + ngx_imap_ssl_conf_t *conf = child; + + ngx_conf_merge_value(conf->enable, prev->enable, 0); + + if (conf->enable == 0) { + return NGX_CONF_OK; + } + + ngx_conf_merge_str_value(conf->certificate, prev->certificate, + NGX_DEFLAUT_CERTIFICATE); + + ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, + NGX_DEFLAUT_CERTIFICATE_KEY); + + ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, ""); + + + /* TODO: configure methods */ + + conf->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); + + if (conf->ssl_ctx == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_new() failed"); + return NGX_CONF_ERROR; + } + + if (ngx_pool_cleanup_add(cf->pool, ngx_ssl_cleanup_ctx, conf->ssl_ctx) + == NULL) + { + return NGX_CONF_ERROR; + } + + +#if 0 + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_ALL); + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(conf->ssl_ctx, SSL_OP_SINGLE_DH_USE); +#endif + + if (conf->ciphers.len) { + if (SSL_CTX_set_cipher_list(conf->ssl_ctx, + (const char *) conf->ciphers.data) == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &conf->ciphers); + } + } + + if (SSL_CTX_use_certificate_chain_file(conf->ssl_ctx, + (char *) conf->certificate.data) == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_use_certificate_chain_file(\"%s\") failed", + conf->certificate.data); + return NGX_CONF_ERROR; + } + + + if (SSL_CTX_use_PrivateKey_file(conf->ssl_ctx, + (char *) conf->certificate_key.data, + SSL_FILETYPE_PEM) == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_use_PrivateKey_file(\"%s\") failed", + conf->certificate_key.data); + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} diff --git a/src/imap/ngx_imap_ssl_module.h b/src/imap/ngx_imap_ssl_module.h new file mode 100644 index 000000000..150a61755 --- /dev/null +++ b/src/imap/ngx_imap_ssl_module.h @@ -0,0 +1,30 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_IMAP_SSL_H_INCLUDED_ +#define _NGX_IMAP_SSL_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_imap.h> + + +typedef struct { + ngx_flag_t enable; + ngx_str_t certificate; + ngx_str_t certificate_key; + + ngx_str_t ciphers; + + ngx_ssl_ctx_t *ssl_ctx; +} ngx_imap_ssl_conf_t; + + +extern ngx_module_t ngx_imap_ssl_module; + + +#endif /* _NGX_IMAP_SSL_H_INCLUDED_ */ |
