diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c index c4e8f0eae..e55010c60 100644 --- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -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; } diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c index edfd98681..226e7419b 100644 --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -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; } diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index 38164af95..0f56d299e 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -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;