The verify callback stores a reference to the client's certificate so that
it can still be reported in logs when the verification fails. At depth 0
it correctly releases the reference that may have been stored by an
earlier call before replacing it, but the depth > 0 branch, which does the
same for chain certificates, overwrote the stored pointer without
releasing it first.
For deployments using "ca-ignore-err", a client presenting a chain that
triggers more than one ignored CA-level error therefore leaks one X509
object per extra error, on every single handshake. Since the client fully
controls the chain it presents and the rate at which it connects, memory
grows without bound until the process is killed.
Let's free the previous reference in that branch too, as the depth 0
branch does.
This was introduced in 2.5 by commit
74f6ab6e8 ("MEDIUM: ssl: Keep a
reference to the client's certificate for use in logs"). It must be
backported to all stable versions.
Reported-by: Claude (ANT-2026-6WW7AT7V)
* reference right now. */
certs = X509_STORE_CTX_get1_chain(x_store);
if (certs) {
+ X509 *prev_crt = client_crt;
+
client_crt = sk_X509_value(certs, 0);
if (client_crt) {
X509_up_ref(client_crt);
+ /* release the reference possibly stored by a
+ * previous call at another depth.
+ */
+ X509_free(prev_crt);
SSL_set_ex_data(ssl, ssl_client_crt_ref_index, client_crt);
}
sk_X509_pop_free(certs, X509_free);