Compare commits

..

No commits in common. "master" and "v3.4-dev3" have entirely different histories.

63 changed files with 1696 additions and 3319 deletions

View file

@ -1,43 +1,6 @@
ChangeLog :
===========
2026/02/04 : 3.4-dev4
- BUG/MEDIUM: hlua: fix invalid lua_pcall() usage in hlua_traceback()
- BUG/MINOR: hlua: consume error object if ignored after a failing lua_pcall()
- BUG/MINOR: promex: Detach promex from the server on error dump its metrics dump
- BUG/MEDIUM: mux-h1: Skip UNUSED htx block when formating the start line
- BUG/MINOR: proto_tcp: Properly report support for HAVE_TCP_MD5SIG feature
- BUG/MINOR: config: check capture pool creations for failures
- BUG/MINOR: stick-tables: abort startup on stk_ctr pool creation failure
- MEDIUM: pools: better check for size rounding overflow on registration
- DOC: reg-tests: update VTest upstream link in the starting guide
- BUG/MINOR: ssl: Properly manage alloc failures in SSL passphrase callback
- BUG/MINOR: ssl: Encrypted keys could not be loaded when given alongside certificate
- MINOR: ssl: display libssl errors on private key loading
- BUG/MAJOR: applet: Don't call I/O handler if the applet was shut
- MINOR: ssl: allow to disable certificate compression
- BUG/MINOR: ssl: fix error message of tune.ssl.certificate-compression
- DOC: config: mention some possible TLS versions restrictions for kTLS
- OPTIM: server: move queueslength in server struct
- OPTIM: proxy: separate queues fields from served
- OPTIM: server: get rid of the last use of _ha_barrier_full()
- DOC: config: mention that idle connection sharing is per thread-group
- MEDIUM: h1: strictly verify quoting in chunk extensions
- BUG/MINOR: config/ssl: fix spelling of "expose-experimental-directives"
- BUG/MEDIUM: ssl: fix msg callbacks on QUIC connections
- MEDIUM: ssl: remove connection from msg callback args
- MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0
- REGTESTS: ssl: make reg-tests compatible with OpenSSL 4.0
- DOC: internals: cleanup few typos in master-worker documentation
- BUG/MEDIUM: applet: Fix test on shut flags for legacy applets
- MINOR: quic: Fix build with USE_QUIC_OPENSSL_COMPAT
- MEDIUM: tcpcheck: add post-80 option for mysql-check to support MySQL 8.x
- BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED
- BUG/MINOR: cpu-topo: count cores not cpus to distinguish core types
- DOC: config: mention the limitation on server id range for consistent hash
- MEDIUM: backend: make "balance random" consider req rate when loads are equal
- BUG/MINOR: config: Fix setting of alt_proto
2026/01/22 : 3.4-dev3
- BUILD: ssl: strchr definition changed in C23
- BUILD: tools: memchr definition changed in C23

View file

@ -1,2 +1,2 @@
$Format:%ci$
2026/02/04
2026/01/22

View file

@ -1 +1 @@
3.4-dev4
3.4-dev3

View file

@ -1255,7 +1255,7 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
if (!stats_fill_sv_line(px, sv, 0, stats, ST_I_PX_MAX, &(ctx->field_num)))
goto error;
return -1;
if ((ctx->flags & PROMEX_FL_NO_MAINT_SRV) && (sv->cur_admin & SRV_ADMF_MAINT))
goto next_sv;
@ -1473,7 +1473,7 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
counters = EXTRA_COUNTERS_GET(sv->extra_counters, mod);
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
goto error;
return -1;
val = stats[ctx->field_num + ctx->mod_field_num];
metric.type = ((val.type == FN_GAUGE) ? PROMEX_MT_GAUGE : PROMEX_MT_COUNTER);
@ -1515,10 +1515,6 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
full:
ret = 0;
goto end;
error:
watcher_detach(&ctx->srv_watch);
return -1;
}
/* Dump metrics of module <mod>. It returns 1 on success, 0 if <out> is full and

View file

@ -3,7 +3,7 @@
Configuration Manual
----------------------
version 3.4
2026/02/04
2026/01/22
This document covers the configuration language as implemented in the version
@ -1983,7 +1983,6 @@ The following keywords are supported in the "global" section :
- tune.ssl.cachesize
- tune.ssl.capture-buffer-size
- tune.ssl.capture-cipherlist-size (deprecated)
- tune.ssl.certificate-compression
- tune.ssl.default-dh-param
- tune.ssl.force-private-cache
- tune.ssl.hard-maxrecord
@ -4005,7 +4004,7 @@ profiling.memory { on | off }
use in production. The same may be achieved at run time on the CLI using the
"set profiling memory" command, please consult the management manual.
profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*
profiling.tasks { auto | on | off }
Enables ('on') or disables ('off') per-task CPU profiling. When set to 'auto'
the profiling automatically turns on a thread when it starts to suffer from
an average latency of 1000 microseconds or higher as reported in the
@ -4016,18 +4015,6 @@ profiling.tasks { auto | on | off | lock | no-lock | memory | no-memory }*
systems, containers, or virtual machines, or when the system swaps (which
must absolutely never happen on a load balancer).
When task profiling is enabled, HAProxy can also collect the time each task
spends with a lock held or waiting for a lock, as well as the time spent
waiting for a memory allocation to succeed in case of a pool cache miss. This
can sometimes help understand certain causes of latency. For this, the extra
keywords "lock" (to enable lock time collection), "no-lock" (to disable it),
"memory" (to enable memory allocation time collection) or "no-memory" (to
disable it) may additionally be passed. By default they are not enabled since
they can have a non-negligible CPU impact on highly loaded systems (3-10%).
Note that the overhead is only taken when profiling is effectively running,
so that when running in "auto" mode, it will only appear when HAProxy decides
to turn it on.
CPU profiling per task can be very convenient to report where the time is
spent and which requests have what effect on which other request. Enabling
it will typically affect the overall's performance by less than 1%, thus it
@ -4539,11 +4526,7 @@ tune.idle-pool.shared { on | off }
disabling this option without setting a conservative value on "pool-low-conn"
for all servers relying on connection reuse to achieve a high performance
level, otherwise connections might be closed very often as the thread count
increases. Note that in any case, connections are only shared between threads
of the same thread group. This means that systems with many NUMA nodes may
show slightly more persistent connections while machines with unified caches
and many CPU cores per node may experience higher CPU usage. In the latter
case, the "max-thread-per-group" tunable may be used to improve the behavior.
increases.
tune.idletimer <timeout>
Sets the duration after which HAProxy will consider that an empty buffer is
@ -5327,22 +5310,6 @@ tune.ssl.capture-cipherlist-size <number> (deprecated)
formats. If the value is 0 (default value) the capture is disabled,
otherwise a buffer is allocated for each SSL/TLS connection.
tune.ssl.certificate-compression { auto | off }
This setting allows to configure the certificate compression support which is
an extension (RFC 8879) to TLS 1.3.
When set to "auto" it uses the default value of the TLS library.
With "off" it tries to explicitely disable the support of the feature.
HAProxy won't try to send compressed certificates anymore nor accept
compressed certificates.
Configures both backend and frontend sides.
This keyword is supported by OpenSSL >= 3.2.0.
The default value is auto.
tune.ssl.default-dh-param <number>
Sets the maximum size of the Diffie-Hellman parameters used for generating
the ephemeral/temporary Diffie-Hellman key in case of DHE key exchange. The
@ -6295,16 +6262,8 @@ balance url_param <param> [check_post]
will take away N-1 of the highest loaded servers at the
expense of performance. With very high values, the algorithm
will converge towards the leastconn's result but much slower.
In addition, for large server farms with very low loads (or
perfect balance), comparing loads will often lead to a tie,
so in case of equal loads between all measured servers, their
request rate over the last second are compared, which allows
to better balance server usage over time in the same spirit
as roundrobin does, and smooth consistent hash unfairness.
The default value is 2, which generally shows very good
distribution and performance. For large farms with low loads
(less than a few requests per second per server), it may help
to raise it to 3 or even 4. This algorithm is also known as
distribution and performance. This algorithm is also known as
the Power of Two Random Choices and is described here :
http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf
@ -10841,7 +10800,7 @@ no option logasap
logging.
option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]
option mysql-check [ user <username> [ { post-41 | pre-41 } ] ]
Use MySQL health checks for server testing
May be used in the following contexts: tcp
@ -10854,12 +10813,6 @@ option mysql-check [ user <username> [ { post-41 | pre-41 | post-80 } ] ]
server.
post-41 Send post v4.1 client compatible checks (the default)
pre-41 Send pre v4.1 client compatible checks
post-80 Send post v8.0 client compatible checks with CLIENT_PLUGIN_AUTH
capability set and mysql_native_password as the authentication
plugin. Use this option when connecting to MySQL 8.0+ servers
where the health check user is created with mysql_native_password
authentication. Example:
CREATE USER 'haproxy'@'%' IDENTIFIED WITH mysql_native_password BY '';
If you specify a username, the check consists of sending two MySQL packet,
one Client Authentication packet, and one QUIT packet, to correctly close
@ -17250,9 +17203,7 @@ interface <interface>
ktls <on|off> [ EXPERIMENTAL ]
Enables or disables ktls for those sockets. If enabled, kTLS will be used
if the kernel supports it and the cipher is compatible. This is only
available on Linux kernel 4.17 and above. Please note that some network
drivers and/or TLS stacks might restrict kTLS usage to TLS v1.2 only. See
also "force-tlsv12".
available on Linux kernel 4.17 and above.
label <label>
Sets an optional label for these sockets. It could be used group sockets by
@ -18355,10 +18306,7 @@ hash-key <key>
id The node keys will be derived from the server's numeric
identifier as set from "id" or which defaults to its position
in the server list. This is the default. Note that only the 28
lowest bits of the ID will be used (i.e. (id % 268435456)), so
better only use values comprised between 1 and this value to
avoid overlap.
in the server list.
addr The node keys will be derived from the server's address, when
available, or else fall back on "id".
@ -18370,9 +18318,7 @@ hash-key <key>
HAProxy processes are balancing traffic to the same set of servers. If the
server order of each process is different (because, for example, DNS records
were resolved in different orders) then this will allow each independent
HAProxy processes to agree on routing decisions. Note: "balance random" also
uses "hash-type consistent", and the quality of the distribution will depend
on the quality of the keys.
HAProxy processes to agree on routing decisions.
id <value>
May be used in the following contexts: tcp, http, log
@ -18517,10 +18463,9 @@ See also: "option tcp-check", "option httpchk"
ktls <on|off> [ EXPERIMENTAL ]
May be used in the following contexts: tcp, http, log, peers, ring
Enables or disables ktls for those sockets. If enabled, kTLS will be used if
the kernel supports it and the cipher is compatible. This is only available
on Linux 4.17 and above. Please note that some network drivers and/or TLS
stacks might restrict kTLS usage to TLS v1.2 only. See also "force-tlsv12".
Enables or disables ktls for those sockets. If enabled, kTLS will be used
if the kernel supports it and the cipher is compatible.
This is only available on Linux.
log-bufsize <bufsize>
May be used in the following contexts: log
@ -20607,7 +20552,6 @@ ip.ver binary integer
ipmask(mask4[,mask6]) address address
json([input-code]) string string
json_query(json_path[,output_type]) string _outtype_
jwt_decrypt_jwk(<jwk>) string binary
jwt_decrypt_cert(<cert>) string binary
jwt_decrypt_secret(<secret>) string binary
jwt_header_query([json_path[,output_type]]) string string
@ -21252,9 +21196,9 @@ ip.fp([<mode>])
can be used to distinguish between multiple apparently identical hosts. The
real-world use case is to refine the identification of misbehaving hosts
between a shared IP address to avoid blocking legitimate users when only one
is misbehaving and needs to be blocked. The converter builds a 8-byte minimum
binary block based on the input. The bytes of the fingerprint are arranged
like this:
is misbehaving and needs to be blocked. The converter builds a 7-byte binary
block based on the input. The bytes of the fingerprint are arranged like
this:
- byte 0: IP TOS field (see ip.tos)
- byte 1:
- bit 7: IPv6 (1) / IPv4 (0)
@ -21269,13 +21213,10 @@ ip.fp([<mode>])
- bits 3..0: TCP window scaling + 1 (1..15) / 0 (no WS advertised)
- byte 3..4: tcp.win
- byte 5..6: tcp.options.mss, or zero if absent
- byte 7: 1 bit per present TCP option, with options 2 to 8 being mapped to
bits 0..6 respectively, and bit 7 indicating the presence of any
option from 9 to 255.
The <mode> argument permits to append more information to the fingerprint. By
default, when the <mode> argument is not set or is zero, the fingerprint is
solely made of the 8 bytes described above. If <mode> is specified as another
solely made of the 7 bytes described above. If <mode> is specified as another
value, it then corresponds to the sum of the following values, and the
respective components will be concatenated to the fingerprint, in the order
below:
@ -21285,7 +21226,7 @@ ip.fp([<mode>])
- 4: the source IP address is appended to the fingerprint, which adds
4 bytes for IPv4 and 16 for IPv6.
Example: make a 13..25 bytes fingerprint using the base FP, the TTL and the
Example: make a 12..24 bytes fingerprint using the base FP, the TTL and the
source address (1+4=5):
frontend test
@ -21461,44 +21402,6 @@ jwt_decrypt_cert(<cert>)
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_cert("/foo/bar.pem")]
jwt_decrypt_jwk(<jwk>)
Performs a signature validation of a JSON Web Token following the JSON Web
Encryption format (see RFC 7516) given in input and return its content
decrypted thanks to the provided JSON Web Key (RFC7517).
The <jwk> parameter must be a valid JWK of type 'oct' or 'RSA' ('kty' field
of the JSON key) that can be provided either as a string or via a variable.
The only tokens managed yet are the ones using the Compact Serialization
format (five dot-separated base64-url encoded strings).
This converter can be used to decode token that have a symmetric-type
algorithm ("alg" field of the JOSE header) among the following: A128KW,
A192KW, A256KW, A128GCMKW, A192GCMKW, A256GCMKW, dir. In this case, we expect
the provided JWK to be of the 'oct' type. Please note that the A128KW and
A192KW algorithms are not available on AWS-LC and decryption will not work.
This converter also manages tokens that have an algorithm ("alg" field of
the JOSE header) among the following: RSA1_5, RSA-OAEP or RSA-OAEP-256. In
such a case an 'RSA' type JWK representing a private key must be provided.
The JWE token must be provided base64url-encoded and the output will be
provided "raw". If an error happens during token parsing, signature
verification or content decryption, an empty string will be returned.
Because of the way quotes, commas and double quotes are treated in the
configuration, the contents of the JWK must be properly escaped for this
converter to work properly (see section 2.2 for more information).
Example:
# Get a JWT from the authorization header, put its decrypted content in an
# HTTP header
http-request set-var(txn.bearer) http_auth_bearer
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_secret(\'{\"kty\":\"oct\",\"k\":\"wAsgsg\"}\')
# or via a variable
http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwk) str(\'{\"kty\":\"oct\",\"k\":\"Q-NFLlghQ\"}\')
http-request set-header X-Decrypted %[var(txn.bearer),jwt_decrypt_jwk(txn.jwk)
jwt_decrypt_secret(<secret>)
Performs a signature validation of a JSON Web Token following the JSON Web
Encryption format (see RFC 7516) given in input and return its content
@ -31781,8 +31684,8 @@ ocsp-update [ off | on ]
jwt [ off | on ]
Allow for this certificate to be used for JWT validation or decryption via
the "jwt_verify_cert", "jwt_decrypt_cert" or "jwt_decrypt" converters when
set to 'on'. Its value defaults to 'off'.
the "jwt_verify_cert" or "jwt_decrypt_cert" converters when set to 'on'. Its
value defaults to 'off'.
When set to 'on' for a given certificate, the CLI command "del ssl cert" will
not work. In order to be deleted, a certificate must not be used, either for

View file

@ -11,7 +11,7 @@ default init, this was controversial but fedora and archlinux already uses it.
At this time HAProxy still had a multi-process model, and the way haproxy is
working was incompatible with the daemon mode.
Systemd is compatible with traditional forking services, but somehow HAProxy
Systemd is compatible with traditionnal forking services, but somehow HAProxy
is different. To work correctly, systemd needs a main PID, this is the PID of
the process that systemd will supervises.
@ -45,7 +45,7 @@ However the wrapper suffered from several problems:
### mworker V1
HAProxy 1.8 got rid of the wrapper which was replaced by the master worker
HAProxy 1.8 got ride of the wrapper which was replaced by the master worker
mode. This first version was basically a reintegration of the wrapper features
within HAProxy. HAProxy is launched with the -W flag, read the configuration and
then fork. In mworker mode, the master is usually launched as a root process,
@ -86,7 +86,7 @@ retrieved automatically.
The master is supervising the workers, when a current worker (not a previous one
from before the reload) is exiting without being asked for a reload, the master
will emit an "exit-on-failure" error and will kill every workers with a SIGTERM
and exits with the same error code than the failed worker, this behavior can be
and exits with the same error code than the failed master, this behavior can be
changed by using the "no exit-on-failure" option in the global section.
While the master is supervising the workers using the wait() function, the
@ -186,8 +186,8 @@ number that can be found in HAPROXY_PROCESSES. With this change the stats socket
in the configuration is less useful and everything can be done from the master
CLI.
With 2.7, the reload mechanism of the master CLI evolved, with previous versions,
this mechanism was asynchronous, so once the `reload` command was received, the
With 2.7, the reload mecanism of the master CLI evolved, with previous versions,
this mecanism was asynchronous, so once the `reload` command was received, the
master would reload, the active master CLI connection was closed, and there was
no way to return a status as a response to the `reload` command. To achieve a
synchronous reload, a dedicated sockpair is used, one side uses a master CLI
@ -208,38 +208,3 @@ starts with -st to achieve a hard stop on the previous worker.
Version 3.0 got rid of the libsystemd dependencies for sd_notify() after the
events of xz/openssh, the function is now implemented directly in haproxy in
src/systemd.c.
### mworker V3
This version was implemented with HAProxy 3.1, the goal was to stop parsing and
applying the configuration in the master process.
One of the caveats of the previous implementation was that the parser could take
a lot of time, and the master process would be stuck in the parser instead of
handling its polling loop, signals etc. Some parts of the configuration parsing
could also be less reliable with third-party code (EXTRA_OBJS), it could, for
example, allow opening FDs and not closing them before the reload which
would crash the master after a few reloads.
The startup of the master-worker was reorganized this way:
- the "discovery" mode, which is a lighter configuration parsing step, only
applies the configuration which need to be effective for the master process.
For example, "master-worker", "mworker-max-reloads" and less than 20 other
keywords that are identified by KWF_DISCOVERY in the code. It is really fast
as it don't need all the configuration to be applied in the master process.
- the master will then fork a worker, with a PROC_O_INIT flag. This worker has
a temporary sockpair connected to the master CLI. Once the worker is forked,
the master initializes its configuration and starts its polling loop.
- The newly forked worker will try to parse the configuration, which could
result in a failure (exit 1), or any bad error code. In case of success, the
worker will send a "READY" message to the master CLI then close this FD. At
this step everything was initialized and the worker can enter its polling
loop.
- The master then waits for the worker, it could:
* receive the READY message over the mCLI, resulting in a successful loading
of haproxy
* receive a SIGCHLD, meaning the worker exited and couldn't load

View file

@ -1725,30 +1725,6 @@ add acl [@<ver>] <acl> <pattern>
This command cannot be used if the reference <acl> is a name also used with
a map. In this case, the "add map" command must be used instead.
add backend <name> from <defproxy> [mode <mode>] [guid <guid>] [ EXPERIMENTAL ]
Instantiate a new backend proxy with the name <name>.
Only TCP or HTTP proxies can be created. All of the settings are inherited
from <defproxy> default proxy instance. By default, it is mandatory to
specify the backend mode via the argument of the same name, unless <defproxy>
already defines it explicitely. It is also possible to use an optional GUID
argument if wanted.
Servers can be added via the command "add server". The backend is initialized
in the unpublished state. Once considered ready for traffic, use "publish
backend" to expose the newly created instance.
All named default proxies can be used, given that they validate the same
inheritance rules applied during configuration parsing. There is some
exceptions though, for example when the mode is neither TCP nor HTTP. Another
exception is that it is not yet possible to use a default proxies which
reference custom HTTP errors, for example via the errorfiles or http-rules
keywords.
This command is restricted and can only be issued on sockets configured for
level "admin". Moreover, this feature is still considered in development so it
also requires experimental mode (see "experimental-mode on").
add map [@<ver>] <map> <key> <value>
add map [@<ver>] <map> <payload>
Add an entry into the map <map> to associate the value <value> to the key
@ -2558,8 +2534,7 @@ set maxconn global <maxconn>
delayed until the threshold is reached. A value of zero restores the initial
setting.
set profiling memory { on | off }
set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
set profiling { tasks | memory } { auto | on | off }
Enables or disables CPU or memory profiling for the indicated subsystem. This
is equivalent to setting or clearing the "profiling" settings in the "global"
section of the configuration file. Please also see "show profiling". Note
@ -2569,13 +2544,6 @@ set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
on the linux-glibc target), and requires USE_MEMORY_PROFILING to be set at
compile time.
. For tasks profiling, it is possible to enable or disable the collection of
per-task lock and memory timings at runtime, but the change is only taken
into account next time the profiler switches from off/auto to on (either
automatically or manually). Thus when using "no-lock" to disable per-task
lock profiling and save CPU cycles, it is recommended to flip the task
profiling off then on to commit the change.
set rate-limit connections global <value>
Change the process-wide connection rate limit, which is set by the global
'maxconnrate' setting. A value of zero disables the limitation. This limit

View file

@ -627,10 +627,7 @@ For the type PP2_TYPE_SSL, the value is itself a defined like this :
uint8_t client;
uint32_t verify;
struct pp2_tlv sub_tlv[0];
} __attribute__((packed));
Note the "packed" attribute which indicates that each field starts immediately
after the previous one (i.e. without type-specific alignment nor padding).
};
The <verify> field will be zero if the client presented a certificate
and it was successfully verified, and non-zero otherwise.

View file

@ -24,7 +24,7 @@ vtest installation
------------------------
To use vtest you will have to download and compile the recent vtest
sources found at https://github.com/vtest/VTest2.
sources found at https://github.com/vtest/VTest.
To compile vtest:

View file

@ -33,8 +33,6 @@
#define HA_PROF_TASKS_MASK 0x00000003 /* per-task CPU profiling mask */
#define HA_PROF_MEMORY 0x00000004 /* memory profiling */
#define HA_PROF_TASKS_MEM 0x00000008 /* per-task CPU profiling with memory */
#define HA_PROF_TASKS_LOCK 0x00000010 /* per-task CPU profiling with locks */
#ifdef USE_MEMORY_PROFILING

View file

@ -192,7 +192,6 @@ struct lbprm {
void (*server_requeue)(struct server *); /* function used to place the server where it must be */
void (*proxy_deinit)(struct proxy *); /* to be called when we're destroying the proxy */
void (*server_deinit)(struct server *); /* to be called when we're destroying the server */
int (*server_init)(struct server *); /* initialize a freshly added server (runtime); <0=fail. */
};
#endif /* _HAPROXY_BACKEND_T_H */

View file

@ -69,7 +69,6 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit);
int be_downtime(struct proxy *px);
int be_supports_dynamic_srv(struct proxy *px, char **msg);
void recount_servers(struct proxy *px);
void update_backend_weight(struct proxy *px);

View file

@ -263,8 +263,6 @@ static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int s
const char *ptr_old = ptr;
const char *end = b_wrap(buf);
uint64_t chunk = 0;
int backslash = 0;
int quote = 0;
stop -= start; // bytes left
start = stop; // bytes to transfer
@ -329,37 +327,13 @@ static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int s
if (--stop == 0)
return 0;
/* The loop seeks the first CRLF or non-tab CTL char
* and stops there. If a backslash/quote is active,
* it's an error. If none, we assume it's the CRLF
* and go back to the top of the loop checking for
* CR then LF. This way CTLs, lone LF etc are handled
* in the fallback path. This allows to protect
* remotes against their own possibly non-compliant
* chunk-ext parser which could mistakenly skip a
* quoted CRLF. Chunk-ext are not used anyway, except
* by attacks.
*/
while (!HTTP_IS_CTL(*ptr) || HTTP_IS_SPHT(*ptr)) {
if (backslash)
backslash = 0; // escaped char
else if (*ptr == '\\' && quote)
backslash = 1;
else if (*ptr == '\\') // backslash not permitted outside quotes
goto error;
else if (*ptr == '"') // begin/end of quoted-pair
quote = !quote;
while (!HTTP_IS_CRLF(*ptr)) {
if (++ptr >= end)
ptr = b_orig(buf);
if (--stop == 0)
return 0;
}
/* mismatched quotes / backslashes end here */
if (quote || backslash)
goto error;
/* CTLs (CRLF) fall to the common check */
/* we have a CRLF now, loop above */
continue;
}
else

View file

@ -147,14 +147,14 @@ __attribute__((constructor)) static void __initcb_##linenum() \
#define _DECLARE_INITCALL(...) \
__DECLARE_INITCALL(__VA_ARGS__)
/* This requires that function <function> is called without arguments
* during init stage <stage> which must be one of init_stage.
/* This requires that function <function> is called with pointer argument
* <argument> during init stage <stage> which must be one of init_stage.
*/
#define INITCALL0(stage, function) \
_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
/* This requires that function <function> is called with pointer argument
* <arg1> during init stage <stage> which must be one of init_stage.
* <argument> during init stage <stage> which must be one of init_stage.
*/
#define INITCALL1(stage, function, arg1) \
_DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)

View file

@ -380,14 +380,6 @@ static inline unsigned long ERR_peek_error_func(const char **func)
#endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && !defined(OPENSSL_IS_AWSLC) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_OPENSSL_WOLFSSL)
# define X509_STORE_getX_objects(x) X509_STORE_get1_objects(x)
# define sk_X509_OBJECT_popX_free(x, y) sk_X509_OBJECT_pop_free(x,y)
#else
# define X509_STORE_getX_objects(x) X509_STORE_get0_objects(x)
# define sk_X509_OBJECT_popX_free(x, y) ({})
#endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070200fL)
#define __OPENSSL_110_CONST__ const
#else

View file

@ -72,8 +72,8 @@ struct pool_registration {
struct list list; /* link element */
const char *name; /* name of the pool */
const char *file; /* where the pool is declared */
ullong size; /* expected object size */
unsigned int line; /* line in the file where the pool is declared, 0 if none */
unsigned int size; /* expected object size */
unsigned int flags; /* MEM_F_* */
unsigned int type_align; /* type-imposed alignment; 0=unspecified */
unsigned int align; /* expected alignment; 0=unspecified */

View file

@ -183,7 +183,7 @@ unsigned long long pool_total_allocated(void);
unsigned long long pool_total_used(void);
void pool_flush(struct pool_head *pool);
void pool_gc(struct pool_head *pool_ctx);
struct pool_head *create_pool_with_loc(const char *name, ullong size, unsigned int align,
struct pool_head *create_pool_with_loc(const char *name, unsigned int size, unsigned int align,
unsigned int flags, const char *file, unsigned int line);
struct pool_head *create_pool_from_reg(const char *name, struct pool_registration *reg);
void create_pool_callback(struct pool_head **ptr, char *name, struct pool_registration *reg);

View file

@ -242,7 +242,7 @@ enum PR_SRV_STATE_FILE {
/* Proxy flags */
#define PR_FL_DISABLED 0x01 /* The proxy was disabled in the configuration (not at runtime) */
#define PR_FL_STOPPED 0x02 /* The proxy was stopped */
#define PR_FL_DEF_EXPLICIT_MODE 0x04 /* Proxy mode is explicitely defined - only used for defaults instance */
#define PR_FL_READY 0x04 /* The proxy is ready to be used (initialized and configured) */
#define PR_FL_EXPLICIT_REF 0x08 /* The default proxy is explicitly referenced by another proxy */
#define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */
#define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */
@ -508,16 +508,10 @@ struct proxy {
EXTRA_COUNTERS(extra_counters_be);
THREAD_ALIGN();
/* these ones change all the time */
int served; /* # of active sessions currently being served */
unsigned int feconn, beconn; /* # of active frontend and backends streams */
THREAD_ALIGN();
/* these ones are only changed when queues are involved, but checked
* all the time.
*/
unsigned int queueslength; /* Sum of the length of each queue */
int served; /* # of active sessions currently being served */
int totpend; /* total number of pending connections on this instance (for stats) */
unsigned int feconn, beconn; /* # of active frontend and backends streams */
};
struct switching_rule {

View file

@ -41,8 +41,6 @@ extern unsigned int error_snapshot_id; /* global ID assigned to each error then
extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */
extern struct list defaults_list; /* all defaults proxies list */
extern unsigned int dynpx_next_id;
extern const struct cfg_opt cfg_opts[];
extern const struct cfg_opt cfg_opts2[];
extern const struct cfg_opt cfg_opts3[];
@ -61,7 +59,6 @@ void deinit_proxy(struct proxy *p);
void free_proxy(struct proxy *p);
const char *proxy_cap_str(int cap);
const char *proxy_mode_str(int mode);
enum pr_mode str_to_proxy_mode(const char *mode);
const char *proxy_find_best_option(const char *word, const char **extra);
uint proxy_get_next_id(uint from);
void proxy_store_name(struct proxy *px);
@ -77,7 +74,8 @@ void defaults_px_destroy_all_unref(void);
void defaults_px_detach(struct proxy *px);
void defaults_px_ref_all(void);
void defaults_px_unref_all(void);
int proxy_ref_defaults(struct proxy *px, struct proxy *defpx, char **errmsg);
void proxy_ref_defaults(struct proxy *px, struct proxy *defpx);
void proxy_unref_defaults(struct proxy *px);
int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg);
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
@ -99,7 +97,6 @@ int resolve_stick_rule(struct proxy *curproxy, struct sticking_rule *mrule);
void free_stick_rules(struct list *rules);
void free_server_rules(struct list *srules);
int proxy_init_per_thr(struct proxy *px);
int proxy_finalize(struct proxy *px, int *err_code);
/*
* This function returns a string containing the type of the proxy in a format

View file

@ -20,7 +20,8 @@
#define QUIC_OPENSSL_COMPAT_CLIENT_APPLICATION "CLIENT_TRAFFIC_SECRET_0"
#define QUIC_OPENSSL_COMPAT_SERVER_APPLICATION "SERVER_TRAFFIC_SECRET_0"
void quic_tls_compat_msg_callback(int write_p, int version, int content_type,
void quic_tls_compat_msg_callback(struct connection *conn,
int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl);
int quic_tls_compat_init(struct bind_conf *bind_conf, SSL_CTX *ctx);
void quic_tls_compat_keylog_callback(const SSL *ssl, const char *line);

View file

@ -383,6 +383,7 @@ struct server {
unsigned next_eweight; /* next pending eweight to commit */
unsigned cumulative_weight; /* weight of servers prior to this one in the same group, for chash balancing */
int maxqueue; /* maximum number of pending connections allowed */
unsigned int queueslength; /* Sum of the length of each queue */
int shard; /* shard (in peers protocol context only) */
int log_bufsize; /* implicit ring bufsize (for log server only - in log backend) */
@ -405,7 +406,6 @@ struct server {
unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */
unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */
unsigned int curr_sess_idle_conns; /* Current number of idle connections attached to a session instead of idle/safe trees. */
unsigned int queueslength; /* Sum of the length of each queue */
/* elements only used during boot, do not perturb and plug the hole */
struct guid_node guid; /* GUID global tree node */

View file

@ -80,7 +80,6 @@ void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror);
const char *ha_default_cert_dir();
extern struct cert_exts cert_exts[];
extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);

View file

@ -194,7 +194,7 @@ struct issuer_chain {
struct connection;
typedef void (*ssl_sock_msg_callback_func)(
typedef void (*ssl_sock_msg_callback_func)(struct connection *conn,
int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl);
@ -338,8 +338,6 @@ struct global_ssl {
int renegotiate; /* Renegotiate mode (SSL_RENEGOTIATE_ flag) */
char **passphrase_cmd;
int passphrase_cmd_args_cnt;
unsigned int certificate_compression:1; /* allow to explicitely disable certificate compression */
};
/* The order here matters for picking a default context,
@ -363,7 +361,6 @@ struct passphrase_cb_data {
const char *path;
struct ckch_data *ckch_data;
int passphrase_idx;
int callback_called;
};
#endif /* USE_OPENSSL */

View file

@ -362,19 +362,15 @@ static inline unsigned long thread_isolated()
extern uint64_t now_mono_time(void); \
if (_LK_ != _LK_UN) { \
th_ctx->lock_level += bal; \
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) \
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) \
lock_start = now_mono_time(); \
} \
(void)(expr); \
if (_LK_ == _LK_UN) { \
th_ctx->lock_level += bal; \
if (th_ctx->lock_level == 0 &&\
unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) \
if (th_ctx->lock_level == 0 && unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) \
th_ctx->locked_total += now_mono_time() - th_ctx->lock_start_date; \
} else if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) { \
} else if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) { \
uint64_t now = now_mono_time(); \
if (lock_start) \
th_ctx->lock_wait_total += now - lock_start; \
@ -388,8 +384,7 @@ static inline unsigned long thread_isolated()
typeof(expr) _expr = (expr); \
if (_expr == 0) { \
th_ctx->lock_level += bal; \
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L)) == \
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_L))) { \
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING)) { \
if (_LK_ == _LK_UN && th_ctx->lock_level == 0) \
th_ctx->locked_total += now_mono_time() - th_ctx->lock_start_date; \
else if (_LK_ != _LK_UN && th_ctx->lock_level == 1) \

View file

@ -69,8 +69,6 @@ enum {
#define TH_FL_IN_DBG_HANDLER 0x00000100 /* thread currently in the debug signal handler */
#define TH_FL_IN_WDT_HANDLER 0x00000200 /* thread currently in the wdt signal handler */
#define TH_FL_IN_ANY_HANDLER 0x00000380 /* mask to test if the thread is in any signal handler */
#define TH_FL_TASK_PROFILING_L 0x00000400 /* task profiling in locks (also requires TASK_PROFILING) */
#define TH_FL_TASK_PROFILING_M 0x00000800 /* task profiling in mem alloc (also requires TASK_PROFILING) */
/* we have 4 buffer-wait queues, in highest to lowest emergency order */
#define DYNBUF_NBQ 4

View file

@ -1,6 +1,6 @@
varnishtest "Test the support for tcp-md5sig option (linux only)"
feature cmd "$HAPROXY_PROGRAM -cc 'feature(HAVE_WORKING_TCP_MD5SIG)'"
feature cmd "$HAPROXY_PROGRAM -cc 'feature(HAVE_TCP_MD5SIG)'"
feature ignore_unknown_macro
haproxy h1 -conf {

View file

@ -1,9 +1,8 @@
#REGTEST_TYPE=devel
# This reg-test checks the behaviour of the jwt_decrypt_secret,
# jwt_decrypt_cert and jwt_decrypt_jwk converters that decode a JSON Web
# Encryption (JWE) token, check its signature and decrypt its content (RFC
# 7516).
# This reg-test checks the behaviour of the jwt_decrypt_secret and
# jwt_decrypt_cert converters that decode a JSON Web Encryption (JWE) token,
# checks its signature and decrypt its content (RFC 7516).
# The tokens have two tiers of encryption, one that is used to encrypt a secret
# ("alg" field of the JOSE header) and this secret is then used to
# encrypt/decrypt the data contained in the token ("enc" field of the JOSE
@ -14,12 +13,12 @@
# have a hardcoded "AWS-LC UNMANAGED" value put in the response header instead
# of the decrypted contents.
varnishtest "Test the 'jwt_decrypt_jwk' functionalities"
varnishtest "Test the 'jwt_decrypt' functionalities"
feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(3.4-dev2)'"
feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL) && openssl_version_atleast(1.1.1)'"
feature ignore_unknown_macro
server s1 -repeat 20 {
server s1 -repeat 10 {
rxreq
txresp
} -start
@ -58,7 +57,6 @@ haproxy h1 -conf {
use_backend secret_based_alg if { path_beg /secret }
use_backend pem_based_alg if { path_beg /pem }
use_backend jwk if { path_beg /jwk }
default_backend dflt
@ -87,21 +85,6 @@ haproxy h1 -conf {
http-after-response set-header X-Decrypted %[var(txn.decrypted)]
server s1 ${s1_addr}:${s1_port}
backend jwk
http-request set-var(txn.jwe) http_auth_bearer
http-request set-var(txn.jwk) req.fhdr(X-JWK)
http-request set-var(txn.decrypted) var(txn.jwe),jwt_decrypt_jwk(txn.jwk)
.if ssllib_name_startswith(AWS-LC)
acl aws_unmanaged var(txn.jwe),jwt_header_query('$.alg') -m str "A128KW"
http-request set-var(txn.decrypted) str("AWS-LC UNMANAGED") if aws_unmanaged
.endif
http-after-response set-header X-Decrypted %[var(txn.decrypted)]
server s1 ${s1_addr}:${s1_port}
backend dflt
server s1 ${s1_addr}:${s1_port}
@ -119,10 +102,6 @@ client c1_1 -connect ${h1_mainfe_sock} {
txreq -url "/secret" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8w" -hdr "X-Secret: ZMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg"
rxresp
expect resp.http.x-decrypted == "Setec Astronomy"
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8w" -hdr "X-JWK: {\"kty\":\"oct\", \"k\":\"ZMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg\"}"
rxresp
expect resp.http.x-decrypted == "Setec Astronomy"
} -run
@ -134,10 +113,6 @@ client c1_2 -connect ${h1_mainfe_sock} {
txreq -url "/secret" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8v" -hdr "X-Secret: ZMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg"
rxresp
expect resp.http.x-decrypted == ""
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8v" -hdr "X-JWK: {\"kty\":\"oct\", \"k\":\"ZMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg\"}"
rxresp
expect resp.http.x-decrypted == ""
} -run
@ -149,10 +124,6 @@ client c1_3 -connect ${h1_mainfe_sock} {
txreq -url "/secret" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8w" -hdr "X-Secret: zMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg"
rxresp
expect resp.http.x-decrypted == ""
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiZGlyIiwgImVuYyI6ICJBMjU2R0NNIn0..hxCk0nP4aVNpgfb7.inlyAZtUzDCTpD_9iuWx.Pyu90cmgkXenMIVu9RUp8v" -hdr "X-JWK: {\"kty\":\"oct\", \"k\":\"zMpktzGq1g6_r4fKVdnx9OaYr4HjxPjIs7l7SwAsgsg\"}"
rxresp
expect resp.http.x-decrypted == ""
} -run
@ -163,11 +134,6 @@ client c2_1 -connect ${h1_mainfe_sock} {
txreq -url "/secret" -hdr "Authorization: Bearer eyJhbGciOiAiQTEyOEtXIiwgImVuYyI6ICJBMTI4Q0JDLUhTMjU2In0.AaOyP1zNjsywJOoQ941JJWT4LQIDlpy3UibM_48HrsoCJ5ENpQhfbQ.h2ZBUiy9ofvcDZOwV2iVJA.K0FhK6ri44ZWmtFUtJRpiZSeT8feKX5grFpU8xG5026bGXAdZADO4ZkQ8DRvSEE9DwNIlK6cIEoSavm12gSzQVXajz3MWv5U6VbK5gPFCeFjJfMPmdQ9THIi-hapcueSxYz2rkcGxo3iP3ixE_bww8UB_XlQvnokhFxtf8NushMkjef4RDrW5vQu4j_qPbqG334msDKmFi8Klprs6JktrADeEJ0bPGN80NKEWp7XPcCbfmcwYe-9z_tPw_KJcQhLpQevfPLfVI4WjPgPxYNGw03qKYnLD7oTjr9qCrQmzUVXutlhxfpD3UQr11SJu8q19Ug82bON-GRd2CjpSrErQq42dd0_mWjG9iDqjqpYFBK9DV_qawy2dxFbfIcCsnb6ewifjoJLiFg2OT7-YdTaC7kqaXeE1JpA-OtMXN72FUDrnQ8r9ifj_VpMNvBf_36dbOCT-cGwIOI8Pf6HH2smXULhtBv9q-qO2zyScpmliqZDXUqmvQ8rxi-xYI2hijV80jo14teZgIotWsZE2FrMPJTkegDmh4cG5UzoUsQxzPhXqHvkss6Hv7h-_fmvXvXY1AZ8T8bL1qM4bS8mKpewmGtjmU6S220tL60ieT2QL0vmTFlJkOE8uFreWlPnxNKBix_zj4Smhg1zS_sl7GoXhp5Q_QY3MOMM5-gCAALY0crqLLWtHswElVOiJSyd64T9HFyXm7Rleqq2kLXmTvDhOR6lzMnA0rcGP7lQGYlLZgFiicsMY722XlKI3v1-cJYvj2RZMPe1ijBLFFTqyPeCBkbsDC3XCpWhMByNHSHKN3t-NJmQBIC-89ZeOMU-WBtqrDDi_CMnaz9mwkyt3P7ja_fVskc4KKBBlMVYDZ3DJeJw3Kg9Pie0XlqHkD6W1vyAWjOM2z76Rh_3553dLAH1HxNRwidLjq3SvoaX3TOU5O2_omFGPBek7QdzhNBGLgv6Zlul_XxZq9UGiVo1jrnkd40_vAZQRL6NyMxGBEij_b8F_wDMz5njrL-a0c2Y5mMno-q8gmM4sFKI1BS5HsrUAw.PFFSFlDslALnebAdaqS_MA" -hdr "X-Secret: 3921VrO5TrLvPQ-NFLlghQ"
rxresp
expect resp.http.x-decrypted ~ "(Sed ut perspiciatis unde omnis iste natus error sit voluptatem doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo veritatis et quasi architecto beatae vitae dicta sunt explicabo\\. Nemo ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt\\. porro quisquam est, qui dolorem ipsum quia dolor sit amet, adipisci velit, sed quia non numquam eius modi tempora incidunt ut dolore magnam aliquam quaerat voluptatem\\. Ut enim ad minima veniam, nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut ea commodi consequatur\\? Quis autem vel eum iure reprehenderit qui in voluptate velit esse quam nihil molestiae consequatur, vel illum qui eum fugiat quo voluptas nulla pariatur\\?|AWS-LC UNMANAGED)"
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiQTEyOEtXIiwgImVuYyI6ICJBMTI4Q0JDLUhTMjU2In0.AaOyP1zNjsywJOoQ941JJWT4LQIDlpy3UibM_48HrsoCJ5ENpQhfbQ.h2ZBUiy9ofvcDZOwV2iVJA.K0FhK6ri44ZWmtFUtJRpiZSeT8feKX5grFpU8xG5026bGXAdZADO4ZkQ8DRvSEE9DwNIlK6cIEoSavm12gSzQVXajz3MWv5U6VbK5gPFCeFjJfMPmdQ9THIi-hapcueSxYz2rkcGxo3iP3ixE_bww8UB_XlQvnokhFxtf8NushMkjef4RDrW5vQu4j_qPbqG334msDKmFi8Klprs6JktrADeEJ0bPGN80NKEWp7XPcCbfmcwYe-9z_tPw_KJcQhLpQevfPLfVI4WjPgPxYNGw03qKYnLD7oTjr9qCrQmzUVXutlhxfpD3UQr11SJu8q19Ug82bON-GRd2CjpSrErQq42dd0_mWjG9iDqjqpYFBK9DV_qawy2dxFbfIcCsnb6ewifjoJLiFg2OT7-YdTaC7kqaXeE1JpA-OtMXN72FUDrnQ8r9ifj_VpMNvBf_36dbOCT-cGwIOI8Pf6HH2smXULhtBv9q-qO2zyScpmliqZDXUqmvQ8rxi-xYI2hijV80jo14teZgIotWsZE2FrMPJTkegDmh4cG5UzoUsQxzPhXqHvkss6Hv7h-_fmvXvXY1AZ8T8bL1qM4bS8mKpewmGtjmU6S220tL60ieT2QL0vmTFlJkOE8uFreWlPnxNKBix_zj4Smhg1zS_sl7GoXhp5Q_QY3MOMM5-gCAALY0crqLLWtHswElVOiJSyd64T9HFyXm7Rleqq2kLXmTvDhOR6lzMnA0rcGP7lQGYlLZgFiicsMY722XlKI3v1-cJYvj2RZMPe1ijBLFFTqyPeCBkbsDC3XCpWhMByNHSHKN3t-NJmQBIC-89ZeOMU-WBtqrDDi_CMnaz9mwkyt3P7ja_fVskc4KKBBlMVYDZ3DJeJw3Kg9Pie0XlqHkD6W1vyAWjOM2z76Rh_3553dLAH1HxNRwidLjq3SvoaX3TOU5O2_omFGPBek7QdzhNBGLgv6Zlul_XxZq9UGiVo1jrnkd40_vAZQRL6NyMxGBEij_b8F_wDMz5njrL-a0c2Y5mMno-q8gmM4sFKI1BS5HsrUAw.PFFSFlDslALnebAdaqS_MA" -hdr "X-JWK: {\"kty\":\"oct\", \"k\":\"3921VrO5TrLvPQ-NFLlghQ\"}"
rxresp
expect resp.http.x-decrypted ~ "(Sed ut perspiciatis unde omnis iste natus error sit voluptatem doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo veritatis et quasi architecto beatae vitae dicta sunt explicabo\\. Nemo ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt\\. porro quisquam est, qui dolorem ipsum quia dolor sit amet, adipisci velit, sed quia non numquam eius modi tempora incidunt ut dolore magnam aliquam quaerat voluptatem\\. Ut enim ad minima veniam, nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut ea commodi consequatur\\? Quis autem vel eum iure reprehenderit qui in voluptate velit esse quam nihil molestiae consequatur, vel illum qui eum fugiat quo voluptas nulla pariatur\\?|AWS-LC UNMANAGED)"
} -run
@ -212,10 +178,6 @@ client c5 -connect ${h1_mainfe_sock} {
txreq -url "/secret" -hdr "Authorization: Bearer eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiaXYiOiJzVE81QjlPRXFuaUhCX3dYIiwidGFnIjoid2M1ZnRpYUFnNGNOR1JkZzNWQ3FXdyJ9.2zqnM9zeNU-eAMp5h2uFJyxbHHKsZs9YAYKzOcIF3d3Q9uq1TMQAvqOIuXw3kU9o.hh5aObIoIMR6Ke0rXm6V1A.R7U-4OlqOR6f2C1b3nI5bFqZBIGNBgza7FfoPEgrQT8.asJCzUAHCuxS7o8Ut4ENfaY5RluLB35F" -hdr "X-Secret: vprpatiNyI-biJY57qr8Gg4--4Rycgb2G5yO1_myYAw"
rxresp
expect resp.http.x-decrypted == "My Encrypted message"
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiaXYiOiJzVE81QjlPRXFuaUhCX3dYIiwidGFnIjoid2M1ZnRpYUFnNGNOR1JkZzNWQ3FXdyJ9.2zqnM9zeNU-eAMp5h2uFJyxbHHKsZs9YAYKzOcIF3d3Q9uq1TMQAvqOIuXw3kU9o.hh5aObIoIMR6Ke0rXm6V1A.R7U-4OlqOR6f2C1b3nI5bFqZBIGNBgza7FfoPEgrQT8.asJCzUAHCuxS7o8Ut4ENfaY5RluLB35F" -hdr "X-JWK: {\"k\":\"vprpatiNyI-biJY57qr8Gg4--4Rycgb2G5yO1_myYAw\",\"kty\":\"oct\"}"
rxresp
expect resp.http.x-decrypted == "My Encrypted message"
} -run
@ -225,12 +187,6 @@ client c6 -connect ${h1_mainfe_sock} {
txreq -url "/pem" -hdr "Authorization: Bearer eyJhbGciOiAiUlNBMV81IiwgImVuYyI6ICJBMjU2R0NNIn0.ew8AbprGcd_J73-CZPIsE1YonD9rtcL7VCuOOuVkrpS_9UzA9_kMh1yw20u-b5rKJAhmFMCQPXl44ro6IzOeHu8E2X_NlPEnQfyNVQ4R1HB_E9sSk5BLxOH3aHkVUh0I-e2eDDj-pdI3OrdjZtnZEBeQ7tpMcoBEbn1VGg7Pmw4qtdS-0qnDSs-PttU-cejjgPUNLRU8UdoRVC9uJKacJms110QugDuFuMYTTSU2nbIYh0deCMRAuKGWt0Ii6EMYW2JaJ7JfXag59Ar1uylQPyEVrocnOsDuB9xnp2jd796qCPdKxBK9yKUnwjal4SQpYbutr40QzG1S4MsKaUorLg.0el2ruY0mm2s7LUR.X5RI6dF06Y_dbAr8meb-6SG5enj5noto9nzgQU5HDrYdiUofPptIf6E-FikKUM9QR4pY9SyphqbPYeAN1ZYVxBrR8tUf4Do2kw1biuuRAmuIyytpmxwvY946T3ctu1Zw3Ymwe-jWXX08EngzssvzFOGT66gkdufrTkC45Fkr0RBOmWa5OVVg_VR6LwcivtQMmlArlrwbaDmmLqt_2p7afT0UksEz4loq0sskw-p7GbhB2lpzXoDnijdHrQkftRbVCiDbK4-qGr7IRFb0YOHvyVFr-kmDoJv2Zsg_rPKV1LkYmPJUbVDo9T3RAcLinlKPK4ZPC_2bWj3M9BvfOq1HeuyVWzX2Cb1mHFdxXFGqaLPfsE0VOfn0GqL7oHVbuczYYw2eKdmiw5LEMwuuJEdYDE9IIFEe8oRB4hNZ0XMYB6oqqZejD0Fh6nqlj5QUrTYpTSE-3LkgK2zRJ0oZFXZyHCB426bmViuE0mXF7twkQep09g0U35-jFBZcSYBDvZZL1t5d_YEQ0QtO0mEeEpGb0Pvk_EsSMFib7NxClz4_rdtwWCFuM4uFOS5vrQMiMqi_TadhLxrugRFhJpsibuScCiJ7eNDrUvwSWEwv1U593MUX3guDq_ONOo_49EOJSyRJtQCNC6FW6GLWSz9TCo6g5LCnXt-pqwu0Iymr7ZTQ3MTsdq2G55JM2e6SdG43iET8r235hynmXHKPUYHlSjsC2AEAY_pGDO0akIhf4wDVIM5rytn-rjQf-29ZJp05g6KPe-EaN1C-X7aBGhgAEgnX-iaXXbotpGeKRTNj2jAG1UrkYi6BGHxluiXJ8jH_LjHuxKyzIObqK8p28ePDKRL-jyNTrvGW2uorgb_u7HGmWYIWLTI7obnZ5vw3MbkjcwEd4bX5JXUj2rRsUWMlZSSFVO9Wgf7MBvcLsyF0Yqun3p0bi__edmcqNF_uuYZT-8jkUlMborqIDDCYYqIolgi5R1Bmut-gFYq6xyfEncxOi50xmYon50UulVnAH-up_RELGtCjmAivaJb8.upVY733IMAT8YbMab2PZnw" -hdr "X-PEM: ${testdir}/rsa1_5.pem"
rxresp
expect resp.http.x-decrypted == "Sed ut perspiciatis unde omnis iste natus error sit voluptatem doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. porro quisquam est, qui dolorem ipsum quia dolor sit amet, adipisci velit, sed quia non numquam eius modi tempora incidunt ut dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in voluptate velit esse quam nihil molestiae consequatur, vel illum qui eum fugiat quo voluptas nulla pariatur?"
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiUlNBMV81IiwgImVuYyI6ICJBMjU2R0NNIn0.ew8AbprGcd_J73-CZPIsE1YonD9rtcL7VCuOOuVkrpS_9UzA9_kMh1yw20u-b5rKJAhmFMCQPXl44ro6IzOeHu8E2X_NlPEnQfyNVQ4R1HB_E9sSk5BLxOH3aHkVUh0I-e2eDDj-pdI3OrdjZtnZEBeQ7tpMcoBEbn1VGg7Pmw4qtdS-0qnDSs-PttU-cejjgPUNLRU8UdoRVC9uJKacJms110QugDuFuMYTTSU2nbIYh0deCMRAuKGWt0Ii6EMYW2JaJ7JfXag59Ar1uylQPyEVrocnOsDuB9xnp2jd796qCPdKxBK9yKUnwjal4SQpYbutr40QzG1S4MsKaUorLg.0el2ruY0mm2s7LUR.X5RI6dF06Y_dbAr8meb-6SG5enj5noto9nzgQU5HDrYdiUofPptIf6E-FikKUM9QR4pY9SyphqbPYeAN1ZYVxBrR8tUf4Do2kw1biuuRAmuIyytpmxwvY946T3ctu1Zw3Ymwe-jWXX08EngzssvzFOGT66gkdufrTkC45Fkr0RBOmWa5OVVg_VR6LwcivtQMmlArlrwbaDmmLqt_2p7afT0UksEz4loq0sskw-p7GbhB2lpzXoDnijdHrQkftRbVCiDbK4-qGr7IRFb0YOHvyVFr-kmDoJv2Zsg_rPKV1LkYmPJUbVDo9T3RAcLinlKPK4ZPC_2bWj3M9BvfOq1HeuyVWzX2Cb1mHFdxXFGqaLPfsE0VOfn0GqL7oHVbuczYYw2eKdmiw5LEMwuuJEdYDE9IIFEe8oRB4hNZ0XMYB6oqqZejD0Fh6nqlj5QUrTYpTSE-3LkgK2zRJ0oZFXZyHCB426bmViuE0mXF7twkQep09g0U35-jFBZcSYBDvZZL1t5d_YEQ0QtO0mEeEpGb0Pvk_EsSMFib7NxClz4_rdtwWCFuM4uFOS5vrQMiMqi_TadhLxrugRFhJpsibuScCiJ7eNDrUvwSWEwv1U593MUX3guDq_ONOo_49EOJSyRJtQCNC6FW6GLWSz9TCo6g5LCnXt-pqwu0Iymr7ZTQ3MTsdq2G55JM2e6SdG43iET8r235hynmXHKPUYHlSjsC2AEAY_pGDO0akIhf4wDVIM5rytn-rjQf-29ZJp05g6KPe-EaN1C-X7aBGhgAEgnX-iaXXbotpGeKRTNj2jAG1UrkYi6BGHxluiXJ8jH_LjHuxKyzIObqK8p28ePDKRL-jyNTrvGW2uorgb_u7HGmWYIWLTI7obnZ5vw3MbkjcwEd4bX5JXUj2rRsUWMlZSSFVO9Wgf7MBvcLsyF0Yqun3p0bi__edmcqNF_uuYZT-8jkUlMborqIDDCYYqIolgi5R1Bmut-gFYq6xyfEncxOi50xmYon50UulVnAH-up_RELGtCjmAivaJb8.upVY733IMAT8YbMab2PZnw" \
-hdr "X-JWK: { \"kty\": \"RSA\", \"e\": \"AQAB\", \"n\": \"wsqJbopx18NQFYLYOq4ZeMSE89yGiEankUpf25yV8QqroKUGrASj_OeqTWUjwPGKTN1vGFFuHYxiJeAUQH2qQPmg9Oqk6-ATBEKn9COKYniQ5459UxCwmZA2RL6ufhrNyq0JF3GfXkjLDBfhU9zJJEOhknsA0L_c-X4AI3d_NbFdMqxNe1V_UWAlLcbKdwO6iC9fAvwUmDQxgy6R0DC1CMouQpenMRcALaSHar1cm4K-syoNobv3HEuqgZ3s6-hOOSqauqAO0GUozPpaIA7OeruyRl5sTWT0r-iz39bchID2bIKtcqLiFcSYPLBcxmsaQCqRlGhmv6stjTCLV1yT9w\", \"kid\": \"ff3c5c96-392e-46ef-a839-6ff16027af78\", \"d\": \"b9hXfQ8lOtw8mX1dpqPcoElGhbczz_-xq2znCXQpbBPSZBUddZvchRSH5pSSKPEHlgb3CSGIdpLqsBCv0C_XmCM9ViN8uqsYgDO9uCLIDK5plWttbkqA_EufvW03R9UgIKWmOL3W4g4t-C2mBb8aByaGGVNjLnlb6i186uBsPGkvaeLHbQcRQKAvhOUTeNiyiiCbUGJwCm4avMiZrsz1r81Y1Z5izo0ERxdZymxM3FRZ9vjTB-6DtitvTXXnaAm1JTu6TIpj38u2mnNLkGMbflOpgelMNKBZVxSmfobIbFN8CHVc1UqLK2ElsZ9RCQANgkMHlMkOMj-XT0wHa3VBUQ\", \"p\": \"8mgriveKJAp1S7SHqirQAfZafxVuAK_A2QBYPsAUhikfBOvN0HtZjgurPXSJSdgR8KbWV7ZjdJM_eOivIb_XiuAaUdIOXbLRet7t9a_NJtmX9iybhoa9VOJFMBq_rbnbbte2kq0-FnXmv3cukbC2LaEw3aEcDgyURLCgWFqt7M0\", \"q\": \"zbbTv5421GowOfKVEuVoA35CEWgl8mdasnEZac2LWxMwKExikKU5LLacLQlcOt7A6n1ZGUC2wyH8mstO5tV34Eug3fnNrbnxFUEE_ZB_njs_rtZnwz57AoUXOXVnd194seIZF9PjdzZcuwXwXbrZ2RSVW8if_ZH5OVYEM1EsA9M\", \"dp\": \"1BaIYmIKn1X3InGlcSFcNRtSOnaJdFhRpotCqkRssKUx2qBlxs7ln_5dqLtZkx5VM_UE_GE7yzc6BZOwBxtOftdsr8HVh-14ksSR9rAGEsO2zVBiEuW4qZf_aQM-ScWfU--wcczZ0dT-Ou8P87Bk9K9fjcn0PeaLoz3WTPepzNE\", \"dq\": \"kYw2u4_UmWvcXVOeV_VKJ5aQZkJ6_sxTpodRBMPyQmkMHKcW4eKU1mcJju_deqWadw5jGPPpm5yTXm5UkAwfOeookoWpGa7CvVf4kPNI6Aphn3GBjunJHNpPuU6w-wvomGsxd-NqQDGNYKHuFFMcyXO_zWXglQdP_1o1tJ1M-BM\", \"qi\": \"j94Ens784M8zsfwWoJhYq9prcSZOGgNbtFWQZO8HP8pcNM9ls7YA4snTtAS_B4peWWFAFZ0LSKPCxAvJnrq69ocmEKEk7ss1Jo062f9pLTQ6cnhMjev3IqLocIFt5Vbsg_PWYpFSR7re6FRbF9EYOM7F2-HRv1idxKCWoyQfBqk\" }"
rxresp
expect resp.http.x-decrypted == "Sed ut perspiciatis unde omnis iste natus error sit voluptatem doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. porro quisquam est, qui dolorem ipsum quia dolor sit amet, adipisci velit, sed quia non numquam eius modi tempora incidunt ut dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in voluptate velit esse quam nihil molestiae consequatur, vel illum qui eum fugiat quo voluptas nulla pariatur?"
} -run
@ -243,22 +199,3 @@ client c7 -connect ${h1_mainfe_sock} {
} -run
# Test 'jwt_decrypt_jwk' error cases
client c8 -connect ${h1_mainfe_sock} {
# Invalid 'oct' JWK
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiaXYiOiJzVE81QjlPRXFuaUhCX3dYIiwidGFnIjoid2M1ZnRpYUFnNGNOR1JkZzNWQ3FXdyJ9.2zqnM9zeNU-eAMp5h2uFJyxbHHKsZs9YAYKzOcIF3d3Q9uq1TMQAvqOIuXw3kU9o.hh5aObIoIMR6Ke0rXm6V1A.R7U-4OlqOR6f2C1b3nI5bFqZBIGNBgza7FfoPEgrQT8.asJCzUAHCuxS7o8Ut4ENfaY5RluLB35F" -hdr "X-JWK: {\"k\":\"invalid\",\"kty\":\"oct\"}"
rxresp
expect resp.http.x-decrypted == ""
# Wrong JWK type
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiJBMjU2R0NNS1ciLCJlbmMiOiJBMTkyQ0JDLUhTMzg0IiwiaXYiOiJzVE81QjlPRXFuaUhCX3dYIiwidGFnIjoid2M1ZnRpYUFnNGNOR1JkZzNWQ3FXdyJ9.2zqnM9zeNU-eAMp5h2uFJyxbHHKsZs9YAYKzOcIF3d3Q9uq1TMQAvqOIuXw3kU9o.hh5aObIoIMR6Ke0rXm6V1A.R7U-4OlqOR6f2C1b3nI5bFqZBIGNBgza7FfoPEgrQT8.asJCzUAHCuxS7o8Ut4ENfaY5RluLB35F" -hdr "X-JWK: {\"k\":\"invalid\",\"kty\":\"RSA\"}"
rxresp
expect resp.http.x-decrypted == ""
# Invalid 'RSA' JWK (truncated 'qi')
txreq -url "/jwk" -hdr "Authorization: Bearer eyJhbGciOiAiUlNBMV81IiwgImVuYyI6ICJBMjU2R0NNIn0.ew8AbprGcd_J73-CZPIsE1YonD9rtcL7VCuOOuVkrpS_9UzA9_kMh1yw20u-b5rKJAhmFMCQPXl44ro6IzOeHu8E2X_NlPEnQfyNVQ4R1HB_E9sSk5BLxOH3aHkVUh0I-e2eDDj-pdI3OrdjZtnZEBeQ7tpMcoBEbn1VGg7Pmw4qtdS-0qnDSs-PttU-cejjgPUNLRU8UdoRVC9uJKacJms110QugDuFuMYTTSU2nbIYh0deCMRAuKGWt0Ii6EMYW2JaJ7JfXag59Ar1uylQPyEVrocnOsDuB9xnp2jd796qCPdKxBK9yKUnwjal4SQpYbutr40QzG1S4MsKaUorLg.0el2ruY0mm2s7LUR.X5RI6dF06Y_dbAr8meb-6SG5enj5noto9nzgQU5HDrYdiUofPptIf6E-FikKUM9QR4pY9SyphqbPYeAN1ZYVxBrR8tUf4Do2kw1biuuRAmuIyytpmxwvY946T3ctu1Zw3Ymwe-jWXX08EngzssvzFOGT66gkdufrTkC45Fkr0RBOmWa5OVVg_VR6LwcivtQMmlArlrwbaDmmLqt_2p7afT0UksEz4loq0sskw-p7GbhB2lpzXoDnijdHrQkftRbVCiDbK4-qGr7IRFb0YOHvyVFr-kmDoJv2Zsg_rPKV1LkYmPJUbVDo9T3RAcLinlKPK4ZPC_2bWj3M9BvfOq1HeuyVWzX2Cb1mHFdxXFGqaLPfsE0VOfn0GqL7oHVbuczYYw2eKdmiw5LEMwuuJEdYDE9IIFEe8oRB4hNZ0XMYB6oqqZejD0Fh6nqlj5QUrTYpTSE-3LkgK2zRJ0oZFXZyHCB426bmViuE0mXF7twkQep09g0U35-jFBZcSYBDvZZL1t5d_YEQ0QtO0mEeEpGb0Pvk_EsSMFib7NxClz4_rdtwWCFuM4uFOS5vrQMiMqi_TadhLxrugRFhJpsibuScCiJ7eNDrUvwSWEwv1U593MUX3guDq_ONOo_49EOJSyRJtQCNC6FW6GLWSz9TCo6g5LCnXt-pqwu0Iymr7ZTQ3MTsdq2G55JM2e6SdG43iET8r235hynmXHKPUYHlSjsC2AEAY_pGDO0akIhf4wDVIM5rytn-rjQf-29ZJp05g6KPe-EaN1C-X7aBGhgAEgnX-iaXXbotpGeKRTNj2jAG1UrkYi6BGHxluiXJ8jH_LjHuxKyzIObqK8p28ePDKRL-jyNTrvGW2uorgb_u7HGmWYIWLTI7obnZ5vw3MbkjcwEd4bX5JXUj2rRsUWMlZSSFVO9Wgf7MBvcLsyF0Yqun3p0bi__edmcqNF_uuYZT-8jkUlMborqIDDCYYqIolgi5R1Bmut-gFYq6xyfEncxOi50xmYon50UulVnAH-up_RELGtCjmAivaJb8.upVY733IMAT8YbMab2PZnw" \
-hdr "X-JWK: { \"kty\": \"RSA\", \"e\": \"AQAB\", \"n\": \"wsqJbopx18NQFYLYOq4ZeMSE89yGiEankUpf25yV8QqroKUGrASj_OeqTWUjwPGKTN1vGFFuHYxiJeAUQH2qQPmg9Oqk6-ATBEKn9COKYniQ5459UxCwmZA2RL6ufhrNyq0JF3GfXkjLDBfhU9zJJEOhknsA0L_c-X4AI3d_NbFdMqxNe1V_UWAlLcbKdwO6iC9fAvwUmDQxgy6R0DC1CMouQpenMRcALaSHar1cm4K-syoNobv3HEuqgZ3s6-hOOSqauqAO0GUozPpaIA7OeruyRl5sTWT0r-iz39bchID2bIKtcqLiFcSYPLBcxmsaQCqRlGhmv6stjTCLV1yT9w\", \"kid\": \"ff3c5c96-392e-46ef-a839-6ff16027af78\", \"d\": \"b9hXfQ8lOtw8mX1dpqPcoElGhbczz_-xq2znCXQpbBPSZBUddZvchRSH5pSSKPEHlgb3CSGIdpLqsBCv0C_XmCM9ViN8uqsYgDO9uCLIDK5plWttbkqA_EufvW03R9UgIKWmOL3W4g4t-C2mBb8aByaGGVNjLnlb6i186uBsPGkvaeLHbQcRQKAvhOUTeNiyiiCbUGJwCm4avMiZrsz1r81Y1Z5izo0ERxdZymxM3FRZ9vjTB-6DtitvTXXnaAm1JTu6TIpj38u2mnNLkGMbflOpgelMNKBZVxSmfobIbFN8CHVc1UqLK2ElsZ9RCQANgkMHlMkOMj-XT0wHa3VBUQ\", \"p\": \"8mgriveKJAp1S7SHqirQAfZafxVuAK_A2QBYPsAUhikfBOvN0HtZjgurPXSJSdgR8KbWV7ZjdJM_eOivIb_XiuAaUdIOXbLRet7t9a_NJtmX9iybhoa9VOJFMBq_rbnbbte2kq0-FnXmv3cukbC2LaEw3aEcDgyURLCgWFqt7M0\", \"q\": \"zbbTv5421GowOfKVEuVoA35CEWgl8mdasnEZac2LWxMwKExikKU5LLacLQlcOt7A6n1ZGUC2wyH8mstO5tV34Eug3fnNrbnxFUEE_ZB_njs_rtZnwz57AoUXOXVnd194seIZF9PjdzZcuwXwXbrZ2RSVW8if_ZH5OVYEM1EsA9M\", \"dp\": \"1BaIYmIKn1X3InGlcSFcNRtSOnaJdFhRpotCqkRssKUx2qBlxs7ln_5dqLtZkx5VM_UE_GE7yzc6BZOwBxtOftdsr8HVh-14ksSR9rAGEsO2zVBiEuW4qZf_aQM-ScWfU--wcczZ0dT-Ou8P87Bk9K9fjcn0PeaLoz3WTPepzNE\", \"dq\": \"kYw2u4_UmWvcXVOeV_VKJ5aQZkJ6_sxTpodRBMPyQmkMHKcW4eKU1mcJju_deqWadw5jGPPpm5yTXm5UkAwfOeookoWpGa7CvVf4kPNI6Aphn3GBjunJHNpPuU6w-wvomGsxd-NqQDGNYKHuFFMcyXO_zWXglQdP_1o1tJ1M-BM\", \"qi\": \"j94Ens784M8zsfwWoJhYq9prcSZOGgNbtFWQZO8HP8pcNM9ls7YA4snTtAS_B4peWWFAFZ0LSKPCxAvJnrq69ocmEKEk7ss1Jo062f9pLTQ6cnhMjev3IqLocIFt5\" }"
rxresp
expect resp.http.x-decrypted == ""
} -run

View file

@ -1,84 +0,0 @@
varnishtest "Add backend via cli"
feature ignore_unknown_macro
haproxy hsrv -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults
mode http
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
frontend fe
bind "fd@${fe}"
http-request return status 200
} -start
haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults
mode http
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
frontend fe
bind "fd@${feS}"
force-be-switch if { req.hdr("x-admin") "1" }
use_backend %[req.hdr(x-be)]
defaults def
defaults def_http
mode http
} -start
client c1 -connect ${h1_feS_sock} {
txreq -hdr "x-be: be"
rxresp
expect resp.status == 503
} -run
haproxy h1 -cli {
# non existent backend
send "experimental-mode on; add backend be from def"
expect ~ "Mode is required"
send "experimental-mode on; add backend be from def_http"
expect ~ "New backend registered."
send "add server be/srv ${hsrv_fe_addr}:${hsrv_fe_port}"
expect ~ "New server registered."
send "enable server be/srv"
expect ~ ".*"
}
client c1 -connect ${h1_feS_sock} {
txreq -hdr "x-be: be"
rxresp
expect resp.status == 503
txreq -hdr "x-be: be" -hdr "x-admin: 1"
rxresp
expect resp.status == 200
} -run
haproxy h1 -cli {
send "publish backend be"
expect ~ "Backend published."
}
client c1 -connect ${h1_feS_sock} {
txreq -hdr "x-be: be"
rxresp
expect resp.status == 200
} -run

View file

@ -51,7 +51,7 @@ haproxy h1 -cli {
# invalid load-balancing algo
send "add server other/s1 ${s1_addr}:${s1_port}"
expect ~ "backend 'other' uses a non dynamic load balancing method"
expect ~ "Backend must use a dynamic load balancing to support dynamic servers."
# invalid mux proto
send "add server other2/s1 ${s1_addr}:${s1_port} proto h2"

View file

@ -145,7 +145,7 @@ haproxy h1 -cli {
send "show ssl ca-file ${testdir}/certs/set_cafile_interCA1.crt:2"
expect !~ ".*SHA1 FingerPrint: 4FFF535278883264693CEA72C4FAD13F995D0098"
send "show ssl ca-file ${testdir}/certs/set_cafile_interCA1.crt:2"
expect ~ ".*SHA1 FingerPrint: 3D3D1D10AD74A8135F05A818E10E5FA91433954D|5F8DAE4B2099A09F9BDDAFD7E9D900F0CE49977C"
expect ~ ".*SHA1 FingerPrint: 3D3D1D10AD74A8135F05A818E10E5FA91433954D"
}
client c1 -connect ${h1_clearverifiedlst_sock} {

View file

@ -86,7 +86,9 @@ haproxy h1 -cli {
expect ~ "\\*${testdir}/certs/interCA2_crl_empty.pem"
send "show ssl crl-file \\*${testdir}/certs/interCA2_crl_empty.pem"
expect ~ "Revoked Certificates:\n.*Serial Number: 1008"
expect ~ "Revoked Certificates:"
send "show ssl crl-file \\*${testdir}/certs/interCA2_crl_empty.pem:1"
expect ~ "Serial Number: 1008"
}
# This connection should still succeed since the transaction was not committed

View file

@ -1,12 +1,10 @@
#!/bin/sh
DESTDIR=${DESTDIR:-${PWD}/../vtest/}
TMPDIR=${TMPDIR:-$(mktemp -d)}
set -eux
curl -fsSL https://github.com/vtest/VTest2/archive/main.tar.gz -o "${TMPDIR}/VTest.tar.gz"
mkdir -p "${TMPDIR}/vtest"
tar xvf ${TMPDIR}/VTest.tar.gz -C "${TMPDIR}/vtest" --strip-components=1
curl -fsSL https://github.com/vtest/VTest2/archive/main.tar.gz -o VTest.tar.gz
mkdir ../vtest
tar xvf VTest.tar.gz -C ../vtest --strip-components=1
# Special flags due to: https://github.com/vtest/VTest/issues/12
# Note: do not use "make -C ../vtest", otherwise MAKEFLAGS contains "w"
@ -15,7 +13,7 @@ tar xvf ${TMPDIR}/VTest.tar.gz -C "${TMPDIR}/vtest" --strip-components=1
# MFLAGS works on BSD but misses variable definitions on GNU Make.
# Better just avoid the -C and do the cd ourselves then.
cd "${TMPDIR}/vtest"
cd ../vtest
set +e
CPUS=${CPUS:-$(nproc 2>/dev/null)}
@ -30,6 +28,3 @@ if test -f /opt/homebrew/include/pcre2.h; then
else
make -j${CPUS} FLAGS="-O2 -s -Wall"
fi
mkdir -p "${DESTDIR}"
cp "${TMPDIR}/vtest/vtest" "${DESTDIR}"

View file

@ -659,20 +659,8 @@ void activity_count_runtime(uint32_t run_time)
if (!(_HA_ATOMIC_LOAD(&th_ctx->flags) & TH_FL_TASK_PROFILING)) {
if (unlikely((profiling & HA_PROF_TASKS_MASK) == HA_PROF_TASKS_ON ||
((profiling & HA_PROF_TASKS_MASK) == HA_PROF_TASKS_AON &&
swrate_avg(run_time, TIME_STATS_SAMPLES) >= up))) {
if (profiling & HA_PROF_TASKS_LOCK)
_HA_ATOMIC_OR(&th_ctx->flags, TH_FL_TASK_PROFILING_L);
else
_HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_TASK_PROFILING_L);
if (profiling & HA_PROF_TASKS_MEM)
_HA_ATOMIC_OR(&th_ctx->flags, TH_FL_TASK_PROFILING_M);
else
_HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_TASK_PROFILING_M);
swrate_avg(run_time, TIME_STATS_SAMPLES) >= up)))
_HA_ATOMIC_OR(&th_ctx->flags, TH_FL_TASK_PROFILING);
}
} else {
if (unlikely((profiling & HA_PROF_TASKS_MASK) == HA_PROF_TASKS_OFF ||
((profiling & HA_PROF_TASKS_MASK) == HA_PROF_TASKS_AOFF &&
@ -704,41 +692,26 @@ static int cfg_parse_prof_memory(char **args, int section_type, struct proxy *cu
}
#endif // USE_MEMORY_PROFILING
/* config parser for global "profiling.tasks", accepts "on", "off", 'auto",
* "lock", "no-lock", "memory", "no-memory".
*/
/* config parser for global "profiling.tasks", accepts "on" or "off" */
static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
int arg;
if (too_many_args(1, args, err, NULL))
return -1;
for (arg = 1; *args[arg]; arg++) {
if (strcmp(args[arg], "on") == 0) {
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON;
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
}
else if (strcmp(args[arg], "auto") == 0) {
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
}
else if (strcmp(args[arg], "off") == 0)
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF;
else if (strcmp(args[arg], "lock") == 0)
profiling |= HA_PROF_TASKS_LOCK;
else if (strcmp(args[arg], "no-lock") == 0)
profiling &= ~HA_PROF_TASKS_LOCK;
else if (strcmp(args[arg], "memory") == 0)
profiling |= HA_PROF_TASKS_MEM;
else if (strcmp(args[arg], "no-memory") == 0)
profiling &= ~HA_PROF_TASKS_MEM;
else
break;
if (strcmp(args[1], "on") == 0) {
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON;
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
}
/* either no arg or invalid arg */
if (arg == 1 || *args[arg]) {
memprintf(err, "'%s' expects a combination of either 'on', 'auto', 'off', 'lock', 'no-lock', 'memory', or 'no-memory', but got '%s'.", args[0], args[arg]);
else if (strcmp(args[1], "auto") == 0) {
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
}
else if (strcmp(args[1], "off") == 0)
profiling = (profiling & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF;
else {
memprintf(err, "'%s' expects either 'on', 'auto', or 'off' but got '%s'.", args[0], args[1]);
return -1;
}
return 0;
@ -747,8 +720,6 @@ static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *cur
/* parse a "set profiling" command. It always returns 1. */
static int cli_parse_set_profiling(char **args, char *payload, struct appctx *appctx, void *private)
{
int arg;
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
return 1;
@ -794,66 +765,52 @@ static int cli_parse_set_profiling(char **args, char *payload, struct appctx *ap
if (strcmp(args[2], "tasks") != 0)
return cli_err(appctx, "Expects either 'tasks' or 'memory'.\n");
for (arg = 3; *args[arg]; arg++) {
if (strcmp(args[arg], "on") == 0) {
unsigned int old = profiling;
int i;
if (strcmp(args[3], "on") == 0) {
unsigned int old = profiling;
int i;
while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON))
;
while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_ON))
;
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
/* also flush current profiling stats */
for (i = 0; i < SCHED_ACT_HASH_BUCKETS; i++) {
HA_ATOMIC_STORE(&sched_activity[i].calls, 0);
HA_ATOMIC_STORE(&sched_activity[i].cpu_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lat_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lkw_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lkd_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].mem_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].func, NULL);
HA_ATOMIC_STORE(&sched_activity[i].caller, NULL);
}
/* also flush current profiling stats */
for (i = 0; i < SCHED_ACT_HASH_BUCKETS; i++) {
HA_ATOMIC_STORE(&sched_activity[i].calls, 0);
HA_ATOMIC_STORE(&sched_activity[i].cpu_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lat_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lkw_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].lkd_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].mem_time, 0);
HA_ATOMIC_STORE(&sched_activity[i].func, NULL);
HA_ATOMIC_STORE(&sched_activity[i].caller, NULL);
}
else if (strcmp(args[arg], "auto") == 0) {
unsigned int old = profiling;
unsigned int new;
do {
if ((old & HA_PROF_TASKS_MASK) >= HA_PROF_TASKS_AON)
new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AON;
else
new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
} while (!_HA_ATOMIC_CAS(&profiling, &old, new));
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
}
else if (strcmp(args[arg], "off") == 0) {
unsigned int old = profiling;
while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF))
;
if (HA_ATOMIC_LOAD(&prof_task_start_ns))
HA_ATOMIC_STORE(&prof_task_stop_ns, now_ns);
}
else if (strcmp(args[arg], "lock") == 0)
HA_ATOMIC_OR(&profiling, HA_PROF_TASKS_LOCK);
else if (strcmp(args[arg], "no-lock") == 0)
HA_ATOMIC_AND(&profiling, ~HA_PROF_TASKS_LOCK);
else if (strcmp(args[arg], "memory") == 0)
HA_ATOMIC_OR(&profiling, HA_PROF_TASKS_MEM);
else if (strcmp(args[arg], "no-memory") == 0)
HA_ATOMIC_AND(&profiling, ~HA_PROF_TASKS_MEM);
else
break; // unknown arg
}
else if (strcmp(args[3], "auto") == 0) {
unsigned int old = profiling;
unsigned int new;
/* either no arg or invalid one */
if (arg == 3 || *args[arg])
return cli_err(appctx, "Expects a combination of either 'on', 'auto', 'off', 'lock', 'no-lock', 'memory' or 'no-memory'.\n");
do {
if ((old & HA_PROF_TASKS_MASK) >= HA_PROF_TASKS_AON)
new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AON;
else
new = (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_AOFF;
} while (!_HA_ATOMIC_CAS(&profiling, &old, new));
HA_ATOMIC_STORE(&prof_task_start_ns, now_ns);
HA_ATOMIC_STORE(&prof_task_stop_ns, 0);
}
else if (strcmp(args[3], "off") == 0) {
unsigned int old = profiling;
while (!_HA_ATOMIC_CAS(&profiling, &old, (old & ~HA_PROF_TASKS_MASK) | HA_PROF_TASKS_OFF))
;
if (HA_ATOMIC_LOAD(&prof_task_start_ns))
HA_ATOMIC_STORE(&prof_task_stop_ns, now_ns);
}
else
return cli_err(appctx, "Expects 'on', 'auto', or 'off'.\n");
return 1;
}

View file

@ -848,12 +848,7 @@ struct task *task_run_applet(struct task *t, void *context, unsigned int state)
input = applet_output_data(app);
output = co_data(oc);
/* Don't call I/O handler if the applet was shut (release callback was
* already called)
*/
if (!se_fl_test(app->sedesc, SE_FL_SHR | SE_FL_SHW))
app->applet->fct(app);
app->applet->fct(app);
TRACE_POINT(APPLET_EV_PROCESS, app);
@ -950,11 +945,7 @@ struct task *task_process_applet(struct task *t, void *context, unsigned int sta
applet_need_more_data(app);
applet_have_no_more_data(app);
/* Don't call I/O handler if the applet was shut (release callback was
* already called)
*/
if (!applet_fl_test(app, APPCTX_FL_SHUTDOWN))
app->applet->fct(app);
app->applet->fct(app);
TRACE_POINT(APPLET_EV_PROCESS, app);

View file

@ -59,7 +59,6 @@
#include <haproxy/task.h>
#include <haproxy/ticks.h>
#include <haproxy/time.h>
#include <haproxy/tools.h>
#include <haproxy/trace.h>
#define TRACE_SOURCE &trace_strm
@ -577,20 +576,9 @@ struct server *get_server_rnd(struct stream *s, const struct server *avoid)
/* compare the new server to the previous best choice and pick
* the one with the least currently served requests.
*/
if (prev && prev != curr) {
uint64_t wcurr = (uint64_t)curr->served * prev->cur_eweight;
uint64_t wprev = (uint64_t)prev->served * curr->cur_eweight;
if (wcurr > wprev)
curr = prev;
else if (wcurr == wprev && curr->counters.shared.tg && prev->counters.shared.tg) {
/* same load: pick the lowest weighted request rate */
wcurr = read_freq_ctr_period_estimate(&curr->counters._sess_per_sec, MS_TO_TICKS(1000));
wprev = read_freq_ctr_period_estimate(&prev->counters._sess_per_sec, MS_TO_TICKS(1000));
if (wprev * curr->cur_eweight < wcurr * prev->cur_eweight)
curr = prev;
}
}
if (prev && prev != curr &&
curr->served * prev->cur_eweight > prev->served * curr->cur_eweight)
curr = prev;
} while (--draws > 0);
/* if the selected server is full, pretend we have none so that we reach
@ -3056,27 +3044,6 @@ int be_downtime(struct proxy *px) {
return ns_to_sec(now_ns) - px->last_change + px->down_time;
}
/* Checks if <px> backend supports the addition of servers at runtime. Either a
* backend or a defaults proxy are supported. If proxy is incompatible, <msg>
* will be allocated to contain a textual explaination.
*/
int be_supports_dynamic_srv(struct proxy *px, char **msg)
{
if (px->lbprm.algo && !(px->lbprm.algo & BE_LB_PROP_DYN)) {
memprintf(msg, "%s '%s' uses a non dynamic load balancing method",
proxy_cap_str(px->cap), px->id);
return 0;
}
if (px->mode == PR_MODE_SYSLOG) {
memprintf(msg, "%s '%s' uses mode log",
proxy_cap_str(px->cap), px->id);
return 0;
}
return 1;
}
/*
* This function returns a string containing the balancing
* mode of the proxy in a format suitable for stats.

View file

@ -501,10 +501,84 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
curproxy->conf.file_prev = file_prev;
curproxy->conf.line_prev = line_prev;
if (curr_defproxy) {
err_code = proxy_ref_defaults(curproxy, curr_defproxy, &errmsg);
if (err_code)
ha_alert("parsing [%s:%d]: %s.\n", file, linenum, errmsg);
if (curr_defproxy && (!LIST_ISEMPTY(&curr_defproxy->http_req_rules) ||
!LIST_ISEMPTY(&curr_defproxy->http_res_rules) ||
!LIST_ISEMPTY(&curr_defproxy->http_after_res_rules) ||
!LIST_ISEMPTY(&curr_defproxy->tcp_req.l4_rules) ||
!LIST_ISEMPTY(&curr_defproxy->tcp_req.l5_rules) ||
!LIST_ISEMPTY(&curr_defproxy->tcp_req.inspect_rules) ||
!LIST_ISEMPTY(&curr_defproxy->tcp_rep.inspect_rules))) {
/* If the current default proxy defines TCP/HTTP rules, the
* current proxy will keep a reference on it. But some sanity
* checks are performed first:
*
* - It cannot be used to init a defaults section
* - It cannot be used to init a listen section
* - It cannot be used to init backend and frontend sections at
* same time. It can be used to init several sections of the
* same type only.
* - It cannot define L4/L5 TCP rules if it is used to init
* backend sections.
* - It cannot define 'tcp-response content' rules if it
* is used to init frontend sections.
*
* If no error is found, refcount of the default proxy is incremented.
*/
/* Note: Add tcpcheck_rules too if unresolve args become allowed in defaults section */
if (rc & PR_CAP_DEF) {
ha_alert("parsing [%s:%d]: a defaults section cannot inherit from a defaults section defining TCP/HTTP rules (defaults section at %s:%d).\n",
file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line);
err_code |= ERR_ALERT | ERR_ABORT;
}
else if ((rc & PR_CAP_LISTEN) == PR_CAP_LISTEN) {
ha_alert("parsing [%s:%d]: a listen section cannot inherit from a defaults section defining TCP/HTTP rules.\n",
file, linenum);
err_code |= ERR_ALERT | ERR_ABORT;
}
else {
char defcap = (curr_defproxy->cap & PR_CAP_LISTEN);
if ((defcap == PR_CAP_BE || defcap == PR_CAP_FE) && (rc & PR_CAP_LISTEN) != defcap) {
ha_alert("parsing [%s:%d]: frontends and backends cannot inherit from the same defaults section"
" if it defines TCP/HTTP rules (defaults section at %s:%d).\n",
file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line);
err_code |= ERR_ALERT | ERR_ABORT;
}
else if (!(rc & PR_CAP_FE) && (!LIST_ISEMPTY(&curr_defproxy->tcp_req.l4_rules) ||
!LIST_ISEMPTY(&curr_defproxy->tcp_req.l5_rules))) {
ha_alert("parsing [%s:%d]: a backend section cannot inherit from a defaults section defining"
" 'tcp-request connection' or 'tcp-request session' rules (defaults section at %s:%d).\n",
file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line);
err_code |= ERR_ALERT | ERR_ABORT;
}
else if (!(rc & PR_CAP_BE) && !LIST_ISEMPTY(&curr_defproxy->tcp_rep.inspect_rules)) {
ha_alert("parsing [%s:%d]: a frontend section cannot inherit from a defaults section defining"
" 'tcp-response content' rules (defaults section at %s:%d).\n",
file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line);
err_code |= ERR_ALERT | ERR_ABORT;
}
else {
curr_defproxy->cap = (curr_defproxy->cap & ~PR_CAP_LISTEN) | (rc & PR_CAP_LISTEN);
proxy_ref_defaults(curproxy, curr_defproxy);
}
}
}
if (curr_defproxy && (curr_defproxy->tcpcheck_rules.flags & TCPCHK_RULES_PROTO_CHK) &&
(curproxy->cap & PR_CAP_LISTEN) == PR_CAP_BE) {
/* If the current default proxy defines tcpcheck rules, the
* current proxy will keep a reference on it. but only if the
* current proxy has the backend capability.
*/
proxy_ref_defaults(curproxy, curr_defproxy);
}
if ((rc & PR_CAP_BE) && curr_defproxy && (curr_defproxy->nb_req_cap || curr_defproxy->nb_rsp_cap)) {
ha_alert("parsing [%s:%d]: backend or defaults sections cannot inherit from a defaults section defining"
" capptures (defaults section at %s:%d).\n",
file, linenum, curr_defproxy->conf.file, curr_defproxy->conf.line);
err_code |= ERR_ALERT | ERR_ABORT;
}
if (rc & PR_CAP_DEF) {
@ -633,32 +707,23 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
goto out;
}
else if (strcmp(args[0], "mode") == 0) { /* sets the proxy mode */
enum pr_mode mode;
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
if (unlikely(strcmp(args[1], "health") == 0)) {
if (strcmp(args[1], "http") == 0) curproxy->mode = PR_MODE_HTTP;
else if (strcmp(args[1], "tcp") == 0) curproxy->mode = PR_MODE_TCP;
else if (strcmp(args[1], "log") == 0 && (curproxy->cap & PR_CAP_BE)) curproxy->mode = PR_MODE_SYSLOG;
else if (strcmp(args[1], "spop") == 0 && (curproxy->cap & PR_CAP_BE)) curproxy->mode = PR_MODE_SPOP;
else if (strcmp(args[1], "health") == 0) {
ha_alert("parsing [%s:%d] : 'mode health' doesn't exist anymore. Please use 'http-request return status 200' instead.\n", file, linenum);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
mode = str_to_proxy_mode(args[1]);
if (!mode) {
else {
ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
else if ((mode == PR_MODE_SYSLOG || mode == PR_MODE_SPOP) &&
!(curproxy->cap & PR_CAP_BE)) {
ha_alert("parsing [%s:%d] : mode %s is only applicable on proxies with backend capability.\n", file, linenum, proxy_mode_str(mode));
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
curproxy->mode = mode;
if (curproxy->cap & PR_CAP_DEF)
curproxy->flags |= PR_FL_DEF_EXPLICIT_MODE;
}
else if (strcmp(args[0], "id") == 0) {
struct proxy *conflict;

View file

@ -496,36 +496,6 @@ static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *
}
#endif
/* Allow to explicitely disable certificate compression when set to "off" */
#ifdef SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
static int ssl_parse_certificate_compression(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
if (too_many_args(1, args, err, NULL))
return -1;
if (strcmp(args[1], "auto") == 0)
global_ssl.certificate_compression = 1;
else if (strcmp(args[1], "off") == 0)
global_ssl.certificate_compression = 0;
else {
memprintf(err, "'%s' expects either 'auto' or 'off' but got '%s'.", args[0], args[1]); return -1;
}
return 0;
}
#else
static int ssl_parse_certificate_compression(char **args, int section_type, struct proxy *curpx,
const struct proxy *defpx, const char *file, int line,
char **err)
{
memprintf(err, "'%s' is not supported by your TLS library. "
"It is known to work only with OpenSSL >= 3.2.0.", args[0]);
return -1;
}
#endif
/* parse "ssl.force-private-cache".
* Returns <0 on alert, >0 on warning, 0 on success.
*/
@ -973,7 +943,7 @@ static int ssl_bind_parse_ktls(char **args, int cur_arg, struct proxy *px, struc
return ERR_ALERT | ERR_FATAL;
}
if (!experimental_directives_allowed) {
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'", args[cur_arg]);
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directive'", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
if (!strcasecmp(args[cur_arg + 1], "on")) {
@ -2050,7 +2020,7 @@ static int srv_parse_ktls(char **args, int *cur_arg, struct proxy *px, struct se
}
if (!experimental_directives_allowed) {
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'", args[*cur_arg]);
memprintf(err, "'%s' directive is experimental, must be allowed via a global 'expose-experimental-directive'", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
@ -2789,7 +2759,6 @@ static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "ssl-security-level", ssl_parse_security_level },
{ CFG_GLOBAL, "ssl-skip-self-issued-ca", ssl_parse_skip_self_issued_ca },
{ CFG_GLOBAL, "tune.ssl.cachesize", ssl_parse_global_int },
{ CFG_GLOBAL, "tune.ssl.certificate-compression", ssl_parse_certificate_compression },
{ CFG_GLOBAL, "tune.ssl.default-dh-param", ssl_parse_global_default_dh },
{ CFG_GLOBAL, "tune.ssl.force-private-cache", ssl_parse_global_private_cache },
{ CFG_GLOBAL, "tune.ssl.lifetime", ssl_parse_global_lifetime },

File diff suppressed because it is too large Load diff

View file

@ -686,10 +686,7 @@ int _cmp_cluster_avg_capa(const void *a, const void *b)
{
const struct ha_cpu_cluster *l = (const struct ha_cpu_cluster *)a;
const struct ha_cpu_cluster *r = (const struct ha_cpu_cluster *)b;
if (!r->nb_cores || !l->nb_cores)
return r->nb_cores - l->nb_cores;
return r->capa * l->nb_cores - l->capa * r->nb_cores;
return r->capa - l->capa;
}
/* re-order a cluster array by cluster index only */
@ -1672,7 +1669,7 @@ static int cpu_policy_performance(int policy, int tmin, int tmax, int gmin, int
capa = 0;
for (cluster = 0; cluster < cpu_topo_maxcpus; cluster++) {
if (capa && ha_cpu_clusters[cluster].capa * 10 < ha_cpu_clusters[cluster].nb_cores * capa * 8) {
if (capa && ha_cpu_clusters[cluster].capa * 10 < ha_cpu_clusters[cluster].nb_cpu * capa * 8) {
/* This cluster is made of cores delivering less than
* 80% of the performance of those of the previous
* cluster, previous one, we're not interested in
@ -1683,8 +1680,8 @@ static int cpu_policy_performance(int policy, int tmin, int tmax, int gmin, int
ha_cpu_topo[cpu].st |= HA_CPU_F_IGNORED;
}
}
else if (ha_cpu_clusters[cluster].nb_cores)
capa = ha_cpu_clusters[cluster].capa / ha_cpu_clusters[cluster].nb_cores;
else if (ha_cpu_clusters[cluster].nb_cpu)
capa = ha_cpu_clusters[cluster].capa / ha_cpu_clusters[cluster].nb_cpu;
else
capa = 0;
}
@ -1717,7 +1714,7 @@ static int cpu_policy_efficiency(int policy, int tmin, int tmax, int gmin, int g
capa = 0;
for (cluster = cpu_topo_maxcpus - 1; cluster >= 0; cluster--) {
if (capa && ha_cpu_clusters[cluster].capa * 8 >= ha_cpu_clusters[cluster].nb_cores * capa * 10) {
if (capa && ha_cpu_clusters[cluster].capa * 8 >= ha_cpu_clusters[cluster].nb_cpu * capa * 10) {
/* This cluster is made of cores each at last 25% faster
* than those of the previous cluster, previous one, we're
* not interested in using it.
@ -1727,8 +1724,8 @@ static int cpu_policy_efficiency(int policy, int tmin, int tmax, int gmin, int g
ha_cpu_topo[cpu].st |= HA_CPU_F_IGNORED;
}
}
else if (ha_cpu_clusters[cluster].nb_cores)
capa = ha_cpu_clusters[cluster].capa / ha_cpu_clusters[cluster].nb_cores;
else if (ha_cpu_clusters[cluster].nb_cpu)
capa = ha_cpu_clusters[cluster].capa / ha_cpu_clusters[cluster].nb_cpu;
else
capa = 0;
}

View file

@ -724,42 +724,14 @@ static size_t h1_parse_full_contig_chunks(struct h1m *h1m, struct htx **dsthtx,
break;
}
else if (likely(end[ridx] == ';')) {
int backslash = 0;
int quote = 0;
/* chunk extension, ends at next CRLF */
if (!++ridx)
goto end_parsing;
/* The loop seeks the first CRLF or non-tab CTL char
* and stops there. If a backslash/quote is active,
* it's an error. If none, we assume it's the CRLF
* and go back to the top of the loop checking for
* CR then LF. This way CTLs, lone LF etc are handled
* in the fallback path. This allows to protect
* remotes against their own possibly non-compliant
* chunk-ext parser which could mistakenly skip a
* quoted CRLF. Chunk-ext are not used anyway, except
* by attacks.
*/
while (!HTTP_IS_CTL(end[ridx]) || HTTP_IS_SPHT(end[ridx])) {
if (backslash)
backslash = 0; // escaped char
else if (end[ridx] == '\\' && quote)
backslash = 1;
else if (end[ridx] == '\\') // backslash not permitted outside quotes
goto parsing_error;
else if (end[ridx] == '"') // begin/end of quoted-pair
quote = !quote;
while (!HTTP_IS_CRLF(end[ridx])) {
if (!++ridx)
goto end_parsing;
}
/* mismatched quotes / backslashes end here */
if (quote || backslash)
goto parsing_error;
/* CTLs (CRLF) fall to the common check */
/* we have a CRLF now, loop above */
continue;
}
else {

View file

@ -205,7 +205,6 @@ struct global global = {
#endif
/* by default allow clients which use a privileged port for TCP only */
.clt_privileged_ports = HA_PROTO_TCP,
.maxthrpertgroup = MAX_THREADS_PER_GROUP,
/* others NULL OK */
};
@ -604,48 +603,6 @@ void display_version()
}
}
/* compare a feature string, ignoring the first character (-/+)
used for qsort */
static int feat_cmp(const void *a, const void *b)
{
const struct ist *ia = a;
const struct ist *ib = b;
struct ist sa = istadv(*ia, 1);
struct ist sb = istadv(*ib, 1);
return istdiff(sa, sb);
}
/* split the feature list into an allocated sorted array of ist
the return ptr must be freed by the caller */
static struct ist *split_feature_list()
{
struct ist *out;
struct ist tmp = ist(build_features);
int n = 1; /* last element don't have a ' ' */
int i = 0;
for (i = 0; build_features[i] != '\0'; i++) {
if (build_features[i] == ' ')
n++;
}
out = calloc(n + 1, sizeof(*out)); // last elem is NULL
if (!out)
goto end;
i = 0;
while (tmp.len)
out[i++] = istsplit(&tmp, ' ');
qsort(out, n, sizeof(struct ist), feat_cmp);
end:
return out;
}
/* display_mode:
* 0 = short version (e.g., "3.3.1")
* 1 = full version (e.g., "3.3.1-dev5-1bb975-71")
@ -685,23 +642,14 @@ void display_version_plain(int display_mode)
static void display_build_opts()
{
const char **opt;
struct ist *feat_list = NULL, *tmp;
feat_list = split_feature_list();
printf("Build options : %s", build_opts_string);
printf("\n\nFeature list :");
for (tmp = feat_list;tmp->ptr;tmp++)
if (!isttest(istist(*tmp, ist("HAVE_WORKING_"))))
printf(" %.*s", (int)tmp->len, tmp->ptr);
printf("\nDetected feature list :");
for (tmp = feat_list;tmp->ptr;tmp++)
if (isttest(istist(*tmp, ist("HAVE_WORKING_"))))
printf(" %.*s", (int)tmp->len, tmp->ptr);
printf("\n\nDefault settings :"
printf("Build options : %s"
"\n\nFeature list : %s"
"\n\nDefault settings :"
"\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
"\n\n",
BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
build_opts_string,
build_features, BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
for (opt = NULL; (opt = hap_get_next_build_opt(opt)); puts(*opt))
;
@ -720,7 +668,6 @@ static void display_build_opts()
putchar('\n');
list_filters(stdout);
putchar('\n');
ha_free(&feat_list);
}
/*
@ -1488,15 +1435,11 @@ static void init_early(int argc, char **argv)
len = strlen(progname);
progname = strdup(progname);
if (!progname) {
ha_alert("Cannot allocate memory for progname.\n");
ha_alert("Cannot allocate memory for log_tag.\n");
exit(EXIT_FAILURE);
}
chunk_initlen(&global.log_tag, strdup(progname), len, len);
if (b_orig(&global.log_tag) == NULL) {
ha_alert("Cannot allocate memory for log_tag.\n");
exit(EXIT_FAILURE);
}
}
/* handles program arguments. Very minimal parsing is performed, variables are
@ -2975,11 +2918,9 @@ void run_poll_loop()
if (thread_has_tasks())
activity[tid].wake_tasks++;
else {
unsigned int flags = _HA_ATOMIC_LOAD(&th_ctx->flags);
while (unlikely(!HA_ATOMIC_CAS(&th_ctx->flags, &flags, (flags | TH_FL_SLEEPING) & ~TH_FL_NOTIFIED)))
__ha_cpu_relax();
_HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
_HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
__ha_barrier_atomic_store();
if (thread_has_tasks()) {
activity[tid].wake_tasks++;
_HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);

View file

@ -273,7 +273,6 @@ static const char *hlua_tostring_safe(lua_State *L, int index)
break;
default:
/* error was caught */
lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
return NULL;
}
return str;
@ -324,7 +323,6 @@ static const char *hlua_pushvfstring_safe(lua_State *L, const char *fmt, va_list
break;
default:
/* error was caught */
lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
dst = NULL;
}
va_end(cpy_argp);
@ -872,7 +870,6 @@ void hlua_unref(lua_State *L, int ref)
__LJMP static int _hlua_traceback(lua_State *L)
{
lua_Debug *ar = lua_touserdata(L, 1);
int ret;
/* Fill fields:
* 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
@ -880,10 +877,7 @@ __LJMP static int _hlua_traceback(lua_State *L)
* 'n': fills in the field name and namewhat;
* 't': fills in the field istailcall;
*/
ret = lua_getinfo(L, "Slnt", ar);
if (!ret)
WILL_LJMP(luaL_error(L, "unexpected"));
return 0;
return lua_getinfo(L, "Slnt", ar);
}
@ -902,11 +896,10 @@ const char *hlua_traceback(lua_State *L, const char* sep)
lua_pushlightuserdata(L, &ar);
/* safe getinfo */
switch (lua_pcall(L, 1, 0, 0)) {
switch (lua_pcall(L, 1, 1, 0)) {
case LUA_OK:
break;
default:
lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
goto end; // abort
}
@ -1005,7 +998,6 @@ static int hlua_pusherror(lua_State *L, const char *fmt, ...)
case LUA_OK:
break;
default:
lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
ret = 0;
}
@ -10196,7 +10188,6 @@ static int hlua_new_event_sub_safe(lua_State *L, struct event_hdl_sub *sub)
return 1;
default:
/* error was caught */
lua_pop(L, 1); // consume the lua object pushed on the stack since we ignore it
return 0;
}
}

View file

@ -960,12 +960,6 @@ static enum act_parse_ret parse_http_req_capture(const char **args, int *orig_ar
hdr->namelen = 0;
hdr->len = len;
hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
if (!hdr->pool) {
memprintf(err, "out of memory");
free(hdr);
release_sample_expr(expr);
return ACT_RET_PRS_ERR;
}
hdr->index = px->nb_req_cap++;
px->req_cap = hdr;

584
src/jwe.c
View file

@ -652,20 +652,33 @@ end:
}
/*
* Decrypt the content of <cek> buffer into <decrypted_cek> buffer thanks to the
* private key <pkey> using algorithm <crypt_alg> (RSA).
* Returns 0 in case of success, 1 otherwise.
*/
static int do_decrypt_cek_rsa(struct buffer *cek, struct buffer *decrypted_cek,
EVP_PKEY *pkey, jwe_alg crypt_alg)
static int decrypt_cek_rsa(struct buffer *cek, struct buffer *decrypted_cek,
struct buffer *cert, jwe_alg crypt_alg)
{
EVP_PKEY_CTX *ctx = NULL;
const EVP_MD *md = NULL;
int retval = 1;
EVP_PKEY *pkey = NULL;
int retval = 0;
int pad = 0;
size_t outl = b_size(decrypted_cek);
struct ckch_store *store = NULL;
if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
goto end;
store = ckchs_lookup(b_orig(cert));
if (!store || !store->data->key || !store->conf.jwt) {
HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
goto end;
}
pkey = store->data->key;
EVP_PKEY_up_ref(pkey);
HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
switch(crypt_alg) {
case JWE_ALG_RSA1_5:
pad = RSA_PKCS1_PADDING;
@ -708,48 +721,10 @@ static int do_decrypt_cek_rsa(struct buffer *cek, struct buffer *decrypted_cek,
decrypted_cek->data = outl;
retval = 0;
retval = 1;
end:
EVP_PKEY_CTX_free(ctx);
return retval;
}
/*
* Look for <cert> in the ckch_store tree and use its private key to decrypt
* <cek> into <decrypted_cek> using <crypt_alg> algorithm (of the RSA alg
* family).
* Returns 0 in case of success, 1 otherwise.
*/
static int decrypt_cek_rsa(struct buffer *cek, struct buffer *decrypted_cek,
struct buffer *cert, jwe_alg crypt_alg)
{
EVP_PKEY *pkey = NULL;
int retval = 1;
struct ckch_store *store = NULL;
if (HA_SPIN_TRYLOCK(CKCH_LOCK, &ckch_lock))
goto end;
store = ckchs_lookup(b_orig(cert));
if (!store || !store->data->key || !store->conf.jwt) {
HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
goto end;
}
pkey = store->data->key;
EVP_PKEY_up_ref(pkey);
HA_SPIN_UNLOCK(CKCH_LOCK, &ckch_lock);
if (do_decrypt_cek_rsa(cek, decrypted_cek, pkey, crypt_alg))
goto end;
retval = 0;
end:
EVP_PKEY_free(pkey);
return retval;
}
@ -846,7 +821,7 @@ static int sample_conv_jwt_decrypt_cert(const struct arg *args, struct sample *s
}
(*cek)->data = size;
if (rsa && decrypt_cek_rsa(*cek, decrypted_cek, cert, alg))
if (rsa && !decrypt_cek_rsa(*cek, decrypted_cek, cert, alg))
goto end;
if (decrypt_ciphertext(enc, items, decoded_items, decrypted_cek, &out))
@ -919,522 +894,11 @@ static int sample_conv_jwt_decrypt_secret_check(struct arg *args, struct sample_
}
/*
* Convert a base64url encoded buffer into a BIGNUM.
*/
static BIGNUM *base64url_to_BIGNUM(struct buffer *b64url_buf)
{
BIGNUM *bn = NULL;
struct buffer *decoded = get_trash_chunk();
int size = 0;
if (!b64url_buf)
return NULL;
size = base64urldec(b_orig(b64url_buf), b_data(b64url_buf),
b_orig(decoded), b_size(decoded));
if (size < 0)
return NULL;
decoded->data = size;
bn = BN_bin2bn((const unsigned char *)b_orig(decoded), b_data(decoded), NULL);
return bn;
}
/*
* Extract a field named <field> of type string out of the <jwk> JSON buffer and
* dump its value in <out>.
* Return 0 in case of success, 1 in case of error (JSON parsing error or value
* not found).
*/
static int get_jwk_field(struct buffer *jwk, const char *field, struct buffer *out)
{
int size = 0;
chunk_reset(out);
size = mjson_get_string(b_orig(jwk), b_data(jwk), field,
b_orig(out), b_size(out));
if (size == -1)
return 1;
out->data = size;
return 0;
}
enum {
RSA_BIGNUM_N,
RSA_BIGNUM_E,
RSA_BIGNUM_D,
RSA_BIGNUM_P,
RSA_BIGNUM_Q,
RSA_BIGNUM_DP,
RSA_BIGNUM_DQ,
RSA_BIGNUM_QI,
RSA_BIGNUM_COUNT
};
/*
* Build the EVP_PKEY out of the BIGNUMs parsed by the caller.
* The RSA_set0_ functions were deprecated in OpenSSL3, hence the two different
* code blocks.
* Returns 0 in case of success, 1 otherwise.
*/
static int do_build_RSA_PKEY(BIGNUM *nums[RSA_BIGNUM_COUNT], EVP_PKEY **pkey)
#if HA_OPENSSL_VERSION_NUMBER >= 0x30000000L
{
int retval = 1;
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *param_bld = NULL;
EVP_PKEY_CTX *pctx = NULL;
param_bld = OSSL_PARAM_BLD_new();
if (!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, nums[RSA_BIGNUM_N]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, nums[RSA_BIGNUM_E]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, nums[RSA_BIGNUM_D]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR1, nums[RSA_BIGNUM_P]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_FACTOR2, nums[RSA_BIGNUM_Q]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT1, nums[RSA_BIGNUM_DP]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_EXPONENT2, nums[RSA_BIGNUM_DQ]) ||
!OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, nums[RSA_BIGNUM_QI]))
goto end;
params = OSSL_PARAM_BLD_to_param(param_bld);
if (!params)
goto end;
pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
if (!pctx)
goto end;
if (EVP_PKEY_fromdata_init(pctx) != 1)
goto end;
if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_KEYPAIR, params) != 1)
goto end;
retval = 0;
end:
OSSL_PARAM_BLD_free(param_bld);
OSSL_PARAM_free(params);
EVP_PKEY_CTX_free(pctx);
return retval;
}
#else /* HA_OPENSSL_VERSION_NUMBER < 0x30000000L */
{
int retval = 1;
RSA *rsa = NULL;
rsa = RSA_new();
if (!rsa)
goto end;
if (RSA_set0_key(rsa, nums[RSA_BIGNUM_N], nums[RSA_BIGNUM_E], nums[RSA_BIGNUM_D]) != 1 ||
RSA_set0_factors(rsa, nums[RSA_BIGNUM_P], nums[RSA_BIGNUM_Q]) != 1 ||
RSA_set0_crt_params(rsa, nums[RSA_BIGNUM_DP], nums[RSA_BIGNUM_DQ], nums[RSA_BIGNUM_QI]) != 1)
goto end;
*pkey = EVP_PKEY_new();
if (!*pkey)
goto end;
if (EVP_PKEY_set1_RSA(*pkey, rsa) != 1)
goto end;
retval = 0;
end:
RSA_free(rsa);
return retval;
}
#endif
static inline void clear_bignums(BIGNUM *nums[RSA_BIGNUM_COUNT])
{
int idx = 0;
while (idx < RSA_BIGNUM_COUNT)
BN_free(nums[idx++]);
}
/*
* Build an EVP_PKEY that contains an RSA private key out of a JWK buffer that
* must have an "RSA" key type ("kty" field).
* Return 0 in case of success, 1 otherwise.
*/
static int build_RSA_PKEY_from_buf(struct buffer *jwk, EVP_PKEY **pkey)
{
BIGNUM *nums[RSA_BIGNUM_COUNT] = {};
int retval = 1;
struct buffer *tmpbuf = alloc_trash_chunk();
if (!tmpbuf)
goto end;
/*
* Extract all the mandatory fields that all represent BIGNUMs out of
* the JWK buffer.
*/
if (get_jwk_field(jwk, "$.n", tmpbuf) || (nums[RSA_BIGNUM_N] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.e", tmpbuf) || (nums[RSA_BIGNUM_E] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.d", tmpbuf) || (nums[RSA_BIGNUM_D] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.p", tmpbuf) || (nums[RSA_BIGNUM_P] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.q", tmpbuf) || (nums[RSA_BIGNUM_Q] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.dp", tmpbuf) || (nums[RSA_BIGNUM_DP] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.dq", tmpbuf) || (nums[RSA_BIGNUM_DQ] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
if (get_jwk_field(jwk, "$.qi", tmpbuf) || (nums[RSA_BIGNUM_QI] = base64url_to_BIGNUM(tmpbuf)) == NULL)
goto end;
retval = do_build_RSA_PKEY(nums, pkey);
end:
/* The bignums are duplicated with OpenSSL3+ but not with the older API */
#if HA_OPENSSL_VERSION_NUMBER >= 0x30000000L
clear_bignums(nums);
#else
if (retval)
clear_bignums(nums);
#endif
free_trash_chunk(tmpbuf);
if (retval) {
EVP_PKEY_free(*pkey);
*pkey = NULL;
}
return retval;
}
typedef enum {
JWK_KTY_OCT,
JWK_KTY_RSA,
// JWK_KTY_EC
} jwk_type;
struct jwk {
jwk_type type;
struct buffer *kid;
union {
EVP_PKEY *pkey;
struct buffer *secret;
};
};
static void clear_jwk(struct jwk *jwk)
{
if (!jwk)
return;
free_trash_chunk(jwk->kid);
jwk->kid = NULL;
switch (jwk->type) {
case JWK_KTY_OCT:
free_trash_chunk(jwk->secret);
jwk->secret = NULL;
break;
case JWK_KTY_RSA:
EVP_PKEY_free(jwk->pkey);
jwk->pkey = NULL;
break;
default:
break;
}
}
/*
* Convert a JWK in buffer <jwk_buf> into either an RSA private key stored in an
* EVP_PKEY or a secret (for symmetric algorithms).
* Returns 0 in case of success, 1 otherwise.
*/
static int process_jwk(struct buffer *jwk_buf, struct jwk *jwk)
{
struct buffer *kty = NULL;
int retval = 1;
kty = get_trash_chunk();
if (get_jwk_field(jwk_buf, "$.kty", kty))
goto end;
/* Look for optional "kid" field */
jwk->kid = alloc_trash_chunk();
if (!jwk->kid)
goto end;
get_jwk_field(jwk_buf, "$.kid", jwk->kid);
if (chunk_strcmp(kty, "oct") == 0) {
struct buffer *tmpbuf = get_trash_chunk();
int size = 0;
jwk->type = JWK_KTY_OCT;
jwk->secret = alloc_trash_chunk();
if (!jwk->secret)
goto end;
if (get_jwk_field(jwk_buf, "$.k", tmpbuf))
goto end;
size = base64urldec(b_orig(tmpbuf), b_data(tmpbuf),
b_orig(jwk->secret), b_size(jwk->secret));
if (size < 0) {
goto end;
}
jwk->secret->data = size;
} else if (chunk_strcmp(kty, "RSA") == 0) {
jwk->type = JWK_KTY_RSA;
if (build_RSA_PKEY_from_buf(jwk_buf, &jwk->pkey))
goto end;
} else
goto end;
retval = 0;
end:
if (retval)
clear_jwk(jwk);
return retval;
}
static int sample_conv_jwt_decrypt_jwk_check(struct arg *args, struct sample_conv *conv,
const char *file, int line, char **err)
{
vars_check_arg(&args[0], NULL);
if (args[0].type == ARGT_STR) {
EVP_PKEY *pkey = NULL;
struct buffer *trash = get_trash_chunk();
if (get_jwk_field(&args[0].data.str, "$.kty", trash) == 0) {
if (chunk_strcmp(trash, "oct") == 0) {
struct buffer *key = get_trash_chunk();
if (get_jwk_field(&args[0].data.str, "$.k", key)) {
memprintf(err, "Missing 'k' field in JWK");
return 0;
}
} else if (chunk_strcmp(trash, "RSA") == 0) {
if (build_RSA_PKEY_from_buf(&args[0].data.str, &pkey)) {
memprintf(err, "Failed to parse JWK");
return 0;
}
EVP_PKEY_free(pkey);
} else {
memprintf(err, "Unmanaged key type (expected 'oct' or 'RSA'");
return 0;
}
} else {
memprintf(err, "Missing key type (expected 'oct' or 'RSA')");
return 0;
}
}
return 1;
}
/*
* Decrypt the contents of a JWE token thanks to the user-provided JWK that can
* either contain an RSA private key or a secret.
* Returns the decrypted contents, or nothing if any error happened.
*/
static int sample_conv_jwt_decrypt_jwk(const struct arg *args, struct sample *smp, void *private)
{
struct buffer *input = NULL;
unsigned int item_num = JWE_ELT_MAX;
struct sample jwk_smp;
struct jwt_item items[JWE_ELT_MAX] = {};
struct buffer *decoded_items[JWE_ELT_MAX] = {};
jwe_alg alg = JWE_ALG_UNMANAGED;
jwe_enc enc = JWE_ENC_UNMANAGED;
int size = 0;
int rsa = 0;
int dir = 0;
int gcm = 0;
int oct = 0;
int retval = 0;
struct buffer **cek = NULL;
struct buffer *decrypted_cek = NULL;
struct buffer *out = NULL;
struct jose_fields fields = {};
struct buffer *alg_tag = NULL;
struct buffer *alg_iv = NULL;
struct buffer *jwk_buf = NULL;
struct jwk jwk = {};
smp_set_owner(&jwk_smp, smp->px, smp->sess, smp->strm, smp->opt);
if (!sample_conv_var2smp_str(&args[0], &jwk_smp))
goto end;
/* Copy JWK parameter */
jwk_buf = alloc_trash_chunk();
if (!jwk_buf)
goto end;
if (!chunk_cpy(jwk_buf, &jwk_smp.data.u.str))
goto end;
/* Copy JWE input token */
input = alloc_trash_chunk();
if (!input)
goto end;
if (!chunk_cpy(input, &smp->data.u.str))
goto end;
if (jwt_tokenize(input, items, &item_num) || item_num != JWE_ELT_MAX)
goto end;
alg_tag = alloc_trash_chunk();
if (!alg_tag)
goto end;
alg_iv = alloc_trash_chunk();
if (!alg_iv)
goto end;
fields.tag = alg_tag;
fields.iv = alg_iv;
/* Base64Url decode the JOSE header */
decoded_items[JWE_ELT_JOSE] = alloc_trash_chunk();
if (!decoded_items[JWE_ELT_JOSE])
goto end;
size = base64urldec(items[JWE_ELT_JOSE].start, items[JWE_ELT_JOSE].length,
b_orig(decoded_items[JWE_ELT_JOSE]), b_size(decoded_items[JWE_ELT_JOSE]));
if (size < 0)
goto end;
decoded_items[JWE_ELT_JOSE]->data = size;
if (!parse_jose(decoded_items[JWE_ELT_JOSE], &alg, &enc, &fields))
goto end;
/* Check if "alg" fits certificate-based JWEs */
switch (alg) {
case JWE_ALG_RSA1_5:
case JWE_ALG_RSA_OAEP:
case JWE_ALG_RSA_OAEP_256:
rsa = 1;
break;
case JWE_ALG_A128KW:
case JWE_ALG_A192KW:
case JWE_ALG_A256KW:
gcm = 0;
oct = 1;
break;
case JWE_ALG_A128GCMKW:
case JWE_ALG_A192GCMKW:
case JWE_ALG_A256GCMKW:
gcm = 1;
oct = 1;
break;
case JWE_ALG_DIR:
dir = 1;
oct = 1;
break;
default:
/* Not managed yet */
goto end;
}
/* Parse JWK argument. */
if (process_jwk(jwk_buf, &jwk))
goto end;
/* Check that the provided JWK is of the proper type */
if ((oct && jwk.type != JWK_KTY_OCT) ||
(rsa && jwk.type != JWK_KTY_RSA))
goto end;
if (dir) {
/* The secret given as parameter should be used directly to
* decode the encrypted content. */
decrypted_cek = alloc_trash_chunk();
if (!decrypted_cek)
goto end;
chunk_memcpy(decrypted_cek, b_orig(jwk.secret), b_data(jwk.secret));
} else {
/* With algorithms other than "dir" we should always have a CEK */
if (!items[JWE_ELT_CEK].length)
goto end;
cek = &decoded_items[JWE_ELT_CEK];
*cek = alloc_trash_chunk();
if (!*cek)
goto end;
decrypted_cek = alloc_trash_chunk();
if (!decrypted_cek) {
goto end;
}
size = base64urldec(items[JWE_ELT_CEK].start, items[JWE_ELT_CEK].length,
(*cek)->area, (*cek)->size);
if (size < 0) {
goto end;
}
(*cek)->data = size;
if (rsa) {
if (do_decrypt_cek_rsa(*cek, decrypted_cek, jwk.pkey, alg))
goto end;
} else {
if (gcm) {
if (!decrypt_cek_aesgcmkw(*cek, alg_tag, alg_iv, decrypted_cek, jwk.secret, alg))
goto end;
} else {
if (!decrypt_cek_aeskw(*cek, decrypted_cek, jwk.secret, alg))
goto end;
}
}
}
if (decrypt_ciphertext(enc, items, decoded_items, decrypted_cek, &out))
goto end;
smp->data.u.str.data = b_data(out);
smp->data.u.str.area = b_orig(out);
smp->data.type = SMP_T_BIN;
smp_dup(smp);
retval = 1;
end:
clear_jwk(&jwk);
free_trash_chunk(jwk_buf);
free_trash_chunk(input);
free_trash_chunk(decrypted_cek);
free_trash_chunk(out);
free_trash_chunk(alg_tag);
free_trash_chunk(alg_iv);
clear_decoded_items(decoded_items);
return retval;
}
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
/* JSON Web Token converters */
{ "jwt_decrypt_secret", sample_conv_jwt_decrypt_secret, ARG1(1,STR), sample_conv_jwt_decrypt_secret_check, SMP_T_BIN, SMP_T_BIN },
{ "jwt_decrypt_cert", sample_conv_jwt_decrypt_cert, ARG1(1,STR), sample_conv_jwt_decrypt_cert_check, SMP_T_BIN, SMP_T_BIN },
{ "jwt_decrypt_jwk", sample_conv_jwt_decrypt_jwk, ARG1(1,STR), sample_conv_jwt_decrypt_jwk_check, SMP_T_BIN, SMP_T_BIN },
{ "jwt_decrypt_cert", sample_conv_jwt_decrypt_cert, ARG1(1,STR), sample_conv_jwt_decrypt_cert_check, SMP_T_BIN, SMP_T_BIN },
{ NULL, NULL, 0, 0, 0 },
}};

View file

@ -552,32 +552,6 @@ struct server *chash_get_next_server(struct proxy *p, struct server *srvtoavoid)
return srv;
}
/* Allocates and initializes lb nodes for server <srv>. Returns < 0 on error.
* This is called by chash_init_server_tree() as well as from srv_alloc_lb()
* for runtime addition.
*/
int chash_server_init(struct server *srv)
{
int node;
srv->lb_nodes = calloc(srv->lb_nodes_tot, sizeof(*srv->lb_nodes));
if (!srv->lb_nodes)
return -1;
srv->lb_server_key = chash_compute_server_key(srv);
for (node = 0; node < srv->lb_nodes_tot; node++) {
srv->lb_nodes[node].server = srv;
srv->lb_nodes[node].node.key = chash_compute_node_key(srv, node);
}
return 0;
}
/* Releases the allocated lb_nodes for this server */
void chash_server_deinit(struct server *srv)
{
ha_free(&srv->lb_nodes);
}
/* This function is responsible for building the active and backup trees for
* consistent hashing. The servers receive an array of initialized nodes
* with their assigned keys. It also sets p->lbprm.wdiv to the eweight to
@ -588,12 +562,11 @@ int chash_init_server_tree(struct proxy *p)
{
struct server *srv;
struct eb_root init_head = EB_ROOT;
int node;
p->lbprm.set_server_status_up = chash_set_server_status_up;
p->lbprm.set_server_status_down = chash_set_server_status_down;
p->lbprm.update_server_eweight = chash_update_server_weight;
p->lbprm.server_init = chash_server_init;
p->lbprm.server_deinit = chash_server_deinit;
p->lbprm.server_take_conn = NULL;
p->lbprm.server_drop_conn = NULL;
@ -615,11 +588,17 @@ int chash_init_server_tree(struct proxy *p)
srv->lb_tree = (srv->flags & SRV_F_BACKUP) ? &p->lbprm.chash.bck : &p->lbprm.chash.act;
srv->lb_nodes_tot = srv->uweight * BE_WEIGHT_SCALE;
srv->lb_nodes_now = 0;
if (chash_server_init(srv) < 0) {
srv->lb_nodes = calloc(srv->lb_nodes_tot,
sizeof(*srv->lb_nodes));
if (!srv->lb_nodes) {
ha_alert("failed to allocate lb_nodes for server %s.\n", srv->id);
return -1;
}
srv->lb_server_key = chash_compute_server_key(srv);
for (node = 0; node < srv->lb_nodes_tot; node++) {
srv->lb_nodes[node].server = srv;
srv->lb_nodes[node].node.key = chash_compute_node_key(srv, node);
}
if (srv_currently_usable(srv))
chash_queue_dequeue_srv(srv);

View file

@ -2488,10 +2488,8 @@ static size_t h1_make_reqline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
goto end;
type = htx_get_blk_type(blk);
sz = htx_get_blksz(blk);
if (type == HTX_BLK_UNUSED) {
htx_remove_blk(htx, blk);
if (type == HTX_BLK_UNUSED)
continue;
}
if (type != HTX_BLK_REQ_SL || sz > count)
goto error;
break;
@ -2579,10 +2577,8 @@ static size_t h1_make_stline(struct h1s *h1s, struct h1m *h1m, struct htx *htx,
type = htx_get_blk_type(blk);
sz = htx_get_blksz(blk);
if (type == HTX_BLK_UNUSED) {
htx_remove_blk(htx, blk);
if (type == HTX_BLK_UNUSED)
continue;
}
if (type != HTX_BLK_RES_SL || sz > count)
goto error;
break;

View file

@ -652,8 +652,8 @@ static int sample_conv_tcp_win(const struct arg *arg_p, struct sample *smp, void
/* Builds a binary fingerprint of the IP+TCP input contents that are supposed
* to rely essentially on the client stack's settings. This can be used for
* example to selectively block bad behaviors at one IP address without
* blocking others. The resulting fingerprint is a binary block of 64 to 384
* bits long (64 being the fixed part and the rest depending on the provided
* blocking others. The resulting fingerprint is a binary block of 56 to 376
* bytes long (56 being the fixed part and the rest depending on the provided
* TCP extensions).
*/
static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *private)
@ -668,7 +668,6 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
uchar tcpflags;
uchar tcplen;
uchar tcpws;
uchar opts;
ushort pktlen;
ushort tcpwin;
ushort tcpmss;
@ -720,8 +719,8 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
else
return 0;
/* prepare trash to contain at least 8 bytes */
trash->data = 8;
/* prepare trash to contain at least 7 bytes */
trash->data = 7;
/* store the TOS in the FP's first byte */
trash->area[0] = iptos;
@ -764,11 +763,9 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
(tcpflags >> 6 << 0); // CWR, ECE
tcpmss = tcpws = 0;
opts = 0;
ofs = 20;
while (ofs < tcplen) {
size_t next;
uchar opt;
if (smp->data.u.str.area[ofs] == 0) // kind0=end of options
break;
@ -785,24 +782,17 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
break;
/* option is complete, take a copy of it */
opt = smp->data.u.str.area[ofs];
if (mode & 2) // mode & 2: append tcp.options_list
trash->area[trash->data++] = opt;
trash->area[trash->data++] = smp->data.u.str.area[ofs];
if (opt == 2 /* MSS */) {
if (smp->data.u.str.area[ofs] == 2 /* MSS */) {
tcpmss = read_n16(smp->data.u.str.area + ofs + 2);
}
else if (opt == 3 /* WS */) {
else if (smp->data.u.str.area[ofs] == 3 /* WS */) {
tcpws = (uchar)smp->data.u.str.area[ofs + 2];
/* output from 1 to 15, thus 0=not found */
tcpws = tcpws > 14 ? 15 : tcpws + 1;
}
/* keep a presence mask of opts 2..8 and others */
if (opt >= 2)
opts |= 1 << (opt < 9 ? opt - 2 : 7);
ofs = next;
}
@ -813,9 +803,6 @@ static int sample_conv_ip_fp(const struct arg *arg_p, struct sample *smp, void *
write_n16(trash->area + 3, tcpwin);
write_n16(trash->area + 5, tcpmss);
/* the the bit mask of present options */
trash->area[7] = opts;
/* mode 4: append source IP address */
if (mode & 4) {
iplen = (ipver == 4) ? 4 : 16;

View file

@ -302,7 +302,7 @@ static int mem_should_fail(const struct pool_head *pool)
* registration struct. Use create_pool() instead which does it for free.
* The alignment will be stored as-is in the registration.
*/
struct pool_head *create_pool_with_loc(const char *name, ullong size,
struct pool_head *create_pool_with_loc(const char *name, unsigned int size,
unsigned int align, unsigned int flags,
const char *file, unsigned int line)
{
@ -335,8 +335,7 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
{
unsigned int extra_mark, extra_caller, extra;
unsigned int flags = reg->flags;
ullong reg_size = reg->size; // copy of the originally requested size
ullong size = reg_size;
unsigned int size = reg->size;
unsigned int alignment = reg->align;
struct pool_head *pool = NULL;
struct pool_head *entry;
@ -375,9 +374,6 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
extra_caller = (pool_debugging & POOL_DBG_CALLER) ? POOL_EXTRA_CALLER : 0;
extra = extra_mark + extra_caller;
if (size > 0xFFFFFFFFULL || (size + extra) > 0xFFFFFFFFULL || (uint)(size + extra) < (uint)reg_size)
goto ovf;
if (!(pool_debugging & POOL_DBG_NO_CACHE)) {
/* we'll store two lists there, we need the room for this. Let's
* make sure it's always OK even when including the extra word
@ -396,7 +392,7 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
*/
if (!(flags & MEM_F_EXACT)) {
align = (pool_debugging & POOL_DBG_TAG) ? sizeof(void *) : 16;
size = ((size + align - 1) & -(ullong)align);
size = ((size + align - 1) & -align);
}
if (pool_debugging & POOL_DBG_BACKUP) {
@ -406,9 +402,6 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
extra += size;
}
if (size > 0xFFFFFFFFULL || (size + extra) > 0xFFFFFFFFULL || (uint)(size + extra) < (uint)reg_size)
goto ovf;
/* TODO: thread: we do not lock pool list for now because all pools are
* created during HAProxy startup (so before threads creation) */
start = &pools;
@ -503,11 +496,6 @@ struct pool_head *create_pool_from_reg(const char *name, struct pool_registratio
fail:
return pool;
ovf:
ha_alert("Failed to create pool '%s' of size '%llu': overflow detected due to too large "
"a configured size and/or configured pool options. Aborting.\n",
name, reg_size);
return NULL;
}
/* Tries to allocate an object for the pool <pool> using the system's allocator
@ -806,8 +794,7 @@ void pool_put_to_cache(struct pool_head *pool, void *ptr, const void *caller)
if (unlikely(pool_cache_bytes > global.tune.pool_cache_size * 3 / 4)) {
uint64_t mem_wait_start = 0;
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)) ==
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)))
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING))
mem_wait_start = now_mono_time();
if (ph->count >= 16 + pool_cache_count / 8 + CONFIG_HAP_POOL_CLUSTER_SIZE)
@ -970,8 +957,7 @@ void pool_gc(struct pool_head *pool_ctx)
uint64_t mem_wait_start = 0;
int isolated = thread_isolated();
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)) ==
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)))
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING))
mem_wait_start = now_mono_time();
if (!isolated)
@ -1033,8 +1019,7 @@ void *__pool_alloc(struct pool_head *pool, unsigned int flags)
/* count allocation time only for cache misses */
uint64_t mem_wait_start = 0;
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)) ==
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)))
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING))
mem_wait_start = now_mono_time();
p = pool_alloc_nocache(pool, caller);
@ -1112,8 +1097,7 @@ void __pool_free(struct pool_head *pool, void *ptr)
global.tune.pool_cache_size < pool->size)) {
uint64_t mem_wait_start = 0;
if (unlikely((th_ctx->flags & (TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)) ==
(TH_FL_TASK_PROFILING|TH_FL_TASK_PROFILING_M)))
if (unlikely(th_ctx->flags & TH_FL_TASK_PROFILING))
mem_wait_start = now_mono_time();
pool_free_nocache(pool, ptr);
@ -1444,7 +1428,7 @@ int dump_pools_info(struct appctx *appctx)
struct pool_registration *reg;
list_for_each_entry(reg, &ctx->pool_info[i].entry->regs, list) {
chunk_appendf(&trash, " > %-12s: size=%llu flags=%#x align=%u", reg->name, reg->size, reg->flags, reg->align);
chunk_appendf(&trash, " > %-12s: size=%u flags=%#x align=%u", reg->name, reg->size, reg->flags, reg->align);
if (reg->file && reg->line)
chunk_appendf(&trash, " [%s:%u]", reg->file, reg->line);
chunk_appendf(&trash, "\n");
@ -1667,7 +1651,7 @@ void create_pool_callback(struct pool_head **ptr, char *name, struct pool_regist
{
*ptr = create_pool_from_reg(name, reg);
if (!*ptr) {
ha_alert("Failed to allocate pool '%s' of size %llu : %s. Aborting.\n",
ha_alert("Failed to allocate pool '%s' of size %u : %s. Aborting.\n",
name, reg->size, strerror(errno));
exit(1);
}

View file

@ -1028,32 +1028,7 @@ static int tcp_get_info(struct connection *conn, long long int *info, int info_n
static void __proto_tcp_init(void)
{
#if defined(__linux__) && defined(TCP_MD5SIG)
/* check if the setsockopt works to register a line in haproxy -vv */
struct sockaddr_in *addr;
int fd;
struct tcp_md5sig md5 = {};
addr = (struct sockaddr_in *)&md5.tcpm_addr;
addr->sin_family = AF_INET;
addr->sin_port = 0;
addr->sin_addr.s_addr = htonl(0x7F000001);
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
goto end;
}
md5.tcpm_keylen = strlcpy2((char*)md5.tcpm_key, "foobar", sizeof(md5.tcpm_key));
if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0) {
goto end;
}
hap_register_feature("HAVE_WORKING_TCP_MD5SIG");
end:
if (fd >= 0)
close(fd);
#if defined(__linux__) && !defined(TCP_MD5SIG)
hap_register_feature("HAVE_TCP_MD5SIG");
#endif
}

File diff suppressed because it is too large Load diff

View file

@ -105,8 +105,11 @@ unsigned int srv_dynamic_maxconn(const struct server *s)
{
unsigned int max;
if (s->minconn == s->maxconn || s->proxy->beconn >= s->proxy->fullconn)
/* static limit, or no fullconn or proxy is full */
if (s->proxy->beconn >= s->proxy->fullconn)
/* no fullconn or proxy is full */
max = s->maxconn;
else if (s->minconn == s->maxconn)
/* static limit */
max = s->maxconn;
else max = MAX(s->minconn,
s->proxy->beconn * s->maxconn / s->proxy->fullconn);

View file

@ -1166,12 +1166,7 @@ int qc_parse_frm(struct quic_frame *frm, struct quic_rx_packet *pkt,
goto leave;
}
if (!quic_dec_int(&frm->type, pos, end)) {
TRACE_ERROR("malformed frame type", QUIC_EV_CONN_PRSFRM, qc);
quic_set_connection_close(qc, quic_err_transport(QC_ERR_FRAME_ENCODING_ERROR));
goto leave;
}
quic_dec_int(&frm->type, pos, end);
if (!quic_frame_type_is_known(frm->type)) {
/* RFC 9000 12.4. Frames and Frame Types
*

View file

@ -359,7 +359,8 @@ leave:
}
/* Callback use to parse TLS messages for <ssl> TLS session. */
void quic_tls_compat_msg_callback(int write_p, int version, int content_type,
void quic_tls_compat_msg_callback(struct connection *conn,
int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl)
{
unsigned int alert;

View file

@ -1155,17 +1155,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
if (frm)
qc_frm_free(qc, &frm);
/* RFC 9002 6.2.3. Speeding up Handshake Completion
*
* To speed up handshake completion under these conditions, an endpoint
* MAY, for a limited number of times per connection, send a packet
* containing unacknowledged CRYPTO data earlier than the PTO expiry,
* subject to the address validation limits in Section 8.1 of [QUIC-
* TRANSPORT]. Doing so at most once for each connection is adequate to
* quickly recover from a single packet loss.
*/
if (fast_retrans && !(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP) &&
qc->iel && qc->hel) {
if (fast_retrans && qc->iel && qc->hel) {
struct quic_enc_level *iqel = qc->iel;
struct quic_enc_level *hqel = qc->hel;

View file

@ -129,11 +129,6 @@ int quic_token_check(struct quic_rx_packet *pkt,
goto err;
}
if (tokenlen != QUIC_TOKEN_LEN) {
TRACE_ERROR("invalid token length", QUIC_EV_CONN_LPKT, qc);
goto err;
}
/* Generate the AAD. */
aadlen = ipaddrcpy(aad, &dgram->saddr);
rand = token + tokenlen - QUIC_TOKEN_RAND_DLEN;

View file

@ -3184,6 +3184,7 @@ void srv_free_params(struct server *srv)
free(srv->cc_algo);
free(srv->tcp_md5sig);
free(srv->addr_key);
free(srv->lb_nodes);
counters_be_shared_drop(&srv->counters.shared);
if (srv->log_target) {
deinit_log_target(srv->log_target);
@ -5888,13 +5889,25 @@ static int cli_parse_enable_server(char **args, char *payload, struct appctx *ap
*/
static int srv_alloc_lb(struct server *sv, struct proxy *be)
{
int node;
sv->lb_tree = (sv->flags & SRV_F_BACKUP) ?
&be->lbprm.chash.bck : &be->lbprm.chash.act;
sv->lb_nodes_tot = sv->uweight * BE_WEIGHT_SCALE;
sv->lb_nodes_now = 0;
if (be->lbprm.server_init && be->lbprm.server_init(sv) < 0)
return 0; // typically out of memory
if (((be->lbprm.algo & (BE_LB_KIND | BE_LB_PARM)) == (BE_LB_KIND_RR | BE_LB_RR_RANDOM)) ||
((be->lbprm.algo & (BE_LB_KIND | BE_LB_HASH_TYPE)) == (BE_LB_KIND_HI | BE_LB_HASH_CONS))) {
sv->lb_nodes = calloc(sv->lb_nodes_tot, sizeof(*sv->lb_nodes));
if (!sv->lb_nodes)
return 0;
for (node = 0; node < sv->lb_nodes_tot; node++) {
sv->lb_nodes[node].server = sv;
sv->lb_nodes[node].node.key = full_hash(sv->puid * SRV_EWGHT_RANGE + node);
}
}
return 1;
}
@ -5918,11 +5931,10 @@ static struct task *server_warmup(struct task *t, void *context, unsigned int st
/* recalculate the weights and update the state */
server_recalc_eweight(s, 1);
HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
/* probably that we can refill this server with a bit more connections */
process_srv_queue(s);
HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock);
/* get back there in 1 second or 1/20th of the slowstart interval,
* whichever is greater, resulting in small 5% steps.
@ -6092,7 +6104,7 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
struct add_srv_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
struct proxy *be;
struct server *srv;
char *be_name, *sv_name, *errmsg;
char *be_name, *sv_name;
int errcode, argc;
int next_id;
const int parse_flags = SRV_PARSE_DYNAMIC|SRV_PARSE_PARSE_ADDR;
@ -6128,9 +6140,13 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
if (!be)
return cli_err(appctx, "No such backend.\n");
errmsg = NULL;
if (!be_supports_dynamic_srv(be, &errmsg)) {
cli_dynerr(appctx, memprintf(&errmsg, "Backend does not support dynamic servers : %s.\n", errmsg));
if (!(be->lbprm.algo & BE_LB_PROP_DYN)) {
cli_err(appctx, "Backend must use a dynamic load balancing to support dynamic servers.\n");
return 1;
}
if (be->mode == PR_MODE_SYSLOG) {
cli_err(appctx," Dynamic servers cannot be used with log backends.\n");
return 1;
}
@ -7400,9 +7416,10 @@ int srv_add_to_idle_list(struct server *srv, struct connection *conn, int is_saf
HA_SPIN_UNLOCK(IDLE_CONNS_LOCK, &idle_conns[tid].idle_conns_lock);
_HA_ATOMIC_INC(&srv->curr_idle_thr[tid]);
if (HA_ATOMIC_LOAD(&srv->idle_node.node.leaf_p) == NULL) {
__ha_barrier_full();
if ((volatile void *)srv->idle_node.node.leaf_p == NULL) {
HA_SPIN_LOCK(OTHER_LOCK, &idle_conn_srv_lock);
if (_HA_ATOMIC_LOAD(&srv->idle_node.node.leaf_p) == NULL) {
if ((volatile void *)srv->idle_node.node.leaf_p == NULL) {
srv->idle_node.key = tick_add(srv->pool_purge_delay,
now_ms);
eb32_insert(&idle_conn_srv, &srv->idle_node);

View file

@ -593,7 +593,7 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d
BIO *in = NULL;
int ret = 1;
EVP_PKEY *key = NULL;
struct passphrase_cb_data cb_data = { path, data, 0, 0 };
struct passphrase_cb_data cb_data = { path, data, 0 };
if (buf) {
/* reading from a buffer */
@ -625,13 +625,11 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d
*/
do {
key = PEM_read_bio_PrivateKey(in, NULL, ssl_sock_passwd_cb, &cb_data);
} while (!key && cb_data.passphrase_idx != -1 && cb_data.callback_called);
} while (!key && cb_data.passphrase_idx != -1);
if (key == NULL) {
unsigned long e = ERR_peek_last_error();
memprintf(err, "%sunable to load private key from file '%s' (%s).\n",
err && *err ? *err : "", path, ERR_error_string(e, NULL));
memprintf(err, "%sunable to load private key from file '%s'.\n",
err && *err ? *err : "", path);
goto end;
}
@ -669,7 +667,6 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
HASSL_DH *dh = NULL;
STACK_OF(X509) *chain = NULL;
struct issuer_chain *issuer_chain = NULL;
struct passphrase_cb_data cb_data = { path, data, 0, 0 };
if (buf) {
/* reading from a buffer */
@ -694,18 +691,8 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d
}
}
/* Read Private Key
* Since multiple private keys might have different passphrases that are
* stored in a local cache, we want to try all the already known
* passphrases first before raising an error. The passphrase_idx field
* of the cb_data parameter will be modified in the callback and set to
* -1 after the external passphrase tool is called.
*/
/* We don't know yet if the private key requires a password. */
data->encrypted_privkey = 0;
do {
key = PEM_read_bio_PrivateKey(in, NULL, ssl_sock_passwd_cb, &cb_data);
} while (!key && cb_data.passphrase_idx != -1 && cb_data.callback_called);
/* Read Private Key */
key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
/* no need to check for errors here, because the private key could be loaded later */
#ifndef OPENSSL_NO_DH
@ -1345,7 +1332,7 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
{
struct cafile_entry *dst = NULL;
X509_STORE *store = NULL;
STACK_OF(X509_OBJECT) *objs = NULL;
STACK_OF(X509_OBJECT) *objs;
int i;
if (!src)
@ -1357,7 +1344,7 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
if (!store)
goto err;
objs = X509_STORE_getX_objects(src->ca_store);
objs = X509_STORE_get0_objects(src->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
X509 *cert;
X509_CRL *crl;
@ -1385,11 +1372,10 @@ struct cafile_entry *ssl_store_dup_cafile_entry(struct cafile_entry *src)
}
}
dst = ssl_store_create_cafile_entry(src->path, store, src->type);
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return dst;
err:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
X509_STORE_free(store);
ha_free(&dst);
@ -1490,25 +1476,6 @@ end:
return retval;
}
/*
* return the default verify cert directory.
*
* It might provided by the SSL library or set in an environment variable
* (commonly SSL_CERT_DIR)
*/
const char *ha_default_cert_dir()
{
const char *dir = NULL;
const char *certdir_varname = X509_get_default_cert_dir_env();
if (certdir_varname)
dir = getenv(certdir_varname);
if (dir == NULL)
dir = X509_get_default_cert_dir();
return dir;
}
/*
* Try to load a ca-file from disk into the ca-file cache.
* <shuterror> allows you to to stop emitting the errors.
@ -1516,13 +1483,13 @@ const char *ha_default_cert_dir()
*/
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror)
{
STACK_OF(X509_OBJECT) *objs = NULL;
X509_STORE *store = ssl_store_get0_locations_file(path);
/* If this function is called by the CLI, we should not call the
* X509_STORE_load_locations function because it performs forbidden disk
* accesses. */
if (!store && create_if_none) {
STACK_OF(X509_OBJECT) *objs;
int cert_count = 0;
struct stat buf;
struct cafile_entry *ca_e;
@ -1538,7 +1505,7 @@ int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_
}
if (strcmp(path, "@system-ca") == 0) {
dir = ha_default_cert_dir();
dir = X509_get_default_cert_dir();
if (!dir) {
if (!shuterror)
ha_alert("Couldn't get the system CA directory from X509_get_default_cert_dir().\n");
@ -1627,7 +1594,7 @@ scandir_err:
}
}
objs = X509_STORE_getX_objects(store);
objs = X509_STORE_get0_objects(store);
cert_count = sk_X509_OBJECT_num(objs);
if (cert_count == 0) {
if (!shuterror)
@ -1641,11 +1608,9 @@ scandir_err:
}
ebst_insert(&cafile_tree, &ca_e->node);
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return (store != NULL);
err:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
X509_STORE_free(store);
store = NULL;
return 0;
@ -3816,7 +3781,7 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
struct buffer *out = alloc_trash_chunk();
int i = 0;
X509 *cert;
STACK_OF(X509_OBJECT) *objs = NULL;
STACK_OF(X509_OBJECT) *objs;
int retval = 0;
int ca_index = ctx->ca_index;
int show_all = ctx->show_all;
@ -3842,7 +3807,7 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
if (!cafile_entry->ca_store)
goto end;
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
for (i = ca_index; i < sk_X509_OBJECT_num(objs); i++) {
cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
@ -3865,16 +3830,13 @@ static int cli_io_handler_show_cafile_detail(struct appctx *appctx)
}
end:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1; /* end, don't come back */
end_no_putchk:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1;
yield:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
/* save the current state */
ctx->ca_index = i;
free_trash_chunk(out);
@ -3977,10 +3939,9 @@ static int get_certificate_count(struct cafile_entry *cafile_entry)
STACK_OF(X509_OBJECT) *objs;
if (cafile_entry && cafile_entry->ca_store) {
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
if (objs)
cert_count = sk_X509_OBJECT_num(objs);
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
}
return cert_count;
}
@ -4510,7 +4471,7 @@ static int cli_io_handler_show_crlfile_detail(struct appctx *appctx)
struct buffer *out = alloc_trash_chunk();
int i;
X509_CRL *crl;
STACK_OF(X509_OBJECT) *objs = NULL;
STACK_OF(X509_OBJECT) *objs;
int retval = 0;
int index = ctx->index;
@ -4535,7 +4496,7 @@ static int cli_io_handler_show_crlfile_detail(struct appctx *appctx)
if (!cafile_entry->ca_store)
goto end;
objs = X509_STORE_getX_objects(cafile_entry->ca_store);
objs = X509_STORE_get0_objects(cafile_entry->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
crl = X509_OBJECT_get0_X509_CRL(sk_X509_OBJECT_value(objs, i));
if (!crl)
@ -4558,11 +4519,9 @@ end:
goto yield;
end_no_putchk:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 1;
yield:
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
free_trash_chunk(out);
return 0; /* should come back */
}

View file

@ -152,9 +152,6 @@ struct global_ssl global_ssl = {
#endif
#ifdef HAVE_ACME
.acme_scheduler = 1,
#endif
#ifdef SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
.certificate_compression = 1,
#endif
.renegotiate = SSL_RENEGOTIATE_DFLT,
.passphrase_cmd = NULL,
@ -630,7 +627,7 @@ static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
if (store_ctx && store) {
int i;
X509_OBJECT *obj;
STACK_OF(X509_OBJECT) *objs = X509_STORE_getX_objects(store);
STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
obj = sk_X509_OBJECT_value(objs, i);
switch (X509_OBJECT_get_type(obj)) {
@ -644,7 +641,6 @@ static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
break;
}
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
return 1;
}
return 0;
@ -688,7 +684,7 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
skn = sk_X509_NAME_new_null();
/* take x509 from cafile_tree */
objs = X509_STORE_getX_objects(ca_e->ca_store);
objs = X509_STORE_get0_objects(ca_e->ca_store);
for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
x = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
if (!x)
@ -724,7 +720,6 @@ static STACK_OF(X509_NAME)* ssl_get_client_ca_file(char *path)
ca_name->xname = xn;
eb64_insert(&ca_name_tree, &ca_name->node);
}
sk_X509_OBJECT_popX_free(objs, X509_OBJECT_free);
ca_e->ca_list = skn;
/* remove temporary ca_name tree */
node = eb64_first(&ca_name_tree);
@ -801,16 +796,16 @@ static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
/* Dedicated callback functions for heartbeat and clienthello.
*/
#ifdef TLS1_RT_HEARTBEAT
static void ssl_sock_parse_heartbeat(int write_p, int version,
static void ssl_sock_parse_heartbeat(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl);
#endif
static void ssl_sock_parse_clienthello(int write_p, int version,
static void ssl_sock_parse_clienthello(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl);
#ifdef HAVE_SSL_KEYLOG
static void ssl_init_keylog(int write_p, int version,
static void ssl_init_keylog(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl);
#endif
@ -1801,23 +1796,18 @@ int ssl_sock_bind_verifycbk(int ok, X509_STORE_CTX *x_store)
}
#ifdef TLS1_RT_HEARTBEAT
static void ssl_sock_parse_heartbeat(int write_p, int version,
static void ssl_sock_parse_heartbeat(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl)
{
/* test heartbeat received (write_p is set to 0
for a received record) */
if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
struct connection *conn = ssl_sock_get_conn(ssl, NULL);
struct ssl_sock_ctx *ctx = NULL;
struct ssl_sock_ctx *ctx = __conn_get_ssl_sock_ctx(conn);
const unsigned char *p = buf;
unsigned int payload;
/* <conn> may be NULL in QUIC context */
if (conn) {
ctx = __conn_get_ssl_sock_ctx(conn);
ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
}
ctx->xprt_st |= SSL_SOCK_RECV_HEARTBEAT;
/* Check if this is a CVE-2014-0160 exploitation attempt. */
if (*p != TLS1_HB_REQUEST)
@ -1848,7 +1838,7 @@ static void ssl_sock_parse_heartbeat(int write_p, int version,
}
#endif
static void ssl_sock_parse_clienthello(int write_p, int version,
static void ssl_sock_parse_clienthello(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl)
{
@ -2142,7 +2132,7 @@ static void ssl_sock_parse_clienthello(int write_p, int version,
#ifdef HAVE_SSL_KEYLOG
static void ssl_init_keylog(int write_p, int version,
static void ssl_init_keylog(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl)
{
@ -2165,13 +2155,20 @@ static void ssl_init_keylog(int write_p, int version,
/* Callback is called for ssl protocol analyse */
static __maybe_unused void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
{
struct connection *conn = ssl_sock_get_conn(ssl, NULL);
struct ssl_sock_msg_callback *cbk;
/* The connection be NULL only for QUIC which does not free its SSL object
* as this done for TCP.
*/
if (!conn)
return;
/* Try to call all callback functions that were registered by using
* ssl_sock_register_msg_callback().
*/
list_for_each_entry(cbk, &ssl_sock_msg_callbacks, list) {
cbk->func(write_p, version, content_type, buf, len, ssl);
cbk->func(conn, write_p, version, content_type, buf, len, ssl);
}
}
@ -3816,8 +3813,6 @@ int ssl_sock_passwd_cb(char *buf, int size, int rwflag, void *userdata)
if (!data || data->passphrase_idx == -1)
return -1;
data->callback_called = 1;
ckch_data = data->ckch_data;
if (ckch_data)
@ -3825,7 +3820,7 @@ int ssl_sock_passwd_cb(char *buf, int size, int rwflag, void *userdata)
if (!global_ssl.passphrase_cmd) {
data->passphrase_idx = -1;
ha_alert("Trying to load a passphrase-protected private key without an 'ssl-passphrase-cmd' defined.\n");
ha_alert("Trying to load a passphrase-protected private key without an 'ssl-passphrase-cmd' defined.");
return -1;
}
@ -3837,16 +3832,13 @@ int ssl_sock_passwd_cb(char *buf, int size, int rwflag, void *userdata)
global_ssl.passphrase_cmd[1] = strdup(data->path);
if (!global_ssl.passphrase_cmd[1]) {
data->passphrase_idx = -1;
ha_alert("ssl_sock_passwd_cb: allocation failure\n");
return -1;
}
if (!passphrase_cache)
if (ssl_sock_create_passphrase_cache()) {
data->passphrase_idx = -1;
if (ssl_sock_create_passphrase_cache())
return -1;
}
/* Try all the already known passphrases first. */
if (data->passphrase_idx < passphrase_idx) {
@ -4082,11 +4074,6 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf)
options |= SSL_OP_NO_RENEGOTIATION;
#endif
#ifdef SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
if (global_ssl.certificate_compression == 0)
options |= SSL_OP_NO_RX_CERTIFICATE_COMPRESSION | SSL_OP_NO_TX_CERTIFICATE_COMPRESSION;
#endif
SSL_CTX_set_options(ctx, options);
#ifdef SSL_MODE_ASYNC
@ -5140,11 +5127,6 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
options &= ~SSL_OP_NO_RENEGOTIATION;
#endif
#ifdef SSL_OP_NO_RX_CERTIFICATE_COMPRESSION
if (global_ssl.certificate_compression == 0)
options |= SSL_OP_NO_RX_CERTIFICATE_COMPRESSION | SSL_OP_NO_TX_CERTIFICATE_COMPRESSION;
#endif
SSL_CTX_set_options(ctx, options);
#ifdef SSL_MODE_ASYNC
@ -8554,7 +8536,6 @@ static void ssl_register_build_options()
#if defined(USE_OPENSSL) && (HA_OPENSSL_VERSION_NUMBER < 0x3000000fL)
memprintf(&ptr, "%s\nSSL library FIPS mode : %s", ptr, FIPS_mode() ? "yes" : "no");
#endif
memprintf(&ptr, "%s\nSSL library default verify directory : %s", ptr, ha_default_cert_dir());
memprintf(&ptr, "%s\nSSL library supports :", ptr);
for (i = CONF_TLSV_MIN; i <= CONF_TLSV_MAX; i++)
if (methodVersions[i].option)

View file

@ -5968,9 +5968,7 @@ static void stkt_late_init(void)
f = find_sample_fetch("src", strlen("src"));
if (f)
smp_fetch_src = f->process;
if (stkt_create_stk_ctr_pool() & (ERR_ABORT | ERR_FATAL))
exit(1); // error already reported by the function
stkt_create_stk_ctr_pool();
for (i = 0; i < CONFIG_HAP_TBL_BUCKETS; i++) {
MT_LIST_INIT(&per_bucket[i].toadd_tables);

View file

@ -970,12 +970,6 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type,
hdr->namelen = 0;
hdr->len = len;
hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
if (!hdr->pool) {
memprintf(err, "parsing [%s:%d] : out of memory", file, line);
free(hdr);
release_sample_expr(expr);
return -1;
}
hdr->index = curpx->nb_req_cap++;
curpx->req_cap = hdr;

View file

@ -4943,35 +4943,6 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
"01" /* COM_QUIT command */
};
/* MySQL >=8.0 client Authentication packet with CLIENT_PLUGIN_AUTH capability.
* MySQL 8.0 changed the default authentication plugin from mysql_native_password
* to caching_sha2_password. By setting CLIENT_PLUGIN_AUTH and specifying
* mysql_native_password as the auth plugin, we can still perform health checks
* against MySQL 8.x servers when the health check user is configured with
* mysql_native_password authentication.
*
* Client capabilities: 0x00088200 (little-endian: 00820800)
* - CLIENT_PROTOCOL_41 (0x00000200)
* - CLIENT_SECURE_CONNECTION (0x00008000)
* - CLIENT_PLUGIN_AUTH (0x00080000)
*/
static char mysql80_rsname[] = "*mysql80-check";
static char mysql80_req[] = {
"%[var(check.header),hex]" /* 3 bytes for the packet length and 1 byte for the sequence ID */
"00820800" /* client capabilities with CLIENT_PLUGIN_AUTH */
"00800001" /* max packet */
"21" /* character set (UTF-8) */
"000000000000000000000000" /* 23 bytes, all zeroes */
"0000000000000000000000"
"%[var(check.username),hex]00" /* the username */
"00" /* auth response length (0 = no password) */
"6d7973716c5f6e61746976655f" /* auth plugin name: "mysql_native_password\0" */
"70617373776f726400"
"010000" /* packet length */
"00" /* sequence ID */
"01" /* COM_QUIT command */
};
struct tcpcheck_ruleset *rs = NULL;
struct tcpcheck_rules *rules = &curpx->tcpcheck_rules;
struct tcpcheck_rule *chk;
@ -5028,14 +4999,8 @@ int proxy_parse_mysql_check_opt(char **args, int cur_arg, struct proxy *curpx, c
mysql_req = mysql40_req;
mysql_rsname = mysql40_rsname;
}
else if (strcmp(args[cur_arg+2], "post-80") == 0) {
/* post-80: CLIENT_PLUGIN_AUTH + mysql_native_password (22 bytes) */
packetlen = userlen + 7 + 27 + 22;
mysql_req = mysql80_req;
mysql_rsname = mysql80_rsname;
}
else {
ha_alert("parsing [%s:%d] : keyword '%s' only supports 'post-41', 'pre-41' and 'post-80' (got '%s').\n",
ha_alert("parsing [%s:%d] : keyword '%s' only supports 'post-41' and 'pre-41' (got '%s').\n",
file, line, args[cur_arg], args[cur_arg+2]);
goto error;
}

View file

@ -1394,12 +1394,6 @@ int thread_map_to_groups()
for (g = 0; g < global.nbtgroups; g++) {
if (!ha_tgroup_info[g].count)
ug++;
else {
if (ha_tgroup_info[g].count > global.maxthrpertgroup) {
ha_alert("thread-group %d assigned too many threads (%d, max=%d)\n", g, ha_tgroup_info[g].count, global.maxthrpertgroup);
return -1;
}
}
ha_tgroup_info[g].tgid_bit = 1UL << g;
}
@ -1647,6 +1641,9 @@ void thread_detect_count(void)
if (global.nbtgroups)
grp_min = grp_max = global.nbtgroups;
if (!global.maxthrpertgroup)
global.maxthrpertgroup = MAX_THREADS_PER_GROUP;
#if defined(USE_THREAD)
/* Adjust to boot settings if not forced */
if (thr_min <= thread_cpus_enabled_at_boot && thread_cpus_enabled_at_boot < thr_max)
@ -2141,6 +2138,11 @@ static int cfg_parse_thread_group(char **args, int section_type, struct proxy *c
return -1;
}
if (ha_tgroup_info[tgroup-1].count > global.maxthrpertgroup) {
memprintf(err, "'%s %ld' assigned too many threads (%d, max=%d)", args[0], tgroup, tot, global.maxthrpertgroup);
return -1;
}
return 0;
}

View file

@ -987,11 +987,6 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
int new_fd = -1;
enum proto_type proto_type = 0; // to shut gcc warning
int ctrl_type = 0; // to shut gcc warning
/*
* Indicates that we want to use an alternate protocol instead of the
* default one.
* Currently, only MPTCP is defined as an alternate protocol for TCP
*/
int alt_proto = 0;
portl = porth = porta = 0;
@ -1016,6 +1011,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
((opts & (PA_O_STREAM|PA_O_DGRAM)) == (PA_O_DGRAM|PA_O_STREAM) && (opts & PA_O_DEFAULT_DGRAM))) {
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
} else {
proto_type = PROTO_TYPE_STREAM;
ctrl_type = SOCK_STREAM;
@ -1030,6 +1026,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
str2 += 6;
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
}
else if (strncmp(str2, "quic+", 5) == 0) {
str2 += 5;
@ -1046,6 +1043,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
ss.ss_family = AF_UNIX;
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
}
else if (strncmp(str2, "uxst@", 5) == 0) {
str2 += 5;
@ -1091,6 +1089,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
ss.ss_family = AF_INET;
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
}
else if (strncmp(str2, "tcp6@", 5) == 0) {
str2 += 5;
@ -1110,6 +1109,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
ss.ss_family = AF_INET6;
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
}
else if (strncmp(str2, "tcp@", 4) == 0) {
str2 += 4;
@ -1129,6 +1129,7 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
ss.ss_family = AF_UNSPEC;
proto_type = PROTO_TYPE_DGRAM;
ctrl_type = SOCK_DGRAM;
alt_proto = 1;
}
else if (strncmp(str2, "quic4@", 6) == 0) {
str2 += 6;
@ -1398,8 +1399,6 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int
}
if (proto || (opts & PA_O_CONNECT)) {
// if the socket type is SOCK_DGRAM, use by default an alternate protocol
alt_proto = alt_proto || (ctrl_type == SOCK_DGRAM);
/* Note: if the caller asks for a proto, we must find one,
* except if we inherit from a raw FD (family == AF_CUST_EXISTING_FD)
* orif we return with an fqdn that will resolve later,