# HG changeset patch # User Igor Sysoev # Date 1189718667 0 # Node ID 2647950e047fafa501ba00580a153e35ef8787f4 # Parent d0cce8369848ce8bc9a30a79d15f5159c599e1f2 optimizations diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -313,6 +313,7 @@ typedef ngx_int_t (*ngx_mail_parse_comma #if (NGX_MAIL_SSL) void ngx_mail_starttls_handler(ngx_event_t *rev); +ngx_int_t ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c); #endif @@ -330,6 +331,8 @@ ngx_int_t ngx_mail_auth_login_username(n ngx_connection_t *c); ngx_int_t ngx_mail_auth_login_password(ngx_mail_session_t *s, ngx_connection_t *c); +ngx_int_t ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, + ngx_connection_t *c, char *prefix, size_t len); ngx_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c); void ngx_mail_send(ngx_event_t *wev); @@ -351,6 +354,7 @@ void ngx_mail_smtp_init_protocol(ngx_eve ngx_int_t ngx_mail_pop3_parse_command(ngx_mail_session_t *s); ngx_int_t ngx_mail_imap_parse_command(ngx_mail_session_t *s); ngx_int_t ngx_mail_smtp_parse_command(ngx_mail_session_t *s); +ngx_int_t ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c); /* STUB */ diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -285,6 +285,29 @@ ngx_mail_salt(ngx_mail_session_t *s, ngx } +#if (NGX_MAIL_SSL) + +ngx_int_t +ngx_mail_starttls_only(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_mail_ssl_conf_t *sslcf; + + if (c->ssl) { + return 0; + } + + sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); + + if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { + return 1; + } + + return 0; +} + +#endif + + ngx_int_t ngx_mail_auth_plain(ngx_mail_session_t *s, ngx_connection_t *c, ngx_uint_t n) { @@ -405,6 +428,35 @@ ngx_mail_auth_login_password(ngx_mail_se ngx_int_t +ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c, + char *prefix, size_t len) +{ + u_char *p; + ngx_str_t salt; + ngx_uint_t n; + + p = ngx_palloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2); + if (p == NULL) { + return NGX_ERROR; + } + + salt.data = ngx_cpymem(p, prefix, len); + s->salt.len -= 2; + + ngx_encode_base64(&salt, &s->salt); + + s->salt.len += 2; + n = len + salt.len; + p[n++] = CR; p[n++] = LF; + + s->out.len = n; + s->out.data = p; + + return NGX_OK; +} + + +ngx_int_t ngx_mail_auth_cram_md5(ngx_mail_session_t *s, ngx_connection_t *c) { u_char *p, *last; diff --git a/src/mail/ngx_mail_imap_handler.c b/src/mail/ngx_mail_imap_handler.c --- a/src/mail/ngx_mail_imap_handler.c +++ b/src/mail/ngx_mail_imap_handler.c @@ -177,11 +177,7 @@ ngx_mail_imap_auth_state(ngx_event_t *re case NGX_IMAP_AUTHENTICATE: rc = ngx_mail_imap_authenticate(s, c); - - if (rc == NGX_OK) { - tag = 0; - } - + tag = (rc != NGX_OK); break; case NGX_IMAP_CAPABILITY: @@ -307,15 +303,10 @@ static ngx_int_t ngx_mail_imap_login(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_str_t *arg; + #if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif @@ -357,53 +348,36 @@ 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) { - u_char *p; - ngx_str_t *arg, salt; - ngx_uint_t n; + ngx_int_t rc; ngx_mail_core_srv_conf_t *cscf; -#if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } #endif - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + rc = ngx_mail_auth_parse(s, c); - arg = s->args.elts; - - if (arg[0].len == 5) { + switch (rc) { - if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { + case NGX_MAIL_AUTH_LOGIN: - s->out.len = sizeof(imap_username) - 1; - s->out.data = imap_username; - s->mail_state = ngx_imap_auth_login_username; - - return NGX_OK; + s->out.len = sizeof(imap_username) - 1; + s->out.data = imap_username; + s->mail_state = ngx_imap_auth_login_username; - } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { + return NGX_OK; - s->out.len = sizeof(imap_plain_next) - 1; - s->out.data = imap_plain_next; - s->mail_state = ngx_imap_auth_plain; + case NGX_MAIL_AUTH_PLAIN: - return NGX_OK; - } + s->out.len = sizeof(imap_plain_next) - 1; + s->out.data = imap_plain_next; + s->mail_state = ngx_imap_auth_plain; - } else if (arg[0].len == 8 - && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) - { - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + return NGX_OK; + + case NGX_MAIL_AUTH_CRAM_MD5: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -411,31 +385,15 @@ ngx_mail_imap_authenticate(ngx_mail_sess return NGX_MAIL_PARSE_INVALID_COMMAND; } - p = ngx_palloc(c->pool, - sizeof("+ " CRLF) - 1 - + ngx_base64_encoded_length(s->salt.len)); - if (p == NULL) { - return NGX_ERROR; + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) { + s->mail_state = ngx_imap_auth_cram_md5; + return NGX_OK; } - p[0] = '+'; p[1]= ' '; - salt.data = &p[2]; - s->salt.len -= 2; - - ngx_encode_base64(&salt, &s->salt); - - s->salt.len += 2; - n = 2 + salt.len; - p[n++] = CR; p[n++] = LF; - - s->out.len = n; - s->out.data = p; - s->mail_state = ngx_imap_auth_cram_md5; - - return NGX_OK; + return NGX_ERROR; } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return rc; } diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c --- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -825,3 +825,56 @@ invalid: return NGX_MAIL_PARSE_INVALID_COMMAND; } + + +ngx_int_t +ngx_mail_auth_parse(ngx_mail_session_t *s, ngx_connection_t *c) +{ + ngx_str_t *arg; + +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } +#endif + + arg = s->args.elts; + + if (arg[0].len == 5) { + + if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { + + if (s->args.nelts == 1) { + return NGX_MAIL_AUTH_LOGIN; + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { + + if (s->args.nelts == 1) { + return NGX_MAIL_AUTH_PLAIN; + } + + if (s->args.nelts == 2) { + return ngx_mail_auth_plain(s, c, 1); + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (arg[0].len == 8) { + + if (s->args.nelts != 1) { + return NGX_MAIL_PARSE_INVALID_COMMAND; + } + + if (ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) { + return NGX_MAIL_AUTH_CRAM_MD5; + } + } + + return NGX_MAIL_PARSE_INVALID_COMMAND; +} diff --git a/src/mail/ngx_mail_pop3_handler.c b/src/mail/ngx_mail_pop3_handler.c --- a/src/mail/ngx_mail_pop3_handler.c +++ b/src/mail/ngx_mail_pop3_handler.c @@ -275,17 +275,11 @@ static ngx_int_t ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c) { ngx_str_t *arg; + #if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } - #endif if (s->args.nelts != 1) { @@ -395,17 +389,11 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s { ngx_str_t *arg; ngx_mail_core_srv_conf_t *cscf; + #if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } - #endif if (s->args.nelts != 2) { @@ -448,21 +436,13 @@ ngx_mail_pop3_apop(ngx_mail_session_t *s static ngx_int_t ngx_mail_pop3_auth(ngx_mail_session_t *s, ngx_connection_t *c) { - size_t n; - u_char *p; - ngx_str_t *arg, salt; + ngx_int_t rc; ngx_mail_core_srv_conf_t *cscf; -#if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } - #endif cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -474,80 +454,39 @@ ngx_mail_pop3_auth(ngx_mail_session_t *s return NGX_OK; } - arg = s->args.elts; - - if (arg[0].len == 5) { + rc = ngx_mail_auth_parse(s, c); - if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { - - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + switch (rc) { - s->out.len = sizeof(pop3_username) - 1; - s->out.data = pop3_username; - s->mail_state = ngx_pop3_auth_login_username; + case NGX_MAIL_AUTH_LOGIN: - return NGX_OK; - - } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { - - if (s->args.nelts == 1) { + s->out.len = sizeof(pop3_username) - 1; + s->out.data = pop3_username; + s->mail_state = ngx_pop3_auth_login_username; - s->out.len = sizeof(pop3_next) - 1; - s->out.data = pop3_next; - s->mail_state = ngx_pop3_auth_plain; + return NGX_OK; - return NGX_OK; - } - - if (s->args.nelts == 2) { + case NGX_MAIL_AUTH_PLAIN: - /* - * workaround for Eudora for Mac: it sends - * AUTH PLAIN [base64 encoded] - */ - - return ngx_mail_auth_plain(s, c, 1); - } + s->out.len = sizeof(pop3_next) - 1; + s->out.data = pop3_next; + s->mail_state = ngx_pop3_auth_plain; - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + return NGX_OK; - } else if (arg[0].len == 8 - && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) - { - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + case NGX_MAIL_AUTH_CRAM_MD5: if (!(cscf->pop3_auth_methods & NGX_MAIL_AUTH_CRAM_MD5_ENABLED)) { return NGX_MAIL_PARSE_INVALID_COMMAND; } - p = ngx_palloc(c->pool, - sizeof("+ " CRLF) - 1 - + ngx_base64_encoded_length(s->salt.len)); - if (p == NULL) { - return NGX_ERROR; + if (ngx_mail_auth_cram_md5_salt(s, c, "+ ", 2) == NGX_OK) { + s->mail_state = ngx_pop3_auth_cram_md5; + return NGX_OK; } - p[0] = '+'; p[1]= ' '; - salt.data = &p[2]; - s->salt.len -= 2; - - ngx_encode_base64(&salt, &s->salt); - - s->salt.len += 2; - n = 2 + salt.len; - p[n++] = CR; p[n++] = LF; - - s->out.len = n; - s->out.data = p; - s->mail_state = ngx_pop3_auth_cram_md5; - - return NGX_OK; + return NGX_ERROR; } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return rc; } diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -284,21 +284,13 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s static ngx_int_t ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) { - u_char *p; - ngx_str_t *arg, salt; - ngx_uint_t n; + ngx_int_t rc; ngx_mail_core_srv_conf_t *cscf; -#if (NGX_MAIL_SSL) - ngx_mail_ssl_conf_t *sslcf; - if (c->ssl == NULL) { - sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module); - - if (sslcf->starttls == NGX_MAIL_STARTTLS_ONLY) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } +#if (NGX_MAIL_SSL) + if (ngx_mail_starttls_only(s, c)) { + return NGX_MAIL_PARSE_INVALID_COMMAND; } - #endif if (s->args.nelts == 0) { @@ -308,41 +300,27 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s return NGX_OK; } - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + rc = ngx_mail_auth_parse(s, c); - arg = s->args.elts; - - if (arg[0].len == 5) { + switch (rc) { - if (ngx_strncasecmp(arg[0].data, (u_char *) "LOGIN", 5) == 0) { + case NGX_MAIL_AUTH_LOGIN: - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } - - s->out.len = sizeof(smtp_username) - 1; - s->out.data = smtp_username; - s->mail_state = ngx_smtp_auth_login_username; + s->out.len = sizeof(smtp_username) - 1; + s->out.data = smtp_username; + s->mail_state = ngx_smtp_auth_login_username; - return NGX_OK; - - } else if (ngx_strncasecmp(arg[0].data, (u_char *) "PLAIN", 5) == 0) { + return NGX_OK; - s->out.len = sizeof(smtp_next) - 1; - s->out.data = smtp_next; - s->mail_state = ngx_smtp_auth_plain; + case NGX_MAIL_AUTH_PLAIN: - return NGX_OK; - } + s->out.len = sizeof(smtp_next) - 1; + s->out.data = smtp_next; + s->mail_state = ngx_smtp_auth_plain; - } else if (arg[0].len == 8 - && ngx_strncasecmp(arg[0].data, (u_char *) "CRAM-MD5", 8) == 0) - { - if (s->args.nelts != 1) { - return NGX_MAIL_PARSE_INVALID_COMMAND; - } + return NGX_OK; + + case NGX_MAIL_AUTH_CRAM_MD5: cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -350,31 +328,15 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s return NGX_MAIL_PARSE_INVALID_COMMAND; } - p = ngx_palloc(c->pool, - sizeof("334 " CRLF) - 1 - + ngx_base64_encoded_length(s->salt.len)); - if (p == NULL) { - return NGX_ERROR; + if (ngx_mail_auth_cram_md5_salt(s, c, "334 ", 4) == NGX_OK) { + s->mail_state = ngx_smtp_auth_cram_md5; + return NGX_OK; } - p[0] = '3'; p[1]= '3'; p[2] = '4'; p[3]= ' '; - salt.data = &p[4]; - s->salt.len -= 2; - - ngx_encode_base64(&salt, &s->salt); - - s->salt.len += 2; - n = 4 + salt.len; - p[n++] = CR; p[n++] = LF; - - s->out.len = n; - s->out.data = p; - s->mail_state = ngx_smtp_auth_cram_md5; - - return NGX_OK; + return NGX_ERROR; } - return NGX_MAIL_PARSE_INVALID_COMMAND; + return rc; }