~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/mail/ngx_mail_smtp_handler.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.