From ee8fbbdc2f3dbccea3a830b40e9eb0be5b392d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 6 Mar 2013 15:38:05 -0300 Subject: Add EIP service --- src/leap/services/eip/eipbootstrapper.py | 315 +++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 src/leap/services/eip/eipbootstrapper.py (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py new file mode 100644 index 00000000..77d7020a --- /dev/null +++ b/src/leap/services/eip/eipbootstrapper.py @@ -0,0 +1,315 @@ +# -*- coding: utf-8 -*- +# eipbootstrapper.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" +EIP bootstrapping +""" + +import requests +import logging +import os +import errno + +from PySide import QtGui, QtCore + +from leap.config.providerconfig import ProviderConfig +from leap.services.eip.eipconfig import EIPConfig + +logger = logging.getLogger(__name__) + + +class EIPBootstrapper(QtCore.QThread): + """ + Sets up EIP for a provider a series of checks and emits signals + after they are passed. + If a check fails, the subsequent checks are not executed + """ + + PASSED_KEY = "passed" + ERROR_KEY = "error" + + IDLE_SLEEP_INTERVAL = 100 + + # All dicts returned are of the form + # {"passed": bool, "error": str} + download_config = QtCore.Signal(dict) + 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() + + # **************************************************** # + # Dependency injection helpers, override this for more + # granular testing + self._fetcher = requests + # **************************************************** # + + self._session = self._fetcher.session() + self._provider_config = None + 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 + + @return: True if the checks passed, False otherwise + @rtype: bool + """ + + assert self._provider_config, "We need a provider configuration!" + + logger.debug("Downloading EIP config for %s" % + (self._provider_config.get_domain(),)) + + download_config_data = { + self.PASSED_KEY: False, + self.ERROR_KEY: "" + } + + self._eip_config = EIPConfig() + + if self._download_if_needed and \ + os.path.exists(os.path.join(self._eip_config.get_path_prefix(), + "leap", + "providers", + self._provider_config.get_domain(), + "eip-service.json")): + download_config_data[self.PASSED_KEY] = True + self.download_config.emit(download_config_data) + return True + + try: + res = self._session.get("%s/%s/%s/%s" % + (self._provider_config.get_api_uri(), + self._provider_config.get_api_version(), + "config", + "eip-service.json"), + verify=self._provider_config + .get_ca_cert_path()) + res.raise_for_status() + + eip_definition = res.content + + self._eip_config.load(data=eip_definition) + self._eip_config.save(["leap", + "providers", + self._provider_config.get_domain(), + "eip-service.json"]) + + download_config_data[self.PASSED_KEY] = True + except Exception as e: + download_config_data[self.ERROR_KEY] = "%s" % (e,) + + logger.debug("Emitting download_config %s" % (download_config_data,)) + self.download_config.emit(download_config_data) + + return download_config_data[self.PASSED_KEY] + + def _download_client_certificates(self): + """ + Downloads the EIP client certificate for the given provider + + @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!" + + logger.debug("Downloading EIP client certificate for %s" % + (self._provider_config.get_domain(),)) + + download_cert = { + self.PASSED_KEY: False, + self.ERROR_KEY: "" + } + + client_cert_path = self._eip_config.\ + get_client_cert_path(self._provider_config, + about_to_download=True) + + if self._download_if_needed and \ + os.path.exists(client_cert_path): + download_cert[self.PASSED_KEY] = True + self.download_client_certificate.emit(download_cert) + return True + + try: + res = self._session.get("%s/%s/%s/" % + (self._provider_config.get_api_uri(), + self._provider_config.get_api_version(), + "cert"), + verify=self._provider_config + .get_ca_cert_path()) + res.raise_for_status() + + client_cert = res.content + + # TODO: check certificate validity + + try: + os.makedirs(os.path.dirname(client_cert_path)) + except OSError as e: + if e.errno == errno.EEXIST and \ + os.path.isdir(os.path.dirname(client_cert_path)): + pass + else: + raise + + with open(client_cert_path, "w") as f: + f.write(client_cert) + + download_cert[self.PASSED_KEY] = True + except Exception as e: + download_cert[self.ERROR_KEY] = "%s" % (e,) + + logger.debug("Emitting download_client_certificates %s" % + (download_cert,)) + self.download_client_certificate.emit(download_cert) + + return download_cert[self.PASSED_KEY] + + def run_eip_setup_checks(self, 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),) + + self._provider_config = provider_config + self._download_if_needed = download_if_needed + + QtCore.QMutexLocker(self._checks_lock) + self._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__": + import sys + from functools import partial + app = QtGui.QApplication(sys.argv) + + import signal + + def sigint_handler(*args, **kwargs): + logger.debug('SIGINT catched. shutting down...') + bootstrapper_thread = args[0] + bootstrapper_thread.set_should_quit() + QtGui.QApplication.quit() + + def signal_tester(d): + print d + + logger = logging.getLogger(name='leap') + logger.setLevel(logging.DEBUG) + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter( + '%(asctime)s ' + '- %(name)s - %(levelname)s - %(message)s') + console.setFormatter(formatter) + logger.addHandler(console) + + eip_thread = EIPBootstrapper() + + sigint = partial(sigint_handler, eip_thread) + 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) + w = QtGui.QWidget() + w.resize(100, 100) + w.show() + + eip_thread.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) + + sys.exit(app.exec_()) -- cgit v1.2.3 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 +++++++------------------------ 1 file changed, 23 insertions(+), 78 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') 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_()) -- cgit v1.2.3 From 2da60cd0f78378fdcb8f6364a798720281b34b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 09:56:05 -0300 Subject: Check and try to fix certificate permissions --- src/leap/services/eip/eipbootstrapper.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index bd6ab715..79ff28d6 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -30,6 +30,7 @@ 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 +from leap.util.files import check_and_fix_urw_only logger = logging.getLogger(__name__) @@ -147,9 +148,14 @@ class EIPBootstrapper(QtCore.QObject): if self._download_if_needed and \ os.path.exists(client_cert_path): - download_cert[self.PASSED_KEY] = True + try: + check_and_fix_urw_only(client_cert_path) + download_cert[self.PASSED_KEY] = True + except Exception as e: + download_cert[self.PASSED_KEY] = False + download_cert[self.ERROR_KEY] = "%s" % (e,) self.download_client_certificate.emit(download_cert) - return True + return download_cert[self.PASSED_KEY] try: res = self._session.get("%s/%s/%s/" % @@ -176,6 +182,8 @@ class EIPBootstrapper(QtCore.QObject): with open(client_cert_path, "w") as f: f.write(client_cert) + check_and_fix_urw_only(client_cert_path) + download_cert[self.PASSED_KEY] = True except Exception as e: download_cert[self.ERROR_KEY] = "%s" % (e,) -- cgit v1.2.3 From a120904b512394346b286bb417adf34fc622e739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 14:26:38 -0300 Subject: Get eip cert with session_id when possible --- src/leap/services/eip/eipbootstrapper.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 79ff28d6..6fbb98b9 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -26,6 +26,7 @@ import errno from PySide import QtGui, QtCore +from leap.crypto.srpauth import SRPAuth from leap.config.providerconfig import ProviderConfig from leap.services.eip.eipconfig import EIPConfig from leap.util.check import leap_assert, leap_assert_type @@ -158,12 +159,18 @@ class EIPBootstrapper(QtCore.QObject): return download_cert[self.PASSED_KEY] try: + srp_auth = SRPAuth(self._provider_config) + session_id = srp_auth.get_session_id() + cookies = None + if session_id: + cookies = {"_session_id": session_id} res = self._session.get("%s/%s/%s/" % (self._provider_config.get_api_uri(), self._provider_config.get_api_version(), "cert"), verify=self._provider_config - .get_ca_cert_path()) + .get_ca_cert_path(), + cookies=cookies) res.raise_for_status() client_cert = res.content -- cgit v1.2.3 From 70c402fe170ca4e01159b03739b7cacda7b0dfd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 09:43:13 -0300 Subject: Add mtime check for existing json definitions before download Also, wait for threads to finish when quitting --- src/leap/services/eip/eipbootstrapper.py | 44 ++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 6fbb98b9..fdf54bbb 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -31,7 +31,7 @@ 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 -from leap.util.files import check_and_fix_urw_only +from leap.util.files import check_and_fix_urw_only, get_mtime logger = logging.getLogger(__name__) @@ -88,33 +88,39 @@ class EIPBootstrapper(QtCore.QObject): self._eip_config = EIPConfig() - if self._download_if_needed and \ - os.path.exists(os.path.join(self._eip_config.get_path_prefix(), - "leap", - "providers", - self._provider_config.get_domain(), - "eip-service.json")): - download_config_data[self.PASSED_KEY] = True - self.download_config.emit(download_config_data) - return True - try: + headers = {} + mtime = get_mtime(os.path.join(self._eip_config + .get_path_prefix(), + "leap", + "providers", + self._provider_config.get_domain(), + "eip-service.json")) + + if self._download_if_needed and mtime: + headers['if-modified-since'] = mtime + res = self._session.get("%s/%s/%s/%s" % (self._provider_config.get_api_uri(), self._provider_config.get_api_version(), "config", "eip-service.json"), verify=self._provider_config - .get_ca_cert_path()) + .get_ca_cert_path(), + headers=headers) res.raise_for_status() - eip_definition = res.content - - self._eip_config.load(data=eip_definition) - self._eip_config.save(["leap", - "providers", - self._provider_config.get_domain(), - "eip-service.json"]) + # Not modified + if res.status_code == 304: + logger.debug("EIP definition has not been modified") + else: + eip_definition = res.content + + self._eip_config.load(data=eip_definition) + self._eip_config.save(["leap", + "providers", + self._provider_config.get_domain(), + "eip-service.json"]) download_config_data[self.PASSED_KEY] = True except Exception as e: -- cgit v1.2.3 From 0ff122cf9fd0a76871093b595910fb7c0d3bfe85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 10:05:58 -0300 Subject: Pass mtime to pluggableconfig's load Also add a request_helpers file to util where all the helper methods for handling requests should go --- src/leap/services/eip/eipbootstrapper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index fdf54bbb..84a309cb 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -32,6 +32,7 @@ from leap.services.eip.eipconfig import EIPConfig from leap.util.check import leap_assert, leap_assert_type from leap.util.checkerthread import CheckerThread from leap.util.files import check_and_fix_urw_only, get_mtime +from leap.util.request_helpers import get_content logger = logging.getLogger(__name__) @@ -114,9 +115,9 @@ class EIPBootstrapper(QtCore.QObject): if res.status_code == 304: logger.debug("EIP definition has not been modified") else: - eip_definition = res.content + eip_definition, mtime = get_content(res) - self._eip_config.load(data=eip_definition) + self._eip_config.load(data=eip_definition, mtime=mtime) self._eip_config.save(["leap", "providers", self._provider_config.get_domain(), -- cgit v1.2.3 From 12d2835c7d1f3c3d11eaa587b2196c104e6859e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 10:21:15 -0300 Subject: Add mkdir_p method to util.files --- src/leap/services/eip/eipbootstrapper.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 84a309cb..3e4e2063 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -22,7 +22,6 @@ EIP bootstrapping import requests import logging import os -import errno from PySide import QtGui, QtCore @@ -31,7 +30,7 @@ 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 -from leap.util.files import check_and_fix_urw_only, get_mtime +from leap.util.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.util.request_helpers import get_content logger = logging.getLogger(__name__) @@ -184,14 +183,7 @@ class EIPBootstrapper(QtCore.QObject): # TODO: check certificate validity - try: - os.makedirs(os.path.dirname(client_cert_path)) - except OSError as e: - if e.errno == errno.EEXIST and \ - os.path.isdir(os.path.dirname(client_cert_path)): - pass - else: - raise + mkdir_p(os.path.dirname(client_cert_path)) with open(client_cert_path, "w") as f: f.write(client_cert) -- cgit v1.2.3 From 60bcc7b27aa934a0d62033e7152b87d5af638491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 11:09:38 -0300 Subject: Add valid pemfile check before saving the downloaded client cert --- src/leap/services/eip/eipbootstrapper.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 3e4e2063..ec3dfe7b 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -32,6 +32,7 @@ from leap.util.check import leap_assert, leap_assert_type from leap.util.checkerthread import CheckerThread from leap.util.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.util.request_helpers import get_content +from leap.util.certs import is_valid_pemfile logger = logging.getLogger(__name__) @@ -183,6 +184,10 @@ class EIPBootstrapper(QtCore.QObject): # TODO: check certificate validity + if not is_valid_pemfile(client_cert): + raise Exception(self.tr("The downloaded certificate is not a " + "valid PEM file")) + mkdir_p(os.path.dirname(client_cert_path)) with open(client_cert_path, "w") as f: -- cgit v1.2.3 From 240d6b7762f7cc8f4c6fd229e4538aa9aa2262a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 11:33:42 -0300 Subject: Check validity for downloaded certs and re-download if needed --- src/leap/services/eip/eipbootstrapper.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index ec3dfe7b..c83cb1b5 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -32,7 +32,7 @@ from leap.util.check import leap_assert, leap_assert_type from leap.util.checkerthread import CheckerThread from leap.util.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.util.request_helpers import get_content -from leap.util.certs import is_valid_pemfile +from leap.util.certs import is_valid_pemfile, should_redownload logger = logging.getLogger(__name__) @@ -154,6 +154,10 @@ class EIPBootstrapper(QtCore.QObject): get_client_cert_path(self._provider_config, about_to_download=True) + # For re-download if something is wrong with the cert + self._download_if_needed = self._download_if_needed and \ + not should_redownload(client_cert_path) + if self._download_if_needed and \ os.path.exists(client_cert_path): try: -- cgit v1.2.3 From d0dfad6ac2af360de6421ce74a6831b5b81ad019 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 14 Mar 2013 07:08:31 +0900 Subject: namespace leap + leap.common split leap is a namespace package from here on. common folder will be deleted and moved to leap_pycommon repository. --- src/leap/services/eip/eipbootstrapper.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index c83cb1b5..19b74856 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -19,20 +19,21 @@ EIP bootstrapping """ -import requests import logging import os +import requests + from PySide import QtGui, QtCore -from leap.crypto.srpauth import SRPAuth +from leap.common.check import leap_assert, leap_assert_type +from leap.common.certs import is_valid_pemfile, should_redownload +from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.config.providerconfig import ProviderConfig +from leap.crypto.srpauth import SRPAuth from leap.services.eip.eipconfig import EIPConfig -from leap.util.check import leap_assert, leap_assert_type from leap.util.checkerthread import CheckerThread -from leap.util.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.util.request_helpers import get_content -from leap.util.certs import is_valid_pemfile, should_redownload logger = logging.getLogger(__name__) -- cgit v1.2.3 From 3d883f79cfe5f8efecd8cbab512eae65101a8c5a Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 1 May 2013 01:48:57 +0900 Subject: add debug to config and cert uris --- src/leap/services/eip/eipbootstrapper.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 19b74856..83f0a0c2 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -102,11 +102,14 @@ class EIPBootstrapper(QtCore.QObject): if self._download_if_needed and mtime: headers['if-modified-since'] = mtime - res = self._session.get("%s/%s/%s/%s" % - (self._provider_config.get_api_uri(), - self._provider_config.get_api_version(), - "config", - "eip-service.json"), + # there is some confusion with this uri, + # it's in 1/config/eip, config/eip and config/1/eip... + config_uri = "%s/%s/config/eip-service.json" % ( + self._provider_config.get_api_uri(), + self._provider_config.get_api_version()) + logger.debug('Downloading eip config from: %s' % config_uri) + + res = self._session.get(config_uri, verify=self._provider_config .get_ca_cert_path(), headers=headers) @@ -176,15 +179,15 @@ class EIPBootstrapper(QtCore.QObject): cookies = None if session_id: cookies = {"_session_id": session_id} - res = self._session.get("%s/%s/%s/" % - (self._provider_config.get_api_uri(), - self._provider_config.get_api_version(), - "cert"), + cert_uri = "%s/%s/cert" % ( + self._provider_config.get_api_uri(), + self._provider_config.get_api_version()) + logger.debug('getting cert from uri: %s' % cert_uri) + res = self._session.get(cert_uri, verify=self._provider_config .get_ca_cert_path(), cookies=cookies) res.raise_for_status() - client_cert = res.content # TODO: check certificate validity -- cgit v1.2.3 From 2dae2703fb8c2ae7e721ce83020c0dd10ff9ca33 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 3 May 2013 02:59:22 +0900 Subject: updated documentation * documentation reviewed after rewrite, ready for 0.2.1 * updated docstrings format to fit sphinx autodoc --- src/leap/services/eip/eipbootstrapper.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 83f0a0c2..a881f235 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -73,8 +73,8 @@ class EIPBootstrapper(QtCore.QObject): """ Downloads the EIP config for the given provider - @return: True if the checks passed, False otherwise - @rtype: bool + :return: True if the checks passed, False otherwise + :rtype: bool """ leap_assert(self._provider_config, @@ -140,8 +140,8 @@ class EIPBootstrapper(QtCore.QObject): """ Downloads the EIP client certificate for the given provider - @return: True if the checks passed, False otherwise - @rtype: bool + :return: True if the checks passed, False otherwise + :rtype: bool """ leap_assert(self._provider_config, "We need a provider configuration!") leap_assert(self._eip_config, "We need an eip configuration!") @@ -219,8 +219,8 @@ class EIPBootstrapper(QtCore.QObject): """ Starts the checks needed for a new eip setup - @param provider_config: Provider configuration - @type provider_config: ProviderConfig + :param provider_config: Provider configuration + :type provider_config: ProviderConfig """ leap_assert(provider_config, "We need a provider config!") leap_assert_type(provider_config, ProviderConfig) -- cgit v1.2.3 From 4c726c1531abfe288604eaa4c1d347e85bed81eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 3 Jun 2013 15:02:41 -0300 Subject: Use Twisted's deferToThread and Deferreds to handle parallel tasks This removes CheckerThread --- src/leap/services/eip/eipbootstrapper.py | 264 +++++++++---------------------- 1 file changed, 78 insertions(+), 186 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index a881f235..7216bb80 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -22,9 +22,7 @@ EIP bootstrapping import logging import os -import requests - -from PySide import QtGui, QtCore +from PySide import QtCore from leap.common.check import leap_assert, leap_assert_type from leap.common.certs import is_valid_pemfile, should_redownload @@ -32,49 +30,34 @@ from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.config.providerconfig import ProviderConfig from leap.crypto.srpauth import SRPAuth from leap.services.eip.eipconfig import EIPConfig -from leap.util.checkerthread import CheckerThread from leap.util.request_helpers import get_content +from leap.services.abstractbootstrapper import AbstractBootstrapper logger = logging.getLogger(__name__) -class EIPBootstrapper(QtCore.QObject): +class EIPBootstrapper(AbstractBootstrapper): """ Sets up EIP for a provider a series of checks and emits signals after they are passed. If a check fails, the subsequent checks are not executed """ - PASSED_KEY = "passed" - ERROR_KEY = "error" - - IDLE_SLEEP_INTERVAL = 100 - # All dicts returned are of the form # {"passed": bool, "error": str} download_config = QtCore.Signal(dict) download_client_certificate = QtCore.Signal(dict) def __init__(self): - QtCore.QObject.__init__(self) + AbstractBootstrapper.__init__(self) - # **************************************************** # - # Dependency injection helpers, override this for more - # granular testing - self._fetcher = requests - # **************************************************** # - - self._session = self._fetcher.session() self._provider_config = None self._eip_config = None self._download_if_needed = False - def _download_config(self): + def _download_config(self, *args): """ Downloads the EIP config for the given provider - - :return: True if the checks passed, False otherwise - :rtype: bool """ leap_assert(self._provider_config, @@ -83,65 +66,47 @@ class EIPBootstrapper(QtCore.QObject): logger.debug("Downloading EIP config for %s" % (self._provider_config.get_domain(),)) - download_config_data = { - self.PASSED_KEY: False, - self.ERROR_KEY: "" - } - self._eip_config = EIPConfig() - try: - headers = {} - mtime = get_mtime(os.path.join(self._eip_config - .get_path_prefix(), - "leap", - "providers", - self._provider_config.get_domain(), - "eip-service.json")) - - if self._download_if_needed and mtime: - headers['if-modified-since'] = mtime - - # there is some confusion with this uri, - # it's in 1/config/eip, config/eip and config/1/eip... - config_uri = "%s/%s/config/eip-service.json" % ( - self._provider_config.get_api_uri(), - self._provider_config.get_api_version()) - logger.debug('Downloading eip config from: %s' % config_uri) - - res = self._session.get(config_uri, - verify=self._provider_config - .get_ca_cert_path(), - headers=headers) - res.raise_for_status() - - # Not modified - if res.status_code == 304: - logger.debug("EIP definition has not been modified") - else: - eip_definition, mtime = get_content(res) - - self._eip_config.load(data=eip_definition, mtime=mtime) - self._eip_config.save(["leap", + headers = {} + mtime = get_mtime(os.path.join(self._eip_config + .get_path_prefix(), + "leap", "providers", self._provider_config.get_domain(), - "eip-service.json"]) - - download_config_data[self.PASSED_KEY] = True - except Exception as e: - download_config_data[self.ERROR_KEY] = "%s" % (e,) - - logger.debug("Emitting download_config %s" % (download_config_data,)) - self.download_config.emit(download_config_data) - - return download_config_data[self.PASSED_KEY] - - def _download_client_certificates(self): + "eip-service.json")) + + if self._download_if_needed and mtime: + headers['if-modified-since'] = mtime + + # there is some confusion with this uri, + # it's in 1/config/eip, config/eip and config/1/eip... + config_uri = "%s/%s/config/eip-service.json" % ( + self._provider_config.get_api_uri(), + self._provider_config.get_api_version()) + logger.debug('Downloading eip config from: %s' % config_uri) + + res = self._session.get(config_uri, + verify=self._provider_config + .get_ca_cert_path(), + headers=headers) + res.raise_for_status() + + # Not modified + if res.status_code == 304: + logger.debug("EIP definition has not been modified") + else: + eip_definition, mtime = get_content(res) + + self._eip_config.load(data=eip_definition, mtime=mtime) + self._eip_config.save(["leap", + "providers", + self._provider_config.get_domain(), + "eip-service.json"]) + + def _download_client_certificates(self, *args): """ Downloads the EIP client certificate for the given provider - - :return: True if the checks passed, False otherwise - :rtype: bool """ leap_assert(self._provider_config, "We need a provider configuration!") leap_assert(self._eip_config, "We need an eip configuration!") @@ -149,11 +114,6 @@ class EIPBootstrapper(QtCore.QObject): logger.debug("Downloading EIP client certificate for %s" % (self._provider_config.get_domain(),)) - download_cert = { - self.PASSED_KEY: False, - self.ERROR_KEY: "" - } - client_cert_path = self._eip_config.\ get_client_cert_path(self._provider_config, about_to_download=True) @@ -164,56 +124,39 @@ class EIPBootstrapper(QtCore.QObject): if self._download_if_needed and \ os.path.exists(client_cert_path): - try: - check_and_fix_urw_only(client_cert_path) - download_cert[self.PASSED_KEY] = True - except Exception as e: - download_cert[self.PASSED_KEY] = False - download_cert[self.ERROR_KEY] = "%s" % (e,) - self.download_client_certificate.emit(download_cert) - return download_cert[self.PASSED_KEY] - - try: - srp_auth = SRPAuth(self._provider_config) - session_id = srp_auth.get_session_id() - cookies = None - if session_id: - cookies = {"_session_id": session_id} - cert_uri = "%s/%s/cert" % ( - self._provider_config.get_api_uri(), - self._provider_config.get_api_version()) - logger.debug('getting cert from uri: %s' % cert_uri) - res = self._session.get(cert_uri, - verify=self._provider_config - .get_ca_cert_path(), - cookies=cookies) - res.raise_for_status() - client_cert = res.content - - # TODO: check certificate validity - - if not is_valid_pemfile(client_cert): - raise Exception(self.tr("The downloaded certificate is not a " - "valid PEM file")) - - mkdir_p(os.path.dirname(client_cert_path)) - - with open(client_cert_path, "w") as f: - f.write(client_cert) - check_and_fix_urw_only(client_cert_path) - - download_cert[self.PASSED_KEY] = True - except Exception as e: - download_cert[self.ERROR_KEY] = "%s" % (e,) - - logger.debug("Emitting download_client_certificates %s" % - (download_cert,)) - self.download_client_certificate.emit(download_cert) - - return download_cert[self.PASSED_KEY] - - def run_eip_setup_checks(self, checker, + return + + srp_auth = SRPAuth(self._provider_config) + session_id = srp_auth.get_session_id() + cookies = None + if session_id: + cookies = {"_session_id": session_id} + cert_uri = "%s/%s/cert" % ( + self._provider_config.get_api_uri(), + self._provider_config.get_api_version()) + logger.debug('getting cert from uri: %s' % cert_uri) + res = self._session.get(cert_uri, + verify=self._provider_config + .get_ca_cert_path(), + cookies=cookies) + res.raise_for_status() + client_cert = res.content + + # TODO: check certificate validity + + if not is_valid_pemfile(client_cert): + raise Exception(self.tr("The downloaded certificate is not a " + "valid PEM file")) + + mkdir_p(os.path.dirname(client_cert_path)) + + with open(client_cert_path, "w") as f: + f.write(client_cert) + + check_and_fix_urw_only(client_cert_path) + + def run_eip_setup_checks(self, provider_config, download_if_needed=False): """ @@ -228,60 +171,9 @@ class EIPBootstrapper(QtCore.QObject): self._provider_config = provider_config self._download_if_needed = download_if_needed - checker.add_checks([ - self._download_config, - self._download_client_certificates - ]) - - -if __name__ == "__main__": - import sys - from functools import partial - app = QtGui.QApplication(sys.argv) - - import signal - - def sigint_handler(*args, **kwargs): - logger.debug('SIGINT catched. shutting down...') - checker = args[0] - checker.set_should_quit() - QtGui.QApplication.quit() - - def signal_tester(d): - print d - - logger = logging.getLogger(name='leap') - logger.setLevel(logging.DEBUG) - console = logging.StreamHandler() - console.setLevel(logging.DEBUG) - formatter = logging.Formatter( - '%(asctime)s ' - '- %(name)s - %(levelname)s - %(message)s') - console.setFormatter(formatter) - logger.addHandler(console) - - eip_checks = EIPBootstrapper() - checker = CheckerThread() - - 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()"), - checker.set_should_quit) - w = QtGui.QWidget() - w.resize(100, 100) - w.show() - - checker.start() - - provider_config = ProviderConfig() - if provider_config.load(os.path.join("leap", - "providers", - "bitmask.net", - "provider.json")): - eip_checks.run_eip_setup_checks(checker, provider_config) - - sys.exit(app.exec_()) + cb_chain = [ + (self._download_config, self.download_config), + (self._download_client_certificates, self.download_client_certificate) + ] + + self.addCallbackChain(cb_chain) -- cgit v1.2.3 From 655cec1fec89eb30fc17bdc0a5f527e5a91ba5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 4 Jun 2013 12:56:17 -0300 Subject: Remove CheckerThread from SRPAuth Also, some pep8 fixes --- src/leap/services/eip/eipbootstrapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 7216bb80..51c3dab4 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -173,7 +173,8 @@ class EIPBootstrapper(AbstractBootstrapper): cb_chain = [ (self._download_config, self.download_config), - (self._download_client_certificates, self.download_client_certificate) + (self._download_client_certificates, \ + self.download_client_certificate) ] self.addCallbackChain(cb_chain) -- cgit v1.2.3 From cd11784b8fdf0cb45783e8d6a8e9b5288f34820d Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 13 Jun 2013 22:48:29 +0900 Subject: pep8 --- src/leap/services/eip/eipbootstrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 51c3dab4..4da8f90f 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -173,8 +173,8 @@ class EIPBootstrapper(AbstractBootstrapper): cb_chain = [ (self._download_config, self.download_config), - (self._download_client_certificates, \ - self.download_client_certificate) + (self._download_client_certificates, + self.download_client_certificate) ] self.addCallbackChain(cb_chain) -- cgit v1.2.3 From 14ddf421eb7ef2c39d4a375b4203cf5692402839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 27 Jun 2013 17:51:36 -0300 Subject: Change leap.common.certs.* calls to be dependent on certs This gives us the possibility of mocking up the methods inside it. Also, return the deferred from the run_* method --- src/leap/services/eip/eipbootstrapper.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src/leap/services/eip/eipbootstrapper.py') diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/services/eip/eipbootstrapper.py index 4da8f90f..b2af0aea 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/services/eip/eipbootstrapper.py @@ -25,7 +25,7 @@ import os from PySide import QtCore from leap.common.check import leap_assert, leap_assert_type -from leap.common.certs import is_valid_pemfile, should_redownload +from leap.common import certs from leap.common.files import check_and_fix_urw_only, get_mtime, mkdir_p from leap.config.providerconfig import ProviderConfig from leap.crypto.srpauth import SRPAuth @@ -120,7 +120,7 @@ class EIPBootstrapper(AbstractBootstrapper): # For re-download if something is wrong with the cert self._download_if_needed = self._download_if_needed and \ - not should_redownload(client_cert_path) + not certs.should_redownload(client_cert_path) if self._download_if_needed and \ os.path.exists(client_cert_path): @@ -143,9 +143,7 @@ class EIPBootstrapper(AbstractBootstrapper): res.raise_for_status() client_cert = res.content - # TODO: check certificate validity - - if not is_valid_pemfile(client_cert): + if not certs.is_valid_pemfile(client_cert): raise Exception(self.tr("The downloaded certificate is not a " "valid PEM file")) @@ -177,4 +175,4 @@ class EIPBootstrapper(AbstractBootstrapper): self.download_client_certificate) ] - self.addCallbackChain(cb_chain) + return self.addCallbackChain(cb_chain) -- cgit v1.2.3