# HG changeset patch # User Igor Sysoev # Date 1165784400 -10800 # Node ID e0b1d0a6c629e83ca048f22049fa75fb3f5b9f6c # Parent e6ae240d59526b3e2eb0ec289b54f6153e4375e5 nginx 0.5.1 *) Bugfix: the "post_action" directive might not run after a unsuccessful completion of a request. *) Workaround: for Eudora for Mac; bug appeared in 0.4.11. Thanks to Bron Gondwana. *) Bugfix: if the "upstream" name was used in the "fastcgi_pass", then the message "no port in upstream" was issued; bug appeared in 0.5.0. *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the same servers but different ports, then these directives uses the first described port; bug appeared in 0.5.0. *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the unix domain sockets, then these directives used first described socket; bug appeared in 0.5.0. *) Bugfix: ngx_http_auth_basic_module ignored the user if it was in the last line in the password file and there was no the carriage return, the line feed, or the ":" symbol after the password. *) Bugfix: the $upstream_response_time variable might be equal to "0.000", although response time was more than 1 millisecond. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,31 @@ +Changes with nginx 0.5.1 11 Dec 2006 + + *) Bugfix: the "post_action" directive might not run after a + unsuccessful completion of a request. + + *) Workaround: for Eudora for Mac; bug appeared in 0.4.11. + Thanks to Bron Gondwana. + + *) Bugfix: if the "upstream" name was used in the "fastcgi_pass", then + the message "no port in upstream" was issued; bug appeared in 0.5.0. + + *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the + same servers but different ports, then these directives uses the + first described port; bug appeared in 0.5.0. + + *) Bugfix: if the "proxy_pass" and "fastcgi_pass" directives used the + unix domain sockets, then these directives used first described + socket; bug appeared in 0.5.0. + + *) Bugfix: ngx_http_auth_basic_module ignored the user if it was in the + last line in the password file and there was no the carriage return, + the line feed, or the ":" symbol after the password. + + *) Bugfix: the $upstream_response_time variable might be equal to + "0.000", although response time was more than 1 millisecond. + + Changes with nginx 0.5.0 04 Dec 2006 *) Change: the parameters in the "%name" form in the "log_format" diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,34 @@ +Изменения в nginx 0.5.1 11.12.2006 + + *) Исправление: директива post_action могла не работать после + неудачного завершения запроса. + + *) Изменение: обход ошибки в Eudora для Mac; ошибка появилась в + 0.4.11. + Спасибо Bron Gondwana. + + *) Исправление: при указании в директиве fastcgi_pass имени описанного + upstream'а выдавалось сообщение "no port in upstream"; ошибка + появилась в 0.5.0. + + *) Исправление: если в директивах proxy_pass и fastcgi_pass + использовались одинаковых имена серверов, но с разными портами, то + эти директивы использовали первый описанный порт; ошибка появилась в + 0.5.0. + + *) Исправление: если в директивах proxy_pass и fastcgi_pass + использовались unix domain сокеты, то эти директивы использовали + первый описанный сокет; ошибка появилась в 0.5.0. + + *) Исправление: ngx_http_auth_basic_module игнорировал пользователя, + если он был указан в последней строке файла паролей и после пароля + не было перевода строки, возврата каретки или символа ":". + + *) Исправление: переменная $upstream_response_time могла быть равна + "0.000", хотя время обработки было больше 1 миллисекунды. + + Изменения в nginx 0.5.0 04.12.2006 *) Изменение: параметры в виде "%name" в директиве log_format больше не diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.5.0" +#define NGINX_VERSION "0.5.1" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -287,6 +287,9 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t u->addrs[0].name.len = len + 5; u->addrs[0].name.data = u->url.data; + u->host.len = len; + u->host.data = p; + u->host_header.len = sizeof("localhost") - 1; u->host_header.data = (u_char *) "localhost"; diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -70,12 +70,6 @@ ngx_time_update(time_t sec, ngx_uint_t m return; } - if (slot == NGX_TIME_SLOTS) { - slot = 0; - } else { - slot++; - } - if (sec == 0) { ngx_gettimeofday(&tv); @@ -87,14 +81,22 @@ ngx_time_update(time_t sec, ngx_uint_t m tp = &cached_time[slot]; - tp->msec = msec; - if (tp->sec == sec) { + tp->msec = msec; ngx_unlock(&ngx_time_lock); return; } + if (slot == NGX_TIME_SLOTS) { + slot = 0; + } else { + slot++; + } + + tp = &cached_time[slot]; + tp->sec = sec; + tp->msec = msec; ngx_gmtime(sec, &gmt); diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -154,6 +154,8 @@ ngx_http_auth_basic_handler(ngx_http_req offset = 0; for ( ;; ) { + i = left; + n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left, offset); @@ -228,6 +230,18 @@ ngx_http_auth_basic_handler(ngx_http_req ngx_http_auth_basic_close(&file); + if (state == sw_passwd) { + pwd.len = i - passwd; + pwd.data = ngx_palloc(r->pool, pwd.len + 1); + if (pwd.data == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1); + + return ngx_http_auth_basic_crypt_handler(r, NULL, &pwd, &alcf->realm); + } + return ngx_http_auth_basic_set_realm(r, &alcf->realm); } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2010,6 +2010,7 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ng ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; + u.upstream = 1; u.no_resolve = 1; lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -583,6 +583,7 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; + u.upstream = 1; u.no_resolve = 1; /* u.uri_part = 1; may be used as namespace */ diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2159,6 +2159,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_ u.url.len = url->len - add; u.url.data = url->data + add; u.default_portn = port; + u.upstream = 1; u.no_resolve = 1; u.uri_part = 1; diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -17,7 +17,7 @@ our @EXPORT = qw( HTTP_SERVER_ERROR ); -our $VERSION = '0.5.0'; +our $VERSION = '0.5.1'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -2247,6 +2247,8 @@ ngx_http_post_action(ngx_http_request_t r->header_only = 1; r->post_action = 1; + r->read_event_handler = ngx_http_block_read; + ngx_http_internal_redirect(r, &clcf->post_action, NULL); return NGX_OK; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -493,17 +493,16 @@ ngx_http_upstream_connect(ngx_http_reque { ngx_int_t rc; ngx_time_t *tp; - ngx_msec_int_t ms; ngx_connection_t *c; r->connection->log->action = "connecting to upstream"; r->connection->single_connection = 0; - if (u->state && u->state->response_time) { + if (u->state && u->state->response_sec) { tp = ngx_timeofday(); - ms = tp->sec * 1000 + tp->msec - u->state->response_time; - u->state->response_time = (ms >= 0) ? ms : 0; + u->state->response_sec = tp->sec - u->state->response_sec; + u->state->response_msec = tp->msec - u->state->response_msec; } u->state = ngx_array_push(&u->states); @@ -516,7 +515,8 @@ ngx_http_upstream_connect(ngx_http_reque ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); tp = ngx_timeofday(); - u->state->response_time = tp->sec * 1000 + tp->msec; + u->state->response_sec = tp->sec; + u->state->response_msec = tp->msec; rc = ngx_event_connect_peer(&u->peer); @@ -2043,18 +2043,17 @@ static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_int_t rc) { - ngx_time_t *tp; - ngx_msec_int_t ms; + ngx_time_t *tp; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "finalize http upstream request: %i", rc); *u->cleanup = NULL; - if (u->state->response_time) { + if (u->state->response_sec) { tp = ngx_timeofday(); - ms = tp->sec * 1000 + tp->msec - u->state->response_time; - u->state->response_time = (ms >= 0) ? ms : 0; + u->state->response_sec = tp->sec - u->state->response_sec; + u->state->response_msec = tp->msec - u->state->response_msec; } u->finalize_request(r, rc); @@ -2531,6 +2530,7 @@ ngx_http_upstream_response_time_variable u_char *p; size_t len; ngx_uint_t i; + ngx_msec_int_t ms; ngx_http_upstream_t *u; ngx_http_upstream_state_t *state; @@ -2562,9 +2562,9 @@ ngx_http_upstream_response_time_variable *p++ = '-'; } else { - p = ngx_sprintf(p, "%d.%03d", - state[i].response_time / 1000, - state[i].response_time % 1000); + ms = state[i].response_sec * 1000 + state[i].response_msec; + ms = (ms >= 0) ? ms : 0; + p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000); } if (++i == u->states.nelts) { @@ -2843,7 +2843,8 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { - if (uscfp[i]->host.len != u->host.len + if (uscfp[i]->port != u->portn + || uscfp[i]->host.len != u->host.len || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) != 0) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -35,7 +35,8 @@ typedef struct { ngx_uint_t bl_state; ngx_uint_t status; - ngx_msec_t response_time; + time_t response_sec; + ngx_uint_t response_msec; ngx_str_t *peer; } ngx_http_upstream_state_t; diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -69,13 +69,20 @@ ngx_http_upstream_init_round_robin(ngx_c if (ngx_inet_resolve_host(cf, &u) != NGX_OK) { if (u.err) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "%s in upstream host \"%V\" is not found in %s:%ui", + "%s in upstream \"%V\" in %s:%ui", u.err, &us->host, us->file_name.data, us->line); } return NGX_ERROR; } + if (us->port == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "no port in upstream \"%V\" in %s:%ui", + &us->host, us->file_name.data, us->line); + return NGX_ERROR; + } + n = u.naddrs; peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_rr_peers_t) diff --git a/src/imap/ngx_imap_handler.c b/src/imap/ngx_imap_handler.c --- a/src/imap/ngx_imap_handler.c +++ b/src/imap/ngx_imap_handler.c @@ -12,6 +12,8 @@ static void ngx_imap_init_session(ngx_connection_t *c); static void ngx_imap_init_protocol(ngx_event_t *rev); +static ngx_int_t ngx_imap_decode_auth_plain(ngx_imap_session_t *s, + ngx_str_t *encoded); static void ngx_imap_do_auth(ngx_imap_session_t *s); static ngx_int_t ngx_imap_read_command(ngx_imap_session_t *s); static u_char *ngx_imap_log_error(ngx_log_t *log, u_char *buf, size_t len); @@ -660,7 +662,7 @@ ngx_pop3_auth_state(ngx_event_t *rev) u_char *text, *p, *last; ssize_t size; ngx_int_t rc; - ngx_str_t *arg, salt, plain; + ngx_str_t *arg, salt; ngx_connection_t *c; ngx_imap_session_t *s; ngx_imap_core_srv_conf_t *cscf; @@ -796,16 +798,17 @@ ngx_pop3_auth_state(ngx_event_t *rev) break; } - if (s->args.nelts != 1) { - rc = NGX_IMAP_PARSE_INVALID_COMMAND; - break; - } - arg = s->args.elts; if (arg[0].len == 5) { if (ngx_strncasecmp(arg[0].data, "LOGIN", 5) == 0) { + + if (s->args.nelts != 1) { + rc = NGX_IMAP_PARSE_INVALID_COMMAND; + break; + } + s->imap_state = ngx_pop3_auth_login_username; size = sizeof(pop3_username) - 1; @@ -814,11 +817,41 @@ ngx_pop3_auth_state(ngx_event_t *rev) break; } else if (ngx_strncasecmp(arg[0].data, "PLAIN", 5) == 0) { - s->imap_state = ngx_pop3_auth_plain; + + if (s->args.nelts == 1) { + s->imap_state = ngx_pop3_auth_plain; + + size = sizeof(pop3_next) - 1; + text = pop3_next; + + break; + } + + if (s->args.nelts == 2) { + + /* + * workaround for Eudora for Mac: it sends + * AUTH PLAIN [base64 encoded] + */ - size = sizeof(pop3_next) - 1; - text = pop3_next; + rc = ngx_imap_decode_auth_plain(s, &arg[1]); + + if (rc == NGX_OK) { + ngx_imap_do_auth(s); + return; + } + if (rc == NGX_ERROR) { + ngx_imap_session_internal_server_error(s); + return; + } + + /* rc == NGX_IMAP_PARSE_INVALID_COMMAND */ + + break; + } + + rc = NGX_IMAP_PARSE_INVALID_COMMAND; break; } @@ -999,64 +1032,21 @@ ngx_pop3_auth_state(ngx_event_t *rev) case ngx_pop3_auth_plain: arg = s->args.elts; -#if (NGX_DEBUG_IMAP_PASSWD) - ngx_log_debug1(NGX_LOG_DEBUG_IMAP, c->log, 0, - "pop3 auth plain: \"%V\"", &arg[0]); -#endif + rc = ngx_imap_decode_auth_plain(s, &arg[0]); - plain.data = ngx_palloc(c->pool, - ngx_base64_decoded_length(arg[0].len)); - if (plain.data == NULL){ + if (rc == NGX_OK) { + ngx_imap_do_auth(s); + return; + } + + if (rc == NGX_ERROR) { ngx_imap_session_internal_server_error(s); return; } - if (ngx_decode_base64(&plain, &arg[0]) != NGX_OK) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid base64 encoding " - "in AUTH PLAIN command"); - rc = NGX_IMAP_PARSE_INVALID_COMMAND; - break; - } - - p = plain.data; - last = p + plain.len; - - while (p < last && *p++) { /* void */ } - - if (p == last) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid login " - "in AUTH PLAIN command"); - rc = NGX_IMAP_PARSE_INVALID_COMMAND; - break; - } - - s->login.data = p; + /* rc == NGX_IMAP_PARSE_INVALID_COMMAND */ - while (p < last && *p) { p++; } - - if (p == last) { - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "client sent invalid password " - "in AUTH PLAIN command"); - rc = NGX_IMAP_PARSE_INVALID_COMMAND; - break; - } - - s->login.len = p++ - s->login.data; - - s->passwd.len = last - p; - s->passwd.data = p; - -#if (NGX_DEBUG_IMAP_PASSWD) - ngx_log_debug2(NGX_LOG_DEBUG_IMAP, c->log, 0, - "pop3 auth plain: \"%V\" \"%V\"", - &s->login, &s->passwd); -#endif - - ngx_imap_do_auth(s); - return; + break; case ngx_pop3_auth_cram_md5: arg = s->args.elts; @@ -1132,6 +1122,66 @@ ngx_pop3_auth_state(ngx_event_t *rev) } +static ngx_int_t +ngx_imap_decode_auth_plain(ngx_imap_session_t *s, ngx_str_t *encoded) +{ + u_char *p, *last; + ngx_str_t plain; + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug1(NGX_LOG_DEBUG_IMAP, s->connection->log, 0, + "pop3 auth plain: \"%V\"", encoded); +#endif + + plain.data = ngx_palloc(s->connection->pool, + ngx_base64_decoded_length(encoded->len)); + if (plain.data == NULL){ + return NGX_ERROR; + } + + if (ngx_decode_base64(&plain, encoded) != NGX_OK) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client sent invalid base64 encoding " + "in AUTH PLAIN command"); + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + + p = plain.data; + last = p + plain.len; + + while (p < last && *p++) { /* void */ } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client sent invalid login in AUTH PLAIN command"); + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + + s->login.data = p; + + while (p < last && *p) { p++; } + + if (p == last) { + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client sent invalid password in AUTH PLAIN command"); + return NGX_IMAP_PARSE_INVALID_COMMAND; + } + + s->login.len = p++ - s->login.data; + + s->passwd.len = last - p; + s->passwd.data = p; + +#if (NGX_DEBUG_IMAP_PASSWD) + ngx_log_debug2(NGX_LOG_DEBUG_IMAP, s->connection->log, 0, + "pop3 auth plain: \"%V\" \"%V\"", + &s->login, &s->passwd); +#endif + + return NGX_OK; +} + + static void ngx_imap_do_auth(ngx_imap_session_t *s) {