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_pop3_module.h>
13e18a033bSKonstantin Ananyev
14e18a033bSKonstantin Ananyev
15e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c);
16e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c);
17e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c,
18e18a033bSKonstantin Ananyev    ngx_int_t stls);
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c);
20e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c);
21e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c);
22e18a033bSKonstantin Ananyev
23e18a033bSKonstantin Ananyev
24e18a033bSKonstantin Ananyevstatic u_char  pop3_greeting[] = "+OK POP3 ready" CRLF;
25e18a033bSKonstantin Ananyevstatic u_char  pop3_ok[] = "+OK" CRLF;
26e18a033bSKonstantin Ananyevstatic u_char  pop3_next[] = "+ " CRLF;
27e18a033bSKonstantin Ananyevstatic u_char  pop3_username[] = "+ VXNlcm5hbWU6" CRLF;
28e18a033bSKonstantin Ananyevstatic u_char  pop3_password[] = "+ UGFzc3dvcmQ6" CRLF;
29e18a033bSKonstantin Ananyevstatic u_char  pop3_invalid_command[] = "-ERR invalid command" CRLF;
30e18a033bSKonstantin Ananyev
31e18a033bSKonstantin Ananyev
32e18a033bSKonstantin Ananyevvoid
33e18a033bSKonstantin Ananyevngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
34e18a033bSKonstantin Ananyev{
35e18a033bSKonstantin Ananyev    u_char                    *p;
36e18a033bSKonstantin Ananyev    ngx_mail_core_srv_conf_t  *cscf;
37e18a033bSKonstantin Ananyev    ngx_mail_pop3_srv_conf_t  *pscf;
38e18a033bSKonstantin Ananyev
39e18a033bSKonstantin Ananyev    pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
40e18a033bSKonstantin Ananyev    cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyev    if (pscf->auth_methods
43e18a033bSKonstantin Ananyev        & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED))
44e18a033bSKonstantin Ananyev    {
45e18a033bSKonstantin Ananyev        if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
46e18a033bSKonstantin Ananyev            ngx_mail_session_internal_server_error(s);
47e18a033bSKonstantin Ananyev            return;
48e18a033bSKonstantin Ananyev        }
49e18a033bSKonstantin Ananyev
50e18a033bSKonstantin Ananyev        s->out.data = ngx_pnalloc(c->pool, sizeof(pop3_greeting) + s->salt.len);
51e18a033bSKonstantin Ananyev        if (s->out.data == NULL) {
52e18a033bSKonstantin Ananyev            ngx_mail_session_internal_server_error(s);
53e18a033bSKonstantin Ananyev            return;
54e18a033bSKonstantin Ananyev        }
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyev        p = ngx_cpymem(s->out.data, pop3_greeting, sizeof(pop3_greeting) - 3);
57e18a033bSKonstantin Ananyev        *p++ = ' ';
58e18a033bSKonstantin Ananyev        p = ngx_cpymem(p, s->salt.data, s->salt.len);
59e18a033bSKonstantin Ananyev
60e18a033bSKonstantin Ananyev        s->out.len = p - s->out.data;
61e18a033bSKonstantin Ananyev
62e18a033bSKonstantin Ananyev    } else {
63e18a033bSKonstantin Ananyev        ngx_str_set(&s->out, pop3_greeting);
64e18a033bSKonstantin Ananyev    }
65e18a033bSKonstantin Ananyev
66e18a033bSKonstantin Ananyev    c->read->handler = ngx_mail_pop3_init_protocol;
67e18a033bSKonstantin Ananyev
68e18a033bSKonstantin Ananyev    ngx_add_timer(c->read, cscf->timeout);
69e18a033bSKonstantin Ananyev
70e18a033bSKonstantin Ananyev    if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
71e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
72e18a033bSKonstantin Ananyev    }
73e18a033bSKonstantin Ananyev
74e18a033bSKonstantin Ananyev    ngx_mail_send(c->write);
75e18a033bSKonstantin Ananyev}
76e18a033bSKonstantin Ananyev
77e18a033bSKonstantin Ananyev
78e18a033bSKonstantin Ananyevvoid
79e18a033bSKonstantin Ananyevngx_mail_pop3_init_protocol(ngx_event_t *rev)
80e18a033bSKonstantin Ananyev{
81e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
82e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
83e18a033bSKonstantin Ananyev
84e18a033bSKonstantin Ananyev    c = rev->data;
85e18a033bSKonstantin Ananyev
86e18a033bSKonstantin Ananyev    c->log->action = "in auth state";
87e18a033bSKonstantin Ananyev
88e18a033bSKonstantin Ananyev    if (rev->timedout) {
89e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
90e18a033bSKonstantin Ananyev        c->timedout = 1;
91e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
92e18a033bSKonstantin Ananyev        return;
93e18a033bSKonstantin Ananyev    }
94e18a033bSKonstantin Ananyev
95e18a033bSKonstantin Ananyev    s = c->data;
96e18a033bSKonstantin Ananyev
97e18a033bSKonstantin Ananyev    if (s->buffer == NULL) {
98e18a033bSKonstantin Ananyev        if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t))
99e18a033bSKonstantin Ananyev            == NGX_ERROR)
100e18a033bSKonstantin Ananyev        {
101e18a033bSKonstantin Ananyev            ngx_mail_session_internal_server_error(s);
102e18a033bSKonstantin Ananyev            return;
103e18a033bSKonstantin Ananyev        }
104e18a033bSKonstantin Ananyev
105e18a033bSKonstantin Ananyev        s->buffer = ngx_create_temp_buf(c->pool, 128);
106e18a033bSKonstantin Ananyev        if (s->buffer == NULL) {
107e18a033bSKonstantin Ananyev            ngx_mail_session_internal_server_error(s);
108e18a033bSKonstantin Ananyev            return;
109e18a033bSKonstantin Ananyev        }
110e18a033bSKonstantin Ananyev    }
111e18a033bSKonstantin Ananyev
112e18a033bSKonstantin Ananyev    s->mail_state = ngx_pop3_start;
113e18a033bSKonstantin Ananyev    c->read->handler = ngx_mail_pop3_auth_state;
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev    ngx_mail_pop3_auth_state(rev);
116e18a033bSKonstantin Ananyev}
117e18a033bSKonstantin Ananyev
118e18a033bSKonstantin Ananyev
119e18a033bSKonstantin Ananyevvoid
120e18a033bSKonstantin Ananyevngx_mail_pop3_auth_state(ngx_event_t *rev)
121e18a033bSKonstantin Ananyev{
122e18a033bSKonstantin Ananyev    ngx_int_t            rc;
123e18a033bSKonstantin Ananyev    ngx_connection_t    *c;
124e18a033bSKonstantin Ananyev    ngx_mail_session_t  *s;
125e18a033bSKonstantin Ananyev
126e18a033bSKonstantin Ananyev    c = rev->data;
127e18a033bSKonstantin Ananyev    s = c->data;
128e18a033bSKonstantin Ananyev
129e18a033bSKonstantin Ananyev    ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 auth state");
130e18a033bSKonstantin Ananyev
131e18a033bSKonstantin Ananyev    if (rev->timedout) {
132e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
133e18a033bSKonstantin Ananyev        c->timedout = 1;
134e18a033bSKonstantin Ananyev        ngx_mail_close_connection(c);
135e18a033bSKonstantin Ananyev        return;
136e18a033bSKonstantin Ananyev    }
137e18a033bSKonstantin Ananyev
138e18a033bSKonstantin Ananyev    if (s->out.len) {
139e18a033bSKonstantin Ananyev        ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy");
140e18a033bSKonstantin Ananyev        s->blocked = 1;
141e18a033bSKonstantin Ananyev        return;
142e18a033bSKonstantin Ananyev    }
143e18a033bSKonstantin Ananyev
144e18a033bSKonstantin Ananyev    s->blocked = 0;
145e18a033bSKonstantin Ananyev
146e18a033bSKonstantin Ananyev    rc = ngx_mail_read_command(s, c);
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev    if (rc == NGX_AGAIN || rc == NGX_ERROR) {
149e18a033bSKonstantin Ananyev        return;
150e18a033bSKonstantin Ananyev    }
151e18a033bSKonstantin Ananyev
152e18a033bSKonstantin Ananyev    ngx_str_set(&s->out, pop3_ok);
153e18a033bSKonstantin Ananyev
154e18a033bSKonstantin Ananyev    if (rc == NGX_OK) {
155e18a033bSKonstantin Ananyev        switch (s->mail_state) {
156e18a033bSKonstantin Ananyev
157e18a033bSKonstantin Ananyev        case ngx_pop3_start:
158e18a033bSKonstantin Ananyev
159e18a033bSKonstantin Ananyev            switch (s->command) {
160e18a033bSKonstantin Ananyev
161e18a033bSKonstantin Ananyev            case NGX_POP3_USER:
162e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_user(s, c);
163e18a033bSKonstantin Ananyev                break;
164e18a033bSKonstantin Ananyev
165e18a033bSKonstantin Ananyev            case NGX_POP3_CAPA:
166e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_capa(s, c, 1);
167e18a033bSKonstantin Ananyev                break;
168e18a033bSKonstantin Ananyev
169e18a033bSKonstantin Ananyev            case NGX_POP3_APOP:
170e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_apop(s, c);
171e18a033bSKonstantin Ananyev                break;
172e18a033bSKonstantin Ananyev
173e18a033bSKonstantin Ananyev            case NGX_POP3_AUTH:
174e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_auth(s, c);
175e18a033bSKonstantin Ananyev                break;
176e18a033bSKonstantin Ananyev
177e18a033bSKonstantin Ananyev            case NGX_POP3_QUIT:
178e18a033bSKonstantin Ananyev                s->quit = 1;
179e18a033bSKonstantin Ananyev                break;
180e18a033bSKonstantin Ananyev
181e18a033bSKonstantin Ananyev            case NGX_POP3_NOOP:
182e18a033bSKonstantin Ananyev                break;
183e18a033bSKonstantin Ananyev
184e18a033bSKonstantin Ananyev            case NGX_POP3_STLS:
185e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_stls(s, c);
186e18a033bSKonstantin Ananyev                break;
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev            default:
189e18a033bSKonstantin Ananyev                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
190e18a033bSKonstantin Ananyev                break;
191e18a033bSKonstantin Ananyev            }
192e18a033bSKonstantin Ananyev
193e18a033bSKonstantin Ananyev            break;
194e18a033bSKonstantin Ananyev
195e18a033bSKonstantin Ananyev        case ngx_pop3_user:
196e18a033bSKonstantin Ananyev
197e18a033bSKonstantin Ananyev            switch (s->command) {
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev            case NGX_POP3_PASS:
200e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_pass(s, c);
201e18a033bSKonstantin Ananyev                break;
202e18a033bSKonstantin Ananyev
203e18a033bSKonstantin Ananyev            case NGX_POP3_CAPA:
204e18a033bSKonstantin Ananyev                rc = ngx_mail_pop3_capa(s, c, 0);
205e18a033bSKonstantin Ananyev                break;
206e18a033bSKonstantin Ananyev
207e18a033bSKonstantin Ananyev            case NGX_POP3_QUIT:
208e18a033bSKonstantin Ananyev                s->quit = 1;
209e18a033bSKonstantin Ananyev                break;
210e18a033bSKonstantin Ananyev
211e18a033bSKonstantin Ananyev            case NGX_POP3_NOOP:
212e18a033bSKonstantin Ananyev                break;
213e18a033bSKonstantin Ananyev
214e18a033bSKonstantin Ananyev            default:
215e18a033bSKonstantin Ananyev                rc = NGX_MAIL_PARSE_INVALID_COMMAND;
216e18a033bSKonstantin Ananyev                break;
217e18a033bSKonstantin Ananyev            }
218e18a033bSKonstantin Ananyev
219e18a033bSKonstantin Ananyev            break;
220e18a033bSKonstantin Ananyev
221e18a033bSKonstantin Ananyev        /* suppress warnings */
222e18a033bSKonstantin Ananyev        case ngx_pop3_passwd:
223e18a033bSKonstantin Ananyev            break;
224e18a033bSKonstantin Ananyev
225e18a033bSKonstantin Ananyev        case ngx_pop3_auth_login_username:
226e18a033bSKonstantin Ananyev            rc = ngx_mail_auth_login_username(s, c, 0);
227e18a033bSKonstantin Ananyev
228e18a033bSKonstantin Ananyev            ngx_str_set(&s->out, pop3_password);
229e18a033bSKonstantin Ananyev            s->mail_state = ngx_pop3_auth_login_password;
230e18a033bSKonstantin Ananyev            break;
231e18a033bSKonstantin Ananyev
232e18a033bSKonstantin Ananyev        case ngx_pop3_auth_login_password:
233e18a033bSKonstantin Ananyev            rc = ngx_mail_auth_login_password(s, c);
234e18a033bSKonstantin Ananyev            break;
235e18a033bSKonstantin Ananyev
236e18a033bSKonstantin Ananyev        case ngx_pop3_auth_plain:
237e18a033bSKonstantin Ananyev            rc = ngx_mail_auth_plain(s, c, 0);
238e18a033bSKonstantin Ananyev            break;
239e18a033bSKonstantin Ananyev
240e18a033bSKonstantin Ananyev        case ngx_pop3_auth_cram_md5:
241e18a033bSKonstantin Ananyev            rc = ngx_mail_auth_cram_md5(s, c);
242e18a033bSKonstantin Ananyev            break;
243e18a033bSKonstantin Ananyev
244e18a033bSKonstantin Ananyev        case ngx_pop3_auth_external:
245e18a033bSKonstantin Ananyev            rc = ngx_mail_auth_external(s, c, 0);
246e18a033bSKonstantin Ananyev            break;
247e18a033bSKonstantin Ananyev        }
248e18a033bSKonstantin Ananyev    }
249e18a033bSKonstantin Ananyev
250e18a033bSKonstantin Ananyev    switch (rc) {
251e18a033bSKonstantin Ananyev
252e18a033bSKonstantin Ananyev    case NGX_DONE:
253e18a033bSKonstantin Ananyev        ngx_mail_auth(s, c);
254e18a033bSKonstantin Ananyev        return;
255e18a033bSKonstantin Ananyev
256e18a033bSKonstantin Ananyev    case NGX_ERROR:
257e18a033bSKonstantin Ananyev        ngx_mail_session_internal_server_error(s);
258e18a033bSKonstantin Ananyev        return;
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev    case NGX_MAIL_PARSE_INVALID_COMMAND:
261e18a033bSKonstantin Ananyev        s->mail_state = ngx_pop3_start;
262e18a033bSKonstantin Ananyev        s->state = 0;
263e18a033bSKonstantin Ananyev
264e18a033bSKonstantin Ananyev        ngx_str_set(&s->out, pop3_invalid_command);
265e18a033bSKonstantin Ananyev
266e18a033bSKonstantin Ananyev        /* fall through */
267e18a033bSKonstantin Ananyev
268e18a033bSKonstantin Ananyev    case NGX_OK:
269e18a033bSKonstantin Ananyev
270e18a033bSKonstantin Ananyev        s->args.nelts = 0;
271e18a033bSKonstantin Ananyev        s->buffer->pos = s->buffer->start;
272e18a033bSKonstantin Ananyev        s->buffer->last = s->buffer->start;
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev        if (s->state) {
275e18a033bSKonstantin Ananyev            s->arg_start = s->buffer->start;
276e18a033bSKonstantin Ananyev        }
277e18a033bSKonstantin Ananyev
278e18a033bSKonstantin Ananyev        ngx_mail_send(c->write);
279e18a033bSKonstantin Ananyev    }
280e18a033bSKonstantin Ananyev}
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyevstatic ngx_int_t
283e18a033bSKonstantin Ananyevngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c)
284e18a033bSKonstantin Ananyev{
285e18a033bSKonstantin Ananyev    ngx_str_t  *arg;
286e18a033bSKonstantin Ananyev
287e18a033bSKonstantin Ananyev#if (NGX_MAIL_SSL)
288e18a033bSKonstantin Ananyev    if (ngx_mail_starttls_only(s, c)) {
289e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
290e18a033bSKonstantin Ananyev    }
291e18a033bSKonstantin Ananyev#endif
292e18a033bSKonstantin Ananyev
293e18a033bSKonstantin Ananyev    if (s->args.nelts != 1) {
294e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
295e18a033bSKonstantin Ananyev    }
296e18a033bSKonstantin Ananyev
297e18a033bSKonstantin Ananyev    arg = s->args.elts;
298e18a033bSKonstantin Ananyev    s->login.len = arg[0].len;
299e18a033bSKonstantin Ananyev    s->login.data = ngx_pnalloc(c->pool, s->login.len);
300e18a033bSKonstantin Ananyev    if (s->login.data == NULL) {
301e18a033bSKonstantin Ananyev        return NGX_ERROR;
302e18a033bSKonstantin Ananyev    }
303e18a033bSKonstantin Ananyev
304e18a033bSKonstantin Ananyev    ngx_memcpy(s->login.data, arg[0].data, s->login.len);
305e18a033bSKonstantin Ananyev
306e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
307e18a033bSKonstantin Ananyev                   "pop3 login: \"%V\"", &s->login);
308e18a033bSKonstantin Ananyev
309e18a033bSKonstantin Ananyev    s->mail_state = ngx_pop3_user;
310e18a033bSKonstantin Ananyev
311e18a033bSKonstantin Ananyev    return NGX_OK;
312e18a033bSKonstantin Ananyev}
313e18a033bSKonstantin Ananyev
314e18a033bSKonstantin Ananyev
315e18a033bSKonstantin Ananyevstatic ngx_int_t
316e18a033bSKonstantin Ananyevngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c)
317e18a033bSKonstantin Ananyev{
318e18a033bSKonstantin Ananyev    ngx_str_t  *arg;
319e18a033bSKonstantin Ananyev
320e18a033bSKonstantin Ananyev    if (s->args.nelts != 1) {
321e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
322e18a033bSKonstantin Ananyev    }
323e18a033bSKonstantin Ananyev
324e18a033bSKonstantin Ananyev    arg = s->args.elts;
325e18a033bSKonstantin Ananyev    s->passwd.len = arg[0].len;
326e18a033bSKonstantin Ananyev    s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len);
327e18a033bSKonstantin Ananyev    if (s->passwd.data == NULL) {
328e18a033bSKonstantin Ananyev        return NGX_ERROR;
329e18a033bSKonstantin Ananyev    }
330e18a033bSKonstantin Ananyev
331e18a033bSKonstantin Ananyev    ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len);
332e18a033bSKonstantin Ananyev
333e18a033bSKonstantin Ananyev#if (NGX_DEBUG_MAIL_PASSWD)
334e18a033bSKonstantin Ananyev    ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
335e18a033bSKonstantin Ananyev                   "pop3 passwd: \"%V\"", &s->passwd);
336e18a033bSKonstantin Ananyev#endif
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyev    return NGX_DONE;
339e18a033bSKonstantin Ananyev}
340e18a033bSKonstantin Ananyev
341e18a033bSKonstantin Ananyev
342e18a033bSKonstantin Ananyevstatic ngx_int_t
343e18a033bSKonstantin Ananyevngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, ngx_int_t stls)
344e18a033bSKonstantin Ananyev{
345e18a033bSKonstantin Ananyev    ngx_mail_pop3_srv_conf_t  *pscf;
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev    pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
348e18a033bSKonstantin Ananyev
349e18a033bSKonstantin Ananyev#if (NGX_MAIL_SSL)
350e18a033bSKonstantin Ananyev
351e18a033bSKonstantin Ananyev    if (stls && c->ssl == NULL) {
352e18a033bSKonstantin Ananyev        ngx_mail_ssl_conf_t  *sslcf;
353e18a033bSKonstantin Ananyev
354e18a033bSKonstantin Ananyev        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
355e18a033bSKonstantin Ananyev
356e18a033bSKonstantin Ananyev        if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
357e18a033bSKonstantin Ananyev            s->out = pscf->starttls_capability;
358e18a033bSKonstantin Ananyev            return NGX_OK;
359e18a033bSKonstantin Ananyev        }
360e18a033bSKonstantin Ananyev
361e18a033bSKonstantin Ananyev        if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
362e18a033bSKonstantin Ananyev            s->out = pscf->starttls_only_capability;
363e18a033bSKonstantin Ananyev            return NGX_OK;
364e18a033bSKonstantin Ananyev        }
365e18a033bSKonstantin Ananyev    }
366e18a033bSKonstantin Ananyev
367e18a033bSKonstantin Ananyev#endif
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev    s->out = pscf->capability;
370e18a033bSKonstantin Ananyev    return NGX_OK;
371e18a033bSKonstantin Ananyev}
372e18a033bSKonstantin Ananyev
373e18a033bSKonstantin Ananyev
374e18a033bSKonstantin Ananyevstatic ngx_int_t
375e18a033bSKonstantin Ananyevngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c)
376e18a033bSKonstantin Ananyev{
377e18a033bSKonstantin Ananyev#if (NGX_MAIL_SSL)
378e18a033bSKonstantin Ananyev    ngx_mail_ssl_conf_t  *sslcf;
379e18a033bSKonstantin Ananyev
380e18a033bSKonstantin Ananyev    if (c->ssl == NULL) {
381e18a033bSKonstantin Ananyev        sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
382e18a033bSKonstantin Ananyev        if (sslcf->starttls) {
383e18a033bSKonstantin Ananyev            c->read->handler = ngx_mail_starttls_handler;
384e18a033bSKonstantin Ananyev            return NGX_OK;
385e18a033bSKonstantin Ananyev        }
386e18a033bSKonstantin Ananyev    }
387e18a033bSKonstantin Ananyev
388e18a033bSKonstantin Ananyev#endif
389e18a033bSKonstantin Ananyev
390e18a033bSKonstantin Ananyev    return NGX_MAIL_PARSE_INVALID_COMMAND;
391e18a033bSKonstantin Ananyev}
392e18a033bSKonstantin Ananyev
393e18a033bSKonstantin Ananyev
394e18a033bSKonstantin Ananyevstatic ngx_int_t
395e18a033bSKonstantin Ananyevngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c)
396e18a033bSKonstantin Ananyev{
397e18a033bSKonstantin Ananyev    ngx_str_t                 *arg;
398e18a033bSKonstantin Ananyev    ngx_mail_pop3_srv_conf_t  *pscf;
399e18a033bSKonstantin Ananyev
400e18a033bSKonstantin Ananyev#if (NGX_MAIL_SSL)
401e18a033bSKonstantin Ananyev    if (ngx_mail_starttls_only(s, c)) {
402e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
403e18a033bSKonstantin Ananyev    }
404e18a033bSKonstantin Ananyev#endif
405e18a033bSKonstantin Ananyev
406e18a033bSKonstantin Ananyev    if (s->args.nelts != 2) {
407e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
408e18a033bSKonstantin Ananyev    }
409e18a033bSKonstantin Ananyev
410e18a033bSKonstantin Ananyev    pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
411e18a033bSKonstantin Ananyev
412e18a033bSKonstantin Ananyev    if (!(pscf->auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) {
413e18a033bSKonstantin Ananyev        return NGX_MAIL_PARSE_INVALID_COMMAND;
414e18a033bSKonstantin Ananyev    }
415e18a033bSKonstantin Ananyev
416e18a033bSKonstantin Ananyev    arg = s->args.elts;
417e18a033bSKonstantin Ananyev
418e18a033bSKonstantin Ananyev    s->login.len = arg[0].len;
419e18a033bSKonstantin Ananyev    s->login.data = ngx_pnalloc(c->pool, s->login.len);
420