Mercurial > hg > nginx-mail
annotate src/mail/ngx_mail_handler.c @ 398:f9e6413396d4 PATCH_NGINX_MAIL_0_2
Mail: IMAP AUTHENTICATE command support.
Supported auth methods: PLAIN, LOGIN, CRAM-MD5.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 19 Jul 2007 02:43:59 +0000 |
parents | e2d916d7e50f |
children | f1e2fab7a46c |
rev | line source |
---|---|
290 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_mail.h> | |
11 | |
12 | |
13 static void ngx_mail_init_session(ngx_connection_t *c); | |
14 static void ngx_mail_init_protocol(ngx_event_t *rev); | |
15 static ngx_int_t ngx_mail_decode_auth_plain(ngx_mail_session_t *s, | |
16 ngx_str_t *encoded); | |
17 static void ngx_mail_do_auth(ngx_mail_session_t *s); | |
18 static u_char *ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len); | |
19 | |
20 #if (NGX_MAIL_SSL) | |
21 static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c); | |
22 static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c); | |
23 #endif | |
24 | |
25 | |
26 static ngx_str_t greetings[] = { | |
27 ngx_string("+OK POP3 ready" CRLF), | |
28 ngx_string("* OK IMAP4 ready" CRLF) | |
29 /* SMTP greeting */ | |
30 }; | |
31 | |
32 static ngx_str_t internal_server_errors[] = { | |
33 ngx_string("-ERR internal server error" CRLF), | |
34 ngx_string("* BAD internal server error" CRLF), | |
35 ngx_string("451 4.3.2 Internal server error" CRLF), | |
36 }; | |
37 | |
38 static u_char pop3_ok[] = "+OK" CRLF; | |
39 static u_char pop3_next[] = "+ " CRLF; | |
40 static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; | |
41 static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; | |
42 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; | |
43 | |
44 static u_char imap_star[] = "* "; | |
45 static u_char imap_ok[] = "OK completed" CRLF; | |
46 static u_char imap_next[] = "+ OK" CRLF; | |
47 static u_char imap_bye[] = "* BYE" CRLF; | |
48 static u_char imap_invalid_command[] = "BAD invalid command" CRLF; | |
49 | |
50 static u_char smtp_ok[] = "250 2.0.0 OK" CRLF; | |
51 static u_char smtp_bye[] = "221 2.0.0 Bye" CRLF; | |
52 static u_char smtp_next[] = "334 " CRLF; | |
53 static u_char smtp_username[] = "334 VXNlcm5hbWU6" CRLF; | |
54 static u_char smtp_password[] = "334 UGFzc3dvcmQ6" CRLF; | |
55 static u_char smtp_invalid_command[] = "500 5.5.1 Invalid command" CRLF; | |
56 static u_char smtp_invalid_argument[] = "501 5.5.4 Invalid argument" CRLF; | |
57 static u_char smtp_auth_required[] = "530 5.7.1 Authentication required" CRLF; | |
58 | |
59 | |
60 void | |
61 ngx_mail_init_connection(ngx_connection_t *c) | |
62 { | |
63 in_addr_t in_addr; | |
64 socklen_t len; | |
65 ngx_uint_t i; | |
66 struct sockaddr_in sin; | |
67 ngx_mail_log_ctx_t *ctx; | |
68 ngx_mail_in_port_t *imip; | |
69 ngx_mail_in_addr_t *imia; | |
70 ngx_mail_session_t *s; | |
71 #if (NGX_MAIL_SSL) | |
72 ngx_mail_ssl_conf_t *sslcf; | |
73 #endif | |
74 | |
75 | |
76 /* find the server configuration for the address:port */ | |
77 | |
78 /* AF_INET only */ | |
79 | |
80 imip = c->listening->servers; | |
81 imia = imip->addrs; | |
82 | |
83 i = 0; | |
84 | |
85 if (imip->naddrs > 1) { | |
86 | |
87 /* | |
88 * There are several addresses on this port and one of them | |
89 * is the "*:port" wildcard so getsockname() is needed to determine | |
90 * the server address. | |
91 * | |
92 * AcceptEx() already gave this address. | |
93 */ | |
94 | |
95 #if (NGX_WIN32) | |
96 if (c->local_sockaddr) { | |
97 in_addr = | |
98 ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr; | |
99 | |
100 } else | |
101 #endif | |
102 { | |
103 len = sizeof(struct sockaddr_in); | |
104 if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { | |
105 ngx_connection_error(c, ngx_socket_errno, | |
106 "getsockname() failed"); | |
107 ngx_mail_close_connection(c); | |
108 return; | |
109 } | |
110 | |
111 in_addr = sin.sin_addr.s_addr; | |
112 } | |
113 | |
114 /* the last address is "*" */ | |
115 | |
116 for ( /* void */ ; i < imip->naddrs - 1; i++) { | |
117 if (in_addr == imia[i].addr) { | |
118 break; | |
119 } | |
120 } | |
121 } | |
122 | |
123 | |
124 s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); | |
125 if (s == NULL) { | |
126 ngx_mail_close_connection(c); | |
127 return; | |
128 } | |
129 | |
130 s->main_conf = imia[i].ctx->main_conf; | |
131 s->srv_conf = imia[i].ctx->srv_conf; | |
132 | |
133 s->addr_text = &imia[i].addr_text; | |
134 | |
135 c->data = s; | |
136 s->connection = c; | |
137 | |
138 ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V", | |
139 c->number, &c->addr_text, s->addr_text); | |
140 | |
141 ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t)); | |
142 if (ctx == NULL) { | |
143 ngx_mail_close_connection(c); | |
144 return; | |
145 } | |
146 | |
147 ctx->client = &c->addr_text; | |
148 ctx->session = s; | |
149 | |
150 c->log->connection = c->number; | |
151 c->log->handler = ngx_mail_log_error; | |
152 c->log->data = ctx; | |
153 c->log->action = "sending client greeting line"; | |
154 | |
155 c->log_error = NGX_ERROR_INFO; | |
156 | |
157 #if (NGX_MAIL_SSL) | |
158 | |
159 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); | |
160 | |
161 if (sslcf->enable) { | |
162 ngx_mail_ssl_init_connection(&sslcf->ssl, c); | |
163 return; | |
164 } | |
165 | |
166 #endif | |
167 | |
168 ngx_mail_init_session(c); | |
169 } | |
170 | |
171 | |
172 #if (NGX_MAIL_SSL) | |
173 | |
394 | 174 void |
290 | 175 ngx_mail_starttls_handler(ngx_event_t *rev) |
176 { | |
177 ngx_connection_t *c; | |
178 ngx_mail_session_t *s; | |
179 ngx_mail_ssl_conf_t *sslcf; | |
180 | |
181 c = rev->data; | |
182 s = c->data; | |
183 s->starttls = 1; | |
184 | |
185 c->log->action = "in starttls state"; | |
186 | |
187 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); | |
188 | |
189 ngx_mail_ssl_init_connection(&sslcf->ssl, c); | |
190 } | |
191 | |
192 | |
193 static void | |
194 ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c) | |
195 { | |
196 ngx_mail_session_t *s; | |
197 ngx_mail_core_srv_conf_t *cscf; | |
198 | |
199 if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) { | |
200 ngx_mail_close_connection(c); | |
201 return; | |
202 } | |
203 | |
204 if (ngx_ssl_handshake(c) == NGX_AGAIN) { | |
205 | |
206 s = c->data; | |
207 | |
208 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
209 | |
210 ngx_add_timer(c->read, cscf->timeout); | |
211 | |
212 c->ssl->handler = ngx_mail_ssl_handshake_handler; | |
213 | |
214 return; | |
215 } | |
216 | |
217 ngx_mail_ssl_handshake_handler(c); | |
218 } | |
219 | |
220 | |
221 static void | |
222 ngx_mail_ssl_handshake_handler(ngx_connection_t *c) | |
223 { | |
224 ngx_mail_session_t *s; | |
225 | |
226 if (c->ssl->handshaked) { | |
227 | |
228 s = c->data; | |
229 | |
230 if (s->starttls) { | |
231 c->read->handler = ngx_mail_init_protocol; | |
232 c->write->handler = ngx_mail_send; | |
233 | |
234 ngx_mail_init_protocol(c->read); | |
235 | |
236 return; | |
237 } | |
238 | |
239 ngx_mail_init_session(c); | |
240 return; | |
241 } | |
242 | |
243 ngx_mail_close_connection(c); | |
244 } | |
245 | |
246 #endif | |
247 | |
248 | |
249 static void | |
250 ngx_mail_init_session(ngx_connection_t *c) | |
251 { | |
252 u_char *p; | |
253 ngx_mail_session_t *s; | |
254 ngx_mail_core_srv_conf_t *cscf; | |
255 | |
256 c->read->handler = ngx_mail_init_protocol; | |
257 c->write->handler = ngx_mail_send; | |
258 | |
259 s = c->data; | |
260 | |
261 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
262 | |
263 s->protocol = cscf->protocol; | |
264 | |
265 s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module); | |
266 if (s->ctx == NULL) { | |
267 ngx_mail_session_internal_server_error(s); | |
268 return; | |
269 } | |
270 | |
394 | 271 if (cscf->handler_init_session) { |
272 cscf->handler_init_session(c); | |
273 return; | |
274 } | |
275 | |
290 | 276 if (s->protocol == NGX_MAIL_SMTP_PROTOCOL) { |
277 s->out = cscf->smtp_greeting; | |
278 | |
279 } else { | |
280 s->out = greetings[s->protocol]; | |
281 } | |
282 | |
283 if ((s->protocol == NGX_MAIL_POP3_PROTOCOL | |
284 && (cscf->pop3_auth_methods | |
285 & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED))) | |
286 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
287 || (s->protocol == NGX_MAIL_IMAP_PROTOCOL |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
288 && (cscf->imap_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
289 |
290 | 290 || (s->protocol == NGX_MAIL_SMTP_PROTOCOL |
291 && (cscf->smtp_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED))) | |
292 { | |
293 s->salt.data = ngx_palloc(c->pool, | |
294 sizeof(" <18446744073709551616.@>" CRLF) - 1 | |
295 + NGX_TIME_T_LEN | |
296 + cscf->server_name.len); | |
297 if (s->salt.data == NULL) { | |
298 ngx_mail_session_internal_server_error(s); | |
299 return; | |
300 } | |
301 | |
302 s->salt.len = ngx_sprintf(s->salt.data, "<%ul.%T@%V>" CRLF, | |
303 ngx_random(), ngx_time(), &cscf->server_name) | |
304 - s->salt.data; | |
305 | |
306 if (s->protocol == NGX_MAIL_POP3_PROTOCOL) { | |
296 | 307 s->out.data = ngx_palloc(c->pool, |
290 | 308 greetings[0].len + 1 + s->salt.len); |
296 | 309 if (s->out.data == NULL) { |
310 ngx_mail_session_internal_server_error(s); | |
311 return; | |
312 } | |
290 | 313 |
296 | 314 p = ngx_cpymem(s->out.data, |
290 | 315 greetings[0].data, greetings[0].len - 2); |
296 | 316 *p++ = ' '; |
317 p = ngx_cpymem(p, s->salt.data, s->salt.len); | |
290 | 318 |
296 | 319 s->out.len = p - s->out.data; |
290 | 320 } |
321 } | |
322 | |
323 ngx_add_timer(c->read, cscf->timeout); | |
324 | |
325 if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { | |
326 ngx_mail_close_connection(c); | |
327 } | |
328 | |
329 ngx_mail_send(c->write); | |
330 } | |
331 | |
332 | |
333 void | |
334 ngx_mail_send(ngx_event_t *wev) | |
335 { | |
336 ngx_int_t n; | |
337 ngx_connection_t *c; | |
338 ngx_mail_session_t *s; | |
339 ngx_mail_core_srv_conf_t *cscf; | |
340 | |
341 c = wev->data; | |
342 s = c->data; | |
343 | |
344 if (wev->timedout) { | |
345 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
346 c->timedout = 1; | |
347 ngx_mail_close_connection(c); | |
348 return; | |
349 } | |
350 | |
351 if (s->out.len == 0) { | |
352 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
353 ngx_mail_close_connection(c); | |
354 } | |
355 | |
356 return; | |
357 } | |
358 | |
359 n = c->send(c, s->out.data, s->out.len); | |
360 | |
361 if (n > 0) { | |
362 s->out.len -= n; | |
363 | |
364 if (wev->timer_set) { | |
365 ngx_del_timer(wev); | |
366 } | |
367 | |
368 if (s->quit) { | |
369 ngx_mail_close_connection(c); | |
370 return; | |
371 } | |
372 | |
373 if (s->blocked) { | |
374 c->read->handler(c->read); | |
375 } | |
376 | |
377 return; | |
378 } | |
379 | |
380 if (n == NGX_ERROR) { | |
381 ngx_mail_close_connection(c); | |
382 return; | |
383 } | |
384 | |
385 /* n == NGX_AGAIN */ | |
386 | |
387 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
388 | |
389 ngx_add_timer(c->write, cscf->timeout); | |
390 | |
391 if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { | |
392 ngx_mail_close_connection(c); | |
393 return; | |
394 } | |
395 } | |
396 | |
397 | |
398 static void | |
399 ngx_mail_init_protocol(ngx_event_t *rev) | |
400 { | |
401 size_t size; | |
402 ngx_connection_t *c; | |
403 ngx_mail_session_t *s; | |
404 ngx_mail_core_srv_conf_t *cscf; | |
405 | |
406 c = rev->data; | |
407 | |
408 c->log->action = "in auth state"; | |
409 | |
410 if (rev->timedout) { | |
411 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
412 c->timedout = 1; | |
413 ngx_mail_close_connection(c); | |
414 return; | |
415 } | |
416 | |
417 s = c->data; | |
394 | 418 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
419 | |
420 if (cscf->handler_init_protocol) { | |
421 cscf->handler_init_protocol(rev); | |
422 return; | |
423 } | |
290 | 424 |
425 switch (s->protocol) { | |
426 | |
427 case NGX_MAIL_POP3_PROTOCOL: | |
428 size = 128; | |
429 s->mail_state = ngx_pop3_start; | |
430 c->read->handler = ngx_pop3_auth_state; | |
431 break; | |
432 | |
433 case NGX_MAIL_IMAP_PROTOCOL: | |
434 size = cscf->imap_client_buffer_size; | |
435 s->mail_state = ngx_imap_start; | |
436 c->read->handler = ngx_imap_auth_state; | |
437 break; | |
438 | |
439 default: /* NGX_MAIL_SMTP_PROTOCOL */ | |
440 size = 512; | |
441 s->mail_state = ngx_smtp_start; | |
442 c->read->handler = ngx_smtp_auth_state; | |
443 break; | |
444 } | |
445 | |
446 if (s->buffer == NULL) { | |
447 if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t)) | |
448 == NGX_ERROR) | |
449 { | |
450 ngx_mail_session_internal_server_error(s); | |
451 return; | |
452 } | |
453 | |
454 s->buffer = ngx_create_temp_buf(c->pool, size); | |
455 if (s->buffer == NULL) { | |
456 ngx_mail_session_internal_server_error(s); | |
457 return; | |
458 } | |
459 } | |
460 | |
394 | 461 if (cscf->handler_read) { |
462 c->read->handler = cscf->handler_read; | |
463 } | |
464 | |
290 | 465 c->read->handler(rev); |
466 } | |
467 | |
468 | |
469 void | |
470 ngx_pop3_auth_state(ngx_event_t *rev) | |
471 { | |
472 u_char *p, *last, *text; | |
473 ssize_t size; | |
474 ngx_int_t rc; | |
475 ngx_str_t *arg, salt; | |
476 ngx_connection_t *c; | |
477 ngx_mail_session_t *s; | |
478 ngx_mail_core_srv_conf_t *cscf; | |
479 #if (NGX_MAIL_SSL) | |
480 ngx_mail_ssl_conf_t *sslcf; | |
481 #endif | |
482 | |
483 c = rev->data; | |
484 s = c->data; | |
485 | |
486 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 auth state"); | |
487 | |
488 if (rev->timedout) { | |
489 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
490 c->timedout = 1; | |
491 ngx_mail_close_connection(c); | |
492 return; | |
493 } | |
494 | |
495 if (s->out.len) { | |
496 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy"); | |
497 s->blocked = 1; | |
498 return; | |
499 } | |
500 | |
501 s->blocked = 0; | |
502 | |
503 rc = ngx_mail_read_command(s); | |
504 | |
505 if (rc == NGX_AGAIN || rc == NGX_ERROR) { | |
506 return; | |
507 } | |
508 | |
509 text = pop3_ok; | |
510 size = sizeof(pop3_ok) - 1; | |
511 | |
512 if (rc == NGX_OK) { | |
513 switch (s->mail_state) { | |
514 | |
515 case ngx_pop3_start: | |
516 | |
517 switch (s->command) { | |
518 | |
519 case NGX_POP3_USER: | |
520 | |
521 #if (NGX_MAIL_SSL) | |
522 | |
523 if (c->ssl == NULL) { | |
524 sslcf = ngx_mail_get_module_srv_conf(s, | |
525 ngx_mail_ssl_module); | |
526 | |
527 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { | |
528 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
529 break; | |
530 } | |
531 } | |
532 #endif | |
533 | |
534 if (s->args.nelts == 1) { | |
535 s->mail_state = ngx_pop3_user; | |
536 | |
537 arg = s->args.elts; | |
538 s->login.len = arg[0].len; | |
539 s->login.data = ngx_palloc(c->pool, s->login.len); | |
540 if (s->login.data == NULL) { | |
541 ngx_mail_session_internal_server_error(s); | |
542 return; | |
543 } | |
544 | |
545 ngx_memcpy(s->login.data, arg[0].data, s->login.len); | |
546 | |
547 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
548 "pop3 login: \"%V\"", &s->login); | |
549 | |
550 break; | |
551 } | |
552 | |
553 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
554 break; | |
555 | |
556 case NGX_POP3_CAPA: | |
557 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
558 | |
559 #if (NGX_MAIL_SSL) | |
560 | |
561 if (c->ssl == NULL) { | |
562 sslcf = ngx_mail_get_module_srv_conf(s, | |
563 ngx_mail_ssl_module); | |
564 | |
565 if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { | |
566 size = cscf->pop3_starttls_capability.len; | |
567 text = cscf->pop3_starttls_capability.data; | |
568 break; | |
569 } | |
570 | |
571 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { | |
572 size = cscf->pop3_starttls_only_capability.len; | |
573 text = cscf->pop3_starttls_only_capability.data; | |
574 break; | |
575 } | |
576 } | |
577 #endif | |
578 | |
579 size = cscf->pop3_capability.len; | |
580 text = cscf->pop3_capability.data; | |
581 break; | |
582 | |
583 case NGX_POP3_APOP: | |
584 | |
585 #if (NGX_MAIL_SSL) | |
586 | |
587 if (c->ssl == NULL) { | |
588 sslcf = ngx_mail_get_module_srv_conf(s, | |
589 ngx_mail_ssl_module); | |
590 | |
591 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { | |
592 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
593 break; | |
594 } | |
595 } | |
596 #endif | |
597 | |
598 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
599 | |
600 if ((cscf->pop3_auth_methods & NGX_MAIL_AUTH_APOP_ENABLED) | |
601 && s->args.nelts == 2) | |
602 { | |
603 arg = s->args.elts; | |
604 | |
605 s->login.len = arg[0].len; | |
606 s->login.data = ngx_palloc(c->pool, s->login.len); | |
607 if (s->login.data == NULL) { | |
608 ngx_mail_session_internal_server_error(s); | |
609 return; | |
610 } | |
611 | |
612 ngx_memcpy(s->login.data, arg[0].data, s->login.len); | |
613 | |
614 s->passwd.len = arg[1].len; | |
615 s->passwd.data = ngx_palloc(c->pool, s->passwd.len); | |
616 if (s->passwd.data == NULL) { | |
617 ngx_mail_session_internal_server_error(s); | |
618 return; | |
619 } | |
620 | |
621 ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len); | |
622 | |
623 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
624 "pop3 apop: \"%V\" \"%V\"", | |
625 &s->login, &s->passwd); | |
626 | |
627 s->auth_method = NGX_MAIL_AUTH_APOP; | |
628 | |
629 ngx_mail_do_auth(s); | |
630 return; | |
631 } | |
632 | |
633 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
634 break; | |
635 | |
636 case NGX_POP3_AUTH: | |
637 | |
638 #if (NGX_MAIL_SSL) | |
639 | |
640 if (c->ssl == NULL) { | |
641 sslcf = ngx_mail_get_module_srv_conf(s, | |
642 ngx_mail_ssl_module); | |
643 | |
644 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { | |
645 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
646 break; | |
647 } | |
648 } | |
649 #endif | |
650 | |
651 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
652 | |
653 if (s->args.nelts == 0) { | |
654 size = cscf->pop3_auth_capability.len; | |
655 text = cscf->pop3_auth_capability.data; | |
656 s->state = 0; | |
657 break; | |
658 } | |
659 | |
660 arg = s->args.elts; | |
661 | |
662 if (arg[0].len == 5) { | |
663 | |
664 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) | |
665 == 0) | |
666 { | |
667 | |
668 if (s->args.nelts != 1) { | |
669 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
670 break; | |
671 } | |
672 | |
673 s->mail_state = ngx_pop3_auth_login_username; | |
674 | |
675 size = sizeof(pop3_username) - 1; | |
676 text = pop3_username; | |
677 | |
678 break; | |
679 | |
680 } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", | |
681 5) | |
682 == 0) | |
683 { | |
684 | |
685 if (s->args.nelts == 1) { | |
686 s->mail_state = ngx_pop3_auth_plain; | |
687 | |
688 size = sizeof(pop3_next) - 1; | |
689 text = pop3_next; | |
690 | |
691 break; | |
692 } | |
693 | |
694 if (s->args.nelts == 2) { | |
695 | |
696 /* | |
697 * workaround for Eudora for Mac: it sends | |
698 * AUTH PLAIN [base64 encoded] | |
699 */ | |
700 | |
701 rc = ngx_mail_decode_auth_plain(s, &arg[1]); | |
702 | |
703 if (rc == NGX_OK) { | |
704 ngx_mail_do_auth(s); | |
705 return; | |
706 } | |
707 | |
708 if (rc == NGX_ERROR) { | |
709 ngx_mail_session_internal_server_error(s); | |
710 return; | |
711 } | |
712 | |
713 /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */ | |
714 | |
715 break; | |
716 } | |
717 | |
718 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
719 break; | |
720 } | |
721 | |
722 } else if (arg[0].len == 8 | |
723 && ngx_strncasecmp(arg[0].data, | |
724 (u_char *) "CRAM-MD5", 8) | |
725 == 0) | |
726 { | |
318 | 727 if (!(cscf->pop3_auth_methods |
728 & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) | |
729 || s->args.nelts != 1) | |
730 { | |
290 | 731 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
732 break; | |
733 } | |
734 | |
735 s->mail_state = ngx_pop3_auth_cram_md5; | |
736 | |
737 text = ngx_palloc(c->pool, | |
738 sizeof("+ " CRLF) - 1 | |
739 + ngx_base64_encoded_length(s->salt.len)); | |
740 if (text == NULL) { | |
741 ngx_mail_session_internal_server_error(s); | |
742 return; | |
743 } | |
744 | |
745 text[0] = '+'; text[1]= ' '; | |
746 salt.data = &text[2]; | |
747 s->salt.len -= 2; | |
748 | |
749 ngx_encode_base64(&salt, &s->salt); | |
750 | |
751 s->salt.len += 2; | |
752 size = 2 + salt.len; | |
753 text[size++] = CR; text[size++] = LF; | |
754 | |
755 break; | |
756 } | |
757 | |
758 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
759 break; | |
760 | |
761 case NGX_POP3_QUIT: | |
762 s->quit = 1; | |
763 break; | |
764 | |
765 case NGX_POP3_NOOP: | |
766 break; | |
767 | |
768 #if (NGX_MAIL_SSL) | |
769 | |
770 case NGX_POP3_STLS: | |
771 if (c->ssl == NULL) { | |
772 sslcf = ngx_mail_get_module_srv_conf(s, | |
773 ngx_mail_ssl_module); | |
774 if (sslcf->starttls) { | |
775 c->read->handler = ngx_mail_starttls_handler; | |
776 break; | |
777 } | |
778 } | |
779 | |
780 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
781 break; | |
782 #endif | |
783 | |
784 default: | |
785 s->mail_state = ngx_pop3_start; | |
786 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
787 break; | |
788 } | |
789 | |
790 break; | |
791 | |
792 case ngx_pop3_user: | |
793 | |
794 switch (s->command) { | |
795 | |
796 case NGX_POP3_PASS: | |
797 if (s->args.nelts == 1) { | |
798 arg = s->args.elts; | |
799 s->passwd.len = arg[0].len; | |
800 s->passwd.data = ngx_palloc(c->pool, s->passwd.len); | |
801 if (s->passwd.data == NULL) { | |
802 ngx_mail_session_internal_server_error(s); | |
803 return; | |
804 } | |
805 | |
806 ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len); | |
807 | |
808 #if (NGX_DEBUG_MAIL_PASSWD) | |
809 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
810 "pop3 passwd: \"%V\"", &s->passwd); | |
811 #endif | |
812 | |
813 ngx_mail_do_auth(s); | |
814 return; | |
815 } | |
816 | |
817 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
818 break; | |
819 | |
820 case NGX_POP3_CAPA: | |
821 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
822 size = cscf->pop3_capability.len; | |
823 text = cscf->pop3_capability.data; | |
824 break; | |
825 | |
826 case NGX_POP3_QUIT: | |
827 s->quit = 1; | |
828 break; | |
829 | |
830 case NGX_POP3_NOOP: | |
831 break; | |
832 | |
833 default: | |
834 s->mail_state = ngx_pop3_start; | |
835 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
836 break; | |
837 } | |
838 | |
839 break; | |
840 | |
841 /* suppress warinings */ | |
842 case ngx_pop3_passwd: | |
843 break; | |
844 | |
845 case ngx_pop3_auth_login_username: | |
846 arg = s->args.elts; | |
847 s->mail_state = ngx_pop3_auth_login_password; | |
848 | |
849 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
850 "pop3 auth login username: \"%V\"", &arg[0]); | |
851 | |
852 s->login.data = ngx_palloc(c->pool, | |
853 ngx_base64_decoded_length(arg[0].len)); | |
854 if (s->login.data == NULL){ | |
855 ngx_mail_session_internal_server_error(s); | |
856 return; | |
857 } | |
858 | |
859 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
860 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
861 "client sent invalid base64 encoding " | |
862 "in AUTH LOGIN command"); | |
863 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
864 break; | |
865 } | |
866 | |
867 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
868 "pop3 auth login username: \"%V\"", &s->login); | |
869 | |
870 size = sizeof(pop3_password) - 1; | |
871 text = pop3_password; | |
872 | |
873 break; | |
874 | |
875 case ngx_pop3_auth_login_password: | |
876 arg = s->args.elts; | |
877 | |
878 #if (NGX_DEBUG_MAIL_PASSWD) | |
879 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
880 "pop3 auth login password: \"%V\"", &arg[0]); | |
881 #endif | |
882 | |
883 s->passwd.data = ngx_palloc(c->pool, | |
884 ngx_base64_decoded_length(arg[0].len)); | |
885 if (s->passwd.data == NULL){ | |
886 ngx_mail_session_internal_server_error(s); | |
887 return; | |
888 } | |
889 | |
890 if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { | |
891 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
892 "client sent invalid base64 encoding " | |
893 "in AUTH LOGIN command"); | |
894 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
895 break; | |
896 } | |
897 | |
898 #if (NGX_DEBUG_MAIL_PASSWD) | |
899 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
900 "pop3 auth login password: \"%V\"", &s->passwd); | |
901 #endif | |
902 | |
903 ngx_mail_do_auth(s); | |
904 return; | |
905 | |
906 case ngx_pop3_auth_plain: | |
907 arg = s->args.elts; | |
908 | |
909 rc = ngx_mail_decode_auth_plain(s, &arg[0]); | |
910 | |
911 if (rc == NGX_OK) { | |
912 ngx_mail_do_auth(s); | |
913 return; | |
914 } | |
915 | |
916 if (rc == NGX_ERROR) { | |
917 ngx_mail_session_internal_server_error(s); | |
918 return; | |
919 } | |
920 | |
921 /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */ | |
922 | |
923 break; | |
924 | |
925 case ngx_pop3_auth_cram_md5: | |
926 arg = s->args.elts; | |
927 | |
928 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
929 "pop3 auth cram-md5: \"%V\"", &arg[0]); | |
930 | |
931 s->login.data = ngx_palloc(c->pool, | |
932 ngx_base64_decoded_length(arg[0].len)); | |
933 if (s->login.data == NULL){ | |
934 ngx_mail_session_internal_server_error(s); | |
935 return; | |
936 } | |
937 | |
938 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
939 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
940 "client sent invalid base64 encoding " | |
941 "in AUTH CRAM-MD5 command"); | |
942 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
943 break; | |
944 } | |
945 | |
946 p = s->login.data; | |
947 last = p + s->login.len; | |
948 | |
949 while (p < last) { | |
950 if (*p++ == ' ') { | |
951 s->login.len = p - s->login.data - 1; | |
952 s->passwd.len = last - p; | |
953 s->passwd.data = p; | |
954 break; | |
955 } | |
956 } | |
957 | |
958 if (s->passwd.len != 32) { | |
959 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
960 "client sent invalid CRAM-MD5 hash " | |
961 "in AUTH CRAM-MD5 command"); | |
962 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
963 break; | |
964 } | |
965 | |
966 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
967 "pop3 auth cram-md5: \"%V\" \"%V\"", | |
968 &s->login, &s->passwd); | |
969 | |
970 s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; | |
971 | |
972 ngx_mail_do_auth(s); | |
973 return; | |
974 } | |
975 } | |
976 | |
977 if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { | |
978 s->mail_state = ngx_pop3_start; | |
979 s->state = 0; | |
980 text = pop3_invalid_command; | |
981 size = sizeof(pop3_invalid_command) - 1; | |
982 } | |
983 | |
984 s->args.nelts = 0; | |
985 s->buffer->pos = s->buffer->start; | |
986 s->buffer->last = s->buffer->start; | |
987 | |
988 if (s->state) { | |
989 s->arg_start = s->buffer->start; | |
990 } | |
991 | |
992 s->out.data = text; | |
993 s->out.len = size; | |
994 | |
995 ngx_mail_send(c->write); | |
996 } | |
997 | |
998 | |
999 void | |
1000 ngx_imap_auth_state(ngx_event_t *rev) | |
1001 { | |
1002 u_char *p, *last, *text, *dst, *src, *end; | |
1003 ssize_t text_len, last_len; | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1004 ngx_str_t *arg, salt; |
290 | 1005 ngx_int_t rc; |
1006 ngx_uint_t tag, i; | |
1007 ngx_connection_t *c; | |
1008 ngx_mail_session_t *s; | |
1009 ngx_mail_core_srv_conf_t *cscf; | |
1010 #if (NGX_MAIL_SSL) | |
1011 ngx_mail_ssl_conf_t *sslcf; | |
1012 #endif | |
1013 | |
1014 c = rev->data; | |
1015 s = c->data; | |
1016 | |
1017 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth state"); | |
1018 | |
1019 if (rev->timedout) { | |
1020 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
1021 c->timedout = 1; | |
1022 ngx_mail_close_connection(c); | |
1023 return; | |
1024 } | |
1025 | |
1026 if (s->out.len) { | |
1027 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap send handler busy"); | |
1028 s->blocked = 1; | |
1029 return; | |
1030 } | |
1031 | |
1032 s->blocked = 0; | |
1033 | |
1034 rc = ngx_mail_read_command(s); | |
1035 | |
1036 if (rc == NGX_AGAIN || rc == NGX_ERROR) { | |
1037 return; | |
1038 } | |
1039 | |
1040 tag = 1; | |
1041 | |
1042 text = NULL; | |
1043 text_len = 0; | |
1044 | |
1045 last = imap_ok; | |
1046 last_len = sizeof(imap_ok) - 1; | |
1047 | |
1048 if (rc == NGX_OK) { | |
1049 | |
1050 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "imap auth command: %i", | |
1051 s->command); | |
1052 | |
1053 if (s->backslash) { | |
1054 | |
1055 arg = s->args.elts; | |
1056 | |
1057 for (i = 0; i < s->args.nelts; i++) { | |
1058 dst = arg[i].data; | |
1059 end = dst + arg[i].len; | |
1060 | |
1061 for (src = dst; src < end; dst++) { | |
1062 *dst = *src; | |
1063 if (*src++ == '\\') { | |
1064 *dst = *src++; | |
1065 } | |
1066 } | |
1067 | |
1068 arg[i].len = dst - arg[i].data; | |
1069 } | |
1070 | |
1071 s->backslash = 0; | |
1072 } | |
1073 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1074 switch (s->mail_state) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1075 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1076 case ngx_imap_start: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1077 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1078 switch (s->command) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1079 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1080 case NGX_IMAP_LOGIN: |
290 | 1081 |
1082 #if (NGX_MAIL_SSL) | |
1083 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1084 if (c->ssl == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1085 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1086 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1087 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1088 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1089 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1090 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1091 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1092 #endif |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1093 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1094 arg = s->args.elts; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1095 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1096 if (s->args.nelts == 2 && arg[0].len) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1097 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1098 s->login.len = arg[0].len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1099 s->login.data = ngx_palloc(c->pool, s->login.len); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1100 if (s->login.data == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1101 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1102 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1103 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1104 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1105 ngx_memcpy(s->login.data, arg[0].data, s->login.len); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1106 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1107 s->passwd.len = arg[1].len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1108 s->passwd.data = ngx_palloc(c->pool, s->passwd.len); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1109 if (s->passwd.data == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1110 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1111 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1112 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1113 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1114 ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1115 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1116 #if (NGX_DEBUG_MAIL_PASSWD) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1117 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1118 "imap login:\"%V\" passwd:\"%V\"", |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1119 &s->login, &s->passwd); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1120 #else |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1121 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1122 "imap login:\"%V\"", &s->login); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1123 #endif |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1124 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1125 ngx_mail_do_auth(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1126 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1127 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1128 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1129 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1130 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1131 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1132 case NGX_IMAP_AUTHENTICATE: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1133 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1134 #if (NGX_MAIL_SSL) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1135 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1136 if (c->ssl == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1137 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1138 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1139 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1140 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1141 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1142 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1143 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1144 #endif |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1145 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1146 if (s->args.nelts != 1) { |
290 | 1147 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
1148 break; | |
1149 } | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1150 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1151 arg = s->args.elts; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1152 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1153 if (arg[0].len == 5) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1154 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1155 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1156 == 0) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1157 { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1158 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1159 s->mail_state = ngx_imap_auth_login_username; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1160 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1161 last_len = sizeof(pop3_username) - 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1162 last = pop3_username; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1163 tag = 0; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1164 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1165 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1166 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1167 } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1168 5) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1169 == 0) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1170 { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1171 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1172 s->mail_state = ngx_imap_auth_plain; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1173 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1174 last_len = sizeof(pop3_next) - 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1175 last = pop3_next; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1176 tag = 0; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1177 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1178 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1179 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1180 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1181 } else if (arg[0].len == 8 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1182 && ngx_strncasecmp(arg[0].data, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1183 (u_char *) "CRAM-MD5", 8) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1184 == 0) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1185 { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1186 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1187 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1188 if (!(cscf->imap_auth_methods |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1189 & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1190 || s->args.nelts != 1) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1191 { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1192 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1193 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1194 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1195 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1196 s->mail_state = ngx_imap_auth_cram_md5; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1197 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1198 last = ngx_palloc(c->pool, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1199 sizeof("+ " CRLF) - 1 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1200 + ngx_base64_encoded_length(s->salt.len)); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1201 if (last == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1202 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1203 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1204 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1205 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1206 last[0] = '+'; last[1]= ' '; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1207 salt.data = &last[2]; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1208 s->salt.len -= 2; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1209 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1210 ngx_encode_base64(&salt, &s->salt); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1211 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1212 s->salt.len += 2; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1213 last_len = 2 + salt.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1214 last[last_len++] = CR; last[last_len++] = LF; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1215 tag = 0; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1216 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1217 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1218 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1219 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1220 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1221 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1222 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1223 case NGX_IMAP_CAPABILITY: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1224 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1225 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1226 #if (NGX_MAIL_SSL) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1227 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1228 if (c->ssl == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1229 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1230 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1231 if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1232 text_len = cscf->imap_starttls_capability.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1233 text = cscf->imap_starttls_capability.data; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1234 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1235 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1236 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1237 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1238 text_len = cscf->imap_starttls_only_capability.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1239 text = cscf->imap_starttls_only_capability.data; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1240 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1241 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1242 } |
290 | 1243 #endif |
1244 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1245 text_len = cscf->imap_capability.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1246 text = cscf->imap_capability.data; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1247 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1248 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1249 case NGX_IMAP_LOGOUT: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1250 s->quit = 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1251 text = imap_bye; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1252 text_len = sizeof(imap_bye) - 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1253 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1254 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1255 case NGX_IMAP_NOOP: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1256 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1257 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1258 #if (NGX_MAIL_SSL) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1259 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1260 case NGX_IMAP_STARTTLS: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1261 if (c->ssl == NULL) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1262 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1263 if (sslcf->starttls) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1264 c->read->handler = ngx_mail_starttls_handler; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1265 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1266 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1267 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1268 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1269 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1270 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1271 #endif |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1272 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1273 default: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1274 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1275 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1276 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1277 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1278 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1279 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1280 case ngx_imap_auth_login_username: |
290 | 1281 arg = s->args.elts; |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1282 s->mail_state = ngx_imap_auth_login_password; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1283 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1284 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1285 "imap auth login username: \"%V\"", &arg[0]); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1286 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1287 s->login.data = ngx_palloc(c->pool, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1288 ngx_base64_decoded_length(arg[0].len)); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1289 if (s->login.data == NULL){ |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1290 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1291 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1292 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1293 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1294 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1295 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1296 "client sent invalid base64 encoding " |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1297 "in AUTH LOGIN command"); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1298 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1299 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1300 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1301 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1302 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1303 "imap auth login username: \"%V\"", &s->login); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1304 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1305 last_len = sizeof(pop3_password) - 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1306 last = pop3_password; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1307 tag = 0; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1308 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1309 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1310 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1311 case ngx_imap_auth_login_password: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1312 arg = s->args.elts; |
290 | 1313 |
1314 #if (NGX_DEBUG_MAIL_PASSWD) | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1315 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1316 "imap auth login password: \"%V\"", &arg[0]); |
290 | 1317 #endif |
1318 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1319 s->passwd.data = ngx_palloc(c->pool, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1320 ngx_base64_decoded_length(arg[0].len)); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1321 if (s->passwd.data == NULL){ |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1322 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1323 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1324 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1325 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1326 if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1327 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1328 "client sent invalid base64 encoding " |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1329 "in AUTH LOGIN command"); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1330 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1331 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1332 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1333 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1334 #if (NGX_DEBUG_MAIL_PASSWD) |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1335 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1336 "imap auth login password: \"%V\"", &s->passwd); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1337 #endif |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1338 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1339 ngx_mail_do_auth(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1340 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1341 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1342 case ngx_imap_auth_plain: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1343 arg = s->args.elts; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1344 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1345 rc = ngx_mail_decode_auth_plain(s, &arg[0]); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1346 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1347 if (rc == NGX_OK) { |
290 | 1348 ngx_mail_do_auth(s); |
1349 return; | |
1350 } | |
1351 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1352 if (rc == NGX_ERROR) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1353 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1354 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1355 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1356 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1357 /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */ |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1358 |
290 | 1359 break; |
1360 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1361 case ngx_imap_auth_cram_md5: |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1362 arg = s->args.elts; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1363 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1364 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1365 "imap auth cram-md5: \"%V\"", &arg[0]); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1366 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1367 s->login.data = ngx_palloc(c->pool, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1368 ngx_base64_decoded_length(arg[0].len)); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1369 if (s->login.data == NULL){ |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1370 ngx_mail_session_internal_server_error(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1371 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1372 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1373 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1374 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1375 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1376 "client sent invalid base64 encoding " |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1377 "in AUTH CRAM-MD5 command"); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1378 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1379 break; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1380 } |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1381 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1382 p = s->login.data; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1383 last = p + s->login.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1384 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1385 while (p < last) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1386 if (*p++ == ' ') { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1387 s->login.len = p - s->login.data - 1; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1388 s->passwd.len = last - p; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1389 s->passwd.data = p; |
290 | 1390 break; |
1391 } | |
1392 } | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1393 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1394 if (s->passwd.len != 32) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1395 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1396 "client sent invalid CRAM-MD5 hash " |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1397 "in AUTH CRAM-MD5 command"); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1398 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1399 break; |
290 | 1400 } |
1401 | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1402 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1403 "imap auth cram-md5: \"%V\" \"%V\"", |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1404 &s->login, &s->passwd); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1405 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1406 s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1407 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1408 ngx_mail_do_auth(s); |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1409 return; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1410 |
290 | 1411 } |
1412 | |
1413 } else if (rc == NGX_IMAP_NEXT) { | |
1414 last = imap_next; | |
1415 last_len = sizeof(imap_next) - 1; | |
1416 tag = 0; | |
1417 } | |
1418 | |
1419 if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1420 s->mail_state = ngx_imap_start; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1421 s->state = 0; |
290 | 1422 last = imap_invalid_command; |
1423 last_len = sizeof(imap_invalid_command) - 1; | |
1424 } | |
1425 | |
1426 if (tag) { | |
1427 if (s->tag.len == 0) { | |
1428 s->tag.len = sizeof(imap_star) - 1; | |
1429 s->tag.data = (u_char *) imap_star; | |
1430 } | |
1431 | |
1432 if (s->tagged_line.len < s->tag.len + text_len + last_len) { | |
1433 s->tagged_line.len = s->tag.len + text_len + last_len; | |
1434 s->tagged_line.data = ngx_palloc(c->pool, s->tagged_line.len); | |
1435 if (s->tagged_line.data == NULL) { | |
1436 ngx_mail_close_connection(c); | |
1437 return; | |
1438 } | |
1439 } | |
1440 | |
1441 s->out.data = s->tagged_line.data; | |
1442 s->out.len = s->tag.len + text_len + last_len; | |
1443 | |
1444 p = s->out.data; | |
1445 | |
1446 if (text) { | |
1447 p = ngx_cpymem(p, text, text_len); | |
1448 } | |
1449 p = ngx_cpymem(p, s->tag.data, s->tag.len); | |
1450 ngx_memcpy(p, last, last_len); | |
1451 | |
1452 | |
1453 } else { | |
1454 s->out.data = last; | |
1455 s->out.len = last_len; | |
1456 } | |
1457 | |
1458 if (rc != NGX_IMAP_NEXT) { | |
1459 s->args.nelts = 0; | |
398
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1460 |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1461 if (s->state) { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1462 /* preserve tag */ |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1463 s->arg_start = s->buffer->start + s->tag.len; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1464 s->buffer->pos = s->arg_start; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1465 s->buffer->last = s->arg_start; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1466 } else { |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1467 s->buffer->pos = s->buffer->start; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1468 s->buffer->last = s->buffer->start; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1469 s->tag.len = 0; |
f9e6413396d4
Mail: IMAP AUTHENTICATE command support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
396
diff
changeset
|
1470 } |
290 | 1471 } |
1472 | |
1473 ngx_mail_send(c->write); | |
1474 } | |
1475 | |
1476 | |
1477 void | |
1478 ngx_smtp_auth_state(ngx_event_t *rev) | |
1479 { | |
1480 u_char *p, *last, *text, ch; | |
1481 ssize_t size; | |
1482 ngx_int_t rc; | |
1483 ngx_str_t *arg, salt, l; | |
1484 ngx_uint_t i; | |
1485 ngx_connection_t *c; | |
1486 ngx_mail_session_t *s; | |
1487 ngx_mail_core_srv_conf_t *cscf; | |
395
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1488 #if (NGX_MAIL_SSL) |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1489 ngx_mail_ssl_conf_t *sslcf; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1490 #endif |
290 | 1491 |
1492 c = rev->data; | |
1493 s = c->data; | |
1494 | |
1495 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp auth state"); | |
1496 | |
1497 if (rev->timedout) { | |
1498 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); | |
1499 c->timedout = 1; | |
1500 ngx_mail_close_connection(c); | |
1501 return; | |
1502 } | |
1503 | |
1504 if (s->out.len) { | |
1505 ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp send handler busy"); | |
1506 s->blocked = 1; | |
1507 return; | |
1508 } | |
1509 | |
1510 s->blocked = 0; | |
1511 | |
1512 rc = ngx_mail_read_command(s); | |
1513 | |
1514 if (rc == NGX_AGAIN || rc == NGX_ERROR) { | |
1515 return; | |
1516 } | |
1517 | |
1518 text = NULL; | |
1519 size = 0; | |
1520 | |
1521 if (rc == NGX_OK) { | |
1522 switch (s->mail_state) { | |
1523 | |
1524 case ngx_smtp_start: | |
1525 | |
1526 switch (s->command) { | |
1527 | |
1528 case NGX_SMTP_HELO: | |
1529 case NGX_SMTP_EHLO: | |
1530 cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); | |
1531 | |
1532 if (s->args.nelts != 1) { | |
1533 text = smtp_invalid_argument; | |
1534 size = sizeof(smtp_invalid_argument) - 1; | |
1535 s->state = 0; | |
1536 break; | |
1537 } | |
1538 | |
1539 arg = s->args.elts; | |
1540 | |
1541 s->smtp_helo.len = arg[0].len; | |
1542 | |
1543 s->smtp_helo.data = ngx_palloc(c->pool, arg[0].len); | |
1544 if (s->smtp_helo.data == NULL) { | |
1545 ngx_mail_session_internal_server_error(s); | |
1546 return; | |
1547 } | |
1548 | |
1549 ngx_memcpy(s->smtp_helo.data, arg[0].data, arg[0].len); | |
1550 | |
1551 if (s->command == NGX_SMTP_HELO) { | |
1552 size = cscf->smtp_server_name.len; | |
1553 text = cscf->smtp_server_name.data; | |
1554 | |
1555 } else { | |
1556 s->esmtp = 1; | |
396
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1557 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1558 #if (NGX_MAIL_SSL) |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1559 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1560 if (c->ssl == NULL) { |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1561 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1562 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1563 if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) { |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1564 size = cscf->smtp_starttls_capability.len; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1565 text = cscf->smtp_starttls_capability.data; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1566 break; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1567 } |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1568 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1569 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1570 size = cscf->smtp_starttls_only_capability.len; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1571 text = cscf->smtp_starttls_only_capability.data; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1572 break; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1573 } |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1574 } |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1575 #endif |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1576 |
290 | 1577 size = cscf->smtp_capability.len; |
1578 text = cscf->smtp_capability.data; | |
1579 } | |
1580 | |
1581 break; | |
1582 | |
1583 case NGX_SMTP_AUTH: | |
1584 | |
396
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1585 #if (NGX_MAIL_SSL) |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1586 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1587 if (c->ssl == NULL) { |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1588 sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1589 |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1590 if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1591 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1592 break; |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1593 } |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1594 } |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1595 #endif |
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1596 |
290 | 1597 if (s->args.nelts == 0) { |
1598 text = smtp_invalid_argument; | |
1599 size = sizeof(smtp_invalid_argument) - 1; | |
1600 s->state = 0; | |
1601 break; | |
1602 } | |
1603 | |
1604 arg = s->args.elts; | |
1605 | |
1606 if (arg[0].len == 5) { | |
1607 | |
1608 if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) | |
1609 == 0) | |
1610 { | |
1611 | |
1612 if (s->args.nelts != 1) { | |
1613 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1614 break; | |
1615 } | |
1616 | |
1617 s->mail_state = ngx_smtp_auth_login_username; | |
1618 | |
1619 size = sizeof(smtp_username) - 1; | |
1620 text = smtp_username; | |
1621 | |
1622 break; | |
1623 | |
1624 } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", | |
1625 5) | |
1626 == 0) | |
1627 { | |
1628 if (s->args.nelts == 1) { | |
1629 s->mail_state = ngx_smtp_auth_plain; | |
1630 | |
1631 size = sizeof(smtp_next) - 1; | |
1632 text = smtp_next; | |
1633 | |
1634 break; | |
1635 } | |
1636 | |
1637 if (s->args.nelts == 2) { | |
1638 | |
1639 rc = ngx_mail_decode_auth_plain(s, &arg[1]); | |
1640 | |
1641 if (rc == NGX_OK) { | |
1642 ngx_mail_do_auth(s); | |
1643 return; | |
1644 } | |
1645 | |
1646 if (rc == NGX_ERROR) { | |
1647 ngx_mail_session_internal_server_error(s); | |
1648 return; | |
1649 } | |
1650 | |
1651 /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */ | |
1652 | |
1653 break; | |
1654 } | |
1655 | |
1656 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1657 break; | |
1658 } | |
1659 | |
1660 } else if (arg[0].len == 8 | |
1661 && ngx_strncasecmp(arg[0].data, | |
1662 (u_char *) "CRAM-MD5", 8) | |
1663 == 0) | |
1664 { | |
318 | 1665 cscf = ngx_mail_get_module_srv_conf(s, |
1666 ngx_mail_core_module); | |
1667 | |
1668 if (!(cscf->smtp_auth_methods | |
1669 & NGX_MAIL_AUTH_CRAM_MD5_ENABLED) | |
1670 || s->args.nelts != 1) | |
1671 { | |
290 | 1672 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
1673 break; | |
1674 } | |
1675 | |
1676 s->mail_state = ngx_smtp_auth_cram_md5; | |
1677 | |
1678 text = ngx_palloc(c->pool, | |
1679 sizeof("334 " CRLF) - 1 | |
1680 + ngx_base64_encoded_length(s->salt.len)); | |
1681 if (text == NULL) { | |
1682 ngx_mail_session_internal_server_error(s); | |
1683 return; | |
1684 } | |
1685 | |
1686 text[0] = '3'; text[1]= '3'; text[2] = '4'; text[3]= ' '; | |
1687 salt.data = &text[4]; | |
1688 s->salt.len -= 2; | |
1689 | |
1690 ngx_encode_base64(&salt, &s->salt); | |
1691 | |
1692 s->salt.len += 2; | |
1693 size = 4 + salt.len; | |
1694 text[size++] = CR; text[size++] = LF; | |
1695 | |
1696 break; | |
1697 } | |
1698 | |
1699 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1700 break; | |
1701 | |
1702 case NGX_SMTP_QUIT: | |
1703 s->quit = 1; | |
1704 text = smtp_bye; | |
1705 size = sizeof(smtp_bye) - 1; | |
1706 break; | |
1707 | |
1708 case NGX_SMTP_MAIL: | |
1709 | |
1710 if (s->connection->log->log_level >= NGX_LOG_INFO) { | |
296 | 1711 l.len = s->buffer->last - s->buffer->start; |
1712 l.data = s->buffer->start; | |
290 | 1713 |
296 | 1714 for (i = 0; i < l.len; i++) { |
1715 ch = l.data[i]; | |
290 | 1716 |
296 | 1717 if (ch != CR && ch != LF) { |
1718 continue; | |
1719 } | |
290 | 1720 |
296 | 1721 l.data[i] = ' '; |
1722 } | |
290 | 1723 |
296 | 1724 while (i) { |
1725 if (l.data[i - 1] != ' ') { | |
1726 break; | |
1727 } | |
290 | 1728 |
296 | 1729 i--; |
1730 } | |
290 | 1731 |
296 | 1732 l.len = i; |
290 | 1733 |
296 | 1734 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, |
1735 "client was rejected: \"%V\"", &l); | |
290 | 1736 } |
1737 | |
1738 text = smtp_auth_required; | |
1739 size = sizeof(smtp_auth_required) - 1; | |
1740 break; | |
1741 | |
1742 case NGX_SMTP_NOOP: | |
1743 case NGX_SMTP_RSET: | |
1744 text = smtp_ok; | |
1745 size = sizeof(smtp_ok) - 1; | |
1746 break; | |
394 | 1747 |
395
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1748 #if (NGX_MAIL_SSL) |
396
e2d916d7e50f
Mail: starttls only support for SMTP.
Maxim Dounin <mdounin@mdounin.ru>
parents:
395
diff
changeset
|
1749 |
395
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1750 case NGX_SMTP_STARTTLS: |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1751 if (c->ssl == NULL) { |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1752 sslcf = ngx_mail_get_module_srv_conf(s, |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1753 ngx_mail_ssl_module); |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1754 if (sslcf->starttls) { |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1755 c->read->handler = ngx_mail_starttls_handler; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1756 |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1757 /* |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1758 * RFC3207 requires us to discard any knowledge obtained |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1759 * from client before STARTTLS. |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1760 */ |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1761 |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1762 s->smtp_helo.len = 0; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1763 s->smtp_helo.data = NULL; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1764 |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1765 text = smtp_ok; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1766 size = sizeof(smtp_ok) - 1; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1767 |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1768 break; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1769 } |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1770 } |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1771 |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1772 rc = NGX_MAIL_PARSE_INVALID_COMMAND; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1773 break; |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1774 #endif |
1c0300c3ae88
Mail: SMTP STARTTLS support.
Maxim Dounin <mdounin@mdounin.ru>
parents:
394
diff
changeset
|
1775 |
394 | 1776 default: |
1777 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1778 break; | |
290 | 1779 } |
1780 | |
1781 break; | |
1782 | |
1783 case ngx_smtp_auth_login_username: | |
1784 arg = s->args.elts; | |
1785 s->mail_state = ngx_smtp_auth_login_password; | |
1786 | |
1787 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1788 "smtp auth login username: \"%V\"", &arg[0]); | |
1789 | |
1790 s->login.data = ngx_palloc(c->pool, | |
1791 ngx_base64_decoded_length(arg[0].len)); | |
1792 if (s->login.data == NULL){ | |
1793 ngx_mail_session_internal_server_error(s); | |
1794 return; | |
1795 } | |
1796 | |
1797 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
1798 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1799 "client sent invalid base64 encoding " | |
1800 "in AUTH LOGIN command"); | |
1801 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1802 break; | |
1803 } | |
1804 | |
1805 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1806 "smtp auth login username: \"%V\"", &s->login); | |
1807 | |
1808 size = sizeof(smtp_password) - 1; | |
1809 text = smtp_password; | |
1810 | |
1811 break; | |
1812 | |
1813 case ngx_smtp_auth_login_password: | |
1814 arg = s->args.elts; | |
1815 | |
1816 #if (NGX_DEBUG_MAIL_PASSWD) | |
1817 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1818 "smtp auth login password: \"%V\"", &arg[0]); | |
1819 #endif | |
1820 | |
1821 s->passwd.data = ngx_palloc(c->pool, | |
1822 ngx_base64_decoded_length(arg[0].len)); | |
1823 if (s->passwd.data == NULL){ | |
1824 ngx_mail_session_internal_server_error(s); | |
1825 return; | |
1826 } | |
1827 | |
1828 if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) { | |
1829 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1830 "client sent invalid base64 encoding " | |
1831 "in AUTH LOGIN command"); | |
1832 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1833 break; | |
1834 } | |
1835 | |
1836 #if (NGX_DEBUG_MAIL_PASSWD) | |
1837 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1838 "smtp auth login password: \"%V\"", &s->passwd); | |
1839 #endif | |
1840 | |
1841 ngx_mail_do_auth(s); | |
1842 return; | |
1843 | |
1844 case ngx_smtp_auth_plain: | |
1845 arg = s->args.elts; | |
1846 | |
1847 rc = ngx_mail_decode_auth_plain(s, &arg[0]); | |
1848 | |
1849 if (rc == NGX_OK) { | |
1850 ngx_mail_do_auth(s); | |
1851 return; | |
1852 } | |
1853 | |
1854 if (rc == NGX_ERROR) { | |
1855 ngx_mail_session_internal_server_error(s); | |
1856 return; | |
1857 } | |
1858 | |
1859 /* rc == NGX_MAIL_PARSE_INVALID_COMMAND */ | |
1860 | |
1861 break; | |
1862 | |
1863 case ngx_smtp_auth_cram_md5: | |
1864 arg = s->args.elts; | |
1865 | |
1866 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1867 "smtp auth cram-md5: \"%V\"", &arg[0]); | |
1868 | |
1869 s->login.data = ngx_palloc(c->pool, | |
1870 ngx_base64_decoded_length(arg[0].len)); | |
1871 if (s->login.data == NULL){ | |
1872 ngx_mail_session_internal_server_error(s); | |
1873 return; | |
1874 } | |
1875 | |
1876 if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) { | |
1877 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1878 "client sent invalid base64 encoding " | |
1879 "in AUTH CRAM-MD5 command"); | |
1880 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1881 break; | |
1882 } | |
1883 | |
1884 p = s->login.data; | |
1885 last = p + s->login.len; | |
1886 | |
1887 while (p < last) { | |
1888 if (*p++ == ' ') { | |
1889 s->login.len = p - s->login.data - 1; | |
1890 s->passwd.len = last - p; | |
1891 s->passwd.data = p; | |
1892 break; | |
1893 } | |
1894 } | |
1895 | |
1896 if (s->passwd.len != 32) { | |
1897 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
1898 "client sent invalid CRAM-MD5 hash " | |
1899 "in AUTH CRAM-MD5 command"); | |
1900 rc = NGX_MAIL_PARSE_INVALID_COMMAND; | |
1901 break; | |
1902 } | |
1903 | |
1904 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
1905 "smtp auth cram-md5: \"%V\" \"%V\"", | |
1906 &s->login, &s->passwd); | |
1907 | |
1908 s->auth_method = NGX_MAIL_AUTH_CRAM_MD5; | |
1909 | |
1910 ngx_mail_do_auth(s); | |
1911 return; | |
1912 } | |
1913 } | |
1914 | |
1915 if (rc == NGX_MAIL_PARSE_INVALID_COMMAND) { | |
1916 s->mail_state = ngx_smtp_start; | |
1917 s->state = 0; | |
1918 text = smtp_invalid_command; | |
1919 size = sizeof(smtp_invalid_command) - 1; | |
1920 } | |
1921 | |
1922 s->args.nelts = 0; | |
1923 s->buffer->pos = s->buffer->start; | |
1924 s->buffer->last = s->buffer->start; | |
1925 | |
1926 if (s->state) { | |
1927 s->arg_start = s->buffer->start; | |
1928 } | |
1929 | |
1930 s->out.data = text; | |
1931 s->out.len = size; | |
1932 | |
1933 ngx_mail_send(c->write); | |
1934 } | |
1935 | |
1936 | |
1937 static ngx_int_t | |
1938 ngx_mail_decode_auth_plain(ngx_mail_session_t *s, ngx_str_t *encoded) | |
1939 { | |
1940 u_char *p, *last; | |
1941 ngx_str_t plain; | |
1942 | |
1943 #if (NGX_DEBUG_MAIL_PASSWD) | |
1944 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, | |
1945 "mail auth plain: \"%V\"", encoded); | |
1946 #endif | |
1947 | |
1948 plain.data = ngx_palloc(s->connection->pool, | |
1949 ngx_base64_decoded_length(encoded->len)); | |
1950 if (plain.data == NULL){ | |
1951 return NGX_ERROR; | |
1952 } | |
1953 | |
1954 if (ngx_decode_base64(&plain, encoded) != NGX_OK) { | |
1955 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, | |
1956 "client sent invalid base64 encoding " | |
1957 "in AUTH PLAIN command"); | |
1958 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
1959 } | |
1960 | |
1961 p = plain.data; | |
1962 last = p + plain.len; | |
1963 | |
1964 while (p < last && *p++) { /* void */ } | |
1965 | |
1966 if (p == last) { | |
1967 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, | |
1968 "client sent invalid login in AUTH PLAIN command"); | |
1969 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
1970 } | |
1971 | |
1972 s->login.data = p; | |
1973 | |
1974 while (p < last && *p) { p++; } | |
1975 | |
1976 if (p == last) { | |
1977 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, | |
1978 "client sent invalid password in AUTH PLAIN command"); | |
1979 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
1980 } | |
1981 | |
1982 s->login.len = p++ - s->login.data; | |
1983 | |
1984 s->passwd.len = last - p; | |
1985 s->passwd.data = p; | |
1986 | |
1987 #if (NGX_DEBUG_MAIL_PASSWD) | |
1988 ngx_log_debug2(NGX_LOG_DEBUG_MAIL, s->connection->log, 0, | |
1989 "mail auth plain: \"%V\" \"%V\"", | |
1990 &s->login, &s->passwd); | |
1991 #endif | |
1992 | |
1993 return NGX_OK; | |
1994 } | |
1995 | |
1996 | |
1997 static void | |
1998 ngx_mail_do_auth(ngx_mail_session_t *s) | |
1999 { | |
2000 s->args.nelts = 0; | |
2001 s->buffer->pos = s->buffer->start; | |
2002 s->buffer->last = s->buffer->start; | |
2003 s->state = 0; | |
2004 | |
2005 if (s->connection->read->timer_set) { | |
2006 ngx_del_timer(s->connection->read); | |
2007 } | |
2008 | |
2009 s->login_attempt++; | |
2010 | |
2011 ngx_mail_auth_http_init(s); | |
2012 } | |
2013 | |
2014 | |
394 | 2015 ngx_int_t |
290 | 2016 ngx_mail_read_command(ngx_mail_session_t *s) |
2017 { | |
2018 ssize_t n; | |
2019 ngx_int_t rc; | |
2020 ngx_str_t l; | |
2021 | |
2022 n = s->connection->recv(s->connection, s->buffer->last, | |
2023 s->buffer->end - s->buffer->last); | |
2024 | |
2025 if (n == NGX_ERROR || n == 0) { | |
2026 ngx_mail_close_connection(s->connection); | |
2027 return NGX_ERROR; | |
2028 } | |
2029 | |
2030 if (n > 0) { | |
2031 s->buffer->last += n; | |
2032 } | |
2033 | |
2034 if (n == NGX_AGAIN) { | |
2035 if (ngx_handle_read_event(s->connection->read, 0) == NGX_ERROR) { | |
2036 ngx_mail_session_internal_server_error(s); | |
2037 return NGX_ERROR; | |
2038 } | |
2039 | |
2040 return NGX_AGAIN; | |
2041 } | |
2042 | |
2043 switch (s->protocol) { | |
2044 case NGX_MAIL_POP3_PROTOCOL: | |
2045 rc = ngx_pop3_parse_command(s); | |
2046 break; | |
2047 | |
2048 case NGX_MAIL_IMAP_PROTOCOL: | |
2049 rc = ngx_imap_parse_command(s); | |
2050 break; | |
2051 | |
2052 default: /* NGX_MAIL_SMTP_PROTOCOL */ | |
2053 rc = ngx_smtp_parse_command(s); | |
2054 break; | |
2055 } | |
2056 | |
2057 if (rc == NGX_AGAIN) { | |
2058 | |
2059 if (s->buffer->last < s->buffer->end) { | |
2060 return rc; | |
2061 } | |
2062 | |
2063 l.len = s->buffer->last - s->buffer->start; | |
2064 l.data = s->buffer->start; | |
2065 | |
2066 ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, | |
2067 "client sent too long command \"%V\"", &l); | |
2068 | |
2069 s->quit = 1; | |
2070 | |
2071 return NGX_MAIL_PARSE_INVALID_COMMAND; | |
2072 } | |
2073 | |
2074 if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) { | |
2075 return rc; | |
2076 } | |
2077 | |
2078 if (rc == NGX_ERROR) { | |
2079 ngx_mail_close_connection(s->connection); | |
2080 return NGX_ERROR; | |
2081 } | |
2082 | |
2083 return NGX_OK; | |
2084 } | |
2085 | |
2086 | |
2087 void | |
2088 ngx_mail_session_internal_server_error(ngx_mail_session_t *s) | |
2089 { | |
2090 s->out = internal_server_errors[s->protocol]; | |
2091 s->quit = 1; | |
2092 | |
2093 ngx_mail_send(s->connection->write); | |
2094 } | |
2095 | |
2096 | |
2097 void | |
2098 ngx_mail_close_connection(ngx_connection_t *c) | |
2099 { | |
2100 ngx_pool_t *pool; | |
2101 | |
2102 ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, | |
2103 "close mail connection: %d", c->fd); | |
2104 | |
2105 #if (NGX_MAIL_SSL) | |
2106 | |
2107 if (c->ssl) { | |
2108 if (ngx_ssl_shutdown(c) == NGX_AGAIN) { | |
2109 c->ssl->handler = ngx_mail_close_connection; | |
2110 return; | |
2111 } | |
2112 } | |
2113 | |
2114 #endif | |
2115 | |
2116 c->destroyed = 1; | |
2117 | |
2118 pool = c->pool; | |
2119 | |
2120 ngx_close_connection(c); | |
2121 | |
2122 ngx_destroy_pool(pool); | |
2123 } | |
2124 | |
2125 | |
2126 static u_char * | |
2127 ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len) | |
2128 { | |
2129 u_char *p; | |
2130 ngx_mail_session_t *s; | |
2131 ngx_mail_log_ctx_t *ctx; | |
2132 | |
2133 if (log->action) { | |
2134 p = ngx_snprintf(buf, len, " while %s", log->action); | |
2135 len -= p - buf; | |
2136 buf = p; | |
2137 } | |
2138 | |
2139 ctx = log->data; | |
2140 | |
2141 p = ngx_snprintf(buf, len, ", client: %V", ctx->client); | |
2142 len -= p - buf; | |
2143 buf = p; | |
2144 | |
2145 s = ctx->session; | |
2146 | |
2147 if (s == NULL) { | |
2148 return p; | |
2149 } | |
2150 | |
2151 p = ngx_snprintf(buf, len, ", server: %V", s->addr_text); | |
2152 len -= p - buf; | |
2153 buf = p; | |
2154 | |
2155 if (s->login.len == 0) { | |
2156 return p; | |
2157 } | |
2158 | |
2159 p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login); | |
2160 len -= p - buf; | |
2161 buf = p; | |
2162 | |
2163 if (s->proxy == NULL) { | |
2164 return p; | |
2165 } | |
2166 | |
2167 p = ngx_snprintf(buf, len, ", upstream: %V", s->proxy->upstream.name); | |
2168 | |
2169 return p; | |
2170 } |