Skip to content

Commit 188c2f1

Browse files
committed
http: clear the proxy credentials as well on port or scheme change
Add tests 2009-2011 to verify switching between proxies with credentials when the switch is driven by a redirect Reported-by: Dwij Mehta Closes #21304
1 parent 9ceb3ff commit 188c2f1

7 files changed

Lines changed: 262 additions & 16 deletions

File tree

lib/http.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,12 +1278,24 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl,
12781278
curlx_free(scheme);
12791279
}
12801280
if(clear) {
1281+
CURLcode result = Curl_reset_userpwd(data);
1282+
if(result) {
1283+
curlx_free(follow_url);
1284+
return result;
1285+
}
12811286
curlx_safefree(data->state.aptr.user);
12821287
curlx_safefree(data->state.aptr.passwd);
12831288
}
12841289
}
12851290
}
12861291
DEBUGASSERT(follow_url);
1292+
{
1293+
CURLcode result = Curl_reset_proxypwd(data);
1294+
if(result) {
1295+
curlx_free(follow_url);
1296+
return result;
1297+
}
1298+
}
12871299

12881300
if(type == FOLLOW_FAKE) {
12891301
/* we are only figuring out the new URL if we would have followed locations

lib/transfer.c

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,40 @@ void Curl_init_CONNECT(struct Curl_easy *data)
438438
data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
439439
}
440440

441+
/*
442+
* Restore the user credentials to those set in options.
443+
*/
444+
CURLcode Curl_reset_userpwd(struct Curl_easy *data)
445+
{
446+
CURLcode result;
447+
if(data->set.str[STRING_USERNAME] || data->set.str[STRING_PASSWORD])
448+
data->state.creds_from = CREDS_OPTION;
449+
result = Curl_setstropt(&data->state.aptr.user,
450+
data->set.str[STRING_USERNAME]);
451+
if(!result)
452+
result = Curl_setstropt(&data->state.aptr.passwd,
453+
data->set.str[STRING_PASSWORD]);
454+
return result;
455+
}
456+
457+
/*
458+
* Restore the proxy credentials to those set in options.
459+
*/
460+
CURLcode Curl_reset_proxypwd(struct Curl_easy *data)
461+
{
462+
#ifndef CURL_DISABLE_PROXY
463+
CURLcode result = Curl_setstropt(&data->state.aptr.proxyuser,
464+
data->set.str[STRING_PROXYUSERNAME]);
465+
if(!result)
466+
result = Curl_setstropt(&data->state.aptr.proxypasswd,
467+
data->set.str[STRING_PROXYPASSWORD]);
468+
return result;
469+
#else
470+
(void)data;
471+
return CURLE_OK;
472+
#endif
473+
}
474+
441475
/*
442476
* Curl_pretransfer() is called immediately before a transfer starts, and only
443477
* once for one transfer no matter if it has redirects or do multi-pass
@@ -586,23 +620,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
586620
return CURLE_OUT_OF_MEMORY;
587621
}
588622

589-
if(data->set.str[STRING_USERNAME] ||
590-
data->set.str[STRING_PASSWORD])
591-
data->state.creds_from = CREDS_OPTION;
592623
if(!result)
593-
result = Curl_setstropt(&data->state.aptr.user,
594-
data->set.str[STRING_USERNAME]);
624+
result = Curl_reset_userpwd(data);
595625
if(!result)
596-
result = Curl_setstropt(&data->state.aptr.passwd,
597-
data->set.str[STRING_PASSWORD]);
598-
#ifndef CURL_DISABLE_PROXY
599-
if(!result)
600-
result = Curl_setstropt(&data->state.aptr.proxyuser,
601-
data->set.str[STRING_PROXYUSERNAME]);
602-
if(!result)
603-
result = Curl_setstropt(&data->state.aptr.proxypasswd,
604-
data->set.str[STRING_PROXYPASSWORD]);
605-
#endif
626+
result = Curl_reset_proxypwd(data);
606627

607628
data->req.headerbytecount = 0;
608629
Curl_headers_cleanup(data);

lib/transfer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ char *Curl_checkheaders(const struct Curl_easy *data,
3131

3232
void Curl_init_CONNECT(struct Curl_easy *data);
3333

34+
CURLcode Curl_reset_userpwd(struct Curl_easy *data);
35+
CURLcode Curl_reset_proxypwd(struct Curl_easy *data);
3436
CURLcode Curl_pretransfer(struct Curl_easy *data);
3537

3638
CURLcode Curl_sendrecv(struct Curl_easy *data);

tests/data/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 \
244244
test1978 test1979 test1980 test1981 test1982 test1983 test1984 \
245245
\
246246
test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
247-
test2008 \
247+
test2008 test2009 test2010 test2011 \
248248
\
249249
test2023 \
250250
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \

tests/data/test2009

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="US-ASCII"?>
2+
<testcase>
3+
<info>
4+
<keywords>
5+
HTTP
6+
HTTP proxy
7+
http_proxy
8+
</keywords>
9+
</info>
10+
# Server-side
11+
<reply>
12+
<connect>
13+
HTTP/1.1 407 Denied
14+
15+
</connect>
16+
<data crlf="headers" nocheck="yes">
17+
HTTP/1.1 301 redirect
18+
Date: Tue, 09 Nov 2010 14:49:00 GMT
19+
Server: test-server/fake
20+
Content-Length: 4
21+
Content-Type: text/html
22+
Location: https://another.example/%TESTNUMBER0002
23+
24+
boo
25+
</data>
26+
</reply>
27+
28+
# Client-side
29+
<client>
30+
<features>
31+
proxy
32+
</features>
33+
<server>
34+
http
35+
https
36+
</server>
37+
<name>
38+
proxy credentials via env variables, redirect from http to https
39+
</name>
40+
41+
<setenv>
42+
http_proxy=http://user:secret@%HOSTIP:%HTTPPORT
43+
https_proxy=https://%HOSTIP:%HTTPSPORT/
44+
</setenv>
45+
<command>
46+
http://somewhere.example/ --follow --proxy-insecure
47+
</command>
48+
</client>
49+
50+
# Verify data after the test has been "shot"
51+
<verify>
52+
<protocol crlf="headers">
53+
GET http://somewhere.example/ HTTP/1.1
54+
Host: somewhere.example
55+
Proxy-Authorization: Basic %b64[user:secret]b64%
56+
User-Agent: curl/%VERSION
57+
Accept: */*
58+
Proxy-Connection: Keep-Alive
59+
60+
CONNECT another.example:443 HTTP/1.1
61+
Host: another.example:443
62+
User-Agent: curl/%VERSION
63+
Proxy-Connection: Keep-Alive
64+
65+
</protocol>
66+
<errorcode>
67+
7
68+
</errorcode>
69+
</verify>
70+
</testcase>

tests/data/test2010

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?xml version="1.0" encoding="US-ASCII"?>
2+
<testcase>
3+
<info>
4+
<keywords>
5+
HTTP
6+
HTTP proxy
7+
http_proxy
8+
</keywords>
9+
</info>
10+
# Server-side
11+
<reply>
12+
<connect>
13+
HTTP/1.1 407 Denied
14+
15+
</connect>
16+
<data crlf="headers" nocheck="yes">
17+
HTTP/1.1 301 redirect
18+
Date: Tue, 09 Nov 2010 14:49:00 GMT
19+
Server: test-server/fake
20+
Content-Length: 4
21+
Content-Type: text/html
22+
Location: https://another.example/%TESTNUMBER0002
23+
24+
boo
25+
</data>
26+
</reply>
27+
28+
# Client-side
29+
<client>
30+
<features>
31+
proxy
32+
</features>
33+
<server>
34+
http
35+
https
36+
</server>
37+
<name>
38+
proxy credentials via options for two proxies, redirect from http to https
39+
</name>
40+
41+
<setenv>
42+
http_proxy=http://%HOSTIP:%HTTPPORT
43+
https_proxy=https://%HOSTIP:%HTTPSPORT/
44+
</setenv>
45+
<command>
46+
--proxy-user batman:robin http://somewhere.example/ --follow --proxy-insecure
47+
</command>
48+
</client>
49+
50+
# Verify data after the test has been "shot"
51+
<verify>
52+
<protocol crlf="headers">
53+
GET http://somewhere.example/ HTTP/1.1
54+
Host: somewhere.example
55+
Proxy-Authorization: Basic %b64[batman:robin]b64%
56+
User-Agent: curl/%VERSION
57+
Accept: */*
58+
Proxy-Connection: Keep-Alive
59+
60+
CONNECT another.example:443 HTTP/1.1
61+
Host: another.example:443
62+
Proxy-Authorization: Basic %b64[batman:robin]b64%
63+
User-Agent: curl/%VERSION
64+
Proxy-Connection: Keep-Alive
65+
66+
</protocol>
67+
<errorcode>
68+
7
69+
</errorcode>
70+
</verify>
71+
</testcase>

tests/data/test2011

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="US-ASCII"?>
2+
<testcase>
3+
<info>
4+
<keywords>
5+
HTTP
6+
HTTP proxy
7+
http_proxy
8+
</keywords>
9+
</info>
10+
# Server-side
11+
<reply>
12+
<connect>
13+
HTTP/1.1 407 Denied
14+
15+
</connect>
16+
<data crlf="headers" nocheck="yes">
17+
HTTP/1.1 301 redirect
18+
Date: Tue, 09 Nov 2010 14:49:00 GMT
19+
Server: test-server/fake
20+
Content-Length: 4
21+
Content-Type: text/html
22+
Location: https://another.example/%TESTNUMBER0002
23+
24+
boo
25+
</data>
26+
</reply>
27+
28+
# Client-side
29+
<client>
30+
<features>
31+
proxy
32+
</features>
33+
<server>
34+
http
35+
https
36+
</server>
37+
<name>
38+
proxy creds via env, cross-scheme redirect, --location-trusted
39+
</name>
40+
41+
<setenv>
42+
http_proxy=http://user:secret@%HOSTIP:%HTTPPORT
43+
https_proxy=https://%HOSTIP:%HTTPSPORT/
44+
</setenv>
45+
<command>
46+
http://somewhere.example/ --location-trusted --proxy-insecure
47+
</command>
48+
</client>
49+
50+
# Verify data after the test has been "shot"
51+
<verify>
52+
<protocol crlf="headers">
53+
GET http://somewhere.example/ HTTP/1.1
54+
Host: somewhere.example
55+
Proxy-Authorization: Basic %b64[user:secret]b64%
56+
User-Agent: curl/%VERSION
57+
Accept: */*
58+
Proxy-Connection: Keep-Alive
59+
60+
CONNECT another.example:443 HTTP/1.1
61+
Host: another.example:443
62+
User-Agent: curl/%VERSION
63+
Proxy-Connection: Keep-Alive
64+
65+
</protocol>
66+
<errorcode>
67+
7
68+
</errorcode>
69+
</verify>
70+
</testcase>

0 commit comments

Comments
 (0)