summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/leap/bitmask/gui/eip_preferenceswindow.py35
-rw-r--r--src/leap/bitmask/gui/eip_status.py18
-rw-r--r--src/leap/bitmask/gui/mainwindow.py80
-rw-r--r--src/leap/bitmask/gui/preferenceswindow.py9
-rw-r--r--src/leap/bitmask/provider/providerbootstrapper.py32
-rw-r--r--src/leap/bitmask/services/eip/eipconfig.py14
-rw-r--r--src/leap/bitmask/services/eip/linuxvpnlauncher.py17
-rw-r--r--src/leap/bitmask/services/eip/vpnlauncher.py3
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py2
9 files changed, 133 insertions, 77 deletions
diff --git a/src/leap/bitmask/gui/eip_preferenceswindow.py b/src/leap/bitmask/gui/eip_preferenceswindow.py
index e0c5d51f..504d1cf1 100644
--- a/src/leap/bitmask/gui/eip_preferenceswindow.py
+++ b/src/leap/bitmask/gui/eip_preferenceswindow.py
@@ -28,6 +28,7 @@ from leap.bitmask.config.leapsettings import LeapSettings
from leap.bitmask.config.providerconfig import ProviderConfig
from leap.bitmask.gui.ui_eippreferences import Ui_EIPPreferences
from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector
+from leap.bitmask.services.eip.eipconfig import get_eipconfig_path
logger = logging.getLogger(__name__)
@@ -52,7 +53,7 @@ class EIPPreferencesWindow(QtGui.QDialog):
self.ui.lblProvidersGatewayStatus.setVisible(False)
# Connections
- self.ui.cbProvidersGateway.currentIndexChanged[unicode].connect(
+ self.ui.cbProvidersGateway.currentIndexChanged[int].connect(
self._populate_gateways)
self.ui.cbGateways.currentIndexChanged[unicode].connect(
@@ -93,7 +94,11 @@ class EIPPreferencesWindow(QtGui.QDialog):
return
for provider in providers:
- self.ui.cbProvidersGateway.addItem(provider)
+ label = provider
+ eip_config_path = get_eipconfig_path(provider, relative=False)
+ if not os.path.isfile(eip_config_path):
+ label = provider + self.tr(" (uninitialized)")
+ self.ui.cbProvidersGateway.addItem(label, userData=provider)
def _save_selected_gateway(self, provider):
"""
@@ -120,7 +125,7 @@ class EIPPreferencesWindow(QtGui.QDialog):
"Gateway settings for provider '{0}' saved.").format(provider)
self._set_providers_gateway_status(msg, success=True)
- def _populate_gateways(self, domain):
+ def _populate_gateways(self, domain_idx):
"""
SLOT
TRIGGERS:
@@ -129,15 +134,29 @@ class EIPPreferencesWindow(QtGui.QDialog):
Loads the gateways that the provider provides into the UI for
the user to select.
- :param domain: the domain of the provider to load gateways from.
- :type domain: str
+ :param domain: the domain index of the provider to load gateways from.
+ :type domain: int
"""
# We hide the maybe-visible status label after a change
self.ui.lblProvidersGatewayStatus.setVisible(False)
- if not domain:
+ if domain_idx == -1:
return
+ domain = self.ui.cbProvidersGateway.itemData(domain_idx)
+
+ if not os.path.isfile(get_eipconfig_path(domain, relative=False)):
+ self._set_providers_gateway_status(
+ self.tr("This is an uninitialized provider, "
+ "please log in first."),
+ error=True)
+ self.ui.pbSaveGateway.setEnabled(False)
+ self.ui.cbGateways.setEnabled(False)
+ return
+ else:
+ self.ui.pbSaveGateway.setEnabled(True)
+ self.ui.cbGateways.setEnabled(True)
+
try:
# disconnect previously connected save method
self.ui.pbSaveGateway.clicked.disconnect()
@@ -151,11 +170,9 @@ class EIPPreferencesWindow(QtGui.QDialog):
eip_config = EIPConfig()
provider_config = ProviderConfig.get_provider_config(domain)
- eip_config_path = os.path.join("leap", "providers",
- domain, "eip-service.json")
api_version = provider_config.get_api_version()
eip_config.set_api_version(api_version)
- eip_loaded = eip_config.load(eip_config_path)
+ eip_loaded = eip_config.load(get_eipconfig_path(domain))
if not eip_loaded or provider_config is None:
self._set_providers_gateway_status(
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index 1899d6a4..4b4d360f 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -77,6 +77,10 @@ class EIPStatusWidget(QtGui.QWidget):
self._provider = ""
+ # Action for the systray
+ self._eip_disabled_action = QtGui.QAction(
+ "{0} is {1}".format(self._service_name, self.tr("disabled")), self)
+
def _make_status_clickable(self):
"""
Makes upload and download figures clickable.
@@ -252,6 +256,15 @@ class EIPStatusWidget(QtGui.QWidget):
self.eip_button.hide()
msg = self.tr("You must login to use {0}".format(self._service_name))
self.eip_label.setText(msg)
+ self._eip_status_menu.setTitle("{0} is {1}".format(
+ self._service_name, self.tr("disabled")))
+
+ # Replace EIP tray menu with an action that displays a "disabled" text
+ menu = self._systray.contextMenu()
+ menu.insertAction(
+ self._eip_status_menu.menuAction(),
+ self._eip_disabled_action)
+ self._eip_status_menu.menuAction().setVisible(False)
@QtCore.Slot()
def enable_eip_start(self):
@@ -262,6 +275,11 @@ class EIPStatusWidget(QtGui.QWidget):
logger.debug('Showing EIP start button')
self.eip_button.show()
+ # Restore the eip action menu
+ menu = self._systray.contextMenu()
+ menu.removeAction(self._eip_disabled_action)
+ self._eip_status_menu.menuAction().setVisible(True)
+
# XXX disable (later) --------------------------
def set_eip_status(self, status, error=False):
"""
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index b0f25af1..929919ac 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -22,7 +22,7 @@ import os
from PySide import QtCore, QtGui
from twisted.internet import threads
-from zope.proxy import ProxyBase, setProxiedObject, sameProxiedObjects
+from zope.proxy import ProxyBase, setProxiedObject
from leap.bitmask import __version__ as VERSION
from leap.bitmask.config.leapsettings import LeapSettings
@@ -44,6 +44,8 @@ from leap.bitmask.platform_init import IS_WIN, IS_MAC
from leap.bitmask.platform_init.initializers import init_platform
from leap.bitmask.provider.providerbootstrapper import ProviderBootstrapper
+from leap.bitmask.services import get_service_display_name, EIP_SERVICE
+
from leap.bitmask.services.mail import conductor as mail_conductor
from leap.bitmask.services import EIP_SERVICE, MX_SERVICE
@@ -339,6 +341,8 @@ class MainWindow(QtGui.QMainWindow):
self.start_eip_machine()
self._mail_conductor.start_mail_machine()
+ self._eip_name = get_service_display_name(EIP_SERVICE)
+
if self._first_run():
self._wizard_firstrun = True
self._wizard = Wizard(bypass_checks=bypass_checks)
@@ -358,15 +362,19 @@ class MainWindow(QtGui.QMainWindow):
Called if the wizard has been cancelled or closed before
finishing.
+ This is executed for the first run wizard only. Any other execution of
+ the wizard won't reach this point.
"""
- if self._wizard_firstrun:
- providers = self._settings.get_configured_providers()
- has_provider_on_disk = len(providers) != 0
- if not has_provider_on_disk:
- # if we don't have any provider configured (included a pinned
- # one) we can't use the application, so quit.
- self.quit()
+ providers = self._settings.get_configured_providers()
+ has_provider_on_disk = len(providers) != 0
+ if not has_provider_on_disk:
+ # if we don't have any provider configured (included a pinned
+ # one) we can't use the application, so quit.
+ self.quit()
else:
+ # This happens if the user finishes the provider
+ # setup but does not register
+ self._wizard = None
self._finish_init()
def _launch_wizard(self):
@@ -463,9 +471,9 @@ class MainWindow(QtGui.QMainWindow):
Displays the preferences window.
"""
- preferences_window = PreferencesWindow(self, self._srp_auth,
- self._provider_config,
- self._soledad)
+ preferences_window = PreferencesWindow(
+ self, self._srp_auth, self._provider_config, self._soledad,
+ self._login_widget.get_selected_provider())
self.soledad_ready.connect(preferences_window.set_soledad_ready)
preferences_window.show()
@@ -538,8 +546,7 @@ class MainWindow(QtGui.QMainWindow):
TRIGGERS:
self._wizard.accepted
- Also called at the end of the constructor if not first run,
- and after _rejected_wizard if not first run.
+ Also called at the end of the constructor if not first run.
Implements the behavior after either constructing the
mainwindow object, loading the saved user/password, or after
@@ -574,6 +581,9 @@ class MainWindow(QtGui.QMainWindow):
if possible_password is not None:
self._login_widget.set_password(possible_password)
self._login()
+ else:
+ self.eip_needs_login.emit()
+
self._wizard = None
else:
self._try_autostart_eip()
@@ -637,7 +647,8 @@ class MainWindow(QtGui.QMainWindow):
systrayMenu.addAction(self._action_visible)
systrayMenu.addSeparator()
- eip_menu = systrayMenu.addMenu(self.tr("Encrypted Internet: OFF"))
+ eip_status_label = "{0}: {1}".format(self._eip_name, self.tr("OFF"))
+ eip_menu = systrayMenu.addMenu(eip_status_label)
eip_menu.addAction(self._action_eip_startstop)
self._eip_status.set_eip_status_menu(eip_menu)
systrayMenu.addSeparator()
@@ -1224,10 +1235,9 @@ class MainWindow(QtGui.QMainWindow):
provider_config, self._eip_config, provider)
if not loaded:
- self._eip_status.set_eip_status(
- self.tr("Could not load Encrypted Internet "
- "Configuration."),
- error=True)
+ eip_status_label = self.tr("Could not load {0} configuration.")
+ eip_status_label = eip_status_label.format(self._eip_name)
+ self._eip_status.set_eip_status(eip_status_label, error=True)
# signal connection aborted to state machine
qtsigs = self._eip_connection.qtsigs
qtsigs.connection_aborted_signal.emit()
@@ -1264,9 +1274,9 @@ class MainWindow(QtGui.QMainWindow):
self._set_eipstatus_off()
except EIPNoTunKextLoaded:
self._eip_status.set_eip_status(
- self.tr("Encrypted Internet cannot be started because "
+ self.tr("{0} cannot be started because "
"the tuntap extension is not installed properly "
- "in your system."))
+ "in your system.").format(self._eip_name))
self._set_eipstatus_off()
except EIPNoPkexecAvailable:
self._eip_status.set_eip_status(
@@ -1363,8 +1373,7 @@ class MainWindow(QtGui.QMainWindow):
Sets eip status to off
"""
# XXX this should be handled by the state machine.
- self._eip_status.set_eip_status(self.tr("EIP has stopped"),
- error=error)
+ self._eip_status.set_eip_status("", error=error)
self._eip_status.set_eip_status_icon("error")
def _eip_finished(self, exitCode):
@@ -1402,17 +1411,18 @@ class MainWindow(QtGui.QMainWindow):
# XXX check if these exitCodes are pkexec/cocoasudo specific
if exitCode in (126, 127):
- self._eip_status.set_eip_status(
- self.tr("Encrypted Internet could not be launched "
- "because you did not authenticate properly."),
- error=True)
+ eip_status_label = self.tr(
+ "{0} could not be launched "
+ "because you did not authenticate properly.")
+ eip_status_label = eip_status_label.format(self._eip_name)
+ self._eip_status.set_eip_status(eip_status_label, error=True)
self._vpn.killit()
signal = qtsigs.connection_aborted_signal
elif exitCode != 0 or not self.user_stopped_eip:
- self._eip_status.set_eip_status(
- self.tr("Encrypted Internet finished in an "
- "unexpected manner!"), error=True)
+ eip_status_label = self.tr("{0} finished in an unexpected manner!")
+ eip_status_label = eip_status_label.format(self._eip_name)
+ self._eip_status.set_eip_status(eip_status_label, error=True)
signal = qtsigs.connection_died_signal
if exitCode == 0 and IS_MAC:
@@ -1449,6 +1459,7 @@ class MainWindow(QtGui.QMainWindow):
self.tr("Not supported"),
error=True)
else:
+ self._eip_status.disable_eip_start()
self._eip_status.set_eip_status(self.tr("Disabled"))
def _finish_eip_bootstrap(self, data):
@@ -1480,10 +1491,9 @@ class MainWindow(QtGui.QMainWindow):
# DO START EIP Connection!
self._eip_connection.qtsigs.do_connect_signal.emit()
else:
- self._eip_status.set_eip_status(
- self.tr("Could not load Encrypted Internet "
- "Configuration."),
- error=True)
+ eip_status_label = self.tr("Could not load {0} configuration.")
+ eip_status_label = eip_status_label.format(self._eip_name)
+ self._eip_status.set_eip_status(eip_status_label, error=True)
def _eip_intermediate_stage(self, data):
# TODO missing param
@@ -1645,9 +1655,9 @@ class MainWindow(QtGui.QMainWindow):
# XXX this can timeout after loong time: See #3368
self._srp_auth.logout()
- if self._soledad:
+ if self._soledad_bootstrapper.soledad is not None:
logger.debug("Closing soledad...")
- self._soledad.close()
+ self._soledad_bootstrapper.soledad.close()
else:
logger.error("No instance of soledad was found.")
diff --git a/src/leap/bitmask/gui/preferenceswindow.py b/src/leap/bitmask/gui/preferenceswindow.py
index 8e9ef95a..b4bddef2 100644
--- a/src/leap/bitmask/gui/preferenceswindow.py
+++ b/src/leap/bitmask/gui/preferenceswindow.py
@@ -42,7 +42,7 @@ class PreferencesWindow(QtGui.QDialog):
"""
Window that displays the preferences.
"""
- def __init__(self, parent, srp_auth, provider_config, soledad):
+ def __init__(self, parent, srp_auth, provider_config, soledad, domain):
"""
:param parent: parent object of the PreferencesWindow.
:parent type: QWidget
@@ -52,6 +52,8 @@ class PreferencesWindow(QtGui.QDialog):
:type provider_config: ProviderConfig
:param soledad: Soledad instance
:type soledad: Soledad
+ :param domain: the selected domain in the login widget
+ :type domain: unicode
"""
QtGui.QDialog.__init__(self, parent)
self.AUTOMATIC_GATEWAY_LABEL = self.tr("Automatic")
@@ -83,9 +85,6 @@ class PreferencesWindow(QtGui.QDialog):
# check if the user is logged in
if srp_auth is not None and srp_auth.get_token() is not None:
# check if provider has 'mx' ...
- domain = provider_config.get_domain()
- self._select_provider_by_name(domain)
-
if provider_config.provides_mx():
enabled_services = self._settings.get_enabled_services(domain)
mx_name = get_service_display_name(MX_SERVICE)
@@ -111,6 +110,8 @@ class PreferencesWindow(QtGui.QDialog):
"In order to change your password you need to be logged in.")
self._set_password_change_status(msg)
+ self._select_provider_by_name(domain)
+
self.ui.gbPasswordChange.setEnabled(pw_enabled)
def set_soledad_ready(self):
diff --git a/src/leap/bitmask/provider/providerbootstrapper.py b/src/leap/bitmask/provider/providerbootstrapper.py
index 2adf8aa8..f5a2003f 100644
--- a/src/leap/bitmask/provider/providerbootstrapper.py
+++ b/src/leap/bitmask/provider/providerbootstrapper.py
@@ -105,13 +105,13 @@ class ProviderBootstrapper(AbstractBootstrapper):
Checks that the name resolution for the provider name works
"""
leap_assert(self._domain, "Cannot check DNS without a domain")
- logger.debug("Checking name resolution for %s" % (self._domain))
+ logger.debug("Checking name resolution for %r" % (self._domain))
# We don't skip this check, since it's basic for the whole
# system to work
# err --- but we can do it after a failure, to diagnose what went
# wrong. Right now we're just adding connection overhead. -- kali
- socket.gethostbyname(self._domain)
+ socket.gethostbyname(self._domain.encode('idna'))
def _check_https(self, *args):
"""
@@ -119,7 +119,7 @@ class ProviderBootstrapper(AbstractBootstrapper):
checks out
"""
leap_assert(self._domain, "Cannot check HTTPS without a domain")
- logger.debug("Checking https for %s" % (self._domain))
+ logger.debug("Checking https for %r" % (self._domain))
# We don't skip this check, since it's basic for the whole
# system to work.
@@ -131,8 +131,8 @@ class ProviderBootstrapper(AbstractBootstrapper):
verify = self.verify.encode(sys.getfilesystemencoding())
try:
- res = self._session.get("https://%s" % (self._domain,),
- verify=verify,
+ uri = "https://{0}".format(self._domain.encode('idna'))
+ res = self._session.get(uri, verify=verify,
timeout=REQUEST_TIMEOUT)
res.raise_for_status()
except requests.exceptions.SSLError as exc:
@@ -154,17 +154,17 @@ class ProviderBootstrapper(AbstractBootstrapper):
"""
leap_assert(self._domain,
"Cannot download provider info without a domain")
- logger.debug("Downloading provider info for %s" % (self._domain))
+ logger.debug("Downloading provider info for %r" % (self._domain))
# --------------------------------------------------------------
# TODO factor out with the download routines in services.
# Watch out! We're handling the verify paramenter differently here.
headers = {}
+ domain = self._domain.encode(sys.getfilesystemencoding())
provider_json = os.path.join(util.get_path_prefix(),
- "leap",
- "providers",
- self._domain, "provider.json")
+ "leap", "providers", domain,
+ "provider.json")
mtime = get_mtime(provider_json)
if self._download_if_needed and mtime:
@@ -190,7 +190,7 @@ class ProviderBootstrapper(AbstractBootstrapper):
logger.debug("Requesting for provider.json... "
"uri: {0}, verify: {1}, headers: {2}".format(
uri, verify, headers))
- res = self._session.get(uri, verify=verify,
+ res = self._session.get(uri.encode('idna'), verify=verify,
headers=headers, timeout=REQUEST_TIMEOUT)
res.raise_for_status()
logger.debug("Request status code: {0}".format(res.status_code))
@@ -206,10 +206,8 @@ class ProviderBootstrapper(AbstractBootstrapper):
provider_config = ProviderConfig()
provider_config.load(data=provider_definition, mtime=mtime)
- provider_config.save(["leap",
- "providers",
- self._domain,
- "provider.json"])
+ provider_config.save(["leap", "providers",
+ domain, "provider.json"])
api_version = provider_config.get_api_version()
if SupportedAPIs.supports(api_version):
@@ -228,7 +226,7 @@ class ProviderBootstrapper(AbstractBootstrapper):
Populates the check queue.
:param domain: domain to check
- :type domain: str
+ :type domain: unicode
:param download_if_needed: if True, makes the checks do not
overwrite already downloaded data
@@ -271,7 +269,7 @@ class ProviderBootstrapper(AbstractBootstrapper):
leap_assert(self._provider_config, "Cannot download the ca cert "
"without a provider config!")
- logger.debug("Downloading ca cert for %s at %s" %
+ logger.debug("Downloading ca cert for %r at %r" %
(self._domain, self._provider_config.get_ca_cert_uri()))
if not self._should_proceed_cert():
@@ -302,7 +300,7 @@ class ProviderBootstrapper(AbstractBootstrapper):
leap_assert(self._provider_config, "Cannot check the ca cert "
"without a provider config!")
- logger.debug("Checking ca fingerprint for %s and cert %s" %
+ logger.debug("Checking ca fingerprint for %r and cert %r" %
(self._domain,
self._provider_config.get_ca_cert_path()))
diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py
index 16ed4cc0..09a3d257 100644
--- a/src/leap/bitmask/services/eip/eipconfig.py
+++ b/src/leap/bitmask/services/eip/eipconfig.py
@@ -33,17 +33,25 @@ from leap.common.check import leap_assert, leap_assert_type
logger = logging.getLogger(__name__)
-def get_eipconfig_path(domain):
+def get_eipconfig_path(domain, relative=True):
"""
- Returns relative path for EIP config.
+ Returns relative or absolute path for EIP config.
:param domain: the domain to which this eipconfig belongs to.
:type domain: str
+ :param relative: defines whether the path should be relative or absolute.
+ :type relative: bool
:returns: the path
:rtype: str
"""
leap_assert(domain is not None, "get_eipconfig_path: We need a domain")
- return os.path.join("leap", "providers", domain, "eip-service.json")
+
+ path = os.path.join("leap", "providers", domain, "eip-service.json")
+
+ if not relative:
+ path = os.path.join(get_path_prefix(), path)
+
+ return path
def load_eipconfig_if_needed(provider_config, eip_config, domain):
diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
index d02f6f96..d24e7ae7 100644
--- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py
+++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
@@ -77,7 +77,7 @@ def _try_to_launch_agent():
Tries to launch a polkit daemon.
"""
env = None
- if flags.STANDALONE is True:
+ if flags.STANDALONE:
env = {"PYTHONPATH": os.path.abspath('../../../../lib/')}
try:
# We need to quote the command because subprocess call
@@ -148,18 +148,21 @@ class LinuxVPNLauncher(VPNLauncher):
def missing_other_files(kls):
"""
'Extend' the VPNLauncher's missing_other_files to check if the polkit
- files is outdated. If the polkit file that is in OTHER_FILES exists but
- is not up to date, it is added to the missing list.
+ files is outdated, in the case of an standalone bundle.
+ If the polkit file that is in OTHER_FILES exists but is not up to date,
+ it is added to the missing list.
:returns: a list of missing files
:rtype: list of str
"""
# we use `super` in order to send the class to use
missing = super(LinuxVPNLauncher, kls).missing_other_files()
- polkit_file = LinuxPolicyChecker.get_polkit_path()
- if polkit_file not in missing:
- if privilege_policies.is_policy_outdated(kls.OPENVPN_BIN_PATH):
- missing.append(polkit_file)
+
+ if flags.STANDALONE:
+ polkit_file = LinuxPolicyChecker.get_polkit_path()
+ if polkit_file not in missing:
+ if privilege_policies.is_policy_outdated(kls.OPENVPN_BIN_PATH):
+ missing.append(polkit_file)
return missing
diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py
index 07497814..99cae7f9 100644
--- a/src/leap/bitmask/services/eip/vpnlauncher.py
+++ b/src/leap/bitmask/services/eip/vpnlauncher.py
@@ -147,7 +147,8 @@ class VPNLauncher(object):
args = []
args += [
- '--setenv', "LEAPOPENVPN", "1"
+ '--setenv', "LEAPOPENVPN", "1",
+ '--nobind'
]
if openvpn_verb is not None:
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index e8c7e9ce..d078ae96 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -196,7 +196,7 @@ class SoledadBootstrapper(AbstractBootstrapper):
leap_assert(not sameProxiedObjects(self._soledad, None),
"Null soledad, error while initializing")
- self.deferred = deferToThread(self._do_soledad_sync)
+ self._do_soledad_sync()
def _do_soledad_sync(self):
"""