comparison src/imap/ngx_imap_handler.c @ 527:7fa11e5c6e96 release-0.1.38

nginx-0.1.38-RELEASE import *) Feature: the "limit_rate" directive is supported in in proxy and FastCGI mode. *) Feature: the "X-Accel-Limit-Rate" response header line is supported in proxy and FastCGI mode. *) Feature: the "break" directive. *) Feature: the "log_not_found" directive. *) Bugfix: the response status code was not changed when request was redirected by the ""X-Accel-Redirect" header line. *) Bugfix: the variables set by the "set" directive could not be used in SSI. *) Bugfix: the segmentation fault may occurred if the SSI page has more than one remote subrequest. *) Bugfix: nginx treated the backend response as invalid if the status line in the header was transferred in two packets; the bug had appeared in 0.1.29. *) Feature: the "ssi_types" directive. *) Feature: the "autoindex_exact_size" directive. *) Bugfix: the ngx_http_autoindex_module did not support the long file names in UTF-8. *) Feature: the IMAP/POP3 proxy.
author Igor Sysoev <igor@sysoev.ru>
date Fri, 08 Jul 2005 14:34:20 +0000
parents 09b42134ac0c
children e5d7d0334fdb
comparison
equal deleted inserted replaced
526:e31ce4d8b8e6 527:7fa11e5c6e96
6 6
7 #include <ngx_config.h> 7 #include <ngx_config.h>
8 #include <ngx_core.h> 8 #include <ngx_core.h>
9 #include <ngx_event.h> 9 #include <ngx_event.h>
10 #include <ngx_imap.h> 10 #include <ngx_imap.h>
11 #include <nginx.h>
12 11
13 12
14 static void ngx_imap_init_session(ngx_event_t *rev); 13 static void ngx_imap_init_session(ngx_event_t *rev);
15 14 static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s);
16 static void ngx_pop3_auth_state(ngx_event_t *rev);
17 static ngx_int_t ngx_pop3_read_command(ngx_imap_session_t *s);
18
19 static void ngx_imap_auth_state(ngx_event_t *rev);
20 15
21 16
22 static ngx_str_t greetings[] = { 17 static ngx_str_t greetings[] = {
23 ngx_string("+OK " NGINX_VER " ready" CRLF), 18 ngx_string("+OK POP3 ready" CRLF),
24 ngx_string("* OK " NGINX_VER " ready" CRLF) 19 ngx_string("* OK IMAP ready" CRLF)
25 }; 20 };
26 21
27 static ngx_str_t internal_server_errors[] = { 22 static ngx_str_t internal_server_errors[] = {
28 ngx_string("-ERR internal server error" CRLF), 23 ngx_string("-ERR internal server error" CRLF),
29 ngx_string("* BAD internal server error" CRLF), 24 ngx_string("* BAD internal server error" CRLF),
30 }; 25 };
31 26
32 static u_char pop3_ok[] = "+OK" CRLF; 27 static u_char pop3_ok[] = "+OK" CRLF;
33 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; 28 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF;
29
30 static u_char imap_ok[] = "OK" CRLF;
31 static u_char imap_next[] = "+ OK" CRLF;
32 static u_char imap_bye[] = "* BYE" CRLF;
33 static u_char imap_invalid_command[] = "BAD invalid command" CRLF;
34 34
35 35
36 void 36 void
37 ngx_imap_init_connection(ngx_connection_t *c) 37 ngx_imap_init_connection(ngx_connection_t *c)
38 { 38 {
85 return; 85 return;
86 } 86 }
87 87
88 s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t)); 88 s = ngx_pcalloc(c->pool, sizeof(ngx_imap_session_t));
89 if (s == NULL) { 89 if (s == NULL) {
90 ngx_imap_close_connection(c); 90 ngx_imap_session_internal_server_error(s);
91 return; 91 return;
92 } 92 }
93 93
94 c->data = s; 94 c->data = s;
95 s->connection = c; 95 s->connection = c;
96 96
97 s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module); 97 s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_imap_max_module);
98 if (s->ctx == NULL) { 98 if (s->ctx == NULL) {
99 ngx_imap_close_connection(c); 99 ngx_imap_session_internal_server_error(s);
100 return; 100 return;
101 } 101 }
102 102
103 ctx = c->ctx; 103 ctx = c->ctx;
104 s->main_conf = ctx->main_conf; 104 s->main_conf = ctx->main_conf;
105 s->srv_conf = ctx->srv_conf; 105 s->srv_conf = ctx->srv_conf;
106 106
107 if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) { 107 if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
108 ngx_imap_close_connection(c); 108 ngx_imap_session_internal_server_error(s);
109 return; 109 return;
110 } 110 }
111 111
112 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module); 112 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
113 113
114 s->protocol = cscf->protocol; 114 s->protocol = cscf->protocol;
115 115
116 if (cscf->protocol == NGX_IMAP_POP3_PROTOCOL) { 116 if (cscf->protocol == NGX_IMAP_POP3_PROTOCOL) {
117 size = 128; 117 size = 128;
118 s->imap_state = ngx_pop3_start;
118 c->read->handler = ngx_pop3_auth_state; 119 c->read->handler = ngx_pop3_auth_state;
119 120
120 } else { 121 } else {
121 size = cscf->imap_client_buffer_size; 122 size = cscf->imap_client_buffer_size;
123 s->imap_state = ngx_imap_start;
122 c->read->handler = ngx_imap_auth_state; 124 c->read->handler = ngx_imap_auth_state;
123 } 125 }
124 126
125 s->buffer = ngx_create_temp_buf(c->pool, size); 127 s->buffer = ngx_create_temp_buf(c->pool, size);
126 if (s->buffer == NULL) { 128 if (s->buffer == NULL) {
127 ngx_imap_close_connection(c); 129 ngx_imap_session_internal_server_error(s);
128 return; 130 return;
129 } 131 }
130 132
131 c->read->handler(rev); 133 c->read->handler(rev);
132 } 134 }
133 135
134 136
135 static void 137 void
136 ngx_imap_auth_state(ngx_event_t *rev) 138 ngx_imap_auth_state(ngx_event_t *rev)
137 { 139 {
138 ngx_connection_t *c; 140 u_char *text, *last, *out, *p;
139 141 ssize_t size, text_len, last_len;
140 c = rev->data; 142 ngx_str_t *arg;
141 143 ngx_int_t rc;
142 ngx_imap_close_connection(c); 144 ngx_uint_t quit, tag;
143 } 145 ngx_connection_t *c;
144 146 ngx_imap_session_t *s;
145 147 ngx_imap_core_srv_conf_t *cscf;
146 static void
147 ngx_pop3_auth_state(ngx_event_t *rev)
148 {
149 u_char *text;
150 ssize_t size;
151 ngx_int_t rc;
152 ngx_uint_t quit;
153 ngx_str_t *arg;
154 ngx_connection_t *c;
155 ngx_imap_session_t *s;
156 148
157 c = rev->data; 149 c = rev->data;
158 s = c->data; 150 s = c->data;
159 151
160 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "pop3 auth state"); 152 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth state");
161 153
162 if (rev->timedout) { 154 if (rev->timedout) {
163 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); 155 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
164 ngx_imap_close_connection(c); 156 ngx_imap_close_connection(c);
165 return; 157 return;
166 } 158 }
167 159
168 rc = ngx_pop3_read_command(s); 160 rc = ngx_imap_read_command(s);
161
162 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth: %i", rc);
163
164 if (rc == NGX_AGAIN || rc == NGX_ERROR) {
165 return;
166 }
167
168 quit = 0;
169 tag = 1;
170
171 text = NULL;
172 text_len = 0;
173
174 last = imap_ok;
175 last_len = sizeof(imap_ok) - 1;
176
177 if (rc == NGX_OK) {
178
179 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, "imap auth command: %i",
180 s->command);
181
182 switch (s->command) {
183
184 case NGX_IMAP_LOGIN:
185 if (s->args.nelts == 2) {
186
187 arg = s->args.elts;
188
189 s->login.len = arg[0].len;
190 s->login.data = ngx_palloc(c->pool, s->login.len);
191 if (s->login.data == NULL) {
192 ngx_imap_session_internal_server_error(s);
193 return;
194 }
195
196 ngx_memcpy(s->login.data, arg[0].data, s->login.len);
197
198 s->passwd.len = arg[1].len;
199 s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
200 if (s->passwd.data == NULL) {
201 ngx_imap_session_internal_server_error(s);
202 return;
203 }
204
205 ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
206
207 ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0,
208 "imap login:\"%V\" passwd:\"%V\"",
209 &s->login, &s->passwd);
210
211 s->args.nelts = 0;
212 s->buffer->pos = s->buffer->start;
213 s->buffer->last = s->buffer->start;
214
215 if (rev->timer_set) {
216 ngx_del_timer(rev);
217 }
218
219 s->login_attempt++;
220
221 ngx_imap_auth_http_init(s);
222
223 return;
224
225 } else {
226 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
227 }
228
229 break;
230
231 case NGX_IMAP_CAPABILITY:
232 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
233 text = cscf->imap_capability->pos;
234 text_len = cscf->imap_capability->last - cscf->imap_capability->pos;
235 break;
236
237 case NGX_IMAP_LOGOUT:
238 text = imap_bye;
239 text_len = sizeof(imap_bye) - 1;
240 quit = 1;
241 break;
242
243 case NGX_IMAP_NOOP:
244 break;
245
246 default:
247 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
248 break;
249 }
250
251 } else if (rc == NGX_IMAP_NEXT) {
252 last = imap_next;
253 last_len = sizeof(imap_next) - 1;
254 tag = 0;
255 }
256
257 if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) {
258 last = imap_invalid_command;
259 last_len = sizeof(imap_invalid_command) - 1;
260 }
261
262 if (tag) {
263 if (s->out.len < text_len + s->tag.len + last_len) {
264
265 s->out.len = text_len + s->tag.len + last_len;
266 s->out.data = ngx_palloc(c->pool, s->out.len);
267 if (s->out.data == NULL) {
268 ngx_imap_close_connection(c);
269 return;
270 }
271 }
272
273 out = s->out.data;
274 p = out;
275
276 if (text) {
277 p = ngx_cpymem(p, text, text_len);
278 }
279 p = ngx_cpymem(p, s->tag.data, s->tag.len);
280 ngx_memcpy(p, last, last_len);
281
282 size = text_len + s->tag.len + last_len;
283
284 } else {
285 out = last;
286 size = last_len;
287 }
288
289 if (ngx_send(c, out, size) < size) {
290 /*
291 * we treat the incomplete sending as NGX_ERROR
292 * because it is very strange here
293 */
294 ngx_imap_close_connection(c);
295 return;
296 }
297
298 if (rc == NGX_IMAP_NEXT) {
299 return;
300 }
301
302 if (quit) {
303 ngx_imap_close_connection(c);
304 return;
305 }
306
307 s->args.nelts = 0;
308 s->buffer->pos = s->buffer->start;
309 s->buffer->last = s->buffer->start;
310 s->tag.len = 0;
311 }
312
313
314 void
315 ngx_pop3_auth_state(ngx_event_t *rev)
316 {
317 u_char *text;
318 ssize_t size;
319 ngx_int_t rc;
320 ngx_uint_t quit;
321 ngx_str_t *arg;
322 ngx_connection_t *c;
323 ngx_imap_session_t *s;
324 ngx_imap_core_srv_conf_t *cscf;
325
326 c = rev->data;
327 s = c->data;
328
329 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0, "pop3 auth state");
330
331 if (rev->timedout) {
332 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
333 ngx_imap_close_connection(c);
334 return;
335 }
336
337 rc = ngx_imap_read_command(s);
169 338
170 if (rc == NGX_AGAIN || rc == NGX_ERROR) { 339 if (rc == NGX_AGAIN || rc == NGX_ERROR) {
171 return; 340 return;
172 } 341 }
173 342
186 if (s->args.nelts == 1) { 355 if (s->args.nelts == 1) {
187 s->imap_state = ngx_pop3_user; 356 s->imap_state = ngx_pop3_user;
188 357
189 arg = s->args.elts; 358 arg = s->args.elts;
190 s->login.len = arg[0].len; 359 s->login.len = arg[0].len;
191 s->login.data = ngx_palloc(c->pool, s->login.len + 1); 360 s->login.data = ngx_palloc(c->pool, s->login.len);
192 if (s->login.data == NULL) { 361 if (s->login.data == NULL) {
193 ngx_imap_close_connection(c); 362 ngx_imap_session_internal_server_error(s);
194 return; 363 return;
195 } 364 }
196 365
197 ngx_cpystrn(s->login.data, arg[0].data, s->login.len + 1); 366 ngx_memcpy(s->login.data, arg[0].data, s->login.len);
198 367
199 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, 368 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0,
200 "pop3 login: \"%s\"", s->login.data); 369 "pop3 login: \"%V\"", &s->login);
201 370
202 } else { 371 } else {
203 rc = NGX_IMAP_PARSE_INVALID_COMMAND; 372 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
204 } 373 }
205 374
206 break; 375 break;
207 376
377 case NGX_POP3_CAPA:
378 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
379 text = cscf->pop3_capability->pos;
380 size = cscf->pop3_capability->last - cscf->pop3_capability->pos;
381 break;
382
208 case NGX_POP3_QUIT: 383 case NGX_POP3_QUIT:
209 quit = 1; 384 quit = 1;
385 break;
386
387 case NGX_POP3_NOOP:
210 break; 388 break;
211 389
212 default: 390 default:
213 s->imap_state = ngx_pop3_start; 391 s->imap_state = ngx_pop3_start;
214 rc = NGX_IMAP_PARSE_INVALID_COMMAND; 392 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
225 if (s->args.nelts == 1) { 403 if (s->args.nelts == 1) {
226 /* STUB */ s->imap_state = ngx_pop3_start; 404 /* STUB */ s->imap_state = ngx_pop3_start;
227 405
228 arg = s->args.elts; 406 arg = s->args.elts;
229 s->passwd.len = arg[0].len; 407 s->passwd.len = arg[0].len;
230 s->passwd.data = ngx_palloc(c->pool, s->passwd.len + 1); 408 s->passwd.data = ngx_palloc(c->pool, s->passwd.len);
231 if (s->passwd.data == NULL) { 409 if (s->passwd.data == NULL) {
232 ngx_imap_close_connection(c); 410 ngx_imap_session_internal_server_error(s);
233 return; 411 return;
234 } 412 }
235 413
236 ngx_cpystrn(s->passwd.data, arg[0].data, s->passwd.len + 1); 414 ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len);
237 415
238 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, 416 ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0,
239 "pop3 passwd: \"%s\"", s->passwd.data); 417 "pop3 passwd: \"%V\"", &s->passwd);
240 418
419 s->args.nelts = 0;
241 s->buffer->pos = s->buffer->start; 420 s->buffer->pos = s->buffer->start;
242 s->buffer->last = s->buffer->start; 421 s->buffer->last = s->buffer->start;
422
423 if (rev->timer_set) {
424 ngx_del_timer(rev);
425 }
243 426
244 ngx_imap_auth_http_init(s); 427 ngx_imap_auth_http_init(s);
245 428
246 return; 429 return;
247 430
249 rc = NGX_IMAP_PARSE_INVALID_COMMAND; 432 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
250 } 433 }
251 434
252 break; 435 break;
253 436
437 case NGX_POP3_CAPA:
438 cscf = ngx_imap_get_module_srv_conf(s, ngx_imap_core_module);
439 text = cscf->pop3_capability->pos;
440 size = cscf->pop3_capability->last - cscf->pop3_capability->pos;
441 break;
442
254 case NGX_POP3_QUIT: 443 case NGX_POP3_QUIT:
255 quit = 1; 444 quit = 1;
445 break;
446
447 case NGX_POP3_NOOP:
256 break; 448 break;
257 449
258 default: 450 default:
259 s->imap_state = ngx_pop3_start; 451 s->imap_state = ngx_pop3_start;
260 rc = NGX_IMAP_PARSE_INVALID_COMMAND; 452 rc = NGX_IMAP_PARSE_INVALID_COMMAND;
261 break; 453 break;
262 } 454 }
263 455
456 break;
457
458 /* suppress warinings */
459 case ngx_pop3_passwd:
264 break; 460 break;
265 } 461 }
266 } 462 }
267 463
268 if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) { 464 if (rc == NGX_IMAP_PARSE_INVALID_COMMAND) {
289 s->buffer->last = s->buffer->start; 485 s->buffer->last = s->buffer->start;
290 } 486 }
291 487
292 488
293 static ngx_int_t 489 static ngx_int_t
294 ngx_pop3_read_command(ngx_imap_session_t *s) 490 ngx_imap_read_command(ngx_imap_session_t *s)
295 { 491 {
296 ssize_t n; 492 ssize_t n;
297 ngx_int_t rc; 493 ngx_int_t rc;
298 494
299 n = ngx_recv(s->connection, s->buffer->last, 495 n = ngx_recv(s->connection, s->buffer->last,
308 s->buffer->last += n; 504 s->buffer->last += n;
309 } 505 }
310 506
311 if (n == NGX_AGAIN) { 507 if (n == NGX_AGAIN) {
312 if (ngx_handle_read_event(s->connection->read, 0) == NGX_ERROR) { 508 if (ngx_handle_read_event(s->connection->read, 0) == NGX_ERROR) {
313 ngx_imap_close_connection(s->connection); 509 ngx_imap_session_internal_server_error(s);
314 return NGX_ERROR; 510 return NGX_ERROR;
315 } 511 }
316 512
317 return NGX_AGAIN; 513 return NGX_AGAIN;
318 } 514 }
319 515
320 rc = ngx_pop3_parse_command(s); 516 if (s->protocol == NGX_IMAP_POP3_PROTOCOL) {
321 517 rc = ngx_pop3_parse_command(s);
322 if (rc == NGX_AGAIN || rc == NGX_IMAP_PARSE_INVALID_COMMAND) { 518 } else {
519 rc = ngx_imap_parse_command(s);
520 }
521
522 if (rc == NGX_AGAIN
523 || rc == NGX_IMAP_NEXT
524 || rc == NGX_IMAP_PARSE_INVALID_COMMAND)
525 {
323 return rc; 526 return rc;
324 } 527 }
325 528
326 if (rc == NGX_ERROR) { 529 if (rc == NGX_ERROR) {
327 ngx_imap_close_connection(s->connection); 530 ngx_imap_close_connection(s->connection);
330 533
331 return NGX_OK; 534 return NGX_OK;
332 } 535 }
333 536
334 537
335 #if 0
336
337 void
338 ngx_imap_close_session(ngx_imap_session_t *s)
339 {
340 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, s->connection->log, 0,
341 "close imap session");
342
343 ngx_imap_close_connection(s->connection);
344 }
345
346 #endif
347
348
349 void 538 void
350 ngx_imap_session_internal_server_error(ngx_imap_session_t *s) 539 ngx_imap_session_internal_server_error(ngx_imap_session_t *s)
351 { 540 {
352 (void) ngx_send(s->connection, internal_server_errors[s->protocol].data, 541 (void) ngx_send(s->connection, internal_server_errors[s->protocol].data,
353 internal_server_errors[s->protocol].len); 542 internal_server_errors[s->protocol].len);