Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.19.2 ]​[ nginx-1.18.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 #include <ngx_mail.h>
0012 #include <ngx_mail_smtp_module.h>
0013 
0014 
0015 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
0016 static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
0017 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
0018 static void ngx_mail_smtp_block_reading(ngx_event_t *rev);
0019 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
0020 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
0021 static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
0022     ngx_connection_t *c);
0023 
0024 static ngx_int_t ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c);
0025 static ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c);
0026 static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c);
0027 static ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s,
0028     ngx_connection_t *c);
0029 static ngx_int_t ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c);
0030 static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c);
0031 
0032 static ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s,
0033     ngx_connection_t *c, char *err);
0034 static void ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s,
0035     ngx_connection_t *c, char *err);
0036 
0037 
0038 static u_char  smtp_ok[] = "250 2.0.0 OK" CRLF;
0039 static u_char  smtp_bye[] = "221 2.0.0 Bye" CRLF;
0040 static u_char  smtp_starttls[] = "220 2.0.0 Start TLS" CRLF;
0041 static u_char  smtp_next[] = "334 " CRLF;
0042 static u_char  smtp_username[] = "334 VXNlcm5hbWU6" CRLF;
0043 static u_char  smtp_password[] = "334 UGFzc3dvcmQ6" CRLF;
0044 static u_char  smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF;
0045 static u_char  smtp_invalid_pipelining[] =
0046     "503 5.5.0 Improper use of SMTP command pipelining" CRLF;
0047 static u_char  smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;
0048 static u_char  smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
0049 static u_char  smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF;
0050 
0051 
0052 static ngx_str_t  smtp_unavailable = ngx_string("[UNAVAILABLE]");
0053 static ngx_str_t  smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
0054 
0055 
0056 void
0057 ngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
0058 {
0059     ngx_resolver_ctx_t        *ctx;
0060     ngx_mail_core_srv_conf_t  *cscf;
0061 
0062     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
0063 
0064     if (cscf->resolver == NULL) {
0065         s->host = smtp_unavailable;
0066         ngx_mail_smtp_greeting(s, c);
0067         return;
0068     }
0069 
0070 #if (NGX_HAVE_UNIX_DOMAIN)
0071     if (c->sockaddr->sa_family == AF_UNIX) {
0072         s->host = smtp_tempunavail;
0073         ngx_mail_smtp_greeting(s, c);
0074         return;
0075     }
0076 #endif
0077 
0078     c->log->action = "in resolving client address";
0079 
0080     ctx = ngx_resolve_start(cscf->resolver, NULL);
0081     if (ctx == NULL) {
0082         ngx_mail_close_connection(c);
0083         return;
0084     }
0085 
0086     ctx->addr.sockaddr = c->sockaddr;
0087     ctx->addr.socklen = c->socklen;
0088     ctx->handler = ngx_mail_smtp_resolve_addr_handler;
0089     ctx->data = s;
0090     ctx->timeout = cscf->resolver_timeout;
0091 
0092     s->resolver_ctx = ctx;
0093     c->read->handler = ngx_mail_smtp_block_reading;
0094 
0095     if (ngx_resolve_addr(ctx) != NGX_OK) {
0096         ngx_mail_close_connection(c);
0097     }
0098 }
0099 
0100 
0101 static void
0102 ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
0103 {
0104     ngx_connection_t    *c;
0105     ngx_mail_session_t  *s;
0106 
0107     s = ctx->data;
0108     c = s->connection;
0109 
0110     if (ctx->state) {
0111         ngx_log_error(NGX_LOG_ERR, c->log, 0,
0112                       "%V could not be resolved (%i: %s)",
0113                       &c->addr_text, ctx->state,
0114                       ngx_resolver_strerror(ctx->state));
0115 
0116         if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
0117             s->host = smtp_unavailable;
0118 
0119         } else {
0120             s->host = smtp_tempunavail;
0121         }
0122 
0123         ngx_resolve_addr_done(ctx);
0124 
0125         ngx_mail_smtp_greeting(s, s->connection);
0126 
0127         return;
0128     }
0129 
0130     c->log->action = "in resolving client hostname";
0131 
0132     s->host.data = ngx_pstrdup(c->pool, &ctx->name);
0133     if (s->host.data == NULL) {
0134         ngx_resolve_addr_done(ctx);
0135         ngx_mail_close_connection(c);
0136         return;
0137     }
0138 
0139     s->host.len = ctx->name.len;
0140 
0141     ngx_resolve_addr_done(ctx);
0142 
0143     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
0144                    "address resolved: %V", &s->host);
0145 
0146     c->read->handler = ngx_mail_smtp_resolve_name;
0147 
0148     ngx_post_event(c->read, &ngx_posted_events);
0149 }
0150 
0151 
0152 static void
0153 ngx_mail_smtp_resolve_name(ngx_event_t *rev)
0154 {
0155     ngx_connection_t          *c;
0156     ngx_mail_session_t        *s;
0157     ngx_resolver_ctx_t        *ctx;
0158     ngx_mail_core_srv_conf_t  *cscf;
0159 
0160     c = rev->data;
0161     s = c->data;
0162 
0163     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
0164 
0165     ctx = ngx_resolve_start(cscf->resolver, NULL);
0166     if (ctx == NULL) {
0167         ngx_mail_close_connection(c);
0168         return;
0169     }
0170 
0171     ctx->name = s->host;
0172     ctx->handler = ngx_mail_smtp_resolve_name_handler;
0173     ctx->data = s;
0174     ctx->timeout = cscf->resolver_timeout;
0175 
0176     s->resolver_ctx = ctx;
0177     c->read->handler = ngx_mail_smtp_block_reading;
0178 
0179     if (ngx_resolve_name(ctx) != NGX_OK) {
0180         ngx_mail_close_connection(c);
0181     }
0182 }
0183 
0184 
0185 static void
0186 ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
0187 {
0188     ngx_uint_t           i;
0189     ngx_connection_t    *c;
0190     ngx_mail_session_t  *s;
0191 
0192     s = ctx->data;
0193     c = s->connection;
0194 
0195     if (ctx->state) {
0196         ngx_log_error(NGX_LOG_ERR, c->log, 0,
0197                       "\"%V\" could not be resolved (%i: %s)",
0198                       &ctx->name, ctx->state,
0199                       ngx_resolver_strerror(ctx->state));
0200 
0201         if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
0202             s->host = smtp_unavailable;
0203 
0204         } else {
0205             s->host = smtp_tempunavail;
0206         }
0207 
0208     } else {
0209 
0210 #if (NGX_DEBUG)
0211         {
0212         u_char     text[NGX_SOCKADDR_STRLEN];
0213         ngx_str_t  addr;
0214 
0215         addr.data = text;
0216 
0217         for (i = 0; i < ctx->naddrs; i++) {
0218             addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr,
0219                                      ctx->addrs[i].socklen,
0220                                      text, NGX_SOCKADDR_STRLEN, 0);
0221 
0222             ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
0223                            "name was resolved to %V", &addr);
0224         }
0225         }
0226 #endif
0227 
0228         for (i = 0; i < ctx->naddrs; i++) {
0229             if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen,
0230                                  c->sockaddr, c->socklen, 0)
0231                 == NGX_OK)
0232             {
0233                 goto found;
0234             }
0235         }
0236 
0237         s->host = smtp_unavailable;
0238     }
0239 
0240 found:
0241 
0242     ngx_resolve_name_done(ctx);
0243 
0244     ngx_mail_smtp_greeting(s, c);
0245 }
0246 
0247 
0248 static void
0249 ngx_mail_smtp_block_reading(ngx_event_t *rev)
0250 {
0251     ngx_connection_t    *c;
0252     ngx_mail_session_t  *s;
0253     ngx_resolver_ctx_t  *ctx;
0254 
0255     c = rev->data;
0256     s = c->data;
0257 
0258     ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp reading blocked");
0259 
0260     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0261 
0262         if (s->resolver_ctx) {
0263             ctx = s->resolver_ctx;
0264 
0265             if (ctx->handler == ngx_mail_smtp_resolve_addr_handler) {
0266                 ngx_resolve_addr_done(ctx);
0267 
0268             } else if (ctx->handler == ngx_mail_smtp_resolve_name_handler) {
0269                 ngx_resolve_name_done(ctx);
0270             }
0271 
0272             s->resolver_ctx = NULL;
0273         }
0274 
0275         ngx_mail_close_connection(c);
0276     }
0277 }
0278 
0279 
0280 static void
0281 ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
0282 {
0283     ngx_msec_t                 timeout;
0284     ngx_mail_core_srv_conf_t  *cscf;
0285     ngx_mail_smtp_srv_conf_t  *sscf;
0286 
0287     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
0288                    "smtp greeting for \"%V\"", &s->host);
0289 
0290     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
0291     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0292 
0293     timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
0294     ngx_add_timer(c->read, timeout);
0295 
0296     if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0297         ngx_mail_close_connection(c);
0298     }
0299 
0300     if (c->read->ready) {
0301         ngx_post_event(c->read, &ngx_posted_events);
0302     }
0303 
0304     if (sscf->greeting_delay) {
0305          c->read->handler = ngx_mail_smtp_invalid_pipelining;
0306          return;
0307     }
0308 
0309     c->read->handler = ngx_mail_smtp_init_protocol;
0310 
0311     s->out = sscf->greeting;
0312 
0313     ngx_mail_send(c->write);
0314 }
0315 
0316 
0317 static void
0318 ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev)
0319 {
0320     ngx_connection_t          *c;
0321     ngx_mail_session_t        *s;
0322     ngx_mail_core_srv_conf_t  *cscf;
0323     ngx_mail_smtp_srv_conf_t  *sscf;
0324 
0325     c = rev->data;
0326     s = c->data;
0327 
0328     c->log->action = "in delay pipelining state";
0329 
0330     if (rev->timedout) {
0331 
0332         ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting");
0333 
0334         rev->timedout = 0;
0335 
0336         cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
0337 
0338         c->read->handler = ngx_mail_smtp_init_protocol;
0339 
0340         ngx_add_timer(c->read, cscf->timeout);
0341 
0342         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0343             ngx_mail_close_connection(c);
0344             return;
0345         }
0346 
0347         sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0348 
0349         s->out = sscf->greeting;
0350 
0351     } else {
0352 
0353         ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining");
0354 
0355         if (s->buffer == NULL) {
0356             if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
0357                 return;
0358             }
0359         }
0360 
0361         if (ngx_mail_smtp_discard_command(s, c,
0362                                 "client was rejected before greeting: \"%V\"")
0363             != NGX_OK)
0364         {
0365             return;
0366         }
0367 
0368         ngx_str_set(&s->out, smtp_invalid_pipelining);
0369         s->quit = 1;
0370     }
0371 
0372     ngx_mail_send(c->write);
0373 }
0374 
0375 
0376 void
0377 ngx_mail_smtp_init_protocol(ngx_event_t *rev)
0378 {
0379     ngx_connection_t    *c;
0380     ngx_mail_session_t  *s;
0381 
0382     c = rev->data;
0383 
0384     c->log->action = "in auth state";
0385 
0386     if (rev->timedout) {
0387         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0388         c->timedout = 1;
0389         ngx_mail_close_connection(c);
0390         return;
0391     }
0392 
0393     s = c->data;
0394 
0395     if (s->buffer == NULL) {
0396         if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
0397             return;
0398         }
0399     }
0400 
0401     s->mail_state = ngx_smtp_start;
0402     c->read->handler = ngx_mail_smtp_auth_state;
0403 
0404     ngx_mail_smtp_auth_state(rev);
0405 }
0406 
0407 
0408 static ngx_int_t
0409 ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c)
0410 {
0411     ngx_mail_smtp_srv_conf_t  *sscf;
0412 
0413     if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
0414         ngx_mail_session_internal_server_error(s);
0415         return NGX_ERROR;
0416     }
0417 
0418     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0419 
0420     s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size);
0421     if (s->buffer == NULL) {
0422         ngx_mail_session_internal_server_error(s);
0423         return NGX_ERROR;
0424     }
0425 
0426     return NGX_OK;
0427 }
0428 
0429 
0430 void
0431 ngx_mail_smtp_auth_state(ngx_event_t *rev)
0432 {
0433     ngx_int_t            rc;
0434     ngx_connection_t    *c;
0435     ngx_mail_session_t  *s;
0436 
0437     c = rev->data;
0438     s = c->data;
0439 
0440     ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state");
0441 
0442     if (rev->timedout) {
0443         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0444         c->timedout = 1;
0445         ngx_mail_close_connection(c);
0446         return;
0447     }
0448 
0449     if (s->out.len) {
0450         ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy");
0451         s->blocked = 1;
0452         return;
0453     }
0454 
0455     s->blocked = 0;
0456 
0457     rc = ngx_mail_read_command(s, c);
0458 
0459     if (rc == NGX_AGAIN || rc == NGX_ERROR) {
0460         return;
0461     }
0462 
0463     ngx_str_set(&s->out, smtp_ok);
0464 
0465     if (rc == NGX_OK) {
0466         switch (s->mail_state) {
0467 
0468         case ngx_smtp_start:
0469 
0470             switch (s->command) {
0471 
0472             case NGX_SMTP_HELO:
0473             case NGX_SMTP_EHLO:
0474                 rc = ngx_mail_smtp_helo(s, c);
0475                 break;
0476 
0477             case NGX_SMTP_AUTH:
0478                 rc = ngx_mail_smtp_auth(s, c);
0479                 break;
0480 
0481             case NGX_SMTP_QUIT:
0482                 s->quit = 1;
0483                 ngx_str_set(&s->out, smtp_bye);
0484                 break;
0485 
0486             case NGX_SMTP_MAIL:
0487                 rc = ngx_mail_smtp_mail(s, c);
0488                 break;
0489 
0490             case NGX_SMTP_RCPT:
0491                 rc = ngx_mail_smtp_rcpt(s, c);
0492                 break;
0493 
0494             case NGX_SMTP_RSET:
0495                 rc = ngx_mail_smtp_rset(s, c);
0496                 break;
0497 
0498             case NGX_SMTP_NOOP:
0499                 break;
0500 
0501             case NGX_SMTP_STARTTLS:
0502                 rc = ngx_mail_smtp_starttls(s, c);
0503                 ngx_str_set(&s->out, smtp_starttls);
0504                 break;
0505 
0506             default:
0507                 rc = NGX_MAIL_PARSE_INVALID_COMMAND;
0508                 break;
0509             }
0510 
0511             break;
0512 
0513         case ngx_smtp_auth_login_username:
0514             rc = ngx_mail_auth_login_username(s, c, 0);
0515 
0516             ngx_str_set(&s->out, smtp_password);
0517             s->mail_state = ngx_smtp_auth_login_password;
0518             break;
0519 
0520         case ngx_smtp_auth_login_password:
0521             rc = ngx_mail_auth_login_password(s, c);
0522             break;
0523 
0524         case ngx_smtp_auth_plain:
0525             rc = ngx_mail_auth_plain(s, c, 0);
0526             break;
0527 
0528         case ngx_smtp_auth_cram_md5:
0529             rc = ngx_mail_auth_cram_md5(s, c);
0530             break;
0531 
0532         case ngx_smtp_auth_external:
0533             rc = ngx_mail_auth_external(s, c, 0);
0534             break;
0535         }
0536     }
0537 
0538     if (s->buffer->pos < s->buffer->last) {
0539         s->blocked = 1;
0540     }
0541 
0542     switch (rc) {
0543 
0544     case NGX_DONE:
0545         ngx_mail_auth(s, c);
0546         return;
0547 
0548     case NGX_ERROR:
0549         ngx_mail_session_internal_server_error(s);
0550         return;
0551 
0552     case NGX_MAIL_PARSE_INVALID_COMMAND:
0553         s->mail_state = ngx_smtp_start;
0554         s->state = 0;
0555         ngx_str_set(&s->out, smtp_invalid_command);
0556 
0557         /* fall through */
0558 
0559     case NGX_OK:
0560         s->args.nelts = 0;
0561 
0562         if (s->buffer->pos == s->buffer->last) {
0563             s->buffer->pos = s->buffer->start;
0564             s->buffer->last = s->buffer->start;
0565         }
0566 
0567         if (s->state) {
0568             s->arg_start = s->buffer->pos;
0569         }
0570 
0571         ngx_mail_send(c->write);
0572     }
0573 }
0574 
0575 
0576 static ngx_int_t
0577 ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c)
0578 {
0579     ngx_str_t                 *arg;
0580     ngx_mail_smtp_srv_conf_t  *sscf;
0581 
0582     if (s->args.nelts != 1) {
0583         ngx_str_set(&s->out, smtp_invalid_argument);
0584         s->state = 0;
0585         return NGX_OK;
0586     }
0587 
0588     arg = s->args.elts;
0589 
0590     s->smtp_helo.len = arg[0].len;
0591 
0592     s->smtp_helo.data = ngx_pnalloc(c->pool, arg[0].len);
0593     if (s->smtp_helo.data == NULL) {
0594         return NGX_ERROR;
0595     }
0596 
0597     ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len);
0598 
0599     ngx_str_null(&s->smtp_from);
0600     ngx_str_null(&s->smtp_to);
0601 
0602     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0603 
0604     if (s->command == NGX_SMTP_HELO) {
0605         s->out = sscf->server_name;
0606 
0607     } else {
0608         s->esmtp = 1;
0609 
0610 #if (NGX_MAIL_SSL)
0611 
0612         if (c->ssl == NULL) {
0613             ngx_mail_ssl_conf_t  *sslcf;
0614 
0615             sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
0616 
0617             if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
0618                 s->out = sscf->starttls_capability;
0619                 return NGX_OK;
0620             }
0621 
0622             if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
0623                 s->out = sscf->starttls_only_capability;
0624                 return NGX_OK;
0625             }
0626         }
0627 #endif
0628 
0629         s->out = sscf->capability;
0630     }
0631 
0632     return NGX_OK;
0633 }
0634 
0635 
0636 static ngx_int_t
0637 ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c)
0638 {
0639     ngx_int_t                  rc;
0640     ngx_mail_core_srv_conf_t  *cscf;
0641     ngx_mail_smtp_srv_conf_t  *sscf;
0642 
0643 #if (NGX_MAIL_SSL)
0644     if (ngx_mail_starttls_only(s, c)) {
0645         return NGX_MAIL_PARSE_INVALID_COMMAND;
0646     }
0647 #endif
0648 
0649     if (s->args.nelts == 0) {
0650         ngx_str_set(&s->out, smtp_invalid_argument);
0651         s->state = 0;
0652         return NGX_OK;
0653     }
0654 
0655     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0656 
0657     rc = ngx_mail_auth_parse(s, c);
0658 
0659     switch (rc) {
0660 
0661     case NGX_MAIL_AUTH_LOGIN:
0662 
0663         ngx_str_set(&s->out, smtp_username);
0664         s->mail_state = ngx_smtp_auth_login_username;
0665 
0666         return NGX_OK;
0667 
0668     case NGX_MAIL_AUTH_LOGIN_USERNAME:
0669 
0670         ngx_str_set(&s->out, smtp_password);
0671         s->mail_state = ngx_smtp_auth_login_password;
0672 
0673         return ngx_mail_auth_login_username(s, c, 1);
0674 
0675     case NGX_MAIL_AUTH_PLAIN:
0676 
0677         ngx_str_set(&s->out, smtp_next);
0678         s->mail_state = ngx_smtp_auth_plain;
0679 
0680         return NGX_OK;
0681 
0682     case NGX_MAIL_AUTH_CRAM_MD5:
0683 
0684         if (!(sscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) {
0685             return NGX_MAIL_PARSE_INVALID_COMMAND;
0686         }
0687 
0688         if (s->salt.data == NULL) {
0689             cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
0690 
0691             if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
0692                 return NGX_ERROR;
0693             }
0694         }
0695 
0696         if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) {
0697             s->mail_state = ngx_smtp_auth_cram_md5;
0698             return NGX_OK;
0699         }
0700 
0701         return NGX_ERROR;
0702 
0703     case NGX_MAIL_AUTH_EXTERNAL:
0704 
0705         if (!(sscf->auth_methods & NGX_MAIL_AUTH_EXTERNAL_ENABLED)) {
0706             return NGX_MAIL_PARSE_INVALID_COMMAND;
0707         }
0708 
0709         ngx_str_set(&s->out, smtp_username);
0710         s->mail_state = ngx_smtp_auth_external;
0711 
0712         return NGX_OK;
0713     }
0714 
0715     return rc;
0716 }
0717 
0718 
0719 static ngx_int_t
0720 ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c)
0721 {
0722     ngx_str_t                 *arg, cmd;
0723     ngx_mail_smtp_srv_conf_t  *sscf;
0724 
0725     sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
0726 
0727     if (!(sscf->auth_methods & NGX_MAIL_AUTH_NONE_ENABLED)) {
0728         ngx_mail_smtp_log_rejected_command(s, c, "client was rejected: \"%V\"");
0729         ngx_str_set(&s->out, smtp_auth_required);
0730         return NGX_OK;
0731     }
0732 
0733     /* auth none */
0734 
0735     if (s->smtp_from.len) {
0736         ngx_str_set(&s->out, smtp_bad_sequence);
0737         return NGX_OK;
0738     }
0739 
0740     if (s->args.nelts == 0) {
0741         ngx_str_set(&s->out, smtp_invalid_argument);
0742         return NGX_OK;
0743     }
0744 
0745     arg = s->args.elts;
0746     arg += s->args.nelts - 1;
0747 
0748     cmd.len = arg->data + arg->len - s->cmd.data;
0749     cmd.data = s->cmd.data;
0750 
0751     s->smtp_from.len = cmd.len;
0752 
0753     s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len);
0754     if (s->smtp_from.data == NULL) {
0755         return NGX_ERROR;
0756     }
0757 
0758     ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len);
0759 
0760     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
0761                    "smtp mail from:\"%V\"", &s->smtp_from);
0762 
0763     ngx_str_set(&s->out, smtp_ok);
0764 
0765     return NGX_OK;
0766 }
0767 
0768 
0769 static ngx_int_t
0770 ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c)
0771 {
0772     ngx_str_t  *arg, cmd;
0773 
0774     if (s->smtp_from.len == 0) {
0775         ngx_str_set(&s->out, smtp_bad_sequence);
0776         return NGX_OK;
0777     }
0778 
0779     if (s->args.nelts == 0) {
0780         ngx_str_set(&s->out, smtp_invalid_argument);
0781         return NGX_OK;
0782     }
0783 
0784     arg = s->args.elts;
0785     arg += s->args.nelts - 1;
0786 
0787     cmd.len = arg->data + arg->len - s->cmd.data;
0788     cmd.data = s->cmd.data;
0789 
0790     s->smtp_to.len = cmd.len;
0791 
0792     s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len);
0793     if (s->smtp_to.data == NULL) {
0794         return NGX_ERROR;
0795     }
0796 
0797     ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len);
0798 
0799     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
0800                    "smtp rcpt to:\"%V\"", &s->smtp_to);
0801 
0802     s->auth_method = NGX_MAIL_AUTH_NONE;
0803 
0804     return NGX_DONE;
0805 }
0806 
0807 
0808 static ngx_int_t
0809 ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c)
0810 {
0811     ngx_str_null(&s->smtp_from);
0812     ngx_str_null(&s->smtp_to);
0813     ngx_str_set(&s->out, smtp_ok);
0814 
0815     return NGX_OK;
0816 }
0817 
0818 
0819 static ngx_int_t
0820 ngx_mail_smtp_starttls(ngx_mail_session_t *s, ngx_connection_t *c)
0821 {
0822 #if (NGX_MAIL_SSL)
0823     ngx_mail_ssl_conf_t  *sslcf;
0824 
0825     if (c->ssl == NULL) {
0826         sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
0827         if (sslcf->starttls) {
0828 
0829             /*
0830              * RFC3207 requires us to discard any knowledge
0831              * obtained from client before STARTTLS.
0832              */
0833 
0834             ngx_str_null(&s->smtp_helo);
0835             ngx_str_null(&s->smtp_from);
0836             ngx_str_null(&s->smtp_to);
0837 
0838             s->buffer->pos = s->buffer->start;
0839             s->buffer->last = s->buffer->start;
0840 
0841             c->read->handler = ngx_mail_starttls_handler;
0842             return NGX_OK;
0843         }
0844     }
0845 
0846 #endif
0847 
0848     return NGX_MAIL_PARSE_INVALID_COMMAND;
0849 }
0850 
0851 
0852 static ngx_int_t
0853 ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c,
0854     char *err)
0855 {
0856     ssize_t    n;
0857 
0858     n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last);
0859 
0860     if (n == NGX_ERROR || n == 0) {
0861         ngx_mail_close_connection(c);
0862         return NGX_ERROR;
0863     }
0864 
0865     if (n > 0) {
0866         s->buffer->last += n;
0867     }
0868 
0869     if (n == NGX_AGAIN) {
0870         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
0871             ngx_mail_session_internal_server_error(s);
0872             return NGX_ERROR;
0873         }
0874 
0875         return NGX_AGAIN;
0876     }
0877 
0878     ngx_mail_smtp_log_rejected_command(s, c, err);
0879 
0880     s->buffer->pos = s->buffer->start;
0881     s->buffer->last = s->buffer->start;
0882 
0883     return NGX_OK;
0884 }
0885 
0886 
0887 static void
0888 ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s, ngx_connection_t *c,
0889     char *err)
0890 {
0891     u_char      ch;
0892     ngx_str_t   cmd;
0893     ngx_uint_t  i;
0894 
0895     if (c->log->log_level < NGX_LOG_INFO) {
0896         return;
0897     }
0898 
0899     cmd.len = s->buffer->last - s->buffer->start;
0900     cmd.data = s->buffer->start;
0901 
0902     for (i = 0; i < cmd.len; i++) {
0903         ch = cmd.data[i];
0904 
0905         if (ch != CR && ch != LF) {
0906             continue;
0907         }
0908 
0909         cmd.data[i] = '_';
0910     }
0911 
0912     cmd.len = i;
0913 
0914     ngx_log_error(NGX_LOG_INFO, c->log, 0, err, &cmd);
0915 }