Annotation of embedaddon/nginx/src/mail/ngx_mail_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: 
        !            13: 
        !            14: static void ngx_mail_init_session(ngx_connection_t *c);
        !            15: 
        !            16: #if (NGX_MAIL_SSL)
        !            17: static void ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c);
        !            18: static void ngx_mail_ssl_handshake_handler(ngx_connection_t *c);
        !            19: #endif
        !            20: 
        !            21: 
        !            22: void
        !            23: ngx_mail_init_connection(ngx_connection_t *c)
        !            24: {
        !            25:     ngx_uint_t             i;
        !            26:     ngx_mail_port_t       *port;
        !            27:     struct sockaddr       *sa;
        !            28:     struct sockaddr_in    *sin;
        !            29:     ngx_mail_log_ctx_t    *ctx;
        !            30:     ngx_mail_in_addr_t    *addr;
        !            31:     ngx_mail_session_t    *s;
        !            32:     ngx_mail_addr_conf_t  *addr_conf;
        !            33: #if (NGX_HAVE_INET6)
        !            34:     struct sockaddr_in6   *sin6;
        !            35:     ngx_mail_in6_addr_t   *addr6;
        !            36: #endif
        !            37: 
        !            38: 
        !            39:     /* find the server configuration for the address:port */
        !            40: 
        !            41:     port = c->listening->servers;
        !            42: 
        !            43:     if (port->naddrs > 1) {
        !            44: 
        !            45:         /*
        !            46:          * There are several addresses on this port and one of them
        !            47:          * is the "*:port" wildcard so getsockname() is needed to determine
        !            48:          * the server address.
        !            49:          *
        !            50:          * AcceptEx() already gave this address.
        !            51:          */
        !            52: 
        !            53:         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
        !            54:             ngx_mail_close_connection(c);
        !            55:             return;
        !            56:         }
        !            57: 
        !            58:         sa = c->local_sockaddr;
        !            59: 
        !            60:         switch (sa->sa_family) {
        !            61: 
        !            62: #if (NGX_HAVE_INET6)
        !            63:         case AF_INET6:
        !            64:             sin6 = (struct sockaddr_in6 *) sa;
        !            65: 
        !            66:             addr6 = port->addrs;
        !            67: 
        !            68:             /* the last address is "*" */
        !            69: 
        !            70:             for (i = 0; i < port->naddrs - 1; i++) {
        !            71:                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
        !            72:                     break;
        !            73:                 }
        !            74:             }
        !            75: 
        !            76:             addr_conf = &addr6[i].conf;
        !            77: 
        !            78:             break;
        !            79: #endif
        !            80: 
        !            81:         default: /* AF_INET */
        !            82:             sin = (struct sockaddr_in *) sa;
        !            83: 
        !            84:             addr = port->addrs;
        !            85: 
        !            86:             /* the last address is "*" */
        !            87: 
        !            88:             for (i = 0; i < port->naddrs - 1; i++) {
        !            89:                 if (addr[i].addr == sin->sin_addr.s_addr) {
        !            90:                     break;
        !            91:                 }
        !            92:             }
        !            93: 
        !            94:             addr_conf = &addr[i].conf;
        !            95: 
        !            96:             break;
        !            97:         }
        !            98: 
        !            99:     } else {
        !           100:         switch (c->local_sockaddr->sa_family) {
        !           101: 
        !           102: #if (NGX_HAVE_INET6)
        !           103:         case AF_INET6:
        !           104:             addr6 = port->addrs;
        !           105:             addr_conf = &addr6[0].conf;
        !           106:             break;
        !           107: #endif
        !           108: 
        !           109:         default: /* AF_INET */
        !           110:             addr = port->addrs;
        !           111:             addr_conf = &addr[0].conf;
        !           112:             break;
        !           113:         }
        !           114:     }
        !           115: 
        !           116:     s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t));
        !           117:     if (s == NULL) {
        !           118:         ngx_mail_close_connection(c);
        !           119:         return;
        !           120:     }
        !           121: 
        !           122:     s->main_conf = addr_conf->ctx->main_conf;
        !           123:     s->srv_conf = addr_conf->ctx->srv_conf;
        !           124: 
        !           125:     s->addr_text = &addr_conf->addr_text;
        !           126: 
        !           127:     c->data = s;
        !           128:     s->connection = c;
        !           129: 
        !           130:     ngx_log_error(NGX_LOG_INFO, c->log, 0, "*%ui client %V connected to %V",
        !           131:                   c->number, &c->addr_text, s->addr_text);
        !           132: 
        !           133:     ctx = ngx_palloc(c->pool, sizeof(ngx_mail_log_ctx_t));
        !           134:     if (ctx == NULL) {
        !           135:         ngx_mail_close_connection(c);
        !           136:         return;
        !           137:     }
        !           138: 
        !           139:     ctx->client = &c->addr_text;
        !           140:     ctx->session = s;
        !           141: 
        !           142:     c->log->connection = c->number;
        !           143:     c->log->handler = ngx_mail_log_error;
        !           144:     c->log->data = ctx;
        !           145:     c->log->action = "sending client greeting line";
        !           146: 
        !           147:     c->log_error = NGX_ERROR_INFO;
        !           148: 
        !           149: #if (NGX_MAIL_SSL)
        !           150:     {
        !           151:     ngx_mail_ssl_conf_t  *sslcf;
        !           152: 
        !           153:     sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
        !           154: 
        !           155:     if (sslcf->enable) {
        !           156:         c->log->action = "SSL handshaking";
        !           157: 
        !           158:         ngx_mail_ssl_init_connection(&sslcf->ssl, c);
        !           159:         return;
        !           160:     }
        !           161: 
        !           162:     if (addr_conf->ssl) {
        !           163: 
        !           164:         c->log->action = "SSL handshaking";
        !           165: 
        !           166:         if (sslcf->ssl.ctx == NULL) {
        !           167:             ngx_log_error(NGX_LOG_ERR, c->log, 0,
        !           168:                           "no \"ssl_certificate\" is defined "
        !           169:                           "in server listening on SSL port");
        !           170:             ngx_mail_close_connection(c);
        !           171:             return;
        !           172:         }
        !           173: 
        !           174:         ngx_mail_ssl_init_connection(&sslcf->ssl, c);
        !           175:         return;
        !           176:     }
        !           177: 
        !           178:     }
        !           179: #endif
        !           180: 
        !           181:     ngx_mail_init_session(c);
        !           182: }
        !           183: 
        !           184: 
        !           185: #if (NGX_MAIL_SSL)
        !           186: 
        !           187: void
        !           188: ngx_mail_starttls_handler(ngx_event_t *rev)
        !           189: {
        !           190:     ngx_connection_t     *c;
        !           191:     ngx_mail_session_t   *s;
        !           192:     ngx_mail_ssl_conf_t  *sslcf;
        !           193: 
        !           194:     c = rev->data;
        !           195:     s = c->data;
        !           196:     s->starttls = 1;
        !           197: 
        !           198:     c->log->action = "in starttls state";
        !           199: 
        !           200:     sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
        !           201: 
        !           202:     ngx_mail_ssl_init_connection(&sslcf->ssl, c);
        !           203: }
        !           204: 
        !           205: 
        !           206: static void
        !           207: ngx_mail_ssl_init_connection(ngx_ssl_t *ssl, ngx_connection_t *c)
        !           208: {
        !           209:     ngx_mail_session_t        *s;
        !           210:     ngx_mail_core_srv_conf_t  *cscf;
        !           211: 
        !           212:     if (ngx_ssl_create_connection(ssl, c, 0) == NGX_ERROR) {
        !           213:         ngx_mail_close_connection(c);
        !           214:         return;
        !           215:     }
        !           216: 
        !           217:     if (ngx_ssl_handshake(c) == NGX_AGAIN) {
        !           218: 
        !           219:         s = c->data;
        !           220: 
        !           221:         cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           222: 
        !           223:         ngx_add_timer(c->read, cscf->timeout);
        !           224: 
        !           225:         c->ssl->handler = ngx_mail_ssl_handshake_handler;
        !           226: 
        !           227:         return;
        !           228:     }
        !           229: 
        !           230:     ngx_mail_ssl_handshake_handler(c);
        !           231: }
        !           232: 
        !           233: 
        !           234: static void
        !           235: ngx_mail_ssl_handshake_handler(ngx_connection_t *c)
        !           236: {
        !           237:     ngx_mail_session_t        *s;
        !           238:     ngx_mail_core_srv_conf_t  *cscf;
        !           239: 
        !           240:     if (c->ssl->handshaked) {
        !           241: 
        !           242:         s = c->data;
        !           243: 
        !           244:         if (s->starttls) {
        !           245:             cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           246: 
        !           247:             c->read->handler = cscf->protocol->init_protocol;
        !           248:             c->write->handler = ngx_mail_send;
        !           249: 
        !           250:             cscf->protocol->init_protocol(c->read);
        !           251: 
        !           252:             return;
        !           253:         }
        !           254: 
        !           255:         c->read->ready = 0;
        !           256: 
        !           257:         ngx_mail_init_session(c);
        !           258:         return;
        !           259:     }
        !           260: 
        !           261:     ngx_mail_close_connection(c);
        !           262: }
        !           263: 
        !           264: #endif
        !           265: 
        !           266: 
        !           267: static void
        !           268: ngx_mail_init_session(ngx_connection_t *c)
        !           269: {
        !           270:     ngx_mail_session_t        *s;
        !           271:     ngx_mail_core_srv_conf_t  *cscf;
        !           272: 
        !           273:     s = c->data;
        !           274: 
        !           275:     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           276: 
        !           277:     s->protocol = cscf->protocol->type;
        !           278: 
        !           279:     s->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_mail_max_module);
        !           280:     if (s->ctx == NULL) {
        !           281:         ngx_mail_session_internal_server_error(s);
        !           282:         return;
        !           283:     }
        !           284: 
        !           285:     c->write->handler = ngx_mail_send;
        !           286: 
        !           287:     cscf->protocol->init_session(s, c);
        !           288: }
        !           289: 
        !           290: 
        !           291: ngx_int_t
        !           292: ngx_mail_salt(ngx_mail_session_t *s, ngx_connection_t *c,
        !           293:     ngx_mail_core_srv_conf_t *cscf)
        !           294: {
        !           295:     s->salt.data = ngx_pnalloc(c->pool,
        !           296:                                sizeof(" <18446744073709551616.@>" CRLF) - 1
        !           297:                                + NGX_TIME_T_LEN
        !           298:                                + cscf->server_name.len);
        !           299:     if (s->salt.data == NULL) {
        !           300:         return NGX_ERROR;
        !           301:     }
        !           302: 
        !           303:     s->salt.len = ngx_sprintf(s->salt.data, "<%ul.%T@%V>" CRLF,
        !           304:                               ngx_random(), ngx_time(), &cscf->server_name)
        !           305:                   - s->salt.data;
        !           306: 
        !           307:     return NGX_OK;
        !           308: }
        !           309: 
        !           310: 
        !           311: #if (NGX_MAIL_SSL)
        !           312: 
        !           313: ngx_int_t
        !           314: ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c)
        !           315: {
        !           316:     ngx_mail_ssl_conf_t  *sslcf;
        !           317: 
        !           318:     if (c->ssl) {
        !           319:         return 0;
        !           320:     }
        !           321: 
        !           322:     sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
        !           323: 
        !           324:     if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) {
        !           325:         return 1;
        !           326:     }
        !           327: 
        !           328:     return 0;
        !           329: }
        !           330: 
        !           331: #endif
        !           332: 
        !           333: 
        !           334: ngx_int_t
        !           335: ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n)
        !           336: {
        !           337:     u_char     *p, *last;
        !           338:     ngx_str_t  *arg, plain;
        !           339: 
        !           340:     arg = s->args.elts;
        !           341: 
        !           342: #if (NGX_DEBUG_MAIL_PASSWD)
        !           343:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           344:                    "mail auth plain: \"%V\"", &arg[n]);
        !           345: #endif
        !           346: 
        !           347:     plain.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
        !           348:     if (plain.data == NULL) {
        !           349:         return NGX_ERROR;
        !           350:     }
        !           351: 
        !           352:     if (ngx_decode_base64(&plain, &arg[n]) != NGX_OK) {
        !           353:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           354:             "client sent invalid base64 encoding in AUTH PLAIN command");
        !           355:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           356:     }
        !           357: 
        !           358:     p = plain.data;
        !           359:     last = p + plain.len;
        !           360: 
        !           361:     while (p < last && *p++) { /* void */ }
        !           362: 
        !           363:     if (p == last) {
        !           364:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           365:                       "client sent invalid login in AUTH PLAIN command");
        !           366:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           367:     }
        !           368: 
        !           369:     s->login.data = p;
        !           370: 
        !           371:     while (p < last && *p) { p++; }
        !           372: 
        !           373:     if (p == last) {
        !           374:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           375:                       "client sent invalid password in AUTH PLAIN command");
        !           376:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           377:     }
        !           378: 
        !           379:     s->login.len = p++ - s->login.data;
        !           380: 
        !           381:     s->passwd.len = last - p;
        !           382:     s->passwd.data = p;
        !           383: 
        !           384: #if (NGX_DEBUG_MAIL_PASSWD)
        !           385:     ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           386:                    "mail auth plain: \"%V\" \"%V\"", &s->login, &s->passwd);
        !           387: #endif
        !           388: 
        !           389:     return NGX_DONE;
        !           390: }
        !           391: 
        !           392: 
        !           393: ngx_int_t
        !           394: ngx_mail_auth_login_username(ngx_mail_session_t *s, ngx_connection_t *c,
        !           395:     ngx_uint_t n)
        !           396: {
        !           397:     ngx_str_t  *arg;
        !           398: 
        !           399:     arg = s->args.elts;
        !           400: 
        !           401:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           402:                    "mail auth login username: \"%V\"", &arg[n]);
        !           403: 
        !           404:     s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[n].len));
        !           405:     if (s->login.data == NULL) {
        !           406:         return NGX_ERROR;
        !           407:     }
        !           408: 
        !           409:     if (ngx_decode_base64(&s->login, &arg[n]) != NGX_OK) {
        !           410:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           411:             "client sent invalid base64 encoding in AUTH LOGIN command");
        !           412:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           413:     }
        !           414: 
        !           415:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           416:                    "mail auth login username: \"%V\"", &s->login);
        !           417: 
        !           418:     return NGX_OK;
        !           419: }
        !           420: 
        !           421: 
        !           422: ngx_int_t
        !           423: ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c)
        !           424: {
        !           425:     ngx_str_t  *arg;
        !           426: 
        !           427:     arg = s->args.elts;
        !           428: 
        !           429: #if (NGX_DEBUG_MAIL_PASSWD)
        !           430:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           431:                    "mail auth login password: \"%V\"", &arg[0]);
        !           432: #endif
        !           433: 
        !           434:     s->passwd.data = ngx_pnalloc(c->pool,
        !           435:                                  ngx_base64_decoded_length(arg[0].len));
        !           436:     if (s->passwd.data == NULL) {
        !           437:         return NGX_ERROR;
        !           438:     }
        !           439: 
        !           440:     if (ngx_decode_base64(&s->passwd, &arg[0]) != NGX_OK) {
        !           441:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           442:             "client sent invalid base64 encoding in AUTH LOGIN command");
        !           443:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           444:     }
        !           445: 
        !           446: #if (NGX_DEBUG_MAIL_PASSWD)
        !           447:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           448:                    "mail auth login password: \"%V\"", &s->passwd);
        !           449: #endif
        !           450: 
        !           451:     return NGX_DONE;
        !           452: }
        !           453: 
        !           454: 
        !           455: ngx_int_t
        !           456: ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c,
        !           457:     char *prefix, size_t len)
        !           458: {
        !           459:     u_char      *p;
        !           460:     ngx_str_t    salt;
        !           461:     ngx_uint_t   n;
        !           462: 
        !           463:     p = ngx_pnalloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2);
        !           464:     if (p == NULL) {
        !           465:         return NGX_ERROR;
        !           466:     }
        !           467: 
        !           468:     salt.data = ngx_cpymem(p, prefix, len);
        !           469:     s->salt.len -= 2;
        !           470: 
        !           471:     ngx_encode_base64(&salt, &s->salt);
        !           472: 
        !           473:     s->salt.len += 2;
        !           474:     n = len + salt.len;
        !           475:     p[n++] = CR; p[n++] = LF;
        !           476: 
        !           477:     s->out.len = n;
        !           478:     s->out.data = p;
        !           479: 
        !           480:     return NGX_OK;
        !           481: }
        !           482: 
        !           483: 
        !           484: ngx_int_t
        !           485: ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c)
        !           486: {
        !           487:     u_char     *p, *last;
        !           488:     ngx_str_t  *arg;
        !           489: 
        !           490:     arg = s->args.elts;
        !           491: 
        !           492:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           493:                    "mail auth cram-md5: \"%V\"", &arg[0]);
        !           494: 
        !           495:     s->login.data = ngx_pnalloc(c->pool, ngx_base64_decoded_length(arg[0].len));
        !           496:     if (s->login.data == NULL) {
        !           497:         return NGX_ERROR;
        !           498:     }
        !           499: 
        !           500:     if (ngx_decode_base64(&s->login, &arg[0]) != NGX_OK) {
        !           501:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           502:             "client sent invalid base64 encoding in AUTH CRAM-MD5 command");
        !           503:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           504:     }
        !           505: 
        !           506:     p = s->login.data;
        !           507:     last = p + s->login.len;
        !           508: 
        !           509:     while (p < last) {
        !           510:         if (*p++ == ' ') {
        !           511:             s->login.len = p - s->login.data - 1;
        !           512:             s->passwd.len = last - p;
        !           513:             s->passwd.data = p;
        !           514:             break;
        !           515:         }
        !           516:     }
        !           517: 
        !           518:     if (s->passwd.len != 32) {
        !           519:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           520:             "client sent invalid CRAM-MD5 hash in AUTH CRAM-MD5 command");
        !           521:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           522:     }
        !           523: 
        !           524:     ngx_log_debug2(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           525:                    "mail auth cram-md5: \"%V\" \"%V\"", &s->login, &s->passwd);
        !           526: 
        !           527:     s->auth_method = NGX_MAIL_AUTH_CRAM_MD5;
        !           528: 
        !           529:     return NGX_DONE;
        !           530: }
        !           531: 
        !           532: 
        !           533: void
        !           534: ngx_mail_send(ngx_event_t *wev)
        !           535: {
        !           536:     ngx_int_t                  n;
        !           537:     ngx_connection_t          *c;
        !           538:     ngx_mail_session_t        *s;
        !           539:     ngx_mail_core_srv_conf_t  *cscf;
        !           540: 
        !           541:     c = wev->data;
        !           542:     s = c->data;
        !           543: 
        !           544:     if (wev->timedout) {
        !           545:         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
        !           546:         c->timedout = 1;
        !           547:         ngx_mail_close_connection(c);
        !           548:         return;
        !           549:     }
        !           550: 
        !           551:     if (s->out.len == 0) {
        !           552:         if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
        !           553:             ngx_mail_close_connection(c);
        !           554:         }
        !           555: 
        !           556:         return;
        !           557:     }
        !           558: 
        !           559:     n = c->send(c, s->out.data, s->out.len);
        !           560: 
        !           561:     if (n > 0) {
        !           562:         s->out.len -= n;
        !           563: 
        !           564:         if (wev->timer_set) {
        !           565:             ngx_del_timer(wev);
        !           566:         }
        !           567: 
        !           568:         if (s->quit) {
        !           569:             ngx_mail_close_connection(c);
        !           570:             return;
        !           571:         }
        !           572: 
        !           573:         if (s->blocked) {
        !           574:             c->read->handler(c->read);
        !           575:         }
        !           576: 
        !           577:         return;
        !           578:     }
        !           579: 
        !           580:     if (n == NGX_ERROR) {
        !           581:         ngx_mail_close_connection(c);
        !           582:         return;
        !           583:     }
        !           584: 
        !           585:     /* n == NGX_AGAIN */
        !           586: 
        !           587:     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           588: 
        !           589:     ngx_add_timer(c->write, cscf->timeout);
        !           590: 
        !           591:     if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
        !           592:         ngx_mail_close_connection(c);
        !           593:         return;
        !           594:     }
        !           595: }
        !           596: 
        !           597: 
        !           598: ngx_int_t
        !           599: ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c)
        !           600: {
        !           601:     ssize_t                    n;
        !           602:     ngx_int_t                  rc;
        !           603:     ngx_str_t                  l;
        !           604:     ngx_mail_core_srv_conf_t  *cscf;
        !           605: 
        !           606:     n = c->recv(c, s->buffer->last, s->buffer->end - s->buffer->last);
        !           607: 
        !           608:     if (n == NGX_ERROR || n == 0) {
        !           609:         ngx_mail_close_connection(c);
        !           610:         return NGX_ERROR;
        !           611:     }
        !           612: 
        !           613:     if (n > 0) {
        !           614:         s->buffer->last += n;
        !           615:     }
        !           616: 
        !           617:     if (n == NGX_AGAIN) {
        !           618:         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
        !           619:             ngx_mail_session_internal_server_error(s);
        !           620:             return NGX_ERROR;
        !           621:         }
        !           622: 
        !           623:         return NGX_AGAIN;
        !           624:     }
        !           625: 
        !           626:     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           627: 
        !           628:     rc = cscf->protocol->parse_command(s);
        !           629: 
        !           630:     if (rc == NGX_AGAIN) {
        !           631: 
        !           632:         if (s->buffer->last < s->buffer->end) {
        !           633:             return rc;
        !           634:         }
        !           635: 
        !           636:         l.len = s->buffer->last - s->buffer->start;
        !           637:         l.data = s->buffer->start;
        !           638: 
        !           639:         ngx_log_error(NGX_LOG_INFO, c->log, 0,
        !           640:                       "client sent too long command \"%V\"", &l);
        !           641: 
        !           642:         s->quit = 1;
        !           643: 
        !           644:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           645:     }
        !           646: 
        !           647:     if (rc == NGX_IMAP_NEXT || rc == NGX_MAIL_PARSE_INVALID_COMMAND) {
        !           648:         return rc;
        !           649:     }
        !           650: 
        !           651:     if (rc == NGX_ERROR) {
        !           652:         ngx_mail_close_connection(c);
        !           653:         return NGX_ERROR;
        !           654:     }
        !           655: 
        !           656:     return NGX_OK;
        !           657: }
        !           658: 
        !           659: 
        !           660: void
        !           661: ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c)
        !           662: {
        !           663:     s->args.nelts = 0;
        !           664:     s->buffer->pos = s->buffer->start;
        !           665:     s->buffer->last = s->buffer->start;
        !           666:     s->state = 0;
        !           667: 
        !           668:     if (c->read->timer_set) {
        !           669:         ngx_del_timer(c->read);
        !           670:     }
        !           671: 
        !           672:     s->login_attempt++;
        !           673: 
        !           674:     ngx_mail_auth_http_init(s);
        !           675: }
        !           676: 
        !           677: 
        !           678: void
        !           679: ngx_mail_session_internal_server_error(ngx_mail_session_t *s)
        !           680: {
        !           681:     ngx_mail_core_srv_conf_t  *cscf;
        !           682: 
        !           683:     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
        !           684: 
        !           685:     s->out = cscf->protocol->internal_server_error;
        !           686:     s->quit = 1;
        !           687: 
        !           688:     ngx_mail_send(s->connection->write);
        !           689: }
        !           690: 
        !           691: 
        !           692: void
        !           693: ngx_mail_close_connection(ngx_connection_t *c)
        !           694: {
        !           695:     ngx_pool_t  *pool;
        !           696: 
        !           697:     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
        !           698:                    "close mail connection: %d", c->fd);
        !           699: 
        !           700: #if (NGX_MAIL_SSL)
        !           701: 
        !           702:     if (c->ssl) {
        !           703:         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
        !           704:             c->ssl->handler = ngx_mail_close_connection;
        !           705:             return;
        !           706:         }
        !           707:     }
        !           708: 
        !           709: #endif
        !           710: 
        !           711: #if (NGX_STAT_STUB)
        !           712:     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
        !           713: #endif
        !           714: 
        !           715:     c->destroyed = 1;
        !           716: 
        !           717:     pool = c->pool;
        !           718: 
        !           719:     ngx_close_connection(c);
        !           720: 
        !           721:     ngx_destroy_pool(pool);
        !           722: }
        !           723: 
        !           724: 
        !           725: u_char *
        !           726: ngx_mail_log_error(ngx_log_t *log, u_char *buf, size_t len)
        !           727: {
        !           728:     u_char              *p;
        !           729:     ngx_mail_session_t  *s;
        !           730:     ngx_mail_log_ctx_t  *ctx;
        !           731: 
        !           732:     if (log->action) {
        !           733:         p = ngx_snprintf(buf, len, " while %s", log->action);
        !           734:         len -= p - buf;
        !           735:         buf = p;
        !           736:     }
        !           737: 
        !           738:     ctx = log->data;
        !           739: 
        !           740:     p = ngx_snprintf(buf, len, ", client: %V", ctx->client);
        !           741:     len -= p - buf;
        !           742:     buf = p;
        !           743: 
        !           744:     s = ctx->session;
        !           745: 
        !           746:     if (s == NULL) {
        !           747:         return p;
        !           748:     }
        !           749: 
        !           750:     p = ngx_snprintf(buf, len, "%s, server: %V",
        !           751:                      s->starttls ? " using starttls" : "",
        !           752:                      s->addr_text);
        !           753:     len -= p - buf;
        !           754:     buf = p;
        !           755: 
        !           756:     if (s->login.len == 0) {
        !           757:         return p;
        !           758:     }
        !           759: 
        !           760:     p = ngx_snprintf(buf, len, ", login: \"%V\"", &s->login);
        !           761:     len -= p - buf;
        !           762:     buf = p;
        !           763: 
        !           764:     if (s->proxy == NULL) {
        !           765:         return p;
        !           766:     }
        !           767: 
        !           768:     p = ngx_snprintf(buf, len, ", upstream: %V", s->proxy->upstream.name);
        !           769: 
        !           770:     return p;
        !           771: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>