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