📄 ngx_mail_smtp_handler.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>#include <ngx_mail.h>#include <ngx_mail_smtp_module.h>static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);static ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c);static ngx_int_t ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c);static ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c);static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c);static ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s, ngx_connection_t *c);static ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s, ngx_connection_t *c, char *err);static void ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s, ngx_connection_t *c, char *err);static u_char smtp_ok[] = "250 2.0.0 OK" CRLF;static u_char smtp_bye[] = "221 2.0.0 Bye" CRLF;static u_char smtp_starttls[] = "220 2.0.0 Start TLS" CRLF;static u_char smtp_next[] = "334 " CRLF;static u_char smtp_username[] = "334 VXNlcm5hbWU6" CRLF;static u_char smtp_password[] = "334 UGFzc3dvcmQ6" CRLF;static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF;static u_char smtp_invalid_pipelining[] = "503 5.5.0 Improper use of SMTP command pipelining" CRLF;static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;static ngx_str_t smtp_unavailable = ngx_string("[UNAVAILABLE]");static ngx_str_t smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");voidngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c){ struct sockaddr_in *sin; ngx_resolver_ctx_t *ctx; ngx_mail_core_srv_conf_t *cscf; cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); if (cscf->resolver == NULL) { s->host = smtp_unavailable; ngx_mail_smtp_greeting(s, c); return; } c->log->action = "in resolving client address"; ctx = ngx_resolve_start(cscf->resolver, NULL); if (ctx == NULL) { ngx_mail_close_connection(c); return; } /* AF_INET only */ sin = (struct sockaddr_in *) c->sockaddr; ctx->addr = sin->sin_addr.s_addr; ctx->handler = ngx_mail_smtp_resolve_addr_handler; ctx->data = s; ctx->timeout = cscf->resolver_timeout; if (ngx_resolve_addr(ctx) != NGX_OK) { ngx_mail_close_connection(c); }}static voidngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx){ ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_core_srv_conf_t *cscf; s = ctx->data; c = s->connection; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "%V could not be resolved (%i: %s)", &c->addr_text, ctx->state, ngx_resolver_strerror(ctx->state)); if (ctx->state == NGX_RESOLVE_NXDOMAIN) { s->host = smtp_unavailable; } else { s->host = smtp_tempunavail; } ngx_resolve_addr_done(ctx); ngx_mail_smtp_greeting(s, s->connection); return; } c->log->action = "in resolving client hostname"; s->host.data = ngx_pstrdup(c->pool, &ctx->name); if (s->host.data == NULL) { ngx_resolve_addr_done(ctx); ngx_mail_close_connection(c); return; } s->host.len = ctx->name.len; ngx_resolve_addr_done(ctx); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "address resolved: %V", &s->host); cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); ctx = ngx_resolve_start(cscf->resolver, NULL); if (ctx == NULL) { ngx_mail_close_connection(c); return; } ctx->name = s->host; ctx->type = NGX_RESOLVE_A; ctx->handler = ngx_mail_smtp_resolve_name_handler; ctx->data = s; ctx->timeout = cscf->resolver_timeout; if (ngx_resolve_name(ctx) != NGX_OK) { ngx_mail_close_connection(c); }}static voidngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx){ in_addr_t addr; ngx_uint_t i; ngx_connection_t *c; struct sockaddr_in *sin; ngx_mail_session_t *s; s = ctx->data; c = s->connection; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "%V could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); if (ctx->state == NGX_RESOLVE_NXDOMAIN) { s->host = smtp_unavailable; } else { s->host = smtp_tempunavail; } } else { /* AF_INET only */ sin = (struct sockaddr_in *) c->sockaddr; for (i = 0; i < ctx->naddrs; i++) { addr = ctx->addrs[i]; ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0, "name was resolved to %ud.%ud.%ud.%ud", (ntohl(addr) >> 24) & 0xff, (ntohl(addr) >> 16) & 0xff, (ntohl(addr) >> 8) & 0xff, ntohl(addr) & 0xff); if (addr == sin->sin_addr.s_addr) { goto found; } } s->host = smtp_unavailable; }found: ngx_resolve_name_done(ctx); ngx_mail_smtp_greeting(s, c);}static voidngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c){ ngx_msec_t timeout; ngx_mail_core_srv_conf_t *cscf; ngx_mail_smtp_srv_conf_t *sscf; ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp greeting for \"%V\"", &s->host); cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout; ngx_add_timer(c->read, timeout); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { ngx_mail_close_connection(c); } if (sscf->greeting_delay) { c->read->handler = ngx_mail_smtp_invalid_pipelining; return; } c->read->handler = ngx_mail_smtp_init_protocol; s->out = sscf->greeting; ngx_mail_send(c->write);}static voidngx_mail_smtp_invalid_pipelining(ngx_event_t *rev){ ngx_connection_t *c; ngx_mail_session_t *s; ngx_mail_core_srv_conf_t *cscf; ngx_mail_smtp_srv_conf_t *sscf; c = rev->data; s = c->data; c->log->action = "in delay pipelining state"; if (rev->timedout) { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting"); rev->timedout = 0; cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); c->read->handler = ngx_mail_smtp_init_protocol; ngx_add_timer(c->read, cscf->timeout); if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { ngx_mail_close_connection(c); return; } sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); s->out = sscf->greeting; } else { ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining"); if (s->buffer == NULL) { if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) { return; } } if (ngx_mail_smtp_discard_command(s, c, "client was rejected before greeting: \"%V\"") != NGX_OK) { return; } s->out.len = sizeof(smtp_invalid_pipelining) - 1; s->out.data = smtp_invalid_pipelining; } ngx_mail_send(c->write);}voidngx_mail_smtp_init_protocol(ngx_event_t *rev){ ngx_connection_t *c; ngx_mail_session_t *s; c = rev->data; c->log->action = "in auth state"; if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); c->timedout = 1; ngx_mail_close_connection(c); return; } s = c->data; if (s->buffer == NULL) { if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) { return; } } s->mail_state = ngx_smtp_start; c->read->handler = ngx_mail_smtp_auth_state; ngx_mail_smtp_auth_state(rev);}static ngx_int_tngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c){ ngx_mail_smtp_srv_conf_t *sscf; if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) { ngx_mail_session_internal_server_error(s); return NGX_ERROR; } sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size); if (s->buffer == NULL) { ngx_mail_session_internal_server_error(s); return NGX_ERROR; } return NGX_OK;}voidngx_mail_smtp_auth_state(ngx_event_t *rev){ ngx_int_t rc; ngx_connection_t *c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -