Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions SPECS/curl/CVE-2026-1965.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
From 34fa034d9a390c4bd65e2d05262755ec8646ac12 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 5 Feb 2026 08:34:21 +0100
Subject: [PATCH] url: fix reuse of connections using HTTP Negotiate

Assume Negotiate means connection-based

Reported-by: Zhicheng Chen
Closes #20534

Upstream reference:
origin: https://github.com/curl/curl/commit/34fa034d9a390c4bd65e2d05262755ec8646ac12.patch & https://github.com/curl/curl/commit/f1a39f221d57354990e3eeeddc3404aede2aff70.patch
Backported patch: https://git.launchpad.net/ubuntu/+source/curl/commit/?id=74697d38d36fa04b9656361a714b7a3d863e43b9
---
lib/url.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)

diff --git a/lib/url.c b/lib/url.c
index 10d875a..6ad8115 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -935,6 +935,18 @@ ConnectionExists(struct Curl_easy *data,
#else
bool wantProxyNTLMhttp = FALSE;
#endif
+#endif
+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+ bool wantNegohttp =
+ (data->state.authhost.want & CURLAUTH_NEGOTIATE) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
+#ifndef CURL_DISABLE_PROXY
+ bool wantProxyNegohttp =
+ needle->bits.proxy_user_passwd &&
+ (data->state.authproxy.want & CURLAUTH_NEGOTIATE) &&
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
+#endif
#endif
/* plain HTTP with upgrade */
bool h2upgrade = (data->state.httpwant == CURL_HTTP_VERSION_2_0) &&
@@ -1273,6 +1285,56 @@ ConnectionExists(struct Curl_easy *data,
}
#endif

+#ifdef USE_SPNEGO
+ /* If we are looking for an HTTP+Negotiate connection, check if this is
+ already authenticating with the right credentials. If not, keep looking
+ so that we can reuse Negotiate connections if possible. */
+ if(wantNegohttp) {
+ if(Curl_timestrcmp(needle->user, check->user) ||
+ Curl_timestrcmp(needle->passwd, check->passwd))
+ continue;
+ }
+ else if(check->http_negotiate_state != GSS_AUTHNONE) {
+ /* Connection is using Negotiate auth but we do not want Negotiate */
+ continue;
+ }
+
+#ifndef CURL_DISABLE_PROXY
+ /* Same for Proxy Negotiate authentication */
+ if(wantProxyNegohttp) {
+ /* Both check->http_proxy.user and check->http_proxy.passwd can be
+ * NULL */
+ if(!check->http_proxy.user || !check->http_proxy.passwd)
+ continue;
+
+ if(Curl_timestrcmp(needle->http_proxy.user,
+ check->http_proxy.user) ||
+ Curl_timestrcmp(needle->http_proxy.passwd,
+ check->http_proxy.passwd))
+ continue;
+ }
+ else if(check->proxy_negotiate_state != GSS_AUTHNONE) {
+ /* Proxy connection is using Negotiate auth but we do not want Negotiate */
+ continue;
+ }
+#endif
+ if(wantNegohttp || wantProxyNegohttp) {
+ /* Credentials are already checked, we may use this connection. We MUST
+ * use a connection where it has already been fully negotiated. If it has
+ * not, we keep on looking for a better one. */
+ chosen = check;
+ if((wantNegohttp &&
+ (check->http_negotiate_state != GSS_AUTHNONE)) ||
+ (wantProxyNegohttp &&
+ (check->proxy_negotiate_state != GSS_AUTHNONE))) {
+ /* We must use this connection, no other */
+ *force_reuse = TRUE;
+ break;
+ }
+ continue; /* get another */
+ }
+#endif
+
if(CONN_INUSE(check)) {
DEBUGASSERT(canmultiplex);
DEBUGASSERT(check->bits.multiplex);
--
2.43.0

149 changes: 149 additions & 0 deletions SPECS/curl/CVE-2026-3783.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
From e3d7401a32a46516c9e5ee877e613e62ed35bddc Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 6 Mar 2026 23:13:07 +0100
Subject: [PATCH] http: only send bearer if auth is allowed

Verify with test 2006

Closes #20843

Upstream Patch reference: https://github.com/curl/curl/commit/e3d7401a32a46516c9e5ee877e613e62ed35bddc.patch
---
lib/http.c | 1 +
tests/data/Makefile.inc | 2 +-
tests/data/test2006 | 98 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 tests/data/test2006

diff --git a/lib/http.c b/lib/http.c
index 2a41f80..093954f 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -659,6 +659,7 @@ output_auth_headers(struct Curl_easy *data,
if(authstatus->picked == CURLAUTH_BEARER) {
/* Bearer */
if((!proxy && data->set.str[STRING_BEARER] &&
+ Curl_auth_allowed_to_host(data) &&
!Curl_checkheaders(data, STRCONST("Authorization")))) {
auth = "Bearer";
result = http_output_bearer(data);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index f34dd00..16af0e5 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -231,7 +231,7 @@ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
test1955 test1956 test1957 test1958 test1959 test1960 test1964 \
test1970 test1971 test1972 test1973 test1974 test1975 \
\
-test2000 test2001 test2002 test2003 test2004 \
+test2000 test2001 test2002 test2003 test2004 test2006 \
\
test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
diff --git a/tests/data/test2006 b/tests/data/test2006
new file mode 100644
index 0000000..4b8b269
--- /dev/null
+++ b/tests/data/test2006
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+netrc
+HTTP
+</keywords>
+</info>
+# Server-side
+<reply>
+<data crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+-foo-
+</data>
+
+<data2 crlf="yes">
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</data2>
+
+<datacheck crlf="yes">
+HTTP/1.1 301 Follow this you fool
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 6
+Connection: close
+Location: http://b.com/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
+ETag: "21025-dc7-39462498"
+Accept-Ranges: bytes
+Content-Length: 7
+Connection: close
+
+target
+</datacheck>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+proxy
+</features>
+<name>
+.netrc default with redirect plus oauth2-bearer
+</name>
+<command>
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER --oauth2-bearer SECRET_TOKEN -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/
+</command>
+<file name="%LOGDIR/netrc%TESTNUMBER" >
+default login testuser password testpass
+</file>
+</client>
+
+<verify>
+<protocol crlf="yes">
+GET http://a.com/ HTTP/1.1
+Host: a.com
+Authorization: Bearer SECRET_TOKEN
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://b.com/%TESTNUMBER0002 HTTP/1.1
+Host: b.com
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>
--
2.43.0

Loading
Loading