← Commit list

d2886c5ac4

Stefan Eissing
Stefan Eissing
2026-06-17
SUCCESS Duration: 203s

Subject

http: for basic+digest auth, do not engage on empty user+passwd

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/creds.h+2 -0
@@ -73,6 +73,8 @@ bool Curl_creds_equal(struct Curl_creds *c1, struct Curl_creds *c2);
/* Provides properties for creds or, if creds is NULL, the empty string */
#define Curl_creds_has_user(c) ((c) && (c)->user[0])
#define Curl_creds_has_passwd(c) ((c) && (c)->passwd[0])
+#define Curl_creds_has_user_or_pass(c) \
+ ((c) && ((c)->user[0] || (c)->passwd[0]))
#define Curl_creds_has_oauth_bearer(c) ((c) && (c)->oauth_bearer[0])
#define Curl_creds_has_sasl_service(c) ((c) && (c)->sasl_service[0])
#define Curl_creds_user(c) ((c) ? (c)->user : "")
lib/http.c+12 -7
@@ -347,8 +347,10 @@ fail:
*
* return TRUE if one was picked
*/
-static bool pickoneauth(struct auth *pick, unsigned long mask)
+static bool pickoneauth(struct auth *pick, unsigned long mask,
+ struct Curl_creds *creds)
{
+ bool have_user_pass = Curl_creds_has_user_or_pass(creds);
bool picked;
/* only deal with authentication we want */
unsigned long avail = pick->avail & pick->want & mask;
@@ -356,20 +358,20 @@ static bool pickoneauth(struct auth *pick, unsigned long mask)
/* The order of these checks is highly relevant, as this will be the order
of preference in case of the existence of multiple accepted types. */
- if(avail & CURLAUTH_NEGOTIATE)
+ if(avail & CURLAUTH_NEGOTIATE) /* available on empty creds */
pick->picked = CURLAUTH_NEGOTIATE;
#ifndef CURL_DISABLE_BEARER_AUTH
- else if(avail & CURLAUTH_BEARER)
+ else if((avail & CURLAUTH_BEARER) && Curl_creds_has_oauth_bearer(creds))
pick->picked = CURLAUTH_BEARER;
#endif
#ifndef CURL_DISABLE_DIGEST_AUTH
- else if(avail & CURLAUTH_DIGEST)
+ else if((avail & CURLAUTH_DIGEST) && have_user_pass)
pick->picked = CURLAUTH_DIGEST;
#endif
else if(avail & CURLAUTH_NTLM)
pick->picked = CURLAUTH_NTLM;
#ifndef CURL_DISABLE_BASIC_AUTH
- else if(avail & CURLAUTH_BASIC)
+ else if((avail & CURLAUTH_BASIC) && have_user_pass)
pick->picked = CURLAUTH_BASIC;
#endif
#ifndef CURL_DISABLE_AWS
@@ -568,7 +570,7 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
if(data->state.creds &&
((data->req.httpcode == 401) ||
(data->req.authneg && data->req.httpcode < 300))) {
- pickhost = pickoneauth(&data->state.authhost, authmask);
+ pickhost = pickoneauth(&data->state.authhost, authmask, data->state.creds);
if(!pickhost)
data->state.authproblem = TRUE;
else
@@ -586,7 +588,8 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data)
((data->req.httpcode == 407) ||
(data->req.authneg && data->req.httpcode < 300))) {
pickproxy = pickoneauth(&data->state.authproxy,
- authmask & ~CURLAUTH_BEARER);
+ authmask & ~CURLAUTH_BEARER,
+ conn->http_proxy.creds);
if(!pickproxy)
data->state.authproblem = TRUE;
else
@@ -699,10 +702,12 @@ static CURLcode output_auth_headers(struct Curl_easy *data,
if(
#ifndef CURL_DISABLE_PROXY
(proxy && conn->http_proxy.creds &&
+ Curl_creds_has_user_or_pass(conn->http_proxy.creds) &&
!Curl_checkProxyheaders(data, conn,
STRCONST("Proxy-authorization"))) ||
#endif
(!proxy && data->state.creds &&
+ Curl_creds_has_user_or_pass(data->state.creds) &&
!Curl_checkheaders(data, STRCONST("Authorization")))) {
auth = "Basic";
result = http_output_basic(data, conn, proxy);
tests/data/Makefile.am+1 -0
@@ -256,6 +256,7 @@ test2088 test2089 test2090 test2091 test2092 \
test2100 test2101 test2102 test2103 test2104 test2105 test2106 test2107 \
\
test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 \
+test2208 \
\
test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 \
test2309 test2310 \
tests/data/test2208+90 -0
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+--location
+HTTP Basic auth
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://@firsthost.com:9999/a/path/%TESTNUMBER0002
+
+</data>
+<data2>
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</data2>
+
+<datacheck>
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+Content-Type: text/html
+Location: http://@firsthost.com:9999/a/path/%TESTNUMBER0002
+
+HTTP/1.1 200 OK
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Connection: close
+Content-Type: text/html
+
+hey
+</datacheck>
+
+</reply>
+
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+</server>
+<name>
+HTTP auth on redirect with empty URL userinfo
+</name>
+<command>
+-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -u joe:secret
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+GET http://firsthost.com/ HTTP/1.1
+Host: firsthost.com
+Authorization: Basic %b64[joe:secret]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+GET http://firsthost.com:9999/a/path/%TESTNUMBER0002 HTTP/1.1
+Host: firsthost.com:9999
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+</protocol>
+</verify>
+</testcase>