Compare commits

...

32 Commits

Author SHA1 Message Date
Maxim Dounin cd77112843 release-1.14.2 tag 2018-12-04 17:52:24 +03:00
Maxim Dounin 668544d45f nginx-1.14.2-RELEASE 2018-12-04 17:52:24 +03:00
Maxim Dounin e749093a79 Updated OpenSSL used for win32 builds. 2018-11-27 17:02:56 +03:00
Maxim Dounin c88dcb8feb Mp4: fixed possible pointer overflow on 32-bit platforms.
On 32-bit platforms mp4->buffer_pos might overflow when a large
enough (close to 4 gigabytes) atom is being skipped, resulting in
incorrect memory addesses being read further in the code.  In most
cases this results in harmless errors being logged, though may also
result in a segmentation fault if hitting unmapped pages.

To address this, ngx_mp4_atom_next() now only increments mp4->buffer_pos
up to mp4->buffer_end.  This ensures that overflow cannot happen.
2018-11-21 20:23:16 +03:00
Maxim Dounin f5cc8c42e1 SSL: explicitly set maximum version (ticket #1654).
With maximum version explicitly set, TLSv1.3 will not be unexpectedly
enabled if nginx compiled with OpenSSL 1.1.0 (without TLSv1.3 support)
will be run with OpenSSL 1.1.1 (with TLSv1.3 support).
2018-10-23 22:11:48 +03:00
Maxim Dounin 93ed5b65ed SSL: enabled TLSv1.3 with BoringSSL.
BoringSSL currently requires SSL_CTX_set_max_proto_version(TLS1_3_VERSION)
to be able to enable TLS 1.3.  This is because by default max protocol
version is set to TLS 1.2, and the SSL_OP_NO_* options are merely used
as a blacklist within the version range specified using the
SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version()
functions.

With this change, we now call SSL_CTX_set_max_proto_version() with an
explicit maximum version set.  This enables TLS 1.3 with BoringSSL.
As a side effect, this change also limits maximum protocol version to
the newest protocol we know about, TLS 1.3.  This seems to be a good
change, as enabling unknown protocols might have unexpected results.

Additionally, we now explicitly call SSL_CTX_set_min_proto_version()
with 0.  This is expected to help with Debian system-wide default
of MinProtocol set to TLSv1.2, see
http://mailman.nginx.org/pipermail/nginx-ru/2017-October/060411.html.

Note that there is no SSL_CTX_set_min_proto_version macro in BoringSSL,
so we call SSL_CTX_set_min_proto_version() and SSL_CTX_set_max_proto_version()
as long as the TLS1_3_VERSION macro is defined.
2018-08-07 02:15:28 +03:00
Maxim Dounin 98f36d7a37 SSL: logging level of "no suitable signature algorithm".
The "no suitable signature algorithm" errors are reported by OpenSSL 1.1.1
when using TLSv1.3 if there are no shared signature algorithms.  In
particular, this can happen if the client limits available signature
algorithms to something we don't have a certificate for, or to an empty
list.  For example, the following command:

    openssl s_client -connect 127.0.0.1:8443 -sigalgs rsa_pkcs1_sha1

will always result in the "no suitable signature algorithm" error
as the "rsa_pkcs1_sha1" algorithm refers solely to signatures which
appear in certificates and not defined for use in TLS 1.3 handshake
messages.

The SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS error is what BoringSSL returns
in the same situation.
2018-09-25 14:00:04 +03:00
Maxim Dounin 9c8a86bc9e SSL: logging level of "no suitable key share".
The "no suitable key share" errors are reported by OpenSSL 1.1.1 when
using TLSv1.3 if there are no shared groups (that is, elliptic curves).
In particular, it is easy enough to trigger by using only a single
curve in ssl_ecdh_curve:

    ssl_ecdh_curve secp384r1;

and using a different curve in the client:

    openssl s_client -connect 127.0.0.1:443 -curves prime256v1

On the client side it is seen as "sslv3 alert handshake failure",
"SSL alert number 40":

0:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:ssl/record/rec_layer_s3.c:1528:SSL alert number 40

It can be also triggered with default ssl_ecdh_curve by using a curve
which is not in the default list (X25519, prime256v1, X448, secp521r1,
secp384r1):

    openssl s_client -connect 127.0.0.1:8443 -curves brainpoolP512r1

Given that many clients hardcode prime256v1, these errors might become
a common problem with TLSv1.3 if ssl_ecdh_curve is redefined.  Previously
this resulted in not using ECDH with such clients, but with TLSv1.3 it
is no longer possible and will result in a handshake failure.

The SSL_R_NO_SHARED_GROUP error is what BoringSSL returns in the same
situation.

Seen at:

https://serverfault.com/questions/932102/nginx-ssl-handshake-error-no-suitable-key-share
2018-09-25 13:59:53 +03:00
Maxim Dounin 843593a7a1 gRPC: disabled keepalive when sending control frames was blocked.
If sending request body was not completed (u->request_body_sent is not set),
the upstream keepalive module won't save such a connection.  However, it
is theoretically possible (though highly unlikely) that sending of some
control frames can be blocked after the request body was sent.  The
ctx->output_blocked flag introduced to disable keepalive in such cases.
2018-09-03 19:34:02 +03:00
Maxim Dounin e4be6e9d4d gRPC: improved keepalive handling.
The code is now able to parse additional control frames after
the response is received, and can send control frames as well.
This fixes keepalive problems as observed with grpc-c, which can
send window update and ping frames after the response, see
http://mailman.nginx.org/pipermail/nginx/2018-August/056620.html.
2018-09-03 19:34:01 +03:00
Maxim Dounin 704c86a23b SSL: fixed build with LibreSSL 2.8.0 (ticket #1605).
LibreSSL 2.8.0 "added const annotations to many existing APIs from OpenSSL,
making interoperability easier for downstream applications".  This includes
the const change in the SSL_CTX_sess_set_get_cb() callback function (see
9dd43f4ef67e), which breaks compilation.

To fix this, added a condition on how we redefine OPENSSL_VERSION_NUMBER
when working with LibreSSL (see 382fc7069e3a).  With LibreSSL 2.8.0,
we now set OPENSSL_VERSION_NUMBER to 0x1010000fL (OpenSSL 1.1.0), so the
appropriate conditions in the code will use "const" as it happens with
OpenSSL 1.1.0 and later versions.
2018-08-10 20:49:06 +03:00
Maxim Dounin 253e6f3ead SSL: fixed SSL_clear_options() usage with OpenSSL 1.1.0+.
In OpenSSL 1.1.0 the SSL_CTRL_CLEAR_OPTIONS macro was removed, so
conditional compilation test on it results in SSL_clear_options()
and SSL_CTX_clear_options() not being used.  Notably, this caused
"ssl_prefer_server_ciphers off" to not work in SNI-based virtual
servers if server preference was switched on in the default server.

It looks like the only possible fix is to test OPENSSL_VERSION_NUMBER
explicitly.
2018-07-16 17:47:20 +03:00
Maxim Dounin 52b6141b16 SSL: logging levels of "unsupported protocol", "version too low".
Starting with OpenSSL 1.1.0, SSL_R_UNSUPPORTED_PROTOCOL instead of
SSL_R_UNKNOWN_PROTOCOL is reported when a protocol is disabled via
an SSL_OP_NO_* option.

Additionally, SSL_R_VERSION_TOO_LOW is reported when using MinProtocol
or when seclevel checks (as set by @SECLEVEL=n in the cipher string)
rejects a protocol, and this is what happens with SSLv3 and @SECLEVEL=1,
which is the default.

There is also the SSL_R_VERSION_TOO_HIGH error code, but it looks like
it is not possible to trigger it.
2018-07-16 17:47:18 +03:00
Maxim Dounin fa02cacff8 SSL: logging level of "https proxy request" errors.
The "http request" and "https proxy request" errors cannot happen
with HTTP due to pre-handshake checks in ngx_http_ssl_handshake(),
but can happen when SSL is used in stream and mail modules.
2018-07-05 20:45:29 +03:00
Maxim Dounin fdbb12cb01 Upstream: fixed tcp_nopush with gRPC.
With gRPC it is possible that a request sending is blocked due to flow
control.  Moreover, further sending might be only allowed once the
backend sees all the data we've already sent.  With such a backend
it is required to clear the TCP_NOPUSH socket option to make sure all
the data we've sent are actually delivered to the backend.

As such, we now clear TCP_NOPUSH in ngx_http_upstream_send_request()
also on NGX_AGAIN if c->write->ready is set.  This fixes a test (which
waits for all the 64k bytes as per initial window before allowing more
bytes) with sendfile enabled when the body was written to a file
in a different context.
2018-07-02 19:03:04 +03:00
Maxim Dounin aa8c49d43e gRPC: clearing buffers in ngx_http_grpc_get_buf().
We copy input buffers to our buffers, so various flags might be
unexpectedly set in buffers returned by ngx_chain_get_free_buf().

In particular, the b->in_file flag might be set when the body was
written to a file in a different context.  With sendfile enabled this
in turn might result in protocol corruption if such a buffer was reused
for a control frame.

Make sure to clear buffers and set only fields we really need to be set.
2018-07-02 19:02:08 +03:00
Maxim Dounin 31ad23c40d Upstream: disable body cleanup with preserve_output (ticket #1565).
With u->conf->preserve_output set the request body file might be used
after the response header is sent, so avoid cleaning it.  (Normally
this is not a problem as u->conf->preserve_output is only set with
r->request_body_no_buffering, but the request body might be already
written to a file in a different context.)
2018-06-13 15:28:11 +03:00
Roman Arutyunyan a7a34f2019 Events: fixed handling zero-length client address.
On Linux recvmsg() syscall may return a zero-length client address when
receiving a datagram from an unbound unix datagram socket.  It is usually
assumed that socket address has at least the sa_family member.  Zero-length
socket address caused buffer over-read in functions which receive socket
address, for example ngx_sock_ntop().  Typically the over-read resulted in
unexpected socket family followed by session close.  Now a fake socket address
is allocated instead of a zero-length client address.
2018-06-01 16:53:02 +03:00
Maxim Dounin 434b9d68ec Removed glibc crypt_r() bug workaround (ticket #1469).
The bug in question was fixed in glibc 2.3.2 and is no longer expected
to manifest itself on real servers.  On the other hand, the workaround
causes compilation problems on various systems.  Previously, we've
already fixed the code to compile with musl libc (fd6fd02f6a4d), and
now it is broken on Fedora 28 where glibc's crypt library was replaced
by libxcrypt.  So the workaround was removed.
2018-05-23 16:38:16 +03:00
Sergey Kandaurov 9437578786 Silenced -Wcast-function-type warnings (closes #1546).
Cast to intermediate "void *" to lose compiler knowledge about the original
type and pass the warning.  This is not a real fix but rather a workaround.

Found by gcc8.
2018-05-07 09:54:37 +00:00
Maxim Dounin 3f247c4b87 Version bump. 2018-12-03 20:07:36 +03:00
Maxim Dounin d61dda3f77 release-1.14.1 tag 2018-11-06 16:52:46 +03:00
Maxim Dounin 3455e7ceb7 nginx-1.14.1-RELEASE 2018-11-06 16:52:46 +03:00
Maxim Dounin bc44cde25c gRPC: limited allocations due to ping and settings frames. 2018-11-06 16:29:59 +03:00
Ruslan Ermilov 416bbdcff3 HTTP/2: limit the number of idle state switches.
An attack that continuously switches HTTP/2 connection between
idle and active states can result in excessive CPU usage.
This is because when a connection switches to the idle state,
all of its memory pool caches are freed.

This change limits the maximum allowed number of idle state
switches to 10 * http2_max_requests (i.e., 10000 by default).
This limits possible CPU usage in one connection, and also
imposes a limit on the maximum lifetime of a connection.

Initially reported by Gal Goldshtein from F5 Networks.
2018-11-06 16:29:49 +03:00
Ruslan Ermilov 5f1bba7d82 HTTP/2: flood detection.
Fixed uncontrolled memory growth in case peer is flooding us with
some frames (e.g., SETTINGS and PING) and doesn't read data.  Fix
is to limit the number of allocated control frames.
2018-11-06 16:29:35 +03:00
Roman Arutyunyan 07b5f8e603 Mp4: fixed reading 64-bit atoms.
Previously there was no validation for the size of a 64-bit atom
in an mp4 file.  This could lead to a CPU hog when the size is 0,
or various other problems due to integer underflow when calculating
atom data size, including segmentation fault or worker process
memory disclosure.
2018-11-06 16:29:18 +03:00
Maxim Dounin b4b96440a6 Updated OpenSSL used for win32 builds. 2018-08-28 15:05:41 +03:00
Maxim Dounin 78c1327437 Version bump. 2018-11-06 16:33:16 +03:00
Maxim Dounin 6f27a99d54 release-1.14.0 tag 2018-04-17 18:22:36 +03:00
Maxim Dounin 8c010c56f5 nginx-1.14.0-RELEASE 2018-04-17 18:22:35 +03:00
Maxim Dounin 2f9748ef7b Stable branch. 2018-04-17 16:30:10 +03:00
19 changed files with 411 additions and 78 deletions

View File

@ -5,6 +5,175 @@
<change_log title="nginx">
<changes ver="1.14.2" date="2018-12-04">
<change type="bugfix">
<para lang="ru">
nginx не собирался gcc 8.1.
</para>
<para lang="en">
nginx could not be built by gcc 8.1.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался на Fedora 28 Linux.
</para>
<para lang="en">
nginx could not be built on Fedora 28 Linux.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в обработке адресов клиентов при использовании unix domain listen-сокетов
для работы с датаграммами на Linux.
</para>
<para lang="en">
in handling of client addresses when using unix domain listen sockets
to work with datagrams on Linux.
</para>
</change>
<change type="change">
<para lang="ru">
уровень логгирования ошибок SSL "http request", "https proxy request",
"unsupported protocol", "version too low", "no suitable key share" и
"no suitable signature algorithm"
понижен с уровня crit до info.
</para>
<para lang="en">
the logging level of the "http request", "https proxy request",
"unsupported protocol", "version too low", "no suitable key share", and
"no suitable signature algorithm" SSL errors
has been lowered from "crit" to "info".
</para>
</change>
<change type="bugfix">
<para lang="ru">
при использовании OpenSSL 1.1.0 и новее
директиву ssl_prefer_server_ciphers нельзя было выключить
в виртуальном сервере, если она была включена в сервере по умолчанию.
</para>
<para lang="en">
when using OpenSSL 1.1.0 or newer
it was not possible to switch off "ssl_prefer_server_ciphers" in
a virtual server if it was switched on in the default server.
</para>
</change>
<change type="bugfix">
<para lang="ru">
nginx не собирался с LibreSSL 2.8.0.
</para>
<para lang="en">
nginx could not be built with LibreSSL 2.8.0.
</para>
</change>
<change type="bugfix">
<para lang="ru">
если nginx был собран с OpenSSL 1.1.0, а использовался с OpenSSL 1.1.1,
протокол TLS 1.3 всегда был разрешён.
</para>
<para lang="en">
if nginx was built with OpenSSL 1.1.0 and used with OpenSSL 1.1.1,
the TLS 1.3 protocol was always enabled.
</para>
</change>
<change type="bugfix">
<para lang="ru">
при отправке сохранённого на диск тела запроса на gRPC-бэкенд
могли возникать ошибки.
</para>
<para lang="en">
sending a disk-buffered request body to a gRPC backend
might fail.
</para>
</change>
<change type="bugfix">
<para lang="ru">
соединения к некоторым gRPC-бэкендам могли не кэшироваться
при использовании директивы keepalive.
</para>
<para lang="en">
connections with some gRPC backends might not be cached
when using the "keepalive" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
в рабочем процессе мог произойти segmentation fault,
если использовался модуль ngx_http_mp4_module на 32-битных платформах.
</para>
<para lang="en">
a segmentation fault might occur in a worker process
if the ngx_http_mp4_module was used on 32-bit platforms.
</para>
</change>
</changes>
<changes ver="1.14.1" date="2018-11-06">
<change type="security">
<para lang="ru">
при использовании HTTP/2 клиент мог вызвать
чрезмерное потреблению памяти (CVE-2018-16843)
и ресурсов процессора (CVE-2018-16844).
</para>
<para lang="en">
when using HTTP/2 a client might cause
excessive memory consumption (CVE-2018-16843)
and CPU usage (CVE-2018-16844).
</para>
</change>
<change type="security">
<para lang="ru">
при обработке специально созданного mp4-файла модулем ngx_http_mp4_module
содержимое памяти рабочего процесса могло быть отправлено клиенту
(CVE-2018-16845).
</para>
<para lang="en">
processing of a specially crafted mp4 file with the ngx_http_mp4_module
might result in worker process memory disclosure
(CVE-2018-16845).
</para>
</change>
<change type="bugfix">
<para lang="ru">
при работе с gRPC-бэкендами могло расходоваться большое количество памяти.
</para>
<para lang="en">
working with gRPC backends might result in excessive memory consumption.
</para>
</change>
</changes>
<changes ver="1.14.0" date="2018-04-17">
<change>
<para lang="ru">
Стабильная ветка 1.14.x.
</para>
<para lang="en">
1.14.x stable branch.
</para>
</change>
</changes>
<changes ver="1.13.12" date="2018-04-10">
<change type="bugfix">

View File

@ -6,7 +6,7 @@ TEMP = tmp
CC = cl
OBJS = objs.msvc8
OPENSSL = openssl-1.0.2o
OPENSSL = openssl-1.0.2q
ZLIB = zlib-1.2.11
PCRE = pcre-8.42

View File

@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
#define nginx_version 1013012
#define NGINX_VERSION "1.13.12"
#define nginx_version 1014002
#define NGINX_VERSION "1.14.2"
#define NGINX_VER "nginx/" NGINX_VERSION
#ifdef NGX_BUILD

View File

@ -448,6 +448,18 @@ ngx_event_recvmsg(ngx_event_t *ev)
c->socklen = sizeof(ngx_sockaddr_t);
}
if (c->socklen == 0) {
/*
* on Linux recvmsg() returns zero msg_namelen
* when receiving packets from unbound AF_UNIX sockets
*/
c->socklen = sizeof(struct sockaddr);
ngx_memzero(&sa, sizeof(struct sockaddr));
sa.sockaddr.sa_family = ls->sockaddr->sa_family;
}
#if (NGX_STAT_STUB)
(void) ngx_atomic_fetch_add(ngx_stat_active, 1);
#endif

View File

@ -296,7 +296,7 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
SSL_CTX_set_options(ssl->ctx, SSL_OP_SINGLE_DH_USE);
#ifdef SSL_CTRL_CLEAR_OPTIONS
#if OPENSSL_VERSION_NUMBER >= 0x009080dfL
/* only in 0.9.8m+ */
SSL_CTX_clear_options(ssl->ctx,
SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
@ -330,6 +330,16 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data)
}
#endif
#ifdef SSL_CTX_set_min_proto_version
SSL_CTX_set_min_proto_version(ssl->ctx, 0);
SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_2_VERSION);
#endif
#ifdef TLS1_3_VERSION
SSL_CTX_set_min_proto_version(ssl->ctx, 0);
SSL_CTX_set_max_proto_version(ssl->ctx, TLS1_3_VERSION);
#endif
#ifdef SSL_OP_NO_COMPRESSION
SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION);
#endif
@ -2059,10 +2069,18 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
/* handshake failures */
if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC /* 103 */
#ifdef SSL_R_NO_SUITABLE_KEY_SHARE
|| n == SSL_R_NO_SUITABLE_KEY_SHARE /* 101 */
#endif
#ifdef SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM
|| n == SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM /* 118 */
#endif
|| n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG /* 129 */
|| n == SSL_R_DIGEST_CHECK_FAILED /* 149 */
|| n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST /* 151 */
|| n == SSL_R_EXCESSIVE_MESSAGE_SIZE /* 152 */
|| n == SSL_R_HTTPS_PROXY_REQUEST /* 155 */
|| n == SSL_R_HTTP_REQUEST /* 156 */
|| n == SSL_R_LENGTH_MISMATCH /* 159 */
#ifdef SSL_R_NO_CIPHERS_PASSED
|| n == SSL_R_NO_CIPHERS_PASSED /* 182 */
@ -2078,6 +2096,13 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
|| n == SSL_R_UNEXPECTED_RECORD /* 245 */
|| n == SSL_R_UNKNOWN_ALERT_TYPE /* 246 */
|| n == SSL_R_UNKNOWN_PROTOCOL /* 252 */
#ifdef SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS
|| n == SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS /* 253 */
#endif
|| n == SSL_R_UNSUPPORTED_PROTOCOL /* 258 */
#ifdef SSL_R_NO_SHARED_GROUP
|| n == SSL_R_NO_SHARED_GROUP /* 266 */
#endif
|| n == SSL_R_WRONG_VERSION_NUMBER /* 267 */
|| n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC /* 281 */
#ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
@ -2093,6 +2118,9 @@ ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err,
#endif
#ifdef SSL_R_INAPPROPRIATE_FALLBACK
|| n == SSL_R_INAPPROPRIATE_FALLBACK /* 373 */
#endif
#ifdef SSL_R_VERSION_TOO_LOW
|| n == SSL_R_VERSION_TOO_LOW /* 396 */
#endif
|| n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
#ifdef SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE

View File

@ -36,8 +36,12 @@
#if (defined LIBRESSL_VERSION_NUMBER && OPENSSL_VERSION_NUMBER == 0x20000000L)
#undef OPENSSL_VERSION_NUMBER
#if (LIBRESSL_VERSION_NUMBER >= 0x2080000fL)
#define OPENSSL_VERSION_NUMBER 0x1010000fL
#else
#define OPENSSL_VERSION_NUMBER 0x1000107fL
#endif
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x10100001L)

View File

@ -3264,7 +3264,8 @@ ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
copy = ngx_array_push_n(params->lengths,
@ -3273,7 +3274,8 @@ ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].skip_empty;

View File

@ -78,6 +78,9 @@ typedef struct {
ngx_uint_t id;
ngx_uint_t pings;
ngx_uint_t settings;
ssize_t send_window;
size_t recv_window;
@ -109,8 +112,10 @@ typedef struct {
unsigned header_sent:1;
unsigned output_closed:1;
unsigned output_blocked:1;
unsigned parsing_headers:1;
unsigned end_stream:1;
unsigned done:1;
unsigned status:1;
ngx_http_request_t *request;
@ -1072,8 +1077,10 @@ ngx_http_grpc_reinit_request(ngx_http_request_t *r)
ctx->state = 0;
ctx->header_sent = 0;
ctx->output_closed = 0;
ctx->output_blocked = 0;
ctx->parsing_headers = 0;
ctx->end_stream = 0;
ctx->done = 0;
ctx->status = 0;
ctx->connection = NULL;
@ -1093,6 +1100,7 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
ngx_int_t rc;
ngx_uint_t next, last;
ngx_chain_t *cl, *out, **ll;
ngx_http_upstream_t *u;
ngx_http_grpc_ctx_t *ctx;
ngx_http_grpc_frame_t *f;
@ -1407,6 +1415,36 @@ ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
rc = NGX_AGAIN;
}
if (rc == NGX_AGAIN) {
ctx->output_blocked = 1;
} else {
ctx->output_blocked = 0;
}
if (ctx->done) {
/*
* We have already got the response and were sending some additional
* control frames. Even if there is still something unsent, stop
* here anyway.
*/
u = r->upstream;
u->length = 0;
if (ctx->in == NULL
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
}
ngx_post_event(u->peer.connection->read, &ngx_posted_events);
}
return rc;
}
@ -1749,6 +1787,7 @@ ngx_http_grpc_process_header(ngx_http_request_t *r)
if (ctx->in == NULL
&& ctx->out == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& b->last == b->pos)
{
u->keepalive = 1;
@ -1832,6 +1871,34 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
rc = ngx_http_grpc_parse_frame(r, ctx, b);
if (rc == NGX_AGAIN) {
if (ctx->done) {
/*
* We have finished parsing the response and the
* remaining control frames. If there are unsent
* control frames, post a write event to send them.
*/
if (ctx->out) {
ngx_post_event(u->peer.connection->write,
&ngx_posted_events);
return NGX_AGAIN;
}
u->length = 0;
if (ctx->in == NULL
&& ctx->output_closed
&& !ctx->output_blocked
&& ctx->state == ngx_http_grpc_st_start)
{
u->keepalive = 1;
}
break;
}
return NGX_AGAIN;
}
@ -1898,6 +1965,13 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
if (ctx->stream_id && ctx->done) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent frame for closed stream %ui",
ctx->stream_id);
return NGX_ERROR;
}
ctx->padding = 0;
}
@ -1914,17 +1988,7 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
ctx->state = ngx_http_grpc_st_start;
if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
u->length = 0;
if (ctx->in == NULL
&& ctx->out == NULL
&& ctx->output_closed
&& b->last == b->pos)
{
u->keepalive = 1;
}
break;
ctx->done = 1;
}
continue;
@ -2094,17 +2158,8 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
"grpc trailer done");
if (ctx->end_stream) {
u->length = 0;
if (ctx->in == NULL
&& ctx->out == NULL
&& ctx->output_closed
&& b->last == b->pos)
{
u->keepalive = 1;
}
return NGX_OK;
ctx->done = 1;
break;
}
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@ -2121,6 +2176,10 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
return NGX_ERROR;
}
if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
continue;
}
/* rc == NGX_AGAIN */
if (ctx->rest == 0) {
@ -2237,17 +2296,7 @@ ngx_http_grpc_filter(void *data, ssize_t bytes)
ctx->state = ngx_http_grpc_st_start;
if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
u->length = 0;
if (ctx->in == NULL
&& ctx->out == NULL
&& ctx->output_closed
&& b->last == b->pos)
{
u->keepalive = 1;
}
break;
ctx->done = 1;
}
}
@ -3531,6 +3580,12 @@ ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
ctx->rest);
return NGX_ERROR;
}
if (ctx->free == NULL && ctx->settings++ > 1000) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent too many settings frames");
return NGX_ERROR;
}
}
for (p = b->pos; p < last; p++) {
@ -3683,6 +3738,12 @@ ngx_http_grpc_parse_ping(ngx_http_request_t *r,
"upstream sent ping frame with ack flag");
return NGX_ERROR;
}
if (ctx->free == NULL && ctx->pings++ > 1000) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"upstream sent too many ping frames");
return NGX_ERROR;
}
}
for (p = b->pos; p < last; p++) {
@ -3868,6 +3929,7 @@ ngx_http_grpc_send_window_update(ngx_http_request_t *r,
static ngx_chain_t *
ngx_http_grpc_get_buf(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
{
u_char *start;
ngx_buf_t *b;
ngx_chain_t *cl;
@ -3877,29 +3939,33 @@ ngx_http_grpc_get_buf(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
}
b = cl->buf;
start = b->start;
b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
b->temporary = 1;
b->flush = 1;
if (b->start == NULL) {
if (start == NULL) {
/*
* each buffer is large enough to hold two window update
* frames in a row
*/
b->start = ngx_palloc(r->pool, 2 * sizeof(ngx_http_grpc_frame_t) + 8);
if (b->start == NULL) {
start = ngx_palloc(r->pool, 2 * sizeof(ngx_http_grpc_frame_t) + 8);
if (start == NULL) {
return NULL;
}
b->pos = b->start;
b->last = b->start;
b->end = b->start + 2 * sizeof(ngx_http_grpc_frame_t) + 8;
}
ngx_memzero(b, sizeof(ngx_buf_t));
b->start = start;
b->pos = start;
b->last = start;
b->end = start + 2 * sizeof(ngx_http_grpc_frame_t) + 8;
b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
b->temporary = 1;
b->flush = 1;
return cl;
}
@ -4389,7 +4455,8 @@ ngx_http_grpc_init_headers(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
size = (sizeof(ngx_http_script_copy_code_t)

View File

@ -169,7 +169,14 @@ typedef struct {
#define ngx_mp4_atom_next(mp4, n) \
mp4->buffer_pos += (size_t) n; \
\
if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \
mp4->buffer_pos = mp4->buffer_end; \
\
} else { \
mp4->buffer_pos += (size_t) n; \
} \
\
mp4->offset += n
@ -942,6 +949,13 @@ ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
atom_size = ngx_mp4_get_64value(atom_header + 8);
atom_header_size = sizeof(ngx_mp4_atom_header64_t);
if (atom_size < sizeof(ngx_mp4_atom_header64_t)) {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%s\" mp4 atom is too small:%uL",
mp4->file.name.data, atom_size);
return NGX_ERROR;
}
} else {
ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
"\"%s\" mp4 atom is too small:%uL",

View File

@ -3493,7 +3493,8 @@ ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
size = (sizeof(ngx_http_script_copy_code_t)

View File

@ -1724,7 +1724,8 @@ ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].key.len + 1;
copy = ngx_array_push_n(params->lengths,
@ -1733,7 +1734,8 @@ ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].skip_empty;

View File

@ -1987,7 +1987,8 @@ ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].key.len;
copy = ngx_array_push_n(params->lengths,
@ -1996,7 +1997,8 @@ ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
return NGX_ERROR;
}
copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
copy->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
copy->len = src[i].skip_empty;

View File

@ -923,7 +923,7 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
#ifdef SSL_CTRL_CLEAR_OPTIONS
#if OPENSSL_VERSION_NUMBER >= 0x009080dfL
/* only in 0.9.8m+ */
SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
~SSL_CTX_get_options(sscf->ssl.ctx));

View File

@ -695,7 +695,8 @@ ngx_http_script_add_copy_code(ngx_http_script_compile_t *sc, ngx_str_t *value,
return NGX_ERROR;
}
code->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
code->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_len_code;
code->len = len;
size = (sizeof(ngx_http_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
@ -784,7 +785,8 @@ ngx_http_script_add_var_code(ngx_http_script_compile_t *sc, ngx_str_t *name)
return NGX_ERROR;
}
code->code = (ngx_http_script_code_pt) ngx_http_script_copy_var_len_code;
code->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_var_len_code;
code->index = (uintptr_t) index;
code = ngx_http_script_add_code(*sc->values,
@ -1178,8 +1180,8 @@ ngx_http_script_add_capture_code(ngx_http_script_compile_t *sc, ngx_uint_t n)
return NGX_ERROR;
}
code->code = (ngx_http_script_code_pt)
ngx_http_script_copy_capture_len_code;
code->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_copy_capture_len_code;
code->n = 2 * n;
@ -1293,7 +1295,8 @@ ngx_http_script_add_full_name_code(ngx_http_script_compile_t *sc)
return NGX_ERROR;
}
code->code = (ngx_http_script_code_pt) ngx_http_script_full_name_len_code;
code->code = (ngx_http_script_code_pt) (void *)
ngx_http_script_full_name_len_code;
code->conf_prefix = sc->conf_prefix;
code = ngx_http_script_add_code(*sc->values,

View File

@ -2008,6 +2008,18 @@ ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
return;
}
if (c->write->ready && c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
if (ngx_tcp_push(c->fd) == -1) {
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
ngx_tcp_push_n " failed");
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
}
return;
}
@ -2901,7 +2913,8 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
if (r->request_body && r->request_body->temp_file
&& r == r->main && !r->preserve_body)
&& r == r->main && !r->preserve_body
&& !u->conf->preserve_output)
{
ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
r->request_body->temp_file->file.fd = NGX_INVALID_FILE;

View File

@ -664,6 +664,7 @@ ngx_http_v2_handle_connection(ngx_http_v2_connection_t *h2c)
h2c->pool = NULL;
h2c->free_frames = NULL;
h2c->frames = 0;
h2c->free_fake_connections = NULL;
#if (NGX_HTTP_SSL)
@ -2895,7 +2896,7 @@ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
frame->blocked = 0;
} else {
} else if (h2c->frames < 10000) {
pool = h2c->pool ? h2c->pool : h2c->connection->pool;
frame = ngx_pcalloc(pool, sizeof(ngx_http_v2_out_frame_t));
@ -2919,6 +2920,15 @@ ngx_http_v2_get_frame(ngx_http_v2_connection_t *h2c, size_t length,
frame->last = frame->first;
frame->handler = ngx_http_v2_frame_handler;
h2c->frames++;
} else {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"http2 flood detected");
h2c->connection->error = 1;
return NULL;
}
#if (NGX_DEBUG)
@ -4471,12 +4481,19 @@ ngx_http_v2_idle_handler(ngx_event_t *rev)
#endif
c->destroyed = 0;
ngx_reusable_connection(c, 0);
h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx,
ngx_http_v2_module);
if (h2c->idle++ > 10 * h2scf->max_requests) {
ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
"http2 flood detected");
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR);
return;
}
c->destroyed = 0;
ngx_reusable_connection(c, 0);
h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log);
if (h2c->pool == NULL) {
ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_INTERNAL_ERROR);

View File

@ -120,6 +120,8 @@ struct ngx_http_v2_connection_s {
ngx_http_connection_t *http_connection;
ngx_uint_t processing;
ngx_uint_t frames;
ngx_uint_t idle;
ngx_uint_t pushing;
ngx_uint_t concurrent_pushes;

View File

@ -21,10 +21,6 @@ ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted)
struct crypt_data cd;
cd.initialized = 0;
#ifdef __GLIBC__
/* work around the glibc bug */
cd.current_salt[0] = ~salt[0];
#endif
value = crypt_r((char *) key, (char *) salt, &cd);

View File

@ -587,7 +587,8 @@ ngx_stream_script_add_copy_code(ngx_stream_script_compile_t *sc,
return NGX_ERROR;
}
code->code = (ngx_stream_script_code_pt) ngx_stream_script_copy_len_code;
code->code = (ngx_stream_script_code_pt) (void *)
ngx_stream_script_copy_len_code;
code->len = len;
size = (sizeof(ngx_stream_script_copy_code_t) + len + sizeof(uintptr_t) - 1)
@ -677,8 +678,8 @@ ngx_stream_script_add_var_code(ngx_stream_script_compile_t *sc, ngx_str_t *name)
return NGX_ERROR;
}
code->code = (ngx_stream_script_code_pt)
ngx_stream_script_copy_var_len_code;
code->code = (ngx_stream_script_code_pt) (void *)
ngx_stream_script_copy_var_len_code;
code->index = (uintptr_t) index;
code = ngx_stream_script_add_code(*sc->values,
@ -767,8 +768,8 @@ ngx_stream_script_add_capture_code(ngx_stream_script_compile_t *sc,
return NGX_ERROR;
}
code->code = (ngx_stream_script_code_pt)
ngx_stream_script_copy_capture_len_code;
code->code = (ngx_stream_script_code_pt) (void *)
ngx_stream_script_copy_capture_len_code;
code->n = 2 * n;
@ -859,7 +860,7 @@ ngx_stream_script_add_full_name_code(ngx_stream_script_compile_t *sc)
return NGX_ERROR;
}
code->code = (ngx_stream_script_code_pt)
code->code = (ngx_stream_script_code_pt) (void *)
ngx_stream_script_full_name_len_code;
code->conf_prefix = sc->conf_prefix;