3 * Copyright (C) Igor Sysoev
7 #include <ngx_config.h>
14 ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
16 u_char ch, *p, *c, c0, c1, c2, c3;
20 sw_spaces_before_argument,
27 for (p = s->buffer->pos; p < s->buffer->last; p++) {
34 if (ch == ' ' || ch == CR || ch == LF) {
39 c0 = ngx_toupper(c[0]);
40 c1 = ngx_toupper(c[1]);
41 c2 = ngx_toupper(c[2]);
42 c3 = ngx_toupper(c[3]);
44 if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R')
46 s->command = NGX_POP3_USER;
48 } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S')
50 s->command = NGX_POP3_PASS;
52 } else if (c0 == 'A' && c1 == 'P' && c2 == 'O' && c3 == 'P')
54 s->command = NGX_POP3_APOP;
56 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T')
58 s->command = NGX_POP3_QUIT;
60 } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A')
62 s->command = NGX_POP3_CAPA;
64 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H')
66 s->command = NGX_POP3_AUTH;
68 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P')
70 s->command = NGX_POP3_NOOP;
72 } else if (c0 == 'S' && c1 == 'T' && c2 == 'L' && c3 == 'S')
74 s->command = NGX_POP3_STLS;
86 state = sw_spaces_before_argument;
89 state = sw_almost_done;
97 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
103 case sw_spaces_before_argument:
108 state = sw_almost_done;
115 if (s->args.nelts <= 2) {
130 * the space should be considered as part of the at username
131 * or password, but not of argument in other commands
134 if (s->command == NGX_POP3_USER
135 || s->command == NGX_POP3_PASS)
144 arg = ngx_array_push(&s->args);
148 arg->len = p - s->arg_start;
149 arg->data = s->arg_start;
154 state = sw_spaces_before_argument;
157 state = sw_almost_done;
186 s->buffer->pos = p + 1;
189 arg = ngx_array_push(&s->args);
193 arg->len = s->arg_end - s->arg_start;
194 arg->data = s->arg_start;
198 s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument;
207 return NGX_MAIL_PARSE_INVALID_COMMAND;
212 ngx_mail_imap_parse_command(ngx_mail_session_t *s)
218 sw_spaces_before_command,
220 sw_spaces_before_argument,
224 sw_no_sync_literal_argument,
225 sw_start_literal_argument,
227 sw_end_literal_argument,
233 for (p = s->buffer->pos; p < s->buffer->last; p++) {
242 s->tag.len = p - s->buffer->start + 1;
243 s->tag.data = s->buffer->start;
244 state = sw_spaces_before_command;
248 return NGX_MAIL_PARSE_INVALID_COMMAND;
251 return NGX_MAIL_PARSE_INVALID_COMMAND;
255 case sw_spaces_before_command:
261 return NGX_MAIL_PARSE_INVALID_COMMAND;
264 return NGX_MAIL_PARSE_INVALID_COMMAND;
273 if (ch == ' ' || ch == CR || ch == LF) {
280 if ((c[0] == 'N' || c[0] == 'n')
281 && (c[1] == 'O'|| c[1] == 'o')
282 && (c[2] == 'O'|| c[2] == 'o')
283 && (c[3] == 'P'|| c[3] == 'p'))
285 s->command = NGX_IMAP_NOOP;
293 if ((c[0] == 'L'|| c[0] == 'l')
294 && (c[1] == 'O'|| c[1] == 'o')
295 && (c[2] == 'G'|| c[2] == 'g')
296 && (c[3] == 'I'|| c[3] == 'i')
297 && (c[4] == 'N'|| c[4] == 'n'))
299 s->command = NGX_IMAP_LOGIN;
307 if ((c[0] == 'L'|| c[0] == 'l')
308 && (c[1] == 'O'|| c[1] == 'o')
309 && (c[2] == 'G'|| c[2] == 'g')
310 && (c[3] == 'O'|| c[3] == 'o')
311 && (c[4] == 'U'|| c[4] == 'u')
312 && (c[5] == 'T'|| c[5] == 't'))
314 s->command = NGX_IMAP_LOGOUT;
323 if ((c[0] == 'S'|| c[0] == 's')
324 && (c[1] == 'T'|| c[1] == 't')
325 && (c[2] == 'A'|| c[2] == 'a')
326 && (c[3] == 'R'|| c[3] == 'r')
327 && (c[4] == 'T'|| c[4] == 't')
328 && (c[5] == 'T'|| c[5] == 't')
329 && (c[6] == 'L'|| c[6] == 'l')
330 && (c[7] == 'S'|| c[7] == 's'))
332 s->command = NGX_IMAP_STARTTLS;
341 if ((c[0] == 'C'|| c[0] == 'c')
342 && (c[1] == 'A'|| c[1] == 'a')
343 && (c[2] == 'P'|| c[2] == 'p')
344 && (c[3] == 'A'|| c[3] == 'a')
345 && (c[4] == 'B'|| c[4] == 'b')
346 && (c[5] == 'I'|| c[5] == 'i')
347 && (c[6] == 'L'|| c[6] == 'l')
348 && (c[7] == 'I'|| c[7] == 'i')
349 && (c[8] == 'T'|| c[8] == 't')
350 && (c[9] == 'Y'|| c[9] == 'y'))
352 s->command = NGX_IMAP_CAPABILITY;
360 if ((c[0] == 'A'|| c[0] == 'a')
361 && (c[1] == 'U'|| c[1] == 'u')
362 && (c[2] == 'T'|| c[2] == 't')
363 && (c[3] == 'H'|| c[3] == 'h')
364 && (c[4] == 'E'|| c[4] == 'e')
365 && (c[5] == 'N'|| c[5] == 'n')
366 && (c[6] == 'T'|| c[6] == 't')
367 && (c[7] == 'I'|| c[7] == 'i')
368 && (c[8] == 'C'|| c[8] == 'c')
369 && (c[9] == 'A'|| c[9] == 'a')
370 && (c[10] == 'T'|| c[10] == 't')
371 && (c[11] == 'E'|| c[11] == 'e'))
373 s->command = NGX_IMAP_AUTHENTICATE;
386 state = sw_spaces_before_argument;
389 state = sw_almost_done;
397 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
403 case sw_spaces_before_argument:
408 state = sw_almost_done;
415 if (s->args.nelts <= 2) {
417 s->arg_start = p + 1;
423 if (s->args.nelts <= 2) {
429 if (s->args.nelts <= 2) {
439 if (ch == ' ' && s->quoted) {
453 arg = ngx_array_push(&s->args);
457 arg->len = p - s->arg_start;
458 arg->data = s->arg_start;
464 state = sw_spaces_before_argument;
467 state = sw_almost_done;
476 state = sw_backslash;
493 if (ch >= '0' && ch <= '9') {
494 s->literal_len = s->literal_len * 10 + (ch - '0');
498 state = sw_start_literal_argument;
502 state = sw_no_sync_literal_argument;
507 case sw_no_sync_literal_argument:
509 s->no_sync_literal = 1;
510 state = sw_start_literal_argument;
515 case sw_start_literal_argument:
520 s->buffer->pos = p + 1;
521 s->arg_start = p + 1;
522 if (s->no_sync_literal == 0) {
523 s->state = sw_literal_argument;
524 return NGX_IMAP_NEXT;
526 state = sw_literal_argument;
527 s->no_sync_literal = 0;
534 case sw_literal_argument:
535 if (s->literal_len && --s->literal_len) {
539 arg = ngx_array_push(&s->args);
543 arg->len = p + 1 - s->arg_start;
544 arg->data = s->arg_start;
546 state = sw_end_literal_argument;
550 case sw_end_literal_argument:
553 if (s->args.nelts <= 2) {
559 state = sw_almost_done;
564 state = sw_spaces_before_argument;
586 s->buffer->pos = p + 1;
589 arg = ngx_array_push(&s->args);
593 arg->len = s->arg_end - s->arg_start;
594 arg->data = s->arg_start;
599 s->no_sync_literal = 0;
603 s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
611 s->no_sync_literal = 0;
614 return NGX_MAIL_PARSE_INVALID_COMMAND;
619 ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
621 u_char ch, *p, *c, c0, c1, c2, c3;
625 sw_spaces_before_argument,
632 for (p = s->buffer->pos; p < s->buffer->last; p++) {
639 if (ch == ' ' || ch == CR || ch == LF) {
640 c = s->buffer->start;
644 c0 = ngx_toupper(c[0]);
645 c1 = ngx_toupper(c[1]);
646 c2 = ngx_toupper(c[2]);
647 c3 = ngx_toupper(c[3]);
649 if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O')
651 s->command = NGX_SMTP_HELO;
653 } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O')
655 s->command = NGX_SMTP_EHLO;
657 } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T')
659 s->command = NGX_SMTP_QUIT;
661 } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H')
663 s->command = NGX_SMTP_AUTH;
665 } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P')
667 s->command = NGX_SMTP_NOOP;
669 } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L')
671 s->command = NGX_SMTP_MAIL;
673 } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T')
675 s->command = NGX_SMTP_RSET;
677 } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T')
679 s->command = NGX_SMTP_RCPT;
681 } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y')
683 s->command = NGX_SMTP_VRFY;
685 } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N')
687 s->command = NGX_SMTP_EXPN;
689 } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P')
691 s->command = NGX_SMTP_HELP;
697 } else if (p - c == 8) {
699 if ((c[0] == 'S'|| c[0] == 's')
700 && (c[1] == 'T'|| c[1] == 't')
701 && (c[2] == 'A'|| c[2] == 'a')
702 && (c[3] == 'R'|| c[3] == 'r')
703 && (c[4] == 'T'|| c[4] == 't')
704 && (c[5] == 'T'|| c[5] == 't')
705 && (c[6] == 'L'|| c[6] == 'l')
706 && (c[7] == 'S'|| c[7] == 's'))
708 s->command = NGX_SMTP_STARTTLS;
720 state = sw_spaces_before_argument;
723 state = sw_almost_done;
731 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
737 case sw_spaces_before_argument:
742 state = sw_almost_done;
749 if (s->args.nelts <= 10) {
763 arg = ngx_array_push(&s->args);
767 arg->len = p - s->arg_start;
768 arg->data = s->arg_start;
773 state = sw_spaces_before_argument;
776 state = sw_almost_done;
805 s->buffer->pos = p + 1;
808 arg = ngx_array_push(&s->args);
812 arg->len = s->arg_end - s->arg_start;
813 arg->data = s->arg_start;
817 s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument;
826 return NGX_MAIL_PARSE_INVALID_COMMAND;
831 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c)
836 if (ngx_mail_starttls_only(s, c)) {
837 return NGX_MAIL_PARSE_INVALID_COMMAND;
843 if (arg[0].len == 5) {
845 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
847 if (s->args.nelts == 1) {
848 return NGX_MAIL_AUTH_LOGIN;
851 return NGX_MAIL_PARSE_INVALID_COMMAND;
854 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
856 if (s->args.nelts == 1) {
857 return NGX_MAIL_AUTH_PLAIN;
860 if (s->args.nelts == 2) {
861 return ngx_mail_auth_plain(s, c, 1);
865 return NGX_MAIL_PARSE_INVALID_COMMAND;
868 if (arg[0].len == 8) {
870 if (s->args.nelts != 1) {
871 return NGX_MAIL_PARSE_INVALID_COMMAND;
874 if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) {
875 return NGX_MAIL_AUTH_CRAM_MD5;
879 return NGX_MAIL_PARSE_INVALID_COMMAND;