# HG changeset patch # User Maxim Dounin # Date 1233698583 -10800 # Node ID a28a95b7a86d3dcd5c44e2dde8b4ab4231066faf # Parent 96428109ec3bbbc2836762ce49dca5bfc238d7da# Parent 28335b73075091c0e231e7660b1c1fca1dc23ef8 Merge with nginx 0.7.33. diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -159,6 +159,10 @@ d5ec0be9c835834844c6d1661b36313413231a06 a6d84efa510670a5401fbd31ddd28f6931a88869 NGINX_0_6_2 fc223117327fbb2e852840dcb533ba5ff998d9ee NGINX_0_6_3 95183808f549b2d1c8d8004b704287025b4bf76b NGINX_0_6_4 +e2d916d7e50f07f94fa4bf0d0e99ba85225ea2fa PATCH_NGINX_MAIL_0_1 +f9e6413396d47def780cf9600bbe35b35ce09e6e PATCH_NGINX_MAIL_0_2 +98c752b41cbc0f0ecaafced85d906effa27e8fc9 PATCH_NGINX_MAIL_0_3 +05c02cbce7be96d0b5e5b9cc581f7752f8ea2e71 PATCH_NGINX_MAIL_0_4 d16d691432c9044f8b26ffccbd6ae68c11d0cde9 NGINX_0_6_5 f7cd062ee035392cb44b3ec340d31f94ce4d83de NGINX_0_6_6 9fc4ab6673f96b0d3eaefd820b6c2520dd8f103d NGINX_0_6_7 @@ -196,6 +200,7 @@ 6de24473fa708acc3b2f13611f5c44b0e3a292c9 0b6053502c552a3021db417cb2dc6caac7ba1bdd NGINX_0_7_7 34fb3a5735483bd22e77f90f305103307a813fc4 NGINX_0_7_8 05981f639d211e316c98ff3074a0f268fbde8bed NGINX_0_7_9 +03a69004d77d39856e192891cb7067605abbcd1b PATCH_NGINX_MAIL_0_5 349057ecf4d5d2886b08e6c61656548577243141 NGINX_0_7_10 9d81578d04bbc73636567e84ed5a48e86826eb1b NGINX_0_7_11 6ebbca3d5ed73b82e1e0aa14adff133b50bbb4ea NGINX_0_7_12 @@ -217,6 +222,8 @@ dac47e9ef0d5fc6ec8cd1e0ff433c86e96d1a358 fd759445d8a890a9db4ab645581358fdce277908 NGINX_0_7_28 49a0eb7ce20c1114dd25a73373b9ad5f77d02ed7 NGINX_0_7_29 dc98ed169c03366ef89869d49da3b21b4b6663fe NGINX_0_7_30 +2580fe1c5a9a300134ea707c5e27d871bc0237f0 PATCH_NGINX_MAIL_0_6 +2c989ee54dbd4bfa12b53f3b0ff59e5def929818 PATCH_NGINX_MAIL_0_7 ce4f9ff90bfa58834c5b0db35395fd980c8c4aa0 NGINX_0_7_31 6281966854a55e092674b01b6861bd025fe158ee NGINX_0_7_32 670af56a1158749e82d7b1fce1ce348f8e10472a NGINX_0_7_33 diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -401,6 +401,8 @@ if [ $MAIL = YES ]; then modules="$modules $MAIL_PROXY_MODULE" MAIL_SRCS="$MAIL_SRCS $MAIL_PROXY_SRCS" + + NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(MAIL_DEPS)" fi 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 @@ -258,11 +258,12 @@ typedef struct { #define NGX_SMTP_STARTTLS 13 -#define NGX_MAIL_AUTH_PLAIN 0 -#define NGX_MAIL_AUTH_LOGIN 1 -#define NGX_MAIL_AUTH_APOP 2 -#define NGX_MAIL_AUTH_CRAM_MD5 3 -#define NGX_MAIL_AUTH_NONE 4 +#define NGX_MAIL_AUTH_PLAIN 0 +#define NGX_MAIL_AUTH_LOGIN 1 +#define NGX_MAIL_AUTH_APOP 2 +#define NGX_MAIL_AUTH_CRAM_MD5 3 +#define NGX_MAIL_AUTH_NONE 4 +#define NGX_MAIL_AUTH_LOGIN_USERNAME 5 #define NGX_MAIL_AUTH_PLAIN_ENABLED 0x0002 @@ -346,7 +347,7 @@ ngx_int_t ngx_mail_salt(ngx_mail_session ngx_int_t ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n); ngx_int_t ngx_mail_auth_login_username(ngx_mail_session_t *s, - ngx_connection_t *c); + ngx_connection_t *c, ngx_int_t initial); ngx_int_t ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c); ngx_int_t ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -356,12 +356,18 @@ ngx_mail_auth_plain(ngx_mail_session_t * ngx_int_t -ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c) +ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c, + ngx_int_t initial) { ngx_str_t *arg; arg = s->args.elts; + if (initial) { + /* username in initial response */ + arg += (s->protocol == NGX_MAIL_SMTP_PROTOCOL) ? 2 : 1; + } + ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "mail auth login username: \"%V\"", &arg[0]); @@ -584,7 +590,9 @@ ngx_mail_read_command(ngx_mail_session_t return NGX_ERROR; } - return NGX_AGAIN; + if (s->buffer->pos == s->buffer->last) { + return NGX_AGAIN; + } } cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -625,8 +633,12 @@ void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c) { s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + s->state = 0; if (c->read->timer_set) { diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -205,7 +205,7 @@ ngx_mail_imap_auth_state(ngx_event_t *re break; case ngx_imap_auth_login_username: - rc = ngx_mail_auth_login_username(s, c); + rc = ngx_mail_auth_login_username(s, c, 0); tag = 0; s->out.len = sizeof(imap_password) - 1; @@ -370,6 +370,14 @@ ngx_mail_imap_authenticate(ngx_mail_sess return NGX_OK; + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + s->out.len = sizeof(imap_password) - 1; + s->out.data = imap_password; + s->mail_state = ngx_imap_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + case NGX_MAIL_AUTH_PLAIN: s->out.len = sizeof(imap_plain_next) - 1; diff --git a/src/mail/ngx_mail_imap_module.c b/src/mail/ngx_mail_imap_module.c diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -622,6 +622,8 @@ ngx_mail_smtp_parse_command(ngx_mail_ses ngx_str_t *arg; enum { sw_start = 0, + sw_command, + sw_invalid, sw_spaces_before_argument, sw_argument, sw_almost_done @@ -636,8 +638,14 @@ ngx_mail_smtp_parse_command(ngx_mail_ses /* SMTP command */ case sw_start: + s->arg_start = p; + state = sw_command; + + /* fall through */ + + case sw_command: if (ch == ' ' || ch == CR || ch == LF) { - c = s->buffer->start; + c = s->arg_start; if (p - c == 4) { @@ -715,6 +723,14 @@ ngx_mail_smtp_parse_command(ngx_mail_ses goto invalid; } + arg = ngx_array_push(&s->args); + if (arg == NULL) { + return NGX_ERROR; + } + arg->len = p - s->arg_start; + arg->data = s->arg_start; + s->arg_start = NULL; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -734,6 +750,9 @@ ngx_mail_smtp_parse_command(ngx_mail_ses break; + case sw_invalid: + goto invalid; + case sw_spaces_before_argument: switch (ch) { case ' ': @@ -820,9 +839,21 @@ done: invalid: - s->state = sw_start; + s->state = sw_invalid; s->arg_start = NULL; + /* skip invalid command till LF */ + + for (p = s->buffer->pos; p < s->buffer->last; p++) { + if (*p == LF) { + s->state = sw_start; + p++; + break; + } + } + + s->buffer->pos = p; + return NGX_MAIL_PARSE_INVALID_COMMAND; } @@ -831,6 +862,7 @@ ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_str_t *arg; + ngx_uint_t nelts; #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { @@ -839,26 +871,37 @@ ngx_mail_auth_parse(ngx_mail_session_t * #endif arg = s->args.elts; + nelts = s->args.nelts; + + if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { + arg++; + nelts--; + } if (arg[0].len == 5) { if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { - if (s->args.nelts == 1) { + if (nelts == 1) { return NGX_MAIL_AUTH_LOGIN; } + if (nelts == 2) { + return NGX_MAIL_AUTH_LOGIN_USERNAME; + } + return NGX_MAIL_PARSE_INVALID_COMMAND; } if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { - if (s->args.nelts == 1) { + if (nelts == 1) { return NGX_MAIL_AUTH_PLAIN; } - if (s->args.nelts == 2) { - return ngx_mail_auth_plain(s, c, 1); + if (nelts == 2) { + return ngx_mail_auth_plain(s, c, + (s->protocol == NGX_MAIL_SMTP_PROTOCOL) ? 2 : 1); } } @@ -867,7 +910,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * if (arg[0].len == 8) { - if (s->args.nelts != 1) { + if (nelts != 1) { return NGX_MAIL_PARSE_INVALID_COMMAND; } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -226,7 +226,7 @@ ngx_mail_pop3_auth_state(ngx_event_t *re break; case ngx_pop3_auth_login_username: - rc = ngx_mail_auth_login_username(s, c); + rc = ngx_mail_auth_login_username(s, c, 0); s->out.len = sizeof(pop3_password) - 1; s->out.data = pop3_password; @@ -474,6 +474,14 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s return NGX_OK; + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + s->out.len = sizeof(pop3_password) - 1; + s->out.data = pop3_password; + s->mail_state = ngx_pop3_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + case NGX_MAIL_AUTH_PLAIN: s->out.len = sizeof(pop3_next) - 1; 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 @@ -630,7 +630,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - ngx_mail_proxy_handler(s->connection->write); + if (s->buffer->pos == s->buffer->last) { + ngx_mail_proxy_handler(s->connection->write); + + } else { + ngx_mail_proxy_handler(c->write); + } return; diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -315,6 +315,7 @@ ngx_mail_smtp_invalid_pipelining(ngx_eve s->out.len = sizeof(smtp_invalid_pipelining) - 1; s->out.data = smtp_invalid_pipelining; + s->quit = 1; } ngx_mail_send(c->write); @@ -462,7 +463,7 @@ ngx_mail_smtp_auth_state(ngx_event_t *re break; case ngx_smtp_auth_login_username: - rc = ngx_mail_auth_login_username(s, c); + rc = ngx_mail_auth_login_username(s, c, 0); s->out.len = sizeof(smtp_password) - 1; s->out.data = smtp_password; @@ -483,6 +484,10 @@ ngx_mail_smtp_auth_state(ngx_event_t *re } } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -504,11 +509,14 @@ ngx_mail_smtp_auth_state(ngx_event_t *re case NGX_OK: s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } if (s->state) { - s->arg_start = s->buffer->start; + s->arg_start = s->buffer->pos; } ngx_mail_send(c->write); @@ -522,7 +530,7 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s ngx_str_t *arg; ngx_mail_smtp_srv_conf_t *sscf; - if (s->args.nelts != 1) { + if (s->args.nelts != 2) { s->out.len = sizeof(smtp_invalid_argument) - 1; s->out.data = smtp_invalid_argument; s->state = 0; @@ -531,14 +539,14 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s arg = s->args.elts; - s->smtp_helo.len = arg[0].len; + s->smtp_helo.len = arg[1].len; - s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len); + s->smtp_helo.data = ngx_pnalloc(c->pool, arg[1].len); if (s->smtp_helo.data == NULL) { return NGX_ERROR; } - ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); + ngx_memcpy(s->smtp_helo.data, arg[1].data, arg[1].len); s->smtp_from.len = 0; s->smtp_from.data = NULL; @@ -592,7 +600,7 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s } #endif - if (s->args.nelts == 0) { + if (s->args.nelts < 2) { s->out.len = sizeof(smtp_invalid_argument) - 1; s->out.data = smtp_invalid_argument; s->state = 0; @@ -611,6 +619,14 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s return NGX_OK; + case NGX_MAIL_AUTH_LOGIN_USERNAME: + + s->out.len = sizeof(smtp_password) - 1; + s->out.data = smtp_password; + s->mail_state = ngx_smtp_auth_login_password; + + return ngx_mail_auth_login_username(s, c, 1); + case NGX_MAIL_AUTH_PLAIN: s->out.len = sizeof(smtp_next) - 1; @@ -650,9 +666,7 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) { - u_char ch; - ngx_str_t l; - ngx_uint_t i; + ngx_str_t *arg, *end, cmd; ngx_mail_smtp_srv_conf_t *sscf; sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); @@ -674,37 +688,20 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s return NGX_OK; } - l.len = s->buffer->last - s->buffer->start; - l.data = s->buffer->start; - - for (i = 0; i < l.len; i++) { - ch = l.data[i]; - - if (ch != CR && ch != LF) { - continue; - } - - l.data[i] = ' '; - } + arg = s->args.elts; + end = arg + s->args.nelts - 1; - while (i) { - if (l.data[i - 1] != ' ') { - break; - } + cmd.len = end->data + end->len - arg->data; + cmd.data = arg->data; - i--; - } + s->smtp_from.len = cmd.len; - l.len = i; - - s->smtp_from.len = l.len; - - s->smtp_from.data = ngx_pnalloc(c->pool, l.len); + s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len); if (s->smtp_from.data == NULL) { return NGX_ERROR; } - ngx_memcpy(s->smtp_from.data, l.data, l.len); + ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp mail from:\"%V\"", &s->smtp_from); @@ -719,9 +716,7 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) { - u_char ch; - ngx_str_t l; - ngx_uint_t i; + ngx_str_t *arg, *end, cmd; if (s->smtp_from.len == 0) { s->out.len = sizeof(smtp_bad_sequence) - 1; @@ -729,37 +724,20 @@ ngx_mail_smtp_rcpt(ngx_mail_session_t *s return NGX_OK; } - l.len = s->buffer->last - s->buffer->start; - l.data = s->buffer->start; - - for (i = 0; i < l.len; i++) { - ch = l.data[i]; - - if (ch != CR && ch != LF) { - continue; - } - - l.data[i] = ' '; - } + arg = s->args.elts; + end = arg + s->args.nelts - 1; - while (i) { - if (l.data[i - 1] != ' ') { - break; - } + cmd.len = end->data + end->len - arg->data; + cmd.data = arg->data; - i--; - } + s->smtp_to.len = cmd.len; - l.len = i; - - s->smtp_to.len = l.len; - - s->smtp_to.data = ngx_pnalloc(c->pool, l.len); + s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len); if (s->smtp_to.data == NULL) { return NGX_ERROR; } - ngx_memcpy(s->smtp_to.data, l.data, l.len); + ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp rcpt to:\"%V\"", &s->smtp_to); diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c