diff options
| -rw-r--r-- | .github/workflows/lint.yml | 2 | ||||
| -rw-r--r-- | mesonbuild/wrap/wrap.py | 28 |
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']) |
