Annotation of embedaddon/nginx/src/mail/ngx_mail_parse.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: #include <ngx_mail_imap_module.h>
        !            14: #include <ngx_mail_smtp_module.h>
        !            15: 
        !            16: 
        !            17: ngx_int_t
        !            18: ngx_mail_pop3_parse_command(ngx_mail_session_t *s)
        !            19: {
        !            20:     u_char      ch, *p, *c, c0, c1, c2, c3;
        !            21:     ngx_str_t  *arg;
        !            22:     enum {
        !            23:         sw_start = 0,
        !            24:         sw_spaces_before_argument,
        !            25:         sw_argument,
        !            26:         sw_almost_done
        !            27:     } state;
        !            28: 
        !            29:     state = s->state;
        !            30: 
        !            31:     for (p = s->buffer->pos; p < s->buffer->last; p++) {
        !            32:         ch = *p;
        !            33: 
        !            34:         switch (state) {
        !            35: 
        !            36:         /* POP3 command */
        !            37:         case sw_start:
        !            38:             if (ch == ' ' || ch == CR || ch == LF) {
        !            39:                 c = s->buffer->start;
        !            40: 
        !            41:                 if (p - c == 4) {
        !            42: 
        !            43:                     c0 = ngx_toupper(c[0]);
        !            44:                     c1 = ngx_toupper(c[1]);
        !            45:                     c2 = ngx_toupper(c[2]);
        !            46:                     c3 = ngx_toupper(c[3]);
        !            47: 
        !            48:                     if (c0 == 'U' && c1 == 'S' && c2 == 'E' && c3 == 'R')
        !            49:                     {
        !            50:                         s->command = NGX_POP3_USER;
        !            51: 
        !            52:                     } else if (c0 == 'P' && c1 == 'A' && c2 == 'S' && c3 == 'S')
        !            53:                     {
        !            54:                         s->command = NGX_POP3_PASS;
        !            55: 
        !            56:                     } else if (c0 == 'A' && c1 == 'P' && c2 == 'O' && c3 == 'P')
        !            57:                     {
        !            58:                         s->command = NGX_POP3_APOP;
        !            59: 
        !            60:                     } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T')
        !            61:                     {
        !            62:                         s->command = NGX_POP3_QUIT;
        !            63: 
        !            64:                     } else if (c0 == 'C' && c1 == 'A' && c2 == 'P' && c3 == 'A')
        !            65:                     {
        !            66:                         s->command = NGX_POP3_CAPA;
        !            67: 
        !            68:                     } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H')
        !            69:                     {
        !            70:                         s->command = NGX_POP3_AUTH;
        !            71: 
        !            72:                     } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P')
        !            73:                     {
        !            74:                         s->command = NGX_POP3_NOOP;
        !            75: #if (NGX_MAIL_SSL)
        !            76:                     } else if (c0 == 'S' && c1 == 'T' && c2 == 'L' && c3 == 'S')
        !            77:                     {
        !            78:                         s->command = NGX_POP3_STLS;
        !            79: #endif
        !            80:                     } else {
        !            81:                         goto invalid;
        !            82:                     }
        !            83: 
        !            84:                 } else {
        !            85:                     goto invalid;
        !            86:                 }
        !            87: 
        !            88:                 switch (ch) {
        !            89:                 case ' ':
        !            90:                     state = sw_spaces_before_argument;
        !            91:                     break;
        !            92:                 case CR:
        !            93:                     state = sw_almost_done;
        !            94:                     break;
        !            95:                 case LF:
        !            96:                     goto done;
        !            97:                 }
        !            98:                 break;
        !            99:             }
        !           100: 
        !           101:             if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
        !           102:                 goto invalid;
        !           103:             }
        !           104: 
        !           105:             break;
        !           106: 
        !           107:         case sw_spaces_before_argument:
        !           108:             switch (ch) {
        !           109:             case ' ':
        !           110:                 break;
        !           111:             case CR:
        !           112:                 state = sw_almost_done;
        !           113:                 s->arg_end = p;
        !           114:                 break;
        !           115:             case LF:
        !           116:                 s->arg_end = p;
        !           117:                 goto done;
        !           118:             default:
        !           119:                 if (s->args.nelts <= 2) {
        !           120:                     state = sw_argument;
        !           121:                     s->arg_start = p;
        !           122:                     break;
        !           123:                 }
        !           124:                 goto invalid;
        !           125:             }
        !           126:             break;
        !           127: 
        !           128:         case sw_argument:
        !           129:             switch (ch) {
        !           130: 
        !           131:             case ' ':
        !           132: 
        !           133:                 /*
        !           134:                  * the space should be considered as part of the at username
        !           135:                  * or password, but not of argument in other commands
        !           136:                  */
        !           137: 
        !           138:                 if (s->command == NGX_POP3_USER
        !           139:                     || s->command == NGX_POP3_PASS)
        !           140:                 {
        !           141:                     break;
        !           142:                 }
        !           143: 
        !           144:                 /* fall through */
        !           145: 
        !           146:             case CR:
        !           147:             case LF:
        !           148:                 arg = ngx_array_push(&s->args);
        !           149:                 if (arg == NULL) {
        !           150:                     return NGX_ERROR;
        !           151:                 }
        !           152:                 arg->len = p - s->arg_start;
        !           153:                 arg->data = s->arg_start;
        !           154:                 s->arg_start = NULL;
        !           155: 
        !           156:                 switch (ch) {
        !           157:                 case ' ':
        !           158:                     state = sw_spaces_before_argument;
        !           159:                     break;
        !           160:                 case CR:
        !           161:                     state = sw_almost_done;
        !           162:                     break;
        !           163:                 case LF:
        !           164:                     goto done;
        !           165:                 }
        !           166:                 break;
        !           167: 
        !           168:             default:
        !           169:                 break;
        !           170:             }
        !           171:             break;
        !           172: 
        !           173:         case sw_almost_done:
        !           174:             switch (ch) {
        !           175:             case LF:
        !           176:                 goto done;
        !           177:             default:
        !           178:                 goto invalid;
        !           179:             }
        !           180:         }
        !           181:     }
        !           182: 
        !           183:     s->buffer->pos = p;
        !           184:     s->state = state;
        !           185: 
        !           186:     return NGX_AGAIN;
        !           187: 
        !           188: done:
        !           189: 
        !           190:     s->buffer->pos = p + 1;
        !           191: 
        !           192:     if (s->arg_start) {
        !           193:         arg = ngx_array_push(&s->args);
        !           194:         if (arg == NULL) {
        !           195:             return NGX_ERROR;
        !           196:         }
        !           197:         arg->len = s->arg_end - s->arg_start;
        !           198:         arg->data = s->arg_start;
        !           199:         s->arg_start = NULL;
        !           200:     }
        !           201: 
        !           202:     s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument;
        !           203: 
        !           204:     return NGX_OK;
        !           205: 
        !           206: invalid:
        !           207: 
        !           208:     s->state = sw_start;
        !           209:     s->arg_start = NULL;
        !           210: 
        !           211:     return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           212: }
        !           213: 
        !           214: 
        !           215: ngx_int_t
        !           216: ngx_mail_imap_parse_command(ngx_mail_session_t *s)
        !           217: {
        !           218:     u_char      ch, *p, *c;
        !           219:     ngx_str_t  *arg;
        !           220:     enum {
        !           221:         sw_start = 0,
        !           222:         sw_spaces_before_command,
        !           223:         sw_command,
        !           224:         sw_spaces_before_argument,
        !           225:         sw_argument,
        !           226:         sw_backslash,
        !           227:         sw_literal,
        !           228:         sw_no_sync_literal_argument,
        !           229:         sw_start_literal_argument,
        !           230:         sw_literal_argument,
        !           231:         sw_end_literal_argument,
        !           232:         sw_almost_done
        !           233:     } state;
        !           234: 
        !           235:     state = s->state;
        !           236: 
        !           237:     for (p = s->buffer->pos; p < s->buffer->last; p++) {
        !           238:         ch = *p;
        !           239: 
        !           240:         switch (state) {
        !           241: 
        !           242:         /* IMAP tag */
        !           243:         case sw_start:
        !           244:             switch (ch) {
        !           245:             case ' ':
        !           246:                 s->tag.len = p - s->buffer->start + 1;
        !           247:                 s->tag.data = s->buffer->start;
        !           248:                 state = sw_spaces_before_command;
        !           249:                 break;
        !           250:             case CR:
        !           251:                 s->state = sw_start;
        !           252:                 return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           253:             case LF:
        !           254:                 s->state = sw_start;
        !           255:                 return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           256:             }
        !           257:             break;
        !           258: 
        !           259:         case sw_spaces_before_command:
        !           260:             switch (ch) {
        !           261:             case ' ':
        !           262:                 break;
        !           263:             case CR:
        !           264:                 s->state = sw_start;
        !           265:                 return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           266:             case LF:
        !           267:                 s->state = sw_start;
        !           268:                 return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           269:             default:
        !           270:                 s->cmd_start = p;
        !           271:                 state = sw_command;
        !           272:                 break;
        !           273:             }
        !           274:             break;
        !           275: 
        !           276:         case sw_command:
        !           277:             if (ch == ' ' || ch == CR || ch == LF) {
        !           278: 
        !           279:                 c = s->cmd_start;
        !           280: 
        !           281:                 switch (p - c) {
        !           282: 
        !           283:                 case 4:
        !           284:                     if ((c[0] == 'N' || c[0] == 'n')
        !           285:                         && (c[1] == 'O'|| c[1] == 'o')
        !           286:                         && (c[2] == 'O'|| c[2] == 'o')
        !           287:                         && (c[3] == 'P'|| c[3] == 'p'))
        !           288:                     {
        !           289:                         s->command = NGX_IMAP_NOOP;
        !           290: 
        !           291:                     } else {
        !           292:                         goto invalid;
        !           293:                     }
        !           294:                     break;
        !           295: 
        !           296:                 case 5:
        !           297:                     if ((c[0] == 'L'|| c[0] == 'l')
        !           298:                         && (c[1] == 'O'|| c[1] == 'o')
        !           299:                         && (c[2] == 'G'|| c[2] == 'g')
        !           300:                         && (c[3] == 'I'|| c[3] == 'i')
        !           301:                         && (c[4] == 'N'|| c[4] == 'n'))
        !           302:                     {
        !           303:                         s->command = NGX_IMAP_LOGIN;
        !           304: 
        !           305:                     } else {
        !           306:                         goto invalid;
        !           307:                     }
        !           308:                     break;
        !           309: 
        !           310:                 case 6:
        !           311:                     if ((c[0] == 'L'|| c[0] == 'l')
        !           312:                         && (c[1] == 'O'|| c[1] == 'o')
        !           313:                         && (c[2] == 'G'|| c[2] == 'g')
        !           314:                         && (c[3] == 'O'|| c[3] == 'o')
        !           315:                         && (c[4] == 'U'|| c[4] == 'u')
        !           316:                         && (c[5] == 'T'|| c[5] == 't'))
        !           317:                     {
        !           318:                         s->command = NGX_IMAP_LOGOUT;
        !           319: 
        !           320:                     } else {
        !           321:                         goto invalid;
        !           322:                     }
        !           323:                     break;
        !           324: 
        !           325: #if (NGX_MAIL_SSL)
        !           326:                 case 8:
        !           327:                     if ((c[0] == 'S'|| c[0] == 's')
        !           328:                         && (c[1] == 'T'|| c[1] == 't')
        !           329:                         && (c[2] == 'A'|| c[2] == 'a')
        !           330:                         && (c[3] == 'R'|| c[3] == 'r')
        !           331:                         && (c[4] == 'T'|| c[4] == 't')
        !           332:                         && (c[5] == 'T'|| c[5] == 't')
        !           333:                         && (c[6] == 'L'|| c[6] == 'l')
        !           334:                         && (c[7] == 'S'|| c[7] == 's'))
        !           335:                     {
        !           336:                         s->command = NGX_IMAP_STARTTLS;
        !           337: 
        !           338:                     } else {
        !           339:                         goto invalid;
        !           340:                     }
        !           341:                     break;
        !           342: #endif
        !           343: 
        !           344:                 case 10:
        !           345:                     if ((c[0] == 'C'|| c[0] == 'c')
        !           346:                         && (c[1] == 'A'|| c[1] == 'a')
        !           347:                         && (c[2] == 'P'|| c[2] == 'p')
        !           348:                         && (c[3] == 'A'|| c[3] == 'a')
        !           349:                         && (c[4] == 'B'|| c[4] == 'b')
        !           350:                         && (c[5] == 'I'|| c[5] == 'i')
        !           351:                         && (c[6] == 'L'|| c[6] == 'l')
        !           352:                         && (c[7] == 'I'|| c[7] == 'i')
        !           353:                         && (c[8] == 'T'|| c[8] == 't')
        !           354:                         && (c[9] == 'Y'|| c[9] == 'y'))
        !           355:                     {
        !           356:                         s->command = NGX_IMAP_CAPABILITY;
        !           357: 
        !           358:                     } else {
        !           359:                         goto invalid;
        !           360:                     }
        !           361:                     break;
        !           362: 
        !           363:                 case 12:
        !           364:                     if ((c[0] == 'A'|| c[0] == 'a')
        !           365:                         && (c[1] == 'U'|| c[1] == 'u')
        !           366:                         && (c[2] == 'T'|| c[2] == 't')
        !           367:                         && (c[3] == 'H'|| c[3] == 'h')
        !           368:                         && (c[4] == 'E'|| c[4] == 'e')
        !           369:                         && (c[5] == 'N'|| c[5] == 'n')
        !           370:                         && (c[6] == 'T'|| c[6] == 't')
        !           371:                         && (c[7] == 'I'|| c[7] == 'i')
        !           372:                         && (c[8] == 'C'|| c[8] == 'c')
        !           373:                         && (c[9] == 'A'|| c[9] == 'a')
        !           374:                         && (c[10] == 'T'|| c[10] == 't')
        !           375:                         && (c[11] == 'E'|| c[11] == 'e'))
        !           376:                     {
        !           377:                         s->command = NGX_IMAP_AUTHENTICATE;
        !           378: 
        !           379:                     } else {
        !           380:                         goto invalid;
        !           381:                     }
        !           382:                     break;
        !           383: 
        !           384:                 default:
        !           385:                     goto invalid;
        !           386:                 }
        !           387: 
        !           388:                 switch (ch) {
        !           389:                 case ' ':
        !           390:                     state = sw_spaces_before_argument;
        !           391:                     break;
        !           392:                 case CR:
        !           393:                     state = sw_almost_done;
        !           394:                     break;
        !           395:                 case LF:
        !           396:                     goto done;
        !           397:                 }
        !           398:                 break;
        !           399:             }
        !           400: 
        !           401:             if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
        !           402:                 goto invalid;
        !           403:             }
        !           404: 
        !           405:             break;
        !           406: 
        !           407:         case sw_spaces_before_argument:
        !           408:             switch (ch) {
        !           409:             case ' ':
        !           410:                 break;
        !           411:             case CR:
        !           412:                 state = sw_almost_done;
        !           413:                 s->arg_end = p;
        !           414:                 break;
        !           415:             case LF:
        !           416:                 s->arg_end = p;
        !           417:                 goto done;
        !           418:             case '"':
        !           419:                 if (s->args.nelts <= 2) {
        !           420:                     s->quoted = 1;
        !           421:                     s->arg_start = p + 1;
        !           422:                     state = sw_argument;
        !           423:                     break;
        !           424:                 }
        !           425:                 goto invalid;
        !           426:             case '{':
        !           427:                 if (s->args.nelts <= 2) {
        !           428:                     state = sw_literal;
        !           429:                     break;
        !           430:                 }
        !           431:                 goto invalid;
        !           432:             default:
        !           433:                 if (s->args.nelts <= 2) {
        !           434:                     s->arg_start = p;
        !           435:                     state = sw_argument;
        !           436:                     break;
        !           437:                 }
        !           438:                 goto invalid;
        !           439:             }
        !           440:             break;
        !           441: 
        !           442:         case sw_argument:
        !           443:             if (ch == ' ' && s->quoted) {
        !           444:                 break;
        !           445:             }
        !           446: 
        !           447:             switch (ch) {
        !           448:             case '"':
        !           449:                 if (!s->quoted) {
        !           450:                     break;
        !           451:                 }
        !           452:                 s->quoted = 0;
        !           453:                 /* fall through */
        !           454:             case ' ':
        !           455:             case CR:
        !           456:             case LF:
        !           457:                 arg = ngx_array_push(&s->args);
        !           458:                 if (arg == NULL) {
        !           459:                     return NGX_ERROR;
        !           460:                 }
        !           461:                 arg->len = p - s->arg_start;
        !           462:                 arg->data = s->arg_start;
        !           463:                 s->arg_start = NULL;
        !           464: 
        !           465:                 switch (ch) {
        !           466:                 case '"':
        !           467:                 case ' ':
        !           468:                     state = sw_spaces_before_argument;
        !           469:                     break;
        !           470:                 case CR:
        !           471:                     state = sw_almost_done;
        !           472:                     break;
        !           473:                 case LF:
        !           474:                     goto done;
        !           475:                 }
        !           476:                 break;
        !           477:             case '\\':
        !           478:                 if (s->quoted) {
        !           479:                     s->backslash = 1;
        !           480:                     state = sw_backslash;
        !           481:                 }
        !           482:                 break;
        !           483:             }
        !           484:             break;
        !           485: 
        !           486:         case sw_backslash:
        !           487:             switch (ch) {
        !           488:             case CR:
        !           489:             case LF:
        !           490:                 goto invalid;
        !           491:             default:
        !           492:                 state = sw_argument;
        !           493:             }
        !           494:             break;
        !           495: 
        !           496:         case sw_literal:
        !           497:             if (ch >= '0' && ch <= '9') {
        !           498:                 s->literal_len = s->literal_len * 10 + (ch - '0');
        !           499:                 break;
        !           500:             }
        !           501:             if (ch == '}') {
        !           502:                 state = sw_start_literal_argument;
        !           503:                 break;
        !           504:             }
        !           505:             if (ch == '+') {
        !           506:                 state = sw_no_sync_literal_argument;
        !           507:                 break;
        !           508:             }
        !           509:             goto invalid;
        !           510: 
        !           511:         case sw_no_sync_literal_argument:
        !           512:             if (ch == '}') {
        !           513:                 s->no_sync_literal = 1;
        !           514:                 state = sw_start_literal_argument;
        !           515:                 break;
        !           516:             }
        !           517:             goto invalid;
        !           518: 
        !           519:         case sw_start_literal_argument:
        !           520:             switch (ch) {
        !           521:             case CR:
        !           522:                 break;
        !           523:             case LF:
        !           524:                 s->buffer->pos = p + 1;
        !           525:                 s->arg_start = p + 1;
        !           526:                 if (s->no_sync_literal == 0) {
        !           527:                     s->state = sw_literal_argument;
        !           528:                     return NGX_IMAP_NEXT;
        !           529:                 }
        !           530:                 state = sw_literal_argument;
        !           531:                 s->no_sync_literal = 0;
        !           532:                 break;
        !           533:             default:
        !           534:                 goto invalid;
        !           535:             }
        !           536:             break;
        !           537: 
        !           538:         case sw_literal_argument:
        !           539:             if (s->literal_len && --s->literal_len) {
        !           540:                 break;
        !           541:             }
        !           542: 
        !           543:             arg = ngx_array_push(&s->args);
        !           544:             if (arg == NULL) {
        !           545:                 return NGX_ERROR;
        !           546:             }
        !           547:             arg->len = p + 1 - s->arg_start;
        !           548:             arg->data = s->arg_start;
        !           549:             s->arg_start = NULL;
        !           550:             state = sw_end_literal_argument;
        !           551: 
        !           552:             break;
        !           553: 
        !           554:         case sw_end_literal_argument:
        !           555:             switch (ch) {
        !           556:             case '{':
        !           557:                 if (s->args.nelts <= 2) {
        !           558:                     state = sw_literal;
        !           559:                     break;
        !           560:                 }
        !           561:                 goto invalid;
        !           562:             case CR:
        !           563:                 state = sw_almost_done;
        !           564:                 break;
        !           565:             case LF:
        !           566:                 goto done;
        !           567:             default:
        !           568:                 state = sw_spaces_before_argument;
        !           569:                 break;
        !           570:             }
        !           571:             break;
        !           572: 
        !           573:         case sw_almost_done:
        !           574:             switch (ch) {
        !           575:             case LF:
        !           576:                 goto done;
        !           577:             default:
        !           578:                 goto invalid;
        !           579:             }
        !           580:         }
        !           581:     }
        !           582: 
        !           583:     s->buffer->pos = p;
        !           584:     s->state = state;
        !           585: 
        !           586:     return NGX_AGAIN;
        !           587: 
        !           588: done:
        !           589: 
        !           590:     s->buffer->pos = p + 1;
        !           591: 
        !           592:     if (s->arg_start) {
        !           593:         arg = ngx_array_push(&s->args);
        !           594:         if (arg == NULL) {
        !           595:             return NGX_ERROR;
        !           596:         }
        !           597:         arg->len = s->arg_end - s->arg_start;
        !           598:         arg->data = s->arg_start;
        !           599: 
        !           600:         s->arg_start = NULL;
        !           601:         s->cmd_start = NULL;
        !           602:         s->quoted = 0;
        !           603:         s->no_sync_literal = 0;
        !           604:         s->literal_len = 0;
        !           605:     }
        !           606: 
        !           607:     s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument;
        !           608: 
        !           609:     return NGX_OK;
        !           610: 
        !           611: invalid:
        !           612: 
        !           613:     s->state = sw_start;
        !           614:     s->quoted = 0;
        !           615:     s->no_sync_literal = 0;
        !           616:     s->literal_len = 0;
        !           617: 
        !           618:     return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           619: }
        !           620: 
        !           621: 
        !           622: ngx_int_t
        !           623: ngx_mail_smtp_parse_command(ngx_mail_session_t *s)
        !           624: {
        !           625:     u_char      ch, *p, *c, c0, c1, c2, c3;
        !           626:     ngx_str_t  *arg;
        !           627:     enum {
        !           628:         sw_start = 0,
        !           629:         sw_spaces_before_argument,
        !           630:         sw_argument,
        !           631:         sw_almost_done
        !           632:     } state;
        !           633: 
        !           634:     state = s->state;
        !           635: 
        !           636:     for (p = s->buffer->pos; p < s->buffer->last; p++) {
        !           637:         ch = *p;
        !           638: 
        !           639:         switch (state) {
        !           640: 
        !           641:         /* SMTP command */
        !           642:         case sw_start:
        !           643:             if (ch == ' ' || ch == CR || ch == LF) {
        !           644:                 c = s->buffer->start;
        !           645: 
        !           646:                 if (p - c == 4) {
        !           647: 
        !           648:                     c0 = ngx_toupper(c[0]);
        !           649:                     c1 = ngx_toupper(c[1]);
        !           650:                     c2 = ngx_toupper(c[2]);
        !           651:                     c3 = ngx_toupper(c[3]);
        !           652: 
        !           653:                     if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'O')
        !           654:                     {
        !           655:                         s->command = NGX_SMTP_HELO;
        !           656: 
        !           657:                     } else if (c0 == 'E' && c1 == 'H' && c2 == 'L' && c3 == 'O')
        !           658:                     {
        !           659:                         s->command = NGX_SMTP_EHLO;
        !           660: 
        !           661:                     } else if (c0 == 'Q' && c1 == 'U' && c2 == 'I' && c3 == 'T')
        !           662:                     {
        !           663:                         s->command = NGX_SMTP_QUIT;
        !           664: 
        !           665:                     } else if (c0 == 'A' && c1 == 'U' && c2 == 'T' && c3 == 'H')
        !           666:                     {
        !           667:                         s->command = NGX_SMTP_AUTH;
        !           668: 
        !           669:                     } else if (c0 == 'N' && c1 == 'O' && c2 == 'O' && c3 == 'P')
        !           670:                     {
        !           671:                         s->command = NGX_SMTP_NOOP;
        !           672: 
        !           673:                     } else if (c0 == 'M' && c1 == 'A' && c2 == 'I' && c3 == 'L')
        !           674:                     {
        !           675:                         s->command = NGX_SMTP_MAIL;
        !           676: 
        !           677:                     } else if (c0 == 'R' && c1 == 'S' && c2 == 'E' && c3 == 'T')
        !           678:                     {
        !           679:                         s->command = NGX_SMTP_RSET;
        !           680: 
        !           681:                     } else if (c0 == 'R' && c1 == 'C' && c2 == 'P' && c3 == 'T')
        !           682:                     {
        !           683:                         s->command = NGX_SMTP_RCPT;
        !           684: 
        !           685:                     } else if (c0 == 'V' && c1 == 'R' && c2 == 'F' && c3 == 'Y')
        !           686:                     {
        !           687:                         s->command = NGX_SMTP_VRFY;
        !           688: 
        !           689:                     } else if (c0 == 'E' && c1 == 'X' && c2 == 'P' && c3 == 'N')
        !           690:                     {
        !           691:                         s->command = NGX_SMTP_EXPN;
        !           692: 
        !           693:                     } else if (c0 == 'H' && c1 == 'E' && c2 == 'L' && c3 == 'P')
        !           694:                     {
        !           695:                         s->command = NGX_SMTP_HELP;
        !           696: 
        !           697:                     } else {
        !           698:                         goto invalid;
        !           699:                     }
        !           700: #if (NGX_MAIL_SSL)
        !           701:                 } else if (p - c == 8) {
        !           702: 
        !           703:                     if ((c[0] == 'S'|| c[0] == 's')
        !           704:                         && (c[1] == 'T'|| c[1] == 't')
        !           705:                         && (c[2] == 'A'|| c[2] == 'a')
        !           706:                         && (c[3] == 'R'|| c[3] == 'r')
        !           707:                         && (c[4] == 'T'|| c[4] == 't')
        !           708:                         && (c[5] == 'T'|| c[5] == 't')
        !           709:                         && (c[6] == 'L'|| c[6] == 'l')
        !           710:                         && (c[7] == 'S'|| c[7] == 's'))
        !           711:                     {
        !           712:                         s->command = NGX_SMTP_STARTTLS;
        !           713: 
        !           714:                     } else {
        !           715:                         goto invalid;
        !           716:                     }
        !           717: #endif
        !           718:                 } else {
        !           719:                     goto invalid;
        !           720:                 }
        !           721: 
        !           722:                 switch (ch) {
        !           723:                 case ' ':
        !           724:                     state = sw_spaces_before_argument;
        !           725:                     break;
        !           726:                 case CR:
        !           727:                     state = sw_almost_done;
        !           728:                     break;
        !           729:                 case LF:
        !           730:                     goto done;
        !           731:                 }
        !           732:                 break;
        !           733:             }
        !           734: 
        !           735:             if ((ch < 'A' || ch > 'Z') && (ch < 'a' || ch > 'z')) {
        !           736:                 goto invalid;
        !           737:             }
        !           738: 
        !           739:             break;
        !           740: 
        !           741:         case sw_spaces_before_argument:
        !           742:             switch (ch) {
        !           743:             case ' ':
        !           744:                 break;
        !           745:             case CR:
        !           746:                 state = sw_almost_done;
        !           747:                 s->arg_end = p;
        !           748:                 break;
        !           749:             case LF:
        !           750:                 s->arg_end = p;
        !           751:                 goto done;
        !           752:             default:
        !           753:                 if (s->args.nelts <= 10) {
        !           754:                     state = sw_argument;
        !           755:                     s->arg_start = p;
        !           756:                     break;
        !           757:                 }
        !           758:                 goto invalid;
        !           759:             }
        !           760:             break;
        !           761: 
        !           762:         case sw_argument:
        !           763:             switch (ch) {
        !           764:             case ' ':
        !           765:             case CR:
        !           766:             case LF:
        !           767:                 arg = ngx_array_push(&s->args);
        !           768:                 if (arg == NULL) {
        !           769:                     return NGX_ERROR;
        !           770:                 }
        !           771:                 arg->len = p - s->arg_start;
        !           772:                 arg->data = s->arg_start;
        !           773:                 s->arg_start = NULL;
        !           774: 
        !           775:                 switch (ch) {
        !           776:                 case ' ':
        !           777:                     state = sw_spaces_before_argument;
        !           778:                     break;
        !           779:                 case CR:
        !           780:                     state = sw_almost_done;
        !           781:                     break;
        !           782:                 case LF:
        !           783:                     goto done;
        !           784:                 }
        !           785:                 break;
        !           786: 
        !           787:             default:
        !           788:                 break;
        !           789:             }
        !           790:             break;
        !           791: 
        !           792:         case sw_almost_done:
        !           793:             switch (ch) {
        !           794:             case LF:
        !           795:                 goto done;
        !           796:             default:
        !           797:                 goto invalid;
        !           798:             }
        !           799:         }
        !           800:     }
        !           801: 
        !           802:     s->buffer->pos = p;
        !           803:     s->state = state;
        !           804: 
        !           805:     return NGX_AGAIN;
        !           806: 
        !           807: done:
        !           808: 
        !           809:     s->buffer->pos = p + 1;
        !           810: 
        !           811:     if (s->arg_start) {
        !           812:         arg = ngx_array_push(&s->args);
        !           813:         if (arg == NULL) {
        !           814:             return NGX_ERROR;
        !           815:         }
        !           816:         arg->len = s->arg_end - s->arg_start;
        !           817:         arg->data = s->arg_start;
        !           818:         s->arg_start = NULL;
        !           819:     }
        !           820: 
        !           821:     s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument;
        !           822: 
        !           823:     return NGX_OK;
        !           824: 
        !           825: invalid:
        !           826: 
        !           827:     s->state = sw_start;
        !           828:     s->arg_start = NULL;
        !           829: 
        !           830:     return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           831: }
        !           832: 
        !           833: 
        !           834: ngx_int_t
        !           835: ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c)
        !           836: {
        !           837:     ngx_str_t                 *arg;
        !           838: 
        !           839: #if (NGX_MAIL_SSL)
        !           840:     if (ngx_mail_starttls_only(s, c)) {
        !           841:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           842:     }
        !           843: #endif
        !           844: 
        !           845:     arg = s->args.elts;
        !           846: 
        !           847:     if (arg[0].len == 5) {
        !           848: 
        !           849:         if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) {
        !           850: 
        !           851:             if (s->args.nelts == 1) {
        !           852:                 return NGX_MAIL_AUTH_LOGIN;
        !           853:             }
        !           854: 
        !           855:             if (s->args.nelts == 2) {
        !           856:                 return NGX_MAIL_AUTH_LOGIN_USERNAME;
        !           857:             }
        !           858: 
        !           859:             return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           860:         }
        !           861: 
        !           862:         if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) {
        !           863: 
        !           864:             if (s->args.nelts == 1) {
        !           865:                 return NGX_MAIL_AUTH_PLAIN;
        !           866:             }
        !           867: 
        !           868:             if (s->args.nelts == 2) {
        !           869:                 return ngx_mail_auth_plain(s, c, 1);
        !           870:             }
        !           871:         }
        !           872: 
        !           873:         return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           874:     }
        !           875: 
        !           876:     if (arg[0].len == 8) {
        !           877: 
        !           878:         if (s->args.nelts != 1) {
        !           879:             return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           880:         }
        !           881: 
        !           882:         if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) {
        !           883:             return NGX_MAIL_AUTH_CRAM_MD5;
        !           884:         }
        !           885:     }
        !           886: 
        !           887:     return NGX_MAIL_PARSE_INVALID_COMMAND;
        !           888: }

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