nginx-0.1.44-RELEASE import
*) Feature: the IMAP/POP3 proxy supports SSL.
*) Feature: the "proxy_timeout" directive of the ngx_imap_proxy_module.
*) Feature: the "userid_mark" directive.
*) Feature: the $remote_user variable value is determined independently
of authorization use.
diff --git a/src/imap/ngx_imap.h b/src/imap/ngx_imap.h
index 8a506db..5e03774 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 @@
ngx_msec_t timeout;
size_t imap_client_buffer_size;
- size_t proxy_buffer_size;
ngx_uint_t protocol;
@@ -82,8 +86,8 @@
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 @@
ngx_uint_t imap_state;
+ unsigned blocked:1;
+ unsigned quit:1;
unsigned protocol:1;
unsigned quoted:1;
@@ -100,6 +106,7 @@
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 @@
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 e66593a..2bf0cc9 100644
--- a/src/imap/ngx_imap_auth_http_module.c
+++ b/src/imap/ngx_imap_auth_http_module.c
@@ -516,13 +516,14 @@
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 e5d7a20..8225574 100644
--- a/src/imap/ngx_imap_core_module.c
+++ b/src/imap/ngx_imap_core_module.c
@@ -75,13 +75,6 @@
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 @@
}
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_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 25509b2..03dedaf 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 @@
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 @@
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)
- if (ngx_send(c, greetings[cscf->protocol].data, size) < size) {
- /*
- * we treat the incomplete sending as NGX_ERROR
- * because it is very strange here
- */
+ 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;
+ }
+
+#endif
+
+ s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
+ if (s == NULL) {
ngx_imap_close_connection(c);
return;
}
- c->read->handler = ngx_imap_init_session;
+ 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 @@
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 @@
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 @@
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 @@
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 @@
return;
}
- quit = 0;
tag = 1;
text = NULL;
@@ -235,9 +326,9 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
break;
case NGX_POP3_QUIT:
- quit = 1;
+ s->quit = 1;
break;
case NGX_POP3_NOOP:
@@ -441,7 +524,7 @@
break;
case NGX_POP3_QUIT:
- quit = 1;
+ s->quit = 1;
break;
case NGX_POP3_NOOP:
@@ -466,23 +549,14 @@
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 @@
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 @@
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_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 be32e6f..f9a84ce 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 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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_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 0000000..e5834a6
--- /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 0000000..150a617
--- /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_ */