Mercurial > hg > nginx-mail
annotate src/mail/ngx_mail_handler.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | 9773720b845e c456a023113c |
children |
rev | line source |
---|---|
290 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_mail.h> | |
11 | |
12 | |
13 static void ngx_mail_init_session(ngx_connection_t *c); | |
14 | |
15 #if (NGX_MAIL_SSL) | |
16 static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); | |
17 static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); | |
18 #endif | |
19 | |
20 | |
21 void | |
22 ngx_mail_init_connection(ngx_connection_t *c) | |
23 { | |
532 | 24 ngx_uint_t i; |
25 ngx_mail_port_t *port; | |
26 struct sockaddr *sa; | |
27 struct sockaddr_in *sin; | |
28 ngx_mail_log_ctx_t *ctx; | |
29 ngx_mail_in_addr_t *addr; | |
30 ngx_mail_session_t *s; | |
31 ngx_mail_addr_conf_t *addr_conf; | |
32 #if (NGX_HAVE_INET6) | |
33 struct sockaddr_in6 *sin6; | |
34 ngx_mail_in6_addr_t *addr6; | |
35 #endif | |
36 | |
290 | 37 |
38 /* find the server configuration for the address:port */ | |
39 | |
40 /* AF_INET only */ | |
41 | |
532 | 42 port = c->listening->servers; |
290 | 43 |
532 | 44 if (port->naddrs > 1) { |
290 | 45 |
46 /* | |
47 * There are several addresses on this port and one of them | |
48 * is the "*:port" wildcard so getsockname() is needed to determine | |
49 * the server address. | |
50 * | |
51 * AcceptEx() already gave this address. | |
52 */ | |
53 | |
532 | 54 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { |
55 ngx_mail_close_connection(c); | |
56 return; | |
57 } | |
58 | |
59 sa = c->local_sockaddr; | |
60 | |
61 switch (sa->sa_family) { | |
290 | 62 |
532 | 63 #if (NGX_HAVE_INET6) |
64 case AF_INET6: | |
65 sin6 = (struct sockaddr_in6 *) sa; | |
66 | |
67 addr6 = port->addrs; | |
68 | |
69 /* the last address is "*" */ | |
70 | |
71 for (i = 0; i < port->naddrs - 1; i++) { | |
72 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { | |
73 break; | |
74 } | |
290 | 75 } |
76 | |
532 | 77 addr_conf = &addr6[i].conf; |
78 | |
79 break; | |
80 #endif | |
81 | |
82 default: /* AF_INET */ | |
83 sin = (struct sockaddr_in *) sa; | |
84 | |
85 addr = port->addrs; | |
86 | |
87 /* the last address is "*" */ | |
88 | |
89 for (i = 0; i < port->naddrs - 1; i++) { | |
90 if (addr[i].addr == sin->sin_addr.s_addr) { | |
91 break; | |
92 } | |
93 } | |
94 | |
95 addr_conf = &addr[i].conf; | |
96 | |
97 break; | |
290 | 98 } |
99 | |
532 | 100 } else { |
101 switch (c->local_sockaddr->sa_family) { | |
290 | 102 |
532 | 103 #if (NGX_HAVE_INET6) |
104 case AF_INET6: | |
105 addr6 = port->addrs; | |
106 addr_conf = &addr6[0].conf; | |
107 break; | |
108 #endif | |
109 | |
110 default: /* AF_INET */ | |
111 addr = port->addrs; | |
112 addr_conf = &addr[0].conf; | |
113 break; | |
290 | 114 } |
115 } | |
116 | |
117 s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); | |
118 if (s == NULL) { | |
119 ngx_mail_close_connection(c); | |
120 return; | |
121 } | |
122 | |
532 | 123 s->main_conf = addr_conf->ctx->main_conf; |
124 s->srv_conf = addr_conf->ctx->srv_conf; | |
290 | 125 |
532 | 126 s->addr_text = &addr_conf->addr_text; |
290 | 127 |
128 c->data = s; | |
129 s->connection = c; | |
130 | |
131 ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", | |
132 c->number, &c->addr_text, s->addr_text); | |
133 | |
134 ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); | |
135 if (ctx == NULL) { | |
136 ngx_mail_close_connection(c); | |
137 return; | |
138 } | |
139 | |
140 ctx->client = &c->addr_text; | |
141 ctx->session = s; | |
142 | |
143 c->log->connection = c->number; | |
144 c->log->handler = ngx_mail_log_error; | |
145 c->log->data = ctx; | |
146 c->log->action = "sending client greeting line"; | |
147 | |
148 c->log_error = NGX_ERROR_INFO; | |
149 | |
150 #if (NGX_MAIL_SSL) | |
356 | 151 { |
152 ngx_mail_ssl_conf_t *sslcf; | |
290 | 153 |
154 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); | |
155 | |
156 if (sslcf->enable) { | |
426 | 157 c->log->action = "SSL handshaking"; |
158 | |
290 | 159 ngx_mail_ssl_init_connection(&sslcf->ssl, c); |
160 return; | |
161 } | |
426 | 162 |
532 | 163 if (addr_conf->ssl) { |
426 | 164 |
165 c->log->action = "SSL handshaking"; | |
166 | |
167 if (sslcf->ssl.ctx == NULL) { | |
168 ngx_log_error(NGX_LOG_ERR, c->log, 0, | |
169 "no \"ssl_certificate\" is defined " | |
170 "in server listening on SSL port"); | |
171 ngx_mail_close_connection(c); | |
172 return; | |
173 } | |
174 | |
175 ngx_mail_ssl_init_connection(&sslcf->ssl, c); | |
176 return; | |
177 } | |
178 | |
356 | 179 } |
290 | 180 #endif |
181 | |
182 ngx_mail_init_session(c); | |
183 } | |
184 | |
185 | |
186 #if (NGX_MAIL_SSL) | |
187 | |
336 | 188 void |
290 | 189 ngx_mail_starttls_handler(ngx_event_t *rev) |
190 { | |
191 ngx_connection_t *c; | |
192 ngx_mail_session_t *s; | |
193 ngx_mail_ssl_conf_t *sslcf; | |
194 | |
195 c = rev->data; | |
196 s = c->data; | |
197 s->starttls = 1; | |
198 | |
199 c->log->action = "in starttls state"; | |
200 | |
201 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); | |
202 | |
203 ngx_mail_ssl_init_connection(&sslcf->ssl, c); | |
204 } | |
205 | |
206 | |
207 static void | |
208 ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) | |
209 { | |
210 ngx_mail_session_t *s; | |
211 ngx_mail_core_srv_conf_t *cscf; | |
212 | |
213 if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { | |
214 ngx_mail_close_connection(c); | |
215 return; | |
216 } | |
217 | |
218 if (ngx_ssl_handshake(c) == NGX_AGAIN) { | |
219 | |
220 s = c->data; | |
221 | |
222 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
223 | |
224 ngx_add_timer(c->read, cscf->timeout); | |
225 | |
226 c->ssl->handler = ngx_mail_ssl_handshake_handler; | |
227 | |
228 return; | |
229 } | |
230 | |
231 ngx_mail_ssl_handshake_handler(c); | |
232 } | |
233 | |
234 | |
235 static void | |
236 ngx_mail_ssl_handshake_handler(ngx_connection_t *c) | |
237 { | |
336 | 238 ngx_mail_session_t *s; |
239 ngx_mail_core_srv_conf_t *cscf; | |
290 | 240 |
241 if (c->ssl->handshaked) { | |
242 | |
243 s = c->data; | |
244 | |
245 if (s->starttls) { | |
336 | 246 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
247 | |
248 c->read->handler = cscf->protocol->init_protocol; | |
290 | 249 c->write->handler = ngx_mail_send; |
250 | |
336 | 251 cscf->protocol->init_protocol(c->read); |
290 | 252 |
253 return; | |
254 } | |
255 | |
411 | 256 c->read->ready = 0; |
257 | |
290 | 258 ngx_mail_init_session(c); |
259 return; | |
260 } | |
261 | |
262 ngx_mail_close_connection(c); | |
263 } | |
264 | |
265 #endif | |
266 | |
267 | |
268 static void | |
269 ngx_mail_init_session(ngx_connection_t *c) | |
270 { | |
271 ngx_mail_session_t *s; | |
272 ngx_mail_core_srv_conf_t *cscf; | |
273 | |
274 s = c->data; | |
275 | |
276 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
277 | |
336 | 278 s->protocol = cscf->protocol->type; |
290 | 279 |
280 s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module); | |
281 if (s->ctx == NULL) { | |
282 ngx_mail_session_internal_server_error(s); | |
283 return; | |
284 } | |
285 | |
336 | 286 c->write->handler = ngx_mail_send; |
287 | |
288 cscf->protocol->init_session(s, c); | |
289 } | |
290 | |
291 | |
292 ngx_int_t | |
293 ngx_mail_salt(ngx_mail_session_t *s, ngx_connection_t *c, | |
294 ngx_mail_core_srv_conf_t *cscf) | |
295 { | |
382 | 296 s->salt.data = ngx_pnalloc(c->pool, |
297 sizeof(" <18446744073709551616.@>" CRLF) - 1 | |
298 + NGX_TIME_T_LEN | |
299 + cscf->server_name.len); | |
336 | 300 if (s->salt.data == NULL) { |
301 return NGX_ERROR; | |
302 } | |
303 | |
304 s->salt.len = ngx_sprintf(s->salt.data, "<%ul.%T@%V>" CRLF, | |
305 ngx_random(), ngx_time(), &cscf->server_name) | |
306 - s->salt.data; | |
307 | |
308 return NGX_OK; | |
309 } | |
310 | |
311 | |
312 #if (NGX_MAIL_SSL) | |
313 | |
314 ngx_int_t | |
315 ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c) | |
316 { | |
317 ngx_mail_ssl_conf_t *sslcf; | |
318 | |
319 if (c->ssl) { | |
320 return 0; | |
321 } | |
322 | |
323 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); | |
324 | |
325 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { | |
326 return 1; | |
327 } | |
328 | |
329 return 0; | |
330 } | |
290 | 331 |
336 | 332 #endif |
333 | |
334 | |
335 ngx_int_t | |
336 ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n) | |
337 { | |
338 u_char *p, *last; | |
339 ngx_str_t *arg, plain; | |
340 | |
341 arg = s->args.elts; | |
342 | |
343 #if (NGX_DEBUG_MAIL_PASSWD) | |
344 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
345 "mail auth plain: \"%V\"", &arg[n]); | |
346 #endif | |
347 | |
382 | 348 plain.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len)); |
625 | 349 if (plain.data == NULL) { |
336 | 350 return NGX_ERROR; |
351 } | |
352 | |
353 if (ngx_decode_base64(&plain, &arg[n]) != NGX_OK) { | |
354 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
355 "client sent invalid base64 encoding in AUTH PLAIN command"); | |
356 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
357 } | |
358 | |
359 p = plain.data; | |
360 last = p + plain.len; | |
361 | |
362 while (p < last && *p++) { /* void */ } | |
363 | |
364 if (p == last) { | |
365 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
366 "client sent invalid login in AUTH PLAIN command"); | |
367 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
368 } | |
369 | |
370 s->login.data = p; | |
371 | |
372 while (p < last && *p) { p++; } | |
373 | |
374 if (p == last) { | |
375 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
376 "client sent invalid password in AUTH PLAIN command"); | |
377 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
290 | 378 } |
379 | |
336 | 380 s->login.len = p++ - s->login.data; |
381 | |
382 s->passwd.len = last - p; | |
383 s->passwd.data = p; | |
384 | |
385 #if (NGX_DEBUG_MAIL_PASSWD) | |
386 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
387 "mail auth plain: \"%V\" \"%V\"", &s->login, &s->passwd); | |
388 #endif | |
389 | |
390 return NGX_DONE; | |
391 } | |
392 | |
290 | 393 |
336 | 394 ngx_int_t |
482 | 395 ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c, |
396 ngx_uint_t n) | |
336 | 397 { |
398 ngx_str_t *arg; | |
399 | |
400 arg = s->args.elts; | |
401 | |
402 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
482 | 403 "mail auth login username: \"%V\"", &arg[n]); |
336 | 404 |
482 | 405 s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len)); |
625 | 406 if (s->login.data == NULL) { |
336 | 407 return NGX_ERROR; |
408 } | |
322 | 409 |
482 | 410 if (ngx_decode_base64(&s->login, &arg[n]) != NGX_OK) { |
336 | 411 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
412 "client sent invalid base64 encoding in AUTH LOGIN command"); | |
413 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
414 } | |
415 | |
416 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
417 "mail auth login username: \"%V\"", &s->login); | |
418 | |
419 return NGX_OK; | |
420 } | |
421 | |
422 | |
423 ngx_int_t | |
424 ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c) | |
425 { | |
426 ngx_str_t *arg; | |
427 | |
428 arg = s->args.elts; | |
429 | |
430 #if (NGX_DEBUG_MAIL_PASSWD) | |
431 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
432 "mail auth login password: \"%V\"", &arg[0]); | |
433 #endif | |
434 | |
382 | 435 s->passwd.data = ngx_pnalloc(c->pool, |
436 ngx_base64_decoded_length(arg[0].len)); | |
625 | 437 if (s->passwd.data == NULL) { |
336 | 438 return NGX_ERROR; |
439 } | |
440 | |
441 if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { | |
442 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
443 "client sent invalid base64 encoding in AUTH LOGIN command"); | |
444 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
445 } | |
290 | 446 |
336 | 447 #if (NGX_DEBUG_MAIL_PASSWD) |
448 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
449 "mail auth login password: \"%V\"", &s->passwd); | |
450 #endif | |
451 | |
452 return NGX_DONE; | |
453 } | |
454 | |
455 | |
456 ngx_int_t | |
457 ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c, | |
458 char *prefix, size_t len) | |
459 { | |
460 u_char *p; | |
461 ngx_str_t salt; | |
462 ngx_uint_t n; | |
463 | |
382 | 464 p = ngx_pnalloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2); |
336 | 465 if (p == NULL) { |
466 return NGX_ERROR; | |
467 } | |
468 | |
469 salt.data = ngx_cpymem(p, prefix, len); | |
470 s->salt.len -= 2; | |
471 | |
472 ngx_encode_base64(&salt, &s->salt); | |
473 | |
474 s->salt.len += 2; | |
475 n = len + salt.len; | |
476 p[n++] = CR; p[n++] = LF; | |
477 | |
478 s->out.len = n; | |
479 s->out.data = p; | |
290 | 480 |
336 | 481 return NGX_OK; |
482 } | |
483 | |
484 | |
485 ngx_int_t | |
486 ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c) | |
487 { | |
488 u_char *p, *last; | |
489 ngx_str_t *arg; | |
490 | |
491 arg = s->args.elts; | |
492 | |
493 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
494 "mail auth cram-md5: \"%V\"", &arg[0]); | |
290 | 495 |
382 | 496 s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len)); |
625 | 497 if (s->login.data == NULL) { |
336 | 498 return NGX_ERROR; |
499 } | |
290 | 500 |
336 | 501 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { |
502 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
503 "client sent invalid base64 encoding in AUTH CRAM-MD5 command"); | |
504 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
505 } | |
506 | |
507 p = s->login.data; | |
508 last = p + s->login.len; | |
509 | |
510 while (p < last) { | |
511 if (*p++ == ' ') { | |
512 s->login.len = p - s->login.data - 1; | |
513 s->passwd.len = last - p; | |
514 s->passwd.data = p; | |
515 break; | |
290 | 516 } |
517 } | |
518 | |
336 | 519 if (s->passwd.len != 32) { |
520 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
521 "client sent invalid CRAM-MD5 hash in AUTH CRAM-MD5 command"); | |
522 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
290 | 523 } |
524 | |
336 | 525 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, |
526 "mail auth cram-md5: \"%V\" \"%V\"", &s->login, &s->passwd); | |
527 | |
528 s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; | |
529 | |
530 return NGX_DONE; | |
290 | 531 } |
532 | |
533 | |
534 void | |
535 ngx_mail_send(ngx_event_t *wev) | |
536 { | |
537 ngx_int_t n; | |
538 ngx_connection_t *c; | |
539 ngx_mail_session_t *s; | |
540 ngx_mail_core_srv_conf_t *cscf; | |
541 | |
542 c = wev->data; | |
543 s = c->data; | |
544 | |
545 if (wev->timedout) { | |
546 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
547 c->timedout = 1; | |
548 ngx_mail_close_connection(c); | |
549 return; | |
550 } | |
551 | |
552 if (s->out.len == 0) { | |
459 | 553 if (ngx_handle_write_event(c->write, 0) != NGX_OK) { |
290 | 554 ngx_mail_close_connection(c); |
555 } | |
556 | |
557 return; | |
558 } | |
559 | |
560 n = c->send(c, s->out.data, s->out.len); | |
561 | |
562 if (n > 0) { | |
563 s->out.len -= n; | |
564 | |
565 if (wev->timer_set) { | |
566 ngx_del_timer(wev); | |
567 } | |
568 | |
569 if (s->quit) { | |
570 ngx_mail_close_connection(c); | |
571 return; | |
572 } | |
573 | |
574 if (s->blocked) { | |
575 c->read->handler(c->read); | |
576 } | |
577 | |
578 return; | |
579 } | |
580 | |
581 if (n == NGX_ERROR) { | |
582 ngx_mail_close_connection(c); | |
583 return; | |
584 } | |
585 | |
586 /* n == NGX_AGAIN */ | |
587 | |
588 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
589 | |
590 ngx_add_timer(c->write, cscf->timeout); | |
591 | |
459 | 592 if (ngx_handle_write_event(c->write, 0) != NGX_OK) { |
290 | 593 ngx_mail_close_connection(c); |
594 return; | |
595 } | |
596 } | |
597 | |
598 | |
336 | 599 ngx_int_t |
600 ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) | |
290 | 601 { |
336 | 602 ssize_t n; |
603 ngx_int_t rc; | |
604 ngx_str_t l; | |
290 | 605 ngx_mail_core_srv_conf_t *cscf; |
606 | |
336 | 607 n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last); |
290 | 608 |
609 if (n == NGX_ERROR || n == 0) { | |
336 | 610 ngx_mail_close_connection(c); |
290 | 611 return NGX_ERROR; |
612 } | |
613 | |
614 if (n > 0) { | |
615 s->buffer->last += n; | |
616 } | |
617 | |
618 if (n == NGX_AGAIN) { | |
459 | 619 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { |
290 | 620 ngx_mail_session_internal_server_error(s); |
621 return NGX_ERROR; | |
622 } | |
623 | |
436
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
624 if (s->buffer->pos == s->buffer->last) { |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
625 return NGX_AGAIN; |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
626 } |
290 | 627 } |
628 | |
336 | 629 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
290 | 630 |
336 | 631 rc = cscf->protocol->parse_command(s); |
290 | 632 |
633 if (rc == NGX_AGAIN) { | |
634 | |
635 if (s->buffer->last < s->buffer->end) { | |
636 return rc; | |
637 } | |
638 | |
639 l.len = s->buffer->last - s->buffer->start; | |
640 l.data = s->buffer->start; | |
641 | |
336 | 642 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
290 | 643 "client sent too long command \"%V\"", &l); |
644 | |
645 s->quit = 1; | |
646 | |
647 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
648 } | |
649 | |
650 if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { | |
651 return rc; | |
652 } | |
653 | |
654 if (rc == NGX_ERROR) { | |
336 | 655 ngx_mail_close_connection(c); |
290 | 656 return NGX_ERROR; |
657 } | |
658 | |
659 return NGX_OK; | |
660 } | |
661 | |
662 | |
663 void | |
336 | 664 ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c) |
665 { | |
666 s->args.nelts = 0; | |
436
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
667 |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
668 if (s->buffer->pos == s->buffer->last) { |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
669 s->buffer->pos = s->buffer->start; |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
670 s->buffer->last = s->buffer->start; |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
671 } |
9b19e26b2660
Mail: smtp pipelining support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
428
diff
changeset
|
672 |
336 | 673 s->state = 0; |
674 | |
675 if (c->read->timer_set) { | |
676 ngx_del_timer(c->read); | |
677 } | |
678 | |
679 s->login_attempt++; | |
680 | |
681 ngx_mail_auth_http_init(s); | |
682 } | |
683 | |
684 | |
685 void | |
290 | 686 ngx_mail_session_internal_server_error(ngx_mail_session_t *s) |
687 { | |
336 | 688 ngx_mail_core_srv_conf_t *cscf; |
689 | |
690 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
691 | |
692 s->out = cscf->protocol->internal_server_error; | |
290 | 693 s->quit = 1; |
694 | |
695 ngx_mail_send(s->connection->write); | |
696 } | |
697 | |
698 | |
699 void | |
700 ngx_mail_close_connection(ngx_connection_t *c) | |
701 { | |
702 ngx_pool_t *pool; | |
703 | |
704 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
705 "close mail connection: %d", c->fd); | |
706 | |
707 #if (NGX_MAIL_SSL) | |
708 | |
709 if (c->ssl) { | |
710 if (ngx_ssl_shutdown(c) == NGX_AGAIN) { | |
711 c->ssl->handler = ngx_mail_close_connection; | |
712 return; | |
713 } | |
714 } | |
715 | |
716 #endif | |
717 | |
336 | 718 #if (NGX_STAT_STUB) |
542 | 719 (void) ngx_atomic_fetch_add(ngx_stat_active, -1); |
336 | 720 #endif |
721 | |
290 | 722 c->destroyed = 1; |
723 | |
724 pool = c->pool; | |
725 | |
726 ngx_close_connection(c); | |
727 | |
728 ngx_destroy_pool(pool); | |
729 } | |
730 | |
731 | |
336 | 732 u_char * |
290 | 733 ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len) |
734 { | |
735 u_char *p; | |
736 ngx_mail_session_t *s; | |
737 ngx_mail_log_ctx_t *ctx; | |
738 | |
739 if (log->action) { | |
740 p = ngx_snprintf(buf, len, " while %s", log->action); | |
741 len -= p - buf; | |
742 buf = p; | |
743 } | |
744 | |
745 ctx = log->data; | |
746 | |
747 p = ngx_snprintf(buf, len, ", client: %V", ctx->client); | |
748 len -= p - buf; | |
749 buf = p; | |
750 | |
751 s = ctx->session; | |
752 | |
753 if (s == NULL) { | |
754 return p; | |
755 } | |
756 | |
336 | 757 p = ngx_snprintf(buf, len, "%s, server: %V", |
758 s->starttls ? " using starttls" : "", | |
759 s->addr_text); | |
290 | 760 len -= p - buf; |
761 buf = p; | |
762 | |
763 if (s->login.len == 0) { | |
764 return p; | |
765 } | |
766 | |
767 p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login); | |
768 len -= p - buf; | |
769 buf = p; | |
770 | |
771 if (s->proxy == NULL) { | |
772 return p; | |
773 } | |
774 | |
775 p = ngx_snprintf(buf, len, ", upstream: %V", s->proxy->upstream.name); | |
776 | |
777 return p; | |
778 } |