changeset 475:96428109ec3b

Merge with nginx 0.7.31.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 26 Jan 2009 03:15:35 +0300
parents b2e9a7371d49 (diff) 02687ee42c28 (current diff)
children a28a95b7a86d
files .hgtags src/mail/ngx_mail_proxy_module.c
diffstat 9 files changed, 147 insertions(+), 83 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
@@ -217,4 +222,6 @@ 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
--- 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
 
 
--- 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,
--- 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) {
--- 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;
--- 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;
         }
 
--- 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;
--- 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;
 
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -298,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);
@@ -445,7 +446,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;
@@ -466,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:
@@ -487,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);
@@ -505,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;
@@ -514,14 +522,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;
@@ -575,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;
@@ -594,6 +602,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;
@@ -633,9 +649,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);
@@ -657,37 +671,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);
@@ -702,9 +699,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;
@@ -712,37 +707,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);