summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/lint.yml2
-rw-r--r--mesonbuild/wrap/wrap.py28
2 files changed, 26 insertions, 4 deletions
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index ef5889579..d9a7836c5 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -53,7 +53,7 @@ jobs:
with:
python-version: '3.x'
# Pin mypy to version 1.8, so we retain the ability to lint for Python 3.7
- - run: python -m pip install "mypy==1.8" strictyaml types-PyYAML types-tqdm types-chevron
+ - run: python -m pip install "mypy==1.8" strictyaml truststore types-PyYAML types-tqdm types-chevron
- run: python run_mypy.py --allver
env:
PYTHONUNBUFFERED: 1
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index e6f390a5d..c675389aa 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -77,6 +77,23 @@ else:
PATCH = shutil.which('patch')
+truststore_message = '''
+
+ If you believe the connection should be secure, but python cannot see the
+ correct SSL certificates, install https://truststore.readthedocs.io/ and
+ try again.'''
+
+@lru_cache(maxsize=None)
+def ssl_truststore() -> T.Optional[ssl.SSLContext]:
+ """ Provide a default context=None for urlopen, but use truststore if installed. """
+ try:
+ import truststore
+ except ImportError:
+ # use default
+ return None
+ else:
+ return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
+
def whitelist_wrapdb(urlstr: str) -> urllib.parse.ParseResult:
""" raises WrapException if not whitelisted subdomain """
url = urllib.parse.urlparse(urlstr)
@@ -99,7 +116,7 @@ def open_wrapdburl(urlstring: str, allow_insecure: bool = False, have_opt: bool
if allow_compression:
headers['Accept-Encoding'] = 'gzip'
req = urllib.request.Request(urllib.parse.urlunparse(url), headers=headers)
- return T.cast('http.client.HTTPResponse', urllib.request.urlopen(req, timeout=REQ_TIMEOUT))
+ return T.cast('http.client.HTTPResponse', urllib.request.urlopen(req, timeout=REQ_TIMEOUT, context=ssl_truststore()))
url = whitelist_wrapdb(urlstring)
if has_ssl:
@@ -110,6 +127,8 @@ def open_wrapdburl(urlstring: str, allow_insecure: bool = False, have_opt: bool
if isinstance(excp, urllib.error.URLError) and isinstance(excp.reason, ssl.SSLCertVerificationError):
if allow_insecure:
mlog.warning(f'{msg}\n\n Proceeding without authentication.')
+ elif ssl_truststore() is None:
+ raise WrapException(f'{msg}{insecure_msg}{truststore_message}')
else:
raise WrapException(f'{msg}{insecure_msg}')
else:
@@ -794,10 +813,13 @@ class Resolver:
try:
req = urllib.request.Request(urlstring, headers=headers)
- resp = urllib.request.urlopen(req, timeout=REQ_TIMEOUT)
+ resp = urllib.request.urlopen(req, timeout=REQ_TIMEOUT, context=ssl_truststore())
except OSError as e:
mlog.log(str(e))
- raise WrapException(f'could not get {urlstring}; is the internet available?')
+ if isinstance(e, urllib.error.URLError) and isinstance(e.reason, ssl.SSLCertVerificationError) and ssl_truststore() is None:
+ raise WrapException(f'could not get {urlstring}; is the internet available?{truststore_message}')
+ else:
+ raise WrapException(f'could not get {urlstring}; is the internet available?')
with contextlib.closing(resp) as resp, tmpfile as tmpfile:
try:
dlsize = int(resp.info()['Content-Length'])