Annotation of embedaddon/nginx/src/mail/ngx_mail_pop3_handler.c, revision 1.1
1.1 ! misho 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
! 33: ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c)
! 34: {
! 35: u_char *p;
! 36: ngx_mail_core_srv_conf_t *cscf;
! 37: ngx_mail_pop3_srv_conf_t *pscf;
! 38:
! 39: pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
! 40: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
! 41:
! 42: if (pscf->auth_methods
! 43: & (NGX_MAIL_AUTH_APOP_ENABLED|NGX_MAIL_AUTH_CRAM_MD5_ENABLED))
! 44: {
! 45: if (ngx_mail_salt(s, c, cscf) != NGX_OK) {
! 46: ngx_mail_session_internal_server_error(s);
! 47: return;
! 48: }
! 49:
! 50: s->out.data = ngx_pnalloc(c->pool, sizeof(pop3_greeting) + s->salt.len);
! 51: if (s->out.data == NULL) {
! 52: ngx_mail_session_internal_server_error(s);
! 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:
! 66: c->read->handler = ngx_mail_pop3_init_protocol;
! 67:
! 68: ngx_add_timer(c->read, cscf->timeout);
! 69:
! 70: if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
! 71: ngx_mail_close_connection(c);
! 72: }
! 73:
! 74: ngx_mail_send(c->write);
! 75: }
! 76:
! 77:
! 78: void
! 79: ngx_mail_pop3_init_protocol(ngx_event_t *rev)
! 80: {
! 81: ngx_connection_t *c;
! 82: ngx_mail_session_t *s;
! 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;
! 91: ngx_mail_close_connection(c);
! 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: {
! 101: ngx_mail_session_internal_server_error(s);
! 102: return;
! 103: }
! 104:
! 105: s->buffer = ngx_create_temp_buf(c->pool, 128);
! 106: if (s->buffer == NULL) {
! 107: ngx_mail_session_internal_server_error(s);
! 108: return;
! 109: }
! 110: }
! 111:
! 112: s->mail_state = ngx_pop3_start;
! 113: c->read->handler = ngx_mail_pop3_auth_state;
! 114:
! 115: ngx_mail_pop3_auth_state(rev);
! 116: }
! 117:
! 118:
! 119: void
! 120: ngx_mail_pop3_auth_state(ngx_event_t *rev)
! 121: {
! 122: ngx_int_t rc;
! 123: ngx_connection_t *c;
! 124: ngx_mail_session_t *s;
! 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;
! 134: ngx_mail_close_connection(c);
! 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:
! 189: rc = NGX_MAIL_PARSE_INVALID_COMMAND;
! 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:
! 215: rc = NGX_MAIL_PARSE_INVALID_COMMAND;
! 216: break;
! 217: }
! 218:
! 219: break;
! 220:
! 221: /* suppress warnings */
! 222: case ngx_pop3_passwd:
! 223: break;
! 224:
! 225: case ngx_pop3_auth_login_username:
! 226: rc = ngx_mail_auth_login_username(s, c, 0);
! 227:
! 228: ngx_str_set(&s->out, pop3_password);
! 229: s->mail_state = ngx_pop3_auth_login_password;
! 230: break;
! 231:
! 232: case ngx_pop3_auth_login_password:
! 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:
! 240: case ngx_pop3_auth_cram_md5:
! 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:
! 253: ngx_mail_session_internal_server_error(s);
! 254: return;
! 255:
! 256: case NGX_MAIL_PARSE_INVALID_COMMAND:
! 257: s->mail_state = ngx_pop3_start;
! 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)) {
! 285: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 286: }
! 287: #endif
! 288:
! 289: if (s->args.nelts != 1) {
! 290: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 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:
! 302: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
! 303: "pop3 login: \"%V\"", &s->login);
! 304:
! 305: s->mail_state = ngx_pop3_user;
! 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) {
! 317: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 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)
! 330: ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
! 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: {
! 341: ngx_mail_pop3_srv_conf_t *pscf;
! 342:
! 343: pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
! 344:
! 345: #if (NGX_MAIL_SSL)
! 346:
! 347: if (stls && c->ssl == NULL) {
! 348: ngx_mail_ssl_conf_t *sslcf;
! 349:
! 350: sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
! 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) {
! 377: sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
! 378: if (sslcf->starttls) {
! 379: c->read->handler = ngx_mail_starttls_handler;
! 380: return NGX_OK;
! 381: }
! 382: }
! 383:
! 384: #endif
! 385:
! 386: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 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;
! 394: ngx_mail_pop3_srv_conf_t *pscf;
! 395:
! 396: #if (NGX_MAIL_SSL)
! 397: if (ngx_mail_starttls_only(s, c)) {
! 398: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 399: }
! 400: #endif
! 401:
! 402: if (s->args.nelts != 2) {
! 403: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 404: }
! 405:
! 406: pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
! 407:
! 408: if (!(pscf->auth_methods & NGX_MAIL_AUTH_APOP_ENABLED)) {
! 409: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 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:
! 430: ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
! 431: "pop3 apop: \"%V\" \"%V\"", &s->login, &s->passwd);
! 432:
! 433: s->auth_method = NGX_MAIL_AUTH_APOP;
! 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;
! 443: ngx_mail_pop3_srv_conf_t *pscf;
! 444:
! 445: #if (NGX_MAIL_SSL)
! 446: if (ngx_mail_starttls_only(s, c)) {
! 447: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 448: }
! 449: #endif
! 450:
! 451: pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
! 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);
! 467: s->mail_state = ngx_pop3_auth_login_username;
! 468:
! 469: return NGX_OK;
! 470:
! 471: case NGX_MAIL_AUTH_LOGIN_USERNAME:
! 472:
! 473: ngx_str_set(&s->out, pop3_password);
! 474: s->mail_state = ngx_pop3_auth_login_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);
! 481: s->mail_state = ngx_pop3_auth_plain;
! 482:
! 483: return NGX_OK;
! 484:
! 485: case NGX_MAIL_AUTH_CRAM_MD5:
! 486:
! 487: if (!(pscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) {
! 488: return NGX_MAIL_PARSE_INVALID_COMMAND;
! 489: }
! 490:
! 491: if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) {
! 492: s->mail_state = ngx_pop3_auth_cram_md5;
! 493: return NGX_OK;
! 494: }
! 495:
! 496: return NGX_ERROR;
! 497: }
! 498:
! 499: return rc;
! 500: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>