Mercurial > hg > nginx-mail
changeset 439:35409f39a096
Merge with nginx 0.7.17.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 15 Sep 2008 21:35:23 +0400 |
parents | 9b19e26b2660 (diff) b453a4324c60 (current diff) |
children | 4c92e29a7375 |
files | .hgtags |
diffstat | 10 files changed, 351 insertions(+), 69 deletions(-) [+] |
line wrap: on
line diff
--- 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
--- a/auto/modules +++ b/auto/modules @@ -390,6 +390,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
--- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -136,8 +136,12 @@ typedef enum { ngx_smtp_auth_plain, ngx_smtp_auth_cram_md5, ngx_smtp_helo, - ngx_smtp_noxclient, - ngx_smtp_xclient + ngx_smtp_helo_xclient, + ngx_smtp_helo_from, + ngx_smtp_xclient, + ngx_smtp_xclient_from, + ngx_smtp_from, + ngx_smtp_to } ngx_smtp_state_e; @@ -173,7 +177,7 @@ typedef struct { unsigned no_sync_literal:1; unsigned starttls:1; unsigned esmtp:1; - unsigned auth_method:2; + unsigned auth_method:3; unsigned auth_wait:1; ngx_str_t login; @@ -187,6 +191,8 @@ typedef struct { ngx_str_t *addr_text; ngx_str_t host; ngx_str_t smtp_helo; + ngx_str_t smtp_from; + ngx_str_t smtp_to; ngx_uint_t command; ngx_array_t args; @@ -256,12 +262,14 @@ typedef struct { #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_ENABLED 0x0002 #define NGX_MAIL_AUTH_LOGIN_ENABLED 0x0004 #define NGX_MAIL_AUTH_APOP_ENABLED 0x0008 #define NGX_MAIL_AUTH_CRAM_MD5_ENABLED 0x0010 +#define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 #define NGX_MAIL_PARSE_INVALID_COMMAND 20 @@ -356,6 +364,9 @@ u_char *ngx_mail_log_error(ngx_log_t *lo char *ngx_mail_capabilities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +#if (NGX_MAIL_SSL) +void ngx_mail_starttls_handler(ngx_event_t *rev); +#endif /* STUB */ void ngx_mail_proxy_init(ngx_mail_session_t *s, ngx_peer_addr_t *peer);
--- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -141,7 +141,8 @@ static ngx_str_t ngx_mail_auth_http_me ngx_string("plain"), ngx_string("plain"), ngx_string("apop"), - ngx_string("cram-md5") + ngx_string("cram-md5"), + ngx_string("none") }; static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0"); @@ -1165,6 +1166,9 @@ ngx_mail_auth_http_create_request(ngx_ma + sizeof(CRLF) - 1 + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len + sizeof(CRLF) - 1 + + sizeof("Auth-SMTP-Helo: ") - 1 + s->smtp_helo.len + + sizeof("Auth-SMTP-From: ") - 1 + s->smtp_from.len + + sizeof("Auth-SMTP-To: ") - 1 + s->smtp_to.len + ahcf->header.len + sizeof(CRLF) - 1; @@ -1219,6 +1223,27 @@ ngx_mail_auth_http_create_request(ngx_ma s->connection->addr_text.len); *b->last++ = CR; *b->last++ = LF; + if (s->auth_method == NGX_MAIL_AUTH_NONE) { + + /* HELO / MAIL FROM / RCPT TO can't contain CRLF, no need to escape */ + + b->last = ngx_cpymem(b->last, "Auth-SMTP-Helo: ", + sizeof("Auth-SMTP-Helo: ") - 1); + b->last = ngx_copy(b->last, s->smtp_helo.data, s->smtp_helo.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-From: ", + sizeof("Auth-SMTP-From: ") - 1); + b->last = ngx_copy(b->last, s->smtp_from.data, s->smtp_from.len); + *b->last++ = CR; *b->last++ = LF; + + b->last = ngx_cpymem(b->last, "Auth-SMTP-To: ", + sizeof("Auth-SMTP-To: ") - 1); + b->last = ngx_copy(b->last, s->smtp_to.data, s->smtp_to.len); + *b->last++ = CR; *b->last++ = LF; + + } + if (ahcf->header.len) { b->last = ngx_copy(b->last, ahcf->header.data, ahcf->header.len); }
--- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -584,7 +584,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 +627,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) {
--- a/src/mail/ngx_mail_imap_module.c +++ b/src/mail/ngx_mail_imap_module.c @@ -36,7 +36,8 @@ static ngx_str_t ngx_mail_imap_auth_met ngx_string("AUTH=PLAIN"), ngx_string("AUTH=LOGIN"), ngx_null_string, /* APOP */ - ngx_string("AUTH=CRAM-MD5") + ngx_string("AUTH=CRAM-MD5"), + ngx_null_string /* NONE */ };
--- 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 ' ': @@ -746,7 +765,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses s->arg_end = p; goto done; default: - if (s->args.nelts <= 2) { + if (s->args.nelts <= 10) { state = sw_argument; s->arg_start = p; break; @@ -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,12 +871,18 @@ 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; } @@ -853,12 +891,13 @@ ngx_mail_auth_parse(ngx_mail_session_t * 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 +906,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; }
--- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -520,11 +520,13 @@ ngx_mail_proxy_smtp_handler(ngx_event_t p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); *p++ = CR; *p = LF; - s->mail_state = pcf->xclient ? ngx_smtp_helo: ngx_smtp_noxclient; + s->mail_state = pcf->xclient ? ngx_smtp_helo_xclient : + s->auth_method == NGX_MAIL_AUTH_NONE ? + ngx_smtp_helo_from : ngx_smtp_helo; break; - case ngx_smtp_helo: + case ngx_smtp_helo_xclient: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, "mail proxy send xclient"); @@ -541,30 +543,73 @@ ngx_mail_proxy_smtp_handler(ngx_event_t return; } - if (s->smtp_helo.len) { - line.len = ngx_sprintf(line.data, - "XCLIENT PROTO=%sSMTP HELO=%V ADDR=%V LOGIN=%V " - "NAME=%V" CRLF, - (s->esmtp ? "E" : ""), &s->smtp_helo, - &s->connection->addr_text, &s->login, &s->host) - - line.data; - } else { - line.len = ngx_sprintf(line.data, - "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V NAME=%V" CRLF, - &s->connection->addr_text, &s->login, &s->host) - - line.data; + line.len = ngx_sprintf(line.data, + "XCLIENT PROTO=%sSMTP%s%V ADDR=%V%s%V " + "NAME=%V" CRLF, + (s->esmtp ? "E" : ""), + (s->smtp_helo.len ? " HELO=" : ""), &s->smtp_helo, + &s->connection->addr_text, + (s->login.len ? " LOGIN=" : ""), &s->login, &s->host) + - line.data; + + s->mail_state = s->auth_method == NGX_MAIL_AUTH_NONE ? + ngx_smtp_xclient_from : ngx_smtp_xclient; + + break; + + case ngx_smtp_helo_from: + case ngx_smtp_xclient_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send mail from"); + + s->connection->log->action = "sending MAIL FROM to upstream"; + + line.len = s->smtp_from.len + sizeof(CRLF) - 1; + line.data = ngx_pnalloc(c->pool, line.len); + if (line.data == NULL) { + ngx_mail_proxy_internal_server_error(s); + return; } - s->mail_state = ngx_smtp_xclient; + p = ngx_cpymem(line.data, s->smtp_from.data, s->smtp_from.len); + *p++ = CR; *p = LF; + + s->mail_state = ngx_smtp_from; + break; - case ngx_smtp_noxclient: - case ngx_smtp_xclient: + case ngx_smtp_from: + ngx_log_debug0(NGX_LOG_DEBUG_MAIL, rev->log, 0, + "mail proxy send rcpt to"); + + s->connection->log->action = "sending RCPT TO to upstream"; + + line.len = s->smtp_to.len + sizeof(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, s->smtp_to.data, s->smtp_to.len); + *p++ = CR; *p = LF; - ngx_memcpy(s->proxy->buffer->start, smtp_ok, sizeof(smtp_ok) - 1); + s->mail_state = ngx_smtp_to; + + break; + + case ngx_smtp_helo: + case ngx_smtp_xclient: + case ngx_smtp_to: - s->proxy->buffer->pos = s->proxy->buffer->start; - s->proxy->buffer->last = s->proxy->buffer->start + sizeof(smtp_ok) - 1; + if (s->auth_method != NGX_MAIL_AUTH_NONE) { + ngx_memcpy(s->proxy->buffer->start, smtp_ok, + sizeof(smtp_ok) - 1); + s->proxy->buffer->last = s->proxy->buffer->start + + sizeof(smtp_ok) - 1; + s->proxy->buffer->pos = s->proxy->buffer->start; + } + s->connection->read->handler = ngx_mail_proxy_handler; s->connection->write->handler = ngx_mail_proxy_handler; @@ -578,7 +623,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; @@ -703,16 +753,27 @@ ngx_mail_proxy_read_response(ngx_mail_se default: /* NGX_MAIL_SMTP_PROTOCOL */ switch (state) { + case ngx_smtp_to: + return NGX_OK; + case ngx_smtp_helo: - case ngx_smtp_noxclient: + case ngx_smtp_helo_from: + case ngx_smtp_helo_xclient: + case ngx_smtp_from: if (p[0] == '2' && p[1] == '5' && p[2] == '0') { return NGX_OK; } break; case ngx_smtp_start: + if (p[0] == '2' && p[1] == '2' && p[2] == '0') { + return NGX_OK; + } + break; + case ngx_smtp_xclient: - if (p[0] == '2' && p[1] == '2' && p[2] == '0') { + case ngx_smtp_xclient_from: + if (p[0] == '2' && (p[1] == '2' || p[1] == '5') && p[2] == '0') { return NGX_OK; } break;
--- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -23,6 +23,8 @@ static ngx_int_t ngx_mail_smtp_auth(ngx_ static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c); static ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c); +static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c); static ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c, char *err); @@ -41,6 +43,7 @@ static u_char smtp_invalid_pipelining[] "503 5.5.0 Improper use of SMTP command pipelining" CRLF; static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; +static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF; static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]"); @@ -295,6 +298,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); @@ -417,8 +421,15 @@ ngx_mail_smtp_auth_state(ngx_event_t *re rc = ngx_mail_smtp_mail(s, c); break; + case NGX_SMTP_RCPT: + rc = ngx_mail_smtp_rcpt(s, c); + break; + + case NGX_SMTP_RSET: + rc = ngx_mail_smtp_rset(s, c); + break; + case NGX_SMTP_NOOP: - case NGX_SMTP_RSET: break; case NGX_SMTP_STARTTLS: @@ -456,6 +467,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: @@ -477,11 +492,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); @@ -495,7 +513,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; @@ -504,14 +522,19 @@ 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; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); @@ -560,7 +583,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; @@ -618,10 +641,93 @@ 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) { - ngx_mail_smtp_log_rejected_command(s, c, "client was rejected: \"%V\""); + 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); + + if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) { + ngx_mail_smtp_log_rejected_command(s, c, + "client was rejected: \"%V\""); + + s->out.len = sizeof(smtp_auth_required) - 1; + s->out.data = smtp_auth_required; + + return NGX_OK; + } + + /* auth none */ + + if (s->smtp_from.len) { + s->out.len = sizeof(smtp_bad_sequence) - 1; + s->out.data = smtp_bad_sequence; + return NGX_OK; + } + + arg = s->args.elts; + end = arg + s->args.nelts - 1; + + cmd.len = end->data + end->len - arg->data; + cmd.data = arg->data; + + s->smtp_from.len = cmd.len; + + s->smtp_from.data = ngx_palloc(c->pool, cmd.len); + if (s->smtp_from.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len); + + s->out.len = sizeof(smtp_ok) - 1; + s->out.data = smtp_ok; + + return NGX_OK; +} - s->out.len = sizeof(smtp_auth_required) - 1; - s->out.data = smtp_auth_required; + +static ngx_int_t +ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg, *end, cmd; + + if (s->smtp_from.len == 0) { + s->out.len = sizeof(smtp_bad_sequence) - 1; + s->out.data = smtp_bad_sequence; + return NGX_OK; + } + + arg = s->args.elts; + end = arg + s->args.nelts - 1; + + cmd.len = end->data + end->len - arg->data; + cmd.data = arg->data; + + s->smtp_to.len = cmd.len; + + s->smtp_to.data = ngx_palloc(c->pool, cmd.len); + if (s->smtp_to.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len); + + s->auth_method = NGX_MAIL_AUTH_NONE; + + return NGX_DONE; +} + + +static ngx_int_t +ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c) +{ + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; + + s->out.len = sizeof(smtp_ok) - 1; + s->out.data = smtp_ok; return NGX_OK; } @@ -644,6 +750,10 @@ ngx_mail_smtp_starttls(ngx_mail_session_ s->smtp_helo.len = 0; s->smtp_helo.data = NULL; + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; c->read->handler = ngx_mail_starttls_handler; return NGX_OK;
--- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -20,6 +20,7 @@ static ngx_conf_bitmask_t ngx_mail_smtp { ngx_string("plain"), NGX_MAIL_AUTH_PLAIN_ENABLED }, { ngx_string("login"), NGX_MAIL_AUTH_LOGIN_ENABLED }, { ngx_string("cram-md5"), NGX_MAIL_AUTH_CRAM_MD5_ENABLED }, + { ngx_string("none"), NGX_MAIL_AUTH_NONE_ENABLED }, { ngx_null_string, 0 } }; @@ -28,7 +29,8 @@ static ngx_str_t ngx_mail_smtp_auth_met ngx_string("PLAIN"), ngx_string("LOGIN"), ngx_null_string, /* APOP */ - ngx_string("CRAM-MD5") + ngx_string("CRAM-MD5"), + ngx_null_string /* NONE */ }; @@ -136,10 +138,10 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t ngx_mail_smtp_srv_conf_t *prev = parent; ngx_mail_smtp_srv_conf_t *conf = child; - u_char *p, *auth; + u_char *p, *auth, *last; size_t size; ngx_str_t *c; - ngx_uint_t i, m; + ngx_uint_t i, m, smtp_auth_enabled; ngx_mail_core_srv_conf_t *cscf; ngx_conf_merge_size_value(conf->client_buffer_size, @@ -192,23 +194,28 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t conf->capabilities = prev->capabilities; } - size = sizeof("250-") - 1 + cscf->server_name.len + sizeof(CRLF) - 1 - + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + size = sizeof("250-") - 1 + cscf->server_name.len + sizeof(CRLF) - 1; c = conf->capabilities.elts; for (i = 0; i < conf->capabilities.nelts; i++) { size += sizeof("250 ") - 1 + c[i].len + sizeof(CRLF) - 1; } + smtp_auth_enabled = 0; for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; m <<= 1, i++) { if (m & conf->auth_methods) { size += 1 + ngx_mail_smtp_auth_methods_names[i].len; + smtp_auth_enabled = 1; } } + if (smtp_auth_enabled) { + size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + } + p = ngx_pnalloc(cf->pool, size); if (p == NULL) { return NGX_CONF_ERROR; @@ -217,11 +224,13 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t conf->capability.len = size; conf->capability.data = p; + last = p; *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; p = ngx_cpymem(p, cscf->server_name.data, cscf->server_name.len); *p++ = CR; *p++ = LF; for (i = 0; i < conf->capabilities.nelts; i++) { + last = p; *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; p = ngx_cpymem(p, c[i].data, c[i].len); *p++ = CR; *p++ = LF; @@ -229,21 +238,28 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t auth = p; - *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; - *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; + if (smtp_auth_enabled) { + last = p; + + *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = ' '; + *p++ = 'A'; *p++ = 'U'; *p++ = 'T'; *p++ = 'H'; - for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; - m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; - m <<= 1, i++) - { - if (m & conf->auth_methods) { - *p++ = ' '; - p = ngx_cpymem(p, ngx_mail_smtp_auth_methods_names[i].data, - ngx_mail_smtp_auth_methods_names[i].len); + for (m = NGX_MAIL_AUTH_PLAIN_ENABLED, i = 0; + m <= NGX_MAIL_AUTH_CRAM_MD5_ENABLED; + m <<= 1, i++) + { + if (m & conf->auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_mail_smtp_auth_methods_names[i].data, + ngx_mail_smtp_auth_methods_names[i].len); + } } - } + + *p++ = CR; *p = LF; - *p++ = CR; *p = LF; + } else { + last[3] = ' '; + } size += sizeof("250 STARTTLS" CRLF) - 1; @@ -262,7 +278,7 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t *p++ = CR; *p = LF; p = conf->starttls_capability.data - + (auth - conf->capability.data) + 3; + + (last - conf->capability.data) + 3; *p = '-'; size = (auth - conf->capability.data) @@ -281,5 +297,11 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + if (last < auth) { + p = conf->starttls_only_capability.data + + (last - conf->capability.data) + 3; + *p = '-'; + } + return NGX_CONF_OK; }