Mercurial > hg > nginx-mail
comparison src/mail/ngx_mail_parse.c @ 436:9b19e26b2660
Mail: smtp pipelining support.
Basically, this does the following two changes (and corresponding
modifications of related code):
1. Does not reset session buffer unless it's reached it's end, and always
wait for LF to terminate command (even if we detected invalid command).
2. Record command name as the first argument to make it available for
handlers (since now we can't assume that command starts from s->buffer->start).
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 11 Sep 2008 15:26:25 +0400 |
parents | 52b28d322d76 |
children | d67e93e97b4a |
comparison
equal
deleted
inserted
replaced
435:e2df123bbbe2 | 436:9b19e26b2660 |
---|---|
620 { | 620 { |
621 u_char ch, *p, *c, c0, c1, c2, c3; | 621 u_char ch, *p, *c, c0, c1, c2, c3; |
622 ngx_str_t *arg; | 622 ngx_str_t *arg; |
623 enum { | 623 enum { |
624 sw_start = 0, | 624 sw_start = 0, |
625 sw_command, | |
626 sw_invalid, | |
625 sw_spaces_before_argument, | 627 sw_spaces_before_argument, |
626 sw_argument, | 628 sw_argument, |
627 sw_almost_done | 629 sw_almost_done |
628 } state; | 630 } state; |
629 | 631 |
634 | 636 |
635 switch (state) { | 637 switch (state) { |
636 | 638 |
637 /* SMTP command */ | 639 /* SMTP command */ |
638 case sw_start: | 640 case sw_start: |
641 s->arg_start = p; | |
642 state = sw_command; | |
643 | |
644 /* fall through */ | |
645 | |
646 case sw_command: | |
639 if (ch == ' ' || ch == CR || ch == LF) { | 647 if (ch == ' ' || ch == CR || ch == LF) { |
640 c = s->buffer->start; | 648 c = s->arg_start; |
641 | 649 |
642 if (p - c == 4) { | 650 if (p - c == 4) { |
643 | 651 |
644 c0 = ngx_toupper(c[0]); | 652 c0 = ngx_toupper(c[0]); |
645 c1 = ngx_toupper(c[1]); | 653 c1 = ngx_toupper(c[1]); |
713 #endif | 721 #endif |
714 } else { | 722 } else { |
715 goto invalid; | 723 goto invalid; |
716 } | 724 } |
717 | 725 |
726 arg = ngx_array_push(&s->args); | |
727 if (arg == NULL) { | |
728 return NGX_ERROR; | |
729 } | |
730 arg->len = p - s->arg_start; | |
731 arg->data = s->arg_start; | |
732 s->arg_start = NULL; | |
733 | |
718 switch (ch) { | 734 switch (ch) { |
719 case ' ': | 735 case ' ': |
720 state = sw_spaces_before_argument; | 736 state = sw_spaces_before_argument; |
721 break; | 737 break; |
722 case CR: | 738 case CR: |
731 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { | 747 if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) { |
732 goto invalid; | 748 goto invalid; |
733 } | 749 } |
734 | 750 |
735 break; | 751 break; |
752 | |
753 case sw_invalid: | |
754 goto invalid; | |
736 | 755 |
737 case sw_spaces_before_argument: | 756 case sw_spaces_before_argument: |
738 switch (ch) { | 757 switch (ch) { |
739 case ' ': | 758 case ' ': |
740 break; | 759 break; |
818 | 837 |
819 return NGX_OK; | 838 return NGX_OK; |
820 | 839 |
821 invalid: | 840 invalid: |
822 | 841 |
823 s->state = sw_start; | 842 s->state = sw_invalid; |
824 s->arg_start = NULL; | 843 s->arg_start = NULL; |
844 | |
845 /* skip invalid command till LF */ | |
846 | |
847 for (p = s->buffer->pos; p < s->buffer->last; p++) { | |
848 if (*p == LF) { | |
849 s->state = sw_start; | |
850 p++; | |
851 break; | |
852 } | |
853 } | |
854 | |
855 s->buffer->pos = p; | |
825 | 856 |
826 return NGX_MAIL_PARSE_INVALID_COMMAND; | 857 return NGX_MAIL_PARSE_INVALID_COMMAND; |
827 } | 858 } |
828 | 859 |
829 | 860 |
830 ngx_int_t | 861 ngx_int_t |
831 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) | 862 ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) |
832 { | 863 { |
833 ngx_str_t *arg; | 864 ngx_str_t *arg; |
865 ngx_uint_t nelts; | |
834 | 866 |
835 #if (NGX_MAIL_SSL) | 867 #if (NGX_MAIL_SSL) |
836 if (ngx_mail_starttls_only(s, c)) { | 868 if (ngx_mail_starttls_only(s, c)) { |
837 return NGX_MAIL_PARSE_INVALID_COMMAND; | 869 return NGX_MAIL_PARSE_INVALID_COMMAND; |
838 } | 870 } |
839 #endif | 871 #endif |
840 | 872 |
841 arg = s->args.elts; | 873 arg = s->args.elts; |
874 nelts = s->args.nelts; | |
875 | |
876 if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { | |
877 arg++; | |
878 nelts--; | |
879 } | |
842 | 880 |
843 if (arg[0].len == 5) { | 881 if (arg[0].len == 5) { |
844 | 882 |
845 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { | 883 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { |
846 | 884 |
847 if (s->args.nelts == 1) { | 885 if (nelts == 1) { |
848 return NGX_MAIL_AUTH_LOGIN; | 886 return NGX_MAIL_AUTH_LOGIN; |
849 } | 887 } |
850 | 888 |
851 return NGX_MAIL_PARSE_INVALID_COMMAND; | 889 return NGX_MAIL_PARSE_INVALID_COMMAND; |
852 } | 890 } |
853 | 891 |
854 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { | 892 if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { |
855 | 893 |
856 if (s->args.nelts == 1) { | 894 if (nelts == 1) { |
857 return NGX_MAIL_AUTH_PLAIN; | 895 return NGX_MAIL_AUTH_PLAIN; |
858 } | 896 } |
859 | 897 |
860 if (s->args.nelts == 2) { | 898 if (nelts == 2) { |
861 return ngx_mail_auth_plain(s, c, 1); | 899 return ngx_mail_auth_plain(s, c, |
900 (s->protocol == NGX_MAIL_SMTP_PROTOCOL) ? 2 : 1); | |
862 } | 901 } |
863 } | 902 } |
864 | 903 |
865 return NGX_MAIL_PARSE_INVALID_COMMAND; | 904 return NGX_MAIL_PARSE_INVALID_COMMAND; |
866 } | 905 } |
867 | 906 |
868 if (arg[0].len == 8) { | 907 if (arg[0].len == 8) { |
869 | 908 |
870 if (s->args.nelts != 1) { | 909 if (nelts != 1) { |
871 return NGX_MAIL_PARSE_INVALID_COMMAND; | 910 return NGX_MAIL_PARSE_INVALID_COMMAND; |
872 } | 911 } |
873 | 912 |
874 if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) { | 913 if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) { |
875 return NGX_MAIL_AUTH_CRAM_MD5; | 914 return NGX_MAIL_AUTH_CRAM_MD5; |