# HG changeset patch # User Kunal Pariani <kpari...@zimbra.com> # Date 1410986530 18000 # Wed Sep 17 15:42:10 2014 -0500 # Node ID dfc11aa2a98e697a562b2aee092a77e3dc13f55a # Parent 65988e6762de9c2c98f5f028fddecf45bc05a913 Update mail parsing to be per protocol (imap/pop/smtp)
diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail.h Wed Sep 17 15:42:10 2014 -0500 @@ -248,6 +248,7 @@ typedef struct { u_char *arg_start; u_char *arg_end; ngx_uint_t literal_len; + ngx_uint_t eargs; /* expected #args for command */ } ngx_mail_session_t; @@ -315,7 +316,12 @@ typedef struct { #define NGX_MAIL_AUTH_NONE_ENABLED 0x0020 -#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_COMMAND 20 +#define NGX_MAIL_PARSE_INVALID_AUTH_MECH 30 +#define NGX_MAIL_AUTH_ABORT 40 +#define NGX_MAIL_AUTH_ARGUMENT 50 +#define NGX_MAIL_AUTH_FAILED 60 +#define NGX_MAIL_LOGIN_FAILED 70 typedef void (*ngx_mail_init_session_pt)(ngx_mail_session_t *s, @@ -399,6 +405,13 @@ ngx_int_t ngx_mail_auth_parse(ngx_mail_s void ngx_mail_send(ngx_event_t *wev); ngx_int_t ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c); +void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s); +void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s); +void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s); void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c); void ngx_mail_close_connection(ngx_connection_t *c); void ngx_mail_session_internal_server_error(ngx_mail_session_t *s); diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_imap_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -21,7 +21,6 @@ static ngx_int_t ngx_mail_imap_capabilit static ngx_int_t ngx_mail_imap_starttls(ngx_mail_session_t *s, ngx_connection_t *c); - static u_char imap_greeting[] = "* OK IMAP4 ready" CRLF; static u_char imap_star[] = "* "; static u_char imap_ok[] = "OK completed" CRLF; @@ -31,7 +30,11 @@ static u_char imap_username[] = "+ VXNl static u_char imap_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char imap_bye[] = "* BYE" CRLF; static u_char imap_invalid_command[] = "BAD invalid command" CRLF; - +static u_char imap_unsupported_mech[] = "NO mechanism not supported" CRLF; +static u_char imap_nocleartext[] = "NO cleartext logins disabled" CRLF; +static u_char imap_authaborted[] = "BAD AUTHENTICATE aborted" CRLF; +static u_char imap_login_failed[] = "NO LOGIN failed" CRLF; +static u_char imap_authenticate_failed[] = "NO AUTHENTICATE failed" CRLF; void ngx_mail_imap_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -235,15 +238,74 @@ ngx_mail_imap_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, imap_authaborted); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, imap_authenticate_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, imap_login_failed); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported IMAP auth mechanism"); + ngx_str_set(&s->out, imap_unsupported_mech); + s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: - s->state = 0; ngx_str_set(&s->out, imap_invalid_command); s->mail_state = ngx_imap_start; + ngx_mail_set_imap_parse_state_start(s); + s->arg_start = NULL; + ngx_mail_reset_parse_buffer(s); break; + + case NGX_MAIL_AUTH_ARGUMENT: + ngx_mail_set_imap_parse_state_argument(s); + /* preserve tag, since tag's memory is allocated in buffer, need to set the + * buffer pos after tag + */ + s->arg_start = s->buffer->start + s->tag.len; + s->buffer->pos = s->arg_start; + s->buffer->last = s->arg_start; + tag = 0; /* just output s->out */ + break; + + case NGX_IMAP_NEXT: + /* do nothing, preserve all the state, including s->state, s->mail_state, + * s->buffer, s->arg_start + */ + break; } if (tag) { @@ -300,6 +362,7 @@ ngx_mail_imap_login(ngx_mail_session_t * #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->text, imap_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -342,7 +405,7 @@ ngx_mail_imap_login(ngx_mail_session_t * static ngx_int_t ngx_mail_imap_authenticate(ngx_mail_session_t *s, ngx_connection_t *c) { - ngx_int_t rc; + ngx_int_t rc, res; ngx_mail_core_srv_conf_t *cscf; ngx_mail_imap_srv_conf_t *iscf; @@ -353,36 +416,48 @@ ngx_mail_imap_authenticate(ngx_mail_sess #endif rc = ngx_mail_auth_parse(s, c); + iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); switch (rc) { case NGX_MAIL_AUTH_LOGIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_username); s->mail_state = ngx_imap_auth_login_username; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_LOGIN_USERNAME: - ngx_str_set(&s->out, imap_password); - s->mail_state = ngx_imap_auth_login_password; - - return ngx_mail_auth_login_username(s, c, 1); + if (!(iscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } + res = ngx_mail_auth_login_username(s, c, 1); + if (res == NGX_MAIL_AUTH_ARGUMENT) { + ngx_str_set(&s->out, imap_password); + s->mail_state = ngx_imap_auth_login_password; + return NGX_MAIL_AUTH_ARGUMENT; + } else { + return res; + } case NGX_MAIL_AUTH_PLAIN: + if (!(iscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, imap_plain_next); s->mail_state = ngx_imap_auth_plain; - return NGX_OK; + return NGX_MAIL_AUTH_ARGUMENT; case NGX_MAIL_AUTH_CRAM_MD5: - iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module); - if (!(iscf->auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } if (s->salt.data == NULL) { diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_parse.c Wed Sep 17 15:42:10 2014 -0500 @@ -13,20 +13,73 @@ #include <ngx_mail_imap_module.h> #include <ngx_mail_smtp_module.h> +typedef enum { + swi_start = 0, + swi_spaces_before_command, + swi_command, + swi_spaces_before_argument, + swi_argument, + swi_backslash, + swi_literal, + swi_no_sync_literal_argument, + swi_start_literal_argument, + swi_literal_argument, + swi_end_literal_argument, + swi_almost_done, +} ngx_imap_parse_state_e; + +typedef enum { + swp_start = 0, + swp_spaces_before_argument, + swp_argument, + swp_almost_done +} ngx_pop3_parse_state_e; + +typedef enum { + sws_start = 0, + sws_command, + sws_spaces_before_argument, + sws_argument, + sws_almost_done, + sws_invalid +} ngx_smtp_parse_state_e; + +inline void ngx_mail_set_imap_parse_state_start(ngx_mail_session_t * s) { + s->state = swi_start; +} + +inline void ngx_mail_set_pop3_parse_state_start(ngx_mail_session_t * s) { + s->state = swp_start; +} + +inline void ngx_mail_set_smtp_parse_state_start(ngx_mail_session_t * s) { + s->state = sws_start; +} + +inline void ngx_mail_set_imap_parse_state_argument(ngx_mail_session_t * s) { + s->state = swi_argument; +} + +inline void ngx_mail_set_pop3_parse_state_argument(ngx_mail_session_t * s) { + s->state = swp_argument; +} + +inline void ngx_mail_set_smtp_parse_state_argument(ngx_mail_session_t * s) { + s->state = sws_argument; +} + +inline void ngx_mail_reset_parse_buffer(ngx_mail_session_t * s) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; +} ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s) { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_pop3_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -34,7 +87,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (state) { /* POP3 command */ - case sw_start: + case swp_start: if (ch == ' ' || ch == CR || ch == LF) { c = s->buffer->start; @@ -87,10 +140,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -104,12 +157,12 @@ ngx_mail_pop3_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swp_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = swp_almost_done; s->arg_end = p; break; case LF: @@ -117,7 +170,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 2) { - state = sw_argument; + state = swp_argument; s->arg_start = p; break; } @@ -125,7 +178,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_argument: + case swp_argument: switch (ch) { case ' ': @@ -155,10 +208,10 @@ ngx_mail_pop3_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = swp_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swp_almost_done; break; case LF: goto done; @@ -170,7 +223,7 @@ ngx_mail_pop3_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case swp_almost_done: switch (ch) { case LF: goto done; @@ -199,13 +252,11 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_POP3_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swp_start; s->arg_start = NULL; return NGX_MAIL_PARSE_INVALID_COMMAND; @@ -217,22 +268,8 @@ ngx_mail_imap_parse_command(ngx_mail_ses { u_char ch, *p, *c; ngx_str_t *arg; - enum { - sw_start = 0, - sw_spaces_before_command, - sw_command, - sw_spaces_before_argument, - sw_argument, - sw_backslash, - sw_literal, - sw_no_sync_literal_argument, - sw_start_literal_argument, - sw_literal_argument, - sw_end_literal_argument, - sw_almost_done - } state; - - state = s->state; + p = NULL; + ngx_imap_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -240,40 +277,41 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (state) { /* IMAP tag */ - case sw_start: + case swi_start: switch (ch) { case ' ': - s->tag.len = p - s->buffer->start + 1; + s->tag.len = p - s->buffer->start; s->tag.data = s->buffer->start; - state = sw_spaces_before_command; + state = swi_spaces_before_command; + s->eargs = 0; break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->tag.len = p - s->buffer->start; + s->tag.data = s->buffer->start; + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; } break; - case sw_spaces_before_command: + case swi_spaces_before_command: switch (ch) { case ' ': break; - case CR: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; - case LF: - s->state = sw_start; - return NGX_MAIL_PARSE_INVALID_COMMAND; + case CR: /* walk through */ + case LF: /* walk through */ + case '\x0': + s->state = swi_start; + return NGX_MAIL_PARSE_INVALID_COMMAND; default: s->cmd_start = p; - state = sw_command; + state = swi_command; break; } break; - case sw_command: + case swi_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -287,7 +325,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[3] == 'P'|| c[3] == 'p')) { s->command = NGX_IMAP_NOOP; - + s->eargs = 0; } else { goto invalid; } @@ -301,7 +339,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[4] == 'N'|| c[4] == 'n')) { s->command = NGX_IMAP_LOGIN; - + s->eargs = 2; } else { goto invalid; } @@ -316,7 +354,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[5] == 'T'|| c[5] == 't')) { s->command = NGX_IMAP_LOGOUT; - + s->eargs = 0; } else { goto invalid; } @@ -334,7 +372,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[7] == 'S'|| c[7] == 's')) { s->command = NGX_IMAP_STARTTLS; - + s->eargs = 0; } else { goto invalid; } @@ -354,7 +392,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[9] == 'Y'|| c[9] == 'y')) { s->command = NGX_IMAP_CAPABILITY; - + s->eargs = 0; } else { goto invalid; } @@ -374,8 +412,12 @@ ngx_mail_imap_parse_command(ngx_mail_ses && (c[10] == 'T'|| c[10] == 't') && (c[11] == 'E'|| c[11] == 'e')) { - s->command = NGX_IMAP_AUTHENTICATE; - + if (ch != ' ') { + goto invalid; + } else { + s->command = NGX_IMAP_AUTHENTICATE; + s->eargs = 1; + } } else { goto invalid; } @@ -387,10 +429,13 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + if (s->command == NGX_IMAP_CAPABILITY) { + goto invalid; + } + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -404,42 +449,48 @@ ngx_mail_imap_parse_command(ngx_mail_ses break; - case sw_spaces_before_argument: + case swi_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + if (s->args.nelts == 0) { + goto invalid; /* no argument */ + } + state = swi_almost_done; s->arg_end = p; break; case LF: + if ( s->args.nelts == 0) { + goto invalid; /* no argument */ + } s->arg_end = p; goto done; case '"': - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->quoted = 1; s->arg_start = p + 1; - state = sw_argument; + state = swi_argument; break; } goto invalid; case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; default: - if (s->args.nelts <= 2) { + if (s->args.nelts <= s->eargs) { s->arg_start = p; - state = sw_argument; + state = swi_argument; break; } goto invalid; } break; - case sw_argument: + case swi_argument: if (ch == ' ' && s->quoted) { break; } @@ -465,10 +516,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses switch (ch) { case '"': case ' ': - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; @@ -477,46 +528,52 @@ ngx_mail_imap_parse_command(ngx_mail_ses case '\\': if (s->quoted) { s->backslash = 1; - state = sw_backslash; + state = swi_backslash; } break; } break; - case sw_backslash: + case swi_backslash: switch (ch) { case CR: case LF: goto invalid; + case '\\': + case '"': + /* (RFC3501) + a backslash may only escape another backslash, or a double quote */ + state = swi_argument; + break; default: - state = sw_argument; + goto invalid; } break; - case sw_literal: + case swi_literal: if (ch >= '0' && ch <= '9') { s->literal_len = s->literal_len * 10 + (ch - '0'); break; } if (ch == '}') { - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } if (ch == '+') { - state = sw_no_sync_literal_argument; + state = swi_no_sync_literal_argument; break; } goto invalid; - case sw_no_sync_literal_argument: + case swi_no_sync_literal_argument: if (ch == '}') { s->no_sync_literal = 1; - state = sw_start_literal_argument; + state = swi_start_literal_argument; break; } goto invalid; - case sw_start_literal_argument: + case swi_start_literal_argument: switch (ch) { case CR: break; @@ -524,10 +581,10 @@ ngx_mail_imap_parse_command(ngx_mail_ses s->buffer->pos = p + 1; s->arg_start = p + 1; if (s->no_sync_literal == 0) { - s->state = sw_literal_argument; + s->state = swi_literal_argument; return NGX_IMAP_NEXT; } - state = sw_literal_argument; + state = swi_literal_argument; s->no_sync_literal = 0; break; default: @@ -535,7 +592,7 @@ ngx_mail_imap_parse_command(ngx_mail_ses } break; - case sw_literal_argument: + case swi_literal_argument: if (s->literal_len && --s->literal_len) { break; } @@ -547,36 +604,39 @@ ngx_mail_imap_parse_command(ngx_mail_ses arg->len = p + 1 - s->arg_start; arg->data = s->arg_start; s->arg_start = NULL; - state = sw_end_literal_argument; + state = swi_end_literal_argument; break; - case sw_end_literal_argument: + case swi_end_literal_argument: switch (ch) { case '{': - if (s->args.nelts <= 2) { - state = sw_literal; + if (s->args.nelts <= s->eargs) { + state = swi_literal; break; } goto invalid; case CR: - state = sw_almost_done; + state = swi_almost_done; break; case LF: goto done; default: - state = sw_spaces_before_argument; + state = swi_spaces_before_argument; break; } break; - case sw_almost_done: + case swi_almost_done: switch (ch) { case LF: goto done; default: goto invalid; } + + default: + break; /* for avoid warning only */ } } @@ -604,13 +664,11 @@ done: s->literal_len = 0; } - s->state = (s->command != NGX_IMAP_AUTHENTICATE) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_start; + s->state = swi_start; s->quoted = 0; s->no_sync_literal = 0; s->literal_len = 0; @@ -624,16 +682,8 @@ ngx_mail_smtp_parse_command(ngx_mail_ses { u_char ch, *p, *c, c0, c1, c2, c3; ngx_str_t *arg; - enum { - sw_start = 0, - sw_command, - sw_invalid, - sw_spaces_before_argument, - sw_argument, - sw_almost_done - } state; - state = s->state; + ngx_smtp_parse_state_e state = s->state; for (p = s->buffer->pos; p < s->buffer->last; p++) { ch = *p; @@ -641,13 +691,13 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (state) { /* SMTP command */ - case sw_start: + case sws_start: s->cmd_start = p; - state = sw_command; + state = sws_command; /* fall through */ - case sw_command: + case sws_command: if (ch == ' ' || ch == CR || ch == LF) { c = s->cmd_start; @@ -732,10 +782,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -749,15 +799,15 @@ ngx_mail_smtp_parse_command(ngx_mail_ses break; - case sw_invalid: + case sws_invalid: goto invalid; - case sw_spaces_before_argument: + case sws_spaces_before_argument: switch (ch) { case ' ': break; case CR: - state = sw_almost_done; + state = sws_almost_done; s->arg_end = p; break; case LF: @@ -765,7 +815,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses goto done; default: if (s->args.nelts <= 10) { - state = sw_argument; + state = sws_argument; s->arg_start = p; break; } @@ -773,7 +823,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_argument: + case sws_argument: switch (ch) { case ' ': case CR: @@ -788,10 +838,10 @@ ngx_mail_smtp_parse_command(ngx_mail_ses switch (ch) { case ' ': - state = sw_spaces_before_argument; + state = sws_spaces_before_argument; break; case CR: - state = sw_almost_done; + state = sws_almost_done; break; case LF: goto done; @@ -803,7 +853,7 @@ ngx_mail_smtp_parse_command(ngx_mail_ses } break; - case sw_almost_done: + case sws_almost_done: switch (ch) { case LF: goto done; @@ -832,20 +882,18 @@ done: s->arg_start = NULL; } - s->state = (s->command != NGX_SMTP_AUTH) ? sw_start : sw_argument; - return NGX_OK; invalid: - s->state = sw_invalid; + s->state = sws_invalid; s->arg_start = NULL; /* skip invalid command till LF */ for (p = s->buffer->pos; p < s->buffer->last; p++) { if (*p == LF) { - s->state = sw_start; + s->state = sws_start; p++; break; } @@ -882,7 +930,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_LOGIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return NGX_MAIL_AUTH_LOGIN_USERNAME; } @@ -895,7 +943,7 @@ ngx_mail_auth_parse(ngx_mail_session_t * return NGX_MAIL_AUTH_PLAIN; } - if (s->args.nelts == 2) { + if (s->args.nelts == 2) { /* initial response */ return ngx_mail_auth_plain(s, c, 1); } } @@ -914,5 +962,5 @@ ngx_mail_auth_parse(ngx_mail_session_t * } } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; } diff -r 65988e6762de -r dfc11aa2a98e src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:24:16 2014 -0500 +++ b/src/mail/ngx_mail_pop3_handler.c Wed Sep 17 15:42:10 2014 -0500 @@ -27,7 +27,11 @@ static u_char pop3_next[] = "+ " CRLF; static u_char pop3_username[] = "+ VXNlcm5hbWU6" CRLF; static u_char pop3_password[] = "+ UGFzc3dvcmQ6" CRLF; static u_char pop3_invalid_command[] = "-ERR invalid command" CRLF; - +static u_char pop3_unsupported_mech[] = "-ERR mechanism not supported" CRLF; +static u_char pop3_nocleartext[] = "-ERR cleartext logins disabled" CRLF; +static u_char pop3_authaborted[] = "-ERR authentication aborted" CRLF; +static u_char pop3_login_failed[] = "-ERR invalid username/password" CRLF; +static u_char pop3_auth_failed[] = "-ERR line is too long" CRLF; void ngx_mail_pop3_init_session(ngx_mail_session_t *s, ngx_connection_t *c) @@ -109,6 +113,7 @@ ngx_mail_pop3_init_protocol(ngx_event_t } } + ngx_mail_set_pop3_parse_state_start(s); s->mail_state = ngx_pop3_start; c->read->handler = ngx_mail_pop3_auth_state; @@ -249,30 +254,63 @@ ngx_mail_pop3_auth_state(ngx_event_t *re ngx_mail_auth(s, c); return; + case NGX_OK: + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_ABORT: + ngx_str_set(&s->out, pop3_authaborted); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_ERROR: ngx_mail_session_internal_server_error(s); return; + case NGX_MAIL_LOGIN_FAILED: + ngx_str_set(&s->out, pop3_login_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_AUTH_FAILED: + ngx_str_set(&s->out, pop3_auth_failed); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + + case NGX_MAIL_PARSE_INVALID_AUTH_MECH: + ngx_log_debug0 (NGX_LOG_DEBUG_MAIL, c->log, 0, + "unsupported POP auth mechanism"); + ngx_str_set(&s->out, pop3_unsupported_mech); + s->mail_state = ngx_pop3_start; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; + case NGX_MAIL_PARSE_INVALID_COMMAND: + ngx_str_set(&s->out, pop3_invalid_command); s->mail_state = ngx_pop3_start; - s->state = 0; + s->arg_start = NULL; + ngx_mail_set_pop3_parse_state_start(s); + break; - ngx_str_set(&s->out, pop3_invalid_command); + case NGX_MAIL_AUTH_ARGUMENT: + s->arg_start = s->buffer->start; + ngx_mail_set_pop3_parse_state_argument(s); + break; - /* fall through */ + } - case NGX_OK: + s->args.nelts = 0; + ngx_mail_reset_parse_buffer(s); - s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; - - if (s->state) { - s->arg_start = s->buffer->start; - } - - ngx_mail_send(c->write); - } + ngx_mail_send(c->write); } static ngx_int_t @@ -282,6 +320,7 @@ ngx_mail_pop3_user(ngx_mail_session_t *s #if (NGX_MAIL_SSL) if (ngx_mail_starttls_only(s, c)) { + ngx_str_set(&s->out, pop3_nocleartext); return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -451,10 +490,7 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module); if (s->args.nelts == 0) { - s->out = pscf->auth_capability; - s->state = 0; - - return NGX_OK; + return NGX_MAIL_PARSE_INVALID_COMMAND; } rc = ngx_mail_auth_parse(s, c); @@ -463,6 +499,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_username); s->mail_state = ngx_pop3_auth_login_username; @@ -470,6 +509,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_LOGIN_USERNAME: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_LOGIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_password); s->mail_state = ngx_pop3_auth_login_password; @@ -477,6 +519,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s case NGX_MAIL_AUTH_PLAIN: + if (!(pscf->auth_methods & NGX_MAIL_AUTH_PLAIN_ENABLED)) { + return NGX_MAIL_PARSE_INVALID_AUTH_MECH; + } ngx_str_set(&s->out, pop3_next); s->mail_state = ngx_pop3_auth_plain; @@ -494,6 +539,9 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s } return NGX_ERROR; + + default: + break; } return rc; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel