]> git.kaiwu.me - nginx.git/commitdiff
Mail: POP3 pipelining support.
authorMaxim Dounin <mdounin@mdounin.ru>
Wed, 19 May 2021 00:13:18 +0000 (03:13 +0300)
committerMaxim Dounin <mdounin@mdounin.ru>
Wed, 19 May 2021 00:13:18 +0000 (03:13 +0300)
The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a),
and ensures that nginx is able to properly handle or reject multiple POP3
commands, as required by the PIPELINING capability (RFC 2449).  The s->cmd
field is not really used and set for consistency.

src/mail/ngx_mail_parse.c
src/mail/ngx_mail_pop3_handler.c
src/mail/ngx_mail_proxy_module.c

index c4e8f0eaedc333ed6308536d580d3499c36d0dfe..e55010c60749001b0ce2a8a167b886f615eaed9c 100644 (file)
@@ -21,6 +21,8 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
     ngx_str_t  *arg;
     enum {
         sw_start = 0,
+        sw_command,
+        sw_invalid,
         sw_spaces_before_argument,
         sw_argument,
         sw_almost_done
@@ -35,8 +37,14 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
 
         /* POP3 command */
         case sw_start:
+            s->cmd_start = p;
+            state = sw_command;
+
+            /* fall through */
+
+        case sw_command:
             if (ch == ' ' || ch == CR || ch == LF) {
-                c = s->buffer->start;
+                c = s->cmd_start;
 
                 if (p - c == 4) {
 
@@ -85,6 +93,9 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
                     goto invalid;
                 }
 
+                s->cmd.data = s->cmd_start;
+                s->cmd.len = p - s->cmd_start;
+
                 switch (ch) {
                 case ' ':
                     state = sw_spaces_before_argument;
@@ -104,6 +115,9 @@ ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
 
             break;
 
+        case sw_invalid:
+            goto invalid;
+
         case sw_spaces_before_argument:
             switch (ch) {
             case ' ':
@@ -205,10 +219,22 @@ done:
 
 invalid:
 
-    s->state = sw_start;
+    s->state = sw_invalid;
     s->arg_start = NULL;
 
-    return NGX_MAIL_PARSE_INVALID_COMMAND;
+    /* skip invalid command till LF */
+
+    for ( /* void */ ; p < s->buffer->last; p++) {
+        if (*p == LF) {
+            s->state = sw_start;
+            s->buffer->pos = p + 1;
+            return NGX_MAIL_PARSE_INVALID_COMMAND;
+        }
+    }
+
+    s->buffer->pos = p;
+
+    return NGX_AGAIN;
 }
 
 
index edfd986812aad2a569ff5b6ef465db64a94024bd..226e7419bd45bfb272a59a598390185d26743404 100644 (file)
@@ -262,6 +262,10 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
         }
     }
 
+    if (s->buffer->pos < s->buffer->last) {
+        s->blocked = 1;
+    }
+
     switch (rc) {
 
     case NGX_DONE:
@@ -283,11 +287,14 @@ ngx_mail_pop3_auth_state(ngx_event_t *rev)
     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;
         }
 
         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
@@ -400,6 +407,8 @@ ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c)
     if (c->ssl == NULL) {
         sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
         if (sslcf->starttls) {
+            s->buffer->pos = s->buffer->start;
+            s->buffer->last = s->buffer->start;
             c->read->handler = ngx_mail_starttls_handler;
             return NGX_OK;
         }
index 38164af95567a3e75805a3fedd0f66212da22fc1..0f56d299e2abe1a3fd71dca990d7b8617268667b 100644 (file)
@@ -327,6 +327,10 @@ ngx_mail_proxy_pop3_handler(ngx_event_t *rev)
         c->log->action = NULL;
         ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in");
 
+        if (s->buffer->pos < s->buffer->last) {
+            ngx_post_event(c->write, &ngx_posted_events);
+        }
+
         ngx_mail_proxy_handler(s->connection->write);
 
         return;