From 11df1251e550c5b4b77a4c66bca96cbbc09cdcc4 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 13 May 2026 09:55:36 +0200 Subject: [PATCH] snpego_sspi: preserve distinction btw policy-only and uncond delegation CURLOPT_GSSAPI_DELEGATION exposes distinct modes: CURLGSSAPI_DELEGATION_POLICY_FLAG is documented as delegating only when OK-AS-DELEGATE policy permits it, while CURLGSSAPI_DELEGATION_FLAG is unconditional. The new SSPI implementation checks for either bit and sets ISC_REQ_DELEGATE, so a caller requesting policy-limited delegation is put on the same SSPI path as unconditional delegation. In addition, curl's existing protection that avoids reusing a connection when the GSS delegation setting differs was guarded only by HAVE_GSSAPI; SSPI-only builds now have an effective delegation option, but the connection's delegation setting was neither copied nor compared. This would cause Windows SSPI Negotiate/Kerberos authentication to delegate credentials contrary to the caller's selected policy or reuse an already-delegated authenticated connection for a transfer that requested no delegation. Follow-up to cc6777d939976b2f322dcbe5a Reported by Codex Security Closes #21583 --- lib/url.c | 8 ++++---- lib/vauth/spnego_sspi.c | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/url.c b/lib/url.c index 5159b25e50..bcd8f54aa8 100644 --- a/lib/url.c +++ b/lib/url.c @@ -943,9 +943,9 @@ static bool url_match_auth(struct connectdata *conn, if(!Curl_creds_same(m->data->state.creds, conn->creds)) return FALSE; } -#ifdef HAVE_GSSAPI - /* GSS delegation differences do not actually affect every connection - and auth method, but this check takes precaution before efficiency */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + /* GSS delegation differences do not actually affect every connection and + auth method, but this check takes precaution before efficiency */ if(m->needle->gssapi_delegation != conn->gssapi_delegation) return FALSE; #endif @@ -1340,7 +1340,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->fclosesocket = data->set.fclosesocket; conn->closesocket_client = data->set.closesocket_client; conn->lastused = conn->created; -#ifdef HAVE_GSSAPI +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) conn->gssapi_delegation = data->set.gssapi_delegation; #endif DEBUGF(infof(data, "alloc connection, bits.close=%d", conn->bits.close)); diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c index d636dfbed4..8808631e49 100644 --- a/lib/vauth/spnego_sspi.c +++ b/lib/vauth/spnego_sspi.c @@ -227,8 +227,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, /* Generate our challenge-response message */ { DWORD sspi_flags = ISC_REQ_CONFIDENTIALITY; - if(data->set.gssapi_delegation & (CURLGSSAPI_DELEGATION_FLAG | - CURLGSSAPI_DELEGATION_POLICY_FLAG)) + if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) sspi_flags |= ISC_REQ_DELEGATE | ISC_REQ_MUTUAL_AUTH; nego->status = Curl_pSecFn->InitializeSecurityContext(nego->credentials,