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;