diff options
Diffstat (limited to 'src/leap/bitmask/provider/providerbootstrapper.py')
-rw-r--r-- | src/leap/bitmask/provider/providerbootstrapper.py | 103 |
1 files changed, 64 insertions, 39 deletions
diff --git a/src/leap/bitmask/provider/providerbootstrapper.py b/src/leap/bitmask/provider/providerbootstrapper.py index f5a2003f..2a519206 100644 --- a/src/leap/bitmask/provider/providerbootstrapper.py +++ b/src/leap/bitmask/provider/providerbootstrapper.py @@ -24,18 +24,18 @@ import sys import requests -from PySide import QtCore - -from leap.bitmask.config.providerconfig import ProviderConfig, MissingCACert -from leap.bitmask.util.request_helpers import get_content +from leap.bitmask import provider from leap.bitmask import util -from leap.bitmask.util.constants import REQUEST_TIMEOUT +from leap.bitmask.config import flags +from leap.bitmask.config.providerconfig import ProviderConfig, MissingCACert +from leap.bitmask.provider import get_provider_path from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper -from leap.bitmask.provider.supportedapis import SupportedAPIs +from leap.bitmask.util.constants import REQUEST_TIMEOUT +from leap.bitmask.util.request_helpers import get_content from leap.common import ca_bundle from leap.common.certs import get_digest -from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.common.check import leap_assert, leap_assert_type, leap_check +from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p logger = logging.getLogger(__name__) @@ -47,6 +47,14 @@ class UnsupportedProviderAPI(Exception): pass +class UnsupportedClientVersionError(Exception): + """ + Raised when attempting to use a provider with an older + client than supported. + """ + pass + + class WrongFingerprint(Exception): """ Raised when a fingerprint comparison does not match. @@ -61,25 +69,21 @@ class ProviderBootstrapper(AbstractBootstrapper): If a check fails, the subsequent checks are not executed """ - # All dicts returned are of the form - # {"passed": bool, "error": str} - name_resolution = QtCore.Signal(dict) - https_connection = QtCore.Signal(dict) - download_provider_info = QtCore.Signal(dict) + MIN_CLIENT_VERSION = 'x-minimum-client-version' - download_ca_cert = QtCore.Signal(dict) - check_ca_fingerprint = QtCore.Signal(dict) - check_api_certificate = QtCore.Signal(dict) - - def __init__(self, bypass_checks=False): + def __init__(self, signaler=None, bypass_checks=False): """ Constructor for provider bootstrapper object + :param signaler: Signaler object used to receive notifications + from the backend + :type signaler: Signaler :param bypass_checks: Set to true if the app should bypass - first round of checks for CA certificates at bootstrap + first round of checks for CA + certificates at bootstrap :type bypass_checks: bool """ - AbstractBootstrapper.__init__(self, bypass_checks) + AbstractBootstrapper.__init__(self, signaler, bypass_checks) self._domain = None self._provider_config = None @@ -95,9 +99,14 @@ class ProviderBootstrapper(AbstractBootstrapper): :rtype: bool or str """ if self._bypass_checks: - verify = False + return False + + cert = flags.CA_CERT_FILE + if cert is not None: + verify = cert else: verify = ca_bundle.where() + return verify def _check_name_resolution(self): @@ -163,8 +172,8 @@ class ProviderBootstrapper(AbstractBootstrapper): headers = {} domain = self._domain.encode(sys.getfilesystemencoding()) provider_json = os.path.join(util.get_path_prefix(), - "leap", "providers", domain, - "provider.json") + get_provider_path(domain)) + mtime = get_mtime(provider_json) if self._download_if_needed and mtime: @@ -195,6 +204,8 @@ class ProviderBootstrapper(AbstractBootstrapper): res.raise_for_status() logger.debug("Request status code: {0}".format(res.status_code)) + min_client_version = res.headers.get(self.MIN_CLIENT_VERSION, '0') + # Not modified if res.status_code == 304: logger.debug("Provider definition has not been modified") @@ -202,6 +213,13 @@ class ProviderBootstrapper(AbstractBootstrapper): # end refactor, more or less... # XXX Watch out, have to check the supported api yet. else: + if flags.APP_VERSION_CHECK: + # TODO split + if not provider.supports_client(min_client_version): + self._signaler.signal( + self._signaler.PROV_UNSUPPORTED_CLIENT) + raise UnsupportedClientVersionError() + provider_definition, mtime = get_content(res) provider_config = ProviderConfig() @@ -209,17 +227,20 @@ class ProviderBootstrapper(AbstractBootstrapper): provider_config.save(["leap", "providers", domain, "provider.json"]) - api_version = provider_config.get_api_version() - if SupportedAPIs.supports(api_version): - logger.debug("Provider definition has been modified") - else: - api_supported = ', '.join(SupportedAPIs.SUPPORTED_APIS) - error = ('Unsupported provider API version. ' - 'Supported versions are: {0}. ' - 'Found: {1}.').format(api_supported, api_version) - - logger.error(error) - raise UnsupportedProviderAPI(error) + if flags.API_VERSION_CHECK: + # TODO split + api_version = provider_config.get_api_version() + if provider.supports_api(api_version): + logger.debug("Provider definition has been modified") + else: + api_supported = ', '.join(provider.SUPPORTED_APIS) + error = ('Unsupported provider API version. ' + 'Supported versions are: {0}. ' + 'Found: {1}.').format(api_supported, api_version) + + logger.error(error) + self._signaler.signal(self._signaler.PROV_UNSUPPORTED_API) + raise UnsupportedProviderAPI(error) def run_provider_select_checks(self, domain, download_if_needed=False): """ @@ -238,9 +259,11 @@ class ProviderBootstrapper(AbstractBootstrapper): self._download_if_needed = download_if_needed cb_chain = [ - (self._check_name_resolution, self.name_resolution), - (self._check_https, self.https_connection), - (self._download_provider_info, self.download_provider_info) + (self._check_name_resolution, + self._signaler.PROV_NAME_RESOLUTION_KEY), + (self._check_https, self._signaler.PROV_HTTPS_CONNECTION_KEY), + (self._download_provider_info, + self._signaler.PROV_DOWNLOAD_PROVIDER_INFO_KEY) ] return self.addCallbackChain(cb_chain) @@ -367,9 +390,11 @@ class ProviderBootstrapper(AbstractBootstrapper): self._download_if_needed = download_if_needed cb_chain = [ - (self._download_ca_cert, self.download_ca_cert), - (self._check_ca_fingerprint, self.check_ca_fingerprint), - (self._check_api_certificate, self.check_api_certificate) + (self._download_ca_cert, self._signaler.PROV_DOWNLOAD_CA_CERT_KEY), + (self._check_ca_fingerprint, + self._signaler.PROV_CHECK_CA_FINGERPRINT_KEY), + (self._check_api_certificate, + self._signaler.PROV_CHECK_API_CERTIFICATE_KEY) ] return self.addCallbackChain(cb_chain) |