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