Commit Graph

24048 Commits

Author SHA1 Message Date
Willy Tarreau
3cbeb6a74b [RELEASE] Released version 3.2-dev7
Released version 3.2-dev7 with the following main changes :
    - BUG/MEDIUM: applet: Don't handle EOI/EOS/ERROR is applet is waiting for room
    - BUG/MEDIUM: spoe/mux-spop: Introduce an NOOP action to deal with empty ACK
    - BUG/MINOR: cfgparse: fix NULL ptr dereference in cfg_parse_peers
    - BUG/MEDIUM: uxst: fix outgoing abns address family in connect()
    - REGTESTS: fix reg-tests/server/abnsz.vtc
    - BUG/MINOR: log: fix outgoing abns address family
    - BUG/MINOR: sink: add tempo between 2 connection attempts for sft servers
    - MINOR: clock: always use atomic ops for global_now_ms
    - CI: QUIC Interop: clean old docker images
    - BUG/MINOR: stream: do not call co_data() from __strm_dump_to_buffer()
    - BUG/MINOR: mux-h1: always make sure h1s->sd exists in h1_dump_h1s_info()
    - MINOR: tinfo: add a new thread flag to indicate a call from a sig handler
    - BUG/MEDIUM: stream: never allocate connection addresses from signal handler
    - MINOR: freq_ctr: provide non-blocking read functions
    - BUG/MEDIUM: stream: use non-blocking freq_ctr calls from the stream dumper
    - MINOR: tools: use only opportunistic symbols resolution
    - CLEANUP: task: move the barrier after clearing th_ctx->current
    - MINOR: compression: Introduce minimum size
    - BUG/MINOR: h2: always trim leading and trailing LWS in header values
    - MINOR: tinfo: split the signal handler report flags into 3
    - BUG/MEDIUM: stream: don't use localtime in dumps from a signal handler
    - OPTIM: connection: don't try to kill other threads' connection when !shared
    - BUILD: add possibility to use different QuicTLS variants
    - MEDIUM: fd: Wait if locked in fd_grab_tgid() and fd_take_tgid().
    - MINOR: fd: Add fd_lock_tgid_cur().
    - MEDIUM: epoll: Make sure we can add a new event
    - MINOR: pollers: Add a fixup_tgid_takeover() method.
    - MEDIUM: pollers: Drop fd events after a takeover to another tgid.
    - MEDIUM: connections: Allow taking over connections from other tgroups.
    - MEDIUM: servers: Add strict-maxconn.
    - BUG/MEDIUM: server: properly initialize PROXY v2 TLVs
    - BUG/MINOR: server: fix the "server-template" prefix memory leak
    - BUG/MINOR: h3: do not report transfer as aborted on preemptive response
    - CLEANUP: h3: fix documentation of h3_rcv_buf()
    - MINOR: hq-interop: properly handle incomplete request
    - BUG/MEDIUM: mux-fcgi: Try to fully fill demux buffer on receive if not empty
    - MINOR: h1: permit to relax the websocket checks for missing mandatory headers
    - BUG/MINOR: hq-interop: fix leak in case of rcv_buf early return
    - BUG/MINOR: server: check for either proxy-protocol v1 or v2 to send hedaer
    - MINOR: jws: implement a JWK public key converter
    - DEBUG: init: add a way to register functions for unit tests
    - TESTS: add a unit test runner in the Makefile
    - TESTS: jws: register a unittest for jwk
    - CI: github: run make unit-tests on the CI
    - TESTS: add config smoke checks in the unit tests
    - MINOR: jws: conversion to NIST curves name
    - CI: github: remove smoke tests from vtest.yml
    - TESTS: ist: fix wrong array size
    - TESTS: ist: use the exit code to return a verdict
    - TESTS: ist: add a ist.sh to launch in make unit-tests
    - CI: github: fix h2spec.config proxy names
    - DEBUG: init: Add a macro to register unit tests
    - MINOR: sample: allow custom date format in error-log-format
    - CLEANUP: log: removing "log-balance" references
    - BUG/MINOR: log: set proper smp size for balance log-hash
    - MINOR: log: use __send_log() with exact payload length
    - MEDIUM: log: postpone the decision to send or not log with empty messages
    - MINOR: proxy: make pr_mode enum bitfield compatible
    - MINOR: cfgparse-listen: add and use cfg_parse_listen_match_option() helper
    - MINOR: log: add options eval for log-forward
    - MINOR: log: detach prepare from parse message
    - MINOR: log: add dont-parse-log and assume-rfc6587-ntf options
    - BUG/MEIDUM: startup: return to initial cwd only after check_config_validity()
    - TESTS: change the output of run-unittests.sh
    - TESTS: unit-tests: store sh -x in a result file
    - CI: github: show results of the Unit tests
    - BUG/MINOR: cfgparse/peers: fix inconsistent check for missing peer server
    - BUG/MINOR: cfgparse/peers: properly handle ignored local peer case
    - BUG/MINOR: server: dont return immediately from parse_server() when skipping checks
    - MINOR: cfgparse/peers: provide more info when ignoring invalid "peer" or "server" lines
    - BUG/MINOR: stream: fix age calculation in "show sess" output
    - MINOR: stream/cli: rework "show sess" to better consider optional arguments
    - MINOR: stream/cli: make "show sess" support filtering on front/back/server
    - TESTS: quic: create first quic unittest
    - MINOR: h3/hq-interop: restore function for standalone FIN receive
    - MINOR/OPTIM: mux-quic: do not allocate rxbuf on standalone FIN
    - MINOR: mux-quic: refine reception of standalone STREAM FIN
    - MINOR: mux-quic: define globally stream rxbuf size
    - MINOR: mux-quic: define rxbuf wrapper
    - MINOR: mux-quic: store QCS Rx buf in a single-entry tree
    - MINOR: mux-quic: adjust Rx data consumption API
    - MINOR: mux-quic: adapt return value of qcc_decode_qcs()
    - MAJOR: mux-quic: support multiple QCS RX buffers
    - MEDIUM: mux-quic: handle too short data splitted on multiple rxbuf
    - MAJOR: mux-quic: increase stream flow-control for multi-buffer alloc
    - BUG/MINOR: cfgparse-tcp: relax namespace bind check
    - MINOR: startup: adjust alert messages, when capabilities are missed
2025-03-07 16:37:57 +01:00
Valentine Krasnobaeva
7d427134fe MINOR: startup: adjust alert messages, when capabilities are missed
CAP_SYS_ADMIN support was added, in order to access sockets in namespaces. So
let's adjust the alert at startup, where we check preserved capabilities from
global.last_checks. Let's mention here cap_sys_admin as well.
2025-03-07 16:37:16 +01:00
Damien Claisse
f0a07f834c BUG/MINOR: cfgparse-tcp: relax namespace bind check
Commit 5cbb278 introduced cap_sys_admin support, and enforced checks for
both binds and servers. However, when binding into a namespace, the bind
is done before dropping privileges. Hence, checking that we have
cap_sys_admin capability set in this case is not needed (and it would
decrease security to add it).
For users starting haproxy with other user than root and without
cap_sys_admin, bind should have already failed.
As a consequence, relax runtime check for binds into a namespace.
2025-03-07 16:23:29 +01:00
Amaury Denoyelle
dc7913d814 MAJOR: mux-quic: increase stream flow-control for multi-buffer alloc
Support for multiple Rx buffers per QCS instance has been introduced by
previous patches. However, due to flow-control initial values, client
were still unable to fully used this to increase their upload
throughput.

This patch increases max-stream-data-bidi-remote flow-control initial
values. A new define QMUX_STREAM_RX_BUF_FACTOR will fix the number of
concurrent buffers allocable per QCS. It is set to 90.

Note that connection flow-control initial value did not changed. It is
still configured to be equivalent to bufsize multiplied by the maximum
concurrent streams. This ensures that Rx buffers allocation is still
constrained per connection, so that it won't be possible to have all
active QCS instances using in parallel their maximum Rx buffers count.
2025-03-07 12:06:27 +01:00
Amaury Denoyelle
75027692a3 MEDIUM: mux-quic: handle too short data splitted on multiple rxbuf
Previous commit introduces support for multiple Rx buffers per QCS
instance. Contiguous data may be splitted accross multiple buffers
depending on their offset.

A particular issue could arise with this new model. Indeed, app_ops
rcv_buf callback can still deal with a single buffer at a time. This may
cause a deadlock in decoding if app_ops layer cannot proceed due to
partial data, but such data are precisely divided on two buffers. This
can for example intervene during HTTP/3 frame header parsing.

To deal with this, a new function is implemented to force data realign
between two contiguous buffers. This is called only when app_ops rcv_buf
returned 0 but data is available in the next buffer after the current
one. In this case, data are transferred from the next into the current
buffer via qcs_transfer_rx_data(). Decoding is then restarted, which
should ensure that app_ops layer has enough data to advance.

During this operation, special care is ensure to removed both
qc_stream_rxbuf entries, as their offset are adjusted. The next buffer
is only reinserted if there is remaining data in it, else it can be
freed.

This case is not easily reproducible as it depends on the HTTP/3 framing
used by the client. It seems to be easily reproduced though with quiche.
$ quiche-client --http-version HTTP/3 --method POST --body /tmp/100m \
  "https://127.0.0.1:20443/post"
2025-03-07 12:06:27 +01:00
Amaury Denoyelle
60f64449fb MAJOR: mux-quic: support multiple QCS RX buffers
Implement support for multiple Rx buffers per QCS instances. This
requires several changes mostly in qcc_recv() / qcc_decode_qcs() which
deal with STREAM frames reception and decoding. These multiple buffers
can be stored in QCS rx.bufs tree which was introduced in an earlier
patch.

On STREAM frame reception, a buffer is retrieved from QCS bufs tree, or
allocated if necessary, based on the data starting offset. Each buffers
are aligned on bufsize for convenience. This ensures there is no overlap
between two contiguous buffers. Special care is taken when dealing with
a STREAM frame which must be splitted and stored in two contiguous
buffers.

When decoding input data, qcc_decode_qcs() is still invoked with a
single buffer as input. This requires a new while loop to ensure
decoding is performed accross multiple contiguous buffers until all data
are decoded or app stream buffer is full.

Also, after qcs_consume() has been performed, the stream Rx channel is
immediately closed if FIN was already received and QCS now contains only
a single buffer with all remaining data. This is necessary as qcc_recv()
is unable to close the Rx channel if FIN is received for a buffer
different from the current readable offset.

Note that for now stream flow-control value is still too low to fully
utilizing this new infrastructure and improve clients upload throughput.
Indeed, flow-control max-stream-data initial values are set to match
bufsize. This ensures that each QCS will use 1 buffer, or at most 2 if
data are splitted. A future patch will increase this value to unblock
this limitation.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
7b168e356f MINOR: mux-quic: adapt return value of qcc_decode_qcs()
Change return value of qcc_decode_qcs(). It now directly returns the
value from app_ops rcv_buf callback. Function documentation is updated
to reflect this.

For now, qcc_decode_qcs() return value is ignored by callers, so this
patch should not have any functional change. However, it will become
necessary when implementing multiple Rx buffers per QCS, as a loop will
be implemented to invoke qcc_decode_qcs() on several contiguous buffers.
Decoding must be stopped however as soon as an error is returned by
rcv_buf callback. This is also the case in case of a null value, which
indicates there is not enough data to continue decoding.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
6b5607d66f MINOR: mux-quic: adjust Rx data consumption API
HTTP/3 data are converted into HTX via qcc_decode_qcs() function. On
completion, these data are removed from QCS Rx buffer via qcs_consume().

This patch adjust qcs_consume() API with several changes. Firstly, the
Rx buffer instance to operate on must now be specified as a new argument
to the function. Secondly, buffer liberation when all data were removed
from qcs_consume() is extracted up to qcc_decode_qcs() caller.

No functional change with this patch. The objective is to have an API
which can be better adapted to multiple Rx buffers per QCS instance.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
a4f31ffeeb MINOR: mux-quic: store QCS Rx buf in a single-entry tree
Convert QCS rx buffer pointer to a tree container. Additionnaly, offset
field of qc_stream_rxbuf is thus transformed into a node tree.

For now, only a single Rx buffer is stored at most in QCS tree. Multiple
Rx buffers will be implemented in a future patch to improve QUIC clients
upload throughput.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
cc3c2d1f12 MINOR: mux-quic: define rxbuf wrapper
Define a new type qc_stream_rxbuf. This is used as a wrapper around QCS
Rx buffer with encapsulation of the ncbuf storage. It is allocated via a
new pool. Several functions are adapted to be able to deal with
qc_stream_rxbuf as a wrapper instead of the previous plain ncbuf
instance.

No functional change should happen with this patch. For now, only a
single qc_stream_rxbuf can be instantiated per QCS. However, this new
type will be useful to implement multiple Rx buffer storage in a future
commit.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
4b1e63d191 MINOR: mux-quic: define globally stream rxbuf size
QCS uses ncbuf for STREAM data storage. This serves as a limit for
maximum STREAM buffering capacity, advertised via QUIC transport
parameters for initial flow-control values.

Define a new function qmux_stream_rx_bufsz() which can be used to
retrieve this Rx buffer size. This can be used both in MUX/H3 layers and
in QUIC transport parameters.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
7dd1eec2b1 MINOR: mux-quic: refine reception of standalone STREAM FIN
Reception of standalone STREAM FIN is a corner case, which may be
difficult to handle. In particular, care must be taken to ensure app_ops
rcv_buf() is always called to be notify about FIN, even if Rx buffer is
empty or full demux flag is set. If this is the case, it could prevent
closure of QCS Rx channel.

To ensure this, rcv_buf() was systematically called if FIN was received,
with or without data payload. This could called unnecessary invokation
when FIN is transmitted with data and full demux flag is set, or data
are received out-of-order.

This patches improve qcc_recv() by detecting explicitely a standalone
FIN case. Thus, rcv_buf() is only forcefully called in this case and if
all data were already previously received.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
20dc8e4ec2 MINOR/OPTIM: mux-quic: do not allocate rxbuf on standalone FIN
STREAM FIN may be received without any payload. However, qcc_recv()
always called qcs_get_ncbuf() indiscriminately, which may allocate a QCS
Rx buffer. This is unneeded as there is no payload to store.

Improve this by skipping qcs_get_ncbuf() invokation when dealing with a
standalone FIN signal. This should prevent superfluous buffer
allocation.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
861b11334c MINOR: h3/hq-interop: restore function for standalone FIN receive
Previously, a function qcs_http_handle_standalone_fin() was implemented
to handle a received standalone FIN, bypassing app_ops layer decoding.
However, this was removed as app_ops layer interaction is necessary. For
example, HTTP/3 checks that FIN is never sent on the control uni stream.

This patch reintroduces qcs_http_handle_standalone_fin(), albeit in a
slightly diminished version. Most importantly, it is now the
responsibility of the app_ops layer itself to use it, to avoid the
shortcoming described above.

The main objective of this patch is to be able to support standalone FIN
in HTTP/0.9 layer. This is easily done via the reintroduction of
qcs_http_handle_standalone_fin() usage. This will be useful to perform
testing, as standalone FIN is a corner case which can easily be broken.
2025-03-07 12:06:26 +01:00
Amaury Denoyelle
6f95d0dad0 TESTS: quic: create first quic unittest
Define a first unit-test dedicated to QUIC. A single test for now
ensures that variable length decoding is compliant. This should be
extended in the future with new set of tests.
2025-03-07 12:06:26 +01:00
Willy Tarreau
5e558c1727 MINOR: stream/cli: make "show sess" support filtering on front/back/server
With "show sess", particularly "show sess all", we're often missing the
ability to inspect only streams attached to a frontend, backend or server.
Let's just add these filters to the command. Only one at a time may be set.

One typical use case could be to dump streams attached to a server after
issuing "shutdown sessions server XXX" to figure why any wouldn't stop
for example.
2025-03-07 10:38:12 +01:00
Willy Tarreau
2bd7cf53cb MINOR: stream/cli: rework "show sess" to better consider optional arguments
The "show sess" CLI command parser is getting really annoying because
several options were added in an exclusive mode as the single possible
argument. Recently some cumulable options were added ("show-uri") but
the older ones were not yet adapted. Let's just make sure that the
various filters such as "older" and "age" now belong to the options
and leave only <id>, "all", and "help" for the first ones. The doc was
updated and it's now easier to find these options.
2025-03-07 10:36:58 +01:00
Willy Tarreau
1cdf2869f6 BUG/MINOR: stream: fix age calculation in "show sess" output
The "show sess" output reports an age that's based on the last byte of
the HTTP request instead of the stream creation date, due to a confusion
between logs->request_ts and the request_date sample fetch function. Most
of the time these are equal except when the request is not yet full for
any reason (e.g. wait-body). This explains why a few "show sess" could
report a few new streams aged by 99 days for example.

Let's perform the correct request timestamp calculation like the sample
fetch function does, by adding t_idle and t_handshake to the accept_ts.
Now the stream's age is correct and can be correctly used with the
"show sess older <age>" variant.

This issue was introduced in 2.9 and the fix can be backported to 3.0.
2025-03-07 10:36:58 +01:00
Aurelien DARRAGON
dbb25720dd MINOR: cfgparse/peers: provide more info when ignoring invalid "peer" or "server" lines
Invalid (incomplete) "server" or "peer" lines under peers section are now
properly ignored. For completeness, in this patch we add some reports so
that the user knows that incomplete lines were ignored.

For an incomplete server line, since it is tolerated (see GH #565), we
only emit a diag warning.

For an incomplete peer line, we report a real warning, as it is not
expected to have a peer line without an address:port specified.

Also, 'newpeer == curpeers->local' check could be simplified since
we already have the 'local_peer' variable which tells us that the
parsed line refers to a local peer.
2025-03-07 09:39:51 +01:00
Aurelien DARRAGON
a76b5358f0 BUG/MINOR: server: dont return immediately from parse_server() when skipping checks
If parse_server() is called under peers section parser, and the address
needs to be parsed but it is missing, we directly return from the function

However since 0fc136ce5b ("REORG: server: use parsing ctx for server
parsing"), parse_server() uses parsing ctx to emit warning/errors, and
the ctx must be reset before returning from the function, yet this early
return was overlooked. Because of that, any ha_{warning,alert..} message
reported after early return from parse_server() could cause messages to
have an extra "parsing [file:line]" info.

We fix that by ensuring parse_server() doesn't return without resetting
the parsing context.

It should be backported up to 2.6
2025-03-07 09:39:46 +01:00
Aurelien DARRAGON
054443dfb9 BUG/MINOR: cfgparse/peers: properly handle ignored local peer case
In 8ba10fea6 ("BUG/MINOR: peers: Incomplete peers sections should be
validated."), some checks were relaxed in parse_server(), and extra logic
was added in the peers section parser in an attempt to properly ignore
incomplete "server" or "peer" statement under peers section.

This was done in response to GH #565, the main intent was that haproxy
should already complain about incomplete peers section (ie: missing
localpeer).

However, 8ba10fea69 explicitly skipped the peer cleanup upon missing
srv association for local peers. This is wrong because later haproxy
code always assumes that peer->srv is valid. Indeed, we got reports
that the (invalid) config below would cause segmentation fault on
all stable versions:

 global
   localpeer 01JM0TEPAREK01FQQ439DDZXD8

 peers my-table
   peer 01JM0TEPAREK01FQQ439DDZXD8

 listen dummy
   bind localhost:8080

To fix the issue, instead of by-passing some cleanup for the local
peer, handle this case specifically by doing the regular peer cleanup
and reset some fields set on the curpeers and curpeers proxy because
of the invalid local peer (do as if the peer was not declared).

It should still comply with requirements from #565.

This patch should be backported to all stable versions.
2025-03-06 22:05:29 +01:00
Aurelien DARRAGON
2560ab892f BUG/MINOR: cfgparse/peers: fix inconsistent check for missing peer server
In the "peers" section parser, right after parse_server() is called, we
used to check whether the curpeers->peers_fe->srv pointer was set or not
to know if parse_server() successfuly added a server to the peers proxy,
server that we can then associate to the new peer.

However the check is wrong, as curpeers->peers_fe->srv points to the
last added server, if a server was successfully added before the
failing one, we cannot detect that the last parse_server() didn't
add a server. This is known to cause bug with bad "peer"/"server"
statements.

To fix the issue, we save a pointer on the last known
curpeers->peers_fe->srv before parse_server() is called, and we then
compare the save with the pointer after parse_server(), if the value
didn't change, then parse_server() didn't add a server. This makes
the check consistent in all situations.

It should be backported to all stable versions.
2025-03-06 22:05:24 +01:00
William Lallemand
29db5406b4 CI: github: show results of the Unit tests
Add a "Show Unit-Tests results" section which show each unit test which
failed by displaying their result file.
2025-03-06 21:23:54 +01:00
William Lallemand
0b22c8e0e0 TESTS: unit-tests: store sh -x in a result file
Store `sh -e -x` of the test in a result file. This file is deleted upon
success, but can be consulted if the test fails
2025-03-06 21:22:38 +01:00
William Lallemand
7fdc4160b2 TESTS: change the output of run-unittests.sh
- "check" is run with sh -e so it will stop at the first error
- output of "check" is not shown anymore
- add a line with the name of the failed test
2025-03-06 17:53:53 +01:00
Valentine Krasnobaeva
e900ef987e BUG/MEIDUM: startup: return to initial cwd only after check_config_validity()
In check_config_validity() we evaluate some sample fetch expressions
(log-format, server rules, etc). These expressions may use external files like
maps.

If some particular 'default-path' was set in the global section before, it's no
longer applied to resolve file pathes in check_config_validity(). parse_cfg()
at the end of config parsing switches back to the initial cwd.

This fixes the issue #2886.

This patch should be backported in all stable versions since 2.4.0, including
2.4.0.
2025-03-06 10:49:48 +01:00
Roberto Moreda
f98b5c4f59 MINOR: log: add dont-parse-log and assume-rfc6587-ntf options
This commit introduces the dont-parse-log option to disable log message
parsing, allowing raw log data to be forwarded without modification.

Also, it adds the assume-rfc6587-ntf option to frame log messages
using only non-transparent framing as per RFC 6587. This avoids
missparsing in certain cases (mainly with non RFC compliant messages).

The documentation is updated to include details on the new options and
their intended use cases.

This feature was discussed in GH #2856
2025-03-06 09:30:39 +01:00
Roberto Moreda
c25e6f5efa MINOR: log: detach prepare from parse message
This commit adds a new function `prepare_log_message` to initialize log
message buffers and metadata. This function sets default values for log
level and facility, ensuring a consistent starting state for log
processing. It also prepares the buffer and metadata fields, simplifying
subsequent log parsing and construction.
2025-03-06 09:30:31 +01:00
Roberto Moreda
834e9af877 MINOR: log: add options eval for log-forward
This commit adds parsing of options in log-forward config sections and
prepares the scenario to implement actual changes of behaviuor. So far
we only take in account proxy->options2, which is the bit container with
more available positions.
2025-03-06 09:30:25 +01:00
Aurelien DARRAGON
0746f6bde0 MINOR: cfgparse-listen: add and use cfg_parse_listen_match_option() helper
cfg_parse_listen_match_option() takes cfg_opt array as parameter, as well
current args, expected mode and cap bitfields.

It is expected to be used under cfg_parse_listen() function or similar.
Its goal is to remove code duplication around proxy->options and
proxy->options2 handling, since the same checks are performed for the
two. Also, this function could help to evaluate proxy options for
mode-specific proxies such as log-forward section for instance:
by giving the expected mode and capatiblity as input, the function
would only match compatible options.
2025-03-06 09:30:18 +01:00
Aurelien DARRAGON
d9aa199100 MINOR: proxy: make pr_mode enum bitfield compatible
Current pr_mode enum is a regular enum because a proxy only supports one
mode at a time. However it can be handy for a function to be given a
list of compatible modes for a proxy, and we can't do that using a
bitfield because pr_mode is not bitfield compatible (values share
the same bits).

In this patch we manually define pr_mode values so that they are all
using separate bits and allows a function to take a bitfield of
compatible modes as parameter.
2025-03-06 09:30:11 +01:00
Aurelien DARRAGON
c7abe7778e MEDIUM: log: postpone the decision to send or not log with empty messages
As reported by Nick Ramirez in GH #2891, it is currently not possible to
use log-profile without a log-format set on the proxy.

This is due to historical reason, because all log sending functions avoid
trying to send a log with empty message. But now with log-profile which
can override log-format, it is possible that some loggers may actually
end up generating a valid log message that should be sent! Yet from the
upper logging functions we don't know about that because loggers are
evaluated in lower API functions.

Thus, to avoid skipping potentially valid messages (thanks to log-profile
overrides), in this patch we postpone the decision to send or not empty
log messages in lower log API layer, ie: _process_send_log_final(), once
the log-profile settings were evaluated for a given logger.

A known side-effect of this change is that fe->log_count statistic may
be increased even if no log message is sent because the message was empty
and even the log-profile didn't help to produce a non empty log message.
But since configurations lacking proxy log-format are not supposed to be
used without log-profile (+ log steps combination) anyway it shouldn't be
an issue.
2025-03-05 15:38:52 +01:00
Aurelien DARRAGON
9e9b110032 MINOR: log: use __send_log() with exact payload length
Historically, __send_log() was called with terminating NULL byte after
the message payload. But now that __send_log() supports being called
without terminating NULL byte (thanks to size hint), and that __sendlog()
actually stips any \n or NULL byte, we don't need to bother with that
anymore. So let's remove extra logic around __send_log() users where we
added 1 extra byte for the terminating NULL byte.

No change of behavior should be expected.
2025-03-05 15:38:46 +01:00
Aurelien DARRAGON
94a9b0f5de BUG/MINOR: log: set proper smp size for balance log-hash
result.data.u.str.size was set to size+1 to take into account terminating
NULL byte as per the comment. But this is wrong because the caller is free
to set size to just the right amount of bytes (without terminating NULL
byte). In fact all smp API functions will not read past str.data so there
is not risk about uninitialized reads, but this leaves an ambiguity for
converters that may use all the smp size to perform transformations, and
since we don't know about the "message" memory origin, we cannot assume
that its size may be greater than size. So we max it out to size just to
be safe.

This bug was not known to cause any issue, it was spotted during code
review. It should be backported in 2.9 with b30bd7a ("MEDIUM: log/balance:
support for the "hash" lb algorithm")
2025-03-05 15:38:41 +01:00
Aurelien DARRAGON
ddf66132f4 CLEANUP: log: removing "log-balance" references
This is a complementary patch to 0e1f389fe9 ("DOC: config: removing
"log-balance" references"): we properly removed all log-balance
references in the doc but there remained some in the code, let's fix
that.

It could be backported in 2.9 with 0e1f389fe9
2025-03-05 15:38:34 +01:00
Valentine Krasnobaeva
b46b81949f MINOR: sample: allow custom date format in error-log-format
Sample fetches %[accept_date] and %[request_date] with converters can be used
in error-log-format string. But in the most error cases they fetches nothing,
as error logs are produced on SSL handshake issues or when invalid PROXY
protocol header is used. Stream object is never allocated in such cases and
smp_fetch_accept_date() just simply returns 0.

There is a need to have a custom date format (ISO8601) also in the error logs,
along with normal logs. When sess_build_logline_orig() builds log line it
always copies the accept date to strm_logs structure. When stream is absent,
accept date is copied from the session object.

So, if the steam object wasn't allocated, let's use the session date info in
smp_fetch_accept_date(). This allows then, in sample_process(), to apply to the
fetched date different converters and formats.

This fixes the issue #2884.
2025-03-04 18:57:29 +01:00
Olivier Houchard
335ef3264b DEBUG: init: Add a macro to register unit tests
Add a new macro, REGISTER_UNITTEST(), that will automatically make sure
we call hap_register_unittest(), instead of having to create a function
that will do so.
2025-03-04 18:18:10 +01:00
William Lallemand
588237ca6e CI: github: fix h2spec.config proxy names
h2spec.config config file emitted a warning because the frontend name
has the same name as the backend.
2025-03-04 11:44:03 +01:00
William Lallemand
06d86822c1 TESTS: ist: add a ist.sh to launch in make unit-tests
Compile and run the ist unit tests from ist.sh
2025-03-04 11:25:35 +01:00
William Lallemand
11ea331e20 TESTS: ist: use the exit code to return a verdict
Use the exit code to return a verdict on the test.
2025-03-04 11:25:35 +01:00
William Lallemand
ddd2c82a35 TESTS: ist: fix wrong array size
test_istzero() and test_istpad() has the wrong array size buf[] which
lacks the space for the '\0';

Could be backported in every stable branches.
2025-03-04 11:25:25 +01:00
William Lallemand
937ece45d4 CI: github: remove smoke tests from vtest.yml
Smoke tests from the vtest.yml are not useful anymore since they are run
directly by tests/unit/smoke/test.sh. This patch removes them.
2025-03-03 12:46:20 +01:00
William Lallemand
cf71e9f5cf MINOR: jws: conversion to NIST curves name
OpenSSL version greater than 3.0 does not use the same API when
manipulating EVP_PKEY structures, the EC_KEY API is deprecated and it's
not possible anymore to get an EC_GROUP and simply call
EC_GROUP_get_curve_name().

Instead, one must call EVP_PKEY_get_utf8_string_param with the
OSSL_PKEY_PARAM_GROUP_NAME parameter, but this would result in a SECG
curves name, instead of a NIST curves name in previous version.
(ex: secp384r1 vs P-384)

This patch adds 2 functions:

- the first one look for a curves name and converts it to an openssl
  NID.

- the second one converts a NID to a NIST curves name

The list only contains: P-256, P-384 and P-521 for now, it could be
extended in the fure with more curves.
2025-03-03 12:43:32 +01:00
William Lallemand
8a6b0b06cd TESTS: add config smoke checks in the unit tests
vtest.yml contains some config checks that are used to check the
memleaks.

This patch adds a unit test which runs the same tests.
2025-03-03 12:43:32 +01:00
William Lallemand
7a2a613132 CI: github: run make unit-tests on the CI
Run the new make unit-tests on the CI.

It requires HAProxy to be built with -DDEBUG_UNIT so the -U option is
available in HAProxy
2025-03-03 12:43:32 +01:00
William Lallemand
09457111bb TESTS: jws: register a unittest for jwk
Add a way to test the jwk converter in the unit test system

    $ make TARGET=linux-glibc USE_OPENSSL=1 CFLAGS="-DDEBUG_UNIT=1"
    $ ./haproxy -U jwk foobar.pem.rsa
    {
        "kty": "RSA",
        "n":   "...",
        "e":   "AQAB"
    }
    $ ./haproxy -U jwk foobar.pem.ecdsa
    {
        "kty": "EC",
        "crv": "P-384",
        "x":   "...",
        "y":   "..."
    }

This is then tested by a shell script:

    $ HAPROXY_PROGRAM=${PWD}/haproxy tests/unit/jwk/test.sh
    + readlink -f tests/unit/jwk/test.sh
    + BASENAME=/haproxy/tests/unit/jwk/test.sh
    + dirname /haproxy/tests/unit/jwk/test.sh
    + TESTDIR=/haproxy/tests/unit/jwk
    + HAPROXY_PROGRAM=/haproxy/haproxy
    + mktemp
    + FILE1=/tmp/tmp.iEICxC5yNK
    + /haproxy/haproxy -U jwk /haproxy/tests/unit/jwk/ecdsa.key
    + diff -Naurp /haproxy/tests/unit/jwk/ecdsa.pub.jwk /tmp/tmp.iEICxC5yNK
    + rm /tmp/tmp.iEICxC5yNK
    + mktemp
    + FILE2=/tmp/tmp.EIrGZGaCDi
    + /haproxy/haproxy -U jwk /haproxy/tests/unit/jwk/rsa.key
    + diff -Naurp /haproxy/tests/unit/jwk/rsa.pub.jwk /tmp/tmp.EIrGZGaCDi
    + rm /tmp/tmp.EIrGZGaCDi

    $ echo $?
    0
2025-03-03 12:43:32 +01:00
William Lallemand
1e7478bb4e TESTS: add a unit test runner in the Makefile
`make unit-tests` would run shell scripts from tests/unit/

The run-unittests.sh script will look for any .sh in tests/unit/ and
will call it twice:

- first with the 'check' argument in order to decide if we should skip
  the test or not
- second to run the check

A simple test could be written this way:

	#!/bin/sh

	check() {
	       ${HAPROXY_PROGRAM} -cc 'feature(OPENSSL)'
	       command -v socat
	}

	run() {
		 ${HAPROXY_PROGRAM} -dI -f ${ROOTDIR}/examples/quick-test.cfg -c
	}

	case "$1" in
	       "check")
	               check
	       ;;
	       "run")
	               run
	       ;;
	esac

The tests *MUST* be written in POSIX shell in order to be portable, and
any special commands should be tested with `command -v` before using it.

Tests are run with `sh -e` so everything must be tested.
2025-03-03 12:43:32 +01:00
William Lallemand
a647839954 DEBUG: init: add a way to register functions for unit tests
Doing unit tests with haproxy was always a bit difficult, some of the
function you want to test would depend on the buffer or trash buffer
initialisation of HAProxy, so building a separate main() for them is
quite hard.

This patch adds a way to register a function that can be called with the
"-U" parameter on the command line, will be executed just after
step_init_1() and will exit the process with its return value as an exit
code.

When using the -U option, every keywords after this option is passed to
the callback and could be used as a parameter, letting the capability to
handle complex arguments if required by the test.

HAProxy need to be built with DEBUG_UNIT to activate this feature.
2025-03-03 12:43:32 +01:00
William Lallemand
4dc0ba233e MINOR: jws: implement a JWK public key converter
Implement a converter which takes an EVP_PKEY and converts it to a
public JWK key. This is the first step of the JWS implementation.

It supports both EC and RSA keys.

Know to work with:

- LibreSSL
- AWS-LC
- OpenSSL > 1.1.1
2025-03-03 12:43:32 +01:00
Willy Tarreau
730641f7ca BUG/MINOR: server: check for either proxy-protocol v1 or v2 to send hedaer
As reported in issue #2882, using "no-send-proxy-v2" on a server line does
not properly disable the use of proxy-protocol if it was enabled in a
default-server directive in combination with other PP options. The reason
for this is that the sending of a proxy header is determined by a test on
srv->pp_opts without any distinction, so disabling PPv2 while leaving other
options results in a PPv1 header to be sent.

Let's fix this by explicitly testing for the presence of either send-proxy
or send-proxy-v2 when deciding to send a proxy header.

This can be backported to all versions. Thanks to Andre Sencioles (@asenci)
for reporting the issue and testing the fix.
2025-03-03 04:05:47 +01:00