comparison src/mail/ngx_mail_parse.c @ 7838:815c63581be4

Mail: POP3 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 POP3 commands, as required by the PIPELINING capability (RFC 2449). The s->cmd field is not really used and set for consistency.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 19 May 2021 03:13:18 +0300
parents ba8a8299b904
children 3974f4e56a4e
comparison
equal deleted inserted replaced
7837:ba8a8299b904 7838:815c63581be4
19 { 19 {
20 u_char ch, *p, *c, c0, c1, c2, c3; 20 u_char ch, *p, *c, c0, c1, c2, c3;
21 ngx_str_t *arg; 21 ngx_str_t *arg;
22 enum { 22 enum {
23 sw_start = 0, 23 sw_start = 0,
24 sw_command,
25 sw_invalid,
24 sw_spaces_before_argument, 26 sw_spaces_before_argument,
25 sw_argument, 27 sw_argument,
26 sw_almost_done 28 sw_almost_done
27 } state; 29 } state;
28 30
33 35
34 switch (state) { 36 switch (state) {
35 37
36 /* POP3 command */ 38 /* POP3 command */
37 case sw_start: 39 case sw_start:
40 s->cmd_start = p;
41 state = sw_command;
42
43 /* fall through */
44
45 case sw_command:
38 if (ch == ' ' || ch == CR || ch == LF) { 46 if (ch == ' ' || ch == CR || ch == LF) {
39 c = s->buffer->start; 47 c = s->cmd_start;
40 48
41 if (p - c == 4) { 49 if (p - c == 4) {
42 50
43 c0 = ngx_toupper(c[0]); 51 c0 = ngx_toupper(c[0]);
44 c1 = ngx_toupper(c[1]); 52 c1 = ngx_toupper(c[1]);
83 91
84 } else { 92 } else {
85 goto invalid; 93 goto invalid;
86 } 94 }
87 95
96 s->cmd.data = s->cmd_start;
97 s->cmd.len = p - s->cmd_start;
98
88 switch (ch) { 99 switch (ch) {
89 case ' ': 100 case ' ':
90 state = sw_spaces_before_argument; 101 state = sw_spaces_before_argument;
91 break; 102 break;
92 case CR: 103 case CR:
101 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { 112 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
102 goto invalid; 113 goto invalid;
103 } 114 }
104 115
105 break; 116 break;
117
118 case sw_invalid:
119 goto invalid;
106 120
107 case sw_spaces_before_argument: 121 case sw_spaces_before_argument:
108 switch (ch) { 122 switch (ch) {
109 case ' ': 123 case ' ':
110 break; 124 break;
203 217
204 return NGX_OK; 218 return NGX_OK;
205 219
206 invalid: 220 invalid:
207 221
208 s->state = sw_start; 222 s->state = sw_invalid;
209 s->arg_start = NULL; 223 s->arg_start = NULL;
210 224
211 return NGX_MAIL_PARSE_INVALID_COMMAND; 225 /* skip invalid command till LF */
226
227 for ( /* void */ ; p < s->buffer->last; p++) {
228 if (*p == LF) {
229 s->state = sw_start;
230 s->buffer->pos = p + 1;
231 return NGX_MAIL_PARSE_INVALID_COMMAND;
232 }
233 }
234
235 s->buffer->pos = p;
236
237 return NGX_AGAIN;
212 } 238 }
213 239
214 240
215 ngx_int_t 241 ngx_int_t
216 ngx_mail_imap_parse_command(ngx_mail_session_t *s) 242 ngx_mail_imap_parse_command(ngx_mail_session_t *s)