diff --git a/lib/creds.h b/lib/creds.h index 36deff323e..0664d08a4f 100644 --- a/lib/creds.h +++ b/lib/creds.h @@ -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 : "") diff --git a/lib/http.c b/lib/http.c index e3697b1fa9..83d0e01152 100644 --- a/lib/http.c +++ b/lib/http.c @@ -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); diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 0d5277d55b..a1d75ab305 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -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 \ diff --git a/tests/data/test2208 b/tests/data/test2208 new file mode 100644 index 0000000000..354d1a2a7e --- /dev/null +++ b/tests/data/test2208 @@ -0,0 +1,90 @@ + + + + +HTTP +HTTP proxy +--location +HTTP Basic auth + + + +# Server-side + + +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 + + + +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 + + + + +# Client-side + + +proxy + + +http + + +HTTP auth on redirect with empty URL userinfo + + +-x http://%HOSTIP:%HTTPPORT http://firsthost.com -L -u joe:secret + + + +# Verify data after the test has been "shot" + + +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 + + + +