Annotation of embedaddon/nginx/src/mail/ngx_mail_pop3_handler.c, revision 1.1.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>