test_13_proxy_auth.py (8250B)
1 #!/usr/bin/env python3 2 # -*- coding: utf-8 -*- 3 #*************************************************************************** 4 # _ _ ____ _ 5 # Project ___| | | | _ \| | 6 # / __| | | | |_) | | 7 # | (__| |_| | _ <| |___ 8 # \___|\___/|_| \_\_____| 9 # 10 # Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 11 # 12 # This software is licensed as described in the file COPYING, which 13 # you should have received as part of this distribution. The terms 14 # are also available at https://curl.se/docs/copyright.html. 15 # 16 # You may opt to use, copy, modify, merge, publish, distribute and/or sell 17 # copies of the Software, and permit persons to whom the Software is 18 # furnished to do so, under the terms of the COPYING file. 19 # 20 # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 21 # KIND, either express or implied. 22 # 23 # SPDX-License-Identifier: curl 24 # 25 ########################################################################### 26 # 27 import logging 28 import os 29 import re 30 import pytest 31 32 from testenv import Env, CurlClient, ExecResult 33 34 35 log = logging.getLogger(__name__) 36 37 38 @pytest.mark.skipif(condition=Env.setup_incomplete(), 39 reason=f"missing: {Env.incomplete_reason()}") 40 class TestProxyAuth: 41 42 def httpd_configure(self, env, httpd): 43 httpd.set_proxy_auth(True) 44 httpd.reload_if_config_changed() 45 46 def get_tunnel_proto_used(self, r: ExecResult): 47 for line in r.trace_lines: 48 m = re.match(r'.* CONNECT tunnel: (\S+) negotiated$', line) 49 if m: 50 return m.group(1) 51 assert False, f'tunnel protocol not found in:\n{"".join(r.trace_lines)}' 52 return None 53 54 # download via http: proxy (no tunnel), no auth 55 def test_13_01_proxy_no_auth(self, env: Env, httpd, configures_httpd): 56 self.httpd_configure(env, httpd) 57 curl = CurlClient(env=env) 58 url = f'http://localhost:{env.http_port}/data.json' 59 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 60 extra_args=curl.get_proxy_args(proxys=False)) 61 r.check_response(count=1, http_status=407) 62 63 # download via http: proxy (no tunnel), auth 64 def test_13_02_proxy_auth(self, env: Env, httpd, configures_httpd): 65 self.httpd_configure(env, httpd) 66 curl = CurlClient(env=env) 67 url = f'http://localhost:{env.http_port}/data.json' 68 xargs = curl.get_proxy_args(proxys=False) 69 xargs.extend(['--proxy-user', 'proxy:proxy']) 70 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 71 extra_args=xargs) 72 r.check_response(count=1, http_status=200) 73 74 @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'), 75 reason='curl lacks HTTPS-proxy support') 76 @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") 77 def test_13_03_proxys_no_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd): 78 self.httpd_configure(env, httpd) 79 curl = CurlClient(env=env) 80 url = f'http://localhost:{env.http_port}/data.json' 81 xargs = curl.get_proxy_args(proxys=True) 82 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 83 extra_args=xargs) 84 r.check_response(count=1, http_status=407) 85 86 @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'), 87 reason='curl lacks HTTPS-proxy support') 88 @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") 89 def test_13_04_proxys_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd): 90 self.httpd_configure(env, httpd) 91 curl = CurlClient(env=env) 92 url = f'http://localhost:{env.http_port}/data.json' 93 xargs = curl.get_proxy_args(proxys=True) 94 xargs.extend(['--proxy-user', 'proxy:proxy']) 95 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 96 extra_args=xargs) 97 r.check_response(count=1, http_status=200) 98 99 def test_13_05_tunnel_http_no_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd): 100 self.httpd_configure(env, httpd) 101 curl = CurlClient(env=env) 102 url = f'http://localhost:{env.http_port}/data.json' 103 xargs = curl.get_proxy_args(proxys=False, tunnel=True) 104 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 105 extra_args=xargs) 106 # expect "COULD_NOT_CONNECT" 107 r.check_response(exitcode=56, http_status=None) 108 109 def test_13_06_tunnel_http_auth(self, env: Env, httpd, configures_httpd): 110 self.httpd_configure(env, httpd) 111 curl = CurlClient(env=env) 112 url = f'http://localhost:{env.http_port}/data.json' 113 xargs = curl.get_proxy_args(proxys=False, tunnel=True) 114 xargs.extend(['--proxy-user', 'proxy:proxy']) 115 r = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, 116 extra_args=xargs) 117 r.check_response(count=1, http_status=200) 118 119 @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") 120 @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'), 121 reason='curl lacks HTTPS-proxy support') 122 @pytest.mark.parametrize("proto", ['http/1.1', 'h2']) 123 @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) 124 def test_13_07_tunnels_no_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd, proto, tunnel): 125 self.httpd_configure(env, httpd) 126 if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): 127 pytest.skip('only supported with nghttp2') 128 curl = CurlClient(env=env) 129 url = f'https://localhost:{env.https_port}/data.json' 130 xargs = curl.get_proxy_args(proxys=True, tunnel=True, proto=tunnel) 131 r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True, 132 extra_args=xargs) 133 # expect "COULD_NOT_CONNECT" 134 r.check_response(exitcode=56, http_status=None) 135 assert self.get_tunnel_proto_used(r) == 'HTTP/2' \ 136 if tunnel == 'h2' else 'HTTP/1.1' 137 138 @pytest.mark.skipif(condition=not Env.have_nghttpx(), reason="no nghttpx available") 139 @pytest.mark.skipif(condition=not Env.curl_has_feature('HTTPS-proxy'), 140 reason='curl lacks HTTPS-proxy support') 141 @pytest.mark.parametrize("proto", ['http/1.1', 'h2']) 142 @pytest.mark.parametrize("tunnel", ['http/1.1', 'h2']) 143 def test_13_08_tunnels_auth(self, env: Env, httpd, configures_httpd, nghttpx_fwd, proto, tunnel): 144 self.httpd_configure(env, httpd) 145 if tunnel == 'h2' and not env.curl_uses_lib('nghttp2'): 146 pytest.skip('only supported with nghttp2') 147 curl = CurlClient(env=env) 148 url = f'https://localhost:{env.https_port}/data.json' 149 xargs = curl.get_proxy_args(proxys=True, tunnel=True, proto=tunnel) 150 xargs.extend(['--proxy-user', 'proxy:proxy']) 151 r = curl.http_download(urls=[url], alpn_proto=proto, with_stats=True, 152 extra_args=xargs) 153 r.check_response(count=1, http_status=200, 154 protocol='HTTP/2' if proto == 'h2' else 'HTTP/1.1') 155 assert self.get_tunnel_proto_used(r) == 'HTTP/2' \ 156 if tunnel == 'h2' else 'HTTP/1.1' 157 158 @pytest.mark.skipif(condition=not Env.curl_has_feature('SPNEGO'), 159 reason='curl lacks SPNEGO support') 160 def test_13_09_negotiate_http(self, env: Env, httpd, configures_httpd): 161 self.httpd_configure(env, httpd) 162 run_env = os.environ.copy() 163 run_env['https_proxy'] = f'http://127.0.0.1:{env.proxy_port}' 164 curl = CurlClient(env=env, run_env=run_env) 165 url = f'https://localhost:{env.https_port}/data.json' 166 r1 = curl.http_download(urls=[url], alpn_proto='http/1.1', with_stats=True, extra_args=[ 167 '--negotiate', '--proxy-user', 'proxy:proxy' 168 ]) 169 r1.check_response(count=1, http_status=200)