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