Mercurial > hg > nginx-quic
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); |