Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_mail_pop3_handler.c
Go to the documentation of this file.
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) Nginx, Inc.
5  */
6 
7 
8 #include <ngx_config.h>
9 #include <ngx_core.h>
10 #include <ngx_event.h>
11 #include <ngx_mail.h>
12 #include <ngx_mail_pop3_module.h>
13 
14 
15 static ngx_int_t ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c);
16 static ngx_int_t ngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c);
17 static ngx_int_t ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c,
18  ngx_int_t stls);
19 static ngx_int_t ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c);
20 static ngx_int_t ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c);
21 static ngx_int_t ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c);
22 
23 
24 static u_char pop3_greeting[] = "+OK POP3 ready" CRLF;
25 static u_char pop3_ok[] = "+OK" CRLF;
26 static u_char pop3_next[] = "+ " CRLF;
27 static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF;
28 static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF;
29 static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF;
30 
31 
32 void
34 {
35  u_char *p;
38 
41 
42  if (pscf->auth_methods
44  {
45  if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
47  return;
48  }
49 
50  s->out.data = ngx_pnalloc(c->pool, sizeof(pop3_greeting) + s->salt.len);
51  if (s->out.data == NULL) {
53  return;
54  }
55 
56  p = ngx_cpymem(s->out.data, pop3_greeting, sizeof(pop3_greeting) - 3);
57  *p++ = ' ';
58  p = ngx_cpymem(p, s->salt.data, s->salt.len);
59 
60  s->out.len = p - s->out.data;
61 
62  } else {
63  ngx_str_set(&s->out, pop3_greeting);
64  }
65 
67 
68  ngx_add_timer(c->read, cscf->timeout);
69 
70  if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
72  }
73 
74  ngx_mail_send(c->write);
75 }
76 
77 
78 void
80 {
83 
84  c = rev->data;
85 
86  c->log->action = "in auth state";
87 
88  if (rev->timedout) {
89  ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
90  c->timedout = 1;
92  return;
93  }
94 
95  s = c->data;
96 
97  if (s->buffer == NULL) {
98  if (ngx_array_init(&s->args, c->pool, 2, sizeof(ngx_str_t))
99  == NGX_ERROR)
100  {
102  return;
103  }
104 
105  s->buffer = ngx_create_temp_buf(c->pool, 128);
106  if (s->buffer == NULL) {
108  return;
109  }
110  }
111 
114 
116 }
117 
118 
119 void
121 {
122  ngx_int_t rc;
123  ngx_connection_t *c;
125 
126  c = rev->data;
127  s = c->data;
128 
129  ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 auth state");
130 
131  if (rev->timedout) {
132  ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
133  c->timedout = 1;
135  return;
136  }
137 
138  if (s->out.len) {
139  ngx_log_debug0(NGX_LOG_DEBUG_MAIL, c->log, 0, "pop3 send handler busy");
140  s->blocked = 1;
141  return;
142  }
143 
144  s->blocked = 0;
145 
146  rc = ngx_mail_read_command(s, c);
147 
148  if (rc == NGX_AGAIN || rc == NGX_ERROR) {
149  return;
150  }
151 
152  ngx_str_set(&s->out, pop3_ok);
153 
154  if (rc == NGX_OK) {
155  switch (s->mail_state) {
156 
157  case ngx_pop3_start:
158 
159  switch (s->command) {
160 
161  case NGX_POP3_USER:
162  rc = ngx_mail_pop3_user(s, c);
163  break;
164 
165  case NGX_POP3_CAPA:
166  rc = ngx_mail_pop3_capa(s, c, 1);
167  break;
168 
169  case NGX_POP3_APOP:
170  rc = ngx_mail_pop3_apop(s, c);
171  break;
172 
173  case NGX_POP3_AUTH:
174  rc = ngx_mail_pop3_auth(s, c);
175  break;
176 
177  case NGX_POP3_QUIT:
178  s->quit = 1;
179  break;
180 
181  case NGX_POP3_NOOP:
182  break;
183 
184  case NGX_POP3_STLS:
185  rc = ngx_mail_pop3_stls(s, c);
186  break;
187 
188  default:
190  break;
191  }
192 
193  break;
194 
195  case ngx_pop3_user:
196 
197  switch (s->command) {
198 
199  case NGX_POP3_PASS:
200  rc = ngx_mail_pop3_pass(s, c);
201  break;
202 
203  case NGX_POP3_CAPA:
204  rc = ngx_mail_pop3_capa(s, c, 0);
205  break;
206 
207  case NGX_POP3_QUIT:
208  s->quit = 1;
209  break;
210 
211  case NGX_POP3_NOOP:
212  break;
213 
214  default:
216  break;
217  }
218 
219  break;
220 
221  /* suppress warnings */
222  case ngx_pop3_passwd:
223  break;
224 
226  rc = ngx_mail_auth_login_username(s, c, 0);
227 
228  ngx_str_set(&s->out, pop3_password);
230  break;
231 
233  rc = ngx_mail_auth_login_password(s, c);
234  break;
235 
236  case ngx_pop3_auth_plain:
237  rc = ngx_mail_auth_plain(s, c, 0);
238  break;
239 
241  rc = ngx_mail_auth_cram_md5(s, c);
242  break;
243  }
244  }
245 
246  switch (rc) {
247 
248  case NGX_DONE:
249  ngx_mail_auth(s, c);
250  return;
251 
252  case NGX_ERROR:
254  return;
255 
258  s->state = 0;
259 
260  ngx_str_set(&s->out, pop3_invalid_command);
261 
262  /* fall through */
263 
264  case NGX_OK:
265 
266  s->args.nelts = 0;
267  s->buffer->pos = s->buffer->start;
268  s->buffer->last = s->buffer->start;
269 
270  if (s->state) {
271  s->arg_start = s->buffer->start;
272  }
273 
274  ngx_mail_send(c->write);
275  }
276 }
277 
278 static ngx_int_t
279 ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c)
280 {
281  ngx_str_t *arg;
282 
283 #if (NGX_MAIL_SSL)
284  if (ngx_mail_starttls_only(s, c)) {
286  }
287 #endif
288 
289  if (s->args.nelts != 1) {
291  }
292 
293  arg = s->args.elts;
294  s->login.len = arg[0].len;
295  s->login.data = ngx_pnalloc(c->pool, s->login.len);
296  if (s->login.data == NULL) {
297  return NGX_ERROR;
298  }
299 
300  ngx_memcpy(s->login.data, arg[0].data, s->login.len);
301 
303  "pop3 login: \"%V\"", &s->login);
304 
306 
307  return NGX_OK;
308 }
309 
310 
311 static ngx_int_t
312 ngx_mail_pop3_pass(ngx_mail_session_t *s, ngx_connection_t *c)
313 {
314  ngx_str_t *arg;
315 
316  if (s->args.nelts != 1) {
318  }
319 
320  arg = s->args.elts;
321  s->passwd.len = arg[0].len;
322  s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len);
323  if (s->passwd.data == NULL) {
324  return NGX_ERROR;
325  }
326 
327  ngx_memcpy(s->passwd.data, arg[0].data, s->passwd.len);
328 
329 #if (NGX_DEBUG_MAIL_PASSWD)
331  "pop3 passwd: \"%V\"", &s->passwd);
332 #endif
333 
334  return NGX_DONE;
335 }
336 
337 
338 static ngx_int_t
339 ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, ngx_int_t stls)
340 {
342 
344 
345 #if (NGX_MAIL_SSL)
346 
347  if (stls && c->ssl == NULL) {
348  ngx_mail_ssl_conf_t *sslcf;
349 
351 
352  if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
353  s->out = pscf->starttls_capability;
354  return NGX_OK;
355  }
356 
357  if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
358  s->out = pscf->starttls_only_capability;
359  return NGX_OK;
360  }
361  }
362 
363 #endif
364 
365  s->out = pscf->capability;
366  return NGX_OK;
367 }
368 
369 
370 static ngx_int_t
371 ngx_mail_pop3_stls(ngx_mail_session_t *s, ngx_connection_t *c)
372 {
373 #if (NGX_MAIL_SSL)
374  ngx_mail_ssl_conf_t *sslcf;
375 
376  if (c->ssl == NULL) {
378  if (sslcf->starttls) {
379  c->read->handler = ngx_mail_starttls_handler;
380  return NGX_OK;
381  }
382  }
383 
384 #endif
385 
387 }
388 
389 
390 static ngx_int_t
391 ngx_mail_pop3_apop(ngx_mail_session_t *s, ngx_connection_t *c)
392 {
393  ngx_str_t *arg;
395 
396 #if (NGX_MAIL_SSL)
397  if (ngx_mail_starttls_only(s, c)) {
399  }
400 #endif
401 
402  if (s->args.nelts != 2) {
404  }
405 
407 
408  if (!(pscf->auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) {
410  }
411 
412  arg = s->args.elts;
413 
414  s->login.len = arg[0].len;
415  s->login.data = ngx_pnalloc(c->pool, s->login.len);
416  if (s->login.data == NULL) {
417  return NGX_ERROR;
418  }
419 
420  ngx_memcpy(s->login.data, arg[0].data, s->login.len);
421 
422  s->passwd.len = arg[1].len;
423  s->passwd.data = ngx_pnalloc(c->pool, s->passwd.len);
424  if (s->passwd.data == NULL) {
425  return NGX_ERROR;
426  }
427 
428  ngx_memcpy(s->passwd.data, arg[1].data, s->passwd.len);
429 
431  "pop3 apop: \"%V\" \"%V\"", &s->login, &s->passwd);
432 
434 
435  return NGX_DONE;
436 }
437 
438 
439 static ngx_int_t
440 ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c)
441 {
442  ngx_int_t rc;
444 
445 #if (NGX_MAIL_SSL)
446  if (ngx_mail_starttls_only(s, c)) {
448  }
449 #endif
450 
452 
453  if (s->args.nelts == 0) {
454  s->out = pscf->auth_capability;
455  s->state = 0;
456 
457  return NGX_OK;
458  }
459 
460  rc = ngx_mail_auth_parse(s, c);
461 
462  switch (rc) {
463 
464  case NGX_MAIL_AUTH_LOGIN:
465 
466  ngx_str_set(&s->out, pop3_username);
468 
469  return NGX_OK;
470 
472 
473  ngx_str_set(&s->out, pop3_password);
475 
476  return ngx_mail_auth_login_username(s, c, 1);
477 
478  case NGX_MAIL_AUTH_PLAIN:
479 
480  ngx_str_set(&s->out, pop3_next);
482 
483  return NGX_OK;
484 
486 
489  }
490 
491  if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
493  return NGX_OK;
494  }
495 
496  return NGX_ERROR;
497  }
498 
499  return rc;
500 }