156 Commits

Author SHA1 Message Date
William Lallemand
7c5a7ef32b MINOR: httpclient: allow ipv4 or ipv6 preference for resolving
The httpclient.resolvers.prefer global keyword allows to configure an
ipv4 or ipv6 preference when resolving. This could be useful in
environment where the ipv6 is not supported.
2022-05-04 16:14:42 +02:00
William Lallemand
8a734cbae3 MINOR: httpclient: configure the resolvers section to use
By default the httpclient uses the resolvers section whose ID is
"default", the httpclient.resolvers.id global option allows to configure
another section to use.
2022-05-04 16:14:35 +02:00
William Lallemand
683fbb86be MINOR: httpclient: allow to configure the ca-file
The global keyword httpclient.ssl.ca-file allows to configure the
ca-file used for the httpclient verify.
2022-05-04 16:14:35 +02:00
William Lallemand
6fce46a910 MEDIUM: httpclient: hard-error when SSL is configured
The hard_error_ssl flag is set when the configuration is explicitely
done for the ssl in the httpclient.

If no configuration was made, the features are simply disabled and no
alert is emitted.
2022-05-04 16:13:17 +02:00
William Lallemand
85af49c5c8 MINOR: httpclient: cleanup the error handling in init
Cleanup the error handling in the initialization so we rely on the
ERR_CODE and use memprintf() to set the errmsg before printing it at the
end of the functions.
2022-05-04 14:33:57 +02:00
William Lallemand
9ff95e2269 MINOR: httpclient: rename dash by dot in global option
Rename the httpclient-ssl-verify into httpclient.ssl.verify.
2022-05-04 13:52:29 +02:00
William Lallemand
853327390e MINOR: httpclient: handle unix and other socket types in dst
httpclient_set_dst() allows one to set the destination address instead
of using the one in the URL or resolving one from the host.
This function also support other types of socket like sockpair@, unix@,
anything that could be used on a server line.

In order to still support this behavior, the address must be set on the
backend in this particular case because the frontend connection does not
support anything other than ipv4 or ipv6.
2022-05-04 11:21:01 +02:00
William Lallemand
0e23526a2c CLEANUP: httpclient: remove the comment about resolving
remove the comment of httpclient_start which states there is no
resolver.
2022-05-04 11:21:01 +02:00
William Lallemand
1218d19921 MEDIUM: httpclient: allow address and port change for resolving
To allow the http-request set-dst to work for the httpclient DNS
resolving, some changes need to be done:

- The destination address need to be set in the frontend (s->csf->dst)
  instead of the backend (s->csb->dst) to be able to use
  tcp_action_req_set_dst()

- SRV_F_MAPPORTS need to be set on the proxy in order to allow the port
  change in alloc_dst_address()
2022-05-04 11:21:01 +02:00
William Lallemand
5392ff6e3c MEDIUM: httpclient: http-request rules for resolving
The httpclient_resolve_init() adds http-request actions which does the
resolving using the Host header of the HTTP request.

The parse_http_req_cond function is directly used over an array of http
rules.

The do-resolve rule uses the "default" resolvers section. If this
section does not exist in the configuration, the resolving is disabling.
2022-05-04 11:21:01 +02:00
William Lallemand
7f1df8ff1a MEDIUM: httpclient: remove url2sa to use a more flexible parser
The httpclient DNS resolver will need a more efficient URL parser which
splits the URL into parts and does not try to resolve.

httpclient_spliturl uses the http_uri_parser in order to split the URL
into several ist.

The result of the function host part is then processed into str2ip2(),
and fails if it it not an IP, allowing us to resolve the domain later.
2022-05-04 11:21:01 +02:00
Willy Tarreau
03bd3952a6 MEDIUM: stream: remove the confusing SF_ADDR_SET flag
This flag is no longer needed now that it must always match the presence
of a destination address on the backend conn_stream. Worse, before previous
patch, if it were to be accidently removed while the address is present, it
could result in a leak of that address since alloc_dst_address() would first
be called to flush it.

Its usage has a long history where addresses were stored in an area shared
with the connection, but as this is no longer the case, there's no reason
for putting this burden onto application-level code that should not focus
on setting obscure flags.

The only place where that made a small difference is in the dequeuing code
in case of queue redistribution, because previously the code would first
clear the flag, and only later when trying to deal with the queue, would
release the address. It's not even certain whether there would exist a
code path going to connect_server() without calling pendconn_dequeue()
first (e.g. retries on queue timeout maybe?).

Now the pendconn_dequeue() code will rely on SF_ASSIGNED to decide to
clear and release the address, since that flag is always set while in
a server's queue, and its clearance implies that we don't want to keep
the address. At least it remains consistent and there's no more risk of
leaking it.
2022-05-02 16:56:01 +02:00
Christopher Faulet
0055d5693e MINOR: httpclient: Don't use co_set_data() to decrement output
The use of co_set_data() should be strictly limited to setting the amount of
existing data to be transmitted. It ought not be used to decrement the
output after the data have left the buffer, because doing so involves
performing incorrect calculations using co_data() that still comprises data
that are not in the buffer anymore. Let's use c_rew() for this, which is
made exactly for this purpose, i.e. decrement c->output by as much as
requested.
2022-04-29 14:12:42 +02:00
Christopher Faulet
6b4f1f64a8 BUG/MINOR: httpclient: Count metadata in size to transfer via htx_xfer_blks()
When HTX blocks are transfer from the HTTP client context to the request
channel, via htx_xfer_blks() function, the metadata must also be counted, in
addition to the data size. Otherwise, expected payload size will not be
copied because the metadata of an HTX block (8 bytes) will be reserved. And
if the payload size is lower than 8 bytes, nothing will be copied. Thus only
a zero-copy will be able to copy the payload.

This issue is 2.6-specific, no backport is needed.
2022-04-29 14:12:42 +02:00
Christopher Faulet
534645d6c0 BUG/MEDIUM: httpclient: Fix loop consuming HTX blocks from the response channel
When the HTTP client consumes the response, it loops on the HTX message to
copy blocks content and it removes blocks by calling htx_remove_blk(). But
this function removes a block and returns the next one in the HTX
message. The result must be used instead of using htx_get_next(). It is
especially important because the block used in htx_get_next() loop was
removed. It only works because the message is not defragmented during the
loop.

In addition, the loop on the response was simplified to iter on blocks
instead of positions.

This patch must be backported to 2.5.
2022-04-29 14:12:42 +02:00
William Lallemand
04994de642 BUG/MINOR: httpclient/ssl: use the correct verify constant
The SSL_SERVER_VERIFY_* constants were incorrectly set on the httpclient
server verify. The right constants are SSL_SOCK_VERIFY_* .

This could cause issues when using "httpclient-ssl-verify" or when the
SSL certificates can't be loaded.

No backport needed
2022-04-28 19:35:21 +02:00
William Lallemand
f1344b3cee MEDIUM: httpclient: re-enable the verify by default
Since the httpclient verify now has a fallback which disable the SSL in
the httpclient without exiting haproxy at startup, we can safely
re-enable it by default.

It could still be disabled with "httpclient-ssl-verify none".
2022-04-26 16:15:23 +02:00
William Lallemand
4006b0f130 MEDIUM: httpclient: disable SSL when the ca-file couldn't be loaded
Emit a warning when the ca-file couldn't be loaded for the httpclient,
and disable the SSL of the httpclient.

We must never be in a case where the verify is disabled without any
configuration, so better disable the SSL completely.

Move the check on the scheme above the initialization of the applet so
we could abort before initializing the appctx.
2022-04-26 16:15:23 +02:00
William Lallemand
eaa703ef06 MEDIUM: httpclient/ssl: verify is configurable and disabled by default
Disable temporary the SSL verify by default in the httpclient. The
initialization of the @system-ca during the init of the httpclient is a
problem in some cases.

The verify can be reactivated with "httpclient-ssl-verify required" in
the global section.
2022-04-22 18:05:17 +02:00
William Lallemand
c6ceba3170 MINOR: httpclient/mworker: disable in the master process
Disable the httpclient in the master process.
2022-04-22 16:49:53 +02:00
William Lallemand
cf5cb0b524 MEDIUM: httpclient/ssl: verify required
The httpclient HTTPS requests now enable the "verify required" option.
To achieve this, the "@system-ca" ca-file is configured in the
httpclient ssl server. Which means all the system CAs will be loaded at
haproxy startup.
2022-04-22 15:45:47 +02:00
William Lallemand
2c8b0842bb MEDIUM: httpclient: change the init sequence
Change the init order of the httpclient, a different init sequence is
required to allow a more complicated init.

The init is splitted in two parts:

- the first part is executed before config_check_validity(), which
  allows to create proxy and more advanced stuff than STG_INIT, because
  we might want to use stuff already initialized in haproxy (trash
  buffers for example)

- the second part is executed after the config_check_validity(),
  currently it is used for the log configuration.
2022-04-22 15:45:47 +02:00
Christopher Faulet
eb50c01fef MINOR: conn-stream: Make cs_detach_* private and use cs_destroy() from outside
A conn-stream is never detached from an endpoint or an application alone,
except on a reset. Thus, to avoid any error, these functions are now
private. And cs_destroy() function is added to destroy a conn-stream. This
function is called when a stream is released, on the front and back
conn-streams, and when a health-check is finished.
2022-04-22 14:32:30 +02:00
Willy Tarreau
e1e9f6bbe5 BUG/MEDIUM: logs: fix http-client's log srv initialization
As anticipated in commit 211ea252d ("BUG/MINOR: logs: fix logsrv leaks
on clean exit"), there were indeed other corner cases that were not
properly covered. Setting the http client's ring_name to NULL make the
sink lookup crash on startup in sink_find () with a config as simple as:

    global
        log ring@buf0 local0

The fields must be properly initialized (both config file name and
the ring_name). This only needs to be backported if/when the commit
above is backported.
2022-04-22 09:40:44 +02:00
Christopher Faulet
67df95a8a2 BUILD: http-client: Avoid dead code when compiled without SSL support
When an HTTP client is started on an HAProxy compiled without the SSL
support, an error is triggered when HTTPS is used. In this case, the freshly
created conn-stream is released. But this code is specific to the non-SSL
part. Thus it is moved the in right #if/#else section.

This patch should fix the issue #1655.
2022-04-14 12:02:35 +02:00
Christopher Faulet
6b0a0fb2f9 CLEANUP: tree-wide: Remove any ref to stream-interfaces
Stream-interfaces are gone. Corresponding files can be safely be removed. In
addition, comments are updated accordingly.
2022-04-13 15:10:16 +02:00
Christopher Faulet
a0bdec350f MEDIUM: stream-int/conn-stream: Move blocking flags from SI to CS
Remaining flags and associated functions are move in the conn-stream
scope. These flags are added on the endpoint and not the conn-stream
itself. This way it will be possible to get them from the mux or the
applet. The functions to get or set these flags are renamed accordingly with
the "cs_" prefix and updated to manipualte a conn-stream instead of a
stream-interface.
2022-04-13 15:10:15 +02:00
Christopher Faulet
da098e6c17 MINOR: stream-int/conn-stream: Move si_shut* and si_chk* in conn-stream scope
si_shutr(), si_shutw(), si_chk_rcv() and si_chk_snd() are moved in the
conn-stream scope and renamed, respectively, cs_shutr(), cs_shutw(),
cs_chk_rcv(), cs_chk_snd() and manipulate a conn-stream instead of a
stream-interface.
2022-04-13 15:10:15 +02:00
Christopher Faulet
8abe712749 MINOR: stream-int: Remove SI_FL_NOLINGER/NOHALF to rely on CS flags instead
Flags to disable lingering and half-close are now handled at the conn-stream
level. Thus SI_FL_NOLINGER and SI_FL_NOHALF stream-int flags are replaced by
CS_FL_NOLINGER and CS_FL_NOHALF conn-stream flags.
2022-04-13 15:10:14 +02:00
Christopher Faulet
8da67aae3e MEDIUM: stream-int/conn-stream: Move src/dst addresses in the conn-stream
The source and destination addresses at the applicative layer are moved from
the stream-interface to the conn-stream. This simplifies a bit the code and
it is a logicial step to remove the stream-interface.
2022-04-13 15:10:14 +02:00
Christopher Faulet
908628c4c0 MEDIUM: tree-wide: Use CS util functions instead of SI ones
At many places, we now use the new CS functions to get a stream or a channel
from a conn-stream instead of using the stream-interface API. It is the
first step to reduce the scope of the stream-interfaces. The main change
here is about the applet I/O callback functions. Before the refactoring, the
stream-interface was the appctx owner. Thus, it was heavily used. Now, as
far as possible,the conn-stream is used. Of course, it remains many calls to
the stream-interface API.
2022-04-13 15:10:14 +02:00
Christopher Faulet
b041b23ae4 MEDIUM: conn-stream: Move remaning flags from CS to endpoint
All old flags CS_FL_* are now moved in the endpoint scope and renamed
CS_EP_* accordingly. It is a systematic replacement. There is no true change
except for the health-check and the endpoint reset. Here it is a bit special
because the same conn-stream is reused. Thus, we must handle endpoint
allocation errors. To do so, cs_reset_endp() has been adapted.

Thanks to this last change, it will now be possible to simplify the
multiplexer and probably the applets too. A review must also be performed to
remove some flags in the channel or the stream-interface. The HTX will
probably be simplified too. Finally, there is now some place in the
conn-stream to move info from the stream-interface.
2022-04-13 15:10:14 +02:00
Christopher Faulet
9ec2f4dc7c MAJOR: conn-stream: Share endpoint struct between the CS and the mux/applet
The conn-stream endpoint is now shared between the conn-stream and the
applet or the multiplexer. If the mux or the applet is created first, it is
responsible to also create the endpoint and share it with the conn-stream.
If the conn-stream is created first, it is the opposite.

When the endpoint is only owned by an applet or a mux, it is called an
orphan endpoint (there is no conn-stream). When it is only owned by a
conn-stream, it is called a detached endpoint (there is no mux/applet).

The last entity that owns an endpoint is responsible to release it. When a
mux or an applet is detached from a conn-stream, the conn-stream
relinquishes the endpoint to recreate a new one. This way, the endpoint
state is never lost for the mux or the applet.
2022-04-13 15:10:14 +02:00
Christopher Faulet
a9e8b3979d MEDIUM: conn-stream: Pre-allocate endpoint to create CS from muxes and applets
It is a transient commit to prepare next changes. Now, when a conn-stream is
created from an applet or a multiplexer, an endpoint is always provided. In
addition, the API to create a conn-stream was specialized to have one
function per type.

The next step will be to share the endpoint structure.
2022-04-13 15:10:14 +02:00
Christopher Faulet
b669d684c0 MEDIUM: conn-stream: Be able to pass endpoint to create a conn-stream
It is a transient commit to prepare next changes. It is possible to pass a
pre-allocated endpoint to create a new conn-stream. If it is NULL, a new
endpoint is created, otherwise the existing one is used. There no more
change at the conn-stream level.

In the applets, all conn-stream are created with no pre-allocated
endpoint. But for multiplexers, an endpoint is systematically created before
creating the conn-stream.
2022-04-13 15:10:14 +02:00
Christopher Faulet
9388204db1 MAJOR: conn-stream: Invert conn-stream endpoint and its context
This change is only significant for the multiplexer part. For the applets,
the context and the endpoint are the same. Thus, there is no much change. For
the multiplexer part, the connection was used to set the conn-stream
endpoint and the mux's stream was the context. But it is a bit strange
because once a mux is installed, it takes over the connection. In a
wonderful world, the connection should be totally hidden behind the mux. The
stream-interface and, in a lesser extent, the stream, still access the
connection because that was inherited from the pre-multiplexer era.

Now, the conn-stream endpoint is the mux's stream (an opaque entity for the
conn-stream) and the connection is the context. Dedicated functions have
been added to attached an applet or a mux to a conn-stream.
2022-04-13 15:10:14 +02:00
Christopher Faulet
2479e5f775 MEDIUM: applet: Set the appctx owner during allocation
The appctx owner is now always a conn-stream. Thus, it can be set during the
appctx allocation. But, to do so, the conn-stream must be created first. It
is not a problem on the server side because the conn-stream is created with
the stream. On the client side, we must take care to create the conn-stream
first.

This change should ease other changes about the applets bootstrapping.
2022-04-13 15:10:13 +02:00
Christopher Faulet
dca3b5b2c6 BUG/MINOR: http_client: Don't add input data on an empty request buffer
When compiled in debug mode, a BUG_ON triggers an error when the payload is
fully transfered from the http-client buffer to the request channel
buffer. In fact, when channel_add_input() is called, the request buffer is
empty. So an error is reported when those data are directly forwarded,
because we try to add some output data on a buffer with no data.

To fix the bug, we must be sure to call channel_add_input() after the data
transfer.

The bug was introduced by the commit ccc7ee45f ("MINOR: httpclient: enable
request buffering"). So, this patch must be backported if the above commit
is backported.
2022-04-07 11:04:39 +02:00
William Lallemand
eb0d4c40ac BUG/MINOR: httpclient: end callback in applet release
In case an error provokes the release of the applet, we will never call
the end callback of the httpclient.

In the case of a lua script, it would mean that the lua task will never
be waked up after a yield, letting the lua script stuck forever.

Fix the issue by moving the callback from the end of the iohandler to
the applet release function.

Must be backported in 2.5.
2022-04-06 14:19:36 +02:00
William Lallemand
71abad050a MEDIUM: httpclient: enable l7-retry
Enable the layer-7 retry in the httpclient. This way the client will
retry upon a connection error or a timeout.
2022-04-06 11:50:10 +02:00
William Lallemand
ccc7ee45f9 MINOR: httpclient: enable request buffering
The request buffering is required for doing l7 retry. The IO handler of
the httpclient need to be rework for that.

This patch change the IO handler so it copies partially the data instead
of swapping buffer. This is needed because the b_xfer won't never work
if the destination buffer is not empty, which is the case when
buffering.
2022-04-06 11:43:01 +02:00
William Lallemand
58a81aeb91 BUG/MINOR: httpclient: CF_SHUTW_NOW should be tested with channel_is_empty()
CF_SHUTW_NOW shouldn't be a condition alone to exit the io handler, it
must be tested with the emptiness of the response channel.

Must be backported to 2.5.
2022-03-18 11:34:10 +01:00
William Lallemand
1eca894321 BUG/MINOR: httpclient: process the response when received before the end of the request
A server could reply a response with a shut before the end of the htx
transfer, in this case the httpclient would leave before computing the
received response.

This patch fixes the issue by calling the "process_data" label instead of
the "more" label which don't do the si_shut.

Must be bacported in 2.5.
2022-03-18 11:34:10 +01:00
William Lallemand
a625b03e83 BUG/MINOR: httpclient: only check co_data() instead of HTTP_MSG_DATA
Checking msg >= HTTP_MSG_DATA was useful to check if we received all the
data. However it does not work correctly in case of errors because we
don't reach this state, preventing to catch the error in the httpclient.

The consequence of this problem is that we don't get the status code of
the error response upon an error.

Fix the issue by only checking co_data().

Must be backported to 2.5.
2022-03-18 11:34:10 +01:00
Willy Tarreau
211ea252d9 BUG/MINOR: logs: fix logsrv leaks on clean exit
Log servers are a real mess because:
  - entries are duplicated using memcpy() without their strings being
    reallocated, which results in these ones not being freeable every
    time.

  - a new field, ring_name, was added in 2.2 by commit 99c453df9
    ("MEDIUM: ring: new section ring to declare custom ring buffers.")
    but it's never initialized during copies, causing the same issue

  - no attempt is made at freeing all that.

Of course, running "haproxy -c" under ASAN quickly notices that and
dumps a core.

This patch adds the missing strdup() and initialization where required,
adds a new free_logsrv() function to cleanly free() such a structure,
calls it from the proxy when iterating over logsrvs instead of silently
leaking their file names and ring names, and adds the same logsrv loop
to the proxy_free_defaults() function so that we don't leak defaults
sections on exit.

It looks a bit entangled, but it comes as a whole because all this stuff
is inter-dependent and was missing.

It's probably preferable not to backport this in the foreseable future
as it may reveal other jokes if some obscure parts continue to memcpy()
the logsrv struct.
2022-03-17 19:53:46 +01:00
William Lallemand
715c101a19 BUILD: httpclient: fix build without SSL
src/http_client.c: In function ‘httpclient_cfg_postparser’:
src/http_client.c:1065:8: error: unused variable ‘errmsg’ [-Werror=unused-variable]
 1065 |  char *errmsg = NULL;
      |        ^~~~~~
src/http_client.c:1064:6: error: unused variable ‘err_code’ [-Werror=unused-variable]
 1064 |  int err_code = 0;
      |      ^~~~~~~~

Fix the build of the httpclient without SSL, the problem was introduced
with previous patch 71e3158 ("BUG/MINOR: httpclient: send the SNI using
the host header")

Must be backported in 2.5 as well.
2022-03-16 16:39:23 +01:00
William Lallemand
71e3158395 BUG/MINOR: httpclient: send the SNI using the host header
Generate an SNI expression which uses the Host header of the request.
This is mandatory for most of the SSL servers nowadays.

Must be backported in 2.5 with the previous patch which export
server_parse_sni_expr().
2022-03-16 15:55:30 +01:00
William Lallemand
97f69c6fb5 BUG/MEDIUM: httpclient: must manipulate head, not first
The httpclient mistakenly use the htx_get_first{_blk}() functions instead
of the htx_get_head{_blk}() functions. Which could stop the httpclient
because it will be without the start line, waiting for data that won't never
come.

Must be backported in 2.5.
2022-03-14 15:10:12 +01:00
William Lallemand
c020b2505d BUG/MINOR: httpclient: remove the UNUSED block when parsing headers
Remove the UNUSED blocks when iterating on headers, we should not stop
when encountering one. We should only stop iterating once we found the
EOH block. It doesn't provoke a problem, since we don't manipulates
the headers before treating them, but it could evolve in the future.

Must be backported to 2.5.
2022-03-14 15:10:12 +01:00
William Lallemand
c8f1eb99b4 BUG/MINOR: httpclient: consume partly the blocks when necessary
Consume partly the blocks in the httpclient I/O handler when there is
not enough room in the destination buffer for the whole block or when
the block is not contained entirely in the channel's output.

It prevents the I/O handler to be stuck in cases when we need to modify
the buffer with a filter for exemple.

Must be backported in 2.5.
2022-03-14 15:10:12 +01:00