diff --git a/lib/http.c b/lib/http.c index 34fa807d8d..b6c1de0b61 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1227,75 +1227,41 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, return CURLE_OUT_OF_MEMORY; } else { - uc = curl_url_get(data->state.uh, CURLUPART_URL, &follow_url, 0); - if(uc) + bool same_origin; + CURLcode result; + CURLU *u = curl_url(); + if(!u) + return CURLE_OUT_OF_MEMORY; + uc = curl_url_set(u, CURLUPART_URL, + Curl_bufref_ptr(&data->state.url), + CURLU_URLENCODE | CURLU_ALLOW_SPACE); + if(!uc) + uc = curl_url_get(data->state.uh, CURLUPART_URL, &follow_url, 0); + if(uc) { + curl_url_cleanup(u); return Curl_uc_to_curlcode(uc); - - /* Clear auth if this redirects to a different port number or protocol, - unless permitted */ - if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { - uint16_t port; - bool clear = FALSE; - - if(data->set.use_port && data->state.allow_port) - /* a custom port is used */ - port = data->set.use_port; - else { - curl_off_t value; - char *portnum; - const char *p; - uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, - CURLU_DEFAULT_PORT); - if(uc) { - curlx_free(follow_url); - return Curl_uc_to_curlcode(uc); - } - p = portnum; - curlx_str_number(&p, &value, 0xffff); - port = (uint16_t)value; - curlx_free(portnum); - } - if(port != data->info.conn_remote_port) { - infof(data, "Clear auth, redirects to port from %d to %d", - data->info.conn_remote_port, port); - clear = TRUE; - } - else { - char *scheme; - const struct Curl_scheme *p; - uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); - if(uc) { - curlx_free(follow_url); - return Curl_uc_to_curlcode(uc); - } - - p = Curl_get_scheme(scheme); - if(p && (p->protocol != data->info.conn_protocol)) { - infof(data, "Clear auth, redirects scheme from %s to %s", - data->info.conn_scheme, scheme); - clear = TRUE; - } - curlx_free(scheme); - } - if(clear) { - CURLcode result = Curl_reset_userpwd(data); - if(result) { - curlx_free(follow_url); - return result; - } - curlx_safefree(data->state.aptr.user); - curlx_safefree(data->state.aptr.passwd); - } } - } - DEBUGASSERT(follow_url); - { - CURLcode result = Curl_reset_proxypwd(data); + + same_origin = Curl_url_same_origin(u, data->state.uh); + curl_url_cleanup(u); + + if((!same_origin && !data->set.allow_auth_to_other_hosts) || + !data->set.str[STRING_USERNAME]) { + result = Curl_reset_userpwd(data); + if(result) { + curlx_free(follow_url); + return result; + } + curlx_safefree(data->state.aptr.user); + curlx_safefree(data->state.aptr.passwd); + } + result = Curl_reset_proxypwd(data); if(result) { curlx_free(follow_url); return result; } } + DEBUGASSERT(follow_url); if(type == FOLLOW_FAKE) { /* we are only figuring out the new URL if we would have followed locations diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 857389450e..e955c8383f 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -265,7 +265,7 @@ test2309 \ \ test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 \ \ -test2500 test2501 test2502 test2503 test2504 test2505 \ +test2500 test2501 test2502 test2503 test2504 test2505 test2506 \ \ test2600 test2601 test2602 test2603 test2604 test2605 \ \ diff --git a/tests/data/test2506 b/tests/data/test2506 new file mode 100644 index 0000000000..9c65002496 --- /dev/null +++ b/tests/data/test2506 @@ -0,0 +1,64 @@ + + + + +HTTP +cookies + + + + + +HTTP/1.1 301 redirect +Date: Tue, 09 Nov 2010 14:49:00 GMT +Content-Length: 3 +Location: http://numbertwo.example/%TESTNUMBER0002 + +ok + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Content-Length: 4 + +yes + + + + + +http + + +proxy + + +lib%TESTNUMBER + + +netrc with redirect using proxy + + +machine site.example login batman password robin + + +http://%HOSTIP:%HTTPPORT http://site.example/ %LOGDIR/netrc2506 + + + + + +GET http://site.example/ HTTP/1.1 +Host: site.example +Authorization: Basic %b64[batman:robin]b64% +Accept: */* +Proxy-Connection: Keep-Alive + +GET http://numbertwo.example/25060002 HTTP/1.1 +Host: numbertwo.example +Accept: */* +Proxy-Connection: Keep-Alive + + + + diff --git a/tests/data/test998 b/tests/data/test998 index 24d1d3dd4e..56dbc0c891 100644 --- a/tests/data/test998 +++ b/tests/data/test998 @@ -77,7 +77,6 @@ Proxy-Connection: Keep-Alive GET http://somewhere.else.example/a/path/9980002 HTTP/1.1 Host: somewhere.else.example -Authorization: Basic %b64[alberto:einstein]b64% User-Agent: curl/%VERSION Accept: */* Proxy-Connection: Keep-Alive diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index bdf8a1dbea..10be282c17 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -112,7 +112,7 @@ TESTS_C = \ lib2023.c lib2032.c lib2082.c \ lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c \ lib2402.c lib2404.c lib2405.c \ - lib2502.c lib2504.c lib2505.c \ + lib2502.c lib2504.c lib2505.c lib2506.c \ lib2700.c \ lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c \ lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c \ diff --git a/tests/libtest/lib2506.c b/tests/libtest/lib2506.c new file mode 100644 index 0000000000..8b3b3429f9 --- /dev/null +++ b/tests/libtest/lib2506.c @@ -0,0 +1,71 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Linus Nielsen Feltzing + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "first.h" + +#include "testtrace.h" + +static size_t sink2506(char *ptr, size_t size, size_t nmemb, void *ud) +{ + (void)ptr; + (void)ud; + return size * nmemb; +} + +static CURLcode test_lib2506(const char *URL) +{ + CURL *curl; + CURLcode result = CURLE_OUT_OF_MEMORY; + + if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { + curl_mfprintf(stderr, "curl_global_init() failed\n"); + return TEST_ERR_MAJOR_BAD; + } + + curl = curl_easy_init(); + if(!curl) { + curl_mfprintf(stderr, "curl_easy_init() failed\n"); + curl_global_cleanup(); + return TEST_ERR_MAJOR_BAD; + } + + test_setopt(curl, CURLOPT_WRITEFUNCTION, sink2506); + test_setopt(curl, CURLOPT_PROXY, URL); + test_setopt(curl, CURLOPT_URL, libtest_arg2); + test_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); + test_setopt(curl, CURLOPT_NETRC_FILE, libtest_arg3); + test_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + test_setopt(curl, CURLOPT_VERBOSE, 1L); + + /* CURLOPT_UNRESTRICTED_AUTH should not make a difference because the + credentials come from netrc */ + test_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L); + + result = curl_easy_perform(curl); + +test_cleanup: + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return result; +}