mirror of
https://github.com/python/cpython.git
synced 2025-08-09 11:29:45 +00:00
[3.12] gh-115197: Stop resolving host in urllib.request proxy bypass (GH-115210)
gh-115197: Stop resolving host in urllib.request proxy bypass (GH-115210)
Use of a proxy is intended to defer DNS for the hosts to the proxy itself, rather than a potential for information leak of the host doing DNS resolution itself for any reason. Proxy bypass lists are strictly name based. Most implementations of proxy support agree.
(cherry picked from commit c43b26d02e
)
Co-authored-by: Weii Wang <weii.wang@canonical.com>
This commit is contained in:
parent
91e680b85c
commit
dec637a953
3 changed files with 64 additions and 44 deletions
|
@ -2589,6 +2589,7 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
|
|||
}
|
||||
"""
|
||||
from fnmatch import fnmatch
|
||||
from ipaddress import AddressValueError, IPv4Address
|
||||
|
||||
hostonly, port = _splitport(host)
|
||||
|
||||
|
@ -2605,20 +2606,17 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
|
|||
return True
|
||||
|
||||
hostIP = None
|
||||
try:
|
||||
hostIP = int(IPv4Address(hostonly))
|
||||
except AddressValueError:
|
||||
pass
|
||||
|
||||
for value in proxy_settings.get('exceptions', ()):
|
||||
# Items in the list are strings like these: *.local, 169.254/16
|
||||
if not value: continue
|
||||
|
||||
m = re.match(r"(\d+(?:\.\d+)*)(/\d+)?", value)
|
||||
if m is not None:
|
||||
if hostIP is None:
|
||||
try:
|
||||
hostIP = socket.gethostbyname(hostonly)
|
||||
hostIP = ip2num(hostIP)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
if m is not None and hostIP is not None:
|
||||
base = ip2num(m.group(1))
|
||||
mask = m.group(2)
|
||||
if mask is None:
|
||||
|
@ -2641,6 +2639,31 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings):
|
|||
return False
|
||||
|
||||
|
||||
# Same as _proxy_bypass_macosx_sysconf, testable on all platforms
|
||||
def _proxy_bypass_winreg_override(host, override):
|
||||
"""Return True if the host should bypass the proxy server.
|
||||
|
||||
The proxy override list is obtained from the Windows
|
||||
Internet settings proxy override registry value.
|
||||
|
||||
An example of a proxy override value is:
|
||||
"www.example.com;*.example.net; 192.168.0.1"
|
||||
"""
|
||||
from fnmatch import fnmatch
|
||||
|
||||
host, _ = _splitport(host)
|
||||
proxy_override = override.split(';')
|
||||
for test in proxy_override:
|
||||
test = test.strip()
|
||||
# "<local>" should bypass the proxy server for all intranet addresses
|
||||
if test == '<local>':
|
||||
if '.' not in host:
|
||||
return True
|
||||
elif fnmatch(host, test):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
from _scproxy import _get_proxy_settings, _get_proxies
|
||||
|
||||
|
@ -2739,7 +2762,7 @@ elif os.name == 'nt':
|
|||
import winreg
|
||||
except ImportError:
|
||||
# Std modules, so should be around - but you never know!
|
||||
return 0
|
||||
return False
|
||||
try:
|
||||
internetSettings = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
||||
r'Software\Microsoft\Windows\CurrentVersion\Internet Settings')
|
||||
|
@ -2749,40 +2772,10 @@ elif os.name == 'nt':
|
|||
'ProxyOverride')[0])
|
||||
# ^^^^ Returned as Unicode but problems if not converted to ASCII
|
||||
except OSError:
|
||||
return 0
|
||||
return False
|
||||
if not proxyEnable or not proxyOverride:
|
||||
return 0
|
||||
# try to make a host list from name and IP address.
|
||||
rawHost, port = _splitport(host)
|
||||
host = [rawHost]
|
||||
try:
|
||||
addr = socket.gethostbyname(rawHost)
|
||||
if addr != rawHost:
|
||||
host.append(addr)
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
fqdn = socket.getfqdn(rawHost)
|
||||
if fqdn != rawHost:
|
||||
host.append(fqdn)
|
||||
except OSError:
|
||||
pass
|
||||
# make a check value list from the registry entry: replace the
|
||||
# '<local>' string by the localhost entry and the corresponding
|
||||
# canonical entry.
|
||||
proxyOverride = proxyOverride.split(';')
|
||||
# now check if we match one of the registry values.
|
||||
for test in proxyOverride:
|
||||
if test == '<local>':
|
||||
if '.' not in rawHost:
|
||||
return 1
|
||||
test = test.replace(".", r"\.") # mask dots
|
||||
test = test.replace("*", r".*") # change glob sequence
|
||||
test = test.replace("?", r".") # change glob char
|
||||
for val in host:
|
||||
if re.match(test, val, re.I):
|
||||
return 1
|
||||
return 0
|
||||
return False
|
||||
return _proxy_bypass_winreg_override(host, proxyOverride)
|
||||
|
||||
def proxy_bypass(host):
|
||||
"""Return True, if host should be bypassed.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue