25553 Commits

Author SHA1 Message Date
Remi Tricot-Le Breton
6f4ca37880 BUG/MINOR: ssl: Potential NULL deref in trace macro
'ctx' might be NULL when we exit 'ssl_sock_handshake', it can't be
dereferenced without check in the trace macro.

This was found by Coverity andraised in GitHub #3113.
This patch should be backported up to 3.2
2025-10-13 15:44:45 +02:00
Remi Tricot-Le Breton
d82019d05c REGTEST: jwt: Test new CLI commands
Test the "add/del ssl jwt" commands and check the new return value in
case of unavailable certificate used in a jwt_verify_cert converter.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
d4bb9983fa MINOR: jwt: Add new "add/del/show ssl jwt" CLI commands
The new "add/del ssl jwt <file>" commands allow to change the "jwt" flag
of an already loaded certificate. It allows to delete certificates used
for JWT validation, which was not yet possible.
The "show ssl jwt" command iterates over all the ckch_stores and dumps
the ones that have the option set.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
daa36adc6e MINOR: ssl: Dump options in "show ssl cert"
Dump the values of the 'ocsp-update' and 'jwt' flags in the output of
'show ssl cert' CLI command.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
0f35b46124 DOC: jwt: Add doc about "jwt_verify_cert" converter
Add information about the new "jwt_verify_cert" converter and update the
existing "jwt_converter" doc to remove mentions of certificates from it.
Add information about the new "jwt" certificate option.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
bf5b912a62 MINOR: jwt: Add specific error code for known but unavailable certificate
A certificate that does not have the 'jwt' flag enabled cannot be used
for JWT validation. We now raise a specific return value so that such a
case can be identified.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
18ff130e9d MINOR: jwt: Add new "jwt" certificate option
This option can be used to enable the use of a given certificate for JWT
verification. It defaults to 'off' so certificates that are declared in
a crt-store and will be used for JWT verification must have a
"jwt on" option in the configuration.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
53957c50c3 MINOR: jwt: Do not look into ckch_store for jwt_verify converter
We must not try to load full-on certificates for 'jwt_verify' converter
anymore. 'jwt_verify_cert' is the only one that accepts a certificate.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
f5632fd481 MINOR: jwt: Add new jwt_verify_cert converter
This converter will be in charge of performing the same operation as the
'jwt_verify' one except that it takes a full-on pem certificate path
instead of a public key path as parameter.
The certificate path can be either provided directly as a string or via
a variable. This allows to use certificates that are not known during
init to perform token validation.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
c3c0597a34 MEDIUM: jwt: Remove certificate support in jwt_verify converter
The jwt_verify converter will not take full-on certificates anymore
in favor of a new soon to come jwt_verify_cert. We might end up with a
new jwt_verify_hmac in the future as well which would allow to deprecate
the jwt_verify converter and remove the need for a specific internal
tree for public keys.
The logic to always look into the internal jwt tree by default and
resolve to locking the ckch tree as little as possible will also be
removed. This allows to get rid of the duplicated reference to
EVP_PKEYs, the one in the jwt tree entry and the one in the ckch_store.
2025-10-13 10:38:52 +02:00
Remi Tricot-Le Breton
b706f2d092 BUG/MINOR: ssl: Free key_base from global_ssl structure during deinit
The key_base field of the global_ssl structure is an strdup'ed field
(when set) which was never free'd during deinit.

This patch can be backported up to branch 3.0.
2025-10-10 17:22:48 +02:00
Remi Tricot-Le Breton
9bc6a0349d BUG/MINOR: ssl: Free global_ssl structure contents during deinit
Some fields of the global_ssl structure are strings that are strdup'ed
but never freed. There is only one static global_ssl structure so not
much memory is used but we might as well free it during deinit.

This patch can be backported to all stable branches.
2025-10-10 17:22:48 +02:00
Christopher Faulet
54b7539d64 BUG/MEDIUM: apppet: Improve spinning loop detection with the new API
Conditions to detect the spinning loop for applets based on the new API are
not accurrate. We cannot continue to check the channel's buffers state to
know if an applet has made some progress. At least, we must also check the
applet's buffers.

After digging to find the right way to do, it was clear that the best is to
use something similar to what is performed for the streams, namely, checking
read and write events. And in fact, it is quite easy to do with the new
API. So let's do so.

This patch must be backported as far as 3.0.
2025-10-10 14:41:15 +02:00
Willy Tarreau
dfe7fa9349 BUILD: makefile: disable tail calls optimizations with memory profiling
The purpose of memory profiling precisely is to figure what function
allocates and what function frees for specific objects. It turns out
that a non-negligible number of release callbacks basically do nothing
but a free() or pool_free() call and return, which the compiler happily
turns into a jump, making the caller of that callback appear as the
real one. That's how we can see libcrypto release to pools such as
ssl-capture for example, which also makes the per-DSO calls appear
wrong:

      10000           0       10720000              0|         0x448c8d ssl_async_fd_free+0x3b9d p_alloc(1072) [pool=ssl-capture]
      50000           0        6800000              0|         0x4456b9 ssl_async_fd_free+0x5c9 p_alloc(136) [pool=ssl-keylogf]
      10072           0         644608              0|         0x447f14 ssl_async_fd_free+0x2e24 p_alloc(64) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445987 ssl_async_fd_free+0x897 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459b8 ssl_async_fd_free+0x8c8 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459e9 ssl_async_fd_free+0x8f9 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a1a ssl_async_fd_free+0x92a p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a4b ssl_async_fd_free+0x95b p_free(-136) [pool=ssl-keylogf]
          0       20072              0       11364608|   0x7f5f1397db62 libcrypto:CRYPTO_free_ex_data+0xf2/0x261 p_free(-566) [pool=ssl-keylogf] [locked=72 (0.3 %)]

Worse, as can be seen on the last line above, there can be a single pool
per call place (since we don't release to arbitrary pools), and the stats
are misleading by reporting the first used pool only when a same function
can call multiple release callbacks. This is why the free call totals
10k ssl-capture and 10072 ssl-keylogfile.

Let's just disable tail call optimization when using memory profiling.
The gains are only very marginal and complicate so much the debugging
that it's not worth it. Now the output is correct, and no longer claims
that libcrypto is the caller:

      10000           0       10720000              0|         0x448c9f ssl_async_fd_free+0x3b9f p_alloc(1072) [pool=ssl-capture]
          0       10000              0       10720000|         0x445af0 ssl_async_fd_free+0x9f0 p_free(-1072) [pool=ssl-capture]
      50000           0        6800000              0|         0x4456c9 ssl_async_fd_free+0x5c9 p_alloc(136) [pool=ssl-keylogf]
      10177           0        1221240              0|         0x45543d ssl_async_fd_handler+0xb51d p_alloc(120) [pool=ssl_sock_ct] [locked=165 (1.6 %)]
      10061           0         643904              0|         0x447f1c ssl_async_fd_free+0x2e1c p_alloc(64) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445987 ssl_async_fd_free+0x887 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459b8 ssl_async_fd_free+0x8b8 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x4459e9 ssl_async_fd_free+0x8e9 p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a1a ssl_async_fd_free+0x91a p_free(-136) [pool=ssl-keylogf]
          0       10000              0        1360000|         0x445a4b ssl_async_fd_free+0x94b p_free(-136) [pool=ssl-keylogf]
          0       10188              0        1222560|         0x44f518 ssl_async_fd_handler+0x55f8 p_free(-120) [pool=ssl_sock_ct] [locked=176 (1.7 %)]
          0       10072              0         644608|         0x445aa6 ssl_async_fd_free+0x9a6 p_free(-64) [pool=ssl-keylogf] [locked=72 (0.7 %)]

An attempt was made to only instrument pool_free() to place a compiler
barrier, but that resulted in much larger code and wouldn't cover
functions ending with a simple "free()" call. "ha_free()" however is
already immune against tail call optimization since it has to write
the NULL when returning from free().

This should be backported to recent stable releases that are still
regularly being debugged.
2025-10-10 13:45:19 +02:00
William Lallemand
47a93dc750 BUG/MINOR: ssl: leak crtlist_name in ssl-f-use
This patch fixes a leak of the temporary variable "crtlist_name" which
is used in the ssl-f-use parser.

Must be backported in 3.2.
2025-10-10 11:22:37 +02:00
William Lallemand
d9365a88a5 BUG/MINOR: ssl: leak in ssl-f-use
Fix the leak of the filename in the struct cfg_crt_node which is a
temporary structure used for ssl-f-use initialization.

Must be backported to 3.2.
2025-10-10 11:22:37 +02:00
Christopher Faulet
cbe5221182 DEBUG: mux-h1: Dump <kip> and <kop> values with sedesc info
It could be handy to debug issues, especially because these values was
recently introduced.
2025-10-10 11:16:21 +02:00
Christopher Faulet
6a0fe6e460 MEDIUM: applet: Forward <kip> to applets
For now, no applets are using the <kop> value when consuming data. At least,
as far as I know. But it remains a good idea to keep the applet API
compatible. So now, the <kip> of the opposite side is properly forwarded to
applets.
2025-10-10 11:11:44 +02:00
Christopher Faulet
4145a61101 BUG/MEDIUM: stconn: Properly forward kip to the opposite SE descriptor
By refactoring the HTX to remove the extra field, a bug was introduced in
the stream-connector part. The <kip> (known input payload) value of a sedesc
was moved to <kop> (knwon output payload) using the same sedesc. Of course,
this is totally wrong. <kip> value of a sedesc must be forwarded to the
opposite side.

In addition, the operation is performed in sc_conn_send(). In this function,
we manipulate the stream-connectors. So se_fwd_kip() function was changed to
use the stream-connectors directely.

Now, the function sc_ep_fwd_kip() is now called with the both
stream-connectors to properly forward <kip> from on side to the opposite
side.

The bug is 3.3-specific. No backport needed.
2025-10-10 11:01:21 +02:00
Willy Tarreau
54f0ab08b8 BUG/MINOR: ssl: always clear the remains of the first hello for the second one
William rightfully pointed that despite the ssl capture being a
structure, some of its entries are only set for certain contents,
so we need to always zero it before using it so as to clear any
remains of a previous use, otherwise we could possibly report some
entries that were only present in the first hello and not the second
one. No need to clear the data though, since any remains will not be
referenced by the fields.

This must be backported wherever commit 336170007c ("BUG/MEDIUM: ssl:
take care of second client hello") is backported.
2025-10-09 18:50:30 +02:00
Willy Tarreau
336170007c BUG/MEDIUM: ssl: take care of second client hello
For a long time we've been observing some sporadic leaks of ssl-capture
pool entries on haproxy.org without figuring exactly the root cause. All
that was seen was that less calls to the free callback were made than
calls to the hello parsing callback, and these were never reproduced
locally.

It recently turned out to be triggered by the presence of "curves" or
"ecdhe" on the "bind" line. Captures have shown the presence of a second
client hello, called "Change Cipher Client Hello" in wireshark traces,
that calls the client hello callback again. That one wasn't prepared for
being called twice per connection, so it allocates an ssl-capture entry
and assigns it to the ex_data entry, possibly overwriting the previous
one.

In this case, the fix is super simple, just reuse the current ex_data
if it exists, otherwise allocate a new one. This completely solves the
problem.

Other callbacks have been audited for the same issue and are not
affected: ssl_ini_keylog() already performs this check and ignores
subsequent calls, and other ones do not allocate data.

This must be backported to all supported versions.
2025-10-09 17:06:49 +02:00
William Lallemand
229eab8fc9 CI: cirrus-ci: bump FreeBSD image to 14-3
FreeBSD CI seems to be broken for a while, try to upgrade the image to
the latest 14.3 version.
2025-10-09 14:06:48 +02:00
William Lallemand
f35caafa6e BUG/MINOR: acme: memory leak from the config parser
This patch fixes some memory leaks in the configuration parser:

- deinit_acme() was never called
- add ha_free() before every strdup() for section overwrite
- lacked some free() in deinit_acme()
2025-10-09 12:04:22 +02:00
William Lallemand
9344ecaade MEDIUM: acme: don't insert acme account key in ckchs_tree
Don't insert the acme account key in the ckchs_tree anymore. ckch_store
are not made to only include a private key. CLI operations are not
possible with them either. That doesn't make much sense to keep it that
way until we rework the ckch_store.
2025-10-09 11:01:58 +02:00
Christopher Faulet
914538cd39 MEDIUM: htx: Remove the HTX extra field
Thanks for previous changes, it is now possible to remove the <extra> field
from the HTX structure. HTX_FL_ALTERED_PAYLOAD flag is also removed because
it is now unsued.
2025-10-08 11:10:42 +02:00
Christopher Faulet
2e2953a3f0 MEDIUM: mux-h1: Stop to use HTX extra value when formatting message
We now rely on the <kop> value to format the message payload before
sending it. It is no longer necessary to use the HTX extra field.
2025-10-08 11:10:42 +02:00
Christopher Faulet
4f40b2de86 MINOR: compression: Use the <kip> value to check body size
When an minimum compression size is defined, we can now use the <kip>
value to skip the compression instead of the HTX extra field.
2025-10-08 11:10:42 +02:00
Christopher Faulet
c0f5b19bc6 MINOR: cache: Use the <kip> value to check too big objects
When an object should be cache, to check if it is too big or not, the
<kip> value is now used instead of the HTX extra field.
2025-10-08 11:10:42 +02:00
Christopher Faulet
f1c659f3ae MINOR: hlua/http-fetch: Use <kip> instead of HTX extra field to get body size
The known input payload length now contains the information. There is no
reason to still rely on the HTX extra field.
2025-10-08 11:10:25 +02:00
Christopher Faulet
be1ce400c4 MINOR: filters: Reset knwon input payload length if a data filter is used
It a data filter is registered on a channel, the corresponding <kip>
field must be reset because the payload may be altered.
2025-10-08 11:01:37 +02:00
Christopher Faulet
30c50e4f19 MINOR: stconn: Move data from kip to kop when data are sent to the consumer
When data are sent to the consumer, the known output payload length is
updated using the known input payload length value and this last one is then
reset. se_fwd_kip() function is used for this purpose.
2025-10-08 11:01:37 +02:00
Christopher Faulet
f6a4d41dd0 MINOR: h3: Set known input payload length of the sedesc
Set <kip> value when data are transfer to the upper layer, in h3_rcv_buf().
The difference between the known length of the payload before and after a
parsing loop is added to <kip> value. When a content-length is specified in
the message, the h3s <body_len> field is used. Otherwise, it is the h3s
<data_len> field.
2025-10-08 11:01:36 +02:00
Christopher Faulet
bc8c6c42f4 MINOR: mux-h2: Set known input payload length of the sedesc
Set <kip> value when data are transfer to the upper layer, in h2_rcv_buf().
The new <body_len> filed of the H2S is used to increment <kip> value and
then it is reset. The patch relies on the previous one ("MINOR: mux-h2: Save
the known length of the payload").
2025-10-08 11:01:36 +02:00
Christopher Faulet
3a6a576e73 MINOR: mux-h2: Use <body_len> H2S field for payload without content-length
Before, the <body_len> H2S field was only use for verity the annonced
content-lenght value was respected. Now, this field is used for all
messages. Messages with a content-length are still handled the same way.
<body_len> is set to the content-length value and decremented by the size of
each DATA frame. For other messages, the value is initialized to ULLONG_MAX
and still decremented by the size of each DATA frame. This change is
mandatory to properly define the known input payload length value of the
sedesc.
2025-10-08 11:01:36 +02:00
Christopher Faulet
4fdc23e648 MINOR: mux-fcgi: Set known input payload length during demux
Set <kip> value during the response parsing. The difference between the body
length before and after a parsing loop is added. The patch relies on the
previous one ("MINOR: h1-htx: Increment body len when parsing a payload with
no xfer length").
2025-10-08 11:01:36 +02:00
Christopher Faulet
2bf2f68cd8 MINOR: mux-h1: Set known input payload length during demux
Set <kip> value during the message parsing. The difference between the body
length before and after a parsing loop is added. The patch relies on the
previous one ("MINOR: h1-htx: Increment body len when parsing a payload with
no xfer length").
2025-10-08 11:01:36 +02:00
Christopher Faulet
c9bc18c0bf MINOR: h1-htx: Increment body len when parsing a payload with no xfer length
In the H1 parseur, the body length was only incremented when the transfer
length was known. So when the content-length was specified or when the
transfer-encoding value was set to "chunk".

Now for messages with unknown transfer length, it is also incremented. It is
mandatory to be able to remove the extra field from the HTX message.
2025-10-08 11:01:36 +02:00
Christopher Faulet
c0b6db2830 MINOR: stconn: Add two fields in sedesc to replace the HTX extra value
For now, the HTX extra value is used to specify the known part, in bytes, of
the HTTP payload we will receive. It may concerne the full payload if a
content-length is specified or the current chunk for a chunk-encoded
message. The main purpose of this value is to be used on the opposite side
to be able to announce chunks bigger than a buffer. It can also be used to
check the validity of the payload on the sending path, to properly detect
too big or too short payload.

However, setting this information in the HTX message itself is not really
appropriate because the information is lost when the HTX message is consumed
and the underlying buffer released. So the producer must take care to always
add it in all HTX messages. it is especially an issue when the payload is
altered by a filter.

So to fix this design issue, the information will be moved in the sedesc. It
is a persistent area to save the information. In addition, to avoid the
ambiguity between what the producer say and what the consumer see, the
information will be splitted in two fields. In this patch, the fields are
added:

 * kip : The known input payload length
 * kop : The known output payload lenght

The producer will be responsible to set <kip> value. The stream will be
responsible to decrement <kip> and increment <kop> accordingly. And the
consumer will be responsible to remove consumed bytes from <kop>.
2025-10-08 11:01:36 +02:00
Christopher Faulet
586511c278 MINOR: h3/qmux: Set QC_SF_UNKNOWN_PL_LENGTH flag on QCS when headers are sent
QC_SF_UNKNOWN_PL_LENGTH flag is set on the qcs to know a payload of message
has an unknown length and not send a RESET_STREAM on shutdown. This flag was
based on the HTX extra field value. However, it is not necessary. When
headers are processed, before sending them, it is possible to check the HTX
start-line to know if the length of the payload is known or not.

So let's do so and don't use anymore the HTX extra field for this purpose.
2025-10-08 11:01:36 +02:00
Willy Tarreau
00b27a993f MAJOR: proxy: enable abortonclose by default on TLS listeners
In the continuity of https://github.com/orgs/haproxy/discussions/3146,
we must also enable abortonclose by default for TLS listeners so as not
to needlessly compute TLS handshakes on dead connections. The change is
very small (just set the default value to 1 in the TLS code when neither
the option nor its opposite were set).

It may possibly cause some TLS handshakes to start failing with 3.3 in
certain legacy environments (e.g. TLS health-checks performed using only
a client hello and closing afterwards), and in this case it is sufficient
to disable the option using "no option abortonclose" in either the
affected frontend or the "defaults" section it derives from.
2025-10-08 10:36:59 +02:00
Willy Tarreau
75103e7701 MINOR: proxy: introduce proxy_abrt_close_def() to pass the desired default
With this function we can now pass the desired default value for the
abortonclose option when neither the option nor its opposite were set.
Let's also take this opportunity for using it directly from the HTTP
analyser since there's no point in re-checking the proxy's mode there.
2025-10-08 10:29:41 +02:00
Willy Tarreau
644b3dc7d8 MAJOR: proxy: enable abortonclose by default on HTTP proxies
As discussed on https://github.com/orgs/haproxy/discussions/3146 and on
the mailing list, there's a marked preference for having abortonclose
enabled by default when relevant. The point being that with todays'
internet, the large majority of requests sent with a closed input
channel are aborted requests, and that it's pointless to waste resources
processing them.

This patch now considers both "option abortonclose" and its opposite
"no option abortonclose" to figure whether abortonclose is enabled or
disabled in a backend. When neither are set (thus not even inherited
from a defaults section), then it considers the proxy's mode, and HTTP
mode implies abortonclose by default.

This may make some legacy services fail starting with 3.3. In this case
it will be sufficient to add "no option abortonclose" in either the
affected backend or the defaults section it derives from. But for
internet-facing proxies it's better to stay with the option enabled.
2025-10-08 10:29:41 +02:00
Willy Tarreau
fe47e8dfc5 MINOR: proxy: only check abortonclose through a dedicated function
In order to prepare for changing the way abortonclose works, let's
replace the direct flag check with a similarly named function
(proxy_abrt_close) which returns the on/off status of the directive
for the proxy. For now it simply reflects the flag's state.
2025-10-08 10:29:41 +02:00
Willy Tarreau
687504344a REGTESTS: http-messaging: fix the websocket and upgrade tests not to close early
By default when building an H2 request, vtest sets the END_STREAM flag
on the HEADERS frame. This is problematic with the websocket and proto
upgrade tests since we're using CONNECT, because it immediately closes
afterwards, which does not correspond to what we're testing. Doing this
in abortonclose mode rightfully produces an error. Let's fix the test
so as not to set the flag on the HEADERS frame. However, doing so means
we'll receive a window update that we must also accept. Now the test
works both with and without abortonclose.
2025-10-08 10:29:41 +02:00
Willy Tarreau
8573c5e2a1 REGTESTS: fix h2_desync_attacks to wait for the response
Tests with abortonclose showed a bug with this test where the client
would close the stream immediately after sending the request, without
waiting for the response, causing some random failures on the server
side.
2025-10-08 10:29:41 +02:00
Willy Tarreau
c42e62d890 MINOR: proxy: explicitly permit abortonclose on frontends and clarify the doc
The "abortonclose" option was recently deprecated in frontends because its
action was essentially limited to the backend part (queuing etc). But in
3.3 we started to support it for TLS on frontends, though it would only
work when placed in a defaults section. Let's officially support it in
frontends, and take this opportunity to clarify the documentation on this
topic, which was incomplete regarding frontend and TLS support. Now the
doc tries to better cover the different use cases.
2025-10-08 10:29:41 +02:00
Willy Tarreau
f657ffc6e7 DEV: patchbot: use git reset+checkout instead of pull
The patchbot stopped on a previous ultra-rare forced push due to wanting
the user's name and e-mail before proceeding. We don't want merges nor
rebases anyway, only to reset the tree to the next one, so let's do that.
2025-10-08 04:38:35 +02:00
William Lallemand
45fba1db27 BUG/MINOR: acme: avoid overflow when diff > notAfter
Avoid an overflow or a negative value if notAfter < diff.

This is unlikely to provoke any problem.

Fixes issue #3138.

Must be backported to 3.2.
2025-10-07 10:54:58 +02:00
William Lallemand
69bd253b23 CLEANUP: mjson: remove unused defines from mjson.h
This patch removes unused defines from mjson.h.
It also removes unused c++ declarations and includes.

string.h is moved to mjson.c
2025-10-06 09:30:07 +02:00
Christopher Faulet
8219fa1842 BUG/MINOR: http-ana: Reset analyse_exp date after 'wait-for-body' action
'wait-for-body' action set analyse_exp date for the channel to the
configured time. However, when the action is finished, it does not reset
it. It is an issue for some following actions, like 'pause', that also rely
on this date.

To fix the issue, we must take care to reset the analyse_exp date to
TICK_ETERNITY when the 'wait-for-body' action is finished.

This patch should fix the issue #3147. It must be backported to all stable
versions.
2025-10-03 17:09:16 +02:00