26428 Commits

Author SHA1 Message Date
Willy Tarreau
ed44adc3ca BUG/MINOR: memprof: avoid a small memory leak in "show profiling"
In 3.1, per-DSO statistics were added to the memprofile output by
commit 401fb0e87a ("MINOR: activity/memprofile: show per-DSO stats").
However an strdup() is performed there on the .info field, that is
never freed when leaving the function. Let's do it each time we leave
it. Ironically, this was found thanks to "show profiling" showing
itself as an unbalanced caller of strdup().

This needs to be backported to 3.0 since that commit was backported
there.
2026-03-12 18:06:37 +01:00
Willy Tarreau
4d5a91b8af BUILD: makefile: fix range build without test command
In 3.3, the "make range" target adopted a test command via the TEST_CMD
variable, with commit 90b70b61b1 ("BUILD: makefile: implement support
for running a command in range"). However now it breaks the script when
TEST_CMD is not set due to the shell expansion leaving two '||' operators
side by side. Let's fix this by passing the contents of the makefile
variable in positional arguments before executing them.
2026-03-12 18:06:37 +01:00
Olivier Houchard
4102461dd6 BUG/MEDIUM: ssl: Don't report read data as early data with AWS-LC
To read early data with AWS-LC (and BoringSSL), we have to use
SSL_read(). But SSL_read() will also try to do the handshake if it
hasn't been done yet, and at some point will do the handshake and will
return data that are actually not early data. So use SSL_in_early_data()
to make sure that the data we received are actually early data, and only
if so add the CO_FL_EARLY_DATA flag. Otherwise any data first received will be
considered early, and a Early-data header will be added.
As this bug was introduced by 76ba026548975a6d1bc23d1344807c64d994bf1e,
it should be backported with it.
2026-03-12 17:31:12 +01:00
William Lallemand
13d13691b5 BUG/MINOR: mworker: always stop the receiving listener
Upon _send_status, always stop the listener from which the request
was received, rather than looking it up from the proc_list entry via
fdtab[proc->ipc_fd[0]].owner.

A BUG_ON is added to verify that the listener which received the
request is the one expected for the reported PID.

This means it is no longer possible to send "_send_status READY XXX"
manually through the master CLI for testing, as that would trigger
the BUG_ON.

Must be backported as far as 3.1.
2026-03-12 17:29:50 +01:00
Olivier Houchard
76ba026548 BUG/MEDIUM: ssl: Handle receiving early data with BoringSSL/AWS-LC
The API for early data is a bit different with BoringSSL and AWS-LC than
it is for OpenSSL. As it was implemented, early data would be accepted,
but would not be processed until the handshake is done. Change that by
doing something similar to what OpenSSL does, and, if 0RTT has been
enabled on the listener, use SSL_read() to try to get early data before
starting the handshake, and if there's any, provide them to the mux the
same way it is done for OpenSSL.
That replaces a bunch of #ifdef SSL_READ_EARLY_DATA_SUCCESS by
something specific to OpenSSL has to be done.
This should be backported to 3.3.
2026-03-12 14:14:51 +01:00
Egor Shestakov
f24ed2a5d1 DOC/CLEANUP: config: update mentions of the old "Global parameters" section
The name of "Global section" was changed only in the summary, not in the
text itself. The names of some related refs were also updated.

Should be backported as far as 3.2.
2026-03-12 09:25:01 +01:00
Tom Braarup
b837b2b86c DOC: configuration: http-check expect example typo
On the http-check expect example
(https://docs.haproxy.org/dev/configuration.html#4.2-http-check%20expect)
there is a typo

-http-check expect header name "set-cookie" value -m beg "sessid="
+http-check expect hdr name "set-cookie" value -m beg "sessid="
2026-03-12 09:20:32 +01:00
Mia Kanashi
b6e28bb4d7 BUG/MINOR: jws: fix memory leak in jws_b64_signature
EVP_MD_CTX is allocated using EVP_MD_CTX_new() but was never freed.
ctx should be initialized to NULL otherwise EVP_MD_CTX_free(ctx) could
segfault.

Must be backported as far as 3.2.
2026-03-12 09:18:42 +01:00
Tim Duesterhus
760fef1fc0 BUG/MINOR: tcpcheck: Fix typo in error error message for http-check expect
With a config:

    backend bk_app
    	http-check expect status 200 string "status: ok"

This now correctly emits the error:

    config : parsing [./patch.cfg:2] : 'http-check expect' : only one pattern expected.

This line containing the typo is unchanged since at least HAProxy 2.2, the
patch should be backported into all supported branches.
2026-03-12 09:10:45 +01:00
William Lallemand
73732abfb2 BUILD: ssl: make X509_NAME usage OpenSSL 4.0 ready
Starting with OpenSSL 4.0, X509_get_subject_name(), X509_get_issuer_name(),
and X509_CRL_get_issuer() return a const-qualified X509_NAME pointer.
Similarly, X509_NAME_get_entry() returns a const X509_NAME_ENTRY *, and
X509_NAME_ENTRY_get_data() returns a const ASN1_STRING *.

Introduce the __X509_NAME_CONST__ macro (defined to 'const' for OpenSSL
>= 4.0.0, empty for WolfSSL and older OpenSSL version which lacks const
on these APIs) and use it to qualify X509_NAME * variables and the
parameters of the three DN helper functions ssl_sock_get_dn_entry(),
ssl_sock_get_dn_formatted(), and ssl_sock_get_dn_oneline(). This avoids
both const-qualifier warnings on OpenSSL 4.0 and discarded-qualifier
warnings on WolfSSL, without needing explicit casts at call sites.

In ssl_sock.c (ssl_get_client_ca_file) and ssl_gencert.c
(ssl_sock_do_create_cert), a __X509_NAME_CONST__ X509_NAME * variable was
being reused to store the result of X509_NAME_dup() and then passed to
mutating functions (X509_NAME_add_entry_by_txt, X509_NAME_free). Introduce
separate X509_NAME * variables (xn_dup, subject) to hold the mutable
duplicate.

Original patch from Alexandr Nedvedicky <sashan@openssl.org>:
https://www.mail-archive.com/haproxy@formilux.org/msg46696.html
2026-03-11 17:00:59 +01:00
William Lallemand
e82f03dd88 BUILD: ssl: use ASN1_STRING accessors for OpenSSL 4.0 compatibility
In OpenSSL 4.0, the ASN1_STRING struct was made opaque and direct access
to its members (->data, ->length, ->type) no longer compiles. Replace
these accesses in ssl_sock_get_serial(), ssl_sock_get_time(), and
asn1_generalizedtime_to_epoch() with the proper accessor functions
ASN1_STRING_get0_data(), ASN1_STRING_length(), and ASN1_STRING_type().

The old direct access is preserved under USE_OPENSSL_WOLFSSL since
WolfSSL does not provide these accessor functions.

Original patch from Alexandr Nedvedicky <sashan@openssl.org>:
https://www.mail-archive.com/haproxy@formilux.org/msg46696.html
2026-03-11 16:59:54 +01:00
William Lallemand
6d14fd0b29 MEDIUM: mworker: exiting when couldn't find the master mworker_proc element
When a master process is reloading, the HAPROXY_PROCESSES variable is
deserialized. In older version of the master-worker (< 1.9), no master
element was existing in this variable.

This is not suppose to happen anymore, and could have provoked problems
in the master anyway.

This patch changes the behavior by exiting the master with an alert if
mp master element was found in this variable.
2026-03-10 15:57:21 +01:00
Christopher Faulet
00563233b7 DEBUG: stconn: Add a CHECK_IF() when I/O are performed on a orphan SC
When no endpoint is attached to a SC, it is unexpected to have I/O (receive
or send). But we honestly don't know if it happens or not. So a CHECK_IF()
is added to be able to track such calls.
2026-03-10 15:10:34 +01:00
Christopher Faulet
b2b0d1a8be MINOR: stconn: Simplify sc_abort/sc_shutdown by merging calls to se_shutdown
Calls to se_shutdown were no the same between applets and mux endpoints.
Only the SHUTW flag was not the same. However, on the multiplexers are
sensitive to the true SHUTW flag. The applets handle all of them the same
way. So calls to se_shutdown() from sc_abort() and sc_shutdown() can be
merged to always use the multiplexer version.
2026-03-10 15:10:34 +01:00
Christopher Faulet
fb1bc592f5 MINOR: stconn: Totally app_ops from the stconns
The stconn app_ops structure is now empty and can be safely removed. So let's do
so.
2026-03-10 15:10:34 +01:00
Christopher Faulet
990456462f MINOR: stconn: Remove .shutdown() callback functions
These callback functions are no longer used, so they can safely be
removed. In addition, the field was removed from the app_ops structure.
2026-03-10 15:10:34 +01:00
Christopher Faulet
c65526ad57 MEDIUM: stconn: Merge all .shutdown() callback functions in sc_shutdown()
sc_shutdown() is no longer relying on .shutdown() callback functions.
Everything was merged in sc_shutdown() with a test on the app type.
2026-03-10 15:10:34 +01:00
Christopher Faulet
9dfff87b69 MINOR: stconn: Remove .abort() callback functions
These callback functions are no longer used, so they can safely be
removed. In addition, the field was removed from the app_ops structure.
2026-03-10 15:10:34 +01:00
Christopher Faulet
0fc6884bc7 MEDIUM: stconn: Merge all .abort() callback functions in sc_abort()
sc_abort() is no longer relying on .abort() callback functions.  Everything
was merged in abort() with a test on the app type.
2026-03-10 15:10:34 +01:00
Christopher Faulet
0c9741b70a MINOR: stconn: Remove .chk_snd() callback functions
These callback functions are no longer used, so they can safely be
removed. In addition, the field was removed from the app_ops structure.
2026-03-10 15:10:34 +01:00
Christopher Faulet
e33dfc4f26 MEDIUM: stconn: Merge all .chk_snd() callback functions in sc_chk_snd()
sc_chk_snd() is no longer relying on .chk_snd() callback functions.
Everything was merged in sc_chk_snd() with a test on the app type.
2026-03-10 15:10:34 +01:00
Christopher Faulet
5aa67f0587 MINOR: stconn: Remove .chk_rcv() callback functions
These callback functions are no longer used, so they can safely be
removed. In addition, the field was removed from the app_ops structure.
2026-03-10 15:10:34 +01:00
Christopher Faulet
aef7afbe65 MEDIUM: stconn: Merge all .chk_rcv() callback functions in sc_chk_rcv()
sc_chk_rcv() is no longer relying on .chk_rcv() callback functions.
Everything was merged in sc_chk_rcv() with a test on the app type.
2026-03-10 15:10:34 +01:00
Christopher Faulet
7c895092a7 MINOR: stconn: Wakup the SC with TASK_WOKEN_IO state from opposite side
When a SC is woken up by the opposite side, in inter stream-connector calls,
TASK_WOKEN_IO state is now used.
2026-03-10 15:10:34 +01:00
Christopher Faulet
aaa97c4441 MINOR: haterm: Remove hstream_wake() function
This function is no longer used, so it can be safely removed.
2026-03-10 15:10:34 +01:00
Christopher Faulet
d491329de9 MINOR: check: Remove wake_srv_chk() function
wake_srv_chk() function is now only used by srv_chk_io_cb(), the
health-checl I/O callback function. So let's remove it. The code of the
function was moved in srv_chk_io_cb().
2026-03-10 15:10:34 +01:00
Christopher Faulet
9c7c669d7a MEDIUM: stconn: Remove .wake() callback function from app_ops
.wake() callback function is no longer used by endpoints. So it can be
removed from the app_ops structure.
2026-03-10 15:10:34 +01:00
Christopher Faulet
a33b42035b MINOR: connection: Call sc_conn_process() instead of .wake() callback function
At we fail to create a mux, in conn_create_mux(), instead of calling the
app_ops .wake() callback function, we can directly call sc_conn_process().
At this stage, we know we are using an connection, so it is safe to do so.
2026-03-10 15:10:34 +01:00
Christopher Faulet
7be95eb892 MINOR: applet: Call sc_applet_process() instead of .wake() callback function
At the end of task_run_applet() and task_process_applet(), instead of
calling the app_ops .wake() callback function, we can directly call
sc_applet_process(). At this stage, we know we are using an applet, so it is
safe to do so.
2026-03-10 15:10:34 +01:00
Christopher Faulet
64d997ebfc MAJOR: muxes: No longer use app_ops .wake() callback function from muxes
Thanks to previous commits, it is now possible to wake the data layer up,
via a tasklet_wakeup, instead of using the app_ops .wake() callback
function.

When a data layer must be notified of a mux event (an error for instance),
we now always perform a tasklet_wakeup(). TASK_WOKEN_MSG state is used by
default. TASK_WOKEN_IO is eventually added if the data layer was subscribed
to receives or sends.

Changes are not trivial at all. We replaced a synchronous call to the
sc_conn_process() function by a tasklet_wakeup().
2026-03-10 15:10:34 +01:00
Christopher Faulet
26a0817c1a MINOR: muxes: Wakup the data layer from a mux stream with TASK_WOKEN_IO state
Now, when a mux stream is waking its data layer up for receives or sends, it
uses the TASK_WOKEN_IO state. The state is not used by the stconn I/O
callback function for now.
2026-03-10 15:10:34 +01:00
Christopher Faulet
376487cca9 MINOR: mux-spop: Rely on spop_strm_notify_send() when resuming streams for sending
In spop_resume_each_sending_spop_strm(), there was exactly the same code
than spop_strm_notify_send(). So let's use spop_strm_notify_send() instead
of duplicating code.
2026-03-10 15:10:34 +01:00
Christopher Faulet
aea0d38fdd MINOR: mux-h2: Rely on h2s_notify_send() when resuming h2s for sending
In h2_resume_each_sending_h2s(), there was exactly the same code than
h2s_notify_send(). So let's use h2s_notify_send() instead of duplicating
code.
2026-03-10 15:10:34 +01:00
Christopher Faulet
7abb7c4c79 MINOR: stconn: Call sc_conn_process from the I/O callback if TASK_WOKEN_MSG state was set
It is the first commit of a series to refactor the SC app_ops. The first
step is to remove the .wake() callback function from the app_ops to replace
all uses by a wakeup of the SC tasklet.

Here, when the SC is woken up, the state is now tested and if TASK_WOKEN_MSG
is set, sc_conn_process() is called.
2026-03-10 15:10:34 +01:00
Remi Tricot-Le Breton
924a92200f DOC: jwt: Add ECDH support in jwt_decrypt converters
The jwt_decrypt_jwk and jwt_decrypt_cert converters now manage
algorithms in the ECDH family.
2026-03-10 14:58:48 +01:00
Remi Tricot-Le Breton
31bbc1f0f1 MINOR: jwt: Manage ec certificates in jwt_decrypt_cert
This patch adds the support of algorithms in the ECDH family in the
jwt_decrypt_cert converter.
2026-03-10 14:58:47 +01:00
Remi Tricot-Le Breton
3925bb8efc MINOR: jwt: Add ecdh-es+axxxkw support in jwt_decrypt_jwk converter
This builds on the ECDH-ES processing and simply requires an extra AES
Key Wrap operation between the built key and the token's CEK.
2026-03-10 14:58:47 +01:00
Remi Tricot-Le Breton
32d9af559f MINOR: jwt: Manage ECDH-ES algorithm in jwt_decrypt_jwk function
When ECDH-ES algorithm is used in a JWE token, no cek is provided and
one must be built in order to decrypt the contents of the token. The
decrypting key is built by deriving a temporary key out of a public key
provided in the token and the private key provided by the user and
performing a concatKDF operation.
2026-03-10 14:58:47 +01:00
Remi Tricot-Le Breton
026652a7eb MINOR: jwt: Parse ec-specific fields in jose header
When the encoding is of the ECDH family, the optional "apu" and "apv"
fields of the JOSE header must be parsed, as well as the mandatory "epk"
field that contains an EC public key used to derive a key that allows
either to decrypt the contents of the token (in case of ECDH-ES) or to
decrypt the content encoding key (cek) when using ECDH-ES+AES Key Wrap.
2026-03-10 14:58:46 +01:00
Remi Tricot-Le Breton
3d9764f4c3 MINOR: jwt: Convert EC JWK to EVP_PKEY
Convert a JWK with the "EC" key type ("kty") into an EVP_PKEY. The JWK
can either represent a public key if it only contains the "x" and "y"
fields, or a private key if it also contains the "d" field.
2026-03-10 14:58:46 +01:00
Remi Tricot-Le Breton
e34b633be3 MINOR: jwt: Improve 'jwt_tokenize' function
The 'jwt_tokenize' function that can be used to split a JWT token into
its subparts can either fully process the token (from beginning to end)
when we need to check its signature, or only partially when using the
jwt_header_query or jwt_member_query converters. In this case we relied
on the fact that the return value of the 'jwt_tokenize' function was not
checked because a '-1' was returned (which was not actually an error).

In order to make this logic more explicit, the 'jwt_tokenize' function
now has a way to warn the caller that the token was invalid (less
subparts than the specified 'item_num') or that the token was not
processed in full (enough subparts found without parsing the token all
the way).
The function will now only return 0 if we found strictly the same number
of subparts as 'item_num'.
2026-03-10 14:20:42 +01:00
William Lallemand
1babe8cb1b Revert "BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check"
This reverts commit 5e14904fef4856372433fc5b7e8d3de9450ec1b5.

The patch is broken, a better implementation is needed.
2026-03-09 16:53:06 +01:00
William Lallemand
1cbd1163f0 BUG/MINOR: mworker: don't set the PROC_O_LEAVING flag on master process
The master process in the proc_list mustn't set the PROC_O_LEAVING flag
since the reload doesn't mean the master will leave.

Could be backported as far as 3.1.
2026-03-09 16:51:56 +01:00
William Lallemand
bd3983b595 MINOR: mworker: add a BUG_ON() on mproxy_li in _send_status
mproxy_li is supposed to be used in _send_status to stop the sockpair FD
between the master and the new worker, being a listener.

This can only work if the listener has been stored in the fdtab owner,
and there's no reason it shouldn't be here.
2026-03-09 16:51:56 +01:00
Willy Tarreau
520faedda0 SCRIPTS: git-show-backports: add a restart-from-last option
It's always a bit tricky to avoid already backported patches when they
just got a different ID (e.g. a critical fix in a topic branch). Most
often with stable topic branches we just want to pick all stable commits
since the last backported one. New option -L instead of -m does exactly
this: it enumerates only commits that were added to the reference branch
after its most recent backport.
2026-03-09 15:36:05 +01:00
Willy Tarreau
459835d535 SCRIPTS: git-show-backports: hide the common ancestor warning in quiet mode
It's annoying to always see that warning in quiet mode when backporting
upstream to topic branches, let's hide it.
2026-03-09 15:36:02 +01:00
William Lallemand
9b3345237a BUG/MINOR: admin: haproxy-reload rename -vv long option
The -vv option used --verbose as its long form, which was identical to
the long form of -v. Since the case statement matches top-to-bottom,
--verbose would always trigger -v (VERBOSE=2), making -vv unreachable
via its long option. The long form is renamed to --verbose=all to avoid
the conflict, and the usage string is updated accordingly.

Must be backported to 3.3.
2026-03-08 01:37:56 +01:00
William Lallemand
2a0cf52cfc MEDIUM: admin: haproxy-reload conversion to POSIX sh
The script relied on a bash-specific process substitution (< <(...)) to
feed socat's output into the read loop. This is replaced with a standard
POSIX pipe into a command group.

The response parsing is also simplified: instead of iterating over each
line with a while loop and echoing them individually, the status line is
read first, the "--" separator consumed, and the remaining output is
streamed to stderr or discarded as a whole depending on the verbosity
level.

Could be backported to 3.3 as it makes it more portable, but introduce a
slight change in the error format.
2026-03-08 01:37:52 +01:00
William Lallemand
551e5f5fd4 BUG/MINOR: admin: haproxy-reload use explicit socat address type
socat was used with the ${MASTER_SOCKET} variable directly, letting it
auto-detect the network protocol. However, when given a plain filename
that does not point to a UNIX socket, socat would create a file at that
path instead of reporting an error.

To fix this, the address type is now determined explicitly: if
MASTER_SOCKET points to an existing UNIX socket file (checked with -S),
UNIX-CONNECT: is used; if it matches a <host>:<port> pattern, TCP: is
used; otherwise an error is reported. The socat_addr variable is also
properly scoped as local to the reload() function.

Could be backported in 3.3.
2026-03-08 01:33:29 +01:00
Aurelien DARRAGON
2a2989bb23 CLEANUP: flt_http_comp: comp_state doesn't bother about the direction anymore
no need to have duplicated comp_ctx and comp_algo for request vs response
in comp_state struct, because thanks to previous commit compression filter
is either oriented on the request or the response, and 2 distinct filters
are instanciated when we need to handle both requests and responses
compression.

Thus we can save us from duplicated struct members and related operations.
2026-03-06 13:55:41 +01:00