Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

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