* [OE-core][scarthgap][PATCH v2 6/8] curl: fix CVE-2026-8932
2026-10-16 13:04 [OE-core][scarthgap][PATCH v2 5/8] curl: fix CVE-2026-8927 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
@ 2026-10-16 13:04 ` Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 7/8] curl: fix CVE-2026-6429 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 8/8] curl: fix CVE-2026-7168 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2 siblings, 0 replies; 4+ messages in thread
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-10-16 13:04 UTC (permalink / raw)
To: openembedded-core; +Cc: yoann.congal
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream fix as referenced in [2], using the
commit shown in [1].
[1] https://github.com/curl/curl/commit/7541ae569d82fb308a5e2d94916027da4fa3ba3e
[2] https://curl.se/docs/CVE-2026-8932.html
Validation: unit3303 passes in a native debug build with OpenSSL.
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
Changes in v2:
- Rebase onto stable/scarthgap-review.
- Record native unit3303 validation.
.../curl/curl/CVE-2026-8932.patch | 423 ++++++++++++++++++
meta/recipes-support/curl/curl_8.7.1.bb | 1 +
2 files changed, 424 insertions(+)
create mode 100644 meta/recipes-support/curl/curl/CVE-2026-8932.patch
diff --git a/meta/recipes-support/curl/curl/CVE-2026-8932.patch b/meta/recipes-support/curl/curl/CVE-2026-8932.patch
new file mode 100644
index 0000000..432d5e5
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2026-8932.patch
@@ -0,0 +1,423 @@
+From c25faf128bba57a64da636f126773b858b35bc27 Mon Sep 17 00:00:00 2001
+From: Joshua Rogers <MegaManSec@users.noreply.github.com>
+Date: Tue, 19 May 2026 11:47:50 +0200
+Subject: [PATCH] tls: fix incomplete mTLS config in conn reuse and session
+ cache
+
+cert_type, key, key_type, key_passwd and key_blob lived in
+ssl_config_data but not in ssl_primary_config, so they were invisible to
+match_ssl_primary_config() and to the TLS session cache peer key.
+
+Two easy handles sharing a connection pool could reuse each other's
+authenticated connections when they differed only on SSLKEY, SSLKEYTYPE,
+KEYPASSWD, SSLCERTTYPE or SSLKEYBLOB. The second handle would silently
+inherit the first handle's authenticated identity.
+
+Promote all five fields into ssl_primary_config so the conn-reuse
+predicate and session cache key cover the complete client credential
+set. Also replace the fixed ":CCERT" session cache marker with the
+actual clientcert path so sessions are not shared across different
+client certificates.
+
+Verified by test 3303 and 3304
+
+Reported-By: Joshua Rogers (AISLE Research)
+Closes #21667
+
+CVE: CVE-2026-8932
+Upstream-Status: Backport [https://github.com/curl/curl/commit/7541ae569d82fb308a5e2d94916027da4fa3ba3e]
+
+Backport Changes:
+- Add the missing credential fields to ssl_primary_config for
+ connection and session matching. Keep the backend fields as aliases
+ instead of changing accesses throughout the TLS backends.
+- Keep the session cache in vtls.c; curl 8.7.1 has no vtls_scache
+ files or peer key API.
+- Use the older unit test harness and allocator (memdebug.h last).
+ Combine unit3304's case-insensitive type checks into unit3303,
+ with key_blob deep copy and connection/session matching checks.
+- Use a writable hostname array for the older char * hostname field.
+
+(cherry picked from commit 7541ae569d82fb308a5e2d94916027da4fa3ba3e)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ lib/urldata.h | 5 +
+ lib/vtls/vtls.c | 25 +++++
+ tests/data/Makefile.inc | 3 +-
+ tests/data/test3303 | 23 +++++
+ tests/unit/Makefile.inc | 4 +-
+ tests/unit/unit3303.c | 211 ++++++++++++++++++++++++++++++++++++++++
+ 6 files changed, 269 insertions(+), 2 deletions(-)
+ create mode 100644 tests/data/test3303
+ create mode 100644 tests/unit/unit3303.c
+
+diff --git a/lib/urldata.h b/lib/urldata.h
+index d2d9424197..9015515e17 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -286,6 +286,11 @@ struct ssl_primary_config {
+ char *CAfile; /* certificate to verify peer against */
+ char *issuercert; /* optional issuer certificate filename */
+ char *clientcert;
++ char *cert_type; /* format for certificate (default: PEM) */
++ char *key; /* private key file name */
++ struct curl_blob *key_blob;
++ char *key_type; /* format for private key (default: PEM) */
++ char *key_passwd; /* plain text private key password */
+ char *cipher_list; /* list of ciphers to use */
+ char *cipher_list13; /* list of TLS 1.3 cipher suites to use */
+ char *pinned_key;
+diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c
+index d13a3cb1b7..c89e8abcc6 100644
+--- a/lib/vtls/vtls.c
++++ b/lib/vtls/vtls.c
+@@ -187,10 +187,15 @@ match_ssl_primary_config(struct Curl_easy *data,
+ blobcmp(c1->cert_blob, c2->cert_blob) &&
+ blobcmp(c1->ca_info_blob, c2->ca_info_blob) &&
+ blobcmp(c1->issuercert_blob, c2->issuercert_blob) &&
++ blobcmp(c1->key_blob, c2->key_blob) &&
+ Curl_safecmp(c1->CApath, c2->CApath) &&
+ Curl_safecmp(c1->CAfile, c2->CAfile) &&
+ Curl_safecmp(c1->issuercert, c2->issuercert) &&
+ Curl_safecmp(c1->clientcert, c2->clientcert) &&
++ curl_strequal(c1->cert_type, c2->cert_type) &&
++ Curl_safecmp(c1->key, c2->key) &&
++ curl_strequal(c1->key_type, c2->key_type) &&
++ !Curl_timestrcmp(c1->key_passwd, c2->key_passwd) &&
+ #ifdef USE_TLS_SRP
+ !Curl_timestrcmp(c1->username, c2->username) &&
+ !Curl_timestrcmp(c1->password, c2->password) &&
+@@ -234,10 +239,15 @@ static bool clone_ssl_primary_config(struct ssl_primary_config *source,
+ CLONE_BLOB(cert_blob);
+ CLONE_BLOB(ca_info_blob);
+ CLONE_BLOB(issuercert_blob);
++ CLONE_BLOB(key_blob);
+ CLONE_STRING(CApath);
+ CLONE_STRING(CAfile);
+ CLONE_STRING(issuercert);
+ CLONE_STRING(clientcert);
++ CLONE_STRING(cert_type);
++ CLONE_STRING(key);
++ CLONE_STRING(key_type);
++ CLONE_STRING(key_passwd);
+ CLONE_STRING(cipher_list);
+ CLONE_STRING(cipher_list13);
+ CLONE_STRING(pinned_key);
+@@ -257,12 +267,17 @@ static void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc)
+ Curl_safefree(sslc->CAfile);
+ Curl_safefree(sslc->issuercert);
+ Curl_safefree(sslc->clientcert);
++ Curl_safefree(sslc->cert_type);
++ Curl_safefree(sslc->key);
++ Curl_safefree(sslc->key_type);
++ Curl_safefree(sslc->key_passwd);
+ Curl_safefree(sslc->cipher_list);
+ Curl_safefree(sslc->cipher_list13);
+ Curl_safefree(sslc->pinned_key);
+ Curl_safefree(sslc->cert_blob);
+ Curl_safefree(sslc->ca_info_blob);
+ Curl_safefree(sslc->issuercert_blob);
++ Curl_safefree(sslc->key_blob);
+ Curl_safefree(sslc->curves);
+ Curl_safefree(sslc->CRLfile);
+ #ifdef USE_TLS_SRP
+@@ -297,6 +312,11 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+ data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD];
+ data->set.ssl.primary.clientcert = data->set.str[STRING_CERT];
+ data->set.ssl.key_blob = data->set.blobs[BLOB_KEY];
++ data->set.ssl.primary.cert_type = data->set.ssl.cert_type;
++ data->set.ssl.primary.key = data->set.ssl.key;
++ data->set.ssl.primary.key_type = data->set.ssl.key_type;
++ data->set.ssl.primary.key_passwd = data->set.ssl.key_passwd;
++ data->set.ssl.primary.key_blob = data->set.ssl.key_blob;
+
+ #ifndef CURL_DISABLE_PROXY
+ data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
+@@ -322,6 +342,11 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data)
+ data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
+ data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
+ data->set.proxy_ssl.key_blob = data->set.blobs[BLOB_KEY_PROXY];
++ data->set.proxy_ssl.primary.cert_type = data->set.proxy_ssl.cert_type;
++ data->set.proxy_ssl.primary.key = data->set.proxy_ssl.key;
++ data->set.proxy_ssl.primary.key_type = data->set.proxy_ssl.key_type;
++ data->set.proxy_ssl.primary.key_passwd = data->set.proxy_ssl.key_passwd;
++ data->set.proxy_ssl.primary.key_blob = data->set.proxy_ssl.key_blob;
+ #ifdef USE_TLS_SRP
+ data->set.proxy_ssl.primary.username =
+ data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index f420a8a4f5..27b1b52a10 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -264,4 +264,5 @@ test3024 test3025 test3026 test3027 test3028 test3029 test3030 \
+ \
+ test3100 test3101 test3102 test3103 \
+ test3200 \
+-test3201 test3202
++test3201 test3202 \
++test3303
+diff --git a/tests/data/test3303 b/tests/data/test3303
+new file mode 100644
+index 0000000000..9b52bcb817
+--- /dev/null
++++ b/tests/data/test3303
+@@ -0,0 +1,23 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++unittest
++TLS
++mTLS
++</keywords>
++</info>
++
++# Client-side
++<client>
++<server>
++none
++</server>
++<features>
++unittest
++</features>
++<name>
++conn-reuse match distinguishes mTLS key, cert_type, key_type and key_passwd fields
++</name>
++</client>
++</testcase>
+diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc
+index 1926b49b3a..afbe29d2b7 100644
+--- a/tests/unit/Makefile.inc
++++ b/tests/unit/Makefile.inc
+@@ -39,7 +39,7 @@ UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \
+ unit1650 unit1651 unit1652 unit1653 unit1654 unit1655 unit1656 \
+ unit1660 unit1661 \
+ unit2600 unit2601 unit2602 unit2603 \
+- unit3200
++ unit3200 unit3303
+
+ unit1300_SOURCES = unit1300.c $(UNITFILES)
+
+@@ -134,3 +134,5 @@ unit2602_SOURCES = unit2602.c $(UNITFILES)
+ unit2603_SOURCES = unit2603.c $(UNITFILES)
+
+ unit3200_SOURCES = unit3200.c $(UNITFILES)
++
++unit3303_SOURCES = unit3303.c $(UNITFILES)
+diff --git a/tests/unit/unit3303.c b/tests/unit/unit3303.c
+new file mode 100644
+index 0000000000..d0a59877d6
+--- /dev/null
++++ b/tests/unit/unit3303.c
+@@ -0,0 +1,211 @@
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ * SPDX-License-Identifier: curl
++ *
++ ***************************************************************************/
++#include "curlcheck.h"
++#include "cfilters.h"
++#include "http.h"
++#include "urldata.h"
++
++#ifdef USE_SSL
++#include "vtls/vtls.h"
++#include "vtls/vtls_int.h"
++#endif
++#include "memdebug.h" /* LAST include file */
++
++static CURLcode unit_setup(void)
++{
++ return curl_global_init(CURL_GLOBAL_ALL);
++}
++
++static void unit_stop(void)
++{
++ curl_global_cleanup();
++}
++
++UNITTEST_START
++#ifdef USE_SSL
++{
++ CURL *curl;
++ struct Curl_easy *data;
++ struct connectdata *conn;
++ struct Curl_cfilter cf;
++ struct ssl_connect_data sslctx;
++ struct ssl_primary_config *primary;
++ struct curl_blob key_blob;
++ struct curl_blob alt_key_blob;
++ struct curl_blob *saved_blob;
++ struct curl_blob *saved_conn_blob;
++ void *sessionid;
++ size_t idsize = 0;
++ bool added = FALSE;
++ char fake_session;
++ char *saved;
++ static char alt_passwd[] = "wrong";
++ static char alt_key[] = "other.key";
++ static char alt_ktype[] = "DER";
++ static char alt_ctype[] = "P12";
++ static char lc_ctype[] = "pem";
++ static char lc_ktype[] = "pem";
++ static char hostname[] = "example.com";
++
++ curl = curl_easy_init();
++ abort_unless(curl, "curl_easy_init failed");
++ data = (struct Curl_easy *)curl;
++
++ key_blob.data = (void *)"first private key";
++ key_blob.len = sizeof("first private key") - 1;
++ key_blob.flags = CURL_BLOB_COPY;
++ alt_key_blob.data = (void *)"second private key";
++ alt_key_blob.len = sizeof("second private key") - 1;
++ alt_key_blob.flags = CURL_BLOB_NOCOPY;
++
++ curl_easy_setopt(curl, CURLOPT_SSLCERT, "client.pem");
++ curl_easy_setopt(curl, CURLOPT_SSLKEY, "client.key");
++ curl_easy_setopt(curl, CURLOPT_SSLKEY_BLOB, &key_blob);
++ curl_easy_setopt(curl, CURLOPT_KEYPASSWD, "secret");
++ curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
++ curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM");
++
++ abort_unless(!Curl_ssl_easy_config_complete(data),
++ "Curl_ssl_easy_config_complete failed");
++
++ conn = calloc(1, sizeof(*conn));
++ abort_unless(conn, "connection allocation failed");
++ abort_unless(!Curl_ssl_conn_config_init(data, conn),
++ "Curl_ssl_conn_config_init failed");
++
++ fail_unless(Curl_ssl_conn_config_match(data, conn, FALSE),
++ "identical mTLS config should match");
++
++ primary = &data->set.ssl.primary;
++
++ fail_unless(conn->ssl_config.key_blob &&
++ conn->ssl_config.key_blob != primary->key_blob &&
++ conn->ssl_config.key_blob->len == primary->key_blob->len &&
++ !memcmp(conn->ssl_config.key_blob->data,
++ primary->key_blob->data, primary->key_blob->len),
++ "key_blob must be cloned into the connection config");
++
++ saved_blob = primary->key_blob;
++ primary->key_blob = &alt_key_blob;
++ fail_unless(!Curl_ssl_conn_config_match(data, conn, FALSE),
++ "different key_blob must not reuse conn");
++ primary->key_blob = saved_blob;
++
++ saved = primary->key_passwd;
++ primary->key_passwd = alt_passwd;
++ fail_unless(!Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "different key_passwd must not reuse conn");
++ primary->key_passwd = saved;
++
++ saved = primary->key;
++ primary->key = alt_key;
++ fail_unless(!Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "different key must not reuse conn");
++ primary->key = saved;
++
++ saved = primary->key_type;
++ primary->key_type = alt_ktype;
++ fail_unless(!Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "different key_type must not reuse conn");
++ primary->key_type = saved;
++
++ saved = primary->cert_type;
++ primary->cert_type = alt_ctype;
++ fail_unless(!Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "different cert_type must not reuse conn");
++ primary->cert_type = saved;
++
++ primary->cert_type = lc_ctype;
++ fail_unless(Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "cert_type comparison must be case-insensitive");
++ primary->cert_type = saved;
++
++ primary->key_type = lc_ktype;
++ fail_unless(Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "key_type comparison must be case-insensitive");
++ primary->key_type = saved;
++
++ fail_unless(Curl_ssl_conn_config_match((struct Curl_easy *)curl, conn,
++ FALSE),
++ "restored mTLS config should match");
++
++ memset(&cf, 0, sizeof(cf));
++ memset(&sslctx, 0, sizeof(sslctx));
++ conn->handler = &Curl_handler_https;
++ sslctx.peer.hostname = hostname;
++ sslctx.port = 443;
++ cf.cft = &Curl_cft_ssl;
++ cf.ctx = &sslctx;
++ cf.conn = conn;
++
++ abort_unless(!Curl_ssl_initsessions(data, 1),
++ "Curl_ssl_initsessions failed");
++ abort_unless(!Curl_ssl_addsessionid(&cf, data, &fake_session, 1,
++ &added),
++ "Curl_ssl_addsessionid failed");
++ fail_unless(added, "session was not added to the cache");
++ fail_unless(data->state.session[0].ssl_config.key_blob &&
++ data->state.session[0].ssl_config.key_blob !=
++ conn->ssl_config.key_blob,
++ "key_blob must be cloned into the session cache");
++
++ sessionid = NULL;
++ fail_unless(!Curl_ssl_getsessionid(&cf, data, &sessionid, &idsize) &&
++ sessionid == &fake_session,
++ "identical key_blob should reuse the TLS session");
++
++ saved_conn_blob = conn->ssl_config.key_blob;
++ conn->ssl_config.key_blob = &alt_key_blob;
++ sessionid = NULL;
++ fail_unless(Curl_ssl_getsessionid(&cf, data, &sessionid, &idsize) &&
++ !sessionid,
++ "different key_blob must not reuse the TLS session");
++ conn->ssl_config.key_blob = saved_conn_blob;
++
++ sessionid = NULL;
++ fail_unless(!Curl_ssl_getsessionid(&cf, data, &sessionid, &idsize) &&
++ sessionid == &fake_session,
++ "restored key_blob should reuse the TLS session");
++
++ Curl_ssl_conn_config_cleanup(conn);
++ conn->ssl_config = data->state.session[0].ssl_config;
++ memset(&data->state.session[0].ssl_config, 0,
++ sizeof(data->state.session[0].ssl_config));
++ free(data->state.session[0].name);
++ data->state.session[0].name = NULL;
++ free(data->state.session[0].conn_to_host);
++ data->state.session[0].conn_to_host = NULL;
++ data->state.session[0].sessionid = NULL;
++ Curl_ssl_conn_config_cleanup(conn);
++ free(conn);
++ curl_easy_cleanup(curl);
++}
++#endif /* USE_SSL */
++UNITTEST_STOP
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
index 9f26195..6f9a814 100644
--- a/meta/recipes-support/curl/curl_8.7.1.bb
+++ b/meta/recipes-support/curl/curl_8.7.1.bb
@@ -45,6 +45,7 @@ SRC_URI = " \
file://CVE-2026-8286.patch \
file://CVE-2026-8927-dependent.patch \
file://CVE-2026-8927.patch \
+ file://CVE-2026-8932.patch \
"
SRC_URI:append:class-nativesdk = " \
--
2.35.6
^ permalink raw reply related [flat|nested] 4+ messages in thread* [OE-core][scarthgap][PATCH v2 7/8] curl: fix CVE-2026-6429
2026-10-16 13:04 [OE-core][scarthgap][PATCH v2 5/8] curl: fix CVE-2026-8927 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 6/8] curl: fix CVE-2026-8932 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
@ 2026-10-16 13:04 ` Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 8/8] curl: fix CVE-2026-7168 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2 siblings, 0 replies; 4+ messages in thread
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-10-16 13:04 UTC (permalink / raw)
To: openembedded-core; +Cc: yoann.congal
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream fix as referenced in [2], using the
commit shown in [1].
[1] https://github.com/curl/curl/commit/b4024bf808bd558026fdc6096e8457f199ace306
[2] https://curl.se/docs/CVE-2026-6429.html
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
Changes in v2:
- Rebase onto stable/scarthgap-review.
.../curl/curl/CVE-2026-6429.patch | 363 ++++++++++++++++++
meta/recipes-support/curl/curl_8.7.1.bb | 1 +
2 files changed, 364 insertions(+)
create mode 100644 meta/recipes-support/curl/curl/CVE-2026-6429.patch
diff --git a/meta/recipes-support/curl/curl/CVE-2026-6429.patch b/meta/recipes-support/curl/curl/CVE-2026-6429.patch
new file mode 100644
index 0000000..03ff4a1
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2026-6429.patch
@@ -0,0 +1,363 @@
+From 8f82af313dcce59c7343b3a4f849aa7e35e066f5 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Thu, 16 Apr 2026 14:26:20 +0200
+Subject: [PATCH] http: clear credentials better on redirect
+
+Verify with test 2506: netrc with redirect using proxy
+
+Updated test 998 which was wrong.
+
+Reported-by: Muhamad Arga Reksapati
+
+Closes #21345
+
+CVE: CVE-2026-6429
+Upstream-Status: Backport [https://github.com/curl/curl/commit/b4024bf808bd558026fdc6096e8457f199ace306]
+
+Backport Changes:
+- Apply the fix in Curl_follow() in transfer.c. curl 8.7.1 lacks
+ Curl_url_same_origin(), so compare the scheme, host and port here.
+ Allow URL spaces and compare schemes before looking up default
+ ports, so an unsupported redirect scheme is a different origin.
+- Register test2506/lib2506 in the older Makefiles and use the old
+ libtest entry point.
+- Remove test998's literal Base64 auth header from the redirected
+ request; upstream uses a Base64 expansion for the same header.
+
+(cherry picked from commit b4024bf808bd558026fdc6096e8457f199ace306)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ lib/transfer.c | 106 ++++++++++++++++++++++---------------
+ tests/data/Makefile.inc | 2 +-
+ tests/data/test2506 | 64 ++++++++++++++++++++++
+ tests/data/test998 | 1 -
+ tests/libtest/Makefile.inc | 5 +-
+ tests/libtest/lib2506.c | 71 +++++++++++++++++++++++++
+ 6 files changed, 202 insertions(+), 47 deletions(-)
+ create mode 100644 tests/data/test2506
+ create mode 100644 tests/libtest/lib2506.c
+
+diff --git a/lib/transfer.c b/lib/transfer.c
+index a73462928d..9103a66865 100644
+--- a/lib/transfer.c
++++ b/lib/transfer.c
+@@ -865,49 +865,67 @@ CURLcode Curl_follow(struct Curl_easy *data,
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+
+- /* Clear auth if this redirects to a different port number or protocol,
+- unless permitted */
+- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
+- char *portnum;
+- int port;
+- bool clear = FALSE;
+-
+- if(data->set.use_port && data->state.allow_port)
+- /* a custom port is used */
+- port = (int)data->set.use_port;
+- else {
+- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
+- CURLU_DEFAULT_PORT);
+- if(uc) {
+- free(newurl);
+- return Curl_uc_to_curlcode(uc);
+- }
+- port = atoi(portnum);
+- free(portnum);
+- }
+- if(port != data->info.conn_remote_port) {
+- infof(data, "Clear auth, redirects to port from %u to %u",
+- data->info.conn_remote_port, port);
+- clear = TRUE;
++ {
++ bool same_origin = FALSE;
++ CURLU *u;
++ char *oldscheme = NULL;
++ char *oldhost = NULL;
++ char *oldport = NULL;
++ char *newscheme = NULL;
++ char *newhost = NULL;
++ char *newport = NULL;
++
++ u = curl_url();
++ if(!u) {
++ free(newurl);
++ return CURLE_OUT_OF_MEMORY;
+ }
+- else {
+- char *scheme;
+- const struct Curl_handler *p;
+- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
+- if(uc) {
+- free(newurl);
+- return Curl_uc_to_curlcode(uc);
+- }
+
+- p = Curl_get_scheme_handler(scheme);
+- if(p && (p->protocol != data->info.conn_protocol)) {
+- infof(data, "Clear auth, redirects scheme from %s to %s",
+- data->info.conn_scheme, scheme);
+- clear = TRUE;
++ uc = curl_url_set(u, CURLUPART_URL, data->state.url,
++ CURLU_URLENCODE | CURLU_ALLOW_SPACE);
++ if(!uc)
++ uc = curl_url_get(u, CURLUPART_SCHEME, &oldscheme, 0);
++ if(!uc)
++ uc = curl_url_get(u, CURLUPART_HOST, &oldhost, 0);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &newscheme, 0);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_HOST, &newhost, 0);
++ if(!uc) {
++ same_origin = strcasecompare(oldscheme, newscheme) &&
++ strcasecompare(oldhost, newhost);
++ if(same_origin) {
++ uc = curl_url_get(u, CURLUPART_PORT, &oldport,
++ CURLU_DEFAULT_PORT);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &newport,
++ CURLU_DEFAULT_PORT);
++ if(!uc)
++ same_origin = !strcmp(oldport, newport);
+ }
+- free(scheme);
+ }
+- if(clear) {
++ if(uc) {
++ curl_url_cleanup(u);
++ free(oldscheme);
++ free(oldhost);
++ free(oldport);
++ free(newscheme);
++ free(newhost);
++ free(newport);
++ free(newurl);
++ return Curl_uc_to_curlcode(uc);
++ }
++
++ curl_url_cleanup(u);
++ free(oldscheme);
++ free(oldhost);
++ free(oldport);
++ free(newscheme);
++ free(newhost);
++ free(newport);
++
++ if((!same_origin && !data->set.allow_auth_to_other_hosts) ||
++ !data->set.str[STRING_USERNAME]) {
+ result = Curl_reset_userpwd(data);
+ if(result) {
+ free(newurl);
+@@ -917,12 +935,12 @@ CURLcode Curl_follow(struct Curl_easy *data,
+ Curl_safefree(data->state.aptr.passwd);
+ }
+ }
+- }
+
+- result = Curl_reset_proxypwd(data);
+- if(result) {
+- free(newurl);
+- return result;
++ result = Curl_reset_proxypwd(data);
++ if(result) {
++ free(newurl);
++ return result;
++ }
+ }
+
+ if(type == FOLLOW_FAKE) {
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index 27b1b52a10..7c0ef24554 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -253,7 +253,7 @@ test2300 test2301 test2302 test2303 test2304 test2305 test2306 test2307 \
+ \
+ test2400 test2401 test2402 test2403 test2404 \
+ \
+-test2500 test2501 test2502 test2503 \
++test2500 test2501 test2502 test2503 test2506 \
+ \
+ test2600 test2601 test2602 test2603 \
+ \
+diff --git a/tests/data/test2506 b/tests/data/test2506
+new file mode 100644
+index 0000000000..9c65002496
+--- /dev/null
++++ b/tests/data/test2506
+@@ -0,0 +1,64 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++HTTP
++cookies
++</keywords>
++</info>
++
++<reply>
++<data crlf="headers" nocheck="yes">
++HTTP/1.1 301 redirect
++Date: Tue, 09 Nov 2010 14:49:00 GMT
++Content-Length: 3
++Location: http://numbertwo.example/%TESTNUMBER0002
++
++ok
++</data>
++<data2 crlf="headers" nocheck="yes">
++HTTP/1.1 200 OK
++Date: Tue, 09 Nov 2010 14:49:00 GMT
++Content-Length: 4
++
++yes
++</data2>
++</reply>
++
++<client>
++<server>
++http
++</server>
++<features>
++proxy
++</features>
++<tool>
++lib%TESTNUMBER
++</tool>
++<name>
++netrc with redirect using proxy
++</name>
++<file name="%LOGDIR/netrc2506">
++machine site.example login batman password robin
++</file>
++<command>
++http://%HOSTIP:%HTTPPORT http://site.example/ %LOGDIR/netrc2506
++</command>
++</client>
++
++<verify>
++<protocol crlf="headers">
++GET http://site.example/ HTTP/1.1
++Host: site.example
++Authorization: Basic %b64[batman:robin]b64%
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://numbertwo.example/25060002 HTTP/1.1
++Host: numbertwo.example
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol>
++</verify>
++</testcase>
+diff --git a/tests/data/test998 b/tests/data/test998
+index 9b44223845..205179fac3 100644
+--- a/tests/data/test998
++++ b/tests/data/test998
+@@ -82,7 +82,6 @@
+
+ GET http://somewhere.else.example/a/path/9980002 HTTP/1.1
+ Host: somewhere.else.example
+- Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg==
+ User-Agent: curl/%VERSION
+ Accept: */*
+ Proxy-Connection: Keep-Alive
+diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
+index 78e16b0428..639d010a00 100644
+--- a/tests/libtest/Makefile.inc
++++ b/tests/libtest/Makefile.inc
+@@ -77,7 +77,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \
+ lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 \
+ lib2301 lib2302 lib2304 lib2305 lib2306 \
+ lib2402 lib2404 \
+- lib2502 \
++ lib2502 lib2506 \
+ lib3010 lib3025 lib3026 lib3027 \
+ lib3100 lib3101 lib3102 lib3103
+
+@@ -689,6 +689,9 @@ lib2404_LDADD = $(TESTUTIL_LIBS)
+ lib2502_SOURCES = lib2502.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+ lib2502_LDADD = $(TESTUTIL_LIBS)
+
++lib2506_SOURCES = lib2506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
++lib2506_LDADD = $(TESTUTIL_LIBS)
++
+ lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+ lib3010_LDADD = $(TESTUTIL_LIBS)
+
+diff --git a/tests/libtest/lib2506.c b/tests/libtest/lib2506.c
+new file mode 100644
+index 0000000000..e6dde18507
+--- /dev/null
++++ b/tests/libtest/lib2506.c
+@@ -0,0 +1,71 @@
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ * SPDX-License-Identifier: curl
++ *
++ ***************************************************************************/
++#include "test.h"
++
++#include "testtrace.h"
++
++static size_t sink2506(char *ptr, size_t size, size_t nmemb, void *ud)
++{
++ (void)ptr;
++ (void)ud;
++ return size * nmemb;
++}
++
++int test(char *URL)
++{
++ CURL *curl;
++ int res = CURLE_OUT_OF_MEMORY;
++
++ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
++ curl_mfprintf(stderr, "curl_global_init() failed\n");
++ return TEST_ERR_MAJOR_BAD;
++ }
++
++ curl = curl_easy_init();
++ if(!curl) {
++ curl_mfprintf(stderr, "curl_easy_init() failed\n");
++ curl_global_cleanup();
++ return TEST_ERR_MAJOR_BAD;
++ }
++
++ test_setopt(curl, CURLOPT_WRITEFUNCTION, sink2506);
++ test_setopt(curl, CURLOPT_PROXY, URL);
++ test_setopt(curl, CURLOPT_URL, libtest_arg2);
++ test_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
++ test_setopt(curl, CURLOPT_NETRC_FILE, libtest_arg3);
++ test_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
++ test_setopt(curl, CURLOPT_VERBOSE, 1L);
++
++ /* CURLOPT_UNRESTRICTED_AUTH should not make a difference because the
++ credentials come from netrc */
++ test_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
++
++ res = curl_easy_perform(curl);
++
++test_cleanup:
++ curl_easy_cleanup(curl);
++ curl_global_cleanup();
++
++ return res;
++}
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
index 6f9a814..00a92d8 100644
--- a/meta/recipes-support/curl/curl_8.7.1.bb
+++ b/meta/recipes-support/curl/curl_8.7.1.bb
@@ -46,6 +46,7 @@ SRC_URI = " \
file://CVE-2026-8927-dependent.patch \
file://CVE-2026-8927.patch \
file://CVE-2026-8932.patch \
+ file://CVE-2026-6429.patch \
"
SRC_URI:append:class-nativesdk = " \
--
2.35.6
^ permalink raw reply related [flat|nested] 4+ messages in thread* [OE-core][scarthgap][PATCH v2 8/8] curl: fix CVE-2026-7168
2026-10-16 13:04 [OE-core][scarthgap][PATCH v2 5/8] curl: fix CVE-2026-8927 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 6/8] curl: fix CVE-2026-8932 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2026-10-16 13:04 ` [OE-core][scarthgap][PATCH v2 7/8] curl: fix CVE-2026-6429 Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
@ 2026-10-16 13:04 ` Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco)
2 siblings, 0 replies; 4+ messages in thread
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-10-16 13:04 UTC (permalink / raw)
To: openembedded-core; +Cc: yoann.congal
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream fix as referenced in [2], using the
commit shown in [1].
[1] https://github.com/curl/curl/commit/c1cfdf59acbaf9504c4578d4cf56cdd7c8594507
[2] https://curl.se/docs/CVE-2026-7168.html
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
Changes in v2:
- Rebase onto stable/scarthgap-review.
- Explain the test.h macro requirements.
.../curl/curl/CVE-2026-7168.patch | 398 ++++++++++++++++++
meta/recipes-support/curl/curl_8.7.1.bb | 1 +
2 files changed, 399 insertions(+)
create mode 100644 meta/recipes-support/curl/curl/CVE-2026-7168.patch
diff --git a/meta/recipes-support/curl/curl/CVE-2026-7168.patch b/meta/recipes-support/curl/curl/CVE-2026-7168.patch
new file mode 100644
index 0000000..42e576e
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2026-7168.patch
@@ -0,0 +1,398 @@
+From 9026628dd5fa02b66cb85606e2121c94f9943efa Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Mon, 27 Apr 2026 09:14:51 +0200
+Subject: [PATCH] setopt: clear proxy auth properties when switching
+
+Verify with test 1588
+
+Closes #21453
+
+CVE: CVE-2026-7168
+Upstream-Status: Backport [https://github.com/curl/curl/commit/c1cfdf59acbaf9504c4578d4cf56cdd7c8594507]
+
+Backport Changes:
+- Add setproxy() to the older setopt.c and include vauth/vauth.h.
+ Keep cleanup as a no-op when Digest is disabled.
+- Register test1588/lib1588 in Makefile.inc and use the old test()
+ entry point and testutil.h. Read test_argv[4] only if test_argc >= 5.
+- curl 8.7.1 has test.h instead of first.h. res_easy_setopt() and
+ res_global_init() write to res, so use that name in init1588()
+ and test(). Keep CURLcode and run1588()'s original result variable.
+- Use the older digest-auth feature name with the dependency patch's
+ feature detection, and crlf="yes" replies for the old test server.
+
+(cherry picked from commit c1cfdf59acbaf9504c4578d4cf56cdd7c8594507)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ lib/setopt.c | 18 ++++-
+ lib/vauth/vauth.h | 2 +
+ tests/data/Makefile.inc | 2 +
+ tests/data/test1588 | 106 ++++++++++++++++++++++++++
+ tests/libtest/Makefile.inc | 5 +-
+ tests/libtest/lib1588.c | 152 +++++++++++++++++++++++++++++++++++++
+ 6 files changed, 282 insertions(+), 3 deletions(-)
+ create mode 100644 tests/data/test1588
+ create mode 100644 tests/libtest/lib1588.c
+
+diff --git a/lib/setopt.c b/lib/setopt.c
+index 8a5a5d7c33..7eaf30910f 100644
+--- a/lib/setopt.c
++++ b/lib/setopt.c
+@@ -51,6 +51,7 @@
+ #include "altsvc.h"
+ #include "hsts.h"
+ #include "tftp.h"
++#include "vauth/vauth.h"
+ #include "strdup.h"
+ /* The last 3 #include files should be in this order */
+ #include "curl_printf.h"
+@@ -76,6 +77,20 @@ CURLcode Curl_setstropt(char **charp, const char *s)
+ return CURLE_OK;
+ }
+
++#ifndef CURL_DISABLE_PROXY
++static CURLcode setproxy(struct Curl_easy *data, const char *proxy)
++{
++ if((data->set.str[STRING_PROXY] && proxy) &&
++ /* there was one set, is this a new one? */
++ !strcmp(data->set.str[STRING_PROXY], proxy))
++ return CURLE_OK; /* same one as before */
++
++ Curl_auth_digest_cleanup(&data->state.proxydigest);
++ memset(&data->state.authproxy, 0, sizeof(data->state.authproxy));
++ return Curl_setstropt(&data->set.str[STRING_PROXY], proxy);
++}
++#endif
++
+ CURLcode Curl_setblobopt(struct curl_blob **blobp,
+ const struct curl_blob *blob)
+ {
+@@ -1139,8 +1154,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
+ * Setting it to NULL, means no proxy but allows the environment variables
+ * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
+ */
+- result = Curl_setstropt(&data->set.str[STRING_PROXY],
+- va_arg(param, char *));
++ result = setproxy(data, va_arg(param, char *));
+ break;
+
+ case CURLOPT_PRE_PROXY:
+diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h
+index 9da0540892..bf5c7a3e12 100644
+--- a/lib/vauth/vauth.h
++++ b/lib/vauth/vauth.h
+@@ -119,6 +119,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
+
+ /* This is used to clean up the digest specific data */
+ void Curl_auth_digest_cleanup(struct digestdata *digest);
++#else
++#define Curl_auth_digest_cleanup(x)
+ #endif /* !CURL_DISABLE_DIGEST_AUTH */
+
+ #ifdef USE_GSASL
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index 7c0ef24554..5e83979417 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -201,6 +201,8 @@ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \
+ test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \
+ test1566 test1567 test1568 test1569 test1570 \
+ \
++test1588 \
++\
+ test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \
+ test1598 \
+ test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 \
+diff --git a/tests/data/test1588 b/tests/data/test1588
+new file mode 100644
+index 0000000000..ba996fb2ff
+--- /dev/null
++++ b/tests/data/test1588
+@@ -0,0 +1,106 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++HTTP
++HTTP GET
++HTTP proxy
++HTTP proxy Digest auth
++multi
++</keywords>
++</info>
++
++# Server-side
++<reply>
++
++# this is returned first since we get no proxy-auth
++<data crlf="yes">
++HTTP/1.1 407 Authorization Required to proxy me my dear
++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345"
++Content-Length: 33
++
++And you should ignore this data.
++</data>
++
++# then this is returned when we get proxy-auth
++<data1000 crlf="yes">
++HTTP/1.1 200 OK
++Content-Length: 21
++Server: no
++
++Nice proxy auth sir!
++</data1000>
++
++<datacheck crlf="headers">
++HTTP/1.1 407 Authorization Required to proxy me my dear
++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345"
++Content-Length: 33
++
++HTTP/1.1 200 OK
++Content-Length: 21
++Server: no
++
++Nice proxy auth sir!
++HTTP/1.1 407 Authorization Required to proxy me my dear
++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345"
++Content-Length: 33
++
++HTTP/1.1 200 OK
++Content-Length: 21
++Server: no
++
++Nice proxy auth sir!
++</datacheck>
++</reply>
++
++# Client-side
++<client>
++<server>
++http
++</server>
++# tool is what to use instead of 'curl'
++<tool>
++lib%TESTNUMBER
++</tool>
++<features>
++!SSPI
++crypto
++proxy
++digest-auth
++</features>
++<name>
++HTTP proxy auth Digest, then change proxy and do it again
++</name>
++<command>
++http://test.remote.example.com/path/%TESTNUMBER %HOSTIP %HTTPPORT silly:person custom.set.host.name
++</command>
++</client>
++
++# Verify data after the test has been "shot"
++<verify>
++<protocol crlf="headers">
++GET http://test.remote.example.com/path/1588 HTTP/1.1
++Host: test.remote.example.com
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://test.remote.example.com/path/1588 HTTP/1.1
++Host: test.remote.example.com
++Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/1588", response="d0b2f000c7e3fca24452b5810713404a"
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://test.remote.example.com/path/1588 HTTP/1.1
++Host: test.remote.example.com
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://test.remote.example.com/path/1588 HTTP/1.1
++Host: test.remote.example.com
++Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/1588", response="d0b2f000c7e3fca24452b5810713404a"
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol>
++</verify>
++</testcase>
+diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
+index 639d010a00..3eeaed2f27 100644
+--- a/tests/libtest/Makefile.inc
++++ b/tests/libtest/Makefile.inc
+@@ -62,7 +62,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \
+ lib1540 lib1541 lib1542 lib1543 lib1545 \
+ lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \
+ lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 \
+- lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 lib1598 \
++ lib1588 lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 lib1598 \
+ \
+ lib1647 \
+ \
+@@ -520,6 +520,9 @@ lib1568_SOURCES = lib1568.c $(SUPPORTFILES)
+
+ lib1569_SOURCES = lib1569.c $(SUPPORTFILES)
+
++lib1588_SOURCES = lib1588.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
++lib1588_LDADD = $(TESTUTIL_LIBS)
++
+ lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+ lib1591_LDADD = $(TESTUTIL_LIBS)
+
+diff --git a/tests/libtest/lib1588.c b/tests/libtest/lib1588.c
+new file mode 100644
+index 0000000000..60d0dd43be
+--- /dev/null
++++ b/tests/libtest/lib1588.c
+@@ -0,0 +1,152 @@
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ * SPDX-License-Identifier: curl
++ *
++ ***************************************************************************/
++/*
++ * argv1 = URL
++ * argv2 = proxy host
++ * argv3 = proxy port
++ * argv4 = proxyuser:password
++ */
++
++#include "test.h"
++#include "testutil.h"
++
++static CURLcode init1588(CURL *curl, const char *url,
++ const char *userpwd, const char *proxy)
++{
++ CURLcode res = CURLE_OK;
++
++ res_easy_setopt(curl, CURLOPT_URL, url);
++ if(res)
++ goto init_failed;
++
++ res_easy_setopt(curl, CURLOPT_PROXY, proxy);
++ if(res)
++ goto init_failed;
++
++ res_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd);
++ if(res)
++ goto init_failed;
++
++ res_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
++ if(res)
++ goto init_failed;
++
++ res_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
++ if(res)
++ goto init_failed;
++#if 0
++ res_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L);
++ if(res)
++ goto init_failed;
++#endif
++
++ res_easy_setopt(curl, CURLOPT_HEADER, 1L);
++ if(res)
++ goto init_failed;
++
++ return CURLE_OK; /* success */
++
++init_failed:
++ return res; /* failure */
++}
++
++static CURLcode run1588(CURL *curl, const char *url, const char *userpwd,
++ const char *proxy)
++{
++ CURLcode result = CURLE_OK;
++
++ result = init1588(curl, url, userpwd, proxy);
++ if(result)
++ return result;
++
++ return curl_easy_perform(curl);
++}
++
++int test(char *URL)
++{
++ int res = CURLE_OK;
++ CURL *curl = NULL;
++ const char *proxyuserpws;
++ struct curl_slist *host = NULL;
++ struct curl_slist *host2 = NULL;
++ char proxy1_resolve[128];
++ char proxy2_resolve[128];
++ char proxy1_connect[128];
++ char proxy2_connect[128];
++
++ if(test_argc < 5)
++ return TEST_ERR_MAJOR_BAD;
++ proxyuserpws = test_argv[4];
++
++ curl_msnprintf(proxy1_resolve, sizeof(proxy1_resolve),
++ "firstproxy:%s:%s", libtest_arg3, libtest_arg2);
++ curl_msnprintf(proxy2_resolve, sizeof(proxy2_resolve),
++ "secondproxy:%s:%s", libtest_arg3, libtest_arg2);
++
++ /* we connect to the fake host name but the right port number */
++ curl_msnprintf(proxy1_connect, sizeof(proxy1_connect),
++ "firstproxy:%s", libtest_arg3);
++ curl_msnprintf(proxy2_connect, sizeof(proxy2_connect),
++ "secondproxy:%s", libtest_arg3);
++
++ res_global_init(CURL_GLOBAL_ALL);
++ if(res)
++ return res;
++
++ curl = curl_easy_init();
++ if(!curl) {
++ curl_mfprintf(stderr, "curl_easy_init() failed\n");
++ curl_global_cleanup();
++ return TEST_ERR_MAJOR_BAD;
++ }
++
++ host = curl_slist_append(NULL, proxy1_resolve);
++ if(!host)
++ goto test_cleanup;
++ host2 = curl_slist_append(host, proxy2_resolve);
++ if(!host2)
++ goto test_cleanup;
++ host = host2;
++
++ start_test_timing();
++
++ easy_setopt(curl, CURLOPT_RESOLVE, host);
++
++ res = run1588(curl, URL, proxyuserpws, proxy1_connect);
++ if(res)
++ goto test_cleanup;
++
++ curl_mfprintf(stderr, "lib1588: now we do the request again\n");
++
++ res = run1588(curl, URL, proxyuserpws, proxy2_connect);
++
++test_cleanup:
++
++ /* proper cleanup sequence - type PB */
++
++ curl_easy_cleanup(curl);
++ curl_global_cleanup();
++ curl_slist_free_all(host);
++ return res;
++}
diff --git a/meta/recipes-support/curl/curl_8.7.1.bb b/meta/recipes-support/curl/curl_8.7.1.bb
index 00a92d8..4ce564a 100644
--- a/meta/recipes-support/curl/curl_8.7.1.bb
+++ b/meta/recipes-support/curl/curl_8.7.1.bb
@@ -47,6 +47,7 @@ SRC_URI = " \
file://CVE-2026-8927.patch \
file://CVE-2026-8932.patch \
file://CVE-2026-6429.patch \
+ file://CVE-2026-7168.patch \
"
SRC_URI:append:class-nativesdk = " \
--
2.35.6
^ permalink raw reply related [flat|nested] 4+ messages in thread