1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev#include <ngx_mail.h>
12e18a033bSKonstantin Ananyev#include <ngx_mail_smtp_module.h>
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev
15e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
16e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
17e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
18e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
19e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
20e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_create_buffer(ngx_mail_session_t *s,
21e18a033bSKonstantin Ananyev    ngx_connection_t *c);
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_helo(ngx_mail_session_t *s, ngx_connection_t *c);
24e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c);
25e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c);
26e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_starttls(ngx_mail_session_t *s,
27e18a033bSKonstantin Ananyev    ngx_connection_t *c);
28e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_rset(ngx_mail_session_t *s, ngx_connection_t *c);
29e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c);
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_smtp_discard_command(ngx_mail_session_t *s,
32e18a033bSKonstantin Ananyev    ngx_connection_t *c, char *err);
33e18a033bSKonstantin Ananyevstatic void ngx_mail_smtp_log_rejected_command(ngx_mail_session_t *s,
34e18a033bSKonstantin Ananyev    ngx_connection_t *c, char *err);
35e18a033bSKonstantin Ananyev
36e18a033bSKonstantin Ananyev
37e18a033bSKonstantin Ananyevstatic u_char  smtp_ok[] = "250 2.0.0 OK" CRLF;
38e18a033bSKonstantin Ananyevstatic u_char  smtp_bye[] = "221 2.0.0 Bye" CRLF;
39e18a033bSKonstantin Ananyevstatic u_char  smtp_starttls[] = "220 2.0.0 Start TLS" CRLF;
40e18a033bSKonstantin Ananyevstatic u_char  smtp_next[] = "334 " CRLF;
41e18a033bSKonstantin Ananyevstatic u_char  smtp_username[] = "334 VXNlcm5hbWU6" CRLF;
42e18a033bSKonstantin Ananyevstatic u_char  smtp_password[] = "334 UGFzc3dvcmQ6" CRLF;
43e18a033bSKonstantin Ananyevstatic u_char  smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF;
44e18a033bSKonstantin Ananyevstatic u_char  smtp_invalid_pipelining[] =
45e18a033bSKonstantin Ananyev    "503 5.5.0 Improper use of SMTP command pipelining" CRLF;
46e18a033bSKonstantin Ananyevstatic u_char  smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF;
47e18a033bSKonstantin Ananyevstatic u_char  smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF;
48e18a033bSKonstantin Ananyevstatic u_char  smtp_bad_sequence[] = "503 5.5.1 Bad sequence of commands" CRLF;
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyev
51e18a033bSKonstantin Ananyevstatic ngx_str_t  smtp_unavailable = ngx_string("[UNAVAILABLE]");
52e18a033bSKonstantin Ananyevstatic ngx_str_t  smtp_tempunavail = ngx_string("[TEMPUNAVAIL]");
53e18a033bSKonstantin Ananyev
54e18a033bSKonstantin Ananyev
55e18a033bSKonstantin Ananyevvoid
56e18a033bSKonstantin Ananyevngx_mail_smtp_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
57e18a033bSKonstantin Ananyev{
58e18a033bSKonstantin Ananyev    ngx_resolver_ctx_t        *ctx;
59e18a033bSKonstantin Ananyev    ngx_mail_core_srv_conf_t  *cscf;
60e18a033bSKonstantin Ananyev
61e18a033bSKonstantin Ananyev    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
62e18a033bSKonstantin Ananyev
63e18a033bSKonstantin Ananyev    if (cscf->resolver == NULL) {
64e18a033bSKonstantin Ananyev        s->host = smtp_unavailable;
65e18a033bSKonstantin Ananyev        ngx_mail_smtp_greeting(s, c);
66e18a033bSKonstantin Ananyev        return;
67e18a033bSKonstantin Ananyev    }
68e18a033bSKonstantin Ananyev
69e18a033bSKonstantin Ananyev#if (NGX_HAVE_UNIX_DOMAIN)
70e18a033bSKonstantin Ananyev    if (c->sockaddr->sa_family == AF_UNIX) {
71e18a033bSKonstantin Ananyev        s->host = smtp_tempunavail;
72e18a033bSKonstantin Ananyev        ngx_mail_smtp_greeting(s, c);
73e18a033bSKonstantin Ananyev        return;
74e18a033bSKonstantin Ananyev    }
75e18a033bSKonstantin Ananyev#endif
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyev    c->log->action = "in resolving client address";
78e18a033bSKonstantin Ananyev
79e18a033bSKonstantin Ananyev    ctx = ngx_resolve_start(cscf->resolver, NULL);
80e18a033bSKonstantin Ananyev    if (ctx == NULL) {
81e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
82e18a033bSKonstantin Ananyev        return;
83e18a033bSKonstantin Ananyev    }
84e18a033bSKonstantin Ananyev
85e18a033bSKonstantin Ananyev    ctx->addr.sockaddr = c->sockaddr;
86e18a033bSKonstantin Ananyev    ctx->addr.socklen = c->socklen;
87e18a033bSKonstantin Ananyev    ctx->handler = ngx_mail_smtp_resolve_addr_handler;
88e18a033bSKonstantin Ananyev    ctx->data = s;
89e18a033bSKonstantin Ananyev    ctx->timeout = cscf->resolver_timeout;
90e18a033bSKonstantin Ananyev
91e18a033bSKonstantin Ananyev    if (ngx_resolve_addr(ctx) != NGX_OK) {
92e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
93e18a033bSKonstantin Ananyev    }
94e18a033bSKonstantin Ananyev}
95e18a033bSKonstantin Ananyev
96e18a033bSKonstantin Ananyev
97e18a033bSKonstantin Ananyevstatic void
98e18a033bSKonstantin Ananyevngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
99e18a033bSKonstantin Ananyev{
100e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
101e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
102e18a033bSKonstantin Ananyev
103e18a033bSKonstantin Ananyev    s = ctx->data;
104e18a033bSKonstantin Ananyev    c = s->connection;
105e18a033bSKonstantin Ananyev
106e18a033bSKonstantin Ananyev    if (ctx->state) {
107e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ERR, c->log, 0,
108e18a033bSKonstantin Ananyev                      "%V could not be resolved (%i: %s)",
109e18a033bSKonstantin Ananyev                      &c->addr_text, ctx->state,
110e18a033bSKonstantin Ananyev                      ngx_resolver_strerror(ctx->state));
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev        if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
113e18a033bSKonstantin Ananyev            s->host = smtp_unavailable;
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev        } else {
116e18a033bSKonstantin Ananyev            s->host = smtp_tempunavail;
117e18a033bSKonstantin Ananyev        }
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyev        ngx_resolve_addr_done(ctx);
120e18a033bSKonstantin Ananyev
121e18a033bSKonstantin Ananyev        ngx_mail_smtp_greeting(s, s->connection);
122e18a033bSKonstantin Ananyev
123e18a033bSKonstantin Ananyev        return;
124e18a033bSKonstantin Ananyev    }
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev    c->log->action = "in resolving client hostname";
127e18a033bSKonstantin Ananyev
128e18a033bSKonstantin Ananyev    s->host.data = ngx_pstrdup(c->pool, &ctx->name);
129e18a033bSKonstantin Ananyev    if (s->host.data == NULL) {
130e18a033bSKonstantin Ananyev        ngx_resolve_addr_done(ctx);
131e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
132e18a033bSKonstantin Ananyev        return;
133e18a033bSKonstantin Ananyev    }
134e18a033bSKonstantin Ananyev
135e18a033bSKonstantin Ananyev    s->host.len = ctx->name.len;
136e18a033bSKonstantin Ananyev
137e18a033bSKonstantin Ananyev    ngx_resolve_addr_done(ctx);
138e18a033bSKonstantin Ananyev
139e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
140e18a033bSKonstantin Ananyev                   "address resolved: %V", &s->host);
141e18a033bSKonstantin Ananyev
142e18a033bSKonstantin Ananyev    c->read->handler = ngx_mail_smtp_resolve_name;
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev    ngx_post_event(c->read, &ngx_posted_events);
145e18a033bSKonstantin Ananyev}
146e18a033bSKonstantin Ananyev
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyevstatic void
149e18a033bSKonstantin Ananyevngx_mail_smtp_resolve_name(ngx_event_t *rev)
150e18a033bSKonstantin Ananyev{
151e18a033bSKonstantin Ananyev    ngx_connection_t          *c;
152e18a033bSKonstantin Ananyev    ngx_mail_session_t        *s;
153e18a033bSKonstantin Ananyev    ngx_resolver_ctx_t        *ctx;
154e18a033bSKonstantin Ananyev    ngx_mail_core_srv_conf_t  *cscf;
155e18a033bSKonstantin Ananyev
156e18a033bSKonstantin Ananyev    c = rev->data;
157e18a033bSKonstantin Ananyev    s = c->data;
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
160e18a033bSKonstantin Ananyev
161e18a033bSKonstantin Ananyev    ctx = ngx_resolve_start(cscf->resolver, NULL);
162e18a033bSKonstantin Ananyev    if (ctx == NULL) {
163e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
164e18a033bSKonstantin Ananyev        return;
165e18a033bSKonstantin Ananyev    }
166e18a033bSKonstantin Ananyev
167e18a033bSKonstantin Ananyev    ctx->name = s->host;
168e18a033bSKonstantin Ananyev    ctx->handler = ngx_mail_smtp_resolve_name_handler;
169e18a033bSKonstantin Ananyev    ctx->data = s;
170e18a033bSKonstantin Ananyev    ctx->timeout = cscf->resolver_timeout;
171e18a033bSKonstantin Ananyev
172e18a033bSKonstantin Ananyev    if (ngx_resolve_name(ctx) != NGX_OK) {
173e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
174e18a033bSKonstantin Ananyev    }
175e18a033bSKonstantin Ananyev}
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev
178e18a033bSKonstantin Ananyevstatic void
179e18a033bSKonstantin Ananyevngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx)
180e18a033bSKonstantin Ananyev{
181e18a033bSKonstantin Ananyev    ngx_uint_t           i;
182e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
183e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
184e18a033bSKonstantin Ananyev
185e18a033bSKonstantin Ananyev    s = ctx->data;
186e18a033bSKonstantin Ananyev    c = s->connection;
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    if (ctx->state) {
189e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ERR, c->log, 0,
190e18a033bSKonstantin Ananyev                      "\"%V\" could not be resolved (%i: %s)",
191e18a033bSKonstantin Ananyev                      &ctx->name, ctx->state,
192e18a033bSKonstantin Ananyev                      ngx_resolver_strerror(ctx->state));
193e18a033bSKonstantin Ananyev
194e18a033bSKonstantin Ananyev        if (ctx->state == NGX_RESOLVE_NXDOMAIN) {
195e18a033bSKonstantin Ananyev            s->host = smtp_unavailable;
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev        } else {
198e18a033bSKonstantin Ananyev            s->host = smtp_tempunavail;
199e18a033bSKonstantin Ananyev        }
200e18a033bSKonstantin Ananyev
201e18a033bSKonstantin Ananyev    } else {
202e18a033bSKonstantin Ananyev
203e18a033bSKonstantin Ananyev#if (NGX_DEBUG)
204e18a033bSKonstantin Ananyev        {
205e18a033bSKonstantin Ananyev        u_char     text[NGX_SOCKADDR_STRLEN];
206e18a033bSKonstantin Ananyev        ngx_str_t  addr;
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev        addr.data = text;
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyev        for (i = 0; i < ctx->naddrs; i++) {
211e18a033bSKonstantin Ananyev            addr.len = ngx_sock_ntop(ctx->addrs[i].sockaddr,
212e18a033bSKonstantin Ananyev                                     ctx->addrs[i].socklen,
213e18a033bSKonstantin Ananyev                                     text, NGX_SOCKADDR_STRLEN, 0);
214e18a033bSKonstantin Ananyev
215e18a033bSKonstantin Ananyev            ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
216e18a033bSKonstantin Ananyev                           "name was resolved to %V", &addr);
217e18a033bSKonstantin Ananyev        }
218e18a033bSKonstantin Ananyev        }
219e18a033bSKonstantin Ananyev#endif
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev        for (i = 0; i < ctx->naddrs; i++) {
222e18a033bSKonstantin Ananyev            if (ngx_cmp_sockaddr(ctx->addrs[i].sockaddr, ctx->addrs[i].socklen,
223e18a033bSKonstantin Ananyev                                 c->sockaddr, c->socklen, 0)
224e18a033bSKonstantin Ananyev                == NGX_OK)
225e18a033bSKonstantin Ananyev            {
226e18a033bSKonstantin Ananyev                goto found;
227e18a033bSKonstantin Ananyev            }
228e18a033bSKonstantin Ananyev        }
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev        s->host = smtp_unavailable;
231e18a033bSKonstantin Ananyev    }
232e18a033bSKonstantin Ananyev
233e18a033bSKonstantin Ananyevfound:
234e18a033bSKonstantin Ananyev
235e18a033bSKonstantin Ananyev    ngx_resolve_name_done(ctx);
236e18a033bSKonstantin Ananyev
237e18a033bSKonstantin Ananyev    ngx_mail_smtp_greeting(s, c);
238e18a033bSKonstantin Ananyev}
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev
241e18a033bSKonstantin Ananyevstatic void
242e18a033bSKonstantin Ananyevngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c)
243e18a033bSKonstantin Ananyev{
244e18a033bSKonstantin Ananyev    ngx_msec_t                 timeout;
245e18a033bSKonstantin Ananyev    ngx_mail_core_srv_conf_t  *cscf;
246e18a033bSKonstantin Ananyev    ngx_mail_smtp_srv_conf_t  *sscf;
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
249e18a033bSKonstantin Ananyev                   "smtp greeting for \"%V\"", &s->host);
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
252e18a033bSKonstantin Ananyev    sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
253e18a033bSKonstantin Ananyev
254e18a033bSKonstantin Ananyev    timeout = sscf->greeting_delay ? sscf->greeting_delay : cscf->timeout;
255e18a033bSKonstantin Ananyev    ngx_add_timer(c->read, timeout);
256e18a033bSKonstantin Ananyev
257e18a033bSKonstantin Ananyev    if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
258e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
259e18a033bSKonstantin Ananyev    }
260e18a033bSKonstantin Ananyev
261e18a033bSKonstantin Ananyev    if (sscf->greeting_delay) {
262e18a033bSKonstantin Ananyev         c->read->handler = ngx_mail_smtp_invalid_pipelining;
263e18a033bSKonstantin Ananyev         return;
264e18a033bSKonstantin Ananyev    }
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev    c->read->handler = ngx_mail_smtp_init_protocol;
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev    s->out = sscf->greeting;
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev    ngx_mail_send(c->write);
271e18a033bSKonstantin Ananyev}
272e18a033bSKonstantin Ananyev
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyevstatic void
275e18a033bSKonstantin Ananyevngx_mail_smtp_invalid_pipelining(ngx_event_t *rev)
276e18a033bSKonstantin Ananyev{
277e18a033bSKonstantin Ananyev    ngx_connection_t          *c;
278e18a033bSKonstantin Ananyev    ngx_mail_session_t        *s;
279e18a033bSKonstantin Ananyev    ngx_mail_core_srv_conf_t  *cscf;
280e18a033bSKonstantin Ananyev    ngx_mail_smtp_srv_conf_t  *sscf;
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyev    c = rev->data;
283e18a033bSKonstantin Ananyev    s = c->data;
284e18a033bSKonstantin Ananyev
285e18a033bSKonstantin Ananyev    c->log->action = "in delay pipelining state";
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev    if (rev->timedout) {
288e18a033bSKonstantin Ananyev
289e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "delay greeting");
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev        rev->timedout = 0;
292e18a033bSKonstantin Ananyev
293e18a033bSKonstantin Ananyev        cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
294e18a033bSKonstantin Ananyev
295e18a033bSKonstantin Ananyev        c->read->handler = ngx_mail_smtp_init_protocol;
296e18a033bSKonstantin Ananyev
297e18a033bSKonstantin Ananyev        ngx_add_timer(c->read, cscf->timeout);
298e18a033bSKonstantin Ananyev
299e18a033bSKonstantin Ananyev        if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
300e18a033bSKonstantin Ananyev            ngx_mail_close_connection(c);
301e18a033bSKonstantin Ananyev            return;
302e18a033bSKonstantin Ananyev        }
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev        sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
305e18a033bSKonstantin Ananyev
306e18a033bSKonstantin Ananyev        s->out = sscf->greeting;
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyev    } else {
309e18a033bSKonstantin Ananyev
310e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "invalid pipelining");
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev        if (s->buffer == NULL) {
313e18a033bSKonstantin Ananyev            if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
314e18a033bSKonstantin Ananyev                return;
315e18a033bSKonstantin Ananyev            }
316e18a033bSKonstantin Ananyev        }
317e18a033bSKonstantin Ananyev
318e18a033bSKonstantin Ananyev        if (ngx_mail_smtp_discard_command(s, c,
319e18a033bSKonstantin Ananyev                                "client was rejected before greeting: \"%V\"")
320e18a033bSKonstantin Ananyev            != NGX_OK)
321e18a033bSKonstantin Ananyev        {
322e18a033bSKonstantin Ananyev            return;
323e18a033bSKonstantin Ananyev        }
324e18a033bSKonstantin Ananyev
325e18a033bSKonstantin Ananyev        ngx_str_set(&s->out, smtp_invalid_pipelining);
326e18a033bSKonstantin Ananyev        s->quit = 1;
327e18a033bSKonstantin Ananyev    }
328e18a033bSKonstantin Ananyev
329e18a033bSKonstantin Ananyev    ngx_mail_send(c->write);
330e18a033bSKonstantin Ananyev}
331e18a033bSKonstantin Ananyev
332e18a033bSKonstantin Ananyev
333e18a033bSKonstantin Ananyevvoid
334e18a033bSKonstantin Ananyevngx_mail_smtp_init_protocol(ngx_event_t *rev)
335e18a033bSKonstantin Ananyev{
336e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
337e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
338e18a033bSKonstantin Ananyev
339e18a033bSKonstantin Ananyev    c = rev->data;
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev    c->log->action = "in auth state";
342e18a033bSKonstantin Ananyev
343e18a033bSKonstantin Ananyev    if (rev->timedout) {
344e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
345e18a033bSKonstantin Ananyev        c->timedout = 1;
346e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
347e18a033bSKonstantin Ananyev        return;
348e18a033bSKonstantin Ananyev    }
349e18a033bSKonstantin Ananyev
350e18a033bSKonstantin Ananyev    s = c->data;
351e18a033bSKonstantin Ananyev
352e18a033bSKonstantin Ananyev    if (s->buffer == NULL) {
353e18a033bSKonstantin Ananyev        if (ngx_mail_smtp_create_buffer(s, c) != NGX_OK) {
354e18a033bSKonstantin Ananyev            return;
355e18a033bSKonstantin Ananyev        }
356e18a033bSKonstantin Ananyev    }
357e18a033bSKonstantin Ananyev
358e18a033bSKonstantin Ananyev    s->mail_state = ngx_smtp_start;
359e18a033bSKonstantin Ananyev    c->read->handler = ngx_mail_smtp_auth_state;
360e18a033bSKonstantin Ananyev
361e18a033bSKonstantin Ananyev    ngx_mail_smtp_auth_state(rev);
362e18a033bSKonstantin Ananyev}
363e18a033bSKonstantin Ananyev
364e18a033bSKonstantin Ananyev
365e18a033bSKonstantin Ananyevstatic ngx_int_t
366e18a033bSKonstantin Ananyevngx_mail_smtp_create_buffer(ngx_mail_session_t *s, ngx_connection_t *c)
367e18a033bSKonstantin Ananyev{
368e18a033bSKonstantin Ananyev    ngx_mail_smtp_srv_conf_t  *sscf;
369e18a033bSKonstantin Ananyev
370e18a033bSKonstantin Ananyev    if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) == NGX_ERROR) {
371e18a033bSKonstantin Ananyev        ngx_mail_session_internal_server_error(s);
372e18a033bSKonstantin Ananyev        return NGX_ERROR;
373e18a033bSKonstantin Ananyev    }
374e18a033bSKonstantin Ananyev
375e18a033bSKonstantin Ananyev    sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module);
376e18a033bSKonstantin Ananyev
377e18a033bSKonstantin Ananyev    s->buffer = ngx_create_temp_buf(c->pool, sscf->client_buffer_size);
378e18a033bSKonstantin Ananyev    if (s->buffer == NULL) {
379e18a033bSKonstantin Ananyev        ngx_mail_session_internal_server_error(s);
380e18a033bSKonstantin Ananyev        return NGX_ERROR;
381e18a033bSKonstantin Ananyev    }
382e18a033bSKonstantin Ananyev
383e18a033bSKonstantin Ananyev    return NGX_OK;
384e18a033bSKonstantin Ananyev}
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyev
387e18a033bSKonstantin Ananyevvoid
388e18a033bSKonstantin Ananyevngx_mail_smtp_auth_state(ngx_event_t *rev)
389e18a033bSKonstantin Ananyev{
390e18a033bSKonstantin Ananyev    ngx_int_t            rc;
391e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
392e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyev    c = rev->data;
395e18a033bSKonstantin Ananyev    s = c->data;
396e18a033bSKonstantin Ananyev
397e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state");
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev    if (rev->timedout) {
400e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
401e18a033bSKonstantin Ananyev        c->timedout = 1;
402e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
403e18a033bSKonstantin Ananyev        return;
404e18a033bSKonstantin Ananyev    }
405e18a033bSKonstantin Ananyev
406e18a033bSKonstantin Ananyev    if (s->out.len) {
407e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy");
408e18a033bSKonstantin Ananyev        s->blocked = 1;
409e18a033bSKonstantin Ananyev        return;
410e18a033bSKonstantin Ananyev    }
411e18a033bSKonstantin Ananyev
412e18a033bSKonstantin Ananyev    s->blocked = 0;
413e18a033bSKonstantin Ananyev
414e18a033bSKonstantin Ananyev    rc = ngx_mail_read_command(s, c);
415e18a033bSKonstantin Ananyev
416e18a033bSKonstantin Ananyev    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
417e18a033bSKonstantin Ananyev        return;
418