Mercurial > hg > nginx-vendor-current
comparison src/imap/ngx_imap_handler.c @ 252:644510700914 NGINX_0_4_11
nginx 0.4.11
*) Feature: the POP3 proxy supports the AUTH LOGIN PLAIN and CRAM-MD5.
*) Feature: the ngx_http_perl_module supports the $r->allow_ranges
method.
*) Bugfix: if the APOP was enabled in the POP3 proxy, then the
USER/PASS commands might not work; bug appeared in 0.4.10.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 25 Oct 2006 00:00:00 +0400 |
parents | fbf2b2f66c9f |
children | 6ae1357b7b7c |
comparison
equal
deleted
inserted
replaced
251:16ffa8ae5759 | 252:644510700914 |
---|---|
30 ngx_string("-ERR internal server error" CRLF), | 30 ngx_string("-ERR internal server error" CRLF), |
31 ngx_string("* BAD internal server error" CRLF), | 31 ngx_string("* BAD internal server error" CRLF), |
32 }; | 32 }; |
33 | 33 |
34 static u_char pop3_ok[] = "+OK" CRLF; | 34 static u_char pop3_ok[] = "+OK" CRLF; |
35 static u_char pop3_next[] = "+ " CRLF; | |
36 static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; | |
37 static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; | |
35 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; | 38 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; |
36 | 39 |
37 static u_char imap_star[] = "* "; | 40 static u_char imap_star[] = "* "; |
38 static u_char imap_ok[] = "OK completed" CRLF; | 41 static u_char imap_ok[] = "OK completed" CRLF; |
39 static u_char imap_next[] = "+ OK" CRLF; | 42 static u_char imap_next[] = "+ OK" CRLF; |
545 s->login_attempt++; | 548 s->login_attempt++; |
546 | 549 |
547 ngx_imap_auth_http_init(s); | 550 ngx_imap_auth_http_init(s); |
548 | 551 |
549 return; | 552 return; |
550 | 553 } |
551 } else { | 554 |
552 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | 555 rc = NGX_IMAP_PARSE_INVALID_COMMAND; |
553 } | |
554 | |
555 break; | 556 break; |
556 | 557 |
557 case NGX_IMAP_CAPABILITY: | 558 case NGX_IMAP_CAPABILITY: |
558 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | 559 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); |
559 | 560 |
664 | 665 |
665 | 666 |
666 void | 667 void |
667 ngx_pop3_auth_state(ngx_event_t *rev) | 668 ngx_pop3_auth_state(ngx_event_t *rev) |
668 { | 669 { |
669 u_char *text; | 670 u_char *text, *p, *last; |
670 ssize_t size; | 671 ssize_t size; |
671 ngx_int_t rc; | 672 ngx_int_t rc; |
672 ngx_str_t *arg; | 673 ngx_str_t *arg, salt, plain; |
673 ngx_connection_t *c; | 674 ngx_connection_t *c; |
674 ngx_imap_session_t *s; | 675 ngx_imap_session_t *s; |
675 ngx_imap_core_srv_conf_t *cscf; | 676 ngx_imap_core_srv_conf_t *cscf; |
676 #if (NGX_IMAP_SSL) | 677 #if (NGX_IMAP_SSL) |
677 ngx_imap_ssl_conf_t *sslcf; | 678 ngx_imap_ssl_conf_t *sslcf; |
728 ngx_memcpy(s->login.data, arg[0].data, s->login.len); | 729 ngx_memcpy(s->login.data, arg[0].data, s->login.len); |
729 | 730 |
730 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | 731 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, |
731 "pop3 login: \"%V\"", &s->login); | 732 "pop3 login: \"%V\"", &s->login); |
732 | 733 |
733 } else { | 734 break; |
734 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | 735 } |
735 } | 736 |
736 | 737 rc = NGX_IMAP_PARSE_INVALID_COMMAND; |
737 break; | 738 break; |
738 | 739 |
739 case NGX_POP3_CAPA: | 740 case NGX_POP3_CAPA: |
740 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | 741 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); |
741 | 742 |
797 } | 798 } |
798 | 799 |
799 ngx_imap_auth_http_init(s); | 800 ngx_imap_auth_http_init(s); |
800 | 801 |
801 return; | 802 return; |
802 | 803 } |
803 } else { | 804 |
805 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
806 break; | |
807 | |
808 case NGX_POP3_AUTH: | |
809 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | |
810 | |
811 if (s->args.nelts == 0) { | |
812 size = cscf->pop3_auth_capability.len; | |
813 text = cscf->pop3_auth_capability.data; | |
814 s->state = 0; | |
815 break; | |
816 } | |
817 | |
818 if (s->args.nelts != 1) { | |
804 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | 819 rc = NGX_IMAP_PARSE_INVALID_COMMAND; |
805 } | 820 break; |
806 | 821 } |
822 | |
823 arg = s->args.elts; | |
824 | |
825 if (arg[0].len == 5) { | |
826 | |
827 if (ngx_strncasecmp(arg[0].data, "LOGIN", 5) == 0) { | |
828 s->imap_state = ngx_pop3_auth_login_username; | |
829 | |
830 size = sizeof(pop3_username) - 1; | |
831 text = pop3_username; | |
832 | |
833 break; | |
834 | |
835 } else if (ngx_strncasecmp(arg[0].data, "PLAIN", 5) == 0) { | |
836 s->imap_state = ngx_pop3_auth_plain; | |
837 | |
838 size = sizeof(pop3_next) - 1; | |
839 text = pop3_next; | |
840 | |
841 break; | |
842 } | |
843 | |
844 } else if (arg[0].len == 8 | |
845 && ngx_strncasecmp(arg[0].data, "CRAM-MD5", 8) == 0) | |
846 { | |
847 s->imap_state = ngx_pop3_auth_cram_md5; | |
848 | |
849 text = ngx_palloc(c->pool, | |
850 sizeof("+ " CRLF) - 1 | |
851 + ngx_base64_encoded_length(s->salt.len)); | |
852 if (text == NULL) { | |
853 ngx_imap_session_internal_server_error(s); | |
854 return; | |
855 } | |
856 | |
857 text[0] = '+'; text[1]= ' '; | |
858 salt.data = &text[2]; | |
859 s->salt.len -= 2; | |
860 | |
861 ngx_encode_base64(&salt, &s->salt); | |
862 | |
863 s->salt.len += 2; | |
864 size = 2 + salt.len; | |
865 text[size++] = CR; text[size++] = LF; | |
866 | |
867 break; | |
868 } | |
869 | |
870 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
807 break; | 871 break; |
808 | 872 |
809 case NGX_POP3_QUIT: | 873 case NGX_POP3_QUIT: |
810 s->quit = 1; | 874 s->quit = 1; |
811 break; | 875 break; |
867 } | 931 } |
868 | 932 |
869 ngx_imap_auth_http_init(s); | 933 ngx_imap_auth_http_init(s); |
870 | 934 |
871 return; | 935 return; |
872 | 936 } |
873 } else { | 937 |
874 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | 938 rc = NGX_IMAP_PARSE_INVALID_COMMAND; |
875 } | |
876 | |
877 break; | 939 break; |
878 | 940 |
879 case NGX_POP3_CAPA: | 941 case NGX_POP3_CAPA: |
880 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); | 942 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); |
881 size = cscf->pop3_capability.len; | 943 size = cscf->pop3_capability.len; |
898 break; | 960 break; |
899 | 961 |
900 /* suppress warinings */ | 962 /* suppress warinings */ |
901 case ngx_pop3_passwd: | 963 case ngx_pop3_passwd: |
902 break; | 964 break; |
965 | |
966 case ngx_pop3_auth_login_username: | |
967 arg = s->args.elts; | |
968 s->imap_state = ngx_pop3_auth_login_password; | |
969 | |
970 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
971 "pop3 auth login username: \"%V\"", &arg[0]); | |
972 | |
973 s->login.data = ngx_palloc(c->pool, | |
974 ngx_base64_decoded_length(arg[0].len)); | |
975 if (s->login.data == NULL){ | |
976 ngx_imap_session_internal_server_error(s); | |
977 return; | |
978 } | |
979 | |
980 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
981 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
982 "client sent invalid base64 encoding " | |
983 "in AUTH LOGIN command"); | |
984 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
985 break; | |
986 } | |
987 | |
988 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
989 "pop3 auth login username: \"%V\"", &s->login); | |
990 | |
991 size = sizeof(pop3_password) - 1; | |
992 text = pop3_password; | |
993 | |
994 break; | |
995 | |
996 case ngx_pop3_auth_login_password: | |
997 arg = s->args.elts; | |
998 | |
999 #if (NGX_DEBUG_IMAP_PASSWD) | |
1000 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1001 "pop3 auth login password: \"%V\"", &arg[0]); | |
1002 #endif | |
1003 | |
1004 s->passwd.data = ngx_palloc(c->pool, | |
1005 ngx_base64_decoded_length(arg[0].len)); | |
1006 if (s->passwd.data == NULL){ | |
1007 ngx_imap_session_internal_server_error(s); | |
1008 return; | |
1009 } | |
1010 | |
1011 if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { | |
1012 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1013 "client sent invalid base64 encoding " | |
1014 "in AUTH LOGIN command"); | |
1015 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1016 break; | |
1017 } | |
1018 | |
1019 #if (NGX_DEBUG_IMAP_PASSWD) | |
1020 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1021 "pop3 auth login password: \"%V\"", &s->passwd); | |
1022 #endif | |
1023 | |
1024 s->args.nelts = 0; | |
1025 s->buffer->pos = s->buffer->start; | |
1026 s->buffer->last = s->buffer->start; | |
1027 | |
1028 if (rev->timer_set) { | |
1029 ngx_del_timer(rev); | |
1030 } | |
1031 | |
1032 ngx_imap_auth_http_init(s); | |
1033 | |
1034 return; | |
1035 | |
1036 case ngx_pop3_auth_plain: | |
1037 arg = s->args.elts; | |
1038 | |
1039 #if (NGX_DEBUG_IMAP_PASSWD) | |
1040 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1041 "pop3 auth plain: \"%V\"", &arg[0]); | |
1042 #endif | |
1043 | |
1044 plain.data = ngx_palloc(c->pool, | |
1045 ngx_base64_decoded_length(arg[0].len)); | |
1046 if (plain.data == NULL){ | |
1047 ngx_imap_session_internal_server_error(s); | |
1048 return; | |
1049 } | |
1050 | |
1051 if (ngx_decode_base64(&plain, &arg[0]) != NGX_OK) { | |
1052 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1053 "client sent invalid base64 encoding " | |
1054 "in AUTH PLAIN command"); | |
1055 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1056 break; | |
1057 } | |
1058 | |
1059 p = plain.data; | |
1060 last = p + plain.len; | |
1061 | |
1062 while (p < last && *p++) { /* void */ } | |
1063 | |
1064 if (p == last) { | |
1065 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1066 "client sent invalid login " | |
1067 "in AUTH PLAIN command"); | |
1068 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1069 break; | |
1070 } | |
1071 | |
1072 s->login.data = p; | |
1073 | |
1074 while (p < last && *p) { p++; } | |
1075 | |
1076 if (p == last) { | |
1077 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1078 "client sent invalid password " | |
1079 "in AUTH PLAIN command"); | |
1080 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1081 break; | |
1082 } | |
1083 | |
1084 s->login.len = p++ - s->login.data; | |
1085 | |
1086 s->passwd.len = last - p; | |
1087 s->passwd.data = p; | |
1088 | |
1089 #if (NGX_DEBUG_IMAP_PASSWD) | |
1090 ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1091 "pop3 auth plain: \"%V\" \"%V\"", | |
1092 &s->login, &s->passwd); | |
1093 #endif | |
1094 | |
1095 s->args.nelts = 0; | |
1096 s->buffer->pos = s->buffer->start; | |
1097 s->buffer->last = s->buffer->start; | |
1098 | |
1099 if (rev->timer_set) { | |
1100 ngx_del_timer(rev); | |
1101 } | |
1102 | |
1103 ngx_imap_auth_http_init(s); | |
1104 | |
1105 return; | |
1106 | |
1107 case ngx_pop3_auth_cram_md5: | |
1108 arg = s->args.elts; | |
1109 | |
1110 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1111 "pop3 auth cram-md5: \"%V\"", &arg[0]); | |
1112 | |
1113 s->login.data = ngx_palloc(c->pool, | |
1114 ngx_base64_decoded_length(arg[0].len)); | |
1115 if (s->login.data == NULL){ | |
1116 ngx_imap_session_internal_server_error(s); | |
1117 return; | |
1118 } | |
1119 | |
1120 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
1121 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1122 "client sent invalid base64 encoding " | |
1123 "in AUTH CRAM-MD5 command"); | |
1124 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1125 break; | |
1126 } | |
1127 | |
1128 p = s->login.data; | |
1129 last = p + s->login.len; | |
1130 | |
1131 while (p < last) { | |
1132 if (*p++ == ' ') { | |
1133 s->login.len = p - s->login.data - 1; | |
1134 s->passwd.len = last - p; | |
1135 s->passwd.data = p; | |
1136 break; | |
1137 } | |
1138 } | |
1139 | |
1140 if (s->passwd.len != 32) { | |
1141 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1142 "client sent invalid CRAM-MD5 hash " | |
1143 "in AUTH CRAM-MD5 command"); | |
1144 rc = NGX_IMAP_PARSE_INVALID_COMMAND; | |
1145 break; | |
1146 } | |
1147 | |
1148 ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, | |
1149 "pop3 auth cram-md5: \"%V\" \"%V\"", | |
1150 &s->login, &s->passwd); | |
1151 | |
1152 s->auth_method = NGX_IMAP_AUTH_CRAM_MD5; | |
1153 | |
1154 s->args.nelts = 0; | |
1155 s->buffer->pos = s->buffer->start; | |
1156 s->buffer->last = s->buffer->start; | |
1157 | |
1158 if (rev->timer_set) { | |
1159 ngx_del_timer(rev); | |
1160 } | |
1161 | |
1162 ngx_imap_auth_http_init(s); | |
1163 | |
1164 return; | |
903 } | 1165 } |
904 } | 1166 } |
905 | 1167 |
906 if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) { | 1168 if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) { |
1169 s->imap_state = ngx_pop3_start; | |
1170 s->state = 0; | |
907 text = pop3_invalid_command; | 1171 text = pop3_invalid_command; |
908 size = sizeof(pop3_invalid_command) - 1; | 1172 size = sizeof(pop3_invalid_command) - 1; |
909 } | 1173 } |
910 | 1174 |
911 s->args.nelts = 0; | 1175 s->args.nelts = 0; |
912 s->buffer->pos = s->buffer->start; | 1176 s->buffer->pos = s->buffer->start; |
913 s->buffer->last = s->buffer->start; | 1177 s->buffer->last = s->buffer->start; |
1178 | |
1179 if (s->state) { | |
1180 s->arg_start = s->buffer->start; | |
1181 } | |
914 | 1182 |
915 s->out.data = text; | 1183 s->out.data = text; |
916 s->out.len = size; | 1184 s->out.len = size; |
917 | 1185 |
918 ngx_imap_send(c->write); | 1186 ngx_imap_send(c->write); |