summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/leap/bitmask/backend.py89
-rw-r--r--src/leap/bitmask/gui/mainwindow.py87
2 files changed, 159 insertions, 17 deletions
diff --git a/src/leap/bitmask/backend.py b/src/leap/bitmask/backend.py
index 2bfcbfa0..8dd9f799 100644
--- a/src/leap/bitmask/backend.py
+++ b/src/leap/bitmask/backend.py
@@ -41,6 +41,8 @@ from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper
from leap.bitmask.services.eip import vpnlauncher, vpnprocess
from leap.bitmask.services.eip import linuxvpnlauncher, darwinvpnlauncher
+from leap.common import certs as leap_certs
+
# Frontend side
from PySide import QtCore
@@ -275,18 +277,23 @@ class EIP(object):
self._vpn = vpnprocess.VPN(signaler=signaler)
- def setup_eip(self, domain):
+ def setup_eip(self, domain, skip_network=False):
"""
Initiate the setup for a provider
:param domain: URL for the provider
:type domain: unicode
+ :param skip_network: Whether checks that involve network should be done
+ or not
+ :type skip_network: bool
:returns: the defer for the operation running in a thread.
:rtype: twisted.internet.defer.Deferred
"""
config = self._provider_config
if get_provider_config(config, domain):
+ if skip_network:
+ return defer.Deferred()
eb = self._eip_bootstrapper
d = eb.run_eip_setup_checks(self._provider_config,
download_if_needed=True)
@@ -334,7 +341,8 @@ class EIP(object):
if not self._provider_config.loaded():
# This means that the user didn't call setup_eip first.
- self._signaler.signal(signaler.BACKEND_BAD_CALL)
+ self._signaler.signal(signaler.BACKEND_BAD_CALL, "EIP.start(), "
+ "no provider loaded")
return
try:
@@ -457,6 +465,47 @@ class EIP(object):
self._signaler.signal(
self._signaler.EIP_GET_GATEWAYS_LIST, gateways)
+ def can_start(self, domain):
+ """
+ Signal whether it has everything that is needed to run EIP or not
+
+ :param domain: the domain for the provider to check
+ :type domain: str
+
+ Signals:
+ eip_can_start
+ eip_cannot_start
+ """
+ try:
+ eip_config = eipconfig.EIPConfig()
+ provider_config = ProviderConfig.get_provider_config(domain)
+
+ api_version = provider_config.get_api_version()
+ eip_config.set_api_version(api_version)
+ eip_loaded = eip_config.load(eipconfig.get_eipconfig_path(domain))
+
+ # check for other problems
+ if not eip_loaded or provider_config is None:
+ raise Exception("Cannot load provider and eip config, cannot "
+ "autostart")
+
+ client_cert_path = eip_config.\
+ get_client_cert_path(provider_config, about_to_download=False)
+
+ if leap_certs.should_redownload(client_cert_path):
+ raise Exception("The client should redownload the certificate,"
+ " cannot autostart")
+
+ if not os.path.isfile(client_cert_path):
+ raise Exception("Can't find the certificate, cannot autostart")
+
+ if self._signaler is not None:
+ self._signaler.signal(self._signaler.EIP_CAN_START)
+ except Exception as e:
+ logger.exception(e)
+ if self._signaler is not None:
+ self._signaler.signal(self._signaler.EIP_CANNOT_START)
+
class Authenticate(object):
"""
@@ -647,6 +696,10 @@ class Signaler(QtCore.QObject):
eip_status_changed = QtCore.Signal(dict)
eip_process_finished = QtCore.Signal(int)
+ # signals whether the needed files to start EIP exist or not
+ eip_can_start = QtCore.Signal(object)
+ eip_cannot_start = QtCore.Signal(object)
+
# This signal is used to warn the backend user that is doing something
# wrong
backend_bad_call = QtCore.Signal(object)
@@ -713,6 +766,9 @@ class Signaler(QtCore.QObject):
EIP_STATUS_CHANGED = "eip_status_changed"
EIP_PROCESS_FINISHED = "eip_process_finished"
+ EIP_CAN_START = "eip_can_start"
+ EIP_CANNOT_START = "eip_cannot_start"
+
BACKEND_BAD_CALL = "backend_bad_call"
def __init__(self):
@@ -767,6 +823,9 @@ class Signaler(QtCore.QObject):
self.EIP_STATUS_CHANGED,
self.EIP_PROCESS_FINISHED,
+ self.EIP_CAN_START,
+ self.EIP_CANNOT_START,
+
self.SRP_AUTH_OK,
self.SRP_AUTH_ERROR,
self.SRP_AUTH_SERVER_ERROR,
@@ -1001,19 +1060,23 @@ class Backend(object):
self._call_queue.put(("register", "register_user", None, provider,
username, password))
- def setup_eip(self, provider):
+ def setup_eip(self, provider, skip_network=False):
"""
Initiate the setup for a provider
- :param domain: URL for the provider
- :type domain: unicode
+ :param provider: URL for the provider
+ :type provider: unicode
+ :param skip_network: Whether checks that involve network should be done
+ or not
+ :type skip_network: bool
Signals:
eip_config_ready -> {PASSED_KEY: bool, ERROR_KEY: str}
eip_client_certificate_ready -> {PASSED_KEY: bool, ERROR_KEY: str}
eip_cancelled_setup
"""
- self._call_queue.put(("eip", "setup_eip", None, provider))
+ self._call_queue.put(("eip", "setup_eip", None, provider,
+ skip_network))
def cancel_setup_eip(self):
"""
@@ -1089,6 +1152,20 @@ class Backend(object):
self._call_queue.put(("eip", "get_initialized_providers",
None, domains))
+ def eip_can_start(self, domain):
+ """
+ Signal whether it has everything that is needed to run EIP or not
+
+ :param domain: the domain for the provider to check
+ :type domain: str
+
+ Signals:
+ eip_can_start
+ eip_cannot_start
+ """
+ self._call_queue.put(("eip", "can_start",
+ None, domain))
+
def login(self, provider, username, password):
"""
Execute the whole authentication process for a user
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 1a88fcce..6e270de1 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -182,6 +182,8 @@ class MainWindow(QtGui.QMainWindow):
self.eip_needs_login.connect(self._eip_status.disable_eip_start)
self.eip_needs_login.connect(self._disable_eip_start_action)
+ self._trying_to_start_eip = False
+
# This is loaded only once, there's a bug when doing that more
# than once
# XXX HACK!! But we need it as long as we are using
@@ -357,11 +359,24 @@ class MainWindow(QtGui.QMainWindow):
self._backend_connected_signals[signal] = method
signal.connect(method)
+ def _backend_bad_call(self, data):
+ """
+ Callback for debugging bad backend calls
+
+ :param data: data from the backend about the problem
+ :type data: str
+ """
+ logger.error("Bad call to the backend:")
+ logger.error(data)
+
def _backend_connect(self):
"""
Helper to connect to backend signals
"""
sig = self._backend.signaler
+
+ sig.backend_bad_call.connect(self._backend_bad_call)
+
self._connect_and_track(sig.prov_name_resolution,
self._intermediate_stage)
self._connect_and_track(sig.prov_https_connection,
@@ -442,6 +457,9 @@ class MainWindow(QtGui.QMainWindow):
sig.eip_process_restart_tls.connect(self._do_eip_restart)
sig.eip_process_restart_ping.connect(self._do_eip_restart)
+ sig.eip_can_start.connect(self._backend_can_start_eip)
+ sig.eip_cannot_start.connect(self._backend_cannot_start_eip)
+
def _disconnect_and_untrack(self):
"""
Helper to disconnect the tracked signals.
@@ -609,17 +627,43 @@ class MainWindow(QtGui.QMainWindow):
"""
settings = self._settings
default_provider = settings.get_defaultprovider()
+
+ if default_provider is None:
+ logger.warning("Trying toupdate eip enabled status but there's no"
+ " default provider. Disabling EIP for the time"
+ " being...")
+ self._backend_cannot_start_eip()
+ return
+
+ self._trying_to_start_eip = settings.get_autostart_eip()
+ self._backend.eip_can_start(default_provider)
+
+ # If we don't want to start eip, we leave everything
+ # initialized to quickly start it
+ if not self._trying_to_start_eip:
+ self._backend.setup_eip(default_provider, skip_network=True)
+
+ def _backend_can_start_eip(self):
+ """
+ TRIGGER:
+ self._backend.signaler.eip_can_start
+
+ If EIP can be started right away, and the client is configured
+ to do so, start it. Otherwise it leaves everything in place
+ for the user to click Turn ON.
+ """
+ settings = self._settings
+ default_provider = settings.get_defaultprovider()
enabled_services = []
if default_provider is not None:
enabled_services = settings.get_enabled_services(default_provider)
eip_enabled = False
if EIP_SERVICE in enabled_services:
- should_autostart = settings.get_autostart_eip()
- if should_autostart and default_provider is not None:
+ eip_enabled = True
+ if default_provider is not None:
self._eip_status.enable_eip_start()
self._eip_status.set_eip_status("")
- eip_enabled = True
else:
# we don't have an usable provider
# so the user needs to log in first
@@ -629,7 +673,32 @@ class MainWindow(QtGui.QMainWindow):
self._eip_status.disable_eip_start()
self._eip_status.set_eip_status(self.tr("Disabled"))
- return eip_enabled
+ if eip_enabled and self._trying_to_start_eip:
+ self._trying_to_start_eip = False
+ self._try_autostart_eip()
+
+ def _backend_cannot_start_eip(self):
+ """
+ TRIGGER:
+ self._backend.signaler.eip_cannot_start
+
+ If EIP can't be started right away, get the UI to what it
+ needs to look like and waits for a proper login/eip bootstrap.
+ """
+ settings = self._settings
+ default_provider = settings.get_defaultprovider()
+ enabled_services = []
+ if default_provider is not None:
+ enabled_services = settings.get_enabled_services(default_provider)
+
+ if EIP_SERVICE in enabled_services:
+ # we don't have a usable provider
+ # so the user needs to log in first
+ self._eip_status.disable_eip_start()
+ else:
+ self._stop_eip()
+ self._eip_status.disable_eip_start()
+ self._eip_status.set_eip_status(self.tr("Disabled"))
@QtCore.Slot()
def _show_eip_preferences(self):
@@ -749,7 +818,7 @@ class MainWindow(QtGui.QMainWindow):
self._wizard = None
self._backend_connect()
else:
- self._try_autostart_eip()
+ self._update_eip_enabled_status()
domain = self._settings.get_provider()
if domain is not None:
@@ -1589,23 +1658,19 @@ class MainWindow(QtGui.QMainWindow):
Tries to autostart EIP
"""
settings = self._settings
-
- if not self._update_eip_enabled_status():
- return
-
default_provider = settings.get_defaultprovider()
self._enabled_services = settings.get_enabled_services(
default_provider)
loaded = self._provisional_provider_config.load(
provider.get_provider_path(default_provider))
- if loaded:
+ if loaded and settings.get_autostart_eip():
# XXX I think we should not try to re-download config every time,
# it adds some delay.
# Maybe if it's the first run in a session,
# or we can try only if it fails.
self._maybe_start_eip()
- else:
+ elif settings.get_autostart_eip():
# XXX: Display a proper message to the user
self.eip_needs_login.emit()
logger.error("Unable to load %s config, cannot autostart." %