comparison src/imap/ngx_imap_handler.c @ 894:4f7dca9c37f0

workaround for Eudora for Mac: it sends AUTH PLAIN [base64 encoded]
author Igor Sysoev <igor@sysoev.ru>
date Mon, 11 Dec 2006 08:27:29 +0000
parents 4d68c486fcb0
children f88651afad40
comparison
equal deleted inserted replaced
893:f029e69eb010 894:4f7dca9c37f0
10 #include <ngx_imap.h> 10 #include <ngx_imap.h>
11 11
12 12
13 static void ngx_imap_init_session(ngx_connection_t *c); 13 static void ngx_imap_init_session(ngx_connection_t *c);
14 static void ngx_imap_init_protocol(ngx_event_t *rev); 14 static void ngx_imap_init_protocol(ngx_event_t *rev);
15 static ngx_int_t ngx_imap_decode_auth_plain(ngx_imap_session_t *s,
16 ngx_str_t *encoded);
15 static void ngx_imap_do_auth(ngx_imap_session_t *s); 17 static void ngx_imap_do_auth(ngx_imap_session_t *s);
16 static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s); 18 static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s);
17 static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len); 19 static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len);
18 20
19 #if (NGX_IMAP_SSL) 21 #if (NGX_IMAP_SSL)
658 ngx_pop3_auth_state(ngx_event_t *rev) 660 ngx_pop3_auth_state(ngx_event_t *rev)
659 { 661 {
660 u_char *text, *p, *last; 662 u_char *text, *p, *last;
661 ssize_t size; 663 ssize_t size;
662 ngx_int_t rc; 664 ngx_int_t rc;
663 ngx_str_t *arg, salt, plain; 665 ngx_str_t *arg, salt;
664 ngx_connection_t *c; 666 ngx_connection_t *c;
665 ngx_imap_session_t *s; 667 ngx_imap_session_t *s;
666 ngx_imap_core_srv_conf_t *cscf; 668 ngx_imap_core_srv_conf_t *cscf;
667 #if (NGX_IMAP_SSL) 669 #if (NGX_IMAP_SSL)
668 ngx_imap_ssl_conf_t *sslcf; 670 ngx_imap_ssl_conf_t *sslcf;
794 text = cscf->pop3_auth_capability.data; 796 text = cscf->pop3_auth_capability.data;
795 s->state = 0; 797 s->state = 0;
796 break; 798 break;
797 } 799 }
798 800
799 if (s->args.nelts != 1) {
800 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
801 break;
802 }
803
804 arg = s->args.elts; 801 arg = s->args.elts;
805 802
806 if (arg[0].len == 5) { 803 if (arg[0].len == 5) {
807 804
808 if (ngx_strncasecmp(arg[0].data, "LOGIN", 5) == 0) { 805 if (ngx_strncasecmp(arg[0].data, "LOGIN", 5) == 0) {
806
807 if (s->args.nelts != 1) {
808 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
809 break;
810 }
811
809 s->imap_state = ngx_pop3_auth_login_username; 812 s->imap_state = ngx_pop3_auth_login_username;
810 813
811 size = sizeof(pop3_username) - 1; 814 size = sizeof(pop3_username) - 1;
812 text = pop3_username; 815 text = pop3_username;
813 816
814 break; 817 break;
815 818
816 } else if (ngx_strncasecmp(arg[0].data, "PLAIN", 5) == 0) { 819 } else if (ngx_strncasecmp(arg[0].data, "PLAIN", 5) == 0) {
817 s->imap_state = ngx_pop3_auth_plain; 820
818 821 if (s->args.nelts == 1) {
819 size = sizeof(pop3_next) - 1; 822 s->imap_state = ngx_pop3_auth_plain;
820 text = pop3_next; 823
821 824 size = sizeof(pop3_next) - 1;
825 text = pop3_next;
826
827 break;
828 }
829
830 if (s->args.nelts == 2) {
831
832 /*
833 * workaround for Eudora for Mac: it sends
834 * AUTH PLAIN [base64 encoded]
835 */
836
837 rc = ngx_imap_decode_auth_plain(s, &arg[1]);
838
839 if (rc == NGX_OK) {
840 ngx_imap_do_auth(s);
841 return;
842 }
843
844 if (rc == NGX_ERROR) {
845 ngx_imap_session_internal_server_error(s);
846 return;
847 }
848
849 /* rc == NGX_IMAP_PARSE_INVALID_COMMAND */
850
851 break;
852 }
853
854 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
822 break; 855 break;
823 } 856 }
824 857
825 } else if (arg[0].len == 8 858 } else if (arg[0].len == 8
826 && ngx_strncasecmp(arg[0].data, "CRAM-MD5", 8) == 0) 859 && ngx_strncasecmp(arg[0].data, "CRAM-MD5", 8) == 0)
997 return; 1030 return;
998 1031
999 case ngx_pop3_auth_plain: 1032 case ngx_pop3_auth_plain:
1000 arg = s->args.elts; 1033 arg = s->args.elts;
1001 1034
1002 #if (NGX_DEBUG_IMAP_PASSWD) 1035 rc = ngx_imap_decode_auth_plain(s, &arg[0]);
1003 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, 1036
1004 "pop3 auth plain: \"%V\"", &arg[0]); 1037 if (rc == NGX_OK) {
1005 #endif 1038 ngx_imap_do_auth(s);
1006 1039 return;
1007 plain.data = ngx_palloc(c->pool, 1040 }
1008 ngx_base64_decoded_length(arg[0].len)); 1041
1009 if (plain.data == NULL){ 1042 if (rc == NGX_ERROR) {
1010 ngx_imap_session_internal_server_error(s); 1043 ngx_imap_session_internal_server_error(s);
1011 return; 1044 return;
1012 } 1045 }
1013 1046
1014 if (ngx_decode_base64(&plain, &arg[0]) != NGX_OK) { 1047 /* rc == NGX_IMAP_PARSE_INVALID_COMMAND */
1015 ngx_log_error(NGX_LOG_INFO, c->log, 0, 1048
1016 "client sent invalid base64 encoding " 1049 break;
1017 "in AUTH PLAIN command");
1018 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
1019 break;
1020 }
1021
1022 p = plain.data;
1023 last = p + plain.len;
1024
1025 while (p < last && *p++) { /* void */ }
1026
1027 if (p == last) {
1028 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1029 "client sent invalid login "
1030 "in AUTH PLAIN command");
1031 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
1032 break;
1033 }
1034
1035 s->login.data = p;
1036
1037 while (p < last && *p) { p++; }
1038
1039 if (p == last) {
1040 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1041 "client sent invalid password "
1042 "in AUTH PLAIN command");
1043 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
1044 break;
1045 }
1046
1047 s->login.len = p++ - s->login.data;
1048
1049 s->passwd.len = last - p;
1050 s->passwd.data = p;
1051
1052 #if (NGX_DEBUG_IMAP_PASSWD)
1053 ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0,
1054 "pop3 auth plain: \"%V\" \"%V\"",
1055 &s->login, &s->passwd);
1056 #endif
1057
1058 ngx_imap_do_auth(s);
1059 return;
1060 1050
1061 case ngx_pop3_auth_cram_md5: 1051 case ngx_pop3_auth_cram_md5:
1062 arg = s->args.elts; 1052 arg = s->args.elts;
1063 1053
1064 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, 1054 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0,
1130 1120
1131 ngx_imap_send(c->write); 1121 ngx_imap_send(c->write);
1132 } 1122 }
1133 1123
1134 1124
1125 static ngx_int_t
1126 ngx_imap_decode_auth_plain(ngx_imap_session_t *s, ngx_str_t *encoded)
1127 {
1128 u_char *p, *last;
1129 ngx_str_t plain;
1130
1131 #if (NGX_DEBUG_IMAP_PASSWD)
1132 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, s->connection->log, 0,
1133 "pop3 auth plain: \"%V\"", encoded);
1134 #endif
1135
1136 plain.data = ngx_palloc(s->connection->pool,
1137 ngx_base64_decoded_length(encoded->len));
1138 if (plain.data == NULL){
1139 return NGX_ERROR;
1140 }
1141
1142 if (ngx_decode_base64(&plain, encoded) != NGX_OK) {
1143 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
1144 "client sent invalid base64 encoding "
1145 "in AUTH PLAIN command");
1146 return NGX_IMAP_PARSE_INVALID_COMMAND;
1147 }
1148
1149 p = plain.data;
1150 last = p + plain.len;
1151
1152 while (p < last && *p++) { /* void */ }
1153
1154 if (p == last) {
1155 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
1156 "client sent invalid login in AUTH PLAIN command");
1157 return NGX_IMAP_PARSE_INVALID_COMMAND;
1158 }
1159
1160 s->login.data = p;
1161
1162 while (p < last && *p) { p++; }
1163
1164 if (p == last) {
1165 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0,
1166 "client sent invalid password in AUTH PLAIN command");
1167 return NGX_IMAP_PARSE_INVALID_COMMAND;
1168 }
1169
1170 s->login.len = p++ - s->login.data;
1171
1172 s->passwd.len = last - p;
1173 s->passwd.data = p;
1174
1175 #if (NGX_DEBUG_IMAP_PASSWD)
1176 ngx_log_debug2(NGX_LOG_DEBUG_IMAP, s->connection->log, 0,
1177 "pop3 auth plain: \"%V\" \"%V\"",
1178 &s->login, &s->passwd);
1179 #endif
1180
1181 return NGX_OK;
1182 }
1183
1184
1135 static void 1185 static void
1136 ngx_imap_do_auth(ngx_imap_session_t *s) 1186 ngx_imap_do_auth(ngx_imap_session_t *s)
1137 { 1187 {
1138 s->args.nelts = 0; 1188 s->args.nelts = 0;
1139 s->buffer->pos = s->buffer->start; 1189 s->buffer->pos = s->buffer->start;