Skip to content

Commit 176d71f

Browse files
[AutoPR- Security] Patch curl for CVE-2026-3784, CVE-2026-3783, CVE-2026-1965 [MEDIUM] (#16181)
Co-authored-by: akhila-guruju <v-guakhila@microsoft.com>
1 parent a6f47eb commit 176d71f

8 files changed

Lines changed: 476 additions & 16 deletions

File tree

SPECS/curl/CVE-2026-1965.patch

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
From 441e8ee4df3e576bf23c30eb31b9fef8c55f5663 Mon Sep 17 00:00:00 2001
2+
From: AllSpark <allspark@microsoft.com>
3+
Date: Thu, 12 Mar 2026 11:59:23 +0000
4+
Subject: [PATCH] url: fix reuse of connections using HTTP Negotiate;
5+
Follow-up: fix copy+paste mistake in url_match_auth_nego
6+
7+
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
8+
Upstream-reference: AI Backport of https://github.com/curl/curl/commit/34fa034d9a390c4bd65e2d05262755ec8646ac12.patch https://github.com/curl/curl/commit/f1a39f221d57354990e3eeeddc3404aede2aff70.patch
9+
---
10+
lib/url.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++----
11+
1 file changed, 85 insertions(+), 5 deletions(-)
12+
13+
diff --git a/lib/url.c b/lib/url.c
14+
index 436edd8..d62eefa 100644
15+
--- a/lib/url.c
16+
+++ b/lib/url.c
17+
@@ -853,6 +853,8 @@ struct url_conn_match {
18+
BIT(may_multiplex);
19+
BIT(want_ntlm_http);
20+
BIT(want_proxy_ntlm_http);
21+
+ BIT(want_nego_http);
22+
+ BIT(want_proxy_nego_http);
23+
24+
BIT(wait_pipe);
25+
BIT(force_reuse);
26+
@@ -861,6 +863,64 @@ struct url_conn_match {
27+
BIT(seen_multiplex_conn);
28+
};
29+
30+
+#if defined(USE_SPNEGO)
31+
+static bool url_match_auth_nego(struct connectdata *conn,
32+
+ struct url_conn_match *m)
33+
+{
34+
+ /* If we are looking for an HTTP+Negotiate connection, check if this is
35+
+ already authenticating with the right credentials. If not, keep looking
36+
+ so that we can reuse Negotiate connections if possible. */
37+
+ if(m->want_nego_http) {
38+
+ if(Curl_timestrcmp(m->needle->user, conn->user) ||
39+
+ Curl_timestrcmp(m->needle->passwd, conn->passwd))
40+
+ return FALSE;
41+
+ }
42+
+ else if(conn->http_negotiate_state != GSS_AUTHNONE) {
43+
+ /* Connection is using Negotiate auth but we do not want Negotiate */
44+
+ return FALSE;
45+
+ }
46+
+
47+
+#ifndef CURL_DISABLE_PROXY
48+
+ /* Same for Proxy Negotiate authentication */
49+
+ if(m->want_proxy_nego_http) {
50+
+ /* Both conn->http_proxy.user and conn->http_proxy.passwd can be
51+
+ * NULL */
52+
+ if(!conn->http_proxy.user || !conn->http_proxy.passwd)
53+
+ return FALSE;
54+
+
55+
+ if(Curl_timestrcmp(m->needle->http_proxy.user,
56+
+ conn->http_proxy.user) ||
57+
+ Curl_timestrcmp(m->needle->http_proxy.passwd,
58+
+ conn->http_proxy.passwd))
59+
+ return FALSE;
60+
+ }
61+
+ else if(conn->proxy_negotiate_state != GSS_AUTHNONE) {
62+
+ /* Proxy connection is using Negotiate auth but we do not want Negotiate */
63+
+ return FALSE;
64+
+ }
65+
+#endif
66+
+ if(m->want_nego_http || m->want_proxy_nego_http) {
67+
+ /* Credentials are already checked, we may use this connection. We MUST
68+
+ * use a connection where it has already been fully negotiated. If it has
69+
+ * not, we keep on looking for a better one. */
70+
+ m->found = conn;
71+
+ if((m->want_nego_http &&
72+
+ (conn->http_negotiate_state != GSS_AUTHNONE)) ||
73+
+ (m->want_proxy_nego_http &&
74+
+ (conn->proxy_negotiate_state != GSS_AUTHNONE))) {
75+
+ /* We must use this connection, no other */
76+
+ m->force_reuse = TRUE;
77+
+ return TRUE;
78+
+ }
79+
+ return FALSE; /* get another */
80+
+ }
81+
+ return TRUE;
82+
+}
83+
+#else
84+
+#define url_match_auth_nego(c, m) ((void)c, (void)m, TRUE)
85+
+#endif
86+
+
87+
+
88+
static bool url_match_conn(struct connectdata *conn, void *userdata)
89+
{
90+
struct url_conn_match *match = userdata;
91+
@@ -1156,6 +1216,13 @@ static bool url_match_conn(struct connectdata *conn, void *userdata)
92+
* If it has not, we keep on looking for a better one. */
93+
match->found = conn;
94+
95+
+
96+
+ if(!url_match_auth_nego(conn, match))
97+
+ return FALSE;
98+
+ else if(match->force_reuse)
99+
+ return TRUE;
100+
+
101+
+
102+
if((match->want_ntlm_http &&
103+
(conn->http_ntlm_state != NTLMSTATE_NONE)) ||
104+
(match->want_proxy_ntlm_http &&
105+
@@ -1251,13 +1318,26 @@ ConnectionExists(struct Curl_easy *data,
106+
match.may_multiplex = xfer_may_multiplex(data, needle);
107+
108+
#ifdef USE_NTLM
109+
- match.want_ntlm_http = ((data->state.authhost.want & CURLAUTH_NTLM) &&
110+
- (needle->handler->protocol & PROTO_FAMILY_HTTP));
111+
+ match.want_ntlm_http =
112+
+ (data->state.authhost.want & CURLAUTH_NTLM) &&
113+
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
114+
#ifndef CURL_DISABLE_PROXY
115+
match.want_proxy_ntlm_http =
116+
- (needle->bits.proxy_user_passwd &&
117+
- (data->state.authproxy.want & CURLAUTH_NTLM) &&
118+
- (needle->handler->protocol & PROTO_FAMILY_HTTP));
119+
+ needle->bits.proxy_user_passwd &&
120+
+ (data->state.authproxy.want & CURLAUTH_NTLM) &&
121+
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
122+
+#endif
123+
+#endif
124+
+
125+
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
126+
+ match.want_nego_http =
127+
+ (data->state.authhost.want & CURLAUTH_NEGOTIATE) &&
128+
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
129+
+#ifndef CURL_DISABLE_PROXY
130+
+ match.want_proxy_nego_http =
131+
+ needle->bits.proxy_user_passwd &&
132+
+ (data->state.authproxy.want & CURLAUTH_NEGOTIATE) &&
133+
+ (needle->handler->protocol & PROTO_FAMILY_HTTP);
134+
#endif
135+
#endif
136+
137+
--
138+
2.45.4
139+

SPECS/curl/CVE-2026-3783.patch

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
From e3d7401a32a46516c9e5ee877e613e62ed35bddc Mon Sep 17 00:00:00 2001
2+
From: Daniel Stenberg <daniel@haxx.se>
3+
Date: Fri, 6 Mar 2026 23:13:07 +0100
4+
Subject: [PATCH] http: only send bearer if auth is allowed
5+
6+
Verify with test 2006
7+
8+
Closes #20843
9+
10+
Upstream Patch reference: https://github.com/curl/curl/commit/e3d7401a32a46516c9e5ee877e613e62ed35bddc.patch
11+
---
12+
lib/http.c | 1 +
13+
tests/data/Makefile.am | 2 +-
14+
tests/data/test2006 | 98 ++++++++++++++++++++++++++++++++++++++++++
15+
3 files changed, 100 insertions(+), 1 deletion(-)
16+
create mode 100644 tests/data/test2006
17+
18+
diff --git a/lib/http.c b/lib/http.c
19+
index 35e7085..4de1667 100644
20+
--- a/lib/http.c
21+
+++ b/lib/http.c
22+
@@ -650,6 +650,7 @@ output_auth_headers(struct Curl_easy *data,
23+
if(authstatus->picked == CURLAUTH_BEARER) {
24+
/* Bearer */
25+
if((!proxy && data->set.str[STRING_BEARER] &&
26+
+ Curl_auth_allowed_to_host(data) &&
27+
!Curl_checkheaders(data, STRCONST("Authorization")))) {
28+
auth = "Bearer";
29+
result = http_output_bearer(data);
30+
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
31+
index 776b593..26e015f 100644
32+
--- a/tests/data/Makefile.am
33+
+++ b/tests/data/Makefile.am
34+
@@ -238,7 +238,7 @@ test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 \
35+
test1955 test1956 test1957 test1958 test1959 test1960 test1964 \
36+
test1970 test1971 test1972 test1973 test1974 test1975 test1976 \
37+
\
38+
-test2000 test2001 test2002 test2003 test2004 \
39+
+test2000 test2001 test2002 test2003 test2004 test2006 \
40+
\
41+
test2023 \
42+
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
43+
diff --git a/tests/data/test2006 b/tests/data/test2006
44+
new file mode 100644
45+
index 0000000..4b8b269
46+
--- /dev/null
47+
+++ b/tests/data/test2006
48+
@@ -0,0 +1,98 @@
49+
+<?xml version="1.0" encoding="US-ASCII"?>
50+
+<testcase>
51+
+<info>
52+
+<keywords>
53+
+netrc
54+
+HTTP
55+
+</keywords>
56+
+</info>
57+
+# Server-side
58+
+<reply>
59+
+<data crlf="yes">
60+
+HTTP/1.1 301 Follow this you fool
61+
+Date: Tue, 09 Nov 2010 14:49:00 GMT
62+
+Server: test-server/fake
63+
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
64+
+ETag: "21025-dc7-39462498"
65+
+Accept-Ranges: bytes
66+
+Content-Length: 6
67+
+Connection: close
68+
+Location: http://b.com/%TESTNUMBER0002
69+
+
70+
+-foo-
71+
+</data>
72+
+
73+
+<data2 crlf="yes">
74+
+HTTP/1.1 200 OK
75+
+Date: Tue, 09 Nov 2010 14:49:00 GMT
76+
+Server: test-server/fake
77+
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
78+
+ETag: "21025-dc7-39462498"
79+
+Accept-Ranges: bytes
80+
+Content-Length: 7
81+
+Connection: close
82+
+
83+
+target
84+
+</data2>
85+
+
86+
+<datacheck crlf="yes">
87+
+HTTP/1.1 301 Follow this you fool
88+
+Date: Tue, 09 Nov 2010 14:49:00 GMT
89+
+Server: test-server/fake
90+
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
91+
+ETag: "21025-dc7-39462498"
92+
+Accept-Ranges: bytes
93+
+Content-Length: 6
94+
+Connection: close
95+
+Location: http://b.com/%TESTNUMBER0002
96+
+
97+
+HTTP/1.1 200 OK
98+
+Date: Tue, 09 Nov 2010 14:49:00 GMT
99+
+Server: test-server/fake
100+
+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT
101+
+ETag: "21025-dc7-39462498"
102+
+Accept-Ranges: bytes
103+
+Content-Length: 7
104+
+Connection: close
105+
+
106+
+target
107+
+</datacheck>
108+
+</reply>
109+
+
110+
+# Client-side
111+
+<client>
112+
+<server>
113+
+http
114+
+</server>
115+
+<features>
116+
+proxy
117+
+</features>
118+
+<name>
119+
+.netrc default with redirect plus oauth2-bearer
120+
+</name>
121+
+<command>
122+
+--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER --oauth2-bearer SECRET_TOKEN -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/
123+
+</command>
124+
+<file name="%LOGDIR/netrc%TESTNUMBER" >
125+
+default login testuser password testpass
126+
+</file>
127+
+</client>
128+
+
129+
+<verify>
130+
+<protocol crlf="yes">
131+
+GET http://a.com/ HTTP/1.1
132+
+Host: a.com
133+
+Authorization: Bearer SECRET_TOKEN
134+
+User-Agent: curl/%VERSION
135+
+Accept: */*
136+
+Proxy-Connection: Keep-Alive
137+
+
138+
+GET http://b.com/%TESTNUMBER0002 HTTP/1.1
139+
+Host: b.com
140+
+User-Agent: curl/%VERSION
141+
+Accept: */*
142+
+Proxy-Connection: Keep-Alive
143+
+
144+
+</protocol>
145+
+</verify>
146+
+</testcase>
147+
--
148+
2.43.0
149+

0 commit comments

Comments
 (0)