[PATCH] pass smtp authentication upstream
David Jonas
djonas at vitalwerks.com
Mon Apr 2 00:50:01 UTC 2012
Hello!
When using nginx as an smtp proxy, we needed to be able to pass smtp
authentication through to the upstream. So I worked up this patch.
Hopefully someone else will find it useful. Any fixes or problems are
more than welcome.
Patch was written against nginx-1.0.14. It adds a boolean configuration
directive, smtp_auth_upstream that enables the functionality. xclient
still works and is performed after authentication, if enabled.
David Jonas
=========================================
diff -r 720380947aef src/mail/ngx_mail.h
--- a/src/mail/ngx_mail.h Wed Mar 28 16:08:26 2012 -0700
+++ b/src/mail/ngx_mail.h Sun Apr 01 17:45:45 2012 -0700
@@ -164,10 +164,15 @@
ngx_smtp_auth_cram_md5,
ngx_smtp_helo,
ngx_smtp_helo_xclient,
+ ngx_smtp_helo_login,
ngx_smtp_helo_from,
ngx_smtp_xclient,
ngx_smtp_xclient_from,
ngx_smtp_xclient_helo,
+ ngx_smtp_login,
+ ngx_smtp_user,
+ ngx_smtp_passwd_xclient,
+ ngx_smtp_passwd_helo,
ngx_smtp_from,
ngx_smtp_to
} ngx_smtp_state_e;
diff -r 720380947aef src/mail/ngx_mail_proxy_module.c
--- a/src/mail/ngx_mail_proxy_module.c Wed Mar 28 16:08:26 2012 -0700
+++ b/src/mail/ngx_mail_proxy_module.c Sun Apr 01 17:45:45 2012 -0700
@@ -16,6 +16,7 @@
ngx_flag_t enable;
ngx_flag_t pass_error_message;
ngx_flag_t xclient;
+ ngx_flag_t smtp_auth_upstream;
size_t buffer_size;
ngx_msec_t timeout;
} ngx_mail_proxy_conf_t;
@@ -74,6 +75,13 @@
offsetof(ngx_mail_proxy_conf_t, xclient),
NULL },
+ { ngx_string("smtp_auth_upstream"),
+ NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_MAIL_SRV_CONF_OFFSET,
+ offsetof(ngx_mail_proxy_conf_t, smtp_auth_upstream),
+ NULL },
+
ngx_null_command
};
@@ -520,7 +528,10 @@
p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len);
*p++ = CR; *p = LF;
- if (pcf->xclient) {
+ if(s->auth_method != NGX_MAIL_AUTH_NONE &&
pcf->smtp_auth_upstream) {
+ s->mail_state = ngx_smtp_helo_login;
+
+ } else if (pcf->xclient) {
s->mail_state = ngx_smtp_helo_xclient;
} else if (s->auth_method == NGX_MAIL_AUTH_NONE) {
@@ -532,7 +543,76 @@
break;
+ case ngx_smtp_helo_login:
+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
+ "mail proxy send login");
+
+ s->connection->log->action = "sending LOGIN command to upstream";
+
+ line.len = sizeof("AUTH LOGIN " CRLF) - 1;
+ line.data = ngx_pnalloc(c->pool, line.len);
+ if (line.data == NULL) {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ p = ngx_cpymem(line.data, "AUTH LOGIN ", sizeof("AUTH LOGIN ")
- 1);
+ *p++ = CR; *p = LF;
+
+ s->mail_state = ngx_smtp_login;
+ break;
+
+ case ngx_smtp_login:
+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy
send user");
+
+ s->connection->log->action = "sending user name to upstream";
+
+ line.len = ngx_base64_encoded_length(s->login.len) + 2;
+ p = ngx_pnalloc(c->pool, line.len);
+ if (p == NULL) {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ line.data = p;
+ ngx_encode_base64(&line, &s->login);
+ p += line.len;
+ *p++ = CR; *p = LF;
+ line.len += 2;
+
+ s->mail_state = ngx_smtp_user;
+ break;
+
+ case ngx_smtp_user:
+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
+ "mail proxy send passwd");
+
+ s->connection->log->action = "sending password to upstream";
+
+ line.len = ngx_base64_encoded_length(s->passwd.len) + 2;
+ p = ngx_pnalloc(c->pool, line.len);
+ if (p == NULL) {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ line.data = p;
+ ngx_encode_base64(&line, &s->passwd);
+ p += line.len;
+ *p++ = CR; *p = LF;
+ line.len += 2;
+
+ pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
+
+ if (pcf->xclient) {
+ s->mail_state = ngx_smtp_passwd_xclient;
+ } else {
+ s->mail_state = ngx_smtp_passwd_helo;
+ }
+ break;
+
case ngx_smtp_helo_xclient:
+ case ngx_smtp_passwd_xclient:
ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
"mail proxy send xclient");
@@ -633,6 +713,7 @@
case ngx_smtp_helo:
case ngx_smtp_xclient:
+ case ngx_smtp_passwd_helo:
case ngx_smtp_to:
b = s->proxy->buffer;
@@ -789,6 +870,7 @@
case ngx_smtp_helo:
case ngx_smtp_xclient:
+ case ngx_smtp_passwd_helo:
case ngx_smtp_to:
b = s->proxy->buffer;
@@ -789,6 +870,7 @@
case ngx_smtp_helo:
case ngx_smtp_helo_xclient:
+ case ngx_smtp_helo_login:
case ngx_smtp_helo_from:
case ngx_smtp_from:
if (p[0] == '2' && p[1] == '5' && p[2] == '0') {
@@ -804,6 +886,20 @@
}
break;
+ case ngx_smtp_login:
+ case ngx_smtp_user:
+ if(p[0] == '3' && p[1] == '3' && p[2] == '4') {
+ return NGX_OK;
+ }
+ break;
+
+ case ngx_smtp_passwd_xclient:
+ case ngx_smtp_passwd_helo:
+ if(p[0] == '2' && p[1] == '3' && p[2] == '5') {
+ return NGX_OK;
+ }
+ break;
+
case ngx_smtp_to:
return NGX_OK;
}
@@ -1065,6 +1161,7 @@
pcf->enable = NGX_CONF_UNSET;
pcf->pass_error_message = NGX_CONF_UNSET;
pcf->xclient = NGX_CONF_UNSET;
+ pcf->smtp_auth_upstream = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
@@ -1081,6 +1178,7 @@
ngx_conf_merge_value(conf->enable, prev->enable, 0);
ngx_conf_merge_value(conf->pass_error_message,
prev->pass_error_message, 0);
ngx_conf_merge_value(conf->xclient, prev->xclient, 1);
+ ngx_conf_merge_value(conf->smtp_auth_upstream,
prev->smtp_auth_upstream, 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);
More information about the nginx-devel
mailing list