diff options
Diffstat (limited to 'src/leap')
-rw-r--r-- | src/leap/bitmask/__init__.py (renamed from src/leap/config/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/_version.py (renamed from src/leap/_version.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/app.py (renamed from src/leap/app.py) | 44 | ||||
-rw-r--r-- | src/leap/bitmask/config/__init__.py (renamed from src/leap/crypto/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/config/leapsettings.py (renamed from src/leap/config/leapsettings.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/config/provider_spec.py (renamed from src/leap/config/provider_spec.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/config/providerconfig.py (renamed from src/leap/config/providerconfig.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/config/tests/test_providerconfig.py (renamed from src/leap/config/tests/test_providerconfig.py) | 4 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/__init__.py (renamed from src/leap/provider/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/srpauth.py (renamed from src/leap/crypto/srpauth.py) | 26 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/srpregister.py (renamed from src/leap/crypto/srpregister.py) | 7 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/__init__.py (renamed from src/leap/crypto/tests/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/eip-service.json (renamed from src/leap/crypto/tests/eip-service.json) | 0 | ||||
-rwxr-xr-x | src/leap/bitmask/crypto/tests/fake_provider.py (renamed from src/leap/crypto/tests/fake_provider.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/openvpn.pem (renamed from src/leap/crypto/tests/openvpn.pem) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/test_provider.json (renamed from src/leap/crypto/tests/test_provider.json) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/test_srpauth.py (renamed from src/leap/crypto/tests/test_srpauth.py) | 50 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/test_srpregister.py (renamed from src/leap/crypto/tests/test_srpregister.py) | 6 | ||||
-rw-r--r-- | src/leap/bitmask/crypto/tests/wrongcert.pem (renamed from src/leap/crypto/tests/wrongcert.pem) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/gui/__init__.py (renamed from src/leap/gui/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/gui/loggerwindow.py (renamed from src/leap/gui/loggerwindow.py) | 27 | ||||
-rw-r--r-- | src/leap/bitmask/gui/login.py (renamed from src/leap/gui/login.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/gui/mainwindow.py (renamed from src/leap/gui/mainwindow.py) | 180 | ||||
-rw-r--r-- | src/leap/bitmask/gui/statuspanel.py (renamed from src/leap/gui/statuspanel.py) | 256 | ||||
-rw-r--r-- | src/leap/bitmask/gui/twisted_main.py (renamed from src/leap/gui/twisted_main.py) | 6 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/loggerwindow.ui (renamed from src/leap/gui/ui/loggerwindow.ui) | 42 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/login.ui (renamed from src/leap/gui/ui/login.ui) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/mainwindow.ui (renamed from src/leap/gui/ui/mainwindow.ui) | 7 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/statuspanel.ui (renamed from src/leap/gui/ui/statuspanel.ui) | 226 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/wizard.ui (renamed from src/leap/gui/ui/wizard.ui) | 36 | ||||
-rw-r--r-- | src/leap/bitmask/gui/wizard.py (renamed from src/leap/gui/wizard.py) | 20 | ||||
-rw-r--r-- | src/leap/bitmask/gui/wizardpage.py (renamed from src/leap/gui/wizardpage.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/platform_init/__init__.py (renamed from src/leap/platform_init/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/platform_init/initializers.py (renamed from src/leap/platform_init/initializers.py) | 12 | ||||
-rw-r--r-- | src/leap/bitmask/platform_init/locks.py (renamed from src/leap/platform_init/locks.py) | 4 | ||||
-rw-r--r-- | src/leap/bitmask/provider/__init__.py (renamed from src/leap/services/eip/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/provider/supportedapis.py (renamed from src/leap/provider/supportedapis.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/__init__.py (renamed from src/leap/services/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/abstractbootstrapper.py (renamed from src/leap/services/abstractbootstrapper.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/__init__.py (renamed from src/leap/services/eip/tests/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/eipbootstrapper.py (renamed from src/leap/services/eip/eipbootstrapper.py) | 14 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/eipconfig.py (renamed from src/leap/services/eip/eipconfig.py) | 4 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/eipspec.py (renamed from src/leap/services/eip/eipspec.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/providerbootstrapper.py (renamed from src/leap/services/eip/providerbootstrapper.py) | 10 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/__init__.py (renamed from src/leap/services/mail/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/test_eipbootstrapper.py (renamed from src/leap/services/eip/tests/test_eipbootstrapper.py) | 10 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/test_eipconfig.py (renamed from src/leap/services/eip/tests/test_eipconfig.py) | 7 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py (renamed from src/leap/services/eip/tests/test_providerbootstrapper.py) | 69 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py (renamed from src/leap/services/eip/tests/test_vpngatewayselector.py) | 18 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/tests/wrongcert.pem (renamed from src/leap/services/eip/tests/wrongcert.pem) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/udstelnet.py (renamed from src/leap/services/eip/udstelnet.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/vpnlaunchers.py (renamed from src/leap/services/eip/vpnlaunchers.py) | 23 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/vpnprocess.py (renamed from src/leap/services/eip/vpnprocess.py) | 20 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/__init__.py (renamed from src/leap/services/soledad/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/imap.py (renamed from src/leap/services/mail/imap.py) | 33 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/smtpbootstrapper.py (renamed from src/leap/services/mail/smtpbootstrapper.py) | 8 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/smtpconfig.py (renamed from src/leap/services/mail/smtpconfig.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/smtpspec.py (renamed from src/leap/services/mail/smtpspec.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/soledad/__init__.py (renamed from src/leap/services/tests/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/soledad/soledadbootstrapper.py (renamed from src/leap/services/soledad/soledadbootstrapper.py) | 78 | ||||
-rw-r--r-- | src/leap/bitmask/services/soledad/soledadconfig.py (renamed from src/leap/services/soledad/soledadconfig.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/services/soledad/soledadspec.py (renamed from src/leap/services/soledad/soledadspec.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/tests/__init__.py (renamed from src/leap/util/tests/__init__.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/services/tests/test_abstractbootstrapper.py (renamed from src/leap/services/tests/test_abstractbootstrapper.py) | 5 | ||||
-rw-r--r-- | src/leap/bitmask/services/tx.py (renamed from src/leap/services/tx.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/util/__init__.py (renamed from src/leap/util/__init__.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/util/constants.py (renamed from src/leap/util/constants.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/keyring_helpers.py (renamed from src/leap/util/keyring_helpers.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/leap_argparse.py (renamed from src/leap/util/leap_argparse.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/util/leap_log_handler.py (renamed from src/leap/util/leap_log_handler.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/privilege_policies.py (renamed from src/leap/util/privilege_policies.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/pyside_tests_helper.py (renamed from src/leap/util/pyside_tests_helper.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/reqs.txt | 14 | ||||
-rw-r--r-- | src/leap/bitmask/util/request_helpers.py (renamed from src/leap/util/request_helpers.py) | 2 | ||||
-rw-r--r-- | src/leap/bitmask/util/requirement_checker.py (renamed from src/leap/util/requirement_checker.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/streamtologger.py (renamed from src/leap/util/streamtologger.py) | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/tests/__init__.py | 0 | ||||
-rw-r--r-- | src/leap/bitmask/util/tests/test_is_release_version.py (renamed from src/leap/util/tests/test_is_release_version.py) | 4 | ||||
-rw-r--r-- | src/leap/bitmask/util/tests/test_leap_log_handler.py (renamed from src/leap/util/tests/test_leap_log_handler.py) | 10 | ||||
-rw-r--r-- | src/leap/bitmask/util/tests/test_streamtologger.py (renamed from src/leap/util/tests/test_streamtologger.py) | 6 |
80 files changed, 987 insertions, 319 deletions
diff --git a/src/leap/config/__init__.py b/src/leap/bitmask/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/config/__init__.py +++ b/src/leap/bitmask/__init__.py diff --git a/src/leap/_version.py b/src/leap/bitmask/_version.py index 05542975..412b0c9e 100644 --- a/src/leap/_version.py +++ b/src/leap/bitmask/_version.py @@ -185,7 +185,7 @@ def versions_from_parentdir(parentdir_prefix, versionfile_source, tag_prefix = "" parentdir_prefix = "bitmask-" -versionfile_source = "src/leap/_version.py" +versionfile_source = "src/leap/bitmask/_version.py" def get_versions(default={"version": "unknown", "full": ""}, verbose=False): diff --git a/src/leap/app.py b/src/leap/bitmask/app.py index 22340d4d..6ffa1d25 100644 --- a/src/leap/app.py +++ b/src/leap/bitmask/app.py @@ -24,27 +24,15 @@ from functools import partial from PySide import QtCore, QtGui +from leap.bitmask.util import leap_argparse +from leap.bitmask.util.leap_log_handler import LeapLogHandler +from leap.bitmask.util.streamtologger import StreamToLogger from leap.common.events import server as event_server -from leap.util import __version__ as VERSION -from leap.util import leap_argparse -from leap.util.leap_log_handler import LeapLogHandler -from leap.util.streamtologger import StreamToLogger -from leap.util.requirement_checker import check_requirements -from leap.gui import locale_rc -from leap.gui import twisted_main -from leap.gui.mainwindow import MainWindow -from leap.platform_init import IS_MAC -from leap.platform_init.locks import we_are_the_one_and_only -from leap.services.tx import leap_services - import codecs codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None) -# pylint: avoid unused import -assert(locale_rc) - def sigint_handler(*args, **kwargs): """ @@ -144,6 +132,29 @@ def main(): logfile = opts.log_file openvpn_verb = opts.openvpn_verb + ############################################################# + # Given how paths and bundling works, we need to delay the imports + # of certain parts that depend on this path settings. + # So first we set all the places where standalone might be queried. + from leap.bitmask.config.providerconfig import ProviderConfig + from leap.common.config.baseconfig import BaseConfig + from leap.bitmask.services.eip.eipconfig import EIPConfig + BaseConfig.standalone = standalone + ProviderConfig.standalone = standalone + EIPConfig.standalone = standalone + + # And then we import all the other stuff + from leap.bitmask.gui import locale_rc + from leap.bitmask.gui import twisted_main + from leap.bitmask.gui.mainwindow import MainWindow + from leap.bitmask.platform_init import IS_MAC + from leap.bitmask.platform_init.locks import we_are_the_one_and_only + from leap.bitmask.util import __version__ as VERSION + from leap.bitmask.util.requirement_checker import check_requirements + + # pylint: avoid unused import + assert(locale_rc) + logger = add_logger_handlers(debug, logfile) replace_stdout_stderr_with_logging(logger) @@ -162,6 +173,9 @@ def main(): logger.info('Starting app') + ProviderConfig.standalone = standalone + EIPConfig.standalone = standalone + # We force the style if on KDE so that it doesn't load all the kde # libs, which causes a compatibility issue in some systems. # For more info, see issue #3194 diff --git a/src/leap/crypto/__init__.py b/src/leap/bitmask/config/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/crypto/__init__.py +++ b/src/leap/bitmask/config/__init__.py diff --git a/src/leap/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py index 35010280..35010280 100644 --- a/src/leap/config/leapsettings.py +++ b/src/leap/bitmask/config/leapsettings.py diff --git a/src/leap/config/provider_spec.py b/src/leap/bitmask/config/provider_spec.py index cf942c7b..cf942c7b 100644 --- a/src/leap/config/provider_spec.py +++ b/src/leap/bitmask/config/provider_spec.py diff --git a/src/leap/config/providerconfig.py b/src/leap/bitmask/config/providerconfig.py index f899b17c..c65932be 100644 --- a/src/leap/config/providerconfig.py +++ b/src/leap/bitmask/config/providerconfig.py @@ -21,9 +21,9 @@ Provider configuration import logging import os +from leap.bitmask.config.provider_spec import leap_provider_spec from leap.common.check import leap_check from leap.common.config.baseconfig import BaseConfig, LocalizedKey -from leap.config.provider_spec import leap_provider_spec logger = logging.getLogger(__name__) diff --git a/src/leap/config/tests/test_providerconfig.py b/src/leap/bitmask/config/tests/test_providerconfig.py index ff2828e6..7661a1ce 100644 --- a/src/leap/config/tests/test_providerconfig.py +++ b/src/leap/bitmask/config/tests/test_providerconfig.py @@ -27,9 +27,9 @@ import os import json import copy +from leap.bitmask.config.providerconfig import ProviderConfig, MissingCACert +from leap.bitmask.services import get_supported from leap.common.testing.basetest import BaseLeapTest -from leap.config.providerconfig import ProviderConfig, MissingCACert -from leap.services import get_supported from mock import Mock diff --git a/src/leap/provider/__init__.py b/src/leap/bitmask/crypto/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/provider/__init__.py +++ b/src/leap/bitmask/crypto/__init__.py diff --git a/src/leap/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py index fc0533fc..7b91205f 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/bitmask/crypto/srpauth.py @@ -29,9 +29,9 @@ from functools import partial from PySide import QtCore from twisted.internet import threads +from leap.bitmask.util import request_helpers as reqhelper +from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.common.check import leap_assert -from leap.util.constants import REQUEST_TIMEOUT -from leap.util import request_helpers as reqhelper from leap.common.events import signal as events_signal from leap.common.events import events_pb2 as proto @@ -193,6 +193,9 @@ class SRPAuth(QtCore.QObject): :type password: str """ logger.debug("Authentication preprocessing...") + + username = username.lower() + self._srp_user = self._srp.User(username, password, self._hashfun, @@ -478,13 +481,14 @@ class SRPAuth(QtCore.QObject): """ logger.debug("Starting logout...") - leap_assert(self.get_session_id(), - "Cannot logout an unexisting session") + if self.get_session_id() is None: + logger.debug("Already logged out") + return logout_url = "%s/%s/%s/" % (self._provider_config.get_api_uri(), self._provider_config. get_api_version(), - "sessions") + "logout") try: self._session.delete(logout_url, data=self.get_session_id(), @@ -494,12 +498,12 @@ class SRPAuth(QtCore.QObject): except Exception as e: logger.warning("Something went wrong with the logout: %r" % (e,)) - - self.set_session_id(None) - self.set_uid(None) - # Also reset the session - self._session = self._fetcher.session() - logger.debug("Successfully logged out.") + else: + self.set_session_id(None) + self.set_uid(None) + # Also reset the session + self._session = self._fetcher.session() + logger.debug("Successfully logged out.") def set_session_id(self, session_id): QtCore.QMutexLocker(self._session_id_lock) diff --git a/src/leap/crypto/srpregister.py b/src/leap/bitmask/crypto/srpregister.py index de1978b5..5c0a8efc 100644 --- a/src/leap/crypto/srpregister.py +++ b/src/leap/bitmask/crypto/srpregister.py @@ -24,8 +24,8 @@ import srp from PySide import QtCore from urlparse import urlparse -from leap.config.providerconfig import ProviderConfig -from leap.util.constants import SIGNUP_TIMEOUT +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.util.constants import SIGNUP_TIMEOUT from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -107,6 +107,9 @@ class SRPRegister(QtCore.QObject): :rtype: tuple :rparam: (ok, request) """ + + username = username.lower() + salt, verifier = self._srp.create_salted_verification_key( username, password, diff --git a/src/leap/crypto/tests/__init__.py b/src/leap/bitmask/crypto/tests/__init__.py index 7f118735..7f118735 100644 --- a/src/leap/crypto/tests/__init__.py +++ b/src/leap/bitmask/crypto/tests/__init__.py diff --git a/src/leap/crypto/tests/eip-service.json b/src/leap/bitmask/crypto/tests/eip-service.json index 24df42a2..24df42a2 100644 --- a/src/leap/crypto/tests/eip-service.json +++ b/src/leap/bitmask/crypto/tests/eip-service.json diff --git a/src/leap/crypto/tests/fake_provider.py b/src/leap/bitmask/crypto/tests/fake_provider.py index 54af485d..54af485d 100755 --- a/src/leap/crypto/tests/fake_provider.py +++ b/src/leap/bitmask/crypto/tests/fake_provider.py diff --git a/src/leap/crypto/tests/openvpn.pem b/src/leap/bitmask/crypto/tests/openvpn.pem index a95e9370..a95e9370 100644 --- a/src/leap/crypto/tests/openvpn.pem +++ b/src/leap/bitmask/crypto/tests/openvpn.pem diff --git a/src/leap/crypto/tests/test_provider.json b/src/leap/bitmask/crypto/tests/test_provider.json index c37bef8f..c37bef8f 100644 --- a/src/leap/crypto/tests/test_provider.json +++ b/src/leap/bitmask/crypto/tests/test_provider.json diff --git a/src/leap/crypto/tests/test_srpauth.py b/src/leap/bitmask/crypto/tests/test_srpauth.py index e3258fd3..6fb2b739 100644 --- a/src/leap/crypto/tests/test_srpauth.py +++ b/src/leap/bitmask/crypto/tests/test_srpauth.py @@ -28,19 +28,20 @@ import binascii import requests import mock +from functools import partial + from mock import MagicMock from nose.twistedtools import reactor, deferred from twisted.python import log from twisted.internet import threads -from functools import partial from requests.models import Response from simplejson.decoder import JSONDecodeError +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto import srpregister, srpauth +from leap.bitmask.crypto.tests import fake_provider +from leap.bitmask.util.request_helpers import get_content from leap.common.testing.https_server import where -from leap.config.providerconfig import ProviderConfig -from leap.crypto import srpregister, srpauth -from leap.crypto.tests import fake_provider -from leap.util.request_helpers import get_content log.startLogging(sys.stdout) @@ -246,9 +247,9 @@ class SRPAuthTestCase(unittest.TestCase): def wrapper(_): with self.assertRaises(srpauth.SRPAuthUnknownUser): - with mock.patch('leap.util.request_helpers.get_content', - new=mock.create_autospec(get_content)) as \ - content: + with mock.patch( + 'leap.bitmask.util.request_helpers.get_content', + new=mock.create_autospec(get_content)) as content: content.return_value = ("{}", 0) self.auth_backend._start_authentication( @@ -263,9 +264,9 @@ class SRPAuthTestCase(unittest.TestCase): def wrapper(_): with self.assertRaises(srpauth.SRPAuthBadStatusCode): - with mock.patch('leap.util.request_helpers.get_content', - new=mock.create_autospec(get_content)) as \ - content: + with mock.patch( + 'leap.bitmask.util.request_helpers.get_content', + new=mock.create_autospec(get_content)) as content: content.return_value = ("{}", 0) self.auth_backend._start_authentication(None, @@ -280,9 +281,9 @@ class SRPAuthTestCase(unittest.TestCase): def wrapper(_): with self.assertRaises(srpauth.SRPAuthNoSalt): - with mock.patch('leap.util.request_helpers.get_content', - new=mock.create_autospec(get_content)) as \ - content: + with mock.patch( + 'leap.bitmask.util.request_helpers.get_content', + new=mock.create_autospec(get_content)) as content: content.return_value = ("{}", 0) self.auth_backend._start_authentication(None, @@ -297,9 +298,9 @@ class SRPAuthTestCase(unittest.TestCase): def wrapper(_): with self.assertRaises(srpauth.SRPAuthNoB): - with mock.patch('leap.util.request_helpers.get_content', - new=mock.create_autospec(get_content)) as \ - content: + with mock.patch( + 'leap.bitmask.util.request_helpers.get_content', + new=mock.create_autospec(get_content)) as content: content.return_value = ('{"salt": ""}', 0) self.auth_backend._start_authentication(None, @@ -316,7 +317,7 @@ class SRPAuthTestCase(unittest.TestCase): test_B = "67890" def wrapper(_): - with mock.patch('leap.util.request_helpers.get_content', + with mock.patch('leap.bitmask.util.request_helpers.get_content', new=mock.create_autospec(get_content)) as \ content: content.return_value = ('{"salt":"%s", "B":"%s"}' % (test_salt, @@ -394,7 +395,7 @@ class SRPAuthTestCase(unittest.TestCase): d = self._prepare_auth_challenge() def wrapper(salt_B): - with mock.patch('leap.util.request_helpers.get_content', + with mock.patch('leap.bitmask.util.request_helpers.get_content', new=mock.create_autospec(get_content)) as \ content: content.return_value = ("{", 0) @@ -420,7 +421,7 @@ class SRPAuthTestCase(unittest.TestCase): return_value=res) def wrapper(salt_B): - with mock.patch('leap.util.request_helpers.get_content', + with mock.patch('leap.bitmask.util.request_helpers.get_content', new=mock.create_autospec(get_content)) as \ content: content.return_value = ("", 0) @@ -444,7 +445,7 @@ class SRPAuthTestCase(unittest.TestCase): return_value=res) def wrapper(salt_B): - with mock.patch('leap.util.request_helpers.get_content', + with mock.patch('leap.bitmask.util.request_helpers.get_content', new=mock.create_autospec(get_content)) as \ content: content.return_value = ("[]", 0) @@ -468,7 +469,7 @@ class SRPAuthTestCase(unittest.TestCase): return_value=res) def wrapper(salt_B): - with mock.patch('leap.util.request_helpers.get_content', + with mock.patch('leap.bitmask.util.request_helpers.get_content', new=mock.create_autospec(get_content)) as \ content: content.return_value = ("{}", 0) @@ -662,11 +663,10 @@ class SRPAuthTestCase(unittest.TestCase): return d @deferred() - def test_logout_fails_if_not_logged_in(self): + def test_logout_does_not_fail_if_not_logged_in(self): def wrapper(*args): - with self.assertRaises(AssertionError): - self.auth_backend.logout() + self.auth_backend.logout() d = threads.deferToThread(wrapper) return d diff --git a/src/leap/crypto/tests/test_srpregister.py b/src/leap/bitmask/crypto/tests/test_srpregister.py index 66b815f2..4d6e7be3 100644 --- a/src/leap/crypto/tests/test_srpregister.py +++ b/src/leap/bitmask/crypto/tests/test_srpregister.py @@ -30,10 +30,10 @@ from nose.twistedtools import reactor, deferred from twisted.python import log from twisted.internet import threads +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto import srpregister, srpauth +from leap.bitmask.crypto.tests import fake_provider from leap.common.testing.https_server import where -from leap.config.providerconfig import ProviderConfig -from leap.crypto import srpregister, srpauth -from leap.crypto.tests import fake_provider log.startLogging(sys.stdout) diff --git a/src/leap/crypto/tests/wrongcert.pem b/src/leap/bitmask/crypto/tests/wrongcert.pem index e6cff38a..e6cff38a 100644 --- a/src/leap/crypto/tests/wrongcert.pem +++ b/src/leap/bitmask/crypto/tests/wrongcert.pem diff --git a/src/leap/gui/__init__.py b/src/leap/bitmask/gui/__init__.py index 4b289442..4b289442 100644 --- a/src/leap/gui/__init__.py +++ b/src/leap/bitmask/gui/__init__.py diff --git a/src/leap/gui/loggerwindow.py b/src/leap/bitmask/gui/loggerwindow.py index fcbdbf19..9b4ba55d 100644 --- a/src/leap/gui/loggerwindow.py +++ b/src/leap/bitmask/gui/loggerwindow.py @@ -21,9 +21,11 @@ History log window import logging from PySide import QtGui + from ui_loggerwindow import Ui_LoggerWindow + +from leap.bitmask.util.leap_log_handler import LeapLogHandler from leap.common.check import leap_assert, leap_assert_type -from leap.util.leap_log_handler import LeapLogHandler logger = logging.getLogger(__name__) @@ -54,6 +56,10 @@ class LoggerWindow(QtGui.QDialog): self.ui.btnWarning.toggled.connect(self._load_history), self.ui.btnError.toggled.connect(self._load_history), self.ui.btnCritical.toggled.connect(self._load_history) + self.ui.leFilterBy.textEdited.connect(self._filter_by) + self.ui.cbCaseInsensitive.stateChanged.connect(self._load_history) + + self._current_filter = "" # Load logging history and connect logger with the widget self._logging_handler = handler @@ -93,7 +99,14 @@ class LoggerWindow(QtGui.QDialog): close_tag = "</td></tr>" message = open_tag + message + close_tag - self.ui.txtLogHistory.append(message) + filter_by = self._current_filter + msg = message + if self.ui.cbCaseInsensitive.isChecked(): + msg = msg.upper() + filter_by = filter_by.upper() + + if msg.find(filter_by) != -1: + self.ui.txtLogHistory.append(message) def _load_history(self): """ @@ -118,6 +131,16 @@ class LoggerWindow(QtGui.QDialog): logging.CRITICAL: self.ui.btnCritical.isChecked() } + def _filter_by(self, text): + """ + Sets the text to use for filtering logs in the log window. + + :param text: the text to compare with the logs when filtering. + :type text: str + """ + self._current_filter = text + self._load_history() + def _save_log_to_file(self): """ Lets the user save the current log to a file diff --git a/src/leap/gui/login.py b/src/leap/bitmask/gui/login.py index de0b2d50..db7b8e2a 100644 --- a/src/leap/gui/login.py +++ b/src/leap/bitmask/gui/login.py @@ -23,7 +23,7 @@ import logging from PySide import QtCore, QtGui from ui_login import Ui_LoginWidget -from leap.util.keyring_helpers import has_keyring +from leap.bitmask.util.keyring_helpers import has_keyring logger = logging.getLogger(__name__) diff --git a/src/leap/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 5ace1043..17275983 100644 --- a/src/leap/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -29,44 +29,48 @@ import keyring from PySide import QtCore, QtGui from twisted.internet import threads -from leap.common.check import leap_assert -from leap.common.events import register -from leap.common.events import events_pb2 as proto -from leap.config.leapsettings import LeapSettings -from leap.config.providerconfig import ProviderConfig -from leap.crypto.srpauth import SRPAuth -from leap.gui.loggerwindow import LoggerWindow -from leap.gui.wizard import Wizard -from leap.gui.login import LoginWidget -from leap.gui.statuspanel import StatusPanelWidget -from leap.services.eip.eipbootstrapper import EIPBootstrapper -from leap.services.eip.eipconfig import EIPConfig -from leap.services.eip.providerbootstrapper import ProviderBootstrapper +from leap.bitmask.config.leapsettings import LeapSettings +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.gui.loggerwindow import LoggerWindow +from leap.bitmask.gui.wizard import Wizard +from leap.bitmask.gui.login import LoginWidget +from leap.bitmask.gui.statuspanel import StatusPanelWidget +from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.bitmask.services.eip.providerbootstrapper import ProviderBootstrapper # XXX: Soledad might not work out of the box in Windows, issue #2932 -from leap.services.soledad.soledadbootstrapper import SoledadBootstrapper -from leap.services.mail.smtpbootstrapper import SMTPBootstrapper -from leap.services.mail import imap -from leap.platform_init import IS_WIN, IS_MAC -from leap.platform_init.initializers import init_platform - -from leap.services.eip.vpnprocess import VPN -from leap.services.eip.vpnprocess import OpenVPNAlreadyRunning -from leap.services.eip.vpnprocess import AlienOpenVPNAlreadyRunning - -from leap.services.eip.vpnlaunchers import VPNLauncherException -from leap.services.eip.vpnlaunchers import OpenVPNNotFoundException -from leap.services.eip.vpnlaunchers import EIPNoPkexecAvailable -from leap.services.eip.vpnlaunchers import EIPNoPolkitAuthAgentAvailable -from leap.services.eip.vpnlaunchers import EIPNoTunKextLoaded - -from leap.util import __version__ as VERSION -from leap.util.keyring_helpers import has_keyring - -from leap.services.mail.smtpconfig import SMTPConfig +from leap.bitmask.services.soledad.soledadbootstrapper import \ + SoledadBootstrapper +from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper +from leap.bitmask.services.mail import imap +from leap.bitmask.platform_init import IS_WIN, IS_MAC +from leap.bitmask.platform_init.initializers import init_platform + +from leap.bitmask.services.eip.vpnprocess import VPN +from leap.bitmask.services.eip.vpnprocess import OpenVPNAlreadyRunning +from leap.bitmask.services.eip.vpnprocess import AlienOpenVPNAlreadyRunning + +from leap.bitmask.services.eip.vpnlaunchers import VPNLauncherException +from leap.bitmask.services.eip.vpnlaunchers import OpenVPNNotFoundException +from leap.bitmask.services.eip.vpnlaunchers import EIPNoPkexecAvailable +from leap.bitmask.services.eip.vpnlaunchers import \ + EIPNoPolkitAuthAgentAvailable +from leap.bitmask.services.eip.vpnlaunchers import EIPNoTunKextLoaded + +from leap.bitmask.util import __version__ as VERSION +from leap.bitmask.util.keyring_helpers import has_keyring +from leap.bitmask.util.leap_log_handler import LeapLogHandler + +from leap.bitmask.services.mail.smtpconfig import SMTPConfig if IS_WIN: - from leap.platform_init.locks import WindowsLock - from leap.platform_init.locks import raise_window_ack + from leap.bitmask.platform_init.locks import WindowsLock + from leap.bitmask.platform_init.locks import raise_window_ack + +from leap.common.check import leap_assert +from leap.common.events import register +from leap.common.events import events_pb2 as proto from ui_mainwindow import Ui_MainWindow @@ -96,6 +100,7 @@ class MainWindow(QtGui.QMainWindow): new_updates = QtCore.Signal(object) raise_window = QtCore.Signal([]) soledad_ready = QtCore.Signal([]) + mail_client_logged_in = QtCore.Signal([]) # We use this flag to detect abnormal terminations user_stopped_eip = False @@ -122,13 +127,17 @@ class MainWindow(QtGui.QMainWindow): """ QtGui.QMainWindow.__init__(self) - # register leap events + # register leap events ######################################## register(signal=proto.UPDATER_NEW_UPDATES, callback=self._new_updates_available, reqcbk=lambda req, resp: None) # make rpc call async register(signal=proto.RAISE_WINDOW, callback=self._on_raise_window_event, reqcbk=lambda req, resp: None) # make rpc call async + register(signal=proto.IMAP_CLIENT_LOGIN, + callback=self._on_mail_client_logged_in, + reqcbk=lambda req, resp: None) # make rpc call async + # end register leap events #################################### self._quit_callback = quit_callback @@ -144,7 +153,7 @@ class MainWindow(QtGui.QMainWindow): self.ui.stackedWidget.widget(self.LOGIN_INDEX)) self.ui.loginLayout.addWidget(self._login_widget) - # Signals + # Qt Signal Connections ##################################### # TODO separate logic from ui signals. self._login_widget.login.connect(self._login) @@ -165,8 +174,6 @@ class MainWindow(QtGui.QMainWindow): # This is loaded only once, there's a bug when doing that more # than once - ProviderConfig.standalone = standalone - EIPConfig.standalone = standalone self._standalone = standalone self._provider_config = ProviderConfig() # Used for automatic start of EIP @@ -202,6 +209,8 @@ class MainWindow(QtGui.QMainWindow): # This thread is similar to the provider bootstrapper self._eip_bootstrapper = EIPBootstrapper() + # TODO change the name of "download_config" signal to + # something less confusing (config_ready maybe) self._eip_bootstrapper.download_config.connect( self._eip_intermediate_stage) self._eip_bootstrapper.download_client_certificate.connect( @@ -212,6 +221,8 @@ class MainWindow(QtGui.QMainWindow): self._soledad_intermediate_stage) self._soledad_bootstrapper.gen_key.connect( self._soledad_bootstrapped_stage) + self._soledad_bootstrapper.soledad_timeout.connect( + self._retry_soledad_connection) self._smtp_bootstrapper = SMTPBootstrapper() self._smtp_bootstrapper.download_config.connect( @@ -268,8 +279,12 @@ class MainWindow(QtGui.QMainWindow): self.ui.btnMore.setVisible(False) self.ui.btnMore.clicked.connect(self._updates_details) + # Services signals/slots connection self.new_updates.connect(self._react_to_new_updates) self.soledad_ready.connect(self._start_imap_service) + self.mail_client_logged_in.connect(self._fetch_incoming_mail) + + ################################# end Qt Signals connection ######## init_platform() @@ -356,7 +371,6 @@ class MainWindow(QtGui.QMainWindow): :return: a logging handler or None :rtype: LeapLogHandler or None """ - from leap.util.leap_log_handler import LeapLogHandler leap_logger = logging.getLogger('leap') for h in leap_logger.handlers: if isinstance(h, LeapLogHandler): @@ -377,6 +391,7 @@ class MainWindow(QtGui.QMainWindow): leap_log_handler = self._get_leap_logging_handler() if leap_log_handler is None: logger.error('Leap logger handler not found') + return else: self._logger_window = LoggerWindow(handler=leap_log_handler) self._logger_window.setVisible( @@ -610,7 +625,7 @@ class MainWindow(QtGui.QMainWindow): self.tr("Hide Main Window"))[int(visible)] # set labels - visible = self.isVisible() + visible = self.isVisible() and self.isActiveWindow() self._action_visible.setText(get_action(visible)) def _toggle_visible(self): @@ -620,8 +635,10 @@ class MainWindow(QtGui.QMainWindow): Toggles the window visibility """ - if not self.isVisible(): + visible = self.isVisible() and self.isActiveWindow() + if not visible: self.show() + self.activateWindow() self.raise_() else: self.hide() @@ -947,8 +964,22 @@ class MainWindow(QtGui.QMainWindow): # TODO: display in the GUI: # should pass signal to a slot in status_panel # that sets the global status - logger.warning("Soledad failed to start: %s" % - (data[self._soledad_bootstrapper.ERROR_KEY],)) + logger.error("Soledad failed to start: %s" % + (data[self._soledad_bootstrapper.ERROR_KEY],)) + self._retry_soledad_connection() + + def _retry_soledad_connection(self): + """ + Retries soledad connection. + """ + logger.debug("Retrying soledad connection.") + if self._soledad_bootstrapper.should_retry_initialization(): + self._soledad_bootstrapper.increment_retries_count() + threads.deferToThread( + self._soledad_bootstrapper.load_and_sync_soledad) + else: + logger.warning("Max number of soledad initialization " + "retries reached.") def _soledad_bootstrapped_stage(self, data): """ @@ -965,13 +996,14 @@ class MainWindow(QtGui.QMainWindow): """ passed = data[self._soledad_bootstrapper.PASSED_KEY] if not passed: + logger.debug("ERROR on soledad bootstrapping:") logger.error(data[self._soledad_bootstrapper.ERROR_KEY]) return + else: + logger.debug("Done bootstrapping Soledad") - logger.debug("Done bootstrapping Soledad") - - self._soledad = self._soledad_bootstrapper.soledad - self._keymanager = self._soledad_bootstrapper.keymanager + self._soledad = self._soledad_bootstrapper.soledad + self._keymanager = self._soledad_bootstrapper.keymanager # Ok, now soledad is ready, so we can allow other things that # depend on soledad to start. @@ -1000,6 +1032,7 @@ class MainWindow(QtGui.QMainWindow): #self._status_panel.set_eip_status( # self.tr("MX is disabled")) + ################################################################### # Service control methods: smtp def _smtp_bootstrapped_stage(self, data): @@ -1042,17 +1075,55 @@ class MainWindow(QtGui.QMainWindow): smtp_key=client_cert, encrypted_only=False) + ################################################################### + # Service control methods: imap + def _start_imap_service(self): """ SLOT TRIGGERS: soledad_ready """ - logger.debug('Starting imap service') + if self._provider_config.provides_mx() and \ + self._enabled_services.count(self.MX_SERVICE) > 0: + logger.debug('Starting imap service') - self._imap_service = imap.start_imap_service( - self._soledad, - self._keymanager) + self._imap_service = imap.start_imap_service( + self._soledad, + self._keymanager) + else: + if self._enabled_services.count(self.MX_SERVICE) > 0: + pass # TODO: show MX status + #self._status_panel.set_eip_status( + # self.tr("%s does not support MX") % + # (self._provider_config.get_domain(),), + # error=True) + else: + pass # TODO: show MX status + #self._status_panel.set_eip_status( + # self.tr("MX is disabled")) + + def _on_mail_client_logged_in(self, req): + """ + Triggers qt signal when client login event is received. + """ + self.mail_client_logged_in.emit() + + def _fetch_incoming_mail(self): + """ + SLOT + TRIGGERS: + mail_client_logged_in + """ + # TODO have a mutex over fetch operation. + if self._imap_service: + logger.debug('Client connected, fetching mail...') + self._imap_service.fetch() + + # end service control methods (imap) + + ################################################################### + # Service control methods: eip def _get_socket_host(self): """ @@ -1060,13 +1131,13 @@ class MainWindow(QtGui.QMainWindow): :rtype: tuple (str, str) (host, port) """ - # TODO: make this properly multiplatform if platform.system() == "Windows": host = "localhost" port = "9876" else: + # XXX cleanup this on exit too host = os.path.join(tempfile.mkdtemp(prefix="leap-tmp"), 'openvpn.socket') port = "unix" @@ -1307,6 +1378,9 @@ class MainWindow(QtGui.QMainWindow): Starts the logout sequence """ + + self._soledad_bootstrapper.cancel_bootstrap() + # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! threads.deferToThread(self._srp_auth.logout) diff --git a/src/leap/gui/statuspanel.py b/src/leap/bitmask/gui/statuspanel.py index f3424c7c..9352eb04 100644 --- a/src/leap/gui/statuspanel.py +++ b/src/leap/bitmask/gui/statuspanel.py @@ -22,14 +22,17 @@ import logging from datetime import datetime from functools import partial + from PySide import QtCore, QtGui -from ui_statuspanel import Ui_StatusPanel +from leap.bitmask.services.eip.vpnprocess import VPNManager +from leap.bitmask.platform_init import IS_WIN, IS_LINUX +from leap.bitmask.util import first +from leap.common.check import leap_assert, leap_assert_type +from leap.common.events import register +from leap.common.events import events_pb2 as proto -from leap.common.check import leap_assert_type -from leap.services.eip.vpnprocess import VPNManager -from leap.platform_init import IS_WIN, IS_LINUX -from leap.util import first +from ui_statuspanel import Ui_StatusPanel logger = logging.getLogger(__name__) @@ -115,6 +118,14 @@ class StatusPanelWidget(QtGui.QWidget): RATE_STR = "%14.2f KB/s" TOTAL_STR = "%14.2f Kb" + MAIL_OFF_ICON = ":/images/mail-unlocked.png" + MAIL_ON_ICON = ":/images/mail-locked.png" + + _soledad_event = QtCore.Signal(object) + _smtp_event = QtCore.Signal(object) + _imap_event = QtCore.Signal(object) + _keymanager_event = QtCore.Signal(object) + def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) @@ -142,6 +153,73 @@ class StatusPanelWidget(QtGui.QWidget): self._set_traffic_rates() self._make_status_clickable() + register(signal=proto.KEYMANAGER_LOOKING_FOR_KEY, + callback=self._mail_handle_keymanager_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.KEYMANAGER_KEY_FOUND, + callback=self._mail_handle_keymanager_events, + reqcbk=lambda req, resp: None) + + # register(signal=proto.KEYMANAGER_KEY_NOT_FOUND, + # callback=self._mail_handle_keymanager_events, + # reqcbk=lambda req, resp: None) + + register(signal=proto.KEYMANAGER_STARTED_KEY_GENERATION, + callback=self._mail_handle_keymanager_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.KEYMANAGER_FINISHED_KEY_GENERATION, + callback=self._mail_handle_keymanager_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.KEYMANAGER_DONE_UPLOADING_KEYS, + callback=self._mail_handle_keymanager_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.SOLEDAD_DONE_DOWNLOADING_KEYS, + callback=self._mail_handle_soledad_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.SOLEDAD_DONE_UPLOADING_KEYS, + callback=self._mail_handle_soledad_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.SMTP_SERVICE_STARTED, + callback=self._mail_handle_smtp_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.SMTP_SERVICE_FAILED_TO_START, + callback=self._mail_handle_smtp_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.IMAP_SERVICE_STARTED, + callback=self._mail_handle_imap_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.IMAP_SERVICE_FAILED_TO_START, + callback=self._mail_handle_imap_events, + reqcbk=lambda req, resp: None) + + register(signal=proto.IMAP_UNREAD_MAIL, + callback=self._mail_handle_imap_events, + reqcbk=lambda req, resp: None) + + self._set_long_mail_status("") + self.ui.lblUnread.setVisible(False) + + self._smtp_started = False + self._imap_started = False + + self._soledad_event.connect( + self._mail_handle_soledad_events_slot) + self._imap_event.connect( + self._mail_handle_imap_events_slot) + self._smtp_event.connect( + self._mail_handle_smtp_events_slot) + self._keymanager_event.connect( + self._mail_handle_keymanager_events_slot) + def _make_status_clickable(self): """ Makes upload and download figures clickable. @@ -420,6 +498,8 @@ class StatusPanelWidget(QtGui.QWidget): self.set_eip_status(self.tr("Waiting to start...")) elif status == "ASSIGN_IP": self.set_eip_status(self.tr("Assigning IP")) + elif status == "RECONNECTING": + self.set_eip_status(self.tr("Reconnecting...")) elif status == "ALREADYRUNNING": # Put the following calls in Qt's event queue, otherwise # the UI won't update properly @@ -457,3 +537,169 @@ class StatusPanelWidget(QtGui.QWidget): def set_provider(self, provider): self.ui.lblProvider.setText(provider) + + def _mail_handle_soledad_events(self, req): + """ + Callback for ... + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self._soledad_event.emit(req) + + def _mail_handle_soledad_events_slot(self, req): + """ + SLOT + TRIGGER: _mail_handle_soledad_events + + Reacts to an Soledad event + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self.ui.lblMailStatus.setText(self.tr("Starting...")) + + ext_status = "" + + if req.event == proto.SOLEDAD_DONE_UPLOADING_KEYS: + ext_status = self.tr("Soledad has started...") + elif req.event == proto.SOLEDAD_DONE_DOWNLOADING_KEYS: + ext_status = self.tr("Soledad is starting, please wait...") + else: + leap_assert(False, + "Don't know how to handle this state: %s" + % (req.event)) + + self._set_long_mail_status(ext_status) + + def _mail_handle_keymanager_events(self, req): + """ + Callback for the KeyManager events + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self._keymanager_event.emit(req) + + def _mail_handle_keymanager_events_slot(self, req): + """ + SLOT + TRIGGER: _mail_handle_keymanager_events + + Reacts to an KeyManager event + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self.ui.lblMailStatus.setText(self.tr("Starting...")) + + ext_status = "" + + if req.event == proto.KEYMANAGER_LOOKING_FOR_KEY: + ext_status = self.tr("Looking for key for this user") + elif req.event == proto.KEYMANAGER_KEY_FOUND: + ext_status = self.tr("Found key! Starting mail...") + # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND: + # ext_status = self.tr("Key not found!") + elif req.event == proto.KEYMANAGER_STARTED_KEY_GENERATION: + ext_status = self.tr("Generating new key, please wait...") + elif req.event == proto.KEYMANAGER_FINISHED_KEY_GENERATION: + ext_status = self.tr("Finished generating key!") + elif req.event == proto.KEYMANAGER_DONE_UPLOADING_KEYS: + ext_status = self.tr("Starting mail...") + else: + leap_assert(False, + "Don't know how to handle this state: %s" + % (req.event)) + + self._set_long_mail_status(ext_status) + + def _mail_handle_smtp_events(self, req): + """ + Callback for the SMTP events + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self._smtp_event.emit(req) + + def _mail_handle_smtp_events_slot(self, req): + """ + SLOT + TRIGGER: _mail_handle_smtp_events + + Reacts to an SMTP event + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + ext_status = "" + + if req.event == proto.SMTP_SERVICE_STARTED: + ext_status = self.tr("SMTP has started...") + self._smtp_started = True + if self._smtp_started and self._imap_started: + self.ui.lblMailStatus.setText(self.tr("ON")) + self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) + self.ui.lblMailIcon.setPixmap( + QtGui.QPixmap(":/images/mail-locked.png")) + ext_status = "" + elif req.event == proto.SMTP_SERVICE_FAILED_TO_START: + ext_status = self.tr("SMTP failed to start, check the logs.") + self.ui.lblMailStatus.setText(self.tr("Failed")) + else: + leap_assert(False, + "Don't know how to handle this state: %s" + % (req.event)) + + self._set_long_mail_status(ext_status) + + def _mail_handle_imap_events(self, req): + """ + Callback for the IMAP events + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + self._imap_event.emit(req) + + def _mail_handle_imap_events_slot(self, req): + """ + SLOT + TRIGGER: _mail_handle_imap_events + + Reacts to an IMAP event + + :param req: Request type + :type req: leap.common.events.events_pb2.SignalRequest + """ + ext_status = None + + if req.event == proto.IMAP_SERVICE_STARTED: + ext_status = self.tr("IMAP has started...") + self._imap_started = True + if self._smtp_started and self._imap_started: + self.ui.lblMailStatus.setText(self.tr("ON")) + self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) + ext_status = "" + elif req.event == proto.IMAP_SERVICE_FAILED_TO_START: + ext_status = self.tr("IMAP failed to start, check the logs.") + self.ui.lblMailStatus.setText(self.tr("Failed")) + elif req.event == proto.IMAP_UNREAD_MAIL: + if self._smtp_started and self._imap_started: + self.ui.lblUnread.setText( + self.tr("%s Unread Emails") % (req.content)) + self.ui.lblUnread.setVisible(req.content != "0") + self.ui.lblMailStatus.setText(self.tr("ON")) + self.ui.lblMailIcon.setPixmap(QtGui.QPixmap(self.MAIL_ON_ICON)) + else: + leap_assert(False, + "Don't know how to handle this state: %s" + % (req.event)) + + if ext_status is not None: + self._set_long_mail_status(ext_status) + + def _set_long_mail_status(self, ext_status): + self.ui.lblLongMailStatus.setText(ext_status) + self.ui.grpMailStatus.setVisible(len(ext_status) > 0) diff --git a/src/leap/gui/twisted_main.py b/src/leap/bitmask/gui/twisted_main.py index c7add3ee..e11af7bd 100644 --- a/src/leap/gui/twisted_main.py +++ b/src/leap/bitmask/gui/twisted_main.py @@ -53,8 +53,8 @@ def quit(app): :type app: QtCore.QApplication """ from twisted.internet import reactor - logger.debug('stopping twisted reactor') + logger.debug('Stopping twisted reactor') try: - reactor.stop() + reactor.callLater(0, reactor.stop) except error.ReactorNotRunning: - logger.debug('reactor not running') + logger.debug('Reactor not running') diff --git a/src/leap/gui/ui/loggerwindow.ui b/src/leap/bitmask/gui/ui/loggerwindow.ui index b08428a9..3de786f7 100644 --- a/src/leap/gui/ui/loggerwindow.ui +++ b/src/leap/bitmask/gui/ui/loggerwindow.ui @@ -14,14 +14,34 @@ <string>Logs</string> </property> <property name="windowIcon"> - <iconset resource="../../../../data/resources/mainwindow.qrc"> + <iconset resource="../../../../../data/resources/mainwindow.qrc"> <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0" colspan="2"> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filter by:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="leFilterBy"/> + </item> + <item row="2" column="2"> + <widget class="QCheckBox" name="cbCaseInsensitive"> + <property name="text"> + <string>Case Insensitive</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0" colspan="3"> <widget class="QTextBrowser" name="txtLogHistory"/> </item> - <item row="0" column="0" colspan="2"> + <item row="0" column="0" colspan="3"> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QPushButton" name="btnDebug"> @@ -29,7 +49,7 @@ <string>Debug</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/script-error.png</normaloff>:/images/oxygen-icons/script-error.png</iconset> </property> <property name="checkable"> @@ -49,7 +69,7 @@ <string>Info</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/dialog-information.png</normaloff>:/images/oxygen-icons/dialog-information.png</iconset> </property> <property name="checkable"> @@ -69,7 +89,7 @@ <string>Warning</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/dialog-warning.png</normaloff>:/images/oxygen-icons/dialog-warning.png</iconset> </property> <property name="checkable"> @@ -89,7 +109,7 @@ <string>Error</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/dialog-error.png</normaloff>:/images/oxygen-icons/dialog-error.png</iconset> </property> <property name="checkable"> @@ -109,7 +129,7 @@ <string>Critical</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/edit-bomb.png</normaloff>:/images/oxygen-icons/edit-bomb.png</iconset> </property> <property name="checkable"> @@ -129,7 +149,7 @@ <string>Save to file</string> </property> <property name="icon"> - <iconset resource="../../../../data/resources/loggerwindow.qrc"> + <iconset resource="../../../../../data/resources/loggerwindow.qrc"> <normaloff>:/images/oxygen-icons/document-save-as.png</normaloff>:/images/oxygen-icons/document-save-as.png</iconset> </property> </widget> @@ -148,8 +168,8 @@ <tabstop>txtLogHistory</tabstop> </tabstops> <resources> - <include location="../../../../data/resources/loggerwindow.qrc"/> - <include location="../../../../data/resources/mainwindow.qrc"/> + <include location="../../../../../data/resources/loggerwindow.qrc"/> + <include location="../../../../../data/resources/mainwindow.qrc"/> </resources> <connections/> </ui> diff --git a/src/leap/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui index 42a6897a..42a6897a 100644 --- a/src/leap/gui/ui/login.ui +++ b/src/leap/bitmask/gui/ui/login.ui diff --git a/src/leap/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index ecd3cbe9..9c4e6ff0 100644 --- a/src/leap/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -14,7 +14,7 @@ <string>Bitmask</string> </property> <property name="windowIcon"> - <iconset resource="../../../../data/resources/mainwindow.qrc"> + <iconset resource="../../../../../data/resources/mainwindow.qrc"> <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset> </property> <property name="inputMethodHints"> @@ -166,7 +166,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/mask-launcher.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/mask-launcher.png</pixmap> </property> <property name="alignment"> <set>Qt::AlignCenter</set> @@ -308,8 +308,9 @@ </action> </widget> <resources> + <include location="../../../../../data/resources/mainwindow.qrc"/> + <include location="../../../../../data/resources/locale.qrc"/> <include location="../../../../data/resources/mainwindow.qrc"/> - <include location="../../../../data/resources/locale.qrc"/> </resources> <connections/> </ui> diff --git a/src/leap/gui/ui/statuspanel.ui b/src/leap/bitmask/gui/ui/statuspanel.ui index 3482ac7c..d77af1da 100644 --- a/src/leap/gui/ui/statuspanel.ui +++ b/src/leap/bitmask/gui/ui/statuspanel.ui @@ -6,7 +6,7 @@ <rect> <x>0</x> <y>0</y> - <width>384</width> + <width>470</width> <height>477</height> </rect> </property> @@ -36,36 +36,40 @@ <string notr="true"/> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="eip_controls"> - <item> - <widget class="QLabel" name="label"> + <item row="5" column="1"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="1" column="0" colspan="3"> + <widget class="QLabel" name="lblUnread"> <property name="text"> - <string>Encrypted Internet: </string> + <string>0 Unread Emails</string> </property> </widget> </item> - <item> - <widget class="QLabel" name="lblEIPStatus"> + <item row="0" column="1"> + <widget class="QLabel" name="lblMailStatus"> <property name="styleSheet"> <string notr="true">font: bold;</string> </property> <property name="text"> - <string>Off</string> - </property> - <property name="textFormat"> - <enum>Qt::AutoText</enum> + <string>Disabled</string> </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="wordWrap"> - <bool>false</bool> + <property name="text"> + <string>Encrypted Mail:</string> </property> </widget> </item> - <item> - <spacer name="horizontalSpacer"> + <item row="0" column="2"> + <spacer name="horizontalSpacer_4"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -77,50 +81,21 @@ </property> </spacer> </item> - <item> - <widget class="QPushButton" name="btnEipStartStop"> - <property name="text"> - <string>Turn On</string> + <item row="2" column="0" colspan="3"> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> </property> - </widget> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>1</height> + </size> + </property> + </spacer> </item> </layout> </item> - <item row="2" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Preferred</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>11</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0" rowspan="2"> - <widget class="QLabel" name="lblVPNStatusIcon"> - <property name="maximumSize"> - <size> - <width>64</width> - <height>64</height> - </size> - </property> - <property name="text"> - <string/> - </property> - <property name="pixmap"> - <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> <item row="1" column="1"> <layout class="QHBoxLayout" name="eip_bandwidth"> <property name="spacing"> @@ -135,7 +110,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/16/down-arrow.png</pixmap> + <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/16/down-arrow.png</pixmap> </property> </widget> </item> @@ -192,7 +167,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/icons.qrc">:/images/light/16/up-arrow.png</pixmap> + <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/16/up-arrow.png</pixmap> </property> </widget> </item> @@ -242,6 +217,85 @@ </item> </layout> </item> + <item row="2" column="0"> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Preferred</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>11</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="0" rowspan="2"> + <widget class="QLabel" name="lblVPNStatusIcon"> + <property name="maximumSize"> + <size> + <width>64</width> + <height>64</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../../../../../data/resources/icons.qrc">:/images/light/64/network-eip-down.png</pixmap> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="4" column="0" rowspan="2"> + <widget class="QLabel" name="lblMailIcon"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>64</width> + <height>64</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>64</width> + <height>999</height> + </size> + </property> + <property name="text"> + <string/> + </property> + <property name="pixmap"> + <pixmap resource="../../../../../data/resources/icons.qrc">:/images/mail-unlocked.png</pixmap> + </property> + </widget> + </item> + <item row="7" column="0" colspan="2"> + <widget class="QGroupBox" name="grpMailStatus"> + <property name="title"> + <string/> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="lblLongMailStatus"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> <item row="3" column="0" colspan="2"> <widget class="QGroupBox" name="globalStatusBox"> <property name="enabled"> @@ -264,6 +318,56 @@ </layout> </widget> </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="eip_controls"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Encrypted Internet: </string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblEIPStatus"> + <property name="styleSheet"> + <string notr="true">font: bold;</string> + </property> + <property name="text"> + <string>Off</string> + </property> + <property name="textFormat"> + <enum>Qt::AutoText</enum> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="btnEipStartStop"> + <property name="text"> + <string>Turn On</string> + </property> + </widget> + </item> + </layout> + </item> </layout> </widget> </item> @@ -283,7 +387,7 @@ </layout> </widget> <resources> - <include location="../../../../data/resources/icons.qrc"/> + <include location="../../../../../data/resources/icons.qrc"/> </resources> <connections/> </ui> diff --git a/src/leap/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui index a8f66bbc..3b8f1215 100644 --- a/src/leap/gui/ui/wizard.ui +++ b/src/leap/bitmask/gui/ui/wizard.ui @@ -7,14 +7,26 @@ <x>0</x> <y>0</y> <width>536</width> - <height>452</height> + <height>490</height> </rect> </property> + <property name="minimumSize"> + <size> + <width>536</width> + <height>490</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>536</width> + <height>490</height> + </size> + </property> <property name="windowTitle"> <string>Bitmask first run</string> </property> <property name="windowIcon"> - <iconset resource="../../../../data/resources/mainwindow.qrc"> + <iconset resource="../../../../../data/resources/mainwindow.qrc"> <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset> </property> <property name="modal"> @@ -193,7 +205,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -215,7 +227,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -237,7 +249,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -486,7 +498,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -508,7 +520,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -551,7 +563,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Emblem-question.png</pixmap> </property> </widget> </item> @@ -771,7 +783,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/leap-color-big.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/mask-icon.png</pixmap> </property> </widget> </item> @@ -787,7 +799,7 @@ <string/> </property> <property name="pixmap"> - <pixmap resource="../../../../data/resources/mainwindow.qrc">:/images/Globe.png</pixmap> + <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/Globe.png</pixmap> </property> </widget> </item> @@ -839,8 +851,8 @@ <tabstop>btnCheck</tabstop> </tabstops> <resources> - <include location="../../../../data/resources/mainwindow.qrc"/> - <include location="../../../../data/resources/locale.qrc"/> + <include location="../../../../../data/resources/mainwindow.qrc"/> + <include location="../../../../../data/resources/locale.qrc"/> </resources> <connections/> </ui> diff --git a/src/leap/gui/wizard.py b/src/leap/bitmask/gui/wizard.py index 2b48fc81..ed6c1da0 100644 --- a/src/leap/gui/wizard.py +++ b/src/leap/bitmask/gui/wizard.py @@ -22,18 +22,20 @@ import os import logging import json -from PySide import QtCore, QtGui from functools import partial + +from PySide import QtCore, QtGui from twisted.internet import threads +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.srpregister import SRPRegister +from leap.bitmask.util.privilege_policies import is_missing_policy_permissions +from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.util.keyring_helpers import has_keyring +from leap.bitmask.services.eip.providerbootstrapper import ProviderBootstrapper +from leap.bitmask.services import get_supported + from ui_wizard import Ui_Wizard -from leap.config.providerconfig import ProviderConfig -from leap.crypto.srpregister import SRPRegister -from leap.util.privilege_policies import is_missing_policy_permissions -from leap.util.request_helpers import get_content -from leap.util.keyring_helpers import has_keyring -from leap.services.eip.providerbootstrapper import ProviderBootstrapper -from leap.services import get_supported logger = logging.getLogger(__name__) @@ -75,7 +77,7 @@ class Wizard(QtGui.QWizard): self.ui.setupUi(self) self.setPixmap(QtGui.QWizard.LogoPixmap, - QtGui.QPixmap(":/images/leap-color-small.png")) + QtGui.QPixmap(":/images/mask-icon.png")) self.QUESTION_ICON = QtGui.QPixmap(":/images/Emblem-question.png") self.ERROR_ICON = QtGui.QPixmap(":/images/Dialog-error.png") diff --git a/src/leap/gui/wizardpage.py b/src/leap/bitmask/gui/wizardpage.py index b2a00028..b2a00028 100644 --- a/src/leap/gui/wizardpage.py +++ b/src/leap/bitmask/gui/wizardpage.py diff --git a/src/leap/platform_init/__init__.py b/src/leap/bitmask/platform_init/__init__.py index 2a262a30..2a262a30 100644 --- a/src/leap/platform_init/__init__.py +++ b/src/leap/bitmask/platform_init/__init__.py diff --git a/src/leap/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py index 46488250..831c6a1c 100644 --- a/src/leap/platform_init/initializers.py +++ b/src/leap/bitmask/platform_init/initializers.py @@ -28,10 +28,10 @@ import tempfile from PySide import QtGui -from leap.config.leapsettings import LeapSettings -from leap.services.eip import vpnlaunchers -from leap.util import first -from leap.util import privilege_policies +from leap.bitmask.config.leapsettings import LeapSettings +from leap.bitmask.services.eip import vpnlaunchers +from leap.bitmask.util import first +from leap.bitmask.util import privilege_policies logger = logging.getLogger(__name__) @@ -223,8 +223,8 @@ def _darwin_has_tun_kext(): """ # XXX we should be smarter here and use kextstats output. - has_kext = os.path.isdir("/System/Library/Extensions/tun.kext") - has_startup = os.path.isdir("/System/Library/StartupItems/tun") + has_kext = os.path.isdir("/Library/Extensions/tun.kext") + has_startup = os.path.isdir("/Library/StartupItems/tun") has_tun_and_startup = has_kext and has_startup logger.debug( 'platform initializer check: has tun_and_startup = %s' % diff --git a/src/leap/platform_init/locks.py b/src/leap/bitmask/platform_init/locks.py index 39b18648..ecfe3b1f 100644 --- a/src/leap/platform_init/locks.py +++ b/src/leap/bitmask/platform_init/locks.py @@ -22,9 +22,9 @@ import errno import os import platform +from leap.bitmask import platform_init from leap.common.events import signal as signal_event from leap.common.events import events_pb2 as proto -from leap import platform_init if platform_init.IS_UNIX: from fcntl import flock, LOCK_EX, LOCK_NB @@ -36,7 +36,7 @@ else: # WINDOWS from tempfile import gettempdir - from leap.util import get_modification_ts, update_modification_ts + from leap.bitmask.util import get_modification_ts, update_modification_ts logger = logging.getLogger(__name__) diff --git a/src/leap/services/eip/__init__.py b/src/leap/bitmask/provider/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/services/eip/__init__.py +++ b/src/leap/bitmask/provider/__init__.py diff --git a/src/leap/provider/supportedapis.py b/src/leap/bitmask/provider/supportedapis.py index 3e650ba2..3e650ba2 100644 --- a/src/leap/provider/supportedapis.py +++ b/src/leap/bitmask/provider/supportedapis.py diff --git a/src/leap/services/__init__.py b/src/leap/bitmask/services/__init__.py index 253359cd..253359cd 100644 --- a/src/leap/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py diff --git a/src/leap/services/abstractbootstrapper.py b/src/leap/bitmask/services/abstractbootstrapper.py index 9e50948c..6d4d319b 100644 --- a/src/leap/services/abstractbootstrapper.py +++ b/src/leap/bitmask/services/abstractbootstrapper.py @@ -26,6 +26,7 @@ from functools import partial from PySide import QtCore from twisted.internet import threads + from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -127,7 +128,6 @@ class AbstractBootstrapper(QtCore.QObject): :type signal: QtCore.SignalInstance """ if signal: - logger.debug("Emitting %s" % (signal,)) signal.emit({self.PASSED_KEY: True, self.ERROR_KEY: ""}) def _callback_threader(self, cb, res, *args, **kwargs): diff --git a/src/leap/services/eip/tests/__init__.py b/src/leap/bitmask/services/eip/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/services/eip/tests/__init__.py +++ b/src/leap/bitmask/services/eip/__init__.py diff --git a/src/leap/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index 1d7bc342..6393e53a 100644 --- a/src/leap/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -24,15 +24,15 @@ import os from PySide import QtCore -from leap.common.check import leap_assert, leap_assert_type +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.util.constants import REQUEST_TIMEOUT +from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.common import certs +from leap.common.check import leap_assert, leap_assert_type 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.request_helpers import get_content -from leap.util.constants import REQUEST_TIMEOUT -from leap.services.abstractbootstrapper import AbstractBootstrapper logger = logging.getLogger(__name__) diff --git a/src/leap/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index d69e1fd8..843e7397 100644 --- a/src/leap/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -25,10 +25,10 @@ import time import ipaddr +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.services.eip.eipspec import get_schema from leap.common.check import leap_assert, leap_assert_type from leap.common.config.baseconfig import BaseConfig -from leap.config.providerconfig import ProviderConfig -from leap.services.eip.eipspec import get_schema logger = logging.getLogger(__name__) diff --git a/src/leap/services/eip/eipspec.py b/src/leap/bitmask/services/eip/eipspec.py index 9cc56be3..9cc56be3 100644 --- a/src/leap/services/eip/eipspec.py +++ b/src/leap/bitmask/services/eip/eipspec.py diff --git a/src/leap/services/eip/providerbootstrapper.py b/src/leap/bitmask/services/eip/providerbootstrapper.py index bf5938dc..ac3a44db 100644 --- a/src/leap/services/eip/providerbootstrapper.py +++ b/src/leap/bitmask/services/eip/providerbootstrapper.py @@ -26,14 +26,14 @@ 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.util.constants import REQUEST_TIMEOUT +from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper +from leap.bitmask.provider.supportedapis import SupportedAPIs 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.config.providerconfig import ProviderConfig, MissingCACert -from leap.util.request_helpers import get_content -from leap.util.constants import REQUEST_TIMEOUT -from leap.services.abstractbootstrapper import AbstractBootstrapper -from leap.provider.supportedapis import SupportedAPIs logger = logging.getLogger(__name__) diff --git a/src/leap/services/mail/__init__.py b/src/leap/bitmask/services/eip/tests/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/services/mail/__init__.py +++ b/src/leap/bitmask/services/eip/tests/__init__.py diff --git a/src/leap/services/eip/tests/test_eipbootstrapper.py b/src/leap/bitmask/services/eip/tests/test_eipbootstrapper.py index f2331eca..d0d78eed 100644 --- a/src/leap/services/eip/tests/test_eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/tests/test_eipbootstrapper.py @@ -36,13 +36,13 @@ from nose.twistedtools import deferred, reactor from twisted.internet import threads from requests.models import Response +from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.tests import fake_provider +from leap.bitmask.crypto.srpauth import SRPAuth from leap.common.testing.basetest import BaseLeapTest -from leap.services.eip.eipbootstrapper import EIPBootstrapper -from leap.services.eip.eipconfig import EIPConfig -from leap.config.providerconfig import ProviderConfig -from leap.crypto.tests import fake_provider from leap.common.files import mkdir_p -from leap.crypto.srpauth import SRPAuth class EIPBootstrapperActiveTest(BaseLeapTest): diff --git a/src/leap/services/eip/tests/test_eipconfig.py b/src/leap/bitmask/services/eip/tests/test_eipconfig.py index 87ce04c2..76305e83 100644 --- a/src/leap/services/eip/tests/test_eipconfig.py +++ b/src/leap/bitmask/services/eip/tests/test_eipconfig.py @@ -22,16 +22,15 @@ import json import os import unittest +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.bitmask.config.providerconfig import ProviderConfig from leap.common.testing.basetest import BaseLeapTest -from leap.services.eip.eipconfig import EIPConfig -from leap.config.providerconfig import ProviderConfig from mock import Mock sample_config = { - "gateways": [ - { + "gateways": [{ "capabilities": { "adblock": False, "filter_dns": True, diff --git a/src/leap/services/eip/tests/test_providerbootstrapper.py b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py index b24334a2..b0685676 100644 --- a/src/leap/services/eip/tests/test_providerbootstrapper.py +++ b/src/leap/bitmask/services/eip/tests/test_providerbootstrapper.py @@ -39,15 +39,16 @@ from nose.twistedtools import deferred, reactor from twisted.internet import threads from requests.models import Response +from leap.bitmask.services.eip.providerbootstrapper import ProviderBootstrapper +from leap.bitmask.services.eip.providerbootstrapper import \ + UnsupportedProviderAPI +from leap.bitmask.services.eip.providerbootstrapper import WrongFingerprint +from leap.bitmask.provider.supportedapis import SupportedAPIs +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.tests import fake_provider +from leap.common.files import mkdir_p from leap.common.testing.https_server import where from leap.common.testing.basetest import BaseLeapTest -from leap.services.eip.providerbootstrapper import ProviderBootstrapper -from leap.services.eip.providerbootstrapper import UnsupportedProviderAPI -from leap.services.eip.providerbootstrapper import WrongFingerprint -from leap.provider.supportedapis import SupportedAPIs -from leap.config.providerconfig import ProviderConfig -from leap.crypto.tests import fake_provider -from leap.common.files import mkdir_p class ProviderBootstrapperTest(BaseLeapTest): @@ -63,7 +64,10 @@ class ProviderBootstrapperTest(BaseLeapTest): self.pb._check_name_resolution() # Something highly likely to fail self.pb._domain = "uquhqweuihowquie.abc.def" - with self.assertRaises(socket.gaierror): + + # In python 2.7.4 raises socket.error + # In python 2.7.5 raises socket.gaierror + with self.assertRaises((socket.gaierror, socket.error)): self.pb._check_name_resolution() @deferred() @@ -420,8 +424,9 @@ class ProviderBootstrapperActiveTest(unittest.TestCase): self.pb._download_provider_info() self.assertTrue(ProviderConfig.save.called) - @mock.patch('leap.config.providerconfig.ProviderConfig.get_ca_cert_path', - lambda x: where('cacert.pem')) + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', + lambda x: where('cacert.pem')) def test_download_provider_info_not_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) @@ -438,8 +443,28 @@ class ProviderBootstrapperActiveTest(unittest.TestCase): # config, because it's new enough self.assertFalse(ProviderConfig.save.called) - @mock.patch('leap.config.providerconfig.ProviderConfig.get_ca_cert_path', - lambda x: where('cacert.pem')) + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_domain', + lambda x: where('testdomain.com')) + def test_download_provider_info_not_modified_and_no_cacert(self): + self._setup_provider_config_with("1", tempfile.mkdtemp()) + self._setup_providerbootstrapper(True) + provider_path = self._produce_dummy_provider_json() + + # set mtime to something really new + os.utime(provider_path, (-1, time.time())) + + with mock.patch.object( + ProviderConfig, 'get_api_uri', + return_value="https://localhost:%s" % (self.https_port,)): + self.pb._download_provider_info() + # we check that it doesn't save the provider + # config, because it's new enough + self.assertFalse(ProviderConfig.save.called) + + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', + lambda x: where('cacert.pem')) def test_download_provider_info_modified(self): self._setup_provider_config_with("1", tempfile.mkdtemp()) self._setup_providerbootstrapper(True) @@ -455,8 +480,9 @@ class ProviderBootstrapperActiveTest(unittest.TestCase): self.assertTrue(ProviderConfig.load.called) self.assertTrue(ProviderConfig.save.called) - @mock.patch('leap.config.providerconfig.ProviderConfig.get_ca_cert_path', - lambda x: where('cacert.pem')) + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', + lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api_raises(self): self._setup_provider_config_with("9999999", tempfile.mkdtemp()) self._setup_providerbootstrapper(False) @@ -468,8 +494,9 @@ class ProviderBootstrapperActiveTest(unittest.TestCase): with self.assertRaises(UnsupportedProviderAPI): self.pb._download_provider_info() - @mock.patch('leap.config.providerconfig.ProviderConfig.get_ca_cert_path', - lambda x: where('cacert.pem')) + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', + lambda x: where('cacert.pem')) def test_download_provider_info_unsupported_api(self): self._setup_provider_config_with(SupportedAPIs.SUPPORTED_APIS[0], tempfile.mkdtemp()) @@ -481,10 +508,12 @@ class ProviderBootstrapperActiveTest(unittest.TestCase): return_value="https://localhost:%s" % (self.https_port,)): self.pb._download_provider_info() - @mock.patch('leap.config.providerconfig.ProviderConfig.get_api_uri', - lambda x: 'api.uri') - @mock.patch('leap.config.providerconfig.ProviderConfig.get_ca_cert_path', - lambda x: '/cert/path') + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_api_uri', + lambda x: 'api.uri') + @mock.patch( + 'leap.bitmask.config.providerconfig.ProviderConfig.get_ca_cert_path', + lambda x: '/cert/path') def test_check_api_certificate_skips(self): self.pb._provider_config = ProviderConfig() self.pb._session.get = mock.MagicMock(return_value=Response()) diff --git a/src/leap/services/eip/tests/test_vpngatewayselector.py b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py index c90681d7..36f8a076 100644 --- a/src/leap/services/eip/tests/test_vpngatewayselector.py +++ b/src/leap/bitmask/services/eip/tests/test_vpngatewayselector.py @@ -19,9 +19,11 @@ tests for vpngatewayselector """ import unittest +import time -from leap.services.eip.eipconfig import EIPConfig, VPNGatewaySelector +from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector from leap.common.testing.basetest import BaseLeapTest + from mock import Mock @@ -127,5 +129,19 @@ class VPNGatewaySelectorTest(BaseLeapTest): self.assertEqual(gateways, [ips[4], ips[2], ips[3], ips[1]]) +class VPNGatewaySelectorDSTTest(VPNGatewaySelectorTest): + """ + VPNGatewaySelector's tests. + It uses the opposite value of the current DST. + """ + def setUp(self): + self._original_daylight = time.daylight + time.daylight = not time.daylight + VPNGatewaySelectorTest.setUp(self) + + def tearDown(self): + VPNGatewaySelectorTest.tearDown(self) + time.daylight = self._original_daylight + if __name__ == "__main__": unittest.main() diff --git a/src/leap/services/eip/tests/wrongcert.pem b/src/leap/bitmask/services/eip/tests/wrongcert.pem index e6cff38a..e6cff38a 100644 --- a/src/leap/services/eip/tests/wrongcert.pem +++ b/src/leap/bitmask/services/eip/tests/wrongcert.pem diff --git a/src/leap/services/eip/udstelnet.py b/src/leap/bitmask/services/eip/udstelnet.py index e6c82350..e6c82350 100644 --- a/src/leap/services/eip/udstelnet.py +++ b/src/leap/bitmask/services/eip/udstelnet.py diff --git a/src/leap/services/eip/vpnlaunchers.py b/src/leap/bitmask/services/eip/vpnlaunchers.py index 17950a25..fb9ac46f 100644 --- a/src/leap/services/eip/vpnlaunchers.py +++ b/src/leap/bitmask/services/eip/vpnlaunchers.py @@ -33,13 +33,13 @@ except ImportError: from abc import ABCMeta, abstractmethod from functools import partial +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector +from leap.bitmask.util import first +from leap.bitmask.util.privilege_policies import LinuxPolicyChecker +from leap.bitmask.util import privilege_policies from leap.common.check import leap_assert, leap_assert_type from leap.common.files import which -from leap.config.providerconfig import ProviderConfig -from leap.services.eip.eipconfig import EIPConfig, VPNGatewaySelector -from leap.util import first -from leap.util.privilege_policies import LinuxPolicyChecker -from leap.util import privilege_policies logger = logging.getLogger(__name__) @@ -407,6 +407,10 @@ class LinuxVPNLauncher(VPNLauncher): args.append(openvpn) openvpn = first(pkexec) + args += [ + '--setenv', "LEAPOPENVPN", "1" + ] + if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] @@ -658,6 +662,10 @@ class DarwinVPNLauncher(VPNLauncher): openvpn = first(openvpn_possibilities) args = [openvpn] + args += [ + '--setenv', "LEAPOPENVPN", "1" + ] + if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] @@ -825,6 +833,11 @@ class WindowsVPNLauncher(VPNLauncher): openvpn = first(openvpn_possibilities) args = [] + + args += [ + '--setenv', "LEAPOPENVPN", "1" + ] + if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] diff --git a/src/leap/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 5b07a3cf..a896b60c 100644 --- a/src/leap/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -26,20 +26,21 @@ import socket from PySide import QtCore +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.services.eip.vpnlaunchers import get_platform_launcher +from leap.bitmask.services.eip.eipconfig import EIPConfig +from leap.bitmask.services.eip.udstelnet import UDSTelnet +from leap.bitmask.util import first +from leap.bitmask.platform_init import IS_MAC from leap.common.check import leap_assert, leap_assert_type -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 import first logger = logging.getLogger(__name__) vpnlog = logging.getLogger('leap.openvpn') from twisted.internet import protocol from twisted.internet import defer -from twisted.internet.task import LoopingCall from twisted.internet import error as internet_error +from twisted.internet.task import LoopingCall class VPNSignals(QtCore.QObject): @@ -228,7 +229,10 @@ class VPNManager(object): """ # Timers, in secs - POLL_TIME = 0.5 + # NOTE: We need to set a bigger poll time in OSX because it seems + # openvpn malfunctions when you ask it a lot of things in a short + # amount of time. + POLL_TIME = 2.5 if IS_MAC else 1.0 CONNECTION_RETRY_TIME = 1 TS_KEY = "ts" @@ -578,7 +582,7 @@ class VPNManager(object): # we need to be able to filter out arguments in the form # --openvpn-foo, since otherwise we are shooting ourselves # in the feet. - if any(map(lambda s: s.startswith("openvpn"), p.cmdline)): + if any(map(lambda s: s.find("LEAPOPENVPN") != -1, p.cmdline)): openvpn_process = p break except psutil.error.AccessDenied: diff --git a/src/leap/services/soledad/__init__.py b/src/leap/bitmask/services/mail/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/services/soledad/__init__.py +++ b/src/leap/bitmask/services/mail/__init__.py diff --git a/src/leap/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 4dceb2ad..4828180e 100644 --- a/src/leap/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -18,13 +18,38 @@ Initialization of imap service """ import logging -import sys +import os +#import sys from leap.mail.imap.service import imap -from twisted.python import log +#from twisted.python import log logger = logging.getLogger(__name__) +# The name of the environment variable that has to be +# set to override the default time value, in seconds. +INCOMING_CHECK_PERIOD_ENV = "BITMASK_MAILCHECK_PERIOD" + + +def get_mail_check_period(): + """ + Tries to get the value of the environment variable for + overriding the period for incoming mail fetch. + """ + period = None + period_str = os.environ.get(INCOMING_CHECK_PERIOD_ENV, None) + try: + period = int(period_str) + except (ValueError, TypeError): + logger.warning("BAD value found for %s: %s" % ( + INCOMING_CHECK_PERIOD_ENV, + period_str)) + except Exception as exc: + logger.warning("Unhandled error while getting %s: %r" % ( + INCOMING_CHECK_PERIOD_ENV, + exc)) + return period + def start_imap_service(*args, **kwargs): """ @@ -34,6 +59,10 @@ def start_imap_service(*args, **kwargs): """ logger.debug('Launching imap service') + override_period = get_mail_check_period() + if override_period: + kwargs['check_period'] = override_period + # Uncomment the next two lines to get a separate debugging log # TODO handle this by a separate flag. #log.startLogging(open('/tmp/leap-imap.log', 'w')) diff --git a/src/leap/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 48040035..0e83424c 100644 --- a/src/leap/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -24,12 +24,12 @@ import os from PySide import QtCore +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.util.request_helpers import get_content +from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.common.check import leap_assert, leap_assert_type from leap.common.files import get_mtime -from leap.config.providerconfig import ProviderConfig -from leap.crypto.srpauth import SRPAuth -from leap.util.request_helpers import get_content -from leap.services.abstractbootstrapper import AbstractBootstrapper logger = logging.getLogger(__name__) diff --git a/src/leap/services/mail/smtpconfig.py b/src/leap/bitmask/services/mail/smtpconfig.py index ea0f9c37..20041c30 100644 --- a/src/leap/services/mail/smtpconfig.py +++ b/src/leap/bitmask/services/mail/smtpconfig.py @@ -20,8 +20,8 @@ SMTP configuration """ import logging +from leap.bitmask.services.mail.smtpspec import get_schema from leap.common.config.baseconfig import BaseConfig -from leap.services.mail.smtpspec import get_schema logger = logging.getLogger(__name__) diff --git a/src/leap/services/mail/smtpspec.py b/src/leap/bitmask/services/mail/smtpspec.py index ff9d1bf8..ff9d1bf8 100644 --- a/src/leap/services/mail/smtpspec.py +++ b/src/leap/bitmask/services/mail/smtpspec.py diff --git a/src/leap/services/tests/__init__.py b/src/leap/bitmask/services/soledad/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/services/tests/__init__.py +++ b/src/leap/bitmask/services/soledad/__init__.py diff --git a/src/leap/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index c67bc004..2419fc0d 100644 --- a/src/leap/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -21,20 +21,21 @@ Soledad bootstrapping import logging import os +import socket from PySide import QtCore from u1db import errors as u1db_errors +from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper +from leap.bitmask.services.soledad.soledadconfig import SoledadConfig +from leap.bitmask.util.request_helpers import get_content from leap.common.check import leap_assert, leap_assert_type from leap.common.files import get_mtime from leap.keymanager import KeyManager, openpgp from leap.keymanager.errors import KeyNotFound -from leap.config.providerconfig import ProviderConfig -from leap.crypto.srpauth import SRPAuth -from leap.services.soledad.soledadconfig import SoledadConfig -from leap.util.request_helpers import get_content -from leap.soledad import Soledad -from leap.services.abstractbootstrapper import AbstractBootstrapper +from leap.soledad.client import Soledad logger = logging.getLogger(__name__) @@ -49,10 +50,14 @@ class SoledadBootstrapper(AbstractBootstrapper): PUBKEY_KEY = "user[public_key]" + MAX_INIT_RETRIES = 10 + # All dicts returned are of the form # {"passed": bool, "error": str} download_config = QtCore.Signal(dict) gen_key = QtCore.Signal(dict) + soledad_timeout = QtCore.Signal() + soledad_failed = QtCore.Signal() def __init__(self): AbstractBootstrapper.__init__(self) @@ -63,8 +68,11 @@ class SoledadBootstrapper(AbstractBootstrapper): self._download_if_needed = False self._user = "" self._password = "" + self._srpauth = None self._soledad = None + self._soledad_retries = 0 + @property def keymanager(self): return self._keymanager @@ -73,7 +81,35 @@ class SoledadBootstrapper(AbstractBootstrapper): def soledad(self): return self._soledad - def _load_and_sync_soledad(self, srp_auth): + @property + def srpauth(self): + leap_assert(self._provider_config is not None, + "We need a provider config") + return SRPAuth(self._provider_config) + + # retries + + def cancel_bootstrap(self): + self._soledad_retries = self.MAX_INIT_RETRIES + + def should_retry_initialization(self): + """ + Returns True if we should retry the initialization. + """ + logger.debug("current retries: %s, max retries: %s" % ( + self._soledad_retries, + self.MAX_INIT_RETRIES)) + return self._soledad_retries < self.MAX_INIT_RETRIES + + def increment_retries_count(self): + """ + Increments the count of initialization retries. + """ + self._soledad_retries += 1 + + # initialization + + def load_and_sync_soledad(self): """ Once everthing is in the right place, we instantiate and sync Soledad @@ -81,6 +117,7 @@ class SoledadBootstrapper(AbstractBootstrapper): :param srp_auth: SRPAuth object used :type srp_auth: SRPAuth """ + srp_auth = self.srpauth uuid = srp_auth.get_uid() prefix = os.path.join(self._soledad_config.get_path_prefix(), @@ -114,8 +151,24 @@ class SoledadBootstrapper(AbstractBootstrapper): cert_file=cert_file, auth_token=srp_auth.get_token()) self._soledad.sync() + + # XXX All these errors should be handled by soledad itself, + # and return a subclass of SoledadInitializationFailed + except socket.timeout: + logger.debug("SOLEDAD TIMED OUT...") + self.soledad_timeout.emit() + except socket.error as exc: + logger.error("Socket error while initializing soledad") + if exc.errno in (111, ): + self.soledad_failed.emit() except u1db_errors.Unauthorized: - logger.error("Error while initializing soledad.") + logger.error("Error while initializing soledad " + "(unauthorized).") + self.soledad_failed.emit() + except Exception as exc: + logger.error("Unhandled error while initializating " + "soledad: %r" % (exc,)) + raise else: raise Exception("No soledad server found") @@ -151,7 +204,8 @@ class SoledadBootstrapper(AbstractBootstrapper): api_version) logger.debug('Downloading soledad config from: %s' % config_uri) - srp_auth = SRPAuth(self._provider_config) + # TODO factor out this srpauth protected get (make decorator) + srp_auth = self.srpauth session_id = srp_auth.get_session_id() cookies = None if session_id: @@ -183,7 +237,7 @@ class SoledadBootstrapper(AbstractBootstrapper): self._provider_config.get_domain(), "soledad-service.json"]) - self._load_and_sync_soledad(srp_auth) + self.load_and_sync_soledad() def _gen_key(self, _): """ @@ -197,8 +251,9 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.debug("Retrieving key for %s" % (address,)) - srp_auth = SRPAuth(self._provider_config) + srp_auth = self.srpauth + # TODO: use which implementation with known paths # TODO: Fix for Windows gpgbin = "/usr/bin/gpg" @@ -251,6 +306,7 @@ class SoledadBootstrapper(AbstractBootstrapper): """ leap_assert_type(provider_config, ProviderConfig) + # XXX we should provider a method for setting provider_config self._provider_config = provider_config self._download_if_needed = download_if_needed self._user = user diff --git a/src/leap/services/soledad/soledadconfig.py b/src/leap/bitmask/services/soledad/soledadconfig.py index a2367692..7ed21f77 100644 --- a/src/leap/services/soledad/soledadconfig.py +++ b/src/leap/bitmask/services/soledad/soledadconfig.py @@ -20,8 +20,8 @@ Soledad configuration """ import logging +from leap.bitmask.services.soledad.soledadspec import get_schema from leap.common.config.baseconfig import BaseConfig -from leap.services.soledad.soledadspec import get_schema logger = logging.getLogger(__name__) diff --git a/src/leap/services/soledad/soledadspec.py b/src/leap/bitmask/services/soledad/soledadspec.py index 111175dd..111175dd 100644 --- a/src/leap/services/soledad/soledadspec.py +++ b/src/leap/bitmask/services/soledad/soledadspec.py diff --git a/src/leap/util/tests/__init__.py b/src/leap/bitmask/services/tests/__init__.py index e69de29b..e69de29b 100644 --- a/src/leap/util/tests/__init__.py +++ b/src/leap/bitmask/services/tests/__init__.py diff --git a/src/leap/services/tests/test_abstractbootstrapper.py b/src/leap/bitmask/services/tests/test_abstractbootstrapper.py index a9ee220f..3ac126ac 100644 --- a/src/leap/services/tests/test_abstractbootstrapper.py +++ b/src/leap/bitmask/services/tests/test_abstractbootstrapper.py @@ -26,8 +26,9 @@ from PySide import QtCore from nose.twistedtools import deferred -from leap.services.abstractbootstrapper import AbstractBootstrapper -from leap.util.pyside_tests_helper import UsesQApplication, BasicPySlotCase +from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper +from leap.bitmask.util.pyside_tests_helper import \ + UsesQApplication, BasicPySlotCase class TesterBootstrapper(AbstractBootstrapper): diff --git a/src/leap/services/tx.py b/src/leap/bitmask/services/tx.py index 7da1cb01..adc6fcea 100644 --- a/src/leap/services/tx.py +++ b/src/leap/bitmask/services/tx.py @@ -20,7 +20,7 @@ Twisted services launched by the client import logging from twisted.application.service import Application -from twisted.internet.task import LoopingCall +#from twisted.internet.task import LoopingCall logger = logging.getLogger(__name__) diff --git a/src/leap/util/__init__.py b/src/leap/bitmask/util/__init__.py index f39b52e9..ce8323cd 100644 --- a/src/leap/util/__init__.py +++ b/src/leap/bitmask/util/__init__.py @@ -49,7 +49,7 @@ __version__ = "unknown" IS_RELEASE_VERSION = False try: - from leap._version import get_versions + from leap.bitmask._version import get_versions __version__ = get_versions()['version'] IS_RELEASE_VERSION = _is_release_version(__version__) del get_versions diff --git a/src/leap/util/constants.py b/src/leap/bitmask/util/constants.py index 63f6b1f7..63f6b1f7 100644 --- a/src/leap/util/constants.py +++ b/src/leap/bitmask/util/constants.py diff --git a/src/leap/util/keyring_helpers.py b/src/leap/bitmask/util/keyring_helpers.py index 8f354f28..8f354f28 100644 --- a/src/leap/util/keyring_helpers.py +++ b/src/leap/bitmask/util/keyring_helpers.py diff --git a/src/leap/util/leap_argparse.py b/src/leap/bitmask/util/leap_argparse.py index f60c4e10..71f5163d 100644 --- a/src/leap/util/leap_argparse.py +++ b/src/leap/bitmask/util/leap_argparse.py @@ -17,7 +17,7 @@ import argparse -from leap.util import IS_RELEASE_VERSION +from leap.bitmask.util import IS_RELEASE_VERSION def build_parser(): diff --git a/src/leap/util/leap_log_handler.py b/src/leap/bitmask/util/leap_log_handler.py index 9adb21a5..9adb21a5 100644 --- a/src/leap/util/leap_log_handler.py +++ b/src/leap/bitmask/util/leap_log_handler.py diff --git a/src/leap/util/privilege_policies.py b/src/leap/bitmask/util/privilege_policies.py index 72442553..72442553 100644 --- a/src/leap/util/privilege_policies.py +++ b/src/leap/bitmask/util/privilege_policies.py diff --git a/src/leap/util/pyside_tests_helper.py b/src/leap/bitmask/util/pyside_tests_helper.py index 5c0eb8d6..5c0eb8d6 100644 --- a/src/leap/util/pyside_tests_helper.py +++ b/src/leap/bitmask/util/pyside_tests_helper.py diff --git a/src/leap/bitmask/util/reqs.txt b/src/leap/bitmask/util/reqs.txt new file mode 100644 index 00000000..0bcf85dc --- /dev/null +++ b/src/leap/bitmask/util/reqs.txt @@ -0,0 +1,14 @@ +requests +srp>=1.0.2 +pyopenssl +keyring +python-dateutil +psutil +ipaddr +twisted +qt4reactor +python-gnupg +leap.common>=0.2.5 +leap.soledad>=0.1.0 +mock +oauth
\ No newline at end of file diff --git a/src/leap/util/request_helpers.py b/src/leap/bitmask/util/request_helpers.py index 74aaa06b..60256b1e 100644 --- a/src/leap/util/request_helpers.py +++ b/src/leap/bitmask/util/request_helpers.py @@ -18,9 +18,7 @@ """ Request helpers for backward compatible "parsing" of requests """ - import time - import json from dateutil import parser as dateparser diff --git a/src/leap/util/requirement_checker.py b/src/leap/bitmask/util/requirement_checker.py index 1d9b9923..1d9b9923 100644 --- a/src/leap/util/requirement_checker.py +++ b/src/leap/bitmask/util/requirement_checker.py diff --git a/src/leap/util/streamtologger.py b/src/leap/bitmask/util/streamtologger.py index 25a06718..25a06718 100644 --- a/src/leap/util/streamtologger.py +++ b/src/leap/bitmask/util/streamtologger.py diff --git a/src/leap/bitmask/util/tests/__init__.py b/src/leap/bitmask/util/tests/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/leap/bitmask/util/tests/__init__.py diff --git a/src/leap/util/tests/test_is_release_version.py b/src/leap/bitmask/util/tests/test_is_release_version.py index 4199f603..088ec66d 100644 --- a/src/leap/util/tests/test_is_release_version.py +++ b/src/leap/bitmask/util/tests/test_is_release_version.py @@ -17,10 +17,10 @@ """ tests for _is_release_version function """ - import unittest + +from leap.bitmask.util import _is_release_version as is_release_version from leap.common.testing.basetest import BaseLeapTest -from leap.util import _is_release_version as is_release_version class TestIsReleaseVersion(BaseLeapTest): diff --git a/src/leap/util/tests/test_leap_log_handler.py b/src/leap/bitmask/util/tests/test_leap_log_handler.py index ea509ea8..518fd35b 100644 --- a/src/leap/util/tests/test_leap_log_handler.py +++ b/src/leap/bitmask/util/tests/test_leap_log_handler.py @@ -17,14 +17,16 @@ """ tests for leap_log_handler """ - -import unittest +try: + import unittest2 as unittest +except ImportError: + import unittest import logging -from leap.util.leap_log_handler import LeapLogHandler +from leap.bitmask.util.leap_log_handler import LeapLogHandler +from leap.bitmask.util.pyside_tests_helper import BasicPySlotCase from leap.common.testing.basetest import BaseLeapTest -from leap.util.pyside_tests_helper import BasicPySlotCase from mock import Mock diff --git a/src/leap/util/tests/test_streamtologger.py b/src/leap/bitmask/util/tests/test_streamtologger.py index 4c98e562..fc97b794 100644 --- a/src/leap/util/tests/test_streamtologger.py +++ b/src/leap/bitmask/util/tests/test_streamtologger.py @@ -26,7 +26,7 @@ except ImportError: import logging import sys -from leap.util.streamtologger import StreamToLogger +from leap.bitmask.util.streamtologger import StreamToLogger from leap.common.testing.basetest import BaseLeapTest @@ -117,6 +117,10 @@ class StreamToLoggerTest(BaseLeapTest): self.assertEqual(log, message) self.assertEqual(log_level, logging.ERROR) + def test_twisted_log(self): + from twisted.python import log + log.startLogging(sys.stdout) + if __name__ == "__main__": unittest.main(verbosity=2) |