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>