proxy-auth: additional tests
No binary (build failed)
—
(log yok)
| @@ -590,29 +590,15 @@ static bool proxy_info_matches(const struct proxy_info *data, | |
| { | |
| if((data->proxytype == needle->proxytype) && | |
| (data->port == needle->port) && | |
| - | curl_strequal(data->host.name, needle->host.name)) |
| - | return TRUE; |
| + | curl_strequal(data->host.name, needle->host.name)) { |
| + | if(Curl_timestrcmp(data->user, needle->user) || |
| + | Curl_timestrcmp(data->passwd, needle->passwd)) |
| + | return FALSE; |
| + | return TRUE; |
| + | } |
| return FALSE; | |
| } | |
| - | |
| - | static bool socks_proxy_info_matches(const struct proxy_info *data, |
| - | const struct proxy_info *needle) |
| - | { |
| - | if(!proxy_info_matches(data, needle)) |
| - | return FALSE; |
| - | |
| - | /* the user information is case-sensitive |
| - | or at least it is not defined as case-insensitive |
| - | see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */ |
| - | |
| - | /* curl_strequal does a case insensitive comparison, |
| - | so do not use it here! */ |
| - | if(Curl_timestrcmp(data->user, needle->user) || |
| - | Curl_timestrcmp(data->passwd, needle->passwd)) |
| - | return FALSE; |
| - | return TRUE; |
| - | } |
| #endif | |
| /* A connection has to have been idle for less than 'conn_max_idle_ms' | |
| @@ -923,7 +909,7 @@ static bool url_match_proxy_use(struct connectdata *conn, | |
| return FALSE; | |
| if(m->needle->bits.socksproxy && | |
| - | !socks_proxy_info_matches(&m->needle->socks_proxy, &conn->socks_proxy)) |
| + | !proxy_info_matches(&m->needle->socks_proxy, &conn->socks_proxy)) |
| return FALSE; | |
| if(m->needle->bits.httpproxy) { | |
| @@ -169,3 +169,23 @@ class TestProxyAuth: | |
| '--negotiate', '--proxy-user', 'proxy:proxy' | |
| ]) | |
| r1.check_response(count=1, http_status=200) | |
| + | |
| + | def test_13_10_tunnels_mixed_auth(self, env: Env, httpd, configures_httpd): |
| + | self.httpd_configure(env, httpd) |
| + | curl = CurlClient(env=env) |
| + | url1 = f'http://localhost:{env.http_port}/data.json?1' |
| + | url2 = f'http://localhost:{env.http_port}/data.json?2' |
| + | url3 = f'http://localhost:{env.http_port}/data.json?3' |
| + | xargs1 = curl.get_proxy_args(proxys=False, tunnel=True) |
| + | xargs1.extend(['--proxy-user', 'proxy:proxy']) # good auth |
| + | xargs2 = curl.get_proxy_args(proxys=False, tunnel=True) |
| + | xargs2.extend(['--proxy-user', 'ungood:ungood']) # bad auth |
| + | xargs3 = curl.get_proxy_args(proxys=False, tunnel=True) |
| + | # no auth |
| + | r = curl.http_download(urls=[url1, url2, url3], alpn_proto='http/1.1', with_stats=True, |
| + | url_options={url1: xargs1, url2: xargs2, url3: xargs3}) |
| + | # only url1 succeeds, others fail, no connection reuse |
| + | assert r.stats[0]['http_code'] == 200, f'{r.dump_logs()}' |
| + | assert r.stats[1]['http_code'] == 0, f'{r.dump_logs()}' |
| + | assert r.stats[2]['http_code'] == 0, f'{r.dump_logs()}' |
| + | assert r.total_connects == 3, f'{r.dump_logs()}' |
| @@ -724,7 +724,8 @@ class CurlClient: | |
| with_tcpdump: bool = False, | |
| no_save: bool = False, | |
| limit_rate: Optional[str] = None, | |
| - | extra_args: Optional[List[str]] = None): |
| + | extra_args: Optional[List[str]] = None, |
| + | url_options: Optional[Dict[str,List[str]]] = None): |
| if extra_args is None: | |
| extra_args = [] | |
| if no_save: | |
| @@ -742,6 +743,7 @@ class CurlClient: | |
| ]) | |
| return self._raw(urls, alpn_proto=alpn_proto, options=extra_args, | |
| with_stats=with_stats, | |
| + | url_options=url_options, |
| with_headers=with_headers, | |
| with_profile=with_profile, | |
| with_tcpdump=with_tcpdump) | |
| @@ -1083,6 +1085,7 @@ class CurlClient: | |
| def _raw(self, urls, intext='', timeout=None, options=None, insecure=False, | |
| alpn_proto: Optional[str] = None, | |
| + | url_options=None, |
| force_resolve=True, | |
| with_stats=False, | |
| with_headers=True, | |
| @@ -1092,7 +1095,8 @@ class CurlClient: | |
| args = self._complete_args( | |
| urls=urls, timeout=timeout, options=options, insecure=insecure, | |
| alpn_proto=alpn_proto, force_resolve=force_resolve, | |
| - | with_headers=with_headers, def_tracing=def_tracing) |
| + | with_headers=with_headers, def_tracing=def_tracing, |
| + | url_options=url_options) |
| r = self._run(args, intext=intext, with_stats=with_stats, | |
| with_profile=with_profile, with_tcpdump=with_tcpdump) | |
| if r.exit_code == 0 and with_headers: | |
| @@ -1102,8 +1106,10 @@ class CurlClient: | |
| def _complete_args(self, urls, timeout=None, options=None, | |
| insecure=False, force_resolve=True, | |
| alpn_proto: Optional[str] = None, | |
| + | url_options=None, |
| with_headers: bool = True, | |
| def_tracing: bool = True): | |
| + | url_sep = [] |
| if not isinstance(urls, list): | |
| urls = [urls] | |
| @@ -1129,7 +1135,13 @@ class CurlClient: | |
| active_options = options[options.index('--next') + 1:] | |
| for url in urls: | |
| - | u = urlparse(urls[0]) |
| + | args.extend(url_sep) |
| + | if url_options is not None: |
| + | url_sep = ['--next'] |
| + | |
| + | u = urlparse(url) |
| + | if url_options is not None and url in url_options: |
| + | args.extend(url_options[url]) |
| if options: | |
| args.extend(options) | |
| if alpn_proto is not None: | |