Mercurial > hg > nginx-mail
changeset 403:d4cac61d8e95
Merge with nginx 0.6.5.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 23 Jul 2007 22:45:18 +0000 |
parents | 29cf4046a9a5 (diff) d16d691432c9 (current diff) |
children | 481e8f936572 |
files | .hgtags src/mail/ngx_mail.h src/mail/ngx_mail_core_module.c src/mail/ngx_mail_handler.c src/mail/ngx_mail_parse.c |
diffstat | 7 files changed, 284 insertions(+), 56 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags +++ b/.hgtags @@ -159,3 +159,6 @@ 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
--- a/auto/modules +++ b/auto/modules @@ -348,6 +348,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_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -137,7 +137,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("unauth") }; static ngx_str_t ngx_mail_smtp_errcode = ngx_string("535 5.7.0"); @@ -897,6 +898,10 @@ ngx_mail_auth_sleep_handler(ngx_event_t ngx_add_timer(rev, cscf->timeout); + if (cscf->handler_read) { + s->connection->read->handler = cscf->handler_read; + } + if (rev->ready) { s->connection->read->handler(rev); return; @@ -1169,6 +1174,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; @@ -1223,6 +1231,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_UNAUTH) { + + /* 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_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -66,6 +66,7 @@ static ngx_conf_bitmask_t ngx_smtp_auth { 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("unauth"), NGX_MAIL_AUTH_UNAUTH_ENABLED }, { ngx_null_string, 0 } }; @@ -74,7 +75,8 @@ static ngx_str_t ngx_imap_auth_methods_ 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 /* UNAUTH */ }; @@ -82,7 +84,8 @@ static ngx_str_t ngx_smtp_auth_methods_ ngx_string("PLAIN"), ngx_string("LOGIN"), ngx_null_string, /* APOP */ - ngx_string("CRAM-MD5") + ngx_string("CRAM-MD5"), + ngx_null_string /* UNAUTH */ }; @@ -301,10 +304,10 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t ngx_mail_core_srv_conf_t *prev = parent; ngx_mail_core_srv_conf_t *conf = child; - u_char *p, *auth; + u_char *p, *auth, *last; size_t size, stls_only_size; ngx_str_t *c, *d; - ngx_uint_t i, m; + ngx_uint_t i, m, smtp_auth_enabled; ngx_conf_merge_size_value(conf->imap_client_buffer_size, prev->imap_client_buffer_size, @@ -599,23 +602,28 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t conf->smtp_capabilities = prev->smtp_capabilities; } - size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1 - + sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + size = sizeof("250-") - 1 + conf->server_name.len + sizeof(CRLF) - 1; c = conf->smtp_capabilities.elts; for (i = 0; i < conf->smtp_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->smtp_auth_methods) { size += 1 + ngx_smtp_auth_methods_names[i].len; + smtp_auth_enabled = 1; } } + if (smtp_auth_enabled) { + size += sizeof("250 AUTH") - 1 + sizeof(CRLF) - 1; + } + p = ngx_palloc(cf->pool, size); if (p == NULL) { return NGX_CONF_ERROR; @@ -624,11 +632,13 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t conf->smtp_capability.len = size; conf->smtp_capability.data = p; + last = p; *p++ = '2'; *p++ = '5'; *p++ = '0'; *p++ = '-'; p = ngx_cpymem(p, conf->server_name.data, conf->server_name.len); *p++ = CR; *p++ = LF; for (i = 0; i < conf->smtp_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; @@ -636,21 +646,28 @@ ngx_mail_core_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->smtp_auth_methods) { - *p++ = ' '; - p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, - ngx_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->smtp_auth_methods) { + *p++ = ' '; + p = ngx_cpymem(p, ngx_smtp_auth_methods_names[i].data, + ngx_smtp_auth_methods_names[i].len); + } } - } + + *p++ = CR; *p = LF; - *p++ = CR; *p = LF; + } else { + last[3] = ' '; + } size += sizeof("250 STARTTLS" CRLF) - 1; @@ -669,11 +686,11 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t *p++ = CR; *p = LF; p = conf->smtp_starttls_capability.data - + (auth - conf->smtp_capability.data) + 3; + + (last - conf->smtp_capability.data) + 3; *p = '-'; size = (auth - conf->smtp_capability.data) - + sizeof("250 STARTTLS" CRLF) - 1; + + sizeof("250 STARTTLS" CRLF) - 1; p = ngx_palloc(cf->pool, size); if (p == NULL) { @@ -686,7 +703,13 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t p = ngx_cpymem(p, conf->smtp_capability.data, auth - conf->smtp_capability.data); - ngx_memcpy(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); + + if (last < auth) { + p = conf->smtp_starttls_only_capability.data + + (last - conf->smtp_capability.data) + 3; + *p = '-'; + } return NGX_CONF_OK; }
--- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -15,7 +15,6 @@ static void ngx_mail_init_protocol(ngx_e static ngx_int_t ngx_mail_decode_auth_plain(ngx_mail_session_t *s, ngx_str_t *encoded); static void ngx_mail_do_auth(ngx_mail_session_t *s); -static ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s); static u_char *ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len); #if (NGX_MAIL_SSL) @@ -56,6 +55,7 @@ static u_char smtp_password[] = "334 UG static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" 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; void @@ -172,7 +172,7 @@ ngx_mail_init_connection(ngx_connection_ #if (NGX_MAIL_SSL) -static void +void ngx_mail_starttls_handler(ngx_event_t *rev) { ngx_connection_t *c; @@ -269,6 +269,11 @@ ngx_mail_init_session(ngx_connection_t * return; } + if (cscf->handler_init_session) { + cscf->handler_init_session(c); + return; + } + if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { s->out = cscf->smtp_greeting; @@ -411,6 +416,12 @@ ngx_mail_init_protocol(ngx_event_t *rev) } s = c->data; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (cscf->handler_init_protocol) { + cscf->handler_init_protocol(rev); + return; + } switch (s->protocol) { @@ -421,7 +432,6 @@ ngx_mail_init_protocol(ngx_event_t *rev) break; case NGX_MAIL_IMAP_PROTOCOL: - cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); size = cscf->imap_client_buffer_size; s->mail_state = ngx_imap_start; c->read->handler = ngx_imap_auth_state; @@ -449,6 +459,10 @@ ngx_mail_init_protocol(ngx_event_t *rev) } } + if (cscf->handler_read) { + c->read->handler = cscf->handler_read; + } + c->read->handler(rev); } @@ -1535,6 +1549,11 @@ ngx_smtp_auth_state(ngx_event_t *rev) ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; + if (s->command == NGX_SMTP_HELO) { size = cscf->smtp_server_name.len; text = cscf->smtp_server_name.data; @@ -1567,6 +1586,17 @@ ngx_smtp_auth_state(ngx_event_t *rev) break; + case NGX_SMTP_RSET: + + s->smtp_from.len = 0; + s->smtp_from.data = NULL; + s->smtp_to.len = 0; + s->smtp_to.data = NULL; + + text = smtp_ok; + size = sizeof(smtp_ok) - 1; + break; + case NGX_SMTP_AUTH: #if (NGX_MAIL_SSL) @@ -1693,8 +1723,12 @@ ngx_smtp_auth_state(ngx_event_t *rev) break; case NGX_SMTP_MAIL: - - if (s->connection->log->log_level >= NGX_LOG_INFO) { + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); + + if (s->connection->log->log_level >= NGX_LOG_INFO + || (cscf->smtp_auth_methods + & NGX_MAIL_AUTH_UNAUTH_ENABLED)) + { l.len = s->buffer->last - s->buffer->start; l.data = s->buffer->start; @@ -1718,16 +1752,91 @@ ngx_smtp_auth_state(ngx_event_t *rev) l.len = i; - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "client was rejected: \"%V\"", &l); + if (!(cscf->smtp_auth_methods + & NGX_MAIL_AUTH_UNAUTH_ENABLED)) + { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client was rejected: \"%V\"", &l); + } + + } + + if (!(cscf->smtp_auth_methods & NGX_MAIL_AUTH_UNAUTH_ENABLED)) + { + text = smtp_auth_required; + size = sizeof(smtp_auth_required) - 1; + break; + } + + /* allow unauth */ + + if (s->smtp_from.len) { + text = smtp_bad_sequence; + size = sizeof(smtp_bad_sequence) - 1; + break; + } + + s->smtp_from.len = l.len; + + s->smtp_from.data = ngx_palloc(c->pool, l.len); + if (s->smtp_from.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; } - text = smtp_auth_required; - size = sizeof(smtp_auth_required) - 1; + ngx_memcpy(s->smtp_from.data, l.data, l.len); + + text = smtp_ok; + size = sizeof(smtp_ok) - 1; break; + case NGX_SMTP_RCPT: + + if (s->smtp_from.len == 0) { + text = smtp_bad_sequence; + size = sizeof(smtp_bad_sequence) - 1; + break; + } + + 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] = ' '; + } + + while (i) { + if (l.data[i - 1] != ' ') { + break; + } + + i--; + } + + l.len = i; + + s->smtp_to.len = l.len; + + s->smtp_to.data = ngx_palloc(c->pool, l.len); + if (s->smtp_to.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } + + ngx_memcpy(s->smtp_to.data, l.data, l.len); + + s->auth_method = NGX_MAIL_AUTH_UNAUTH; + + ngx_mail_do_auth(s); + return; + case NGX_SMTP_NOOP: - case NGX_SMTP_RSET: text = smtp_ok; size = sizeof(smtp_ok) - 1; break; @@ -1748,6 +1857,10 @@ ngx_smtp_auth_state(ngx_event_t *rev) 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; text = smtp_ok; size = sizeof(smtp_ok) - 1; @@ -1999,7 +2112,7 @@ ngx_mail_do_auth(ngx_mail_session_t *s) } -static ngx_int_t +ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s) { ssize_t n;
--- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -739,7 +739,7 @@ ngx_int_t ngx_smtp_parse_command(ngx_mai 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;
--- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -102,7 +102,8 @@ ngx_module_t ngx_mail_proxy_module = { }; -static u_char smtp_ok[] = "235 2.0.0 OK" CRLF; +static u_char smtp_auth_ok[] = "235 2.0.0 OK" CRLF; +static u_char smtp_ok[] = "250 2.0.0 OK" CRLF; void @@ -516,11 +517,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_UNAUTH ? + 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"); @@ -537,31 +540,77 @@ 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=[UNAVAILABLE]" CRLF, - (s->esmtp ? "E" : ""), &s->smtp_helo, - &s->connection->addr_text, &s->login) - - line.data; - } else { - line.len = ngx_sprintf(line.data, - "XCLIENT PROTO=SMTP ADDR=%V LOGIN=%V " - "NAME=[UNAVAILABLE]" CRLF, - &s->connection->addr_text, &s->login) - - line.data; + line.len = ngx_sprintf(line.data, + "XCLIENT PROTO=%sSMTP%s%V ADDR=%V%s%V " + "NAME=[UNAVAILABLE]" CRLF, + (s->esmtp ? "E" : ""), + (s->smtp_helo.len ? " HELO=" : ""), &s->smtp_helo, + &s->connection->addr_text, + (s->login.len ? " LOGIN=" : ""), &s->login) + - line.data; + + s->mail_state = s->auth_method == NGX_MAIL_AUTH_UNAUTH ? + 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_palloc(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_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_palloc(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; + + s->mail_state = ngx_smtp_to; + + break; + + case ngx_smtp_helo: case ngx_smtp_xclient: + case ngx_smtp_to: - ngx_memcpy(s->proxy->buffer->start, smtp_ok, sizeof(smtp_ok) - 1); + if (s->auth_method == NGX_MAIL_AUTH_UNAUTH) { + ngx_memcpy(s->proxy->buffer->start, smtp_ok, sizeof(smtp_ok) - 1); + s->proxy->buffer->last = s->proxy->buffer->start + + sizeof(smtp_ok) - 1; + } else { + ngx_memcpy(s->proxy->buffer->start, smtp_auth_ok, + sizeof(smtp_auth_ok) - 1); + s->proxy->buffer->last = s->proxy->buffer->start + + sizeof(smtp_auth_ok) - 1; + } s->proxy->buffer->pos = s->proxy->buffer->start; - s->proxy->buffer->last = s->proxy->buffer->start + sizeof(smtp_ok) - 1; s->connection->read->handler = ngx_mail_proxy_handler; s->connection->write->handler = ngx_mail_proxy_handler; @@ -701,15 +750,24 @@ ngx_mail_proxy_read_response(ngx_mail_se switch (state) { case ngx_smtp_helo: - case ngx_smtp_noxclient: + case ngx_smtp_helo_from: + case ngx_smtp_helo_xclient: + case ngx_smtp_from: + case ngx_smtp_to: 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;