Commit graph

4447 commits

Author SHA1 Message Date
Ondřej Surý
882adbdc20
Bump the allowed HTTP headers in statschannel to 100
Firefox 90+ apparently sends more than 10 headers, so we need to bump
the number to some higher number.  Bump it to 100 just to be on a save
side, this is for internal use only anyway.

(cherry picked from commit e4654d1a6a)
2022-11-11 09:23:47 +01:00
Ondřej Surý
9274876dec
Serialize the HTTP/1.1 statschannel requests
The statschannel truncated test still terminates abruptly sometimes and
it doesn't return the answer for the first query.  This might happen
when the second process_request() discovers there's not enough space
before the sending is complete and the connection is terminated before
the client gets the data.

Change the isc_http, so it pauses the reading when it receives the data
and resumes it only after the sending has completed or there's
incomplete request waiting for more data.

This makes the request processing slightly less efficient, but also less
taxing for the server, because previously all requests that has been
received via single TCP read would be processed in the loop and the
sends would be queued after the read callback has processed a full
buffer.

(cherry picked from commit 13959781cb)
2022-10-20 17:23:36 +02:00
Ondřej Surý
067502a16e
Rewrite isc_httpd using picohttpparser and isc_url_parse
Rewrite the isc_httpd to be more robust.

1. Replace the hand-crafted HTTP request parser with picohttpparser for
   parsing the whole HTTP/1.0 and HTTP/1.1 requests.  Limit the number
   of allowed headers to 10 (arbitrary number).

2. Replace the hand-crafted URL parser with isc_url_parse for parsing
   the URL from the HTTP request.

3. Increase the receive buffer to match the isc_netmgr buffers, so we
   can at least receive two full isc_nm_read()s.  This makes the
   truncation processing much simpler.

4. Process the received buffer from single isc_nm_read() in a single
   loop and schedule the sends to be independent of each other.

The first two changes makes the code simpler and rely on already
existing libraries that we already had (isc_url based on nodejs) or are
used elsewhere (picohttpparser).

The second two changes remove the artificial "truncation" limit on
parsing multiple request.  Now only a request that has too many
headers (currently 10) or is too big (so, the receive buffer fills up
without reaching end of the request) will end the connection.

We can be benevolent here with the limites, because the statschannel
channel is by definition private and access must be allowed only to
administrators of the server.  There are no timers, no rate-limiting, no
upper limit on the number of requests that can be served, etc.

(cherry picked from commit beecde7120)
2022-10-20 16:10:21 +02:00
Ondřej Surý
944ddd0fb2
Add picohttpparser.{c.h} from https://github.com/h2o/picohttpparser
PicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.

Unlike most parsers, it is stateless and does not allocate memory by
itself. All it does is accept pointer to buffer and the output
structure, and setups the pointers in the latter to point at the
necessary portions of the buffer.

(cherry picked from commit 3a8884f024)
2022-10-20 15:49:27 +02:00
Artem Boldariev
a6f14565b4 TLS Stream: handle successful TLS handshake after listener shutdown
It was possible that accept callback can be called after listener
shutdown. In such a case the callback pointer equals NULL, leading to
segmentation fault. This commit fixes that.
2022-10-18 16:40:08 +03:00
Artem Boldariev
c62994e6a4 Synchronise stop listening operation for multi-layer transports
This commit introduces a primitive isc__nmsocket_stop() which performs
shutting down on a multilayered socket ensuring the proper order of
the operations.

The shared data within the socket object can be destroyed after the
call completed, as it is guaranteed to not be used from within the
context of other worker threads.

(cherry picked from commit 5ab2c0ebb3)
2022-10-18 16:40:08 +03:00
Ondřej Surý
6525ebc777
Replace (void *)-1 with ISC_LINK_TOMBSTONE
Instead of having "arbitrary" (void *)-1 to define non-linked, add a
ISC_LINK_TOMBSTONE(type) macro that replaces the "magic" value with a
define.

(cherry picked from commit 5e20c2ccfb)
2022-10-18 14:30:43 +02:00
Ondřej Surý
8efe60d423
Add ISC_{LIST,LINK}_INITIALIZER for designated initializers
Since we are using designated initializers, we were missing initializers
for ISC_LIST and ISC_LINK, add them, so you can do

    *foo = (foo_t){ .list = ISC_LIST_INITIALIZER };

Instead of:

    *foo = (foo_t){ 0 };
    ISC_LIST_INIT(foo->list);

(cherry picked from commit cb3c36b8bf)
2022-10-18 14:30:43 +02:00
Tony Finch
b48c73d802 Remove redundant #include <isc/strerr.h>
Most uses are now internal to <isc/util.h>
2022-10-17 16:08:28 +01:00
Tony Finch
96b6bae5bc Include the function name when reporting unexpected errors
I.e. print the name of the function in BIND that called the system
function that returned an error. Since it was useful for pthreads
code, it seems worthwhile doing so everywhere.

(cherry picked from commit 26ed03a61e)
2022-10-17 16:00:27 +01:00
Tony Finch
8dfc078ea3 De-duplicate some calls to strerror_r()
Specifically, when reporting an unexpected or fatal error.

(cherry picked from commit a34a2784b1)
2022-10-17 16:00:27 +01:00
Tony Finch
f273fdfc12 De-duplicate __FILE__, __LINE__
Mostly generated automatically with the following semantic patch,
except where coccinelle was confused by #ifdef in lib/isc/net.c

@@ expression list args; @@
- UNEXPECTED_ERROR(__FILE__, __LINE__, args)
+ UNEXPECTED_ERROR(args)
@@ expression list args; @@
- FATAL_ERROR(__FILE__, __LINE__, args)
+ FATAL_ERROR(args)

(cherry picked from commit ec50c58f52)
2022-10-17 16:00:26 +01:00
Artem Boldariev
15b7605e72 TLS DNS: fix certificate verification error message reporting
This commit fixes TLS DNS verification error message reporting which
we probably broke during one of the recent networking code
refactorings.

This prevent e.g. dig from producing useful error messages related to
TLS certificates verification.
2022-10-12 16:53:06 +03:00
Artem Boldariev
e229af39e7 TLS: clear error queue before doing IO or calling SSL_get_error()
Ensure that TLS error is empty before calling SSL_get_error() or doing
SSL I/O so that the result will not get affected by prior error
statuses.

In particular, the improper error handling led to intermittent unit
test failure and, thus, could be responsible for some of the system
test failures and other intermittent TLS-related issues.

See here for more details:

https://www.openssl.org/docs/man3.0/man3/SSL_get_error.html

In particular, it mentions the following:

> The current thread's error queue must be empty before the TLS/SSL
> I/O operation is attempted, or SSL_get_error() will not work
> reliably.

As we use the result of SSL_get_error() to decide on I/O operations,
we need to ensure that it works reliably by cleaning the error queue.

TLS DNS: empty error queue before attempting I/O
2022-10-12 16:39:46 +03:00
Mark Andrews
886df1542e Use strnstr implementation from FreeBSD if not provided by OS
(cherry picked from commit 5f07fe8cbb)
2022-10-04 15:33:33 +11:00
Evan Hunt
369858730a change ISC__BUFFER macros to inline functions
previously, when ISC_BUFFER_USEINLINE was defined, macros were
used to implement isc_buffer primitives (isc_buffer_init(),
isc_buffer_region(), etc). these macros were missing the DbC
assertions for those primitives, which made it possible for
coding errors to go undetected.

adding the assertions to the macros caused compiler warnings on
some platforms. therefore, this commit converts the ISC__BUFFER
macros to static inline functions instead, with assertions included,
and eliminates the non-inline implementation from buffer.c.

the --enable-buffer-useinline configure option has been removed.

(cherry picked from commit 1926ddc987)
2022-09-27 00:45:28 -07:00
Evan Hunt
357b59ec68 additional code cleanups in httpd.c
- use isc_buffer functions when appropriate, rather than converting
  to and from isc_region unnecessarily
- use the zlib total_out value instead of calculating it
- use c99 struct initialization

(cherry picked from commit 4b7248545e)
2022-09-21 12:54:27 -07:00
Michał Kępień
0a53f61727 BIND 9.18.7
-----BEGIN PGP SIGNATURE-----
 
 iQJDBAABCgAtFiEENKwGS3ftSQfs1TU17QVz/8hFYQUFAmMZ4qIPHG1pY2hhbEBp
 c2Mub3JnAAoJEO0Fc//IRWEFpl0QAItVxvXJ2yQw+06QhlmA7l0pmKgAqKzgwzcD
 hpOsYsglMGhkyry+eWr+XOSEyU/MAIHSvhaKvvlicZMrthe4wmip4O0M24BldVmL
 Vvqb8/0vg2/8hom9aJu9NgRaGX/ybewauIG21drPR4O6MnLfX+8m0c0bbO1I60bn
 xSL5OX1DzDYJhMQ+hBlG2hTlEhovtXBFZYpTR2H9ITvXMrDJNbs3VQZLKFrD56Ge
 WitoPeE4lkGpDcPTtFys3siRJjIOAl9jKUZWqfnhmiYGC0USMmXneEEuM9/sMXFv
 jh0AtymJbe0s9bceYD961RE1pd9cdbrUg+6EJIhoGqNL+ANtj61jtdpLtWwWWKgU
 3MiEJF7YQLQ0lWXArUtMTRwWUYeVpxPprzwXIdQfiTp35fTBoOzL3rslq4HdVCxA
 SPtAunI8OFsr2Njglf2VsJfcX0x7V4lbftnmY3e24b+C+YXddRVc+83cGZvh2kvB
 NKY2Y8/Op8BsFyUoJ69Umcrx+xZSmO0ngEA62lKjJ/oAZ/WaQ8bkcajCdtLYKFJd
 rTXw/UsdKQDlUQ/rCU/Ge+Y/BKFRn3f7UA0D0Mvp+DpTus9DYMvy/nWWphVgWNGP
 E2j/1orf/dGdWojvFLGe4zPl8BCRHqgoxfGBaizR4N3eTKHcOS2uVJJ0x4WfY9xe
 nUKGK+iw
 =OVc+
 -----END PGP SIGNATURE-----

Merge tag 'v9_18_7' into v9_18

BIND 9.18.7
2022-09-21 13:13:30 +02:00
Ondřej Surý
2adaa53619
Handle canceled read during sending data over stats channel
An assertion failure would be triggered when the TCP connection
is canceled during sending the data back to the client.

Don't require the state to be `RECV` on non successful read to
gracefully handle canceled TCP connection during the SEND state of the
HTTPD channel.

(cherry picked from commit 6562227cc8)
2022-09-15 10:58:09 +02:00
Evan Hunt
13333db69f compression buffer was not reused correctly
when the compression buffer was reused for multiple statistics
requests, responses could grow beyond the correct size. this was
because the buffer was not cleared before reuse; compressed data
was still written to the beginning of the buffer, but then the size
of used region was increased by the amount written, rather than set
to the amount written. this caused responses to grow larger and
larger, potentially reading past the end of the allocated buffer.

(cherry picked from commit 47e9fa981e)
2022-09-08 11:40:18 +02:00
Aram Sargsyan
982b491d7c Add mctx attach/detach when creating/destroying a memory pool
This should make sure that the memory context is not destroyed
before the memory pool, which is using the context.

(cherry picked from commit e97c3eea95)
2022-09-02 08:17:47 +00:00
Aram Sargsyan
d4c5d1c650 Fix statistics channel multiple request processing with non-empty bodies
When the HTTP request has a body part after the HTTP headers, it is
not getting processed and is being prepended to the next request's data,
which results in an error when trying to parse it.

Improve the httpd.c:process_request() function with the following
additions:

1. Require that HTTP POST requests must have Content-Length header.
2. When Content-Length header is set, extract its value, and make sure
   that it is valid and that the whole request's body is received before
   processing the request.
3. Discard the request's body by consuming Content-Length worth of data
   in the buffer.

(cherry picked from commit c2bbdc8a648c9630b2c9cea5227ad5c309c2ade5)
2022-08-19 08:27:01 +00:00
Aram Sargsyan
1005dd74d9 Enhance the have_header() function to find the HTTP header's value
Add a new `const char **fvalue` parameter to the httpd.c:have_header()
function which, when set, will point to the found header's value.

(cherry picked from commit 376e698dc21f4117d6461101c4cfbaef2b724592)
2022-08-19 08:26:18 +00:00
Evan Hunt
1843780151 fix overflow error in mem_putstats()
an integer overflow could cause an assertion failure when
freeing memory.

(cherry picked from commit 0401e0867b1516386fab9b390b750a2f99883188)
2022-08-09 11:21:35 -07:00
Artem Boldariev
c2fa72027c TLS: do not ignore readpaused flag in certain circumstances
In some circumstances generic TLS code could have resumed data reading
unexpectedly on the TCP layer code. Due to this, the behaviour of
isc_nm_pauseread() and isc_nm_resumeread() might have been
unexpected. This commit fixes that.

The bug does not seems to have real consequences in the existing code
due to the way the code is used. However, the bug could have lead to
unexpected behaviour and, at any rate, makes the TLS code behave
differently from the TCP code, with which it attempts to be as
compatible as possible.

(cherry picked from commit ec0647d546204a0e09aeaf0e2aabb37f1fb67dd0)
2022-08-02 17:31:15 +03:00
Artem Boldariev
a957511734 TLS: fix double resumption in isc__nm_tls_resumeread()
This commit fixes an obvious error in isc__nm_tls_resumeread() so that
read cannot be resumed twice.
2022-07-26 15:27:40 +03:00
Artem Boldariev
a165b66fc7 TLS: clear 'errno' when handling SSL status
Sometimes tls_do_bio() might be called when there is no new data to
process (most notably, when resuming reads), in such a case internal
TLS session state will remain untouched and old value in 'errno' will
alter the result of SSL_get_error() call, possibly making it to return
SSL_ERROR_SYSCALL. This value will be treated as an error, and will
lead to closing the connection, which is not what expected.
2022-07-26 15:27:40 +03:00
Ondřej Surý
d242ced18f
Cleanup the STATID_CONNECT and STATID_CONNECTFAIL stat counters
The STATID_CONNECT and STATID_CONNECTFAIL statistics were used
incorrectly. The STATID_CONNECT was incremented twice (once in
the *_connect_direct() and once in the callback) and STATID_CONNECTFAIL
would not be incremented at all if the failure happened in the callback.

Closes: #3452
(cherry picked from commit 59e1703b50dc4a5c52e3d6ae13bdd873a677b03f)
2022-07-14 21:48:44 +02:00
Ondřej Surý
259f4481bd
Handle the transient TCP connect() failures on FreeBSD
On FreeBSD (and perhaps other *BSD) systems, the TCP connect() call (via
uv_tcp_connect()) can fail with transient UV_EADDRINUSE error.  The UDP
code already handles this by trying three times (is a charm) before
giving up.  Add a code for the TCP, TCPDNS and TLSDNS layers to also try
three times before giving up by calling uv_tcp_connect() from the
callback two more time on UV_EADDRINUSE error.

Additionally, stop the timer only if we succeed or on hard error via
isc__nm_failed_connect_cb().

(cherry picked from commit b21f507c0ac5b5d2d2c27fd2d71e27e8605dd5fc)
2022-07-14 21:47:47 +02:00
Artem Boldariev
814baa3e6b TLS: do not ignore accept callback result
Before this change the TLS code would ignore the accept callback result,
and would not try to gracefully close the connection. This had not been
noticed, as it is not really required for DoH. Now the code tries to
shut down the TLS connection gracefully when accepting it is not
successful.

(cherry picked from commit ffcb54211e)
2022-07-12 15:32:45 +03:00
Artem Boldariev
c85949fbe1 TLSDNS: try pass incoming data to OpenSSL if there are any
Otherwise the code path will lead to a call to SSL_get_error()
returning SSL_ERROR_SSL, which in turn might lead to closing
connection to early in an unexpected way, as it is clearly not what is
intended.

The issue was found when working on loppmgr branch and appears to
be timing related as well. Might be responsible for some unexpected
transmission failures e.g. on zone transfers.

(cherry picked from commit 8585b92f98)
2022-07-12 15:29:36 +03:00
Artem Boldariev
ba7fabde01 TLS: bail out earlier when NM is stopping
In some operations - most prominently when establishing connection -
it might be beneficial to bail out earlier when the network manager
is stopping.

The issue is backported from loopmgr branch, where such a change is
not only beneficial, but required.

(cherry picked from commit fc74b15e67)
2022-07-12 15:28:15 +03:00
Artem Boldariev
0754def85d TLS: sometimes TCP conn. handle might be NULL on when connecting
In some cases - in particular, in case of errors, NULL might be passed
to a connection callback instead of a handle that could have led to
an abort. This commit ensures that such a situation will not occur.

The issue was found when working on the loopmgr branch.

(cherry picked from commit ac4fb34f18)
2022-07-12 15:26:50 +03:00
Artem Boldariev
c44633feb2 TLS: try to close sockets whenever there are no pending operations
This commit ensures that the underlying TCP socket of a TLS connection
gets closed earlier whenever there are no pending operations on it.

In the loop-manager branch, in some circumstances the connection
could have remained opened for far too long for no reason. This
commit ensures that will not happen.

(cherry picked from commit 88524e26ec)
2022-07-12 15:25:30 +03:00
Artem Boldariev
3e69cc35b8 TLS: Implement isc_nmhandle_setwritetimeout()
This commit adds a proper implementation of
isc_nmhandle_setwritetimeout() for TLS connections. Now it passes the
value to the underlying TCP handle.

(cherry picked from commit 237ce05b89)
2022-07-12 15:22:57 +03:00
Evan Hunt
b061e86d17 REQUIRE should not have side effects
it's a style violation to have REQUIRE or INSIST contain code that
must run for the server to work. this was being done with some
atomic_compare_exchange calls. these have been cleaned up.  uses
of atomic_compare_exchange in assertions have been replaced with
a new macro atomic_compare_exchange_enforced, which uses RUNTIME_CHECK
to ensure that the exchange was successful.

(cherry picked from commit a499794984)
2022-07-05 13:04:17 -07:00
Artem Boldariev
b6b07c5646 Update the set of HTTP endpoints on reconfiguration
This commit ensures that on reconfiguration the set of HTTP
endpoints (=paths) is being updated within HTTP listeners.

(cherry picked from commit d2e13ddf22)
2022-06-28 16:37:31 +03:00
Artem Boldariev
bb8ba2c027 Update max concurrent streams limit in HTTP listeners on reconfig
This commit ensures that HTTP listeners concurrent streams limit gets
updated properly on reconfiguration.

(cherry picked from commit e72962d5f1)
2022-06-28 16:37:31 +03:00
Michal Nowak
d3eb307e3c
Update clang to version 14
(cherry picked from commit 1c45a9885a)
2022-06-16 18:09:33 +02:00
Artem Boldariev
b3490213eb CID 352848: split xfrin_start() and remove dead code
This commit separates TLS context creation code from xfrin_start() as
it has become too large and hard to follow into a new
function (similarly how it is done in dighost.c)

The dead code has been removed from the cleanup section of the TLS
creation code:

* there is no way 'tlsctx' can equal 'found';
* there is no way 'sess_cache' can be non-NULL in the cleanup section.

Also, it fixes a bug in the older version of the code, where TLS
client session context fetched from the cache would not get passed to
isc_nm_tlsdnsconnect().

(cherry picked from commit 98f758ed4f)
2022-06-15 17:02:45 +03:00
Artem Boldariev
334eeef5a1 Do not provide a shim for SSL_SESSION_is_resumable()
The recently added TLS client session cache used
SSL_SESSION_is_resumable() to avoid polluting the cache with
non-resumable sessions. However, it turned out that we cannot provide
a shim for this function across the whole range of OpenSSL versions
due to the fact that OpenSSL 1.1.0 does uses opaque pointers for
SSL_SESSION objects.

The commit replaces the shim for SSL_SESSION_is_resumable() with a non
public approximation of it on systems shipped with OpenSSL 1.1.0. It
is not turned into a proper shim because it does not fully emulate the
behaviour of SSL_SESSION_is_resumable(), but in our case it is good
enough, as it still helps to protect the cache from pollution.

For systems shipped with OpenSSL 1.0.X and derivatives (e.g. older
versions of LibreSSL), the provided replacement perfectly mimics the
function it is intended to replace.

(cherry picked from commit 40be3c9263)
2022-06-15 17:02:45 +03:00
Artem Boldariev
0cec9cca37 Fix an abort in DoH (client-side) when writing on closing sock
The commit fixes a corner case in client-side DoH code, when a write
attempt is done on a closing socket (session).

The change ensures that the write call-back will be called with a
proper error code (see failed_send_cb() call in client_httpsend()).

(cherry picked from commit 9abb00bb5f)
2022-06-15 17:02:45 +03:00
Artem Boldariev
cb6591f277 Avoid aborting when uv_timer_start() is used on a closing socket
In such a case it will return UV_EINVAL (-EINVAL), leading to
aborting, as the code expects the function to succeed.

(cherry picked from commit 245f7cec2e)
2022-06-15 17:02:45 +03:00
Artem Boldariev
5154bac7c5 Add SSL_SESSION_is_resumable() implementation shim
This commit adds SSL_SESSION_is_resumable() implementation if it is
missing.

(cherry picked from commit 35338b4105)
2022-06-15 17:02:45 +03:00
Artem Boldariev
e02284354a DoT: implement TLS client session resumption
This commit extends DoT code with TLS client session resumption
support implemented on top of the TLS client session cache.

(cherry picked from commit 86465c1dac)
2022-06-15 17:02:45 +03:00
Artem Boldariev
0a4a76ff7a TLS stream/DoH: implement TLS client session resumption
This commit extends TLS stream code and DoH code with TLS client
session resumption support implemented on top of the TLS client
session cache.

(cherry picked from commit 90bc13a5d5)
2022-06-15 17:02:45 +03:00
Artem Boldariev
6ec48f1e78 Extend TLS context cache with TLS client session cache
This commit extends TLS context cache with TLS client session cache so
that an associated session cache can be stored alongside the TLS
context within the context cache.

(cherry picked from commit 987892d113)
2022-06-15 17:02:45 +03:00
Artem Boldariev
7c8d76c458 Add TLS client session cache implementation
This commit adds an implementation of a client TLS session cache. TLS
client session cache is an object which allows efficient storing and
retrieval of previously saved TLS sessions so that they can be
resumed. This object is supposed to be a foundation for implementing
TLS session resumption - a standard technique to reduce the cost of
re-establishing a connection to the remote server endpoint.

OpenSSL does server-side TLS session caching transparently by
default. However, on the client-side, a TLS session to resume must be
manually specified when establishing the TLS connection. The TLS
client session cache is precisely the foundation for that.

(cherry picked from commit 4ef40988f3)
2022-06-15 17:02:45 +03:00
Artem Boldariev
9b320b1682 TLS DNS: do not call accept callback twice
Before the changes from this commit were introduced, the accept
callback function will get called twice when accepting connection
during two of these stages:

* when accepting the TCP connection;
* when handshake has completed.

That is clearly an error, as it should have been called only once. As
far as I understand it the mistake is a result of TLS DNS transport
being essentially a fork of TCP transport, where calling the accept
callback immediately after accepting TCP connection makes sense.

This commit fixes this mistake. It did not have any very serious
consequences because in BIND the accept callback only checks an ACL
and updates stats.

(cherry picked from commit e616d7f240)
2022-06-15 15:32:49 +03:00
Ondřej Surý
579270509f Gracefully handle uv_read_start() failures
Under specific rare timing circumstances the uv_read_start() could
fail with UV_EINVAL when the connection is reset between the connect (or
accept) and the uv_read_start() call on the nmworker loop.  Handle such
situation gracefully by propagating the errors from uv_read_start() into
upper layers, so the socket can be internally closed().

(cherry picked from commit b432d5d3bc)
2022-06-14 11:54:11 +02:00