Welcome! Log In Create A New Profile

Advanced

[nginx] Mail: IMAP pipelining support.

Maxim Dounin
May 18, 2021 09:28PM
details: https://hg.nginx.org/nginx/rev/b38728495e1a
branches:
changeset: 7843:b38728495e1a
user: Maxim Dounin <mdounin@mdounin.ru>
date: Wed May 19 03:13:28 2021 +0300
description:
Mail: IMAP pipelining support.

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 IMAP
commands. The s->cmd field is not really used and set for consistency.

Non-synchronizing literals handling in invalid/unknown commands is limited,
so when a non-synchronizing literal is detected at the end of a discarded
line, the connection is closed.

diffstat:

src/mail/ngx_mail.h | 1 +
src/mail/ngx_mail_imap_handler.c | 17 +++++++---
src/mail/ngx_mail_parse.c | 61 +++++++++++++++++++++++++++++++--------
src/mail/ngx_mail_proxy_module.c | 4 ++
4 files changed, 65 insertions(+), 18 deletions(-)

diffs (190 lines):

diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail.h
--- a/src/mail/ngx_mail.h Wed May 19 03:13:26 2021 +0300
+++ b/src/mail/ngx_mail.h Wed May 19 03:13:28 2021 +0300
@@ -236,6 +236,7 @@ typedef struct {
/* used to parse POP3/IMAP/SMTP command */

ngx_uint_t state;
+ u_char *tag_start;
u_char *cmd_start;
u_char *arg_start;
ngx_uint_t literal_len;
diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_imap_handler.c
--- a/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:26 2021 +0300
+++ b/src/mail/ngx_mail_imap_handler.c Wed May 19 03:13:28 2021 +0300
@@ -226,6 +226,10 @@ ngx_mail_imap_auth_state(ngx_event_t *re
ngx_str_set(&s->out, imap_next);
}

+ if (s->buffer->pos < s->buffer->last) {
+ s->blocked = 1;
+ }
+
switch (rc) {

case NGX_DONE:
@@ -275,13 +279,14 @@ ngx_mail_imap_auth_state(ngx_event_t *re

if (s->state) {
/* preserve tag */
- s->arg_start = s->buffer->start + s->tag.len;
- s->buffer->pos = s->arg_start;
- s->buffer->last = s->arg_start;
+ s->arg_start = s->buffer->pos;

} else {
- 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->tag.len = 0;
}
}
@@ -459,6 +464,8 @@ ngx_mail_imap_starttls(ngx_mail_session_
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;
}
diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_parse.c
--- a/src/mail/ngx_mail_parse.c Wed May 19 03:13:26 2021 +0300
+++ b/src/mail/ngx_mail_parse.c Wed May 19 03:13:28 2021 +0300
@@ -231,6 +231,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses
ngx_str_t *arg;
enum {
sw_start = 0,
+ sw_tag,
+ sw_invalid,
sw_spaces_before_command,
sw_command,
sw_spaces_before_argument,
@@ -253,18 +255,21 @@ ngx_mail_imap_parse_command(ngx_mail_ses

/* IMAP tag */
case sw_start:
+ s->tag_start = p;
+ state = sw_tag;
+
+ /* fall through */
+
+ case sw_tag:
switch (ch) {
case ' ':
- s->tag.len = p - s->buffer->start + 1;
- s->tag.data = s->buffer->start;
+ s->tag.len = p - s->tag_start + 1;
+ s->tag.data = s->tag_start;
state = sw_spaces_before_command;
break;
case CR:
- s->state = sw_start;
- return NGX_MAIL_PARSE_INVALID_COMMAND;
case LF:
- s->state = sw_start;
- return NGX_MAIL_PARSE_INVALID_COMMAND;
+ goto invalid;
default:
if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')
&& (ch < '0' || ch > '9') && ch != '-' && ch != '.'
@@ -272,23 +277,23 @@ ngx_mail_imap_parse_command(ngx_mail_ses
{
goto invalid;
}
- if (p - s->buffer->start > 31) {
+ if (p - s->tag_start > 31) {
goto invalid;
}
break;
}
break;

+ case sw_invalid:
+ goto invalid;
+
case sw_spaces_before_command:
switch (ch) {
case ' ':
break;
case CR:
- s->state = sw_start;
- return NGX_MAIL_PARSE_INVALID_COMMAND;
case LF:
- s->state = sw_start;
- return NGX_MAIL_PARSE_INVALID_COMMAND;
+ goto invalid;
default:
s->cmd_start = p;
state = sw_command;
@@ -408,6 +413,9 @@ ngx_mail_imap_parse_command(ngx_mail_ses
goto invalid;
}

+ s->cmd.data = s->cmd_start;
+ s->cmd.len = p - s->cmd_start;
+
switch (ch) {
case ' ':
state = sw_spaces_before_argument;
@@ -631,13 +639,40 @@ done:

invalid:

- s->state = sw_start;
+ s->state = sw_invalid;
s->quoted = 0;
s->backslash = 0;
s->no_sync_literal = 0;
s->literal_len = 0;

- 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;
+
+ /* detect non-synchronizing literals */
+
+ if ((size_t) (p - s->buffer->start) > sizeof("{1+}") - 1) {
+ p--;
+
+ if (*p == CR) {
+ p--;
+ }
+
+ if (*p == '}' && *(p - 1) == '+') {
+ s->quit = 1;
+ }
+ }
+
+ return NGX_MAIL_PARSE_INVALID_COMMAND;
+ }
+ }
+
+ s->buffer->pos = p;
+
+ return NGX_AGAIN;
}


diff -r 4b15f1b92100 -r b38728495e1a src/mail/ngx_mail_proxy_module.c
--- a/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:26 2021 +0300
+++ b/src/mail/ngx_mail_proxy_module.c Wed May 19 03:13:28 2021 +0300
@@ -486,6 +486,10 @@ ngx_mail_proxy_imap_handler(ngx_event_t
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;
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[nginx] Mail: IMAP pipelining support.

Maxim Dounin 229 May 18, 2021 09:28PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 240
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready