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);