# HG changeset patch # User Maxim Dounin # Date 1351093451 -14400 # Node ID 39bd0f3da80c0d38fdb8953f02b57569e6c58109 # Parent 4e294657b8000cf23e89ba51581ac2e41140d199 Mail: simplify proxy smtp state machine. No functional changes. Several states are dropped at cost of additional state transitions. Now states are mostly match other protocols, i.e. indicate last command send. diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -175,11 +175,8 @@ typedef enum { ngx_smtp_auth_plain, ngx_smtp_auth_cram_md5, ngx_smtp_helo, - ngx_smtp_helo_xclient, - ngx_smtp_helo_from, ngx_smtp_xclient, - ngx_smtp_xclient_from, - ngx_smtp_xclient_helo, + ngx_smtp_client_helo, ngx_smtp_from, ngx_smtp_to } ngx_smtp_state_e; diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -495,6 +495,8 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } +redo: + switch (s->mail_state) { case ngx_smtp_start: @@ -521,18 +523,15 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *p++ = CR; *p = LF; if (pcf->xclient) { - s->mail_state = ngx_smtp_helo_xclient; - - } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { - s->mail_state = ngx_smtp_helo_from; + s->mail_state = ngx_smtp_helo; } else { - s->mail_state = ngx_smtp_helo; + s->mail_state = ngx_smtp_client_helo; } break; - case ngx_smtp_helo_xclient: + case ngx_smtp_helo: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send xclient"); @@ -554,19 +553,15 @@ ngx_mail_proxy_smtp_handler(ngx_event_t (s->login.len ? " LOGIN=" : ""), &s->login, &s->host) - line.data; - if (s->smtp_helo.len) { - s->mail_state = ngx_smtp_xclient_helo; + s->mail_state = ngx_smtp_xclient; + break; - } else if (s->auth_method == NGX_MAIL_AUTH_NONE) { - s->mail_state = ngx_smtp_xclient_from; - - } else { - s->mail_state = ngx_smtp_xclient; + case ngx_smtp_xclient: + if (!s->smtp_helo.len) { + s->mail_state = ngx_smtp_client_helo; + goto redo; } - break; - - case ngx_smtp_xclient_helo: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send client ehlo"); @@ -585,13 +580,15 @@ ngx_mail_proxy_smtp_handler(ngx_event_t &s->smtp_helo) - line.data; - s->mail_state = (s->auth_method == NGX_MAIL_AUTH_NONE) ? - ngx_smtp_helo_from : ngx_smtp_helo; - + s->mail_state = ngx_smtp_client_helo; break; - case ngx_smtp_helo_from: - case ngx_smtp_xclient_from: + case ngx_smtp_client_helo: + if (s->auth_method != NGX_MAIL_AUTH_NONE) { + s->mail_state = ngx_smtp_to; + goto redo; + } + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send mail from"); @@ -608,7 +605,6 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *p++ = CR; *p = LF; s->mail_state = ngx_smtp_from; - break; case ngx_smtp_from: @@ -628,11 +624,8 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *p++ = CR; *p = LF; s->mail_state = ngx_smtp_to; - break; - case ngx_smtp_helo: - case ngx_smtp_xclient: case ngx_smtp_to: b = s->proxy->buffer; @@ -788,8 +781,7 @@ ngx_mail_proxy_read_response(ngx_mail_se break; case ngx_smtp_helo: - case ngx_smtp_helo_xclient: - case ngx_smtp_helo_from: + case ngx_smtp_client_helo: case ngx_smtp_from: if (p[0] == '2' && p[1] == '5' && p[2] == '0') { return NGX_OK; @@ -797,8 +789,6 @@ ngx_mail_proxy_read_response(ngx_mail_se break; case ngx_smtp_xclient: - case ngx_smtp_xclient_from: - case ngx_smtp_xclient_helo: if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { return NGX_OK; } # HG changeset patch # User Maxim Dounin # Date 1351093547 -14400 # Node ID e6350f6f1e383e68661fc4200e39c1916df2165a # Parent 39bd0f3da80c0d38fdb8953f02b57569e6c58109 Mail: proxy_smtp_auth directive. Directive proxy_smtp_auth instructs nginx to authenticate user on backend via AUTH command, similar to what is normally done for IMAP and POP3. diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- 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_com 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 }; @@ -463,7 +471,7 @@ ngx_mail_proxy_smtp_handler(ngx_event_t { 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; @@ -584,6 +592,62 @@ redo: break; case ngx_smtp_client_helo: + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + s->mail_state = ngx_smtp_auth_plain; + goto redo; + } + + pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module); + + if (!pcf->smtp_auth) { + s->mail_state = ngx_smtp_auth_plain; + goto redo; + } + + 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_WARN, s->connection->log, 0, + "no password available"); + + s->mail_state = ngx_smtp_auth_plain; + goto redo; + } + + 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; + + case ngx_smtp_auth_plain: if (s->auth_method != NGX_MAIL_AUTH_NONE) { s->mail_state = ngx_smtp_to; goto redo; @@ -794,6 +858,12 @@ ngx_mail_proxy_read_response(ngx_mail_se } 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; } @@ -1055,6 +1125,7 @@ ngx_mail_proxy_create_conf(ngx_conf_t *c 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; @@ -1071,6 +1142,7 @@ ngx_mail_proxy_merge_conf(ngx_conf_t *cf 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);