|
| 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 | + |
0 commit comments