diff options
author | nginx <nginx@nginx.org> | 2013-10-01 13:59:27 +0000 |
---|---|---|
committer | Jon Kolb <jon@b0g.us> | 2013-10-01 13:59:27 +0000 |
commit | e52bddaaa90e64b2291f6e58ef1a2cff71604f6a (patch) | |
tree | 3c012324730d2c06c7f9dd7d84a4481404e894a4 | |
parent | c6e358d8a8b9773f4244cca3fb0f4dff1a93c838 (diff) | |
download | nginx-e52bddaaa90e64b2291f6e58ef1a2cff71604f6a.tar.gz |
Changes with nginx 1.5.6 01 Oct 2013v1.5.6
*) Feature: the "fastcgi_buffering" directive.
*) Feature: the "proxy_ssl_protocols" and "proxy_ssl_ciphers"
directives.
Thanks to Piotr Sikora.
*) Feature: optimization of SSL handshakes when using long certificate
chains.
*) Feature: the mail proxy supports SMTP pipelining.
*) Bugfix: in the ngx_http_auth_basic_module when using "$apr1$"
password encryption method.
Thanks to Markus Linnala.
*) Bugfix: in MacOSX, Cygwin, and nginx/Windows incorrect location might
be used to process a request if locations were given using characters
in different cases.
*) Bugfix: automatic redirect with appended trailing slash for proxied
locations might not work.
*) Bugfix: in the mail proxy server.
*) Bugfix: in the ngx_http_spdy_module.
34 files changed, 580 insertions, 148 deletions
@@ -1,4 +1,33 @@ +Changes with nginx 1.5.6 01 Oct 2013 + + *) Feature: the "fastcgi_buffering" directive. + + *) Feature: the "proxy_ssl_protocols" and "proxy_ssl_ciphers" + directives. + Thanks to Piotr Sikora. + + *) Feature: optimization of SSL handshakes when using long certificate + chains. + + *) Feature: the mail proxy supports SMTP pipelining. + + *) Bugfix: in the ngx_http_auth_basic_module when using "$apr1$" + password encryption method. + Thanks to Markus Linnala. + + *) Bugfix: in MacOSX, Cygwin, and nginx/Windows incorrect location might + be used to process a request if locations were given using characters + in different cases. + + *) Bugfix: automatic redirect with appended trailing slash for proxied + locations might not work. + + *) Bugfix: in the mail proxy server. + + *) Bugfix: in the ngx_http_spdy_module. + + Changes with nginx 1.5.5 17 Sep 2013 *) Change: now nginx assumes HTTP/1.0 by default if it is not able to diff --git a/CHANGES.ru b/CHANGES.ru index de89fa996..7beb4ebac 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,32 @@ +Изменения в nginx 1.5.6 01.10.2013 + + *) Добавление: директива fastcgi_buffering. + + *) Добавление: директивы proxy_ssl_protocols и proxy_ssl_ciphers. + Спасибо Piotr Sikora. + + *) Добавление: оптимизация SSL handshake при использовании длинных + цепочек сертификатов. + + *) Добавление: почтовый прокси-сервер поддерживает SMTP pipelining. + + *) Исправление: в модуле ngx_http_auth_basic_module при использовании + метода шифрования паролей "$apr1$". + Спасибо Markus Linnala. + + *) Исправление: на MacOSX, Cygwin и nginx/Windows для обработки запроса + мог использоваться неверный location, если для задания location'ов + использовались символы разных регистров. + + *) Исправление: автоматическое перенаправление с добавлением + завершающего слэша для проксированных location'ов могло не работать. + + *) Исправление: в почтовом прокси-сервере. + + *) Исправление: в модуле ngx_http_spdy_module. + + Изменения в nginx 1.5.5 17.09.2013 *) Изменение: теперь nginx по умолчанию использует HTTP/1.0, если точно diff --git a/auto/modules b/auto/modules index 3feaf53e1..e1eda943f 100644 --- a/auto/modules +++ b/auto/modules @@ -483,6 +483,8 @@ if [ $MAIL = YES ]; then modules="$modules $MAIL_PROXY_MODULE" MAIL_SRCS="$MAIL_SRCS $MAIL_PROXY_SRCS" + + NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(MAIL_DEPS)" fi diff --git a/conf/mime.types b/conf/mime.types index 6e3e8e00e..f63a77a55 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -26,6 +26,7 @@ types { application/font-woff woff; application/java-archive jar war ear; + application/json json; application/mac-binhex40 hqx; application/msword doc; application/pdf pdf; diff --git a/src/core/nginx.h b/src/core/nginx.h index 7117a03ad..ea6b1a87f 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1005005 -#define NGINX_VERSION "1.5.5" +#define nginx_version 1005006 +#define NGINX_VERSION "1.5.6" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_crypt.c b/src/core/ngx_crypt.c index 629d160e8..e2376c6f1 100644 --- a/src/core/ngx_crypt.c +++ b/src/core/ngx_crypt.c @@ -137,7 +137,7 @@ ngx_crypt_apr1(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) /* output */ - *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 16 + 1); + *encrypted = ngx_pnalloc(pool, sizeof("$apr1$") - 1 + saltlen + 1 + 22 + 1); if (*encrypted == NULL) { return NGX_ERROR; } diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index d3ff36855..fe6b1ee71 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -853,6 +853,46 @@ ngx_dns_strcmp(u_char *s1, u_char *s2) ngx_int_t +ngx_filename_cmp(u_char *s1, u_char *s2, size_t n) +{ + ngx_uint_t c1, c2; + + while (n) { + c1 = (ngx_uint_t) *s1++; + c2 = (ngx_uint_t) *s2++; + +#if (NGX_HAVE_CASELESS_FILESYSTEM) + c1 = tolower(c1); + c2 = tolower(c2); +#endif + + if (c1 == c2) { + + if (c1) { + n--; + continue; + } + + return 0; + } + + /* we need '/' to be the lowest character */ + + if (c1 == 0 || c2 == 0) { + return c1 - c2; + } + + c1 = (c1 == '/') ? 0 : c1; + c2 = (c2 == '/') ? 0 : c2; + + return c1 - c2; + } + + return 0; +} + + +ngx_int_t ngx_atoi(u_char *line, size_t n) { ngx_int_t value; diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 92d246ebc..99bdbda6f 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -167,6 +167,7 @@ ngx_int_t ngx_rstrncmp(u_char *s1, u_char *s2, size_t n); ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n); ngx_int_t ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2); ngx_int_t ngx_dns_strcmp(u_char *s1, u_char *s2); +ngx_int_t ngx_filename_cmp(u_char *s1, u_char *s2, size_t n); ngx_int_t ngx_atoi(u_char *line, size_t n); ngx_int_t ngx_atofp(u_char *line, size_t n, size_t point); diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index fedb604de..cd8f0e711 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -280,6 +280,8 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert, { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set_ex_data() failed"); + X509_free(x509); + BIO_free(bio); return NGX_ERROR; } @@ -519,6 +521,7 @@ ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store) static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) { + BIO *rbio, *wbio; ngx_connection_t *c; if (where & SSL_CB_HANDSHAKE_START) { @@ -529,6 +532,31 @@ ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret) ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation"); } } + + if ((where & SSL_CB_ACCEPT_LOOP) == SSL_CB_ACCEPT_LOOP) { + c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn); + + if (!c->ssl->handshake_buffer_set) { + /* + * By default OpenSSL uses 4k buffer during a handshake, + * which is too low for long certificate chains and might + * result in extra round-trips. + * + * To adjust a buffer size we detect that buffering was added + * to write side of the connection by comparing rbio and wbio. + * If they are different, we assume that it's due to buffering + * added to wbio, and set buffer size. + */ + + rbio = SSL_get_rbio(ssl_conn); + wbio = SSL_get_wbio(ssl_conn); + + if (rbio != wbio) { + (void) BIO_set_write_buffer_size(wbio, NGX_SSL_BUFSIZE); + c->ssl->handshake_buffer_set = 1; + } + } + } } diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index 790702ea8..cca01c679 100644 --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -48,6 +48,7 @@ typedef struct { unsigned buffer:1; unsigned no_wait_shutdown:1; unsigned no_send_shutdown:1; + unsigned handshake_buffer_set:1; } ngx_ssl_connection_t; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index 0b186d792..dd79418a2 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -138,6 +138,8 @@ static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r); static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data); static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf); +static ngx_int_t ngx_http_fastcgi_non_buffered_filter(void *data, + ssize_t bytes); static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f); static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r); @@ -233,6 +235,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access), NULL }, + { ngx_string("fastcgi_buffering"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffering), + NULL }, + { ngx_string("fastcgi_ignore_client_abort"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -579,13 +588,6 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r) ngx_http_fastcgi_ctx_t *f; ngx_http_fastcgi_loc_conf_t *flcf; - if (r->subrequest_in_memory) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "ngx_http_fastcgi_module does not support " - "subrequest in memory"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } @@ -622,7 +624,7 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r) u->finalize_request = ngx_http_fastcgi_finalize_request; r->state = 0; - u->buffering = 1; + u->buffering = flcf->upstream.buffering; u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t)); if (u->pipe == NULL) { @@ -633,6 +635,8 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r) u->pipe->input_ctx = r; u->input_filter_init = ngx_http_fastcgi_input_filter_init; + u->input_filter = ngx_http_fastcgi_non_buffered_filter; + u->input_filter_ctx = r; rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); @@ -1915,6 +1919,222 @@ ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) static ngx_int_t +ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes) +{ + u_char *m, *msg; + ngx_int_t rc; + ngx_buf_t *b, *buf; + ngx_chain_t *cl, **ll; + ngx_http_request_t *r; + ngx_http_upstream_t *u; + ngx_http_fastcgi_ctx_t *f; + + r = data; + f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); + + u = r->upstream; + buf = &u->buffer; + + buf->pos = buf->last; + buf->last += bytes; + + for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) { + ll = &cl->next; + } + + f->pos = buf->pos; + f->last = buf->last; + + for ( ;; ) { + if (f->state < ngx_http_fastcgi_st_data) { + + rc = ngx_http_fastcgi_process_record(r, f); + + if (rc == NGX_AGAIN) { + break; + } + + if (rc == NGX_ERROR) { + return NGX_ERROR; + } + + if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { + f->state = ngx_http_fastcgi_st_padding; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http fastcgi closed stdout"); + + continue; + } + } + + if (f->state == ngx_http_fastcgi_st_padding) { + + if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { + + if (f->pos + f->padding < f->last) { + u->length = 0; + break; + } + + if (f->pos + f->padding == f->last) { + u->length = 0; + u->keepalive = 1; + break; + } + + f->padding -= f->last - f->pos; + + break; + } + + if (f->pos + f->padding < f->last) { + f->state = ngx_http_fastcgi_st_version; + f->pos += f->padding; + + continue; + } + + if (f->pos + f->padding == f->last) { + f->state = ngx_http_fastcgi_st_version; + + break; + } + + f->padding -= f->last - f->pos; + + break; + } + + + /* f->state == ngx_http_fastcgi_st_data */ + + if (f->type == NGX_HTTP_FASTCGI_STDERR) { + + if (f->length) { + + if (f->pos == f->last) { + break; + } + + msg = f->pos; + + if (f->pos + f->length <= f->last) { + f->pos += f->length; + f->length = 0; + f->state = ngx_http_fastcgi_st_padding; + + } else { + f->length -= f->last - f->pos; + f->pos = f->last; + } + + for (m = f->pos - 1; msg < m; m--) { + if (*m != LF && *m != CR && *m != '.' && *m != ' ') { + break; + } + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "FastCGI sent in stderr: \"%*s\"", + m + 1 - msg, msg); + + } else { + f->state = ngx_http_fastcgi_st_padding; + } + + continue; + } + + if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) { + + if (f->pos + f->length <= f->last) { + f->state = ngx_http_fastcgi_st_padding; + f->pos += f->length; + + continue; + } + + f->length -= f->last - f->pos; + + break; + } + + + /* f->type == NGX_HTTP_FASTCGI_STDOUT */ + + if (f->pos == f->last) { + break; + } + + cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs); + if (cl == NULL) { + return NGX_ERROR; + } + + *ll = cl; + ll = &cl->next; + + b = cl->buf; + + b->flush = 1; + b->memory = 1; + + b->pos = f->pos; + b->tag = u->output.tag; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http fastcgi output buf %p", b->pos); + + if (f->pos + f->length <= f->last) { + f->state = ngx_http_fastcgi_st_padding; + f->pos += f->length; + b->last = f->pos; + + continue; + } + + f->length -= f->last - f->pos; + b->last = f->last; + + break; + } + + /* provide continuous buffer for subrequests in memory */ + + if (r->subrequest_in_memory) { + + cl = u->out_bufs; + + if (cl) { + buf->pos = cl->buf->pos; + } + + buf->last = buf->pos; + + for (cl = u->out_bufs; cl; cl = cl->next) { + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http fastcgi in memory %p-%p %uz", + cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf)); + + if (buf->last == cl->buf->pos) { + buf->last = cl->buf->last; + continue; + } + + buf->last = ngx_movemem(buf->last, cl->buf->pos, + cl->buf->last - cl->buf->pos); + + cl->buf->pos = buf->last - (cl->buf->last - cl->buf->pos); + cl->buf->last = buf->last; + } + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f) { @@ -2126,6 +2346,8 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) /* "fastcgi_cyclic_temp_file" is disabled */ conf->upstream.cyclic_temp_file = 0; + conf->upstream.change_buffering = 1; + conf->catch_stderr = NGX_CONF_UNSET_PTR; conf->keep_conn = NGX_CONF_UNSET; @@ -2347,12 +2569,6 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->upstream.no_cache, prev->upstream.no_cache, NULL); - if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, " - "now it should be used together with \"fastcgi_cache_bypass\""); - } - ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index f5fd83d14..cf68711cd 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -76,6 +76,12 @@ typedef struct { ngx_uint_t headers_hash_max_size; ngx_uint_t headers_hash_bucket_size; + +#if (NGX_HTTP_SSL) + ngx_uint_t ssl; + ngx_uint_t ssl_protocols; + ngx_str_t ssl_ciphers; +#endif } ngx_http_proxy_loc_conf_t; @@ -186,6 +192,20 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = { }; +#if (NGX_HTTP_SSL) + +static ngx_conf_bitmask_t ngx_http_proxy_ssl_protocols[] = { + { ngx_string("SSLv2"), NGX_SSL_SSLv2 }, + { ngx_string("SSLv3"), NGX_SSL_SSLv3 }, + { ngx_string("TLSv1"), NGX_SSL_TLSv1 }, + { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 }, + { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 }, + { ngx_null_string, 0 } +}; + +#endif + + static ngx_conf_enum_t ngx_http_proxy_http_version[] = { { ngx_string("1.0"), NGX_HTTP_VERSION_10 }, { ngx_string("1.1"), NGX_HTTP_VERSION_11 }, @@ -512,6 +532,20 @@ static ngx_command_t ngx_http_proxy_commands[] = { offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse), NULL }, + { ngx_string("proxy_ssl_protocols"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_conf_set_bitmask_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_protocols), + &ngx_http_proxy_ssl_protocols }, + + { ngx_string("proxy_ssl_ciphers"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers), + NULL }, + #endif ngx_null_command @@ -2386,6 +2420,9 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) * conf->body_set = NULL; * conf->body_source = { 0, NULL }; * conf->redirects = NULL; + * conf->ssl = 0; + * conf->ssl_protocols = 0; + * conf->ssl_ciphers = { 0, NULL }; */ conf->upstream.store = NGX_CONF_UNSET; @@ -2660,12 +2697,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_ptr_value(conf->upstream.no_cache, prev->upstream.no_cache, NULL); - if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) { - ngx_log_error(NGX_LOG_WARN, cf->log, 0, - "\"proxy_no_cache\" functionality has been changed in 0.8.46, " - "now it should be used together with \"proxy_cache_bypass\""); - } - ngx_conf_merge_ptr_value(conf->upstream.cache_valid, prev->upstream.cache_valid, NULL); @@ -2701,6 +2732,18 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) #if (NGX_HTTP_SSL) ngx_conf_merge_value(conf->upstream.ssl_session_reuse, prev->upstream.ssl_session_reuse, 1); + + ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols, + (NGX_CONF_BITMASK_SET|NGX_SSL_SSLv3 + |NGX_SSL_TLSv1|NGX_SSL_TLSv1_1 + |NGX_SSL_TLSv1_2)); + + ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, + "DEFAULT"); + + if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) { + return NGX_CONF_ERROR; + } #endif ngx_conf_merge_value(conf->redirect, prev->redirect, 1); @@ -3146,9 +3189,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } #if (NGX_HTTP_SSL) - if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) { - return NGX_CONF_ERROR; - } + plcf->ssl = 1; #endif return NGX_CONF_OK; @@ -3161,9 +3202,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) { #if (NGX_HTTP_SSL) - if (ngx_http_proxy_set_ssl(cf, plcf) != NGX_OK) { - return NGX_CONF_ERROR; - } + plcf->ssl = 1; add = 8; port = 443; @@ -3745,15 +3784,22 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf) plcf->upstream.ssl->log = cf->log; - if (ngx_ssl_create(plcf->upstream.ssl, - NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1 - |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2, - NULL) + if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL) != NGX_OK) { return NGX_ERROR; } + if (SSL_CTX_set_cipher_list(plcf->upstream.ssl->ctx, + (const char *) plcf->ssl_ciphers.data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &plcf->ssl_ciphers); + return NGX_ERROR; + } + cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { return NGX_ERROR; diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c index e8f822ca0..f9c0d1427 100644 --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -394,13 +394,6 @@ ngx_http_scgi_handler(ngx_http_request_t *r) ngx_http_upstream_t *u; ngx_http_scgi_loc_conf_t *scf; - if (r->subrequest_in_memory) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "ngx_http_scgi_module does not support " - "subrequests in memory"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index a6c803da0..75dd7f4b0 100644 --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -561,6 +561,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, "SSL_CTX_set_cipher_list(\"%V\") failed", &conf->ciphers); + return NGX_CONF_ERROR; } if (conf->verify) { diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c index b8bee864e..0635299e8 100644 --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -427,13 +427,6 @@ ngx_http_uwsgi_handler(ngx_http_request_t *r) ngx_http_upstream_t *u; ngx_http_uwsgi_loc_conf_t *uwcf; - if (r->subrequest_in_memory) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "ngx_http_uwsgi_module does not support " - "subrequests in memory"); - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c index 987ae54df..91bb04f55 100644 --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -949,7 +949,8 @@ ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two) #endif - rc = ngx_strcmp(first->name.data, second->name.data); + rc = ngx_filename_cmp(first->name.data, second->name.data, + ngx_min(first->name.len, second->name.len) + 1); if (rc == 0 && !first->exact_match && second->exact_match) { /* an exact match must be before the same inclusive one */ @@ -975,8 +976,10 @@ ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations) lq = (ngx_http_location_queue_t *) q; lx = (ngx_http_location_queue_t *) x; - if (ngx_strcmp(lq->name->data, lx->name->data) == 0) { - + if (lq->name->len == lx->name->len + && ngx_filename_cmp(lq->name->data, lx->name->data, lx->name->len) + == 0) + { if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "duplicate location \"%V\" in %s:%ui", @@ -1028,7 +1031,7 @@ ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q) lx = (ngx_http_location_queue_t *) x; if (len > lx->name->len - || (ngx_strncmp(name, lx->name->data, len) != 0)) + || ngx_filename_cmp(name, lx->name->data, len) != 0) { break; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 85b4fe882..f8c695645 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3219,9 +3219,9 @@ ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) #if (NGX_PCRE) if (clcf->regex == NULL - && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0) + && ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0) #else - if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0) + if (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0) #endif { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index fc54836f6..507dc939c 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -264,13 +264,13 @@ ngx_http_header_filter(ngx_http_request_t *r) len += ngx_http_status_lines[status].len; } else { - len += NGX_INT_T_LEN; + len += NGX_INT_T_LEN + 1 /* SP */; status_line = NULL; } if (status_line && status_line->len == 0) { status = r->headers_out.status; - len += NGX_INT_T_LEN; + len += NGX_INT_T_LEN + 1 /* SP */; status_line = NULL; } } @@ -451,7 +451,7 @@ ngx_http_header_filter(ngx_http_request_t *r) b->last = ngx_copy(b->last, status_line->data, status_line->len); } else { - b->last = ngx_sprintf(b->last, "%03ui", status); + b->last = ngx_sprintf(b->last, "%03ui ", status); } *b->last++ = CR; *b->last++ = LF; diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c index e7bebccd5..36e23be02 100644 --- a/src/http/ngx_http_spdy.c +++ b/src/http/ngx_http_spdy.c @@ -145,6 +145,8 @@ static ngx_int_t ngx_http_spdy_construct_request_line(ngx_http_request_t *r); static void ngx_http_spdy_run_request(ngx_http_request_t *r); static ngx_int_t ngx_http_spdy_init_request_body(ngx_http_request_t *r); +static void ngx_http_spdy_close_stream_handler(ngx_event_t *ev); + static void ngx_http_spdy_handle_connection_handler(ngx_event_t *rev); static void ngx_http_spdy_keepalive_handler(ngx_event_t *rev); static void ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, @@ -1214,6 +1216,7 @@ ngx_http_spdy_state_data(ngx_http_spdy_connection_t *sc, u_char *pos, } if (rb->post_handler) { + r->read_event_handler = ngx_http_block_reading; rb->post_handler(r); } } @@ -1824,7 +1827,7 @@ ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id, rev->data = fc; rev->ready = 1; - rev->handler = ngx_http_empty_handler; + rev->handler = ngx_http_spdy_close_stream_handler; rev->log = log; ngx_memcpy(wev, rev, sizeof(ngx_event_t)); @@ -2607,10 +2610,29 @@ ngx_http_spdy_read_request_body(ngx_http_request_t *r, r->request_body->post_handler = post_handler; + r->read_event_handler = ngx_http_test_reading; + r->write_event_handler = ngx_http_request_empty_handler; + return NGX_AGAIN; } +static void +ngx_http_spdy_close_stream_handler(ngx_event_t *ev) +{ + ngx_connection_t *fc; + ngx_http_request_t *r; + + fc = ev->data; + r = fc->data; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "spdy close stream handler"); + + ngx_http_spdy_close_stream(r->spdy_stream, 0); +} + + void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) { @@ -2810,6 +2832,7 @@ ngx_http_spdy_finalize_connection(ngx_http_spdy_connection_t *sc, c->error = 1; c->read->handler = ngx_http_empty_handler; + c->write->handler = ngx_http_empty_handler; sc->last_out = NULL; diff --git a/src/http/ngx_http_spdy.h b/src/http/ngx_http_spdy.h index 63014066d..c47243fb0 100644 --- a/src/http/ngx_http_spdy.h +++ b/src/http/ngx_http_spdy.h @@ -173,9 +173,9 @@ ngx_http_spdy_queue_blocked_frame(ngx_http_spdy_connection_t *sc, { ngx_http_spdy_out_frame_t **out; - for (out = &sc->last_out; *out && !(*out)->blocked; out = &(*out)->next) + for (out = &sc->last_out; *out; out = &(*out)->next) { - if (frame->priority >= (*out)->priority) { + if ((*out)->blocked) { break; } } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 2321f6e97..4a4f8eba2 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1711,10 +1711,6 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u) if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) { - if (r->subrequest_in_memory) { - u->buffer.last = u->buffer.pos; - } - if (ngx_http_upstream_test_next(r, u) == NGX_OK) { return; } @@ -3464,6 +3460,12 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r, #endif + if (r->subrequest_in_memory + && u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) + { + u->buffer.last = u->buffer.pos; + } + if (rc == NGX_DECLINED) { return; } diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h index ccdfb8c6f..dc39f1e13 100644 --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -234,6 +234,8 @@ typedef struct { ngx_str_t smtp_from; ngx_str_t smtp_to; + ngx_str_t cmd; + ngx_uint_t command; ngx_array_t args; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c index ae955f9c6..7cfff1a07 100644 --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -620,7 +620,9 @@ ngx_mail_read_command(ngx_mail_session_t *s, ngx_connection_t *c) return NGX_ERROR; } - return NGX_AGAIN; + if (s->buffer->pos == s->buffer->last) { + return NGX_AGAIN; + } } cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); @@ -661,8 +663,12 @@ void ngx_mail_auth(ngx_mail_session_t *s, ngx_connection_t *c) { s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } + s->state = 0; if (c->read->timer_set) { diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c index 7de6c19a1..b158f5a0f 100644 --- a/src/mail/ngx_mail_parse.c +++ b/src/mail/ngx_mail_parse.c @@ -626,6 +626,8 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) ngx_str_t *arg; enum { sw_start = 0, + sw_command, + sw_invalid, sw_spaces_before_argument, sw_argument, sw_almost_done @@ -640,8 +642,14 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) /* SMTP command */ case sw_start: + s->cmd_start = p; + state = sw_command; + + /* fall through */ + + case sw_command: if (ch == ' ' || ch == CR || ch == LF) { - c = s->buffer->start; + c = s->cmd_start; if (p - c == 4) { @@ -719,6 +727,9 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) goto invalid; } + s->cmd.data = s->cmd_start; + s->cmd.len = p - s->cmd_start; + switch (ch) { case ' ': state = sw_spaces_before_argument; @@ -738,6 +749,9 @@ ngx_mail_smtp_parse_command(ngx_mail_session_t *s) break; + case sw_invalid: + goto invalid; + case sw_spaces_before_argument: switch (ch) { case ' ': @@ -824,9 +838,21 @@ done: invalid: - s->state = sw_start; + s->state = sw_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; + p++; + break; + } + } + + s->buffer->pos = p; + return NGX_MAIL_PARSE_INVALID_COMMAND; } diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c index 4ea608cea..02222c122 100644 --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -657,7 +657,12 @@ ngx_mail_proxy_smtp_handler(ngx_event_t *rev) c->log->action = NULL; ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - ngx_mail_proxy_handler(s->connection->write); + if (s->buffer->pos == s->buffer->last) { + ngx_mail_proxy_handler(s->connection->write); + + } else { + ngx_mail_proxy_handler(c->write); + } return; @@ -702,7 +707,7 @@ ngx_mail_proxy_dummy_handler(ngx_event_t *wev) static ngx_int_t ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state) { - u_char *p; + u_char *p, *m; ssize_t n; ngx_buf_t *b; ngx_mail_proxy_conf_t *pcf; @@ -779,6 +784,25 @@ ngx_mail_proxy_read_response(ngx_mail_session_t *s, ngx_uint_t state) break; default: /* NGX_MAIL_SMTP_PROTOCOL */ + + if (p[3] == '-') { + /* multiline reply, check if we got last line */ + + m = b->last - (sizeof(CRLF "200" CRLF) - 1); + + while (m > p) { + if (m[0] == CR && m[1] == LF) { + break; + } + + m--; + } + + if (m <= p || m[5] == '-') { + return NGX_AGAIN; + } + } + switch (state) { case ngx_smtp_start: diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c index 21714239f..0238b6282 100644 --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -321,6 +321,7 @@ ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev) } ngx_str_set(&s->out, smtp_invalid_pipelining); + s->quit = 1; } ngx_mail_send(c->write); @@ -485,6 +486,10 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev) } } + if (s->buffer->pos < s->buffer->last) { + s->blocked = 1; + } + switch (rc) { case NGX_DONE: @@ -504,11 +509,14 @@ ngx_mail_smtp_auth_state(ngx_event_t *rev) case NGX_OK: s->args.nelts = 0; - s->buffer->pos = s->buffer->start; - s->buffer->last = s->buffer->start; + + if (s->buffer->pos == s->buffer->last) { + s->buffer->pos = s->buffer->start; + s->buffer->last = s->buffer->start; + } if (s->state) { - s->arg_start = s->buffer->start; + s->arg_start = s->buffer->pos; } ngx_mail_send(c->write); @@ -651,9 +659,7 @@ ngx_mail_smtp_auth(ngx_mail_session_t *s, ngx_connection_t *c) static ngx_int_t ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) { - u_char ch; - ngx_str_t l; - ngx_uint_t i; + ngx_str_t *arg, cmd; ngx_mail_smtp_srv_conf_t *sscf; sscf = ngx_mail_get_module_srv_conf(s, ngx_mail_smtp_module); @@ -671,37 +677,20 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) return NGX_OK; } - l.len = s->buffer->last - s->buffer->start; - l.data = s->buffer->start; - - for (i = 0; i < l.len; i++) { - ch = l.data[i]; - - if (ch != CR && ch != LF) { - continue; - } - - l.data[i] = ' '; - } - - while (i) { - if (l.data[i - 1] != ' ') { - break; - } - - i--; - } + arg = s->args.elts; + arg += s->args.nelts - 1; - l.len = i; + cmd.len = arg->data + arg->len - s->cmd.data; + cmd.data = s->cmd.data; - s->smtp_from.len = l.len; + s->smtp_from.len = cmd.len; - s->smtp_from.data = ngx_pnalloc(c->pool, l.len); + s->smtp_from.data = ngx_pnalloc(c->pool, cmd.len); if (s->smtp_from.data == NULL) { return NGX_ERROR; } - ngx_memcpy(s->smtp_from.data, l.data, l.len); + ngx_memcpy(s->smtp_from.data, cmd.data, cmd.len); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp mail from:\"%V\"", &s->smtp_from); @@ -715,46 +704,27 @@ ngx_mail_smtp_mail(ngx_mail_session_t *s, ngx_connection_t *c) static ngx_int_t ngx_mail_smtp_rcpt(ngx_mail_session_t *s, ngx_connection_t *c) { - u_char ch; - ngx_str_t l; - ngx_uint_t i; + ngx_str_t *arg, cmd; if (s->smtp_from.len == 0) { ngx_str_set(&s->out, smtp_bad_sequence); return NGX_OK; } - l.len = s->buffer->last - s->buffer->start; - l.data = s->buffer->start; - - for (i = 0; i < l.len; i++) { - ch = l.data[i]; - - if (ch != CR && ch != LF) { - continue; - } - - l.data[i] = ' '; - } - - while (i) { - if (l.data[i - 1] != ' ') { - break; - } - - i--; - } + arg = s->args.elts; + arg += s->args.nelts - 1; - l.len = i; + cmd.len = arg->data + arg->len - s->cmd.data; + cmd.data = s->cmd.data; - s->smtp_to.len = l.len; + s->smtp_to.len = cmd.len; - s->smtp_to.data = ngx_pnalloc(c->pool, l.len); + s->smtp_to.data = ngx_pnalloc(c->pool, cmd.len); if (s->smtp_to.data == NULL) { return NGX_ERROR; } - ngx_memcpy(s->smtp_to.data, l.data, l.len); + ngx_memcpy(s->smtp_to.data, cmd.data, cmd.len); ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "smtp rcpt to:\"%V\"", &s->smtp_to); diff --git a/src/mail/ngx_mail_smtp_module.c b/src/mail/ngx_mail_smtp_module.c index cdd4e5eb1..02bbf1fb9 100644 --- a/src/mail/ngx_mail_smtp_module.c +++ b/src/mail/ngx_mail_smtp_module.c @@ -277,7 +277,6 @@ ngx_mail_smtp_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) p = ngx_cpymem(p, conf->capability.data, conf->capability.len); p = ngx_cpymem(p, "250 STARTTLS" CRLF, sizeof("250 STARTTLS" CRLF) - 1); - *p++ = CR; *p = LF; p = conf->starttls_capability.data + (last - conf->capability.data) + 3; diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index dbfb9c702..18fd66aed 100644 --- a/src/mail/ngx_mail_ssl_module.c +++ b/src/mail/ngx_mail_ssl_module.c @@ -235,6 +235,11 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) mode = ""; } + if (conf->file == NULL) { + conf->file = prev->file; + conf->line = prev->line; + } + if (*mode) { if (conf->certificate.len == 0) { @@ -287,15 +292,14 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) return NGX_CONF_ERROR; } - if (conf->ciphers.len) { - if (SSL_CTX_set_cipher_list(conf->ssl.ctx, - (const char *) conf->ciphers.data) - == 0) - { - ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, - "SSL_CTX_set_cipher_list(\"%V\") failed", - &conf->ciphers); - } + if (SSL_CTX_set_cipher_list(conf->ssl.ctx, + (const char *) conf->ciphers.data) + == 0) + { + ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0, + "SSL_CTX_set_cipher_list(\"%V\") failed", + &conf->ciphers); + return NGX_CONF_ERROR; } if (conf->prefer_server_ciphers) { diff --git a/src/os/unix/ngx_darwin_config.h b/src/os/unix/ngx_darwin_config.h index 149778c29..7ac86c73e 100644 --- a/src/os/unix/ngx_darwin_config.h +++ b/src/os/unix/ngx_darwin_config.h @@ -20,6 +20,7 @@ #include <stddef.h> /* offsetof() */ #include <stdio.h> #include <stdlib.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <signal.h> diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index df759df52..4b2016500 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -192,17 +192,6 @@ ngx_int_t ngx_create_file_mapping(ngx_file_mapping_t *fm); void ngx_close_file_mapping(ngx_file_mapping_t *fm); -#if (NGX_HAVE_CASELESS_FILESYSTEM) - -#define ngx_filename_cmp(s1, s2, n) strncasecmp((char *) s1, (char *) s2, n) - -#else - -#define ngx_filename_cmp ngx_memcmp - -#endif - - #define ngx_realpath(p, r) (u_char *) realpath((char *) p, (char *) r) #define ngx_realpath_n "realpath()" #define ngx_getcwd(buf, size) (getcwd((char *) buf, size) != NULL) diff --git a/src/os/unix/ngx_freebsd_config.h b/src/os/unix/ngx_freebsd_config.h index 248e7a731..92b2928c8 100644 --- a/src/os/unix/ngx_freebsd_config.h +++ b/src/os/unix/ngx_freebsd_config.h @@ -16,6 +16,7 @@ #include <stddef.h> /* offsetof() */ #include <stdio.h> #include <stdlib.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <signal.h> diff --git a/src/os/unix/ngx_linux_config.h b/src/os/unix/ngx_linux_config.h index 8467a97fe..72594bac0 100644 --- a/src/os/unix/ngx_linux_config.h +++ b/src/os/unix/ngx_linux_config.h @@ -22,6 +22,7 @@ #include <stddef.h> /* offsetof() */ #include <stdio.h> #include <stdlib.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <signal.h> diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h index 4cf90cc98..d725659df 100644 --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -39,6 +39,7 @@ #include <stddef.h> /* offsetof() */ #include <stdio.h> #include <stdlib.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <signal.h> diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h index e664ba826..ddfd98457 100644 --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -22,6 +22,7 @@ #include <stddef.h> /* offsetof() */ #include <stdio.h> #include <stdlib.h> +#include <ctype.h> #include <errno.h> #include <string.h> #include <signal.h> |