aboutsummaryrefslogtreecommitdiff
path: root/src/mail/ngx_mail_proxy_module.c
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2020-10-03 21:04:57 +0300
committerMaxim Dounin <mdounin@mdounin.ru>2020-10-03 21:04:57 +0300
commit1e92a0a4cef98902aed35d7b402a6a402951aba4 (patch)
tree64779fd37e143a30d36fb0e30eca6b144ed30eaf /src/mail/ngx_mail_proxy_module.c
parent8523ef8e8673cb4c586125b9913e753ee3a62f0c (diff)
downloadnginx-1e92a0a4cef98902aed35d7b402a6a402951aba4.tar.gz
nginx-1e92a0a4cef98902aed35d7b402a6a402951aba4.zip
Mail: proxy_smtp_auth directive.
The proxy_smtp_auth directive instructs nginx to authenticate users on backend via the AUTH command (using the PLAIN SASL mechanism), similar to what is normally done for IMAP and POP3. If xclient is enabled along with proxy_smtp_auth, the XCLIENT command won't try to send the LOGIN parameter.
Diffstat (limited to 'src/mail/ngx_mail_proxy_module.c')
-rw-r--r--src/mail/ngx_mail_proxy_module.c89
1 files changed, 85 insertions, 4 deletions
diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c
index 1c86e54cf..610f54780 100644
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -16,6 +16,7 @@ typedef struct {
ngx_flag_t enable;
ngx_flag_t pass_error_message;
ngx_flag_t xclient;
+ ngx_flag_t smtp_auth;
size_t buffer_size;
ngx_msec_t timeout;
} ngx_mail_proxy_conf_t;
@@ -74,6 +75,13 @@ static ngx_command_t ngx_mail_proxy_commands[] = {
offsetof(ngx_mail_proxy_conf_t, xclient),
NULL },
+ { ngx_string("proxy_smtp_auth"),
+ 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),
+ NULL },
+
ngx_null_command
};
@@ -450,7 +458,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
{
u_char *p;
ngx_int_t rc;
- ngx_str_t line;
+ ngx_str_t line, auth, encoded;
ngx_buf_t *b;
ngx_connection_t *c;
ngx_mail_session_t *s;
@@ -513,6 +521,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
} else if (s->auth_method == NGX_MAIL_AUTH_NONE) {
s->mail_state = ngx_smtp_helo_from;
+ } else if (pcf->smtp_auth) {
+ s->mail_state = ngx_smtp_helo_auth;
+
} else {
s->mail_state = ngx_smtp_helo;
}
@@ -552,7 +563,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
p = ngx_copy(p, s->connection->addr_text.data,
s->connection->addr_text.len);
- if (s->login.len) {
+ pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
+
+ if (s->login.len && !pcf->smtp_auth) {
p = ngx_cpymem(p, " LOGIN=", sizeof(" LOGIN=") - 1);
p = ngx_copy(p, s->login.data, s->login.len);
}
@@ -570,6 +583,9 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
} else if (s->auth_method == NGX_MAIL_AUTH_NONE) {
s->mail_state = ngx_smtp_xclient_from;
+ } else if (pcf->smtp_auth) {
+ s->mail_state = ngx_smtp_xclient_auth;
+
} else {
s->mail_state = ngx_smtp_xclient;
}
@@ -595,8 +611,62 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
&s->smtp_helo)
- line.data;
- s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ?
- ngx_smtp_helo_from : ngx_smtp_helo;
+ pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);
+
+ if (s->auth_method == NGX_MAIL_AUTH_NONE) {
+ s->mail_state = ngx_smtp_helo_from;
+
+ } else if (pcf->smtp_auth) {
+ s->mail_state = ngx_smtp_helo_auth;
+
+ } else {
+ s->mail_state = ngx_smtp_helo;
+ }
+
+ break;
+
+ case ngx_smtp_helo_auth:
+ case ngx_smtp_xclient_auth:
+ ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0,
+ "mail proxy send auth");
+
+ s->connection->log->action = "sending AUTH to upstream";
+
+ if (s->passwd.data == NULL) {
+ ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+ "no password available");
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ auth.len = 1 + s->login.len + 1 + s->passwd.len;
+ auth.data = ngx_pnalloc(c->pool, auth.len);
+ if (auth.data == NULL) {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ auth.len = ngx_sprintf(auth.data, "%Z%V%Z%V", &s->login, &s->passwd)
+ - auth.data;
+
+ line.len = sizeof("AUTH PLAIN " CRLF) - 1
+ + ngx_base64_encoded_length(auth.len);
+
+ line.data = ngx_pnalloc(c->pool, line.len);
+ if (line.data == NULL) {
+ ngx_mail_proxy_internal_server_error(s);
+ return;
+ }
+
+ encoded.data = ngx_cpymem(line.data, "AUTH PLAIN ",
+ sizeof("AUTH PLAIN ") - 1);
+
+ ngx_encode_base64(&encoded, &auth);
+
+ p = encoded.data + encoded.len;
+ *p++ = CR; *p = LF;
+
+ s->mail_state = ngx_smtp_auth_plain;
break;
@@ -643,6 +713,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev)
case ngx_smtp_helo:
case ngx_smtp_xclient:
+ case ngx_smtp_auth_plain:
case ngx_smtp_to:
b = s->proxy->buffer;
@@ -824,6 +895,7 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
case ngx_smtp_helo:
case ngx_smtp_helo_xclient:
case ngx_smtp_helo_from:
+ case ngx_smtp_helo_auth:
case ngx_smtp_from:
if (p[0] == '2' && p[1] == '5' && p[2] == '0') {
return NGX_OK;
@@ -833,11 +905,18 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state)
case ngx_smtp_xclient:
case ngx_smtp_xclient_from:
case ngx_smtp_xclient_helo:
+ case ngx_smtp_xclient_auth:
if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') {
return NGX_OK;
}
break;
+ case ngx_smtp_auth_plain:
+ if (p[0] == '2' && p[1] == '3' && p[2] == '5') {
+ return NGX_OK;
+ }
+ break;
+
case ngx_smtp_to:
return NGX_OK;
}
@@ -1102,6 +1181,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *cf)
pcf->enable = NGX_CONF_UNSET;
pcf->pass_error_message = NGX_CONF_UNSET;
pcf->xclient = NGX_CONF_UNSET;
+ pcf->smtp_auth = NGX_CONF_UNSET;
pcf->buffer_size = NGX_CONF_UNSET_SIZE;
pcf->timeout = NGX_CONF_UNSET_MSEC;
@@ -1118,6 +1198,7 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf, void *parent, void *child)
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, prev->smtp_auth, 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);