Bug 8897 - Can not download new or updated add-ons

Apple provides a hacked OpenSSL that checks Keychain for certs after failing
to find them elsewhere (and normally there is no elsewhere). The versions
provided for OS X versions < 10.8 are obsolete, preventing building
osm-gps-maps's dependencies, so we provide our own but it can't be similarly
hacked to use Keychain because that is a private API to which Apple doesn't
provide headers.

This is at root a Python problem, see https://bugs.python.org/issue17128

To work around it, disable certificate verification for this one URL for
macs only. This does create the small security risk of a MITM attack injecting
malicious add-ons, but since the URL is user-editable a phishing attack is
more likely and there's nothing that SSL can do about that.
This commit is contained in:
John Ralls 2015-09-27 12:19:44 -07:00
parent f51aaccc78
commit 6016acafdb

View File

@ -53,7 +53,7 @@ from ..utils.configmanager import safe_eval
from ..config import config from ..config import config
from ..const import GRAMPS_LOCALE as glocale from ..const import GRAMPS_LOCALE as glocale
_ = glocale.translation.sgettext _ = glocale.translation.sgettext
from ..constfunc import conv_to_unicode from ..constfunc import conv_to_unicode, mac
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -112,7 +112,7 @@ class Zipfile(object):
names = self.zip_obj.namelist() names = self.zip_obj.namelist()
for name in self.get_paths(names): for name in self.get_paths(names):
fullname = os.path.join(path, name) fullname = os.path.join(path, name)
if not os.path.exists(fullname): if not os.path.exists(fullname):
os.mkdir(fullname) os.mkdir(fullname)
for name in self.get_files(names): for name in self.get_files(names):
fullname = os.path.join(path, name) fullname = os.path.join(path, name)
@ -176,6 +176,12 @@ class Zipfile(object):
def available_updates(): def available_updates():
whattypes = config.get('behavior.check-for-update-types') whattypes = config.get('behavior.check-for-update-types')
from urllib.request import urlopen from urllib.request import urlopen
if mac():
from ssl import create_default_context, CERT_NONE
context = create_default_context()
context.check_hostname = False
context.verify_mode = CERT_NONE
LOG.debug("Checking for updated addons...") LOG.debug("Checking for updated addons...")
langs = glocale.get_language_list() langs = glocale.get_language_list()
langs.append("en") langs.append("en")
@ -186,12 +192,12 @@ def available_updates():
(config.get("behavior.addons-url"), lang)) (config.get("behavior.addons-url"), lang))
LOG.debug(" trying: %s" % URL) LOG.debug(" trying: %s" % URL)
try: try:
fp = urlopen(URL, timeout=10) # seconds fp = urlopen(URL, timeout=10, context=context) # seconds
except: except:
try: try:
URL = ("%s/listings/addons-%s.txt" % URL = ("%s/listings/addons-%s.txt" %
(config.get("behavior.addons-url"), lang[:2])) (config.get("behavior.addons-url"), lang[:2]))
fp = urlopen(URL, timeout=10) fp = urlopen(URL, timeout=10, context=context)
except Exception as err: # some error except Exception as err: # some error
LOG.warning("Failed to open addon metadata for {lang} {url}: {err}". LOG.warning("Failed to open addon metadata for {lang} {url}: {err}".
format(lang=lang, url=URL, err=err)) format(lang=lang, url=URL, err=err))
@ -307,8 +313,8 @@ def load_addon_file(path, callback=None):
callback((_("Examining '%s'...") % gpr_file) + "\n") callback((_("Examining '%s'...") % gpr_file) + "\n")
contents = file_obj.extractfile(gpr_file).read() contents = file_obj.extractfile(gpr_file).read()
# Put a fake register and _ function in environment: # Put a fake register and _ function in environment:
env = make_environment(register=register, env = make_environment(register=register,
newplugin=newplugin, newplugin=newplugin,
_=lambda text: text) _=lambda text: text)
# clear out the result variable: # clear out the result variable:
globals()["register_results"] = [] globals()["register_results"] = []