Annotation of embedaddon/nginx/src/mail/ngx_mail_smtp_handler.c, revision 1.1.1.1
1.1 misho 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: #include <ngx_mail_smtp_module.h>
13:
14:
15: static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
16: static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
17: static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
18: static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
19: static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
20: static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
21: ngx_connection_t *c);
22:
23: static ngx_int_t ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c);
24: static ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c);
25: static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c);
26: static ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s,
27: ngx_connection_t *c);
28: static ngx_int_t ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c);
29: static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c);
30:
31: static ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s,
32: ngx_connection_t *c, char *err);
33: static void ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s,
34: ngx_connection_t *c, char *err);
35:
36:
37: static u_char smtp_ok[] = "250 2.0.0 OK" CRLF;
38: static u_char smtp_bye[] = "221 2.0.0 Bye" CRLF;
39: static u_char smtp_starttls[] = "220 2.0.0 Start TLS" CRLF;
40: static u_char smtp_next[] = "334 " CRLF;
41: static u_char smtp_username[] = "334 VXNlcm5hbWU6" CRLF;
42: static u_char smtp_password[] = "334 UGFzc3dvcmQ6" CRLF;
43: static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF;
44: static u_char smtp_invalid_pipelining[] =
45: "503 5.5.0 Improper use of SMTP command pipelining" CRLF;
46: static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;
47: static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
48: static u_char smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF;
49:
50:
51: static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]");
52: static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
53:
54:
55: void
56: ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
57: {
58: struct sockaddr_in *sin;
59: ngx_resolver_ctx_t *ctx;
60: ngx_mail_core_srv_conf_t *cscf;
61:
62: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
63:
64: if (cscf->resolver == NULL) {
65: s->host = smtp_unavailable;
66: ngx_mail_smtp_greeting(s, c);
67: return;
68: }
69:
70: if (c->sockaddr->sa_family != AF_INET) {
71: s->host = smtp_tempunavail;
72: ngx_mail_smtp_greeting(s, c);
73: return;
74: }
75:
76: c->log->action = "in resolving client address";
77:
78: ctx = ngx_resolve_start(cscf->resolver, NULL);
79: if (ctx == NULL) {
80: ngx_mail_close_connection(c);
81: return;
82: }
83:
84: /* AF_INET only */
85:
86: sin = (struct sockaddr_in *) c->sockaddr;
87:
88: ctx->addr = sin->sin_addr.s_addr;
89: ctx->handler = ngx_mail_smtp_resolve_addr_handler;
90: ctx->data = s;
91: ctx->timeout = cscf->resolver_timeout;
92:
93: if (ngx_resolve_addr(ctx) != NGX_OK) {
94: ngx_mail_close_connection(c);
95: }
96: }
97:
98:
99: static void
100: ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
101: {
102: ngx_connection_t *c;
103: ngx_mail_session_t *s;
104:
105: s = ctx->data;
106: c = s->connection;
107:
108: if (ctx->state) {
109: ngx_log_error(NGX_LOG_ERR, c->log, 0,
110: "%V could not be resolved (%i: %s)",
111: &c->addr_text, ctx->state,
112: ngx_resolver_strerror(ctx->state));
113:
114: if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
115: s->host = smtp_unavailable;
116:
117: } else {
118: s->host = smtp_tempunavail;
119: }
120:
121: ngx_resolve_addr_done(ctx);
122:
123: ngx_mail_smtp_greeting(s, s->connection);
124:
125: return;
126: }
127:
128: c->log->action = "in resolving client hostname";
129:
130: s->host.data = ngx_pstrdup(c->pool, &ctx->name);
131: if (s->host.data == NULL) {
132: ngx_resolve_addr_done(ctx);
133: ngx_mail_close_connection(c);
134: return;
135: }
136:
137: s->host.len = ctx->name.len;
138:
139: ngx_resolve_addr_done(ctx);
140:
141: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
142: "address resolved: %V", &s->host);
143:
144: c->read->handler = ngx_mail_smtp_resolve_name;
145:
146: ngx_post_event(c->read, &ngx_posted_events);
147: }
148:
149:
150: static void
151: ngx_mail_smtp_resolve_name(ngx_event_t *rev)
152: {
153: ngx_connection_t *c;
154: ngx_mail_session_t *s;
155: ngx_resolver_ctx_t *ctx;
156: ngx_mail_core_srv_conf_t *cscf;
157:
158: c = rev->data;
159: s = c->data;
160:
161: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
162:
163: ctx = ngx_resolve_start(cscf->resolver, NULL);
164: if (ctx == NULL) {
165: ngx_mail_close_connection(c);
166: return;
167: }
168:
169: ctx->name = s->host;
170: ctx->type = NGX_RESOLVE_A;
171: ctx->handler = ngx_mail_smtp_resolve_name_handler;
172: ctx->data = s;
173: ctx->timeout = cscf->resolver_timeout;
174:
175: if (ngx_resolve_name(ctx) != NGX_OK) {
176: ngx_mail_close_connection(c);
177: }
178: }
179:
180:
181: static void
182: ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
183: {
184: in_addr_t addr;
185: ngx_uint_t i;
186: ngx_connection_t *c;
187: struct sockaddr_in *sin;
188: ngx_mail_session_t *s;
189:
190: s = ctx->data;
191: c = s->connection;
192:
193: if (ctx->state) {
194: ngx_log_error(NGX_LOG_ERR, c->log, 0,
195: "\"%V\" could not be resolved (%i: %s)",
196: &ctx->name, ctx->state,
197: ngx_resolver_strerror(ctx->state));
198:
199: if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
200: s->host = smtp_unavailable;
201:
202: } else {
203: s->host = smtp_tempunavail;
204: }
205:
206: } else {
207:
208: /* AF_INET only */
209:
210: sin = (struct sockaddr_in *) c->sockaddr;
211:
212: for (i = 0; i < ctx->naddrs; i++) {
213:
214: addr = ctx->addrs[i];
215:
216: ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0,
217: "name was resolved to %ud.%ud.%ud.%ud",
218: (ntohl(addr) >> 24) & 0xff,
219: (ntohl(addr) >> 16) & 0xff,
220: (ntohl(addr) >> 8) & 0xff,
221: ntohl(addr) & 0xff);
222:
223: if (addr == sin->sin_addr.s_addr) {
224: goto found;
225: }
226: }
227:
228: s->host = smtp_unavailable;
229: }
230:
231: found:
232:
233: ngx_resolve_name_done(ctx);
234:
235: ngx_mail_smtp_greeting(s, c);
236: }
237:
238:
239: static void
240: ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
241: {
242: ngx_msec_t timeout;
243: ngx_mail_core_srv_conf_t *cscf;
244: ngx_mail_smtp_srv_conf_t *sscf;
245:
246: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
247: "smtp greeting for \"%V\"", &s->host);
248:
249: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
250: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
251:
252: timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
253: ngx_add_timer(c->read, timeout);
254:
255: if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
256: ngx_mail_close_connection(c);
257: }
258:
259: if (sscf->greeting_delay) {
260: c->read->handler = ngx_mail_smtp_invalid_pipelining;
261: return;
262: }
263:
264: c->read->handler = ngx_mail_smtp_init_protocol;
265:
266: s->out = sscf->greeting;
267:
268: ngx_mail_send(c->write);
269: }
270:
271:
272: static void
273: ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev)
274: {
275: ngx_connection_t *c;
276: ngx_mail_session_t *s;
277: ngx_mail_core_srv_conf_t *cscf;
278: ngx_mail_smtp_srv_conf_t *sscf;
279:
280: c = rev->data;
281: s = c->data;
282:
283: c->log->action = "in delay pipelining state";
284:
285: if (rev->timedout) {
286:
287: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting");
288:
289: rev->timedout = 0;
290:
291: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
292:
293: c->read->handler = ngx_mail_smtp_init_protocol;
294:
295: ngx_add_timer(c->read, cscf->timeout);
296:
297: if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
298: ngx_mail_close_connection(c);
299: return;
300: }
301:
302: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
303:
304: s->out = sscf->greeting;
305:
306: } else {
307:
308: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining");
309:
310: if (s->buffer == NULL) {
311: if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
312: return;
313: }
314: }
315:
316: if (ngx_mail_smtp_discard_command(s, c,
317: "client was rejected before greeting: \"%V\"")
318: != NGX_OK)
319: {
320: return;
321: }
322:
323: ngx_str_set(&s->out, smtp_invalid_pipelining);
324: }
325:
326: ngx_mail_send(c->write);
327: }
328:
329:
330: void
331: ngx_mail_smtp_init_protocol(ngx_event_t *rev)
332: {
333: ngx_connection_t *c;
334: ngx_mail_session_t *s;
335:
336: c = rev->data;
337:
338: c->log->action = "in auth state";
339:
340: if (rev->timedout) {
341: ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
342: c->timedout = 1;
343: ngx_mail_close_connection(c);
344: return;
345: }
346:
347: s = c->data;
348:
349: if (s->buffer == NULL) {
350: if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
351: return;
352: }
353: }
354:
355: s->mail_state = ngx_smtp_start;
356: c->read->handler = ngx_mail_smtp_auth_state;
357:
358: ngx_mail_smtp_auth_state(rev);
359: }
360:
361:
362: static ngx_int_t
363: ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c)
364: {
365: ngx_mail_smtp_srv_conf_t *sscf;
366:
367: if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
368: ngx_mail_session_internal_server_error(s);
369: return NGX_ERROR;
370: }
371:
372: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
373:
374: s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size);
375: if (s->buffer == NULL) {
376: ngx_mail_session_internal_server_error(s);
377: return NGX_ERROR;
378: }
379:
380: return NGX_OK;
381: }
382:
383:
384: void
385: ngx_mail_smtp_auth_state(ngx_event_t *rev)
386: {
387: ngx_int_t rc;
388: ngx_connection_t *c;
389: ngx_mail_session_t *s;
390:
391: c = rev->data;
392: s = c->data;
393:
394: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state");
395:
396: if (rev->timedout) {
397: ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
398: c->timedout = 1;
399: ngx_mail_close_connection(c);
400: return;
401: }
402:
403: if (s->out.len) {
404: ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy");
405: s->blocked = 1;
406: return;
407: }
408:
409: s->blocked = 0;
410:
411: rc = ngx_mail_read_command(s, c);
412:
413: if (rc == NGX_AGAIN || rc == NGX_ERROR) {
414: return;
415: }
416:
417: ngx_str_set(&s->out, smtp_ok);
418:
419: if (rc == NGX_OK) {
420: switch (s->mail_state) {
421:
422: case ngx_smtp_start:
423:
424: switch (s->command) {
425:
426: case NGX_SMTP_HELO:
427: case NGX_SMTP_EHLO:
428: rc = ngx_mail_smtp_helo(s, c);
429: break;
430:
431: case NGX_SMTP_AUTH:
432: rc = ngx_mail_smtp_auth(s, c);
433: break;
434:
435: case NGX_SMTP_QUIT:
436: s->quit = 1;
437: ngx_str_set(&s->out, smtp_bye);
438: break;
439:
440: case NGX_SMTP_MAIL:
441: rc = ngx_mail_smtp_mail(s, c);
442: break;
443:
444: case NGX_SMTP_RCPT:
445: rc = ngx_mail_smtp_rcpt(s, c);
446: break;
447:
448: case NGX_SMTP_RSET:
449: rc = ngx_mail_smtp_rset(s, c);
450: break;
451:
452: case NGX_SMTP_NOOP:
453: break;
454:
455: case NGX_SMTP_STARTTLS:
456: rc = ngx_mail_smtp_starttls(s, c);
457: ngx_str_set(&s->out, smtp_starttls);
458: break;
459:
460: default:
461: rc = NGX_MAIL_PARSE_INVALID_COMMAND;
462: break;
463: }
464:
465: break;
466:
467: case ngx_smtp_auth_login_username:
468: rc = ngx_mail_auth_login_username(s, c, 0);
469:
470: ngx_str_set(&s->out, smtp_password);
471: s->mail_state = ngx_smtp_auth_login_password;
472: break;
473:
474: case ngx_smtp_auth_login_password:
475: rc = ngx_mail_auth_login_password(s, c);
476: break;
477:
478: case ngx_smtp_auth_plain:
479: rc = ngx_mail_auth_plain(s, c, 0);
480: break;
481:
482: case ngx_smtp_auth_cram_md5:
483: rc = ngx_mail_auth_cram_md5(s, c);
484: break;
485: }
486: }
487:
488: switch (rc) {
489:
490: case NGX_DONE:
491: ngx_mail_auth(s, c);
492: return;
493:
494: case NGX_ERROR:
495: ngx_mail_session_internal_server_error(s);
496: return;
497:
498: case NGX_MAIL_PARSE_INVALID_COMMAND:
499: s->mail_state = ngx_smtp_start;
500: s->state = 0;
501: ngx_str_set(&s->out, smtp_invalid_command);
502:
503: /* fall through */
504:
505: case NGX_OK:
506: s->args.nelts = 0;
507: s->buffer->pos = s->buffer->start;
508: s->buffer->last = s->buffer->start;
509:
510: if (s->state) {
511: s->arg_start = s->buffer->start;
512: }
513:
514: ngx_mail_send(c->write);
515: }
516: }
517:
518:
519: static ngx_int_t
520: ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c)
521: {
522: ngx_str_t *arg;
523: ngx_mail_smtp_srv_conf_t *sscf;
524:
525: if (s->args.nelts != 1) {
526: ngx_str_set(&s->out, smtp_invalid_argument);
527: s->state = 0;
528: return NGX_OK;
529: }
530:
531: arg = s->args.elts;
532:
533: s->smtp_helo.len = arg[0].len;
534:
535: s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len);
536: if (s->smtp_helo.data == NULL) {
537: return NGX_ERROR;
538: }
539:
540: ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len);
541:
542: ngx_str_null(&s->smtp_from);
543: ngx_str_null(&s->smtp_to);
544:
545: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
546:
547: if (s->command == NGX_SMTP_HELO) {
548: s->out = sscf->server_name;
549:
550: } else {
551: s->esmtp = 1;
552:
553: #if (NGX_MAIL_SSL)
554:
555: if (c->ssl == NULL) {
556: ngx_mail_ssl_conf_t *sslcf;
557:
558: sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
559:
560: if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
561: s->out = sscf->starttls_capability;
562: return NGX_OK;
563: }
564:
565: if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
566: s->out = sscf->starttls_only_capability;
567: return NGX_OK;
568: }
569: }
570: #endif
571:
572: s->out = sscf->capability;
573: }
574:
575: return NGX_OK;
576: }
577:
578:
579: static ngx_int_t
580: ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c)
581: {
582: ngx_int_t rc;
583: ngx_mail_core_srv_conf_t *cscf;
584: ngx_mail_smtp_srv_conf_t *sscf;
585:
586: #if (NGX_MAIL_SSL)
587: if (ngx_mail_starttls_only(s, c)) {
588: return NGX_MAIL_PARSE_INVALID_COMMAND;
589: }
590: #endif
591:
592: if (s->args.nelts == 0) {
593: ngx_str_set(&s->out, smtp_invalid_argument);
594: s->state = 0;
595: return NGX_OK;
596: }
597:
598: rc = ngx_mail_auth_parse(s, c);
599:
600: switch (rc) {
601:
602: case NGX_MAIL_AUTH_LOGIN:
603:
604: ngx_str_set(&s->out, smtp_username);
605: s->mail_state = ngx_smtp_auth_login_username;
606:
607: return NGX_OK;
608:
609: case NGX_MAIL_AUTH_LOGIN_USERNAME:
610:
611: ngx_str_set(&s->out, smtp_password);
612: s->mail_state = ngx_smtp_auth_login_password;
613:
614: return ngx_mail_auth_login_username(s, c, 1);
615:
616: case NGX_MAIL_AUTH_PLAIN:
617:
618: ngx_str_set(&s->out, smtp_next);
619: s->mail_state = ngx_smtp_auth_plain;
620:
621: return NGX_OK;
622:
623: case NGX_MAIL_AUTH_CRAM_MD5:
624:
625: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
626:
627: if (!(sscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) {
628: return NGX_MAIL_PARSE_INVALID_COMMAND;
629: }
630:
631: if (s->salt.data == NULL) {
632: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
633:
634: if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
635: return NGX_ERROR;
636: }
637: }
638:
639: if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) {
640: s->mail_state = ngx_smtp_auth_cram_md5;
641: return NGX_OK;
642: }
643:
644: return NGX_ERROR;
645: }
646:
647: return rc;
648: }
649:
650:
651: static ngx_int_t
652: ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
653: {
654: u_char ch;
655: ngx_str_t l;
656: ngx_uint_t i;
657: ngx_mail_smtp_srv_conf_t *sscf;
658:
659: sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
660:
661: if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) {
662: ngx_mail_smtp_log_rejected_command(s, c, "client was rejected: \"%V\"");
663: ngx_str_set(&s->out, smtp_auth_required);
664: return NGX_OK;
665: }
666:
667: /* auth none */
668:
669: if (s->smtp_from.len) {
670: ngx_str_set(&s->out, smtp_bad_sequence);
671: return NGX_OK;
672: }
673:
674: l.len = s->buffer->last - s->buffer->start;
675: l.data = s->buffer->start;
676:
677: for (i = 0; i < l.len; i++) {
678: ch = l.data[i];
679:
680: if (ch != CR && ch != LF) {
681: continue;
682: }
683:
684: l.data[i] = ' ';
685: }
686:
687: while (i) {
688: if (l.data[i - 1] != ' ') {
689: break;
690: }
691:
692: i--;
693: }
694:
695: l.len = i;
696:
697: s->smtp_from.len = l.len;
698:
699: s->smtp_from.data = ngx_pnalloc(c->pool, l.len);
700: if (s->smtp_from.data == NULL) {
701: return NGX_ERROR;
702: }
703:
704: ngx_memcpy(s->smtp_from.data, l.data, l.len);
705:
706: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
707: "smtp mail from:\"%V\"", &s->smtp_from);
708:
709: ngx_str_set(&s->out, smtp_ok);
710:
711: return NGX_OK;
712: }
713:
714:
715: static ngx_int_t
716: ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c)
717: {
718: u_char ch;
719: ngx_str_t l;
720: ngx_uint_t i;
721:
722: if (s->smtp_from.len == 0) {
723: ngx_str_set(&s->out, smtp_bad_sequence);
724: return NGX_OK;
725: }
726:
727: l.len = s->buffer->last - s->buffer->start;
728: l.data = s->buffer->start;
729:
730: for (i = 0; i < l.len; i++) {
731: ch = l.data[i];
732:
733: if (ch != CR && ch != LF) {
734: continue;
735: }
736:
737: l.data[i] = ' ';
738: }
739:
740: while (i) {
741: if (l.data[i - 1] != ' ') {
742: break;
743: }
744:
745: i--;
746: }
747:
748: l.len = i;
749:
750: s->smtp_to.len = l.len;
751:
752: s->smtp_to.data = ngx_pnalloc(c->pool, l.len);
753: if (s->smtp_to.data == NULL) {
754: return NGX_ERROR;
755: }
756:
757: ngx_memcpy(s->smtp_to.data, l.data, l.len);
758:
759: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
760: "smtp rcpt to:\"%V\"", &s->smtp_to);
761:
762: s->auth_method = NGX_MAIL_AUTH_NONE;
763:
764: return NGX_DONE;
765: }
766:
767:
768: static ngx_int_t
769: ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c)
770: {
771: ngx_str_null(&s->smtp_from);
772: ngx_str_null(&s->smtp_to);
773: ngx_str_set(&s->out, smtp_ok);
774:
775: return NGX_OK;
776: }
777:
778:
779: static ngx_int_t
780: ngx_mail_smtp_starttls(ngx_mail_session_t *s, ngx_connection_t *c)
781: {
782: #if (NGX_MAIL_SSL)
783: ngx_mail_ssl_conf_t *sslcf;
784:
785: if (c->ssl == NULL) {
786: sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
787: if (sslcf->starttls) {
788:
789: /*
790: * RFC3207 requires us to discard any knowledge
791: * obtained from client before STARTTLS.
792: */
793:
794: ngx_str_null(&s->smtp_helo);
795: ngx_str_null(&s->smtp_from);
796: ngx_str_null(&s->smtp_to);
797:
798: c->read->handler = ngx_mail_starttls_handler;
799: return NGX_OK;
800: }
801: }
802:
803: #endif
804:
805: return NGX_MAIL_PARSE_INVALID_COMMAND;
806: }
807:
808:
809: static ngx_int_t
810: ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c,
811: char *err)
812: {
813: ssize_t n;
814:
815: n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last);
816:
817: if (n == NGX_ERROR || n == 0) {
818: ngx_mail_close_connection(c);
819: return NGX_ERROR;
820: }
821:
822: if (n > 0) {
823: s->buffer->last += n;
824: }
825:
826: if (n == NGX_AGAIN) {
827: if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
828: ngx_mail_session_internal_server_error(s);
829: return NGX_ERROR;
830: }
831:
832: return NGX_AGAIN;
833: }
834:
835: ngx_mail_smtp_log_rejected_command(s, c, err);
836:
837: s->buffer->pos = s->buffer->start;
838: s->buffer->last = s->buffer->start;
839:
840: return NGX_OK;
841: }
842:
843:
844: static void
845: ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s, ngx_connection_t *c,
846: char *err)
847: {
848: u_char ch;
849: ngx_str_t cmd;
850: ngx_uint_t i;
851:
852: if (c->log->log_level < NGX_LOG_INFO) {
853: return;
854: }
855:
856: cmd.len = s->buffer->last - s->buffer->start;
857: cmd.data = s->buffer->start;
858:
859: for (i = 0; i < cmd.len; i++) {
860: ch = cmd.data[i];
861:
862: if (ch != CR && ch != LF) {
863: continue;
864: }
865:
866: cmd.data[i] = '_';
867: }
868:
869: cmd.len = i;
870:
871: ngx_log_error(NGX_LOG_INFO, c->log, 0, err, &cmd);
872: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>