url: proxy ssl connection reuse fix
- tunnel https proxy used for http: transfers does no check if proxy-ssl configuration matches - test cases added, test_10_12 fails on 8.4.0 Closes #12255
This commit is contained in:
parent
7e828fe503
commit
3e6254f819
20
lib/url.c
20
lib/url.c
@ -1203,17 +1203,19 @@ ConnectionExists(struct Curl_easy *data,
|
||||
continue;
|
||||
|
||||
if(IS_HTTPS_PROXY(needle->http_proxy.proxytype)) {
|
||||
/* use https proxy */
|
||||
if(needle->http_proxy.proxytype !=
|
||||
check->http_proxy.proxytype)
|
||||
/* https proxies come in different types, http/1.1, h2, ... */
|
||||
if(needle->http_proxy.proxytype != check->http_proxy.proxytype)
|
||||
continue;
|
||||
/* match SSL config to proxy */
|
||||
if(!Curl_ssl_conn_config_match(data, check, TRUE)) {
|
||||
DEBUGF(infof(data,
|
||||
"Connection #%" CURL_FORMAT_CURL_OFF_T
|
||||
" has different SSL proxy parameters, can't reuse",
|
||||
check->connection_id));
|
||||
continue;
|
||||
else if(needle->handler->flags&PROTOPT_SSL) {
|
||||
/* use double layer ssl */
|
||||
if(!Curl_ssl_conn_config_match(data, check, TRUE))
|
||||
continue;
|
||||
}
|
||||
else if(!Curl_ssl_conn_config_match(data, check, FALSE))
|
||||
continue;
|
||||
/* the SSL config to the server, which may apply here is checked
|
||||
* further below */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -247,3 +247,105 @@ class TestProxy:
|
||||
assert r.total_connects == 2
|
||||
else:
|
||||
assert r.total_connects == 2
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
|
||||
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
|
||||
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
|
||||
def test_10_10_reuse_proxy(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
|
||||
# url twice via https: proxy separated with '--next', will reuse
|
||||
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
|
||||
pytest.skip('only supported with nghttp2')
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://localhost:{env.https_port}/data.json'
|
||||
proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
|
||||
r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=proxy_args)
|
||||
r1.check_response(count=1, http_status=200)
|
||||
assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
|
||||
if tunnel == 'h2' else 'HTTP/1.1'
|
||||
# get the args, duplicate separated with '--next'
|
||||
x2_args = r1.args[1:]
|
||||
x2_args.append('--next')
|
||||
x2_args.extend(proxy_args)
|
||||
r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=x2_args)
|
||||
r2.check_response(count=2, http_status=200)
|
||||
assert r2.total_connects == 1
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
|
||||
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
|
||||
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
|
||||
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
|
||||
def test_10_11_noreuse_proxy_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
|
||||
# different --proxy-tls13-ciphers, no reuse of connection for https:
|
||||
curl = CurlClient(env=env)
|
||||
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
|
||||
pytest.skip('only supported with nghttp2')
|
||||
url = f'https://localhost:{env.https_port}/data.json'
|
||||
proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
|
||||
r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=proxy_args)
|
||||
r1.check_response(count=1, http_status=200)
|
||||
assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
|
||||
if tunnel == 'h2' else 'HTTP/1.1'
|
||||
# get the args, duplicate separated with '--next'
|
||||
x2_args = r1.args[1:]
|
||||
x2_args.append('--next')
|
||||
x2_args.extend(proxy_args)
|
||||
x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
|
||||
r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=x2_args)
|
||||
r2.check_response(count=2, http_status=200)
|
||||
assert r2.total_connects == 2
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
|
||||
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
|
||||
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
|
||||
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
|
||||
def test_10_12_noreuse_proxy_http(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
|
||||
# different --proxy-tls13-ciphers, no reuse of connection for http:
|
||||
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
|
||||
pytest.skip('only supported with nghttp2')
|
||||
curl = CurlClient(env=env)
|
||||
url = f'http://localhost:{env.http_port}/data.json'
|
||||
proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
|
||||
r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=proxy_args)
|
||||
r1.check_response(count=1, http_status=200)
|
||||
assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
|
||||
if tunnel == 'h2' else 'HTTP/1.1'
|
||||
# get the args, duplicate separated with '--next'
|
||||
x2_args = r1.args[1:]
|
||||
x2_args.append('--next')
|
||||
x2_args.extend(proxy_args)
|
||||
x2_args.extend(['--proxy-tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
|
||||
r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=x2_args)
|
||||
r2.check_response(count=2, http_status=200)
|
||||
assert r2.total_connects == 2
|
||||
|
||||
@pytest.mark.skipif(condition=not Env.have_ssl_curl(), reason=f"curl without SSL")
|
||||
@pytest.mark.parametrize("tunnel", ['http/1.1', 'h2'])
|
||||
@pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available")
|
||||
@pytest.mark.skipif(condition=not Env.curl_uses_lib('openssl'), reason="tls13-ciphers not supported")
|
||||
def test_10_13_noreuse_https(self, env: Env, httpd, nghttpx_fwd, tunnel, repeat):
|
||||
# different --tls13-ciphers on https: same proxy config
|
||||
if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'):
|
||||
pytest.skip('only supported with nghttp2')
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://localhost:{env.https_port}/data.json'
|
||||
proxy_args = curl.get_proxy_args(tunnel=True, proto=tunnel)
|
||||
r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=proxy_args)
|
||||
r1.check_response(count=1, http_status=200)
|
||||
assert self.get_tunnel_proto_used(r1) == 'HTTP/2' \
|
||||
if tunnel == 'h2' else 'HTTP/1.1'
|
||||
# get the args, duplicate separated with '--next'
|
||||
x2_args = r1.args[1:]
|
||||
x2_args.append('--next')
|
||||
x2_args.extend(proxy_args)
|
||||
x2_args.extend(['--tls13-ciphers', 'TLS_AES_128_GCM_SHA256'])
|
||||
r2 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True,
|
||||
extra_args=x2_args)
|
||||
r2.check_response(count=2, http_status=200)
|
||||
assert r2.total_connects == 2
|
||||
|
||||
@ -510,8 +510,14 @@ class CurlClient:
|
||||
args.extend(['--trace-config', 'http/2,http/3,h2-proxy,h1-proxy'])
|
||||
pass
|
||||
|
||||
active_options = options
|
||||
if options is not None and '--next' in options:
|
||||
active_options = options[options.index('--next') + 1:]
|
||||
|
||||
for url in urls:
|
||||
u = urlparse(urls[0])
|
||||
if options:
|
||||
args.extend(options)
|
||||
if alpn_proto is not None:
|
||||
if alpn_proto not in self.ALPN_ARG:
|
||||
raise Exception(f'unknown ALPN protocol: "{alpn_proto}"')
|
||||
@ -521,7 +527,7 @@ class CurlClient:
|
||||
pass
|
||||
elif insecure:
|
||||
args.append('--insecure')
|
||||
elif options and "--cacert" in options:
|
||||
elif active_options and "--cacert" in active_options:
|
||||
pass
|
||||
elif u.hostname:
|
||||
args.extend(["--cacert", self.env.ca.cert_file])
|
||||
@ -532,8 +538,6 @@ class CurlClient:
|
||||
args.extend(["--resolve", f"{u.hostname}:{port}:127.0.0.1"])
|
||||
if timeout is not None and int(timeout) > 0:
|
||||
args.extend(["--connect-timeout", str(int(timeout))])
|
||||
if options:
|
||||
args.extend(options)
|
||||
args.append(url)
|
||||
return args
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user