Mercurial > hg > nginx-mail
diff src/mail/ngx_mail_handler.c @ 400:f1e2fab7a46c
Mail: smtp proxy without authentication.
Activated by auth method "unauth" in smtp_auth directive.
Waits for MAIL FROM and first RCPT TO from client, asks auth_http for
backend with additional headers Auth-SMTP-Helo, Auth-SMTP-From,
Auth-SMTP-To, and establishes connection to backend.
Auth-SMTP-From/To currently contain full command (e.g. "mail from: <>"),
this may change in future.
The functionality was designed to take off load from real smtp servers.
Additionally it may be used to implement pop-before-smtp authentication
(but dont do it unless you really need it - use real auth instead).
Current bug-features:
- If only "unauth" method activated in config, other methods (e.g. plain,
login) not advertised but accepted. Make sure your auth server handles
this gracefully.
- If backend server returns error on MAIL FROM / RCPT TO command while
proxy tunnel setup, nginx will close connection to client with 4xx
error. One may use proxy_pass_error_message directive to pass original
error message to client.
- Syntax of MAIL FROM / RCPT TO commands from client isn't checked.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 22 Jul 2007 23:55:12 +0000 |
parents | f9e6413396d4 |
children | d4cac61d8e95 |
line wrap: on
line diff
--- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -55,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 @@ -1548,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; @@ -1580,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) @@ -1706,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; @@ -1731,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; @@ -1761,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;