diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-12-05 16:18:09 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-12-05 16:18:09 +0300 |
commit | d3283ff9224a41a1a24c2d89f671811c0747480a (patch) | |
tree | e122c436f72f587622e8ec0e75632434045e330d /src/imap | |
parent | 0624ed3d7eaa1995d9e5ec4292bd1eccda09cafc (diff) |
nginx-0.3.13-RELEASE importrelease-0.3.13
*) Feature: the IMAP/POP3 proxy supports STARTTLS and STLS.
*) Bugfix: the IMAP/POP3 proxy did not work with the select, poll, and
/dev/poll methods.
*) Bugfix: in SSI handling.
*) Bugfix: now Solaris sendfilev() is not used to transfer the client
request body to FastCGI-server via the unix domain socket.
*) Bugfix: the "auth_basic" directive did not disable the
authorization; the bug had appeared in 0.3.11.
Diffstat (limited to 'src/imap')
-rw-r--r-- | src/imap/ngx_imap.h | 56 | ||||
-rw-r--r-- | src/imap/ngx_imap_auth_http_module.c | 4 | ||||
-rw-r--r-- | src/imap/ngx_imap_core_module.c | 84 | ||||
-rw-r--r-- | src/imap/ngx_imap_handler.c | 196 | ||||
-rw-r--r-- | src/imap/ngx_imap_parse.c | 25 | ||||
-rw-r--r-- | src/imap/ngx_imap_proxy_module.c | 122 | ||||
-rw-r--r-- | src/imap/ngx_imap_ssl_module.c | 20 | ||||
-rw-r--r-- | src/imap/ngx_imap_ssl_module.h | 6 |
8 files changed, 389 insertions, 124 deletions
diff --git a/src/imap/ngx_imap.h b/src/imap/ngx_imap.h index fed6852b1..1f3c12eea 100644 --- a/src/imap/ngx_imap.h +++ b/src/imap/ngx_imap.h @@ -20,13 +20,13 @@ typedef struct { - void **main_conf; - void **srv_conf; + void **main_conf; + void **srv_conf; } ngx_imap_conf_ctx_t; typedef struct { - ngx_array_t servers; /* ngx_imap_core_srv_conf_t */ + ngx_array_t servers; /* ngx_imap_core_srv_conf_t */ } ngx_imap_core_main_conf_t; @@ -34,17 +34,20 @@ typedef struct { #define NGX_IMAP_IMAP_PROTOCOL 1 typedef struct { - ngx_msec_t timeout; + ngx_msec_t timeout; - size_t imap_client_buffer_size; + size_t imap_client_buffer_size; - ngx_uint_t protocol; + ngx_uint_t protocol; - ngx_buf_t *pop3_capability; - ngx_buf_t *imap_capability; + ngx_str_t pop3_capability; + ngx_str_t pop3_starttls_capability; + ngx_str_t imap_capability; + ngx_str_t imap_starttls_capability; + ngx_str_t imap_starttls_only_capability; - ngx_array_t pop3_capabilities; - ngx_array_t imap_capabilities; + ngx_array_t pop3_capabilities; + ngx_array_t imap_capabilities; /* server ctx */ ngx_imap_conf_ctx_t *ctx; @@ -52,11 +55,12 @@ typedef struct { typedef struct { - void *(*create_main_conf)(ngx_conf_t *cf); - char *(*init_main_conf)(ngx_conf_t *cf, void *conf); + void *(*create_main_conf)(ngx_conf_t *cf); + char *(*init_main_conf)(ngx_conf_t *cf, void *conf); - void *(*create_srv_conf)(ngx_conf_t *cf); - char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf); + void *(*create_srv_conf)(ngx_conf_t *cf); + char *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, + void *conf); } ngx_imap_module_t; @@ -126,8 +130,8 @@ typedef struct { typedef struct { - ngx_str_t *client; - ngx_imap_session_t *session; + ngx_str_t *client; + ngx_imap_session_t *session; } ngx_imap_log_ctx_t; @@ -136,22 +140,24 @@ typedef struct { #define NGX_POP3_CAPA 3 #define NGX_POP3_QUIT 4 #define NGX_POP3_NOOP 5 -#define NGX_POP3_APOP 6 -#define NGX_POP3_STAT 7 -#define NGX_POP3_LIST 8 -#define NGX_POP3_RETR 9 -#define NGX_POP3_DELE 10 -#define NGX_POP3_RSET 11 -#define NGX_POP3_TOP 12 -#define NGX_POP3_UIDL 13 +#define NGX_POP3_STLS 6 +#define NGX_POP3_APOP 7 +#define NGX_POP3_STAT 8 +#define NGX_POP3_LIST 9 +#define NGX_POP3_RETR 10 +#define NGX_POP3_DELE 11 +#define NGX_POP3_RSET 12 +#define NGX_POP3_TOP 13 +#define NGX_POP3_UIDL 14 #define NGX_IMAP_LOGIN 1 #define NGX_IMAP_LOGOUT 2 #define NGX_IMAP_CAPABILITY 3 #define NGX_IMAP_NOOP 4 +#define NGX_IMAP_STARTTLS 5 -#define NGX_IMAP_NEXT 5 +#define NGX_IMAP_NEXT 6 #define NGX_IMAP_PARSE_INVALID_COMMAND 20 diff --git a/src/imap/ngx_imap_auth_http_module.c b/src/imap/ngx_imap_auth_http_module.c index 75350d5ad..cedb0d830 100644 --- a/src/imap/ngx_imap_auth_http_module.c +++ b/src/imap/ngx_imap_auth_http_module.c @@ -727,7 +727,7 @@ ngx_imap_auth_sleep_handler(ngx_event_t *rev) ngx_imap_send(s->connection->write); - if (c->closed) { + if (c->destroyed) { return; } @@ -1181,6 +1181,8 @@ ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + ahcf->peers->number = 1; + ahcf->host_header = inet_upstream.host_header; ahcf->uri = inet_upstream.uri; } diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c index 6408e5401..e805a8161 100644 --- a/src/imap/ngx_imap_core_module.c +++ b/src/imap/ngx_imap_core_module.c @@ -181,8 +181,8 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_imap_core_srv_conf_t *prev = parent; ngx_imap_core_srv_conf_t *conf = child; + u_char *p; size_t size; - ngx_buf_t *b; ngx_str_t *c, *d; ngx_uint_t i; @@ -218,22 +218,40 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) size += c[i].len + sizeof(CRLF) - 1; } - b = ngx_create_temp_buf(cf->pool, size); - if (b == NULL) { + p = ngx_palloc(cf->pool, size); + if (p == NULL) { return NGX_CONF_ERROR; } - b->last = ngx_cpymem(b->last, "+OK Capability list follows" CRLF, - sizeof("+OK Capability list follows" CRLF) - 1); + conf->pop3_capability.len = size; + conf->pop3_capability.data = p; + + p = ngx_cpymem(p, "+OK Capability list follows" CRLF, + sizeof("+OK Capability list follows" CRLF) - 1); for (i = 0; i < conf->pop3_capabilities.nelts; i++) { - b->last = ngx_cpymem(b->last, c[i].data, c[i].len); - *b->last++ = CR; *b->last++ = LF; + p = ngx_cpymem(p, c[i].data, c[i].len); + *p++ = CR; *p++ = LF; + } + + *p++ = '.'; *p++ = CR; *p = LF; + + + size += sizeof("STLS" CRLF) - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; } - *b->last++ = '.'; *b->last++ = CR; *b->last++ = LF; + conf->pop3_starttls_capability.len = size; + conf->pop3_starttls_capability.data = p; + + p = ngx_cpymem(p, conf->pop3_capability.data, + conf->pop3_capability.len - (sizeof("." CRLF) - 1)); - conf->pop3_capability = b; + p = ngx_cpymem(p, "STLS" CRLF, sizeof("STLS" CRLF) - 1); + *p++ = '.'; *p++ = CR; *p = LF; if (conf->imap_capabilities.nelts == 0) { @@ -259,21 +277,55 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) size += 1 + c[i].len; } - b = ngx_create_temp_buf(cf->pool, size); - if (b == NULL) { + p = ngx_palloc(cf->pool, size); + if (p == NULL) { return NGX_CONF_ERROR; } - b->last = ngx_cpymem(b->last, "* CAPABILITY", sizeof("* CAPABILITY") - 1); + conf->imap_capability.len = size; + conf->imap_capability.data = p; + + p = ngx_cpymem(p, "* CAPABILITY", sizeof("* CAPABILITY") - 1); for (i = 0; i < conf->imap_capabilities.nelts; i++) { - *b->last++ = ' '; - b->last = ngx_cpymem(b->last, c[i].data, c[i].len); + *p++ = ' '; + p = ngx_cpymem(p, c[i].data, c[i].len); } - *b->last++ = CR; *b->last++ = LF; + *p++ = CR; *p = LF; + + + size += sizeof(" STARTTLS") - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->imap_starttls_capability.len = size; + conf->imap_starttls_capability.data = p; + + p = ngx_cpymem(p, conf->imap_capability.data, + conf->imap_capability.len - (sizeof(CRLF) - 1)); + p = ngx_cpymem(p, " STARTTLS", sizeof(" STARTTLS") - 1); + *p++ = CR; *p = LF; + + + size += sizeof(" LOGINDISABLED") - 1; + + p = ngx_palloc(cf->pool, size); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + conf->imap_starttls_only_capability.len = size; + conf->imap_starttls_only_capability.data = p; + + p = ngx_cpymem(p, conf->imap_starttls_capability.data, + conf->imap_starttls_capability.len - (sizeof(CRLF) - 1)); + p = ngx_cpymem(p, " LOGINDISABLED", sizeof(" LOGINDISABLED") - 1); + *p++ = CR; *p = LF; - conf->imap_capability = b; return NGX_CONF_OK; } diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c index ddff96a29..f90b96880 100644 --- a/src/imap/ngx_imap_handler.c +++ b/src/imap/ngx_imap_handler.c @@ -16,6 +16,7 @@ static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s); static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len); #if (NGX_IMAP_SSL) +static void ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); static void ngx_imap_ssl_handshake_handler(ngx_connection_t *c); #endif @@ -43,11 +44,10 @@ static u_char imap_invalid_command[] = "BAD invalid command" CRLF; void ngx_imap_init_connection(ngx_connection_t *c) { - ngx_imap_log_ctx_t *lctx; + ngx_imap_log_ctx_t *lctx; #if (NGX_IMAP_SSL) - ngx_imap_conf_ctx_t *ctx; - ngx_imap_ssl_conf_t *sslcf; - ngx_imap_core_srv_conf_t *cscf; + ngx_imap_conf_ctx_t *ctx; + ngx_imap_ssl_conf_t *sslcf; #endif ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", @@ -75,44 +75,82 @@ ngx_imap_init_connection(ngx_connection_t *c) sslcf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_ssl_module); if (sslcf->enable) { - if (ngx_ssl_create_connection(&sslcf->ssl, c, 0) == NGX_ERROR) { - ngx_imap_close_connection(c); - return; - } + ngx_imap_ssl_init_connection(&sslcf->ssl, c); + return; + } - if (ngx_ssl_handshake(c) == NGX_AGAIN) { +#endif - cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); + ngx_imap_init_session(c); +} - ngx_add_timer(c->read, cscf->timeout); - c->ssl->handler = ngx_imap_ssl_handshake_handler; +#if (NGX_IMAP_SSL) - return; - } +static void +ngx_imap_starttls_handler(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_imap_session_t *s; + ngx_imap_ssl_conf_t *sslcf; + + c = rev->data; + s = c->data; + + c->log->action = "in starttls state"; - ngx_imap_ssl_handshake_handler(c); + sslcf = ngx_imap_get_module_srv_conf(s, ngx_imap_ssl_module); + + ngx_imap_ssl_init_connection(&sslcf->ssl, c); +} + + +static void +ngx_imap_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) +{ + ngx_imap_conf_ctx_t *ctx; + ngx_imap_core_srv_conf_t *cscf; + + if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { + ngx_imap_close_connection(c); return; } -#endif + if (ngx_ssl_handshake(c) == NGX_AGAIN) { - ngx_imap_init_session(c); -} + ctx = c->ctx; + cscf = ngx_imap_get_module_srv_conf(ctx, ngx_imap_core_module); + ngx_add_timer(c->read, cscf->timeout); + + c->ssl->handler = ngx_imap_ssl_handshake_handler; + + return; + } + + ngx_imap_ssl_handshake_handler(c); +} -#if (NGX_IMAP_SSL) static void ngx_imap_ssl_handshake_handler(ngx_connection_t *c) { if (c->ssl->handshaked) { + + if (c->data) { + c->read->handler = ngx_imap_init_protocol; + c->write->handler = ngx_imap_send; + + ngx_imap_init_protocol(c->read); + + return; + } + ngx_imap_init_session(c); return; } ngx_imap_close_connection(c); - return; } #endif @@ -253,11 +291,6 @@ ngx_imap_init_protocol(ngx_event_t *rev) 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; - } - if (s->protocol == NGX_IMAP_POP3_PROTOCOL) { size = 128; s->imap_state = ngx_pop3_start; @@ -270,10 +303,19 @@ ngx_imap_init_protocol(ngx_event_t *rev) c->read->handler = ngx_imap_auth_state; } - s->buffer = ngx_create_temp_buf(c->pool, size); if (s->buffer == NULL) { - ngx_imap_session_internal_server_error(s); - return; + if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) + == NGX_ERROR) + { + ngx_imap_session_internal_server_error(s); + return; + } + + s->buffer = ngx_create_temp_buf(c->pool, size); + if (s->buffer == NULL) { + ngx_imap_session_internal_server_error(s); + return; + } } c->read->handler(rev); @@ -291,6 +333,9 @@ ngx_imap_auth_state(ngx_event_t *rev) ngx_connection_t *c; ngx_imap_session_t *s; ngx_imap_core_srv_conf_t *cscf; +#if (NGX_IMAP_SSL) + ngx_imap_ssl_conf_t *sslcf; +#endif c = rev->data; s = c->data; @@ -357,6 +402,19 @@ ngx_imap_auth_state(ngx_event_t *rev) switch (s->command) { case NGX_IMAP_LOGIN: + +#if (NGX_IMAP_SSL) + + if (c->ssl == NULL) { + sslcf = ngx_imap_get_module_srv_conf(s, ngx_imap_ssl_module); + + if (sslcf->starttls == NGX_IMAP_STARTTLS_ONLY) { + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + } +#endif + arg = s->args.elts; if (s->args.nelts == 2 && arg[0].len) { @@ -410,8 +468,28 @@ ngx_imap_auth_state(ngx_event_t *rev) case NGX_IMAP_CAPABILITY: cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); - text = cscf->imap_capability->pos; - text_len = cscf->imap_capability->last - cscf->imap_capability->pos; + +#if (NGX_IMAP_SSL) + + if (c->ssl == NULL) { + sslcf = ngx_imap_get_module_srv_conf(s, ngx_imap_ssl_module); + + if (sslcf->starttls == NGX_IMAP_STARTTLS_ON) { + text_len = cscf->imap_starttls_capability.len; + text = cscf->imap_starttls_capability.data; + break; + } + + if (sslcf->starttls == NGX_IMAP_STARTTLS_ONLY) { + text_len = cscf->imap_starttls_only_capability.len; + text = cscf->imap_starttls_only_capability.data; + break; + } + } +#endif + + text_len = cscf->imap_capability.len; + text = cscf->imap_capability.data; break; case NGX_IMAP_LOGOUT: @@ -423,6 +501,21 @@ ngx_imap_auth_state(ngx_event_t *rev) case NGX_IMAP_NOOP: break; +#if (NGX_IMAP_SSL) + + case NGX_IMAP_STARTTLS: + if (c->ssl == NULL) { + sslcf = ngx_imap_get_module_srv_conf(s, ngx_imap_ssl_module); + if (sslcf->starttls) { + c->read->handler = ngx_imap_starttls_handler; + break; + } + } + + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; +#endif + default: rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; @@ -492,6 +585,9 @@ ngx_pop3_auth_state(ngx_event_t *rev) ngx_connection_t *c; ngx_imap_session_t *s; ngx_imap_core_srv_conf_t *cscf; +#if (NGX_IMAP_SSL) + ngx_imap_ssl_conf_t *sslcf; +#endif c = rev->data; s = c->data; @@ -554,8 +650,22 @@ ngx_pop3_auth_state(ngx_event_t *rev) case NGX_POP3_CAPA: cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); - text = cscf->pop3_capability->pos; - size = cscf->pop3_capability->last - cscf->pop3_capability->pos; + +#if (NGX_IMAP_SSL) + + if (c->ssl == NULL) { + sslcf = ngx_imap_get_module_srv_conf(s, + ngx_imap_ssl_module); + if (sslcf->starttls) { + size = cscf->pop3_starttls_capability.len; + text = cscf->pop3_starttls_capability.data; + break; + } + } +#endif + + size = cscf->pop3_capability.len; + text = cscf->pop3_capability.data; break; case NGX_POP3_QUIT: @@ -565,6 +675,22 @@ ngx_pop3_auth_state(ngx_event_t *rev) case NGX_POP3_NOOP: break; +#if (NGX_IMAP_SSL) + + case NGX_POP3_STLS: + if (c->ssl == NULL) { + sslcf = ngx_imap_get_module_srv_conf(s, + ngx_imap_ssl_module); + if (sslcf->starttls) { + c->read->handler = ngx_imap_starttls_handler; + break; + } + } + + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; +#endif + default: s->imap_state = ngx_pop3_start; rc = NGX_IMAP_PARSE_INVALID_COMMAND; @@ -616,8 +742,8 @@ ngx_pop3_auth_state(ngx_event_t *rev) case NGX_POP3_CAPA: cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); - text = cscf->pop3_capability->pos; - size = cscf->pop3_capability->last - cscf->pop3_capability->pos; + size = cscf->pop3_capability.len; + text = cscf->pop3_capability.data; break; case NGX_POP3_QUIT: @@ -735,7 +861,7 @@ ngx_imap_close_connection(ngx_connection_t *c) #endif - c->closed = 1; + c->destroyed = 1; pool = c->pool; diff --git a/src/imap/ngx_imap_parse.c b/src/imap/ngx_imap_parse.c index d8c436b87..eea4550a8 100644 --- a/src/imap/ngx_imap_parse.c +++ b/src/imap/ngx_imap_parse.c @@ -119,6 +119,25 @@ ngx_int_t ngx_imap_parse_command(ngx_imap_session_t *s) } break; +#if (NGX_IMAP_SSL) + case 8: + if ((c[0] == 'S'|| c[0] == 's') + && (c[1] == 'T'|| c[1] == 't') + && (c[2] == 'A'|| c[2] == 'a') + && (c[3] == 'R'|| c[3] == 'r') + && (c[4] == 'T'|| c[4] == 't') + && (c[5] == 'T'|| c[5] == 't') + && (c[6] == 'L'|| c[6] == 'l') + && (c[7] == 'S'|| c[7] == 's')) + { + s->command = NGX_IMAP_STARTTLS; + + } else { + goto invalid; + } + break; +#endif + case 10: if ((c[0] == 'C'|| c[0] == 'c') && (c[1] == 'A'|| c[1] == 'a') @@ -421,7 +440,11 @@ ngx_int_t ngx_pop3_parse_command(ngx_imap_session_t *s) } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P') { s->command = NGX_POP3_NOOP; - +#if (NGX_IMAP_SSL) + } else if (c0 == 'S' && c1 == 'T' && c2 == 'L' && c3 == 'S') + { + s->command = NGX_POP3_STLS; +#endif } else { goto invalid; } diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c index 62329607f..bdce364b9 100644 --- a/src/imap/ngx_imap_proxy_module.c +++ b/src/imap/ngx_imap_proxy_module.c @@ -286,8 +286,6 @@ ngx_imap_proxy_imap_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - - c->log->action = "proxying"; } } @@ -405,16 +403,24 @@ ngx_imap_proxy_pop3_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - - c->log->action = "proxying"; } } static void -ngx_imap_proxy_dummy_handler(ngx_event_t *ev) +ngx_imap_proxy_dummy_handler(ngx_event_t *wev) { - ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, "imap proxy dummy handler"); + ngx_connection_t *c; + ngx_imap_session_t *s; + + ngx_log_debug0(NGX_LOG_DEBUG_IMAP, wev->log, 0, "imap proxy dummy handler"); + + if (ngx_handle_write_event(wev, 0) == NGX_ERROR) { + c = wev->data; + s = c->data; + + ngx_imap_proxy_close_session(s); + } } @@ -487,11 +493,11 @@ ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) static void ngx_imap_proxy_handler(ngx_event_t *ev) { - char *action; + char *action, *recv_action, *send_action; size_t size; ssize_t n; ngx_buf_t *b; - ngx_uint_t again, do_write; + ngx_uint_t do_write; ngx_connection_t *c, *src, *dst; ngx_imap_session_t *s; ngx_imap_proxy_conf_t *pcf; @@ -500,6 +506,8 @@ ngx_imap_proxy_handler(ngx_event_t *ev) s = c->data; if (ev->timedout) { + c->log->action = "proxying"; + if (c == s->connection) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); @@ -516,11 +524,15 @@ ngx_imap_proxy_handler(ngx_event_t *ev) if (c == s->connection) { if (ev->write) { + recv_action = "proxying and reading from upstream"; + send_action = "proxying and sending to client"; src = s->proxy->upstream.connection; dst = c; b = s->proxy->buffer; } else { + recv_action = "proxying and reading from client"; + send_action = "proxying and sending to upstream"; src = c; dst = s->proxy->upstream.connection; b = s->buffer; @@ -528,11 +540,15 @@ ngx_imap_proxy_handler(ngx_event_t *ev) } else { if (ev->write) { + recv_action = "proxying and reading from upstream"; + send_action = "proxying and sending to client"; src = s->connection; dst = c; b = s->buffer; } else { + recv_action = "proxying and reading from client"; + send_action = "proxying and sending to upstream"; src = c; dst = s->connection; b = s->proxy->buffer; @@ -545,14 +561,15 @@ ngx_imap_proxy_handler(ngx_event_t *ev) "imap proxy handler: %d, #%d > #%d", do_write, src->fd, dst->fd); - do { - again = 0; + for ( ;; ) { - if (do_write == 1) { + if (do_write) { size = b->last - b->pos; if (size && dst->write->ready) { + c->log->action = send_action; + n = dst->send(dst, b->pos, size); if (n == NGX_ERROR) { @@ -561,7 +578,6 @@ ngx_imap_proxy_handler(ngx_event_t *ev) } if (n > 0) { - again = 1; b->pos += n; if (b->pos == b->last) { @@ -569,58 +585,74 @@ ngx_imap_proxy_handler(ngx_event_t *ev) b->last = b->start; } } - - if (n == NGX_AGAIN || n < (ssize_t) size) { - if (ngx_handle_write_event(dst->write, /* TODO: LOWAT */ 0) - == NGX_ERROR) - { - ngx_imap_proxy_close_session(s); - return; - } - } } } size = b->end - b->last; if (size && src->read->ready) { - n = src->recv(src, b->last, size); - - if (n == NGX_ERROR) { - ngx_imap_proxy_close_session(s); - return; - } + c->log->action = recv_action; - if (n == 0) { - action = c->log->action; - c->log->action = NULL; - ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); - c->log->action = action; + n = src->recv(src, b->last, size); - ngx_imap_proxy_close_session(s); - return; + if (n == NGX_AGAIN || n == 0) { + break; } if (n > 0) { - again = 1; do_write = 1; b->last += n; - } - if (n == NGX_AGAIN || n < (ssize_t) size) { - if (ngx_handle_read_event(src->read, 0) == NGX_ERROR) { - ngx_imap_proxy_close_session(s); - return; - } + continue; } - if (c == s->connection) { - pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); - ngx_add_timer(c->read, pcf->timeout); + if (n == NGX_ERROR) { + src->read->eof = 1; } } - } while (again); + break; + } + + c->log->action = "proxying"; + + if ((s->connection->read->eof || s->proxy->upstream.connection->read->eof) + && s->buffer->pos == s->buffer->last + && s->proxy->buffer->pos == s->proxy->buffer->last) + { + action = c->log->action; + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxied session done"); + c->log->action = action; + + ngx_imap_proxy_close_session(s); + return; + } + + if (ngx_handle_write_event(dst->write, 0) == NGX_ERROR) { + ngx_imap_proxy_close_session(s); + return; + } + + if (ngx_handle_read_event(dst->read, 0) == NGX_ERROR) { + ngx_imap_proxy_close_session(s); + return; + } + + if (ngx_handle_write_event(src->write, 0) == NGX_ERROR) { + ngx_imap_proxy_close_session(s); + return; + } + + if (ngx_handle_read_event(src->read, 0) == NGX_ERROR) { + ngx_imap_proxy_close_session(s); + return; + } + + if (c == s->connection) { + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(c->read, pcf->timeout); + } } diff --git a/src/imap/ngx_imap_ssl_module.c b/src/imap/ngx_imap_ssl_module.c index cbbbb6802..cb2b8caf5 100644 --- a/src/imap/ngx_imap_ssl_module.c +++ b/src/imap/ngx_imap_ssl_module.c @@ -27,6 +27,15 @@ static char ngx_imap_ssl_openssl097[] = "OpenSSL 0.9.7 and higher"; #endif +static ngx_conf_enum_t ngx_http_starttls_state[] = { + { ngx_string("off"), NGX_IMAP_STARTTLS_OFF }, + { ngx_string("on"), NGX_IMAP_STARTTLS_ON }, + { ngx_string("only"), NGX_IMAP_STARTTLS_ONLY }, + { ngx_null_string, 0 } +}; + + + static ngx_conf_bitmask_t ngx_imap_ssl_protocols[] = { { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, @@ -44,6 +53,13 @@ static ngx_command_t ngx_imap_ssl_commands[] = { offsetof(ngx_imap_ssl_conf_t, enable), NULL }, + { ngx_string("starttls"), + NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_IMAP_SRV_CONF_OFFSET, + offsetof(ngx_imap_ssl_conf_t, starttls), + ngx_http_starttls_state }, + { ngx_string("ssl_certificate"), NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -146,6 +162,7 @@ ngx_imap_ssl_create_conf(ngx_conf_t *cf) */ scf->enable = NGX_CONF_UNSET; + scf->starttls = NGX_CONF_UNSET; scf->session_timeout = NGX_CONF_UNSET; scf->prefer_server_ciphers = NGX_CONF_UNSET; @@ -162,8 +179,9 @@ ngx_imap_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_pool_cleanup_t *cln; ngx_conf_merge_value(conf->enable, prev->enable, 0); + ngx_conf_merge_value(conf->starttls, prev->starttls, NGX_IMAP_STARTTLS_OFF); - if (conf->enable == 0) { + if (conf->enable == 0 && conf->starttls == NGX_IMAP_STARTTLS_OFF) { return NGX_CONF_OK; } diff --git a/src/imap/ngx_imap_ssl_module.h b/src/imap/ngx_imap_ssl_module.h index 2ac9f119e..7b05bce5c 100644 --- a/src/imap/ngx_imap_ssl_module.h +++ b/src/imap/ngx_imap_ssl_module.h @@ -13,12 +13,18 @@ #include <ngx_imap.h> +#define NGX_IMAP_STARTTLS_OFF 0 +#define NGX_IMAP_STARTTLS_ON 1 +#define NGX_IMAP_STARTTLS_ONLY 2 + + typedef struct { ngx_flag_t enable; ngx_ssl_t ssl; ngx_flag_t prefer_server_ciphers; + ngx_flag_t starttls; ngx_uint_t protocols; |