Mercurial > hg > nginx
comparison src/mail/ngx_mail_parse.c @ 7843:b38728495e1a
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.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Wed, 19 May 2021 03:13:28 +0300 |
parents | 4b15f1b92100 |
children |
comparison
equal
deleted
inserted
replaced
7842:4b15f1b92100 | 7843:b38728495e1a |
---|---|
229 { | 229 { |
230 u_char ch, *p, *c, *dst, *src, *end; | 230 u_char ch, *p, *c, *dst, *src, *end; |
231 ngx_str_t *arg; | 231 ngx_str_t *arg; |
232 enum { | 232 enum { |
233 sw_start = 0, | 233 sw_start = 0, |
234 sw_tag, | |
235 sw_invalid, | |
234 sw_spaces_before_command, | 236 sw_spaces_before_command, |
235 sw_command, | 237 sw_command, |
236 sw_spaces_before_argument, | 238 sw_spaces_before_argument, |
237 sw_argument, | 239 sw_argument, |
238 sw_backslash, | 240 sw_backslash, |
251 | 253 |
252 switch (state) { | 254 switch (state) { |
253 | 255 |
254 /* IMAP tag */ | 256 /* IMAP tag */ |
255 case sw_start: | 257 case sw_start: |
258 s->tag_start = p; | |
259 state = sw_tag; | |
260 | |
261 /* fall through */ | |
262 | |
263 case sw_tag: | |
256 switch (ch) { | 264 switch (ch) { |
257 case ' ': | 265 case ' ': |
258 s->tag.len = p - s->buffer->start + 1; | 266 s->tag.len = p - s->tag_start + 1; |
259 s->tag.data = s->buffer->start; | 267 s->tag.data = s->tag_start; |
260 state = sw_spaces_before_command; | 268 state = sw_spaces_before_command; |
261 break; | 269 break; |
262 case CR: | 270 case CR: |
263 s->state = sw_start; | 271 case LF: |
264 return NGX_MAIL_PARSE_INVALID_COMMAND; | 272 goto invalid; |
265 case LF: | |
266 s->state = sw_start; | |
267 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
268 default: | 273 default: |
269 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') | 274 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z') |
270 && (ch < '0' || ch > '9') && ch != '-' && ch != '.' | 275 && (ch < '0' || ch > '9') && ch != '-' && ch != '.' |
271 && ch != '_') | 276 && ch != '_') |
272 { | 277 { |
273 goto invalid; | 278 goto invalid; |
274 } | 279 } |
275 if (p - s->buffer->start > 31) { | 280 if (p - s->tag_start > 31) { |
276 goto invalid; | 281 goto invalid; |
277 } | 282 } |
278 break; | 283 break; |
279 } | 284 } |
280 break; | 285 break; |
281 | 286 |
287 case sw_invalid: | |
288 goto invalid; | |
289 | |
282 case sw_spaces_before_command: | 290 case sw_spaces_before_command: |
283 switch (ch) { | 291 switch (ch) { |
284 case ' ': | 292 case ' ': |
285 break; | 293 break; |
286 case CR: | 294 case CR: |
287 s->state = sw_start; | 295 case LF: |
288 return NGX_MAIL_PARSE_INVALID_COMMAND; | 296 goto invalid; |
289 case LF: | |
290 s->state = sw_start; | |
291 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
292 default: | 297 default: |
293 s->cmd_start = p; | 298 s->cmd_start = p; |
294 state = sw_command; | 299 state = sw_command; |
295 break; | 300 break; |
296 } | 301 } |
406 | 411 |
407 default: | 412 default: |
408 goto invalid; | 413 goto invalid; |
409 } | 414 } |
410 | 415 |
416 s->cmd.data = s->cmd_start; | |
417 s->cmd.len = p - s->cmd_start; | |
418 | |
411 switch (ch) { | 419 switch (ch) { |
412 case ' ': | 420 case ' ': |
413 state = sw_spaces_before_argument; | 421 state = sw_spaces_before_argument; |
414 break; | 422 break; |
415 case CR: | 423 case CR: |
629 | 637 |
630 return NGX_OK; | 638 return NGX_OK; |
631 | 639 |
632 invalid: | 640 invalid: |
633 | 641 |
634 s->state = sw_start; | 642 s->state = sw_invalid; |
635 s->quoted = 0; | 643 s->quoted = 0; |
636 s->backslash = 0; | 644 s->backslash = 0; |
637 s->no_sync_literal = 0; | 645 s->no_sync_literal = 0; |
638 s->literal_len = 0; | 646 s->literal_len = 0; |
639 | 647 |
640 return NGX_MAIL_PARSE_INVALID_COMMAND; | 648 /* skip invalid command till LF */ |
649 | |
650 for ( /* void */ ; p < s->buffer->last; p++) { | |
651 if (*p == LF) { | |
652 s->state = sw_start; | |
653 s->buffer->pos = p + 1; | |
654 | |
655 /* detect non-synchronizing literals */ | |
656 | |
657 if ((size_t) (p - s->buffer->start) > sizeof("{1+}") - 1) { | |
658 p--; | |
659 | |
660 if (*p == CR) { | |
661 p--; | |
662 } | |
663 | |
664 if (*p == '}' && *(p - 1) == '+') { | |
665 s->quit = 1; | |
666 } | |
667 } | |
668 | |
669 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
670 } | |
671 } | |
672 | |
673 s->buffer->pos = p; | |
674 | |
675 return NGX_AGAIN; | |
641 } | 676 } |
642 | 677 |
643 | 678 |
644 ngx_int_t | 679 ngx_int_t |
645 ngx_mail_smtp_parse_command(ngx_mail_session_t *s) | 680 ngx_mail_smtp_parse_command(ngx_mail_session_t *s) |