summaryrefslogtreecommitdiffhomepage
path: root/src/http (follow)
AgeCommit message (Collapse)AuthorFilesLines
2025-02-05SNI: added restriction for TLSv1.3 cross-SNI session resumption.Sergey Kandaurov1-2/+25
In OpenSSL, session resumption always happens in the default SSL context, prior to invoking the SNI callback. Further, unlike in TLSv1.2 and older protocols, SSL_get_servername() returns values received in the resumption handshake, which may be different from the value in the initial handshake. Notably, this makes the restriction added in b720f650b insufficient for sessions resumed with different SNI server name. Considering the example from b720f650b, previously, a client was able to request example.org by presenting a certificate for example.org, then to resume and request example.com. The fix is to reject handshakes resumed with a different server name, if verification of client certificates is enabled in a corresponding server configuration.
2025-02-05Gzip: compatibility with recent zlib-ng 2.2.x versions.Sergey Kandaurov1-3/+5
It now uses 5/4 times more memory for the pending buffer. Further, a single allocation is now used, which takes additional 56 bytes for deflate_allocs in 64-bit mode aligned to 16, to store sub-allocation pointers, and the total allocation size now padded up to 128 bytes, which takes theoretically 200 additional bytes in total. This fits though into "4 * (64 + sizeof(void*))" additional space for ZALLOC used in zlib-ng 2.1.x versions. The comment was updated to reflect this.
2025-02-05Mp4: prevent chunk index underflow.Roman Arutyunyan1-0/+6
When cropping stsc atom, it's assumed that chunk index is never 0. Based on this assumption, start_chunk and end_chunk are calculated by subtracting 1 from it. If chunk index is zero, start_chunk or end_chunk may underflow, which will later trigger "start/end time is out mp4 stco chunks" error. The change adds an explicit check for zero chunk index to avoid underflow and report a proper error. Zero chunk index is explicitly banned in ISO/IEC 14496-12, 8.7.4 Sample To Chunk Box. It's also implicitly banned in QuickTime File Format specification. Description of chunk offset table references "Chunk 1" as the first table element.
2025-02-05Mp4: unordered stsc chunks error for the final chunk.Roman Arutyunyan1-0/+7
Currently an error is triggered if any of the chunk runs in stsc are unordered. This however does not include the final chunk run, which ends with trak->chunks + 1. The previous chunk index can be larger leading to a 32-bit overflow. This could allow to skip the validity check "if (start_sample > n)". This could later lead to a large trak->start_chunk/trak->end_chunk, which would be caught later in ngx_http_mp4_update_stco_atom() or ngx_http_mp4_update_co64_atom(). While there are no implications of the validity check being avoided, the change still adds a check to ensure the final chunk run is ordered, to produce a meaningful error and avoid a potential integer overflow.
2025-02-05Mp4: fixed handling an empty run of chunks in stsc atom.Roman Arutyunyan1-1/+4
A specially crafted mp4 file with an empty run of chunks in the stsc atom and a large value for samples per chunk for that run, combined with a specially crafted request, allowed to store that large value in prev_samples and later in trak->end_chunk_samples while in ngx_http_mp4_crop_stsc_data(). Later in ngx_http_mp4_update_stsz_atom() this could result in buffer overread while calculating trak->end_chunk_samples_size. Now the value of samples per chunk specified for an empty run is ignored.
2024-08-12Mp4: rejecting unordered chunks in stsc atom.Roman Arutyunyan1-0/+7
Unordered chunks could result in trak->end_chunk smaller than trak->start_chunk in ngx_http_mp4_crop_stsc_data(). Later in ngx_http_mp4_update_stco_atom() this caused buffer overread while trying to calculate trak->end_offset.
2024-08-12Mp4: fixed buffer underread while updating stsz atom.Roman Arutyunyan1-3/+4
While cropping an stsc atom in ngx_http_mp4_crop_stsc_data(), a 32-bit integer overflow could happen, which could result in incorrect seeking and a very large value stored in "samples". This resulted in a large invalid value of trak->end_chunk_samples. This value is further used to calculate the value of trak->end_chunk_samples_size in ngx_http_mp4_update_stsz_atom(). While doing this, a large invalid value of trak->end_chunk_samples could result in reading memory before stsz atom start. This could potentially result in a segfault.
2024-05-28HTTP/3: fixed handling of zero-length literal field line.Sergey Kandaurov1-0/+3
Previously, st->value was passed with NULL data pointer to header handlers.
2024-05-28HTTP/3: fixed dynamic table overflow.Roman Arutyunyan1-1/+1
While inserting a new entry into the dynamic table, first the entry is added, and then older entries are evicted until table size is within capacity. After the first step, the number of entries may temporarily exceed the maximum calculated from capacity by one entry, which previously caused table overflow. The easiest way to trigger the issue is to keep adding entries with empty names and values until first eviction. The issue was introduced by 987bee4363d1.
2024-05-28HTTP/3: decoder stream pre-creation.Roman Arutyunyan3-9/+17
Previously a decoder stream was created on demand for sending Section Acknowledgement, Stream Cancellation and Insert Count Increment. If conditions for sending any of these instructions never happen, a decoder stream is not created at all. These conditions include client not using the dynamic table and no streams abandoned by server (RFC 9204, Section 2.2.2.2). However RFC 9204, Section 4.2 defines only one condition for not creating a decoder stream: An endpoint MAY avoid creating a decoder stream if its decoder sets the maximum capacity of the dynamic table to zero. The change enables pre-creation of the decoder stream at HTTP/3 session initialization if maximum dynamic table capacity is not zero. Note that this value is currently hardcoded to 4096 bytes and is not configurable, so the stream is now always created. Also, the change fixes a potential stack overflow when creating a decoder stream in ngx_http_v3_send_cancel_stream() while draining a request stream by ngx_drain_connections(). Creating a decoder stream involves calling ngx_get_connection(), which calls ngx_drain_connections(), which will drain the same request stream again. If client's MAX_STREAMS for uni stream is high enough, these recursive calls will continue until we run out of stack. Otherwise, decoder stream creation will fail at some point and the request stream connection will be drained. This may result in use-after-free, since this connection could still be referenced up the stack.
2024-05-23Optimized chain link usage (ticket #2614).Roman Arutyunyan5-12/+37
Previously chain links could sometimes be dropped instead of being reused, which could result in increased memory consumption during long requests. A similar chain link issue in ngx_http_gzip_filter_module was fixed in da46bfc484ef (1.11.10). Based on a patch by Sangmin Lee.
2024-02-26Rewrite: fixed "return" directive without response text.Piotr Sikora1-0/+1
Previously, the response text wasn't initialized and the rewrite module was sending response body set to NULL. Found with UndefinedBehaviorSanitizer (pointer-overflow). Signed-off-by: Piotr Sikora <piotr@aviatrix.com>
2024-03-18Fixed undefined behaviour with IPv4-mapped IPv6 addresses.Sergey Kandaurov3-4/+4
Previously, it could result when left-shifting signed integer due to implicit integer promotion, such that the most significant bit appeared on the sign bit. In practice, though, this results in the same left value as with an explicit cast, at least on known compilers, such as GCC and Clang. The reason is that in_addr_t, which is equivalent to uint32_t and same as "unsigned int" in ILP32 and LP64 data type models, has the same type width as the intermediate after integer promotion, so there's no side effects such as sign-extension. This explains why adding an explicit cast does not change object files in practice. Found with UndefinedBehaviorSanitizer (shift). Based on a patch by Piotr Sikora.
2024-03-14Geo: fixed uninitialized memory access.Piotr Sikora1-3/+1
While copying ngx_http_variable_value_t structures to geo binary base in ngx_http_geo_copy_values(), and similarly in the stream module, uninitialized parts of these structures are copied as well. These include the "escape" field and possible holes. Calculating crc32 of this data triggers uninitialized memory access. Found with MemorySanitizer. Signed-off-by: Piotr Sikora <piotr@aviatrix.com>
2024-03-22Overhauled some diagnostic messages akin to 1b05b9bbcebf.Sergey Kandaurov2-2/+2
2024-01-30HTTP/3: added more compatibility checks for "listen ... quic".Sergey Kandaurov1-5/+31
Now "fastopen", "backlog", "accept_filter", "deferred", and "so_keepalive" parameters are not allowed with "quic" in the "listen" directive. Reported by Izorkin.
2024-01-30Upstream: fixed usage of closed sockets with filter finalization.Maxim Dounin1-0/+4
When filter finalization is triggered when working with an upstream server, and error_page redirects request processing to some simple handler, ngx_http_request_finalize() triggers request termination when the response is sent. In particular, via the upstream cleanup handler, nginx will close the upstream connection and the corresponding socket. Still, this can happen to be with ngx_event_pipe() on stack. While the code will set p->downstream_error due to NGX_ERROR returned from the output filter chain by filter finalization, otherwise the error will be ignored till control returns to ngx_http_upstream_process_request(). And event pipe might try reading from the (already closed) socket, resulting in "readv() failed (9: Bad file descriptor) while reading upstream" errors (or even segfaults with SSL). Such errors were seen with the following configuration: location /t2 { proxy_pass http://127.0.0.1:8080/big; image_filter_buffer 10m; image_filter resize 150 100; error_page 415 = /empty; } location /empty { return 204; } location /big { # big enough static file } Fix is to clear p->upstream in ngx_http_upstream_finalize_request(), and ensure that p->upstream is checked in ngx_event_pipe_read_upstream() and when handling events at ngx_event_pipe() exit.
2024-01-30Fixed request termination with AIO and subrequests (ticket #2555).Maxim Dounin5-23/+71
When a request was terminated due to an error via ngx_http_terminate_request() while an AIO operation was running in a subrequest, various issues were observed. This happened because ngx_http_request_finalizer() was only set in the subrequest where ngx_http_terminate_request() was called, but not in the subrequest where the AIO operation was running. After completion of the AIO operation normal processing of the subrequest was resumed, leading to issues. In particular, in case of the upstream module, termination of the request called upstream cleanup, which closed the upstream connection. Attempts to further work with the upstream connection after AIO operation completion resulted in segfaults in ngx_ssl_recv(), "readv() failed (9: Bad file descriptor) while reading upstream" errors, or socket leaks. In ticket #2555, issues were observed with the following configuration with cache background update (with thread writing instrumented to introduce a delay, when a client closes the connection during an update): location = /background-and-aio-write { proxy_pass ... proxy_cache one; proxy_cache_valid 200 1s; proxy_cache_background_update on; proxy_cache_use_stale updating; aio threads; aio_write on; limit_rate 1000; } Similarly, the same issue can be seen with SSI, and can be caused by errors in subrequests, such as in the following configuration (where "/proxy" uses AIO, and "/sleep" returns 444 after some delay, causing request termination): location = /ssi-active-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/proxy" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Or the same with both AIO operation and the error in non-active subrequests (which needs slightly different handling, see below): location = /ssi-non-active-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static" --> <!--#include virtual="/proxy" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Similarly, issues can be observed with just static files. However, with static files potential impact is limited due to timeout safeguards in ngx_http_writer(), and the fact that c->error is set during request termination. In a simple configuration with an AIO operation in the active subrequest, such as in the following configuration, the connection is closed right after completion of the AIO operation anyway, since ngx_http_writer() tries to write to the connection and fails due to c->error set: location = /ssi-active-static-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static-aio" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } In the following configuration, with an AIO operation in a non-active subrequest, the connection is closed only after send_timeout expires: location = /ssi-non-active-static-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static" --> <!--#include virtual="/static-aio" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Fix is to introduce r->main->terminated flag, which is to be checked by AIO event handlers when the r->main->blocked counter is decremented. When the flag is set, handlers are expected to wake up the connection instead of the subrequest (which might be already cleaned up). Additionally, now ngx_http_request_finalizer() is always set in the active subrequest, so waking up the connection properly finalizes the request even if termination happened in a non-active subrequest.
2024-01-29AIO operations now add timers (ticket #2162).Maxim Dounin3-0/+65
Each AIO (thread IO) operation being run is now accompanied with 1-minute timer. This timer prevents unexpected shutdown of the worker process while an AIO operation is running, and logs an alert if the operation is running for too long. This fixes "open socket left" alerts during worker processes shutdown due to pending AIO (or thread IO) operations while corresponding requests have no timers. In particular, such errors were observed while reading cache headers (ticket #2162), and with worker_shutdown_timeout.
2023-11-29HTTP: uniform checks in ngx_http_alloc_large_header_buffer().Vladimir Khomutov1-7/+25
If URI is not fully parsed yet, some pointers are not set. As a result, the calculation of "new + (ptr - old)" expression is flawed. According to C11, 6.5.6 Additive operators, p.9: : When two pointers are subtracted, both shall point to elements : of the same array object, or one past the last element of the : array object Since "ptr" is not set, subtraction leads to undefined behaviour, because "ptr" and "old" are not in the same buffer (i.e. array objects). Prodded by GCC undefined behaviour sanitizer.
2023-11-28HTTP: removed unused r->port_start and r->port_end.Vladimir Khomutov3-10/+0
Neither r->port_start nor r->port_end were ever used. The r->port_end is set by the parser, though it was never used by the following code (and was never usable, since not copied by the ngx_http_alloc_large_header_buffer() without r->port_start set).
2023-11-14HTTP/3: added Huffman decoding error logging.Sergey Kandaurov1-0/+2
2023-11-14Adjusted Huffman coding debug logging, missed in 7977:336084ff943b.Sergey Kandaurov1-3/+3
Spotted by XingY Wang.
2023-10-21HTTP/2: fixed buffer management with HTTP/2 auto-detection.Sergey Kandaurov2-6/+4
As part of normal HTTP/2 processing, incomplete frames are saved in the control state using a fixed size memcpy of NGX_HTTP_V2_STATE_BUFFER_SIZE. For this matter, two state buffers are reserved in the HTTP/2 recv buffer. As part of HTTP/2 auto-detection on plain TCP connections, initial data is first read into a buffer specified by the client_header_buffer_size directive that doesn't have state reservation. Previously, this made it possible to over-read the buffer as part of saving the state. The fix is to read the available buffer size rather than a fixed size. Although memcpy of a fixed size can produce a better optimized code, handling of incomplete frames isn't a common execution path, so it was sacrificed for the sake of simplicity of the fix.
2023-10-10HTTP/2: per-iteration stream handling limit.Maxim Dounin2-0/+17
To ensure that attempts to flood servers with many streams are detected early, a limit of no more than 2 * max_concurrent_streams new streams per one event loop iteration was introduced. This limit is applied even if max_concurrent_streams is not yet reached - for example, if corresponding streams are handled synchronously or reset. Further, refused streams are now limited to maximum of max_concurrent_streams and 100, similarly to priority_limit initial value, providing some tolerance to clients trying to open several streams at the connection start, yet low tolerance to flooding attempts.
2023-09-14HTTP/3: postponed session creation to init() callback.Roman Arutyunyan4-13/+13
Now the session object is assigned to c->data while ngx_http_connection_t object is referenced by its http_connection field, similar to ngx_http_v2_connection_t and ngx_http_request_t. The change allows to eliminate v3_session field from ngx_http_connection_t. The field was under NGX_HTTP_V3 macro, which was a source of binary compatibility problems when nginx/module is build with/without HTTP/3 support. Postponing is essential since c->data should retain the reference to ngx_http_connection_t object throughout QUIC handshake, because SSL callbacks ngx_http_ssl_servername() and ngx_http_ssl_alpn_select() rely on this.
2023-09-13HTTP/3: moved variable initialization.Roman Arutyunyan1-1/+2
2023-09-13QUIC: "handshake_timeout" configuration parameter.Roman Arutyunyan2-9/+7
Previously QUIC did not have such parameter and handshake duration was controlled by HTTP/3. However that required creating and storing HTTP/3 session on first client datagram. Apparently there's no convenient way to store the session object until QUIC handshake is complete. In the followup patches session creation will be postponed to init() callback.
2023-08-31Upstream: fixed handling of Status headers without reason-phrase.Maxim Dounin3-3/+12
Status header with an empty reason-phrase, such as "Status: 404 ", is valid per CGI specification, but looses the trailing space during parsing. Currently, this results in "HTTP/1.1 404" HTTP status line in the response, which violates HTTP specification due to missing trailing space. With this change, only the status code is used from such short Status header lines, so nginx will generate status line itself, with the space and appropriate reason phrase if available. Reported at: https://mailman.nginx.org/pipermail/nginx/2023-August/EX7G4JUUHJWJE5UOAZMO5UD6OJILCYGX.html
2023-07-12HTTP/3: fixed $body_bytes_sent.Sergey Kandaurov1-0/+1
2023-06-08HTTP/2: removed server push (ticket #2432).Sergey Kandaurov5-1010/+56
Although it has better implementation status than HTTP/3 server push, it remains of limited use, with adoption numbers seen as negligible. Per IETF 102 materials, server push was used only in 0.04% of sessions. It was considered to be "difficult to use effectively" in RFC 9113. Its use is further limited by badly matching to fetch/cache/connection models in browsers, see related discussions linked from [1]. Server push was disabled in Chrome 106 [2]. The http2_push, http2_push_preload, and http2_max_concurrent_pushes directives are made obsolete. In particular, this essentially reverts 7201:641306096f5b and 7207:3d2b0b02bd3d. [1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/ [2] https://chromestatus.com/feature/6302414934114304
2023-06-08SSL: removed the "ssl" directive.Roman Arutyunyan3-89/+2
It has been deprecated since 7270:46c0c7ef4913 (1.15.0) in favour of the "ssl" parameter of the "listen" directive, which has been available since 2224:109849282793 (0.7.14).
2023-05-16HTTP/2: "http2" directive.Roman Arutyunyan7-62/+127
The directive enables HTTP/2 in the current server. The previous way to enable HTTP/2 via "listen ... http2" is now deprecated. The new approach allows to share HTTP/2 and HTTP/0.9-1.1 on the same port. For SSL connections, HTTP/2 is now selected by ALPN callback based on whether the protocol is enabled in the virtual server chosen by SNI. This however only works since OpenSSL 1.0.2h, where ALPN callback is invoked after SNI callback. For older versions of OpenSSL, HTTP/2 is enabled based on the default virtual server configuration. For plain TCP connections, HTTP/2 is now auto-detected by HTTP/2 preface, if HTTP/2 is enabled in the default virtual server. If preface is not matched, HTTP/0.9-1.1 is assumed.
2023-05-19Merged with the quic branch.Roman Arutyunyan23-24/+7361
2023-05-12HTTP/3: removed server push support.Roman Arutyunyan7-1082/+6
2023-05-14Common tree insert function for QUIC and UDP connections.Roman Arutyunyan1-7/+0
Previously, ngx_udp_rbtree_insert_value() was used for plain UDP and ngx_quic_rbtree_insert_value() was used for QUIC. Because of this it was impossible to initialize connection tree in ngx_create_listening() since this function is not aware what kind of listening it creates. Now ngx_udp_rbtree_insert_value() is used for both QUIC and UDP. To make is possible, a generic key field is added to ngx_udp_connection_t. It keeps client address for UDP and connection ID for QUIC.
2023-05-11QUIC: style.Maxim Dounin2-3/+4
2023-05-11HTTP/3: removed "http3" parameter of "listen" directive.Roman Arutyunyan5-33/+7
The parameter has been deprecated since c851a2ed5ce8.
2023-05-11QUIC: removed "quic_mtu" directive.Roman Arutyunyan1-37/+0
The directive used to set the value of the "max_udp_payload_size" transport parameter. According to RFC 9000, Section 18.2, the value specifies the size of buffer for reading incoming datagrams: This limit does act as an additional constraint on datagram size in the same way as the path MTU, but it is a property of the endpoint and not the path; see Section 14. It is expected that this is the space an endpoint dedicates to holding incoming packets. Current QUIC implementation uses the maximum possible buffer size (65527) for reading datagrams.
2023-05-01Variables: avoid possible buffer overrun with some "$sent_http_*".Sergey Kandaurov1-2/+4
The existing logic to evaluate multi header "$sent_http_*" variables, such as $sent_http_cache_control, as previously introduced in 1.23.0, doesn't take into account that one or more elements can be cleared, yet still present in a linked list, pointed to by the next field. Such elements don't contribute to the resulting variable length, an attempt to append a separator for them ends up in out of bounds write. This is not possible with standard modules, though at least one third party module is known to override multi header values this way, so it makes sense to harden the logic. The fix restores a generic boundary check.
2023-05-04HTTP/3: fixed ngx_http_v3_init_session() error handling.Sergey Kandaurov1-3/+0
A QUIC connection is not usable yet at this early stage of spin up.
2023-04-06HTTP/3: fixed CANCEL_PUSH handling.Sergey Kandaurov1-1/+1
2023-03-29Merged with the default branch.Sergey Kandaurov15-43/+113
2023-03-27Gzip: compatibility with recent zlib-ng versions.Maxim Dounin1-6/+12
It now uses custom alloc_aligned() wrapper for all allocations, therefore all allocations are larger than expected by (64 + sizeof(void*)). Further, they are seen as allocations of 1 element. Relevant calculations were adjusted to reflect this, and state allocation is now protected with a flag to avoid misinterpreting other allocations as the zlib deflate_state allocation. Further, it no longer forces window bits to 13 on compression level 1, so the comment was adjusted to reflect this.
2023-03-24SSL: enabled TLSv1.3 by default.Maxim Dounin4-8/+12
2023-03-24HTTP/3: fixed OpenSSL compatibility layer initialization.Sergey Kandaurov1-4/+36
SSL context is not present if the default server has neither certificates nor ssl_reject_handshake enabled. Previously, this led to null pointer dereference before it would be caught with configuration checks. Additionally, non-default servers with distinct SSL contexts need to initialize compatibility layer in order to complete a QUIC handshake.
2023-03-10HTTP/2: finalize request as bad if header validation fails.Maxim Dounin1-8/+1
Similarly to 7192:d5a535774861, this avoids spurious zero statuses in access.log, and in line with other header-related errors.
2023-03-10HTTP/2: socket leak with "return 444" in error_page (ticket #2455).Maxim Dounin1-0/+4
Similarly to ticket #274 (7354:1812f1d79d84), early request finalization without calling ngx_http_run_posted_requests() resulted in a connection hang (a socket leak) if the 400 (Bad Request) error was generated in ngx_http_v2_state_process_header() due to invalid request headers and "return 444" was used in error_page 400.
2023-02-02Lingering close for connections with pipelined requests.Maxim Dounin1-1/+3
This is expected to help with clients using pipelining with some constant depth, such as apt[1][2]. When downloading many resources, apt uses pipelining with some constant depth, a number of requests in flight. This essentially means that after receiving a response it sends an additional request to the server, and this can result in requests arriving to the server at any time. Further, additional requests are sent one-by-one, and can be easily seen as such (neither as pipelined, nor followed by pipelined requests). The only safe approach to close such connections (for example, when keepalive_requests is reached) is with lingering. To do so, now nginx monitors if pipelining was used on the connection, and if it was, closes the connection with lingering. [1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=973861#10 [2] https://mailman.nginx.org/pipermail/nginx-devel/2023-January/ZA2SP5SJU55LHEBCJMFDB2AZVELRLTHI.html
2023-01-28Fixed "zero size buf" alerts with subrequests.Maxim Dounin6-12/+6
Since 4611:2b6cb7528409 responses from the gzip static, flv, and mp4 modules can be used with subrequests, though empty files were not properly handled. Empty gzipped, flv, and mp4 files thus resulted in "zero size buf in output" alerts. While valid corresponding files are not expected to be empty, such files shouldn't result in alerts. Fix is to set b->sync on such empty subrequest responses, similarly to what ngx_http_send_special() does. Additionally, the static module, the ngx_http_send_response() function, and file cache are modified to do the same instead of not sending the response body at all in such cases, since not sending the response body at all is believed to be at least questionable, and might break various filters which do not expect such behaviour.