[PATCH] openssl: toggling CURLSSLOPT_NO_PARTIALCHAIN makes a different CA cache
authorDaniel Stenberg <daniel@haxx.se>
Wed, 17 Dec 2025 09:54:16 +0000 (10:54 +0100)
committerSamuel Henrique <samueloph@debian.org>
Fri, 8 May 2026 14:16:21 +0000 (07:16 -0700)
Reported-by: Stanislav Fort
Closes #20009

Backported-by: Samuel Henrique <samueloph@debian.org>
 * Refresh patch context for lib/vtls/openssl.c

Backported by: Samuel Henrique <samueloph@debian.org>
 * Bookworm 7.88.1 names the cache struct `multi_ssl_backend_data`
   (vs `ossl_x509_share` in 8.14.1+) and the helpers `cached_x509_store_*`
   (without the `ossl_` prefix). Apply the same logic against those names.
   Replace the upstream `CURL_UNCONST(data)` macro with a plain
   `(struct Curl_easy *)data` cast since CURL_UNCONST does not exist in
   bookworm.

Gbp-Pq: Name CVE-2025-14819.patch

lib/vtls/openssl.c

index 6557783a7f38b8f182d953c820c75e19fc995f37..1f2579e7341ebc6e9e702bd82d63ab870ba247bb 100644 (file)
@@ -302,6 +302,7 @@ struct multi_ssl_backend_data {
   char *CAfile;         /* CAfile path used to generate X509 store */
   X509_STORE *store;    /* cached X509 store or NULL if none */
   struct curltime time; /* when the cached store was created */
+  BIT(no_partialchain); /* keep partial chain state */
 };
 #endif /* HAVE_SSL_X509_STORE_SHARE */
 
@@ -3339,9 +3340,14 @@ static bool cached_x509_store_expired(const struct Curl_easy *data,
 
 static bool cached_x509_store_different(
   struct Curl_cfilter *cf,
+  const struct Curl_easy *data,
   const struct multi_ssl_backend_data *mb)
 {
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+  struct ssl_config_data *ssl_config =
+    Curl_ssl_cf_get_config(cf, (struct Curl_easy *)data);
+  if(mb->no_partialchain != ssl_config->no_partialchain)
+    return true;
   if(!mb->CAfile || !conn_config->CAfile)
     return mb->CAfile != conn_config->CAfile;
 
@@ -3358,7 +3364,7 @@ static X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf,
      multi->ssl_backend_data &&
      multi->ssl_backend_data->store &&
      !cached_x509_store_expired(data, multi->ssl_backend_data) &&
-     !cached_x509_store_different(cf, multi->ssl_backend_data)) {
+     !cached_x509_store_different(cf, data, multi->ssl_backend_data)) {
     store = multi->ssl_backend_data->store;
   }
 
@@ -3386,6 +3392,8 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
 
   if(X509_STORE_up_ref(store)) {
     char *CAfile = NULL;
+    struct ssl_config_data *ssl_config =
+      Curl_ssl_cf_get_config(cf, (struct Curl_easy *)data);
 
     if(conn_config->CAfile) {
       CAfile = strdup(conn_config->CAfile);
@@ -3403,6 +3411,7 @@ static void set_cached_x509_store(struct Curl_cfilter *cf,
     mbackend->time = Curl_now();
     mbackend->store = store;
     mbackend->CAfile = CAfile;
+    mbackend->no_partialchain = ssl_config->no_partialchain;
   }
 }