Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/imap
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-12-05 16:18:09 +0300
committerIgor Sysoev <igor@sysoev.ru>2005-12-05 16:18:09 +0300
commitd3283ff9224a41a1a24c2d89f671811c0747480a (patch)
treee122c436f72f587622e8ec0e75632434045e330d /src/imap
parent0624ed3d7eaa1995d9e5ec4292bd1eccda09cafc (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.h56
-rw-r--r--src/imap/ngx_imap_auth_http_module.c4
-rw-r--r--src/imap/ngx_imap_core_module.c84
-rw-r--r--src/imap/ngx_imap_handler.c196
-rw-r--r--src/imap/ngx_imap_parse.c25
-rw-r--r--src/imap/ngx_imap_proxy_module.c122
-rw-r--r--src/imap/ngx_imap_ssl_module.c20
-rw-r--r--src/imap/ngx_imap_ssl_module.h6
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;