[PATCH] SSL support for the mail proxy module
Kunal Pariani
kpariani at zimbra.com
Tue Aug 19 22:58:15 UTC 2014
# HG changeset patch
# User Kunal Pariani <kpariani at zimbra.com>
# Date 1408485440 25200
# Tue Aug 19 14:57:20 2014 -0700
# Node ID 7858c2a9ac0e83aa779197fc028b4d078612e7e8
# Parent f25ab24517bb5e45b1b7fa1a1502b907f2cff213
SSL support for the mail proxy
diff -r f25ab24517bb -r 7858c2a9ac0e src/mail/ngx_mail_proxy_module.c
--- a/src/mail/ngx_mail_proxy_module.c Mon Aug 04 16:26:30 2014 -0700
+++ b/src/mail/ngx_mail_proxy_module.c Tue Aug 19 14:57:20 2014 -0700
@@ -18,6 +18,8 @@
ngx_flag_t xclient;
size_t buffer_size;
ngx_msec_t timeout;
+ ngx_flag_t proxy_ssl;
+ ngx_ssl_t *ssl;
} ngx_mail_proxy_conf_t;
@@ -35,7 +37,13 @@
static void *ngx_mail_proxy_create_conf(ngx_conf_t *cf);
static char *ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent,
void *child);
-
+#if (NGX_MAIL_SSL)
+static char *ngx_mail_proxy_ssl(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static void ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s,
+ ngx_connection_t *c);
+static void ngx_mail_proxy_ssl_handshake(ngx_connection_t *c);
+#endif
static ngx_command_t ngx_mail_proxy_commands[] = {
@@ -74,6 +82,16 @@
offsetof(ngx_mail_proxy_conf_t, xclient),
NULL },
+#if (NGX_MAIL_SSL)
+ { ngx_string("proxy_ssl"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
+ ngx_mail_proxy_ssl,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_proxy_conf_t, proxy_ssl),
+ NULL },
+
+#endif
+
ngx_null_command
};
@@ -174,6 +192,15 @@
s->out.len = 0;
+#if (NGX_MAIL_SSL)
+
+ if (pcf->proxy_ssl && p->upstream.connection->ssl == NULL) {
+ ngx_mail_proxy_ssl_init_connection(s, p->upstream.connection);
+ return;
+ }
+
+#endif
+
switch (s->protocol) {
case NGX_MAIL_POP3_PROTOCOL:
@@ -1092,6 +1119,13 @@
"close mail proxy connection: %d",
s->proxy->upstream.connection->fd);
+#if (NGX_MAIL_SSL)
+ if (s->proxy->upstream.connection->ssl) {
+ s->proxy->upstream.connection->ssl->no_wait_shutdown = 1;
+ ngx_ssl_shutdown(s->proxy->upstream.connection);
+ }
+#endif
+
ngx_close_connection(s->proxy->upstream.connection);
}
@@ -1114,6 +1148,8 @@
pcf->xclient = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
+ pcf->proxy_ssl = NGX_CONF_UNSET;
+ pcf->ssl = NGX_CONF_UNSET_PTR;
return pcf;
}
@@ -1131,6 +1167,118 @@
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);
+ ngx_conf_merge_value(conf->proxy_ssl, prev->proxy_ssl, 0);
+ ngx_conf_merge_ptr_value(conf->ssl, prev->ssl, NULL);
return NGX_CONF_OK;
}
+
+#if (NGX_MAIL_SSL)
+
+static char *
+ngx_mail_proxy_ssl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
+
+ ngx_pool_cleanup_t *cln;
+ char *rc;
+ ngx_mail_proxy_conf_t *pcf;
+
+ rc = ngx_conf_set_flag_slot(cf, cmd, conf);
+ if (rc != NGX_CONF_OK) {
+ return rc;
+ }
+
+ pcf = (ngx_mail_proxy_conf_t *)conf;
+
+ if (!pcf->proxy_ssl) {
+ return NGX_CONF_OK;
+ }
+
+ pcf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+
+ if (pcf->ssl == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pcf->ssl->log = cf->log;
+
+ // don't support SSLv2 anymore
+ if (ngx_ssl_create(pcf->ssl, NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
+ != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ cln = ngx_pool_cleanup_add(cf->pool, 0);
+ if (cln == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ cln->handler = ngx_ssl_cleanup_ctx;
+ cln->data = pcf->ssl;
+
+ return NGX_CONF_OK;
+}
+
+static void
+ngx_mail_proxy_ssl_init_connection(ngx_mail_session_t *s, ngx_connection_t *c)
+{
+ ngx_int_t rc;
+ ngx_mail_proxy_conf_t *pcf;
+
+ pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
+
+ if (ngx_ssl_create_connection(pcf->ssl, c,
+ NGX_SSL_BUFFER|NGX_SSL_CLIENT)
+ != NGX_OK)
+ {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ s->connection->log->action = "SSL handshaking to upstream";
+
+ rc = ngx_ssl_handshake(c);
+
+ if (rc == NGX_AGAIN) {
+ c->ssl->handler = ngx_mail_proxy_ssl_handshake;
+ return;
+ }
+
+ ngx_mail_proxy_ssl_handshake(c);
+}
+
+
+static void
+ngx_mail_proxy_ssl_handshake(ngx_connection_t *c)
+{
+ ngx_mail_session_t *s;
+ s = c->data;
+
+ if (c->ssl->handshaked) {
+ c->write->handler = ngx_mail_proxy_dummy_handler;
+ switch (s->protocol) {
+
+ case NGX_MAIL_POP3_PROTOCOL:
+ c->read->handler = ngx_mail_proxy_pop3_handler;
+ s->mail_state = ngx_pop3_start;
+ break;
+
+ case NGX_MAIL_IMAP_PROTOCOL:
+ c->read->handler = ngx_mail_proxy_imap_handler;
+ s->mail_state = ngx_imap_start;
+ break;
+
+ default: /* NGX_MAIL_SMTP_PROTOCOL */
+ c->read->handler = ngx_mail_proxy_smtp_handler;
+ s->mail_state = ngx_smtp_start;
+ break;
+ }
+
+ /* server might have sent the initial welcome msg */
+ c->read->handler(c->read);
+ } else {
+ /* when handshake fails, we should close the session */
+ ngx_mail_proxy_upstream_error(s);
+ }
+}
+
+#endif
Thanks
-Kunal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20140819/9d614093/attachment-0001.html>
More information about the nginx-devel
mailing list