From 751638b4eb8208e1eaa1beaaed284da6b412bca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 7 Mar 2013 19:05:11 -0300 Subject: Change asserts for a custom leap_assert method Also: - Make SRPAuth and the Bootstrappers be a QObject instead of a QThread so we can use them inside another more generic thread - Add a generic CheckerThread that runs checks or whatever operation as long as it returns a boolean value - Closes the whole application if the wizard is rejected at the first run - Do not fail when the config directory doesn't exist - Set the wizard pixmap logo as LEAP's logo - Improve wizard checks - Make SRPRegister play nice with the CheckerThread --- src/leap/services/eip/eipbootstrapper.py | 101 +++++-------------- src/leap/services/eip/eipconfig.py | 13 ++- src/leap/services/eip/providerbootstrapper.py | 137 ++++++++------------------ src/leap/services/eip/vpn.py | 15 ++- src/leap/services/eip/vpnlaunchers.py | 24 ++--- 5 files changed, 90 insertions(+), 200 deletions(-) (limited to 'src/leap/services') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 77d7020a..bd6ab715 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -28,11 +28,13 @@ from PySide import QtGui, QtCore from leap.config.providerconfig import ProviderConfig from leap.services.eip.eipconfig import EIPConfig +from leap.util.check import leap_assert, leap_assert_type +from leap.util.checkerthread import CheckerThread logger = logging.getLogger(__name__) -class EIPBootstrapper(QtCore.QThread): +class EIPBootstrapper(QtCore.QObject): """ Sets up EIP for a provider a series of checks and emits signals after they are passed. @@ -50,13 +52,7 @@ class EIPBootstrapper(QtCore.QThread): download_client_certificate = QtCore.Signal(dict) def __init__(self): - QtCore.QThread.__init__(self) - - self._checks = [] - self._checks_lock = QtCore.QMutex() - - self._should_quit = False - self._should_quit_lock = QtCore.QMutex() + QtCore.QObject.__init__(self) # **************************************************** # # Dependency injection helpers, override this for more @@ -69,35 +65,6 @@ class EIPBootstrapper(QtCore.QThread): self._eip_config = None self._download_if_needed = False - def get_should_quit(self): - """ - Returns wether this thread should quit - - @rtype: bool - @return: True if the thread should terminate itself, Flase otherwise - """ - - QtCore.QMutexLocker(self._should_quit_lock) - return self._should_quit - - def set_should_quit(self): - """ - Sets the should_quit flag to True so that this thread - terminates the first chance it gets - """ - QtCore.QMutexLocker(self._should_quit_lock) - self._should_quit = True - self.wait() - - def start(self): - """ - Starts the thread and resets the should_quit flag - """ - with QtCore.QMutexLocker(self._should_quit_lock): - self._should_quit = False - - QtCore.QThread.start(self) - def _download_config(self): """ Downloads the EIP config for the given provider @@ -106,7 +73,8 @@ class EIPBootstrapper(QtCore.QThread): @rtype: bool """ - assert self._provider_config, "We need a provider configuration!" + leap_assert(self._provider_config, + "We need a provider configuration!") logger.debug("Downloading EIP config for %s" % (self._provider_config.get_domain(),)) @@ -162,8 +130,8 @@ class EIPBootstrapper(QtCore.QThread): @return: True if the checks passed, False otherwise @rtype: bool """ - assert self._provider_config, "We need a provider configuration!" - assert self._eip_config, "We need an eip configuration!" + leap_assert(self._provider_config, "We need a provider configuration!") + leap_assert(self._eip_config, "We need an eip configuration!") logger.debug("Downloading EIP client certificate for %s" % (self._provider_config.get_domain(),)) @@ -218,49 +186,25 @@ class EIPBootstrapper(QtCore.QThread): return download_cert[self.PASSED_KEY] - def run_eip_setup_checks(self, provider_config, download_if_needed=False): + def run_eip_setup_checks(self, checker, + provider_config, + download_if_needed=False): """ Starts the checks needed for a new eip setup @param provider_config: Provider configuration @type provider_config: ProviderConfig """ - assert provider_config, "We need a provider config!" - assert isinstance(provider_config, ProviderConfig), "Expected " + \ - "ProviderConfig type, not %r" % (type(provider_config),) + leap_assert(provider_config, "We need a provider config!") + leap_assert_type(provider_config, ProviderConfig) self._provider_config = provider_config self._download_if_needed = download_if_needed - QtCore.QMutexLocker(self._checks_lock) - self._checks = [ + checker.add_checks([ self._download_config, self._download_client_certificates - ] - - def run(self): - """ - Main run loop for this thread. Executes the checks. - """ - shouldContinue = False - while True: - if self.get_should_quit(): - logger.debug("Quitting provider bootstrap thread") - return - checkSomething = False - with QtCore.QMutexLocker(self._checks_lock): - if len(self._checks) > 0: - check = self._checks.pop(0) - shouldContinue = check() - checkSomething = True - if not shouldContinue: - logger.debug("Something went wrong with the checks, " - - "clearing...") - self._checks = [] - checkSomething = False - if not checkSomething: - self.usleep(self.IDLE_SLEEP_INTERVAL) + ]) if __name__ == "__main__": @@ -272,8 +216,8 @@ if __name__ == "__main__": def sigint_handler(*args, **kwargs): logger.debug('SIGINT catched. shutting down...') - bootstrapper_thread = args[0] - bootstrapper_thread.set_should_quit() + checker = args[0] + checker.set_should_quit() QtGui.QApplication.quit() def signal_tester(d): @@ -289,27 +233,28 @@ if __name__ == "__main__": console.setFormatter(formatter) logger.addHandler(console) - eip_thread = EIPBootstrapper() + eip_checks = EIPBootstrapper() + checker = CheckerThread() - sigint = partial(sigint_handler, eip_thread) + sigint = partial(sigint_handler, checker) signal.signal(signal.SIGINT, sigint) timer = QtCore.QTimer() timer.start(500) timer.timeout.connect(lambda: None) app.connect(app, QtCore.SIGNAL("aboutToQuit()"), - eip_thread.set_should_quit) + checker.set_should_quit) w = QtGui.QWidget() w.resize(100, 100) w.show() - eip_thread.start() + checker.start() provider_config = ProviderConfig() if provider_config.load(os.path.join("leap", "providers", "bitmask.net", "provider.json")): - eip_thread.run_eip_setup_checks(provider_config) + eip_checks.run_eip_setup_checks(checker, provider_config) sys.exit(app.exec_()) diff --git a/src/leap/services/eip/eipconfig.py b/src/leap/services/eip/eipconfig.py index ac06fef1..eab5bfd4 100644 --- a/src/leap/services/eip/eipconfig.py +++ b/src/leap/services/eip/eipconfig.py @@ -24,6 +24,7 @@ import logging from leap.config.baseconfig import BaseConfig from leap.config.providerconfig import ProviderConfig from leap.services.eip.eipspec import eipservice_config_spec +from leap.util.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -61,7 +62,7 @@ class EIPConfig(BaseConfig): def get_gateway_ip(self, index=0): gateways = self.get_gateways() - assert len(gateways) > 0, "We don't have any gateway!" + leap_assert(len(gateways) > 0, "We don't have any gateway!") if index > len(gateways): index = 0 logger.warning("Provided an unknown gateway index %s, " + @@ -75,10 +76,8 @@ class EIPConfig(BaseConfig): Returns the path to the certificate used by openvpn """ - assert providerconfig, "We need a provider" - assert isinstance(providerconfig, ProviderConfig), "The provider " + \ - "needs to be of type ProviderConfig instead of %s" % \ - (type(providerconfig),) + leap_assert(providerconfig, "We need a provider") + leap_assert_type(providerconfig, ProviderConfig) cert_path = os.path.join(self.get_path_prefix(), "leap", @@ -89,8 +88,8 @@ class EIPConfig(BaseConfig): "openvpn.pem") if not about_to_download: - assert os.path.exists(cert_path), \ - "You need to download the certificate first" + leap_assert(os.path.exists(cert_path), + "You need to download the certificate first") logger.debug("Using OpenVPN cert %s" % (cert_path,)) return cert_path diff --git a/src/leap/services/eip/providerbootstrapper.py b/src/leap/services/eip/providerbootstrapper.py index babcd47b..ecdc4e07 100644 --- a/src/leap/services/eip/providerbootstrapper.py +++ b/src/leap/services/eip/providerbootstrapper.py @@ -29,11 +29,13 @@ from OpenSSL import crypto from PySide import QtGui, QtCore from leap.config.providerconfig import ProviderConfig +from leap.util.check import leap_assert, leap_assert_type +from leap.util.checkerthread import CheckerThread logger = logging.getLogger(__name__) -class ProviderBootstrapper(QtCore.QThread): +class ProviderBootstrapper(QtCore.QObject): """ Given a provider URL performs a series of checks and emits signals after they are passed. @@ -56,13 +58,7 @@ class ProviderBootstrapper(QtCore.QThread): check_api_certificate = QtCore.Signal(dict) def __init__(self): - QtCore.QThread.__init__(self) - - self._checks = [] - self._checks_lock = QtCore.QMutex() - - self._should_quit = False - self._should_quit_lock = QtCore.QMutex() + QtCore.QObject.__init__(self) # **************************************************** # # Dependency injection helpers, override this for more @@ -75,35 +71,6 @@ class ProviderBootstrapper(QtCore.QThread): self._provider_config = None self._download_if_needed = False - def get_should_quit(self): - """ - Returns wether this thread should quit - - @rtype: bool - @return: True if the thread should terminate itself, Flase otherwise - """ - - QtCore.QMutexLocker(self._should_quit_lock) - return self._should_quit - - def set_should_quit(self): - """ - Sets the should_quit flag to True so that this thread - terminates the first chance it gets - """ - QtCore.QMutexLocker(self._should_quit_lock) - self._should_quit = True - self.wait() - - def start(self): - """ - Starts the thread and resets the should_quit flag - """ - with QtCore.QMutexLocker(self._should_quit_lock): - self._should_quit = False - - QtCore.QThread.start(self) - def _should_proceed_provider(self): """ Returns False if provider.json already exists for the given @@ -131,7 +98,7 @@ class ProviderBootstrapper(QtCore.QThread): @rtype: bool """ - assert self._domain, "Cannot check DNS without a domain" + leap_assert(self._domain, "Cannot check DNS without a domain") logger.debug("Checking name resolution for %s" % (self._domain)) @@ -162,7 +129,7 @@ class ProviderBootstrapper(QtCore.QThread): @rtype: bool """ - assert self._domain, "Cannot check HTTPS without a domain" + leap_assert(self._domain, "Cannot check HTTPS without a domain") logger.debug("Checking https for %s" % (self._domain)) @@ -193,7 +160,8 @@ class ProviderBootstrapper(QtCore.QThread): @return: True if the checks passed, False otherwise @rtype: bool """ - assert self._domain, "Cannot download provider info without a domain" + leap_assert(self._domain, + "Cannot download provider info without a domain") logger.debug("Downloading provider info for %s" % (self._domain)) @@ -230,7 +198,8 @@ class ProviderBootstrapper(QtCore.QThread): return download_data[self.PASSED_KEY] - def run_provider_select_checks(self, domain, download_if_needed=False): + def run_provider_select_checks(self, checker, + domain, download_if_needed=False): """ Populates the check queue @@ -243,17 +212,16 @@ class ProviderBootstrapper(QtCore.QThread): @return: True if the checks passed, False otherwise @rtype: bool """ - assert domain and len(domain) > 0, "We need a domain!" + leap_assert(domain and len(domain) > 0, "We need a domain!") self._domain = domain self._download_if_needed = download_if_needed - QtCore.QMutexLocker(self._checks_lock) - self._checks = [ + checker.add_checks([ self._check_name_resolution, self._check_https, self._download_provider_info - ] + ]) def _should_proceed_cert(self): """ @@ -262,7 +230,7 @@ class ProviderBootstrapper(QtCore.QThread): @rtype: bool """ - assert self._provider_config, "We need a provider config!" + leap_assert(self._provider_config, "We need a provider config!") if not self._download_if_needed: return True @@ -278,8 +246,8 @@ class ProviderBootstrapper(QtCore.QThread): @rtype: bool """ - assert self._provider_config, "Cannot download the ca cert " + \ - "without a provider config!" + leap_assert(self._provider_config, "Cannot download the ca cert " + "without a provider config!") logger.debug("Downloading ca cert for %s at %s" % (self._domain, self._provider_config.get_ca_cert_uri())) @@ -331,8 +299,8 @@ class ProviderBootstrapper(QtCore.QThread): @return: True if the checks passed, False otherwise @rtype: bool """ - assert self._provider_config, "Cannot check the ca cert " + \ - "without a provider config!" + leap_assert(self._provider_config, "Cannot check the ca cert " + "without a provider config!") logger.debug("Checking ca fingerprint for %s and cert %s" % (self._domain, @@ -350,7 +318,7 @@ class ProviderBootstrapper(QtCore.QThread): try: parts = self._provider_config.get_ca_cert_fingerprint().split(":") - assert len(parts) == 2, "Wrong fingerprint format" + leap_assert(len(parts) == 2, "Wrong fingerprint format") method = parts[0].strip() fingerprint = parts[1].strip() @@ -358,13 +326,13 @@ class ProviderBootstrapper(QtCore.QThread): with open(self._provider_config.get_ca_cert_path()) as f: cert_data = f.read() - assert len(cert_data) > 0, "Could not read certificate data" + leap_assert(len(cert_data) > 0, "Could not read certificate data") x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert_data) digest = x509.digest(method).replace(":", "").lower() - assert digest == fingerprint, \ - "Downloaded certificate has a different fingerprint!" + leap_assert(digest == fingerprint, + "Downloaded certificate has a different fingerprint!") check_ca_fingerprint_data[self.PASSED_KEY] = True except Exception as e: @@ -384,8 +352,8 @@ class ProviderBootstrapper(QtCore.QThread): @return: True if the checks passed, False otherwise @rtype: bool """ - assert self._provider_config, "Cannot check the ca cert " + \ - "without a provider config!" + leap_assert(self._provider_config, "Cannot check the ca cert " + "without a provider config!") logger.debug("Checking api certificate for %s and cert %s" % (self._provider_config.get_api_uri(), @@ -418,7 +386,8 @@ class ProviderBootstrapper(QtCore.QThread): return check_api_certificate_data[self.PASSED_KEY] - def run_provider_setup_checks(self, provider_config, + def run_provider_setup_checks(self, checker, + provider_config, download_if_needed=False): """ Starts the checks needed for a new provider setup @@ -429,43 +398,17 @@ class ProviderBootstrapper(QtCore.QThread): overwrite already downloaded data @type download_if_needed: bool """ - assert provider_config, "We need a provider config!" - assert isinstance(provider_config, ProviderConfig), "Expected " + \ - "ProviderConfig type, not %r" % (type(provider_config),) + leap_assert(provider_config, "We need a provider config!") + leap_assert_type(provider_config, ProviderConfig) self._provider_config = provider_config self._download_if_needed = download_if_needed - QtCore.QMutexLocker(self._checks_lock) - self._checks = [ + checker.add_checks([ self._download_ca_cert, self._check_ca_fingerprint, self._check_api_certificate - ] - - def run(self): - """ - Main run loop for this thread. Executes the checks. - """ - shouldContinue = False - while True: - if self.get_should_quit(): - logger.debug("Quitting provider bootstrap thread") - return - checkSomething = False - with QtCore.QMutexLocker(self._checks_lock): - if len(self._checks) > 0: - check = self._checks.pop(0) - shouldContinue = check() - checkSomething = True - if not shouldContinue: - logger.debug("Something went wrong with the checks, " - "clearing...") - self._checks = [] - checkSomething = False - if not checkSomething: - self.usleep(self.IDLE_SLEEP_INTERVAL) - + ]) if __name__ == "__main__": import sys @@ -476,8 +419,8 @@ if __name__ == "__main__": def sigint_handler(*args, **kwargs): logger.debug('SIGINT catched. shutting down...') - bootstrapper_thread = args[0] - bootstrapper_thread.set_should_quit() + bootstrapper_checks = args[0] + bootstrapper_checks.set_should_quit() QtGui.QApplication.quit() def signal_tester(d): @@ -493,28 +436,32 @@ if __name__ == "__main__": console.setFormatter(formatter) logger.addHandler(console) - bootstrapper_thread = ProviderBootstrapper() + bootstrapper_checks = ProviderBootstrapper() + + checker = CheckerThread() + checker.start() - sigint = partial(sigint_handler, bootstrapper_thread) + sigint = partial(sigint_handler, checker) signal.signal(signal.SIGINT, sigint) timer = QtCore.QTimer() timer.start(500) timer.timeout.connect(lambda: None) app.connect(app, QtCore.SIGNAL("aboutToQuit()"), - bootstrapper_thread.set_should_quit) + checker.set_should_quit) w = QtGui.QWidget() w.resize(100, 100) w.show() - bootstrapper_thread.start() - bootstrapper_thread.run_provider_select_checks("bitmask.net") + bootstrapper_checks.run_provider_select_checks(checker, + "bitmask.net") provider_config = ProviderConfig() if provider_config.load(os.path.join("leap", "providers", "bitmask.net", "provider.json")): - bootstrapper_thread.run_provider_setup_checks(provider_config) + bootstrapper_checks.run_provider_setup_checks(checker, + provider_config) sys.exit(app.exec_()) diff --git a/src/leap/services/eip/vpn.py b/src/leap/services/eip/vpn.py index f117cdbc..88692442 100644 --- a/src/leap/services/eip/vpn.py +++ b/src/leap/services/eip/vpn.py @@ -29,6 +29,7 @@ from leap.config.providerconfig import ProviderConfig from leap.services.eip.vpnlaunchers import get_platform_launcher from leap.services.eip.eipconfig import EIPConfig from leap.services.eip.udstelnet import UDSTelnet +from leap.util.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) ON_POSIX = 'posix' in sys.builtin_module_names @@ -123,13 +124,11 @@ class VPN(QtCore.QThread): socket, or port otherwise @type socket_port: str """ - assert eipconfig, "We need an eip config" - assert isinstance(eipconfig, EIPConfig), "Expected EIPConfig " + \ - "object instead of %s" % (type(eipconfig),) - assert providerconfig, "We need a provider config" - assert isinstance(providerconfig, ProviderConfig), "Expected " + \ - "ProviderConfig object instead of %s" % (type(providerconfig),) - assert not self._started, "Starting process more than once!" + leap_assert(eipconfig, "We need an eip config") + leap_assert_type(eipconfig, EIPConfig) + leap_assert(providerconfig, "We need a provider config") + leap_assert_type(providerconfig, ProviderConfig) + leap_assert(not self._started, "Starting process more than once!") logger.debug("Starting VPN...") @@ -202,7 +201,7 @@ class VPN(QtCore.QThread): @return: response read @rtype: list """ - assert self._tn, "We need a tn connection!" + leap_assert(self._tn, "We need a tn connection!") try: self._tn.write("%s\n" % (command,)) buf = self._tn.read_until(until, 2) diff --git a/src/leap/services/eip/vpnlaunchers.py b/src/leap/services/eip/vpnlaunchers.py index 68978248..00e9c966 100644 --- a/src/leap/services/eip/vpnlaunchers.py +++ b/src/leap/services/eip/vpnlaunchers.py @@ -29,6 +29,7 @@ from abc import ABCMeta, abstractmethod from leap.config.providerconfig import ProviderConfig from leap.services.eip.eipconfig import EIPConfig +from leap.util.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -65,8 +66,8 @@ class VPNLauncher: def get_platform_launcher(): launcher = globals()[platform.system() + "VPNLauncher"] - assert launcher, "Unimplemented platform launcher: %s" % \ - (platform.system(),) + leap_assert(launcher, "Unimplemented platform launcher: %s" % + (platform.system(),)) return launcher() @@ -165,17 +166,15 @@ class LinuxVPNLauncher(VPNLauncher): @return: A VPN command ready to be launched @rtype: list """ - assert eipconfig, "We need an eip config" - assert isinstance(eipconfig, EIPConfig), "Expected EIPConfig " + \ - "object instead of %s" % (type(eipconfig),) - assert providerconfig, "We need a provider config" - assert isinstance(providerconfig, ProviderConfig), "Expected " + \ - "ProviderConfig object instead of %s" % (type(providerconfig),) - assert socket_host, "We need a socket host!" - assert socket_port, "We need a socket port!" + leap_assert(eipconfig, "We need an eip config") + leap_assert_type(eipconfig, EIPConfig) + leap_assert(providerconfig, "We need a provider config") + leap_assert_type(providerconfig, ProviderConfig) + leap_assert(socket_host, "We need a socket host!") + leap_assert(socket_port, "We need a socket port!") openvpn_possibilities = which(self.OPENVPN_BIN) - assert len(openvpn_possibilities) > 0, "We couldn't find openvpn" + leap_assert(len(openvpn_possibilities) > 0, "We couldn't find openvpn") openvpn = openvpn_possibilities[0] args = [] @@ -183,7 +182,8 @@ class LinuxVPNLauncher(VPNLauncher): if _is_pkexec_in_system(): if _is_auth_agent_running(): pkexec_possibilities = which(self.PKEXEC_BIN) - assert len(pkexec_possibilities) > 0, "We couldn't find pkexec" + leap_assert(len(pkexec_possibilities) > 0, + "We couldn't find pkexec") args.append(openvpn) openvpn = pkexec_possibilities[0] else: -- cgit v1.2.3