Commit Graph

5670 Commits

Author SHA1 Message Date
Roman Arutyunyan
27cdfe30f7 Mp4: added ngx_http_mp4_update_mdhd_atom() function.
The function updates the duration field of mdhd atom.  Previously it was
updated in ngx_http_mp4_read_mdhd_atom().  The change makes it possible to
alter track duration as a result of processing track frames.
2021-10-28 13:11:31 +03:00
Alexey Radkov
3253b346fb Core: removed unnecessary restriction in hash initialization.
Hash initialization ignores elements with key.data set to NULL.
Nevertheless, the initial hash bucket size check didn't skip them,
resulting in unnecessary restrictions on, for example, variables with
long names and with the NGX_HTTP_VARIABLE_NOHASH flag.

Fix is to update the initial hash bucket size check to skip elements
with key.data set to NULL, similarly to how it is done in other parts
of the code.
2021-08-19 20:51:27 +03:00
Maxim Dounin
1fc61b7b1f SSL: SSL_sendfile() support with kernel TLS.
Requires OpenSSL 3.0 compiled with "enable-ktls" option.  Further, KTLS
needs to be enabled in kernel, and in OpenSSL, either via OpenSSL
configuration file or with "ssl_conf_command Options KTLS;" in nginx
configuration.

On FreeBSD, kernel TLS is available starting with FreeBSD 13.0, and
can be enabled with "sysctl kern.ipc.tls.enable=1" and "kldload ktls_ocf"
to load a software backend, see man ktls(4) for details.

On Linux, kernel TLS is available starting with kernel 4.13 (at least 5.2
is recommended), and needs kernel compiled with CONFIG_TLS=y (with
CONFIG_TLS=m, which is used at least on Ubuntu 21.04 by default,
the tls module needs to be loaded with "modprobe tls").
2021-10-21 18:44:07 +03:00
Maxim Dounin
3ab1b64463 Style: added missing "static" specifiers.
Mostly found by gcc -Wtraditional, per "non-static declaration of ...
follows static declaration [-Wtraditional]" warnings.
2021-10-21 18:43:13 +03:00
Maxim Dounin
f29d7ade54 Removed CLOCK_MONOTONIC_COARSE support.
While clock_gettime(CLOCK_MONOTONIC_COARSE) is faster than
clock_gettime(CLOCK_MONOTONIC), the latter is fast enough on Linux for
practical usage, and the difference is negligible compared to other costs
at each event loop iteration.  On the other hand, CLOCK_MONOTONIC_COARSE
causes various issues with typical CONFIG_HZ=250, notably very inaccurate
limit_rate handling in some edge cases (ticket #1678) and negative difference
between $request_time and $upstream_response_time (ticket #1965).
2021-10-21 18:38:38 +03:00
Vladimir Homutov
1fecec0cbf Mail: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].

For POP3 and IMAP protocols IANA-assigned ALPN IDs are used [2].
For the SMTP protocol "smtp" is used.

[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
2021-10-20 09:45:34 +03:00
Vladimir Homutov
ebb6f7d656 HTTP: connections with wrong ALPN protocols are now rejected.
This is a recommended behavior by RFC 7301 and is useful
for mitigation of protocol confusion attacks [1].

To avoid possible negative effects, list of supported protocols
was extended to include all possible HTTP protocol ALPN IDs
registered by IANA [2], i.e. "http/1.0" and "http/0.9".

[1] https://alpaca-attack.com/
[2] https://www.iana.org/assignments/tls-extensiontype-values/
2021-10-20 09:50:02 +03:00
Vladimir Homutov
df472eecc0 Stream: the "ssl_alpn" directive.
The directive sets the server list of supported application protocols
and requires one of this protocols to be negotiated if client is using
ALPN.
2021-10-19 12:19:59 +03:00
Vladimir Homutov
a9f4f25b72 SSL: added $ssl_alpn_protocol variable.
The variable contains protocol selected by ALPN during handshake and
is empty otherwise.
2021-10-14 11:46:23 +03:00
Vladimir Homutov
1db517fb71 HTTP/2: removed support for NPN.
NPN was replaced with ALPN, published as RFC 7301 in July 2014.
It used to negotiate SPDY (and, in transition, HTTP/2).

NPN supported appeared in OpenSSL 1.0.1. It does not work with TLSv1.3 [1].
ALPN is supported since OpenSSL 1.0.2.

The NPN support was dropped in Firefox 53 [2] and Chrome 51 [3].

[1] https://github.com/openssl/openssl/issues/3665.
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1248198
[3] https://www.chromestatus.com/feature/5767920709795840
2021-10-15 10:02:15 +03:00
Maxim Dounin
dde319ee0c Upstream: fixed logging level of upstream invalid header errors.
In b87b7092cedb (nginx 1.21.1), logging level of "upstream sent invalid
header" errors was accidentally changed to "info".  This change restores
the "error" level, which is a proper logging level for upstream-side
errors.
2021-10-18 16:46:59 +03:00
Maxim Dounin
6119609cae Synced ngx_http_subrequest() argument names (ticket #2255). 2021-10-12 23:18:18 +03:00
Awdhesh Mathpal
2a88047ac1 Proxy: disabled keepalive on extra data in non-buffered mode.
The u->keepalive flag is initialized early if the response has no body
(or an empty body), and needs to be reset if there are any extra data,
similarly to how it is done in ngx_http_proxy_copy_filter().  Missed
in 83c4622053b0.
2021-10-07 19:23:11 -07:00
Maxim Dounin
c9c3f2f005 Fixed $content_length cacheability with chunked (ticket #2252). 2021-10-06 18:01:42 +03:00
Vladimir Homutov
e56ba23158 Stream: added half-close support.
The "proxy_half_close" directive enables handling of TCP half close.  If
enabled, connection to proxied server is kept open until both read ends get
EOF.  Write end shutdown is properly transmitted via proxy.
2021-09-22 10:20:00 +03:00
Roman Arutyunyan
adbd28b7a9 Request body: do not create temp file if there's nothing to write.
Do this only when the entire request body is empty and
r->request_body_in_file_only is set.

The issue manifested itself with missing warning "a client request body is
buffered to a temporary file" when the entire rb->buf is full and all buffers
are delayed by a filter.
2021-09-10 12:59:22 +03:00
Roman Arutyunyan
8165597cf6 Version bump. 2021-09-14 12:12:02 +03:00
Maxim Dounin
243469df65 HTTP/2: optimized processing of small DATA frames.
The request body filter chain is no longer called after processing
a DATA frame.  Instead, we now post a read event to do this.  This
ensures that multiple small DATA frames read during the same event loop
iteration are coalesced together, resulting in much faster processing.

Since rb->buf can now contain unprocessed data, window update is no
longer sent in ngx_http_v2_state_read_data() in case of flow control
being used due to filter buffering.  Instead, window will be updated
by ngx_http_v2_read_client_request_body_handler() in the posted read
event.
2021-09-06 14:54:50 +03:00
Maxim Dounin
584a30b4d5 HTTP/2: fixed timers left after request body reading.
Following rb->filter_need_buffering changes, request body reading is
only finished after the filter chain is called and rb->last_saved is set.
As such, with r->request_body_no_buffering, timer on fc->read is no
longer removed when the last part of the body is received, potentially
resulting in incorrect behaviour.

The fix is to call ngx_http_v2_process_request_body() from the
ngx_http_v2_read_unbuffered_request_body() function instead of
directly calling ngx_http_v2_filter_request_body(), so the timer
is properly removed.
2021-09-06 14:54:48 +03:00
Maxim Dounin
27fb6cdb9f HTTP/2: fixed window updates when buffering in filters.
In the body read handler, the window was incorrectly calculated
based on the full buffer size instead of the amount of free space
in the buffer.  If the request body is buffered by a filter, and
the buffer is not empty after the read event is generated by the
filter to resume request body processing, this could result in
"http2 negative window update" alerts.

Further, in the body ready handler and in ngx_http_v2_state_read_data()
the buffer wasn't cleared when the data were already written to disk,
so the client might stuck without window updates.
2021-09-06 14:54:47 +03:00
Roman Arutyunyan
16557ff8b6 Fixed debug logging. 2021-09-02 12:25:37 +03:00
Roman Arutyunyan
3575f44a17 Version bump. 2021-09-03 17:19:33 +03:00
Maxim Dounin
15bf6d8cc9 HTTP/2: avoid memcpy() with NULL source and zero length.
Prodded by Clang Static Analyzer.
2021-08-31 16:44:13 +03:00
Sergey Kandaurov
1e8c0d4e06 Give GCC atomics precedence over deprecated Darwin atomic(3).
This allows to build nginx on macOS with -Wdeprecated-declarations.
2021-08-30 14:45:21 +03:00
Maxim Dounin
67d160bf25 Request body: reading body buffering in filters.
If a filter wants to buffer the request body during reading (for
example, to check an external scanner), it can now do so.  To make
it possible, the code now checks rb->last_saved (introduced in the
previous change) along with rb->rest == 0.

Since in HTTP/2 this requires flow control to avoid overflowing the
request body buffer, so filters which need buffering have to set
the rb->filter_need_buffering flag on the first filter call.  (Note
that each filter is expected to call the next filter, so all filters
will be able set the flag if needed.)
2021-08-29 22:22:02 +03:00
Maxim Dounin
2a70921380 Request body: introduced rb->last_saved flag.
It indicates that the last buffer was received by the save filter,
and can be used to check this at higher levels.  To be used in the
following changes.
2021-08-29 22:21:03 +03:00
Maxim Dounin
fd9d43b087 Request body: added alert to catch duplicate body saving.
If due to an error ngx_http_request_body_save_filter() is called
more than once with rb->rest == 0, this used to result in a segmentation
fault.  Added an alert to catch such errors, just in case.
2021-08-29 22:20:54 +03:00
Maxim Dounin
aa02695f5e Request body: missing comments about initialization. 2021-08-29 22:20:49 +03:00
Maxim Dounin
2862eb40e8 HTTP/2: improved handling of preread unbuffered requests.
Previously, fully preread unbuffered requests larger than client body
buffer size were saved to disk, despite the fact that "unbuffered" is
expected to imply no disk buffering.
2021-08-29 22:20:44 +03:00
Maxim Dounin
9f90d11cf5 HTTP/2: improved handling of END_STREAM in a separate DATA frame.
The save body filter saves the request body to disk once the buffer is full.
Yet in HTTP/2 this might happen even if there is no need to save anything
to disk, notably when content length is known and the END_STREAM flag is
sent in a separate empty DATA frame.  Workaround is to provide additional
byte in the buffer, so saving the request body won't be triggered.

This fixes unexpected request body disk buffering in HTTP/2 observed after
the previous change when content length is known and the END_STREAM flag
is sent in a separate empty DATA frame.
2021-08-29 22:20:38 +03:00
Maxim Dounin
78d9a3af91 HTTP/2: reworked body reading to better match HTTP/1.x code.
In particular, now the code always uses a buffer limited by
client_body_buffer_size.  At the cost of an additional copy it
ensures that small DATA frames are not directly mapped to small
write() syscalls, but rather buffered in memory before writing.
Further, requests without Content-Length are no longer forced
to use temporary files.
2021-08-29 22:20:36 +03:00
Maxim Dounin
301efb8a73 HTTP/2: improved body reading logging. 2021-08-29 22:20:34 +03:00
Maxim Dounin
c231640eba Upstream: fixed timeouts with gRPC, SSL and select (ticket #2229).
With SSL it is possible that an established connection is ready for
reading after the handshake.  Further, events might be already disabled
in case of level-triggered event methods.  If this happens and
ngx_http_upstream_send_request() blocks waiting for some data from
the upstream, such as flow control in case of gRPC, the connection
will time out due to no read events on the upstream connection.

Fix is to explicitly check the c->read->ready flag if sending request
blocks and post a read event if it is set.

Note that while it is possible to modify ngx_ssl_handshake() to keep
read events active, this won't completely resolve the issue, since
there can be data already received during the SSL handshake
(see 573bd30e46b4).
2021-08-20 03:53:56 +03:00
Rob Mueller
d4dad02e5e Mail: Auth-SSL-Protocol and Auth-SSL-Cipher headers (ticket #2134).
This adds new Auth-SSL-Protocol and Auth-SSL-Cipher headers to
the mail proxy auth protocol when SSL is enabled.

This can be useful for detecting users using older clients that
negotiate old ciphers when you want to upgrade to newer
TLS versions of remove suppport for old and insecure ciphers.
You can use your auth backend to notify these users before the
upgrade that they either need to upgrade their client software
or contact your support team to work out an upgrade path.
2021-08-13 03:57:47 -04:00
Maxim Dounin
ce5996cdd1 SSL: ciphers now set before loading certificates (ticket #2035).
To load old/weak server or client certificates it might be needed to adjust
the security level, as introduced in OpenSSL 1.1.0.  This change ensures that
ciphers are set before loading the certificates, so security level changes
via the cipher string apply to certificate loading.
2021-08-16 22:40:31 +03:00
Sergey Kandaurov
926e0aa70a SSL: removed use of the SSL_OP_MSIE_SSLV2_RSA_PADDING option.
It has no effect since OpenSSL 0.9.7h and 0.9.8a.
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
9e4e7a4e42 SSL: removed export ciphers support.
Export ciphers are forbidden to negotiate in TLS 1.1 and later protocol modes.
They are disabled since OpenSSL 1.0.2g by default unless explicitly configured
with "enable-weak-ssl-ciphers", and completely removed in OpenSSL 1.1.0.
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
5155845ce4 SSL: use of the SSL_OP_IGNORE_UNEXPECTED_EOF option.
A new behaviour was introduced in OpenSSL 1.1.1e, when a peer does not send
close_notify before closing the connection.  Previously, it was to return
SSL_ERROR_SYSCALL with errno 0, known since at least OpenSSL 0.9.7, and is
handled gracefully in nginx.  Now it returns SSL_ERROR_SSL with a distinct
reason SSL_R_UNEXPECTED_EOF_WHILE_READING ("unexpected eof while reading").
This leads to critical errors seen in nginx within various routines such as
SSL_do_handshake(), SSL_read(), SSL_shutdown().  The behaviour was restored
in OpenSSL 1.1.1f, but presents in OpenSSL 3.0 by default.

Use of the SSL_OP_IGNORE_UNEXPECTED_EOF option added in OpenSSL 3.0 allows
to set a compatible behaviour to return SSL_ERROR_ZERO_RETURN:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=09b90e0

See for additional details: https://github.com/openssl/openssl/issues/11381
2021-08-10 23:43:17 +03:00
Sergey Kandaurov
3df7efd34b SSL: silenced warnings when building with OpenSSL 3.0.
The OPENSSL_SUPPRESS_DEPRECATED macro is used to suppress deprecation warnings.
This covers Session Tickets keys, SSL Engine, DH low level API for DHE ciphers.

Unlike OPENSSL_API_COMPAT, it works well with OpenSSL built with no-deprecated.
In particular, it doesn't unhide various macros in OpenSSL includes, which are
meant to be hidden under OPENSSL_NO_DEPRECATED.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
9609288e7c SSL: ERR_peek_error_line_data() compatibility with OpenSSL 3.0.
ERR_peek_error_line_data() was deprecated in favour of ERR_peek_error_all().
Here we use the ERR_peek_error_data() helper to pass only used arguments.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
b26858aa3c SSL: using SSL_CTX_set0_tmp_dh_pkey() with OpenSSL 3.0 in dhparam.
Using PEM_read_bio_DHparams() and SSL_CTX_set_tmp_dh() is deprecated
as part of deprecating the low level DH functions in favor of EVP_PKEY:
https://git.openssl.org/?p=openssl.git;a=commitdiff;h=163f6dc
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
ccc9bbad32 SSL: SSL_get_peer_certificate() is deprecated in OpenSSL 3.0.
Switch to SSL_get1_peer_certificate() when building with OpenSSL 3.0
and OPENSSL_NO_DEPRECATED defined.
2021-08-10 23:43:16 +03:00
Sergey Kandaurov
36af236d6e SSL: RSA data type is deprecated in OpenSSL 3.0.
The only consumer is a callback function for SSL_CTX_set_tmp_rsa_callback()
deprecated in OpenSSL 1.1.0.  Now the function is conditionally compiled too.
2021-08-10 23:42:59 +03:00
Sergey Kandaurov
7bcb50c061 Disabled HTTP/1.0 requests with Transfer-Encoding.
The latest HTTP/1.1 draft describes Transfer-Encoding in HTTP/1.0 as having
potentially faulty message framing as that could have been forwarded without
handling of the chunked encoding, and forbids processing subsequest requests
over that connection: https://github.com/httpwg/http-core/issues/879.

While handling of such requests is permitted, the most secure approach seems
to reject them.
2021-08-09 18:12:12 +03:00
Sergey Kandaurov
02bd43d05b SSL: SSL_CTX_set_tmp_dh() error handling.
For example, it can fail due to weak DH parameters.
2021-08-04 21:27:51 +03:00
Maxim Dounin
15769c3918 SSL: set events ready flags after handshake.
The c->read->ready and c->write->ready flags might be reset during
the handshake, and not set again if the handshake was finished on
the other event.  At the same time, some data might be read from
the socket during the handshake, so missing c->read->ready flag might
result in a connection hang, for example, when waiting for an SMTP
greeting (which was already received during the handshake).

Found by Sergey Kandaurov.
2021-08-03 20:50:30 +03:00
Maxim Dounin
f8394db6fe Version bump. 2021-08-03 20:50:08 +03:00
Ruslan Ermilov
b445d1884f Win32: use only preallocated memory in send/recv chain functions.
The ngx_wsasend_chain() and ngx_wsarecv_chain() functions were
modified to use only preallocated memory, and the number of
preallocated wsabufs was increased to 64.
2021-07-05 13:26:49 +03:00
Ruslan Ermilov
b20768e61c Use only preallocated memory in ngx_readv_chain() (ticket #1408).
In d1bde5c3c5d2, the number of preallocated iovec's for ngx_readv_chain()
was increased.  Still, in some setups, the function might allocate memory
for iovec's from a connection pool, which is only freed when closing the
connection.

The ngx_readv_chain() function was modified to use only preallocated
memory, similarly to the ngx_writev_chain() change in 8e903522c17a.
2021-07-05 13:09:23 +03:00
Maxim Dounin
07c63a4264 Disabled control characters in the Host header.
Control characters (0x00-0x1f, 0x7f) and space are not expected to appear
in the Host header.  Requests with such characters in the Host header are
now unconditionally rejected.
2021-06-28 18:01:24 +03:00
Maxim Dounin
7587778a33 Improved logging of invalid headers.
In 71edd9192f24 logging of invalid headers which were rejected with the
NGX_HTTP_PARSE_INVALID_HEADER error was restricted to just the "client
sent invalid header line" message, without any attempts to log the header
itself.

This patch returns logging of the header up to the invalid character and
the character itself.  The r->header_end pointer is now properly set
in all cases to make logging possible.

The same logging is also introduced when parsing headers from upstream
servers.
2021-06-28 18:01:20 +03:00
Maxim Dounin
9ab4d368af Disabled control characters and space in header names.
Control characters (0x00-0x1f, 0x7f), space, and colon were never allowed in
header names.  The only somewhat valid use is header continuation which nginx
never supported and which is explicitly obsolete by RFC 7230.

Previously, such headers were considered invalid and were ignored by default
(as per ignore_invalid_headers directive).  With this change, such headers
are unconditionally rejected.

It is expected to make nginx more resilient to various attacks, in particular,
with ignore_invalid_headers switched off (which is inherently unsecure, though
nevertheless sometimes used in the wild).
2021-06-28 18:01:18 +03:00
Maxim Dounin
0b66bd4be7 Disabled control characters in URIs.
Control characters (0x00-0x1f, 0x7f) were never allowed in URIs, and must
be percent-encoded by clients.  Further, these are not believed to appear
in practice.  On the other hand, passing such characters might make various
attacks possible or easier, despite the fact that currently allowed control
characters are not significant for HTTP request parsing.
2021-06-28 18:01:15 +03:00
Maxim Dounin
05395f4889 Disabled spaces in URIs (ticket #196).
From now on, requests with spaces in URIs are immediately rejected rather
than allowed.  Spaces were allowed in 31e9677b15a1 (0.8.41) to handle bad
clients.  It is believed that now this behaviour causes more harm than
good.
2021-06-28 18:01:13 +03:00
Maxim Dounin
fee09fc49d Core: escaping of chars not allowed in URIs per RFC 3986.
Per RFC 3986 only the following characters are allowed in URIs unescaped:

unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

And "%" can appear as a part of escaping itself.  The following
characters are not allowed and need to be escaped: %00-%1F, %7F-%FF,
" ", """, "<", ">", "\", "^", "`", "{", "|", "}".

Not escaping ">" is known to cause problems at least with MS Exchange (see
http://nginx.org/pipermail/nginx-ru/2010-January/031261.html) and in
Tomcat (ticket #2191).

The patch adds escaping of the following chars in all URI parts: """, "<",
">", "\", "^", "`", "{", "|", "}".  Note that comments are mostly preserved
to outline important characters being escaped.
2021-06-28 18:01:11 +03:00
Maxim Dounin
31d1c34b39 Core: fixed comment about escaping in arguments.
After 4954530db2af, the ";" character is escaped by
ngx_escape_uri(NGX_ESCAPE_ARGS).
2021-06-28 18:01:09 +03:00
Maxim Dounin
a6c109fea5 Disabled requests with both Content-Length and Transfer-Encoding.
HTTP clients are not allowed to generate such requests since Transfer-Encoding
introduction in RFC 2068, and they are not expected to appear in practice
except in attempts to perform a request smuggling attack.  While handling of
such requests is strictly defined, the most secure approach seems to reject
them.
2021-06-28 18:01:06 +03:00
Maxim Dounin
5f85bb3714 Added CONNECT method rejection.
No valid CONNECT requests are expected to appear within nginx, since it
is not a forward proxy.  Further, request line parsing will reject
proper CONNECT requests anyway, since we don't allow authority-form of
request-target.  On the other hand, RFC 7230 specifies separate message
length rules for CONNECT which we don't support, so make sure to always
reject CONNECTs to avoid potential abuse.
2021-06-28 18:01:04 +03:00
Maxim Dounin
d9c1d1bae7 Moved TRACE method rejection to a better place.
Previously, TRACE requests were rejected before parsing Transfer-Encoding.
This is not important since keepalive is not enabled at this point anyway,
though rejecting such requests after properly parsing other headers is
less likely to cause issues in case of further code changes.
2021-06-28 18:01:00 +03:00
Vladimir Homutov
8b92710728 Core: added the ngx_rbtree_data() macro. 2021-06-21 09:42:43 +03:00
Maxim Dounin
a407583ef1 Fixed format strings for ngx_win32_version. 2021-06-18 04:00:21 +03:00
Sergey Kandaurov
693e4134a5 gRPC: RST_STREAM(NO_ERROR) handling micro-optimization.
After 2096b21fcd10, a single RST_STREAM(NO_ERROR) may not result in an error.
This change removes several unnecessary ctx->type checks for such a case.
2021-06-17 11:44:06 +03:00
Sergey Kandaurov
dcdf7ec096 gRPC: handling GOAWAY with a higher last stream identifier.
Previously, once received from upstream, it couldn't limit
opening additional streams in a cached keepalive connection.
2021-06-17 11:43:55 +03:00
Maxim Dounin
5eadaf69e3 Fixed SSL logging with lingering close.
Recent fixes to SSL shutdown with lingering close (554c6ae25ffc, 1.19.5)
broke logging of SSL variables.  To make sure logging of SSL variables
works properly, avoid freeing c->ssl when doing an SSL shutdown before
lingering close.

Reported by Reinis Rozitis
(http://mailman.nginx.org/pipermail/nginx/2021-May/060670.html).
2021-06-01 17:37:51 +03:00
Maxim Dounin
235d2df1de SSL: ngx_ssl_shutdown() rework.
Instead of calling SSL_free() with each return point, introduced a single
place where cleanup happens.  As a positive side effect, this fixes two
potential memory leaks on ngx_handle_read_event() and ngx_handle_write_event()
errors where there were no SSL_free() calls (though unlikely practical,
as errors there are only expected to happen due to bugs or kernel issues).
2021-06-01 17:37:49 +03:00
Maxim Dounin
52cde89586 Core: disabled SO_REUSEADDR on UDP sockets while testing config.
On Linux, SO_REUSEADDR allows completely duplicate UDP sockets, so using
SO_REUSEADDR when testing configuration results in packets being dropped
if there is an existing traffic on the sockets being tested (ticket #2187).
While dropped packets are expected with UDP, it is better to avoid this
when possible.

With this change, SO_REUSEADDR is no longer set on datagram sockets when
testing configuration.
2021-05-31 16:36:51 +03:00
Maxim Dounin
85a104aa4e Core: disabled cloning sockets when testing config (ticket #2188).
Since we anyway do not set SO_REUSEPORT when testing configuration
(see ecb5cd305b06), trying to open additional sockets does not make much
sense, as all these additional sockets are expected to result in EADDRINUSE
errors from bind().  On the other hand, there are reports that trying
to open these sockets takes significant time under load: total configuration
testing time greater than 15s was observed in ticket #2188, compared to less
than 1s without load.

With this change, no additional sockets are opened during testing
configuration.
2021-05-31 16:36:37 +03:00
Maxim Dounin
427cfff79b Version bump. 2021-05-31 16:36:12 +03:00
Maxim Dounin
e860ecce82 Resolver: explicit check for compression pointers in question.
Since nginx always uses exactly one entry in the question section of
a DNS query, and never uses compression pointers in this entry, parsing
of a DNS response in ngx_resolver_process_response() does not expect
compression pointers to appear in the question section of the DNS
response.  Indeed, compression pointers in the first name of a DNS response
hardly make sense, do not seem to be allowed by RFC 1035 (which says
"a pointer to a prior occurance of the same name", note "prior"), and
were never observed in practice.

Added an explicit check to ngx_resolver_process_response()'s parsing
of the question section to properly report an error if compression pointers
nevertheless appear in the question section.
2021-05-25 15:17:50 +03:00
Maxim Dounin
f85d701694 Resolver: simplified ngx_resolver_copy().
Instead of checking on each label if we need to place a dot or not,
now it always adds a dot after a label, and reduces the resulting
length afterwards.
2021-05-25 15:17:45 +03:00
Maxim Dounin
f1dd1d50e0 Resolver: reworked ngx_resolver_copy() copy loop.
To make the code easier to read, reworked the ngx_resolver_copy()
copy loop to match the one used to calculate length.  No functional
changes.
2021-05-25 15:17:43 +03:00
Maxim Dounin
bbd403a7ab Resolver: fixed label types handling in ngx_resolver_copy().
Previously, anything with any of the two high bits set were interpreted
as compression pointers.  This is incorrect, as RFC 1035 clearly states
that "The 10 and 01 combinations are reserved for future use".  Further,
the 01 combination is actually allocated for EDNS extended label type
(see RFC 2671 and RFC 6891), not really used though.

Fix is to reject unrecognized label types rather than misinterpreting
them as compression pointers.
2021-05-25 15:17:41 +03:00
Maxim Dounin
077a890a76 Resolver: fixed off-by-one read in ngx_resolver_copy().
It is believed to be harmless, and in the worst case it uses some
uninitialized memory as a part of the compression pointer length,
eventually leading to the "name is out of DNS response" error.
2021-05-25 15:17:38 +03:00
Maxim Dounin
9f1dcb0c04 Resolver: fixed off-by-one write in ngx_resolver_copy().
Reported by Luis Merino, Markus Vervier, Eric Sesterhenn, X41 D-Sec GmbH.
2021-05-25 15:17:36 +03:00
Ruslan Ermilov
41a241b3ef Location header escaping in redirects (ticket #882).
The header is escaped in redirects based on request URI or
location name (auto redirect).
2021-05-24 21:55:20 +03:00
Maxim Dounin
52d0ec7d17 Fixed log action when using SSL certificates with variables.
When variables are used in ssl_certificate or ssl_certificate_key, a request
is created in the certificate callback to evaluate the variables, and then
freed.  Freeing it, however, updates c->log->action to "closing request",
resulting in confusing error messages like "client timed out ... while
closing request" when a client times out during the SSL handshake.

Fix is to restore c->log->action after calling ngx_http_free_request().
2021-05-24 18:23:42 +03:00
Ruslan Ermilov
ecbe06b9fe Stream: the "fastopen" parameter of the "listen" directive.
Based on a patch by Anbang Wen.
2021-05-20 19:59:16 +03:00
Ruslan Ermilov
6029e211c6 Core: fixed comment about msie_refresh escaping.
After 12a656452ad1, the "%" character is no longer escaped by
ngx_escape_uri(NGX_ESCAPE_REFRESH).
2021-05-19 16:24:13 +03:00
Maxim Dounin
173f16f736 Mail: max_errors directive.
Similarly to smtpd_hard_error_limit in Postfix and smtp_max_unknown_commands
in Exim, specifies the number of errors after which the connection is closed.
2021-05-19 03:13:31 +03:00
Maxim Dounin
5015209054 Mail: IMAP pipelining support.
The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a),
and ensures that nginx is able to properly handle or reject multiple IMAP
commands.  The s->cmd field is not really used and set for consistency.

Non-synchronizing literals handling in invalid/unknown commands is limited,
so when a non-synchronizing literal is detected at the end of a discarded
line, the connection is closed.
2021-05-19 03:13:28 +03:00
Maxim Dounin
4617dd64b8 Mail: stricter checking of IMAP tags.
Only "A-Za-z0-9-._" characters now allowed (which is stricter than what
RFC 3501 requires, but expected to be enough for all known clients),
and tags shouldn't be longer than 32 characters.
2021-05-19 03:13:26 +03:00
Maxim Dounin
82840d1651 Mail: fixed backslash handling in IMAP literals.
Previously, s->backslash was set if any of the arguments was a quoted
string with a backslash character.  After successful command parsing
this resulted in all arguments being filtered to remove backslashes.
This is, however, incorrect, as backslashes should not be removed from
IMAP literals.  For example:

   S: * OK IMAP4 ready
   C: a01 login {9}
   S: + OK
   C: user\name "pass\"word"
   S: * BAD internal server error

resulted in "Auth-User: username" instead of "Auth-User: user\name"
as it should.

Fix is to apply backslash filtering on per-argument basis during parsing.
2021-05-19 03:13:23 +03:00
Maxim Dounin
fabe28259f Mail: removed dead s->arg_start handling.
As discussed in the previous change, s->arg_start handling in the "done"
labels of ngx_mail_pop3_parse_command(), ngx_mail_imap_parse_command(),
and ngx_mail_smtp_parse_command() is wrong: s->arg_start cannot be
set there, as it is handled and cleared on all code paths where the
"done" labels are reached.  The relevant code is dead and now removed.
2021-05-19 03:13:22 +03:00
Maxim Dounin
3c660ef59b Mail: fixed s->arg_start clearing on invalid IMAP commands.
Previously, s->arg_start was left intact after invalid IMAP commands,
and this might result in an argument incorrectly added to the following
command.  Similarly, s->backslash was left intact as well, leading
to unneeded backslash removal.

For example (LFs from the client are explicitly shown as "<LF>"):

  S: * OK IMAP4 ready
  C: a01 login "\<LF>
  S: a01 BAD invalid command
  C: a0000000000\2 authenticate <LF>
  S: a00000000002 aBAD invalid command

The backslash followed by LF generates invalid command with s->arg_start
and s->backslash set, the following command incorrectly treats anything
from the old s->arg_start to the space after the command as an argument,
and removes the backslash from the tag.  If there is no space, s->arg_end
will be NULL.

Both things seem to be harmless though.  In particular:

- This can be used to provide an incorrect argument to a command without
  arguments.  The only command which seems to look at the single argument
  is AUTHENTICATE, and it checks the argument length before trying to
  access it.

- Backslash removal uses the "end" pointer, and stops due to "src < end"
  condition instead of scanning all the process memory if s->arg_end is
  NULL (and arg[0].len is huge).

- There should be no backslashes in unquoted strings.

An obvious fix is to clear s->arg_start and s->backslash on invalid commands,
similarly to how it is done in POP3 parsing (added in 810:e3aa8f305d21) and
SMTP parsing.

This, however, makes it clear that s->arg_start handling in the "done"
label is wrong: s->arg_start cannot be legitimately set there, as it
is expected to be cleared in all possible cases when the "done" label is
reached.  The relevant code is dead and will be removed by the following
change.
2021-05-19 03:13:20 +03:00
Maxim Dounin
d96d60d2e0 Mail: POP3 pipelining support.
The change is mostly the same as the SMTP one (04e43d03e153 and 3f5d0af4e40a),
and ensures that nginx is able to properly handle or reject multiple POP3
commands, as required by the PIPELINING capability (RFC 2449).  The s->cmd
field is not really used and set for consistency.
2021-05-19 03:13:18 +03:00
Maxim Dounin
317223cb56 Mail: optimized discarding invalid SMTP commands.
There is no need to scan buffer from s->buffer->pos, as we already scanned
the buffer till "p" and wasn't able to find an LF.

There is no real need for this change in SMTP, since it is at most a
microoptimization of a non-common code path.  Similar code in IMAP, however,
will have to start scanning from "p" to be correct, since there can be
newlines in IMAP literals.
2021-05-19 03:13:17 +03:00
Maxim Dounin
204f944add Mail: fixed handling of invalid SMTP commands split between reads.
Previously, if an invalid SMTP command was split between reads, nginx failed
to wait for LF before returning an error, and interpreted the rest of the
command received later as a separate command.

The sw_invalid state in ngx_mail_smtp_parse_command(), introduced in
04e43d03e153, did not work, since ngx_mail_smtp_auth_state() clears
s->state when returning an error due to NGX_MAIL_PARSE_INVALID_COMMAND.
And not clearing s->state will introduce another problem: the rest
of the command would trigger duplicate error when rest of the command is
received.

Fix is to return NGX_AGAIN from ngx_mail_smtp_parse_command() until full
command is received.
2021-05-19 03:13:15 +03:00
Maxim Dounin
60a5a6f0d3 Mail: fixed SMTP pipelining to send the response immediately.
Previously, if there were some pipelined SMTP data in the buffer when
a proxied connection with the backend was established, nginx called
ngx_mail_proxy_handler() to send these data, and not tried to send the
response to the last command.  In most cases, this response was later sent
along with the response to the pipelined command, but if for some reason
client decides to wait for the response before finishing the next command
this might result in a connection hang.

Fix is to always call ngx_mail_proxy_handler() to send the response, and
additionally post an event to send the pipelined data if needed.
2021-05-19 03:13:12 +03:00
Maxim Dounin
c7de65228f Upstream: variables support in certificates. 2021-05-06 02:22:09 +03:00
Maxim Dounin
a6bce8c227 Auth basic: changed alcf->user_file to be a pointer.
This saves some memory in typical case when auth_basic_user_file is not
explicitly set, and unifies the code with alcf->realm.
2021-05-06 02:22:07 +03:00
Maxim Dounin
4faa840853 Changed complex value slots to use NGX_CONF_UNSET_PTR.
With this change, it is now possible to use ngx_conf_merge_ptr_value()
to merge complex values.  This change follows much earlier changes in
ngx_conf_merge_ptr_value() and ngx_conf_set_str_array_slot()
in 1452:cd586e963db0 (0.6.10) and 1701:40d004d95d88 (0.6.22), and the
change in ngx_conf_set_keyval_slot() (7728:485dba3e2a01, 1.19.4).

To preserve compatibility with existing 3rd party modules, both NULL
and NGX_CONF_UNSET_PTR are accepted for now.
2021-05-06 02:22:03 +03:00
Ruslan Ermilov
f02e2a734e Restored zeroing of ngx_channel_t in ngx_pass_open_channel().
Due to structure's alignment, some uninitialized memory contents may have
been passed between processes.

Zeroing was removed in 0215ec9aaa8a.

Reported by Johnny Wang.
2021-04-22 16:12:52 +03:00
Maxim Dounin
7b9920aad8 Mail: fixed reading with fully filled buffer (ticket #2159).
With SMTP pipelining, ngx_mail_read_command() can be called with s->buffer
without any space available, to parse additional commands received to the
buffer on previous calls.  Previously, this resulted in recv() being called
with zero length, resulting in zero being returned, which was interpreted
as a connection close by the client, so nginx silently closed connection.

Fix is to avoid calling c->recv() if there is no free space in the buffer,
but continue parsing of the already received commands.
2021-04-21 23:24:59 +03:00
Maxim Dounin
ead9ab0925 Version bump. 2021-04-21 23:24:48 +03:00
Maxim Dounin
eb52de8311 Changed keepalive_requests default to 1000 (ticket #2155).
It turns out no browsers implement HTTP/2 GOAWAY handling properly, and
large enough number of resources on a page results in failures to load
some resources.  In particular, Chrome seems to experience errors if
loading of all resources requires more than 1 connection (while it
is usually able to retry requests at least once, even with 2 connections
there are occasional failures for some reason), Safari if loading requires
more than 3 connections, and Firefox if loading requires more than 10
connections (can be configured with network.http.request.max-attempts,
defaults to 10).

It does not seem to be possible to resolve this on nginx side, even strict
limiting of maximum concurrency does not help, and loading issues seems to
be triggered by merely queueing of a request for a particular connection.
The only available mitigation seems to use higher keepalive_requests value.

The new default is 1000 and matches previously used default for
http2_max_requests.  It is expected to be enough for 99.98% of the pages
(https://httparchive.org/reports/state-of-the-web?start=latest#reqTotal)
even in Chrome.
2021-04-08 00:16:30 +03:00
Maxim Dounin
497acbd0ed Added $connection_time variable. 2021-04-08 00:16:17 +03:00
Maxim Dounin
d9996d6f27 Introduced the "keepalive_time" directive.
Similar to lingering_time, it limits total connection lifetime before
keepalive is switched off.  The default is 1 hour, which is close to
the total maximum connection lifetime possible with default
keepalive_requests and keepalive_timeout.
2021-04-08 00:15:48 +03:00
Maxim Dounin
5599731c00 HTTP/2: relaxed PRIORITY frames limit.
Firefox uses several idle streams for PRIORITY frames[1], and
"http2_max_concurrent_streams 1;" results in "client sent too many
PRIORITY frames" errors when a connection is established by Firefox.

Fix is to relax the PRIORITY frames limit to use at least 100 as
the initial value (which is the recommended by the HTTP/2 protocol
minimum limit on the number of concurrent streams, so it is not
unreasonable for clients to assume that similar number of idle streams
can be used for prioritization).

[1] https://hg.mozilla.org/mozilla-central/file/32a9e6e145d6e3071c3993a20bb603a2f388722b/netwerk/protocol/http/Http2Stream.cpp#l1270
2021-04-07 02:03:29 +03:00
Maxim Dounin
4af67214ad Gzip: updated handling of zlib variant from Intel.
In current versions (all versions based on zlib 1.2.11, at least
since 2018) it no longer uses 64K hash and does not force window
bits to 13 if it is less than 13.  That is, it needs just 16 bytes
more memory than normal zlib, so these bytes are simply added to
the normal size calculation.
2021-04-05 04:07:17 +03:00
Maxim Dounin
e3797a66a3 Gzip: support for zlib-ng. 2021-04-05 04:06:58 +03:00