summaryrefslogtreecommitdiff
path: root/src/leap/bitmask
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask')
-rw-r--r--src/leap/bitmask/app.py19
-rw-r--r--src/leap/bitmask/config/__init__.py0
-rw-r--r--src/leap/bitmask/config/leapsettings.py63
-rw-r--r--src/leap/bitmask/crypto/srpauth.py18
-rw-r--r--src/leap/bitmask/gui/eip_status.py2
-rw-r--r--src/leap/bitmask/gui/login.py4
-rw-r--r--src/leap/bitmask/gui/mail_status.py19
-rw-r--r--src/leap/bitmask/gui/mainwindow.py337
-rw-r--r--src/leap/bitmask/gui/ui/eip_status.ui4
-rw-r--r--src/leap/bitmask/gui/ui/eippreferences.ui10
-rw-r--r--src/leap/bitmask/gui/ui/login.ui230
-rw-r--r--src/leap/bitmask/gui/ui/mail_status.ui73
-rw-r--r--src/leap/bitmask/gui/ui/mainwindow.ui44
-rw-r--r--src/leap/bitmask/gui/ui/wizard.ui8
-rw-r--r--src/leap/bitmask/gui/wizard.py3
-rw-r--r--src/leap/bitmask/services/eip/connection.py1
-rw-r--r--src/leap/bitmask/services/eip/linuxvpnlauncher.py10
-rw-r--r--src/leap/bitmask/services/eip/vpnlauncher.py26
-rw-r--r--src/leap/bitmask/services/eip/vpnprocess.py96
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py8
-rw-r--r--src/leap/bitmask/util/leap_argparse.py3
-rw-r--r--src/leap/bitmask/util/leap_log_handler.py3
22 files changed, 644 insertions, 337 deletions
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py
index c1859478..40a77075 100644
--- a/src/leap/bitmask/app.py
+++ b/src/leap/bitmask/app.py
@@ -54,6 +54,7 @@ from leap.bitmask.util import leap_argparse
from leap.bitmask.util import log_silencer
from leap.bitmask.util.leap_log_handler import LeapLogHandler
from leap.bitmask.util.streamtologger import StreamToLogger
+from leap.bitmask.platform_init import IS_WIN
from leap.common.events import server as event_server
import codecs
@@ -99,7 +100,8 @@ def add_logger_handlers(debug=False, logfile=None):
logger = logging.getLogger(name='leap')
logger.setLevel(level)
- log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+ log_format = ('%(asctime)s - %(name)s:%(funcName)s:L#%(lineno)s '
+ '- %(levelname)s - %(message)s')
formatter = logging.Formatter(log_format)
# Console handler
@@ -140,12 +142,15 @@ def replace_stdout_stderr_with_logging(logger):
- the twisted log output
with a custom one that writes to the logger.
"""
- sys.stdout = StreamToLogger(logger, logging.DEBUG)
- sys.stderr = StreamToLogger(logger, logging.ERROR)
-
- # Replace twisted's logger to use our custom output.
- from twisted.python import log
- log.startLogging(sys.stdout)
+ # Disabling this on windows since it breaks ALL THE THINGS
+ # The issue for this is #4149
+ if not IS_WIN:
+ sys.stdout = StreamToLogger(logger, logging.DEBUG)
+ sys.stderr = StreamToLogger(logger, logging.ERROR)
+
+ # Replace twisted's logger to use our custom output.
+ from twisted.python import log
+ log.startLogging(sys.stdout)
def main():
diff --git a/src/leap/bitmask/config/__init__.py b/src/leap/bitmask/config/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/leap/bitmask/config/__init__.py
diff --git a/src/leap/bitmask/config/leapsettings.py b/src/leap/bitmask/config/leapsettings.py
index 4660535a..c524425e 100644
--- a/src/leap/bitmask/config/leapsettings.py
+++ b/src/leap/bitmask/config/leapsettings.py
@@ -62,13 +62,14 @@ class LeapSettings(object):
GEOMETRY_KEY = "Geometry"
WINDOWSTATE_KEY = "WindowState"
USER_KEY = "User"
- PROPERPROVIDER_KEY = "ProperProvider"
+ PROVIDER_KEY = "Provider"
REMEMBER_KEY = "RememberUserAndPass"
DEFAULTPROVIDER_KEY = "DefaultProvider"
AUTOSTARTEIP_KEY = "AutoStartEIP"
ALERTMISSING_KEY = "AlertMissingScripts"
GATEWAY_KEY = "Gateway"
PINNED_KEY = "Pinned"
+ SKIPFIRSTRUN_KEY = "SkipFirstRun"
# values
GATEWAY_AUTOMATIC = "Automatic"
@@ -241,6 +242,24 @@ class LeapSettings(object):
leap_assert(len(user) > 0, "We cannot save an empty user")
self._settings.setValue(self.USER_KEY, user)
+ def get_provider(self):
+ """
+ Returns the configured provider to remember, None if there isn't one
+
+ :rtype: str or None
+ """
+ return self._settings.value(self.PROVIDER_KEY, None)
+
+ def set_provider(self, provider):
+ """
+ Saves the provider to remember
+
+ :param provider: provider name to remember
+ :type provider: str
+ """
+ leap_assert(len(provider) > 0, "We cannot save an empty provider")
+ self._settings.setValue(self.PROVIDER_KEY, provider)
+
def get_remember(self):
"""
Returns the value of the remember selection.
@@ -260,29 +279,6 @@ class LeapSettings(object):
leap_assert_type(remember, bool)
self._settings.setValue(self.REMEMBER_KEY, remember)
- # TODO: make this scale with multiple providers, we are assuming
- # just one for now
- def get_properprovider(self):
- """
- Returns True if there is a properly configured provider.
-
- .. note:: this assumes only one provider for now.
-
- :rtype: bool
- """
- return to_bool(self._settings.value(self.PROPERPROVIDER_KEY, False))
-
- def set_properprovider(self, properprovider):
- """
- Sets whether the app should automatically login.
-
- :param properprovider: True if the provider is properly configured,
- False otherwise.
- :type properprovider: bool
- """
- leap_assert_type(properprovider, bool)
- self._settings.setValue(self.PROPERPROVIDER_KEY, properprovider)
-
def get_defaultprovider(self):
"""
Returns the default provider to be used for autostarting EIP
@@ -338,3 +334,22 @@ class LeapSettings(object):
"""
leap_assert_type(value, bool)
self._settings.setValue(self.ALERTMISSING_KEY, value)
+
+ def get_skip_first_run(self):
+ """
+ Gets the setting for skip running the first run wizard.
+
+ :returns: if the first run wizard should be skipped or not
+ :rtype: bool
+ """
+ return to_bool(self._settings.value(self.SKIPFIRSTRUN_KEY, False))
+
+ def set_skip_first_run(self, skip):
+ """
+ Gets the setting for skip the first run wizard.
+
+ :param skip: if the first run wizard should be skipped or not
+ :type skip: bool
+ """
+ leap_assert_type(skip, bool)
+ self._settings.setValue(self.SKIPFIRSTRUN_KEY, skip)
diff --git a/src/leap/bitmask/crypto/srpauth.py b/src/leap/bitmask/crypto/srpauth.py
index cbff4b49..47ed21b0 100644
--- a/src/leap/bitmask/crypto/srpauth.py
+++ b/src/leap/bitmask/crypto/srpauth.py
@@ -25,6 +25,7 @@ import json
#this error is raised from requests
from simplejson.decoder import JSONDecodeError
from functools import partial
+from requests.adapters import HTTPAdapter
from PySide import QtCore
from twisted.internet import threads
@@ -154,7 +155,8 @@ class SRPAuth(QtCore.QObject):
self._ng = self._srp.NG_1024
# **************************************************** #
- self._session = self._fetcher.session()
+ self._reset_session()
+
self._session_id = None
self._session_id_lock = QtCore.QMutex()
self._uid = None
@@ -172,6 +174,18 @@ class SRPAuth(QtCore.QObject):
self._username = None
self._password = None
+ def _reset_session(self):
+ """
+ Resets the current session and sets max retries to 30.
+ """
+ self._session = self._fetcher.session()
+ # We need to bump the default retries, otherwise logout
+ # fails most of the times
+ # NOTE: This is a workaround for the moment, the server
+ # side seems to return correctly every time, but it fails
+ # on the client end.
+ self._session.mount('https://', HTTPAdapter(max_retries=30))
+
def _safe_unhexlify(self, val):
"""
Rounds the val to a multiple of 2 and returns the
@@ -508,7 +522,7 @@ class SRPAuth(QtCore.QObject):
self._username = username
self._password = password
- self._session = self._fetcher.session()
+ self._reset_session()
d = threads.deferToThread(self._authentication_preprocessing,
username=username,
diff --git a/src/leap/bitmask/gui/eip_status.py b/src/leap/bitmask/gui/eip_status.py
index 946eaa4e..77685cd3 100644
--- a/src/leap/bitmask/gui/eip_status.py
+++ b/src/leap/bitmask/gui/eip_status.py
@@ -424,6 +424,8 @@ class EIPStatusWidget(QtGui.QWidget):
tray_message = self.tr("Encrypted Internet: ON")
selected_pixmap = self.CONNECTED_ICON
selected_pixmap_tray = self.CONNECTED_ICON_TRAY
+ self._eip_status = 'ON'
+ self._update_systray_tooltip()
self.set_eip_icon(selected_pixmap)
self._systray.setIcon(QtGui.QIcon(selected_pixmap_tray))
diff --git a/src/leap/bitmask/gui/login.py b/src/leap/bitmask/gui/login.py
index 582f26be..ac34fe23 100644
--- a/src/leap/bitmask/gui/login.py
+++ b/src/leap/bitmask/gui/login.py
@@ -94,6 +94,9 @@ class LoginWidget(QtGui.QWidget):
self.ui.clblErrorMsg.hide()
self.ui.clblErrorMsg.clicked.connect(self.ui.clblErrorMsg.hide)
+ self.ui.lnUser.textEdited.connect(self.ui.clblErrorMsg.hide)
+ self.ui.lnPassword.textEdited.connect(self.ui.clblErrorMsg.hide)
+
def _remember_state_changed(self, state):
"""
Saves the remember state in the LeapSettings
@@ -294,6 +297,7 @@ class LoginWidget(QtGui.QWidget):
self.set_enabled(False)
self.ui.clblErrorMsg.hide()
+ self._settings.set_provider(provider)
if self.get_remember() and has_keyring():
# in the keyring and in the settings
# we store the value 'usename@provider'
diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py
index ab9052d7..83533666 100644
--- a/src/leap/bitmask/gui/mail_status.py
+++ b/src/leap/bitmask/gui/mail_status.py
@@ -35,7 +35,6 @@ class MailStatusWidget(QtGui.QWidget):
"""
Status widget that displays the state of the LEAP Mail service
"""
- eip_connection_connected = QtCore.Signal()
_soledad_event = QtCore.Signal(object)
_smtp_event = QtCore.Signal(object)
_imap_event = QtCore.Signal(object)
@@ -193,6 +192,17 @@ class MailStatusWidget(QtGui.QWidget):
leap_assert_type(action_mail_status, QtGui.QAction)
self._action_mail_status = action_mail_status
+ def set_soledad_failed(self):
+ """
+ SLOT
+ TRIGGER:
+ SoledadBootstrapper.soledad_failed
+
+ This method is called whenever soledad has a failure.
+ """
+ msg = self.tr("There was an unexpected problem with Soledad.")
+ self._set_mail_status(msg, ready=-1)
+
def _set_mail_status(self, status, ready=0):
"""
Sets the Mail status in the label and in the tray icon.
@@ -377,8 +387,11 @@ class MailStatusWidget(QtGui.QWidget):
self._set_mail_status(self.tr("Failed"))
elif req.event == proto.IMAP_UNREAD_MAIL:
if self._smtp_started and self._imap_started:
- self._set_mail_status(self.tr("%s Unread Emails") %
- (req.content), ready=2)
+ if req.content != "0":
+ self._set_mail_status(self.tr("%s Unread Emails") %
+ (req.content,), ready=2)
+ else:
+ self._set_mail_status("", ready=2)
else:
leap_assert(False, # XXX ???
"Don't know how to handle this state: %s"
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index 84f09fd9..f5631c69 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -174,10 +174,12 @@ class MainWindow(QtGui.QMainWindow):
self._eip_connection = EIPConnection()
+ # XXX this should be handled by EIP Conductor
self._eip_connection.qtsigs.connecting_signal.connect(
self._start_eip)
self._eip_connection.qtsigs.disconnecting_signal.connect(
self._stop_eip)
+
self._eip_status.eip_connection_connected.connect(
self._on_eip_connected)
self.eip_needs_login.connect(
@@ -228,13 +230,22 @@ class MainWindow(QtGui.QMainWindow):
self._eip_intermediate_stage)
self._eip_bootstrapper.download_client_certificate.connect(
self._finish_eip_bootstrap)
+
self._vpn = VPN(openvpn_verb=openvpn_verb)
+
+ # connect vpn process signals
self._vpn.qtsigs.state_changed.connect(
self._eip_status.update_vpn_state)
self._vpn.qtsigs.status_changed.connect(
self._eip_status.update_vpn_status)
self._vpn.qtsigs.process_finished.connect(
self._eip_finished)
+ self._vpn.qtsigs.network_unreachable.connect(
+ self._on_eip_network_unreachable)
+ self._vpn.qtsigs.process_restart_tls.connect(
+ self._do_eip_restart)
+ self._vpn.qtsigs.process_restart_ping.connect(
+ self._do_eip_restart)
self._soledad_bootstrapper = SoledadBootstrapper()
self._soledad_bootstrapper.download_config.connect(
@@ -243,8 +254,8 @@ class MainWindow(QtGui.QMainWindow):
self._soledad_bootstrapped_stage)
self._soledad_bootstrapper.soledad_timeout.connect(
self._retry_soledad_connection)
- # XXX missing connect to soledad_failed (signal unrecoverable to user)
- # TODO wait until chiiph ui refactor.
+ self._soledad_bootstrapper.soledad_failed.connect(
+ self._mail_status.set_soledad_failed)
self._smtp_bootstrapper = SMTPBootstrapper()
self._smtp_bootstrapper.download_config.connect(
@@ -258,7 +269,7 @@ class MainWindow(QtGui.QMainWindow):
self._launch_wizard)
if IS_MAC:
- self.ui.menuFile.menuAction().setText(self.tr("Util"))
+ self.ui.menuFile.menuAction().setText(self.tr("File"))
self.raise_window.connect(self._do_raise_mainwindow)
@@ -267,8 +278,9 @@ class MainWindow(QtGui.QMainWindow):
self._systray = None
+ # XXX separate actions into a different
+ # module.
self._action_mail_status = QtGui.QAction(self.tr("Mail is OFF"), self)
- self._action_mail_status.setEnabled(False)
self._mail_status.set_action_mail_status(self._action_mail_status)
self._action_eip_startstop = QtGui.QAction("", self)
@@ -286,6 +298,11 @@ class MainWindow(QtGui.QMainWindow):
self.ui.lblNewUpdates.setVisible(False)
self.ui.btnMore.setVisible(False)
+ #########################################
+ # We hide this in height temporarily too
+ self.ui.lblNewUpdates.resize(0, 0)
+ self.ui.btnMore.resize(0, 0)
+ #########################################
self.ui.btnMore.clicked.connect(self._updates_details)
# Services signals/slots connection
@@ -352,8 +369,12 @@ class MainWindow(QtGui.QMainWindow):
finishing.
"""
if self._wizard_firstrun:
- self._settings.set_properprovider(False)
- 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:
self._finish_init()
@@ -381,6 +402,7 @@ class MainWindow(QtGui.QMainWindow):
if IS_MAC:
self._wizard.raise_()
self._wizard.finished.connect(self._wizard_finished)
+ self._settings.set_skip_first_run(True)
def _wizard_finished(self):
"""
@@ -399,6 +421,8 @@ class MainWindow(QtGui.QMainWindow):
:return: a logging handler or None
:rtype: LeapLogHandler or None
"""
+ # TODO this can be a function, does not need
+ # to be a method.
leap_logger = logging.getLogger('leap')
for h in leap_logger.handlers:
if isinstance(h, LeapLogHandler):
@@ -464,6 +488,10 @@ class MainWindow(QtGui.QMainWindow):
"""
self._soledad_ready = True
+ #
+ # updates
+ #
+
def _new_updates_available(self, req):
"""
Callback for the new updates event
@@ -553,9 +581,13 @@ class MainWindow(QtGui.QMainWindow):
self._login_widget.set_password(possible_password)
self._login()
self._wizard = None
- self._settings.set_properprovider(True)
else:
self._try_autostart_eip()
+
+ domain = self._settings.get_provider()
+ if domain is not None:
+ self._login_widget.select_provider_by_name(domain)
+
if not self._settings.get_remember():
# nothing to do here
return
@@ -573,9 +605,6 @@ class MainWindow(QtGui.QMainWindow):
# fill the username
self._login_widget.set_user(username)
- # select the configured provider in the combo box
- self._login_widget.select_provider_by_name(domain)
-
self._login_widget.set_remember(True)
saved_password = None
@@ -591,43 +620,9 @@ class MainWindow(QtGui.QMainWindow):
saved_password.decode("utf8"))
self._login()
- def _try_autostart_eip(self):
- """
- Tries to autostart EIP
- """
- settings = self._settings
-
- should_autostart = settings.get_autostart_eip()
- if not should_autostart:
- logger.debug('Will not autostart EIP since it is setup '
- 'to not to do it')
- self.eip_needs_login.emit()
- return
-
- default_provider = settings.get_defaultprovider()
-
- if default_provider is None:
- logger.info("Cannot autostart Encrypted Internet because there is "
- "no default provider configured")
- self.eip_needs_login.emit()
- return
-
- self._enabled_services = settings.get_enabled_services(
- default_provider)
-
- loaded = self._provisional_provider_config.load(
- provider.get_provider_path(default_provider))
- if loaded:
- # 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._download_eip_config()
- else:
- # XXX: Display a proper message to the user
- self.eip_needs_login.emit()
- logger.error("Unable to load %s config, cannot autostart." %
- (default_provider,))
+ #
+ # systray
+ #
def _show_systray(self):
"""
@@ -649,7 +644,7 @@ class MainWindow(QtGui.QMainWindow):
eip_menu = systrayMenu.addMenu(self.tr("Encrypted Internet: OFF"))
eip_menu.addAction(self._action_eip_startstop)
self._eip_status.set_eip_status_menu(eip_menu)
-
+ systrayMenu.addSeparator()
systrayMenu.addAction(self._action_mail_status)
systrayMenu.addSeparator()
systrayMenu.addAction(self.ui.action_quit)
@@ -799,8 +794,8 @@ class MainWindow(QtGui.QMainWindow):
"""
providers = self._settings.get_configured_providers()
has_provider_on_disk = len(providers) != 0
- is_proper_provider = self._settings.get_properprovider()
- return not (has_provider_on_disk and is_proper_provider)
+ skip_first_run = self._settings.get_skip_first_run()
+ return not (has_provider_on_disk and skip_first_run)
def _download_provider_config(self):
"""
@@ -951,6 +946,7 @@ class MainWindow(QtGui.QMainWindow):
"""
self._login_widget.logged_in()
+ self.ui.lblLoginProvider.setText(self._provider_config.get_name())
self._enabled_services = self._settings.get_enabled_services(
self._provider_config.get_domain())
@@ -971,7 +967,11 @@ class MainWindow(QtGui.QMainWindow):
self._download_eip_config()
+ ###################################################################
+ # Service control methods: soledad
+
def _soledad_intermediate_stage(self, data):
+ # TODO missing param docstring
"""
SLOT
TRIGGERS:
@@ -1222,16 +1222,53 @@ class MainWindow(QtGui.QMainWindow):
signal that currently is beeing processed under status_panel.
After the refactor to EIPConductor this should not be necessary.
"""
- logger.debug('EIP connected signal received ...')
self._eip_connection.qtsigs.connected_signal.emit()
+ def _try_autostart_eip(self):
+ """
+ Tries to autostart EIP
+ """
+ settings = self._settings
+
+ should_autostart = settings.get_autostart_eip()
+ if not should_autostart:
+ logger.debug('Will not autostart EIP since it is setup '
+ 'to not to do it')
+ self.eip_needs_login.emit()
+ return
+
+ default_provider = settings.get_defaultprovider()
+
+ if default_provider is None:
+ logger.info("Cannot autostart Encrypted Internet because there is "
+ "no default provider configured")
+ self.eip_needs_login.emit()
+ return
+
+ self._enabled_services = settings.get_enabled_services(
+ default_provider)
+
+ loaded = self._provisional_provider_config.load(
+ provider.get_provider_path(default_provider))
+ if loaded:
+ # 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._download_eip_config()
+ else:
+ # XXX: Display a proper message to the user
+ self.eip_needs_login.emit()
+ logger.error("Unable to load %s config, cannot autostart." %
+ (default_provider,))
+
@QtCore.Slot()
def _start_eip(self):
"""
SLOT
TRIGGERS:
- self._eip_status.start_eip
- self._action_eip_startstop.triggered
+ self._eip_connection.qtsigs.do_connect_signal
+ (via state machine)
or called from _finish_eip_bootstrap
Starts EIP
@@ -1332,8 +1369,8 @@ class MainWindow(QtGui.QMainWindow):
"""
SLOT
TRIGGERS:
- self._eip_status.stop_eip
- self._action_eip_startstop.triggered
+ self._eip_connection.qtsigs.do_disconnect_signal
+ (via state machine)
or called from _eip_finished
Stops vpn process and makes gui adjustments to reflect
@@ -1357,14 +1394,100 @@ class MainWindow(QtGui.QMainWindow):
self._get_best_provider_config().get_domain()))
self._eip_status.eip_stopped()
+ @QtCore.Slot()
+ def _on_eip_network_unreachable(self):
+ # XXX Should move to EIP Conductor
+ """
+ SLOT
+ TRIGGERS:
+ self._eip_connection.qtsigs.network_unreachable
+
+ Displays a "network unreachable" error in the EIP status panel.
+ """
+ self._eip_status.set_eip_status(self.tr("Network is unreachable"),
+ error=True)
+ self._eip_status.set_eip_status_icon("error")
+
+ @QtCore.Slot()
+ def _do_eip_restart(self):
+ # XXX Should move to EIP Conductor
+ """
+ SLOT
+ self._eip_connection.qtsigs.process_restart
+
+ Restart the connection.
+ """
+ # for some reason, emitting the do_disconnect/do_connect
+ # signals hangs the UI.
+ self._stop_eip()
+ QtCore.QTimer.singleShot(2000, self._start_eip)
+
def _set_eipstatus_off(self, error=True):
"""
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_icon("error")
+ def _eip_finished(self, exitCode):
+ """
+ SLOT
+ TRIGGERS:
+ self._vpn.process_finished
+
+ Triggered when the EIP/VPN process finishes to set the UI
+ accordingly.
+
+ Ideally we would have the right exit code here,
+ but the use of different wrappers (pkexec, cocoasudo) swallows
+ the openvpn exit code so we get zero exit in some cases where we
+ shouldn't. As a workaround we just use a flag to indicate
+ a purposeful switch off, and mark everything else as unexpected.
+
+ In the near future we should trigger a native notification from here,
+ since the user really really wants to know she is unprotected asap.
+ And the right thing to do will be to fail-close.
+
+ :param exitCode: the exit code of the eip process.
+ :type exitCode: int
+ """
+ # TODO move to EIPConductor.
+ # TODO Add error catching to the openvpn log observer
+ # so we can have a more precise idea of which type
+ # of error did we have (server side, local problem, etc)
+
+ logger.info("VPN process finished with exitCode %s..."
+ % (exitCode,))
+
+ qtsigs = self._eip_connection.qtsigs
+ signal = qtsigs.disconnected_signal
+
+ # 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)
+ 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)
+ signal = qtsigs.connection_died_signal
+
+ if exitCode == 0 and IS_MAC:
+ # XXX remove this warning after I fix cocoasudo.
+ logger.warning("The above exit code MIGHT BE WRONG.")
+
+ # We emit signals to trigger transitions in the state machine:
+ signal.emit()
+
+ # eip boostrapping, config etc...
+
def _download_eip_config(self):
"""
Starts the EIP bootstrapping sequence
@@ -1426,7 +1549,25 @@ class MainWindow(QtGui.QMainWindow):
"Configuration."),
error=True)
- # end eip methods -------------------------------------------
+ def _eip_intermediate_stage(self, data):
+ # TODO missing param
+ """
+ SLOT
+ TRIGGERS:
+ self._eip_bootstrapper.download_config
+
+ If there was a problem, displays it, otherwise it does nothing.
+ This is used for intermediate bootstrapping stages, in case
+ they fail.
+ """
+ passed = data[self._provider_bootstrapper.PASSED_KEY]
+ if not passed:
+ self._login_widget.set_status(
+ self.tr("Unable to connect: Problem with provider"))
+ logger.error(data[self._provider_bootstrapper.ERROR_KEY])
+ self._already_started_eip = False
+
+ # end of EIP methods ---------------------------------------------
def _get_best_provider_config(self):
"""
@@ -1469,6 +1610,7 @@ class MainWindow(QtGui.QMainWindow):
self.logout.emit()
def _done_logging_out(self, ok, message):
+ # TODO missing params in docstring
"""
SLOT
TRIGGER: self._srp_auth.logout_finished
@@ -1477,6 +1619,7 @@ class MainWindow(QtGui.QMainWindow):
logging out
"""
self._login_widget.done_logout()
+ self.ui.lblLoginProvider.setText(self.tr("Login"))
if ok:
self._logged_user = None
@@ -1489,6 +1632,7 @@ class MainWindow(QtGui.QMainWindow):
error=True)
def _intermediate_stage(self, data):
+ # TODO this method name is confusing as hell.
"""
SLOT
TRIGGERS:
@@ -1508,80 +1652,9 @@ class MainWindow(QtGui.QMainWindow):
self.tr("Unable to connect: Problem with provider"))
logger.error(data[self._provider_bootstrapper.ERROR_KEY])
- def _eip_intermediate_stage(self, data):
- """
- SLOT
- TRIGGERS:
- self._eip_bootstrapper.download_config
-
- If there was a problem, displays it, otherwise it does nothing.
- This is used for intermediate bootstrapping stages, in case
- they fail.
- """
- passed = data[self._provider_bootstrapper.PASSED_KEY]
- if not passed:
- self._login_widget.set_status(
- self.tr("Unable to connect: Problem with provider"))
- logger.error(data[self._provider_bootstrapper.ERROR_KEY])
- self._already_started_eip = False
-
- def _eip_finished(self, exitCode):
- """
- SLOT
- TRIGGERS:
- self._vpn.process_finished
-
- Triggered when the EIP/VPN process finishes to set the UI
- accordingly.
- """
- # TODO move to EIPConductor.
- logger.info("VPN process finished with exitCode %s..."
- % (exitCode,))
-
- # Ideally we would have the right exit code here,
- # but the use of different wrappers (pkexec, cocoasudo) swallows
- # the openvpn exit code so we get zero exit in some cases where we
- # shouldn't. As a workaround we just use a flag to indicate
- # a purposeful switch off, and mark everything else as unexpected.
-
- # In the near future we should trigger a native notification from here,
- # since the user really really wants to know she is unprotected asap.
- # And the right thing to do will be to fail-close.
-
- # TODO we should have a way of parsing the latest lines in the vpn
- # log buffer so we can have a more precise idea of which type
- # of error did we have (server side, local problem, etc)
-
- qtsigs = self._eip_connection.qtsigs
- signal = qtsigs.disconnected_signal
-
- # 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)
- 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)
- signal = qtsigs.connection_died_signal
-
- if exitCode == 0 and IS_MAC:
- # XXX remove this warning after I fix cocoasudo.
- logger.warning("The above exit code MIGHT BE WRONG.")
-
- # XXX verify that the logic kees the same w/o the abnormal flag
- # after the refactor to EIPConnection has been completed
- # (eipconductor taking the most of the logic under transitions
- # that right now are handled under status_panel)
- #self._stop_eip(abnormal)
-
- # We emit signals to trigger transitions in the state machine:
- signal.emit()
+ #
+ # window handling methods
+ #
def _on_raise_window_event(self, req):
"""
@@ -1607,6 +1680,10 @@ class MainWindow(QtGui.QMainWindow):
if IS_MAC:
self.raise_()
+ #
+ # cleanup and quit methods
+ #
+
def _cleanup_pidfiles(self):
"""
Removes lockfiles on a clean shutdown.
diff --git a/src/leap/bitmask/gui/ui/eip_status.ui b/src/leap/bitmask/gui/ui/eip_status.ui
index 27df3f31..25831118 100644
--- a/src/leap/bitmask/gui/ui/eip_status.ui
+++ b/src/leap/bitmask/gui/ui/eip_status.ui
@@ -94,8 +94,8 @@
<widget class="QLabel" name="lblVPNStatusIcon">
<property name="maximumSize">
<size>
- <width>16</width>
- <height>16</height>
+ <width>24</width>
+ <height>24</height>
</size>
</property>
<property name="text">
diff --git a/src/leap/bitmask/gui/ui/eippreferences.ui b/src/leap/bitmask/gui/ui/eippreferences.ui
index 9493d330..cc77c82e 100644
--- a/src/leap/bitmask/gui/ui/eippreferences.ui
+++ b/src/leap/bitmask/gui/ui/eippreferences.ui
@@ -6,12 +6,12 @@
<rect>
<x>0</x>
<y>0</y>
- <width>398</width>
- <height>262</height>
+ <width>435</width>
+ <height>273</height>
</rect>
</property>
<property name="windowTitle">
- <string>EIP Preferences</string>
+ <string>Encrypted Internet Preferences</string>
</property>
<property name="windowIcon">
<iconset resource="../../../../../data/resources/mainwindow.qrc">
@@ -88,7 +88,7 @@
<item row="0" column="0">
<widget class="QGroupBox" name="gbAutomaticEIP">
<property name="title">
- <string>Automatic EIP start</string>
+ <string>Automatic Encrypted Internet start</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
@@ -126,7 +126,7 @@
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
- <string>Enable Automatic start of EIP</string>
+ <string>Enable Automatic start:</string>
</property>
<property name="checked">
<bool>true</bool>
diff --git a/src/leap/bitmask/gui/ui/login.ui b/src/leap/bitmask/gui/ui/login.ui
index a1842608..e7ca1652 100644
--- a/src/leap/bitmask/gui/ui/login.ui
+++ b/src/leap/bitmask/gui/ui/login.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>468</width>
- <height>350</height>
+ <height>363</height>
</rect>
</property>
<property name="sizePolicy">
@@ -32,104 +32,26 @@
<property name="margin">
<number>0</number>
</property>
- <item row="2" column="2" colspan="2">
- <widget class="QWidget" name="logged_widget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
+ <property name="verticalSpacing">
+ <number>-1</number>
+ </property>
+ <item row="2" column="0">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
</property>
- <layout class="QGridLayout" name="gridLayout_5">
- <property name="bottomMargin">
- <number>24</number>
- </property>
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="lblUser">
- <property name="font">
- <font>
- <pointsize>15</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QPushButton" name="btnLogout">
- <property name="text">
- <string>Logout</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <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 row="2" column="0" colspan="2">
- <widget class="QLabel" name="lblLoginStatus">
- <property name="styleSheet">
- <string notr="true">color: rgb(132, 132, 132);
-font: 75 12pt &quot;Lucida Grande&quot;;</string>
- </property>
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="1" column="1" rowspan="2">
- <widget class="QLabel" name="label">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
+ <property name="sizeType">
+ <enum>QSizePolicy::Maximum</enum>
</property>
- <property name="maximumSize">
+ <property name="sizeHint" stdset="0">
<size>
- <width>16777215</width>
- <height>800</height>
+ <width>12</width>
+ <height>0</height>
</size>
</property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/black/32/user.png</pixmap>
- </property>
- <property name="scaledContents">
- <bool>false</bool>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- </widget>
+ </spacer>
</item>
- <item row="1" column="2" colspan="2">
+ <item row="2" column="2" colspan="2">
<widget class="QWidget" name="login_widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -224,21 +146,36 @@ font: 75 12pt &quot;Lucida Grande&quot;;</string>
</layout>
</widget>
</item>
- <item row="1" column="0">
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Maximum</enum>
+ <item row="2" column="1" rowspan="2">
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
- <property name="sizeHint" stdset="0">
+ <property name="maximumSize">
<size>
- <width>12</width>
- <height>0</height>
+ <width>16777215</width>
+ <height>800</height>
</size>
</property>
- </spacer>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/black/32/user.png</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ </widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="ClickableLabel" name="clblErrorMsg">
@@ -259,6 +196,91 @@ font: 75 12pt &quot;Lucida Grande&quot;;</string>
</property>
</widget>
</item>
+ <item row="3" column="2" colspan="2">
+ <widget class="QWidget" name="logged_widget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_5">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>24</number>
+ </property>
+ <item row="1" column="1">
+ <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 row="1" column="0">
+ <widget class="QPushButton" name="btnLogout">
+ <property name="text">
+ <string>Logout</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QLabel" name="lblUser">
+ <property name="font">
+ <font>
+ <pointsize>15</pointsize>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="lblLoginStatus">
+ <property name="styleSheet">
+ <string notr="true">color: rgb(132, 132, 132);
+font: 75 12pt &quot;Lucida Grande&quot;;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>5</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
</layout>
</widget>
<customwidgets>
diff --git a/src/leap/bitmask/gui/ui/mail_status.ui b/src/leap/bitmask/gui/ui/mail_status.ui
index 1327f9e7..22976f39 100644
--- a/src/leap/bitmask/gui/ui/mail_status.ui
+++ b/src/leap/bitmask/gui/ui/mail_status.ui
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
- <height>72</height>
+ <height>79</height>
</rect>
</property>
<property name="sizePolicy">
@@ -20,9 +20,25 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
<item row="0" column="1" rowspan="2">
<layout class="QGridLayout" name="gridLayout_3">
- <item row="1" column="0" colspan="3">
+ <item row="1" column="1">
+ <spacer name="horizontalSpacer_4">
+ <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 row="2" column="0" colspan="3">
<widget class="QLabel" name="lblMailStatus">
<property name="styleSheet">
<string notr="true">color: rgb(80, 80, 80);</string>
@@ -32,7 +48,26 @@
</property>
</widget>
</item>
- <item row="0" column="0">
+ <item row="1" column="3">
+ <widget class="QLabel" name="lblMailStatusIcon">
+ <property name="maximumSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/black/32/off.png</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@@ -45,38 +80,22 @@
</property>
</widget>
</item>
- <item row="0" column="1">
- <spacer name="horizontalSpacer_4">
+ <item row="0" column="0">
+ <spacer name="verticalSpacer">
<property name="orientation">
- <enum>Qt::Horizontal</enum>
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
- <width>40</width>
- <height>20</height>
+ <width>0</width>
+ <height>5</height>
</size>
</property>
</spacer>
</item>
- <item row="0" column="3">
- <widget class="QLabel" name="lblMailStatusIcon">
- <property name="maximumSize">
- <size>
- <width>16</width>
- <height>16</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="pixmap">
- <pixmap resource="../../../../../data/resources/mainwindow.qrc">:/images/black/32/off.png</pixmap>
- </property>
- <property name="scaledContents">
- <bool>true</bool>
- </property>
- </widget>
- </item>
</layout>
</item>
<item row="0" column="0">
diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui
index 920160b8..10c77057 100644
--- a/src/leap/bitmask/gui/ui/mainwindow.ui
+++ b/src/leap/bitmask/gui/ui/mainwindow.ui
@@ -86,13 +86,16 @@
<number>0</number>
</property>
<item>
- <widget class="QWidget" name="widget_2" native="true">
+ <widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="styleSheet">
+ <string notr="true">QFrame{background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(160, 160, 160, 128), stop:1 rgba(255, 255, 255, 0));}</string>
+ </property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>24</number>
@@ -109,6 +112,9 @@
<bold>true</bold>
</font>
</property>
+ <property name="styleSheet">
+ <string notr="true">background-color: rgba(255, 255, 255, 0);</string>
+ </property>
<property name="text">
<string>Encrypted Internet</string>
</property>
@@ -122,6 +128,9 @@
<height>20</height>
</size>
</property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
<property name="text">
<string/>
</property>
@@ -167,13 +176,21 @@
</widget>
</item>
<item>
- <widget class="QWidget" name="widget" native="true">
+ <widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QFrame{
+background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(160, 160, 160, 128), stop:1 rgba(255, 255, 255, 0));
+}</string>
+ </property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>24</number>
@@ -190,6 +207,9 @@
<bold>true</bold>
</font>
</property>
+ <property name="styleSheet">
+ <string notr="true">background-color: rgba(255, 255, 255, 0);</string>
+ </property>
<property name="text">
<string>Login</string>
</property>
@@ -203,6 +223,9 @@
<height>20</height>
</size>
</property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
<property name="text">
<string/>
</property>
@@ -216,7 +239,11 @@
</widget>
</item>
<item>
- <layout class="QVBoxLayout" name="loginLayout"/>
+ <layout class="QVBoxLayout" name="loginLayout">
+ <property name="topMargin">
+ <number>12</number>
+ </property>
+ </layout>
</item>
<item>
<widget class="Line" name="line_2">
@@ -226,7 +253,10 @@
</widget>
</item>
<item>
- <layout class="QVBoxLayout" name="mailLayout">
+ <layout class="QVBoxLayout" name="mailLayout" stretch="">
+ <property name="spacing">
+ <number>-1</number>
+ </property>
<property name="margin">
<number>12</number>
</property>
@@ -269,7 +299,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
@@ -290,7 +320,7 @@
<item row="1" column="2">
<widget class="QPushButton" name="btnMore">
<property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -311,7 +341,7 @@
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
- <height>20</height>
+ <height>0</height>
</size>
</property>
</spacer>
diff --git a/src/leap/bitmask/gui/ui/wizard.ui b/src/leap/bitmask/gui/ui/wizard.ui
index 0f6eef6e..cf591470 100644
--- a/src/leap/bitmask/gui/ui/wizard.ui
+++ b/src/leap/bitmask/gui/ui/wizard.ui
@@ -7,19 +7,19 @@
<x>0</x>
<y>0</y>
<width>536</width>
- <height>490</height>
+ <height>510</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>536</width>
- <height>490</height>
+ <height>510</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>536</width>
- <height>490</height>
+ <height>510</height>
</size>
</property>
<property name="windowTitle">
@@ -124,7 +124,7 @@
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
- <enum>QSizePolicy::Fixed</enum>
+ <enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
diff --git a/src/leap/bitmask/gui/wizard.py b/src/leap/bitmask/gui/wizard.py
index e3f5904e..6ba65410 100644
--- a/src/leap/bitmask/gui/wizard.py
+++ b/src/leap/bitmask/gui/wizard.py
@@ -53,9 +53,6 @@ class Wizard(QtGui.QWizard):
REGISTER_USER_PAGE = 4
SERVICES_PAGE = 5
- WEAK_PASSWORDS = ("123456", "qweasd", "qwerty",
- "password")
-
BARE_USERNAME_REGEX = r"^[A-Za-z\d_]+$"
def __init__(self, bypass_checks=False):
diff --git a/src/leap/bitmask/services/eip/connection.py b/src/leap/bitmask/services/eip/connection.py
index 08b29070..962d9cf2 100644
--- a/src/leap/bitmask/services/eip/connection.py
+++ b/src/leap/bitmask/services/eip/connection.py
@@ -46,4 +46,5 @@ class EIPConnectionSignals(QtCore.QObject):
class EIPConnection(AbstractLEAPConnection):
def __init__(self):
+ # XXX this should be public instead
self._qtsigs = EIPConnectionSignals()
diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
index c2c28627..efb23285 100644
--- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py
+++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
@@ -61,9 +61,13 @@ def _is_auth_agent_running():
:return: True if it's running, False if it's not.
:rtype: boolean
"""
- ps = 'ps aux | grep polkit-%s-authentication-agent-1'
- opts = (ps % case for case in ['[g]nome', '[k]de'])
- is_running = map(lambda l: commands.getoutput(l), opts)
+ # the [x] thing is to avoid grep match itself
+ polkit_options = [
+ 'ps aux | grep polkit-[g]nome-authentication-agent-1',
+ 'ps aux | grep polkit-[k]de-authentication-agent-1',
+ 'ps aux | grep [l]xpolkit'
+ ]
+ is_running = [commands.getoutput(cmd) for cmd in polkit_options]
return any(is_running)
diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py
index 935d75f1..bce3599b 100644
--- a/src/leap/bitmask/services/eip/vpnlauncher.py
+++ b/src/leap/bitmask/services/eip/vpnlauncher.py
@@ -102,6 +102,8 @@ class VPNLauncher(object):
UPDOWN_FILES = None
OTHER_FILES = None
+ UP_SCRIPT = None
+ DOWN_SCRIPT = None
@classmethod
@abstractmethod
@@ -164,7 +166,7 @@ class VPNLauncher(object):
if not gateways:
logger.error('No gateway was found!')
- raise VPNLauncherException(kls.tr('No gateway was found!'))
+ raise VPNLauncherException('No gateway was found!')
logger.debug("Using gateways ips: {0}".format(', '.join(gateways)))
@@ -211,15 +213,17 @@ class VPNLauncher(object):
'--script-security', '2'
]
- if _has_updown_scripts(kls.UP_SCRIPT):
- args += [
- '--up', '\"%s\"' % (kls.UP_SCRIPT,),
- ]
+ if kls.UP_SCRIPT is not None:
+ if _has_updown_scripts(kls.UP_SCRIPT):
+ args += [
+ '--up', '\"%s\"' % (kls.UP_SCRIPT,),
+ ]
- if _has_updown_scripts(kls.DOWN_SCRIPT):
- args += [
- '--down', '\"%s\"' % (kls.DOWN_SCRIPT,)
- ]
+ if kls.DOWN_SCRIPT is not None:
+ if _has_updown_scripts(kls.DOWN_SCRIPT):
+ args += [
+ '--down', '\"%s\"' % (kls.DOWN_SCRIPT,)
+ ]
###########################################################
# For the time being we are disabling the usage of the
@@ -241,6 +245,10 @@ class VPNLauncher(object):
'--ca', providerconfig.get_ca_cert_path()
]
+ args += [
+ '--ping', '10',
+ '--ping-restart', '30']
+
command_and_args = [openvpn] + args
logger.debug("Running VPN with command:")
logger.debug(" ".join(command_and_args))
diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py
index 707967e0..19e1aa7b 100644
--- a/src/leap/bitmask/services/eip/vpnprocess.py
+++ b/src/leap/bitmask/services/eip/vpnprocess.py
@@ -24,6 +24,8 @@ import psutil.error
import shutil
import socket
+from itertools import chain, repeat
+
from PySide import QtCore
from leap.bitmask.config.providerconfig import ProviderConfig
@@ -50,14 +52,93 @@ class VPNSignals(QtCore.QObject):
They are instantiated in the VPN object and passed along
till the VPNProcess.
"""
+ # signals for the process
state_changed = QtCore.Signal(dict)
status_changed = QtCore.Signal(dict)
process_finished = QtCore.Signal(int)
+ # signals that come from parsing
+ # openvpn output
+ network_unreachable = QtCore.Signal()
+ process_restart_tls = QtCore.Signal()
+ process_restart_ping = QtCore.Signal()
+
def __init__(self):
QtCore.QObject.__init__(self)
+class VPNObserver(object):
+ """
+ A class containing different patterns in the openvpn output that
+ we can react upon.
+ """
+
+ # TODO this is i18n-sensitive, right?
+ # in that case, we should add the translations :/
+ # until we find something better.
+
+ _events = {
+ 'NETWORK_UNREACHABLE': (
+ 'Network is unreachable (code=101)',),
+ 'PROCESS_RESTART_TLS': (
+ "SIGUSR1[soft,tls-error]",),
+ 'PROCESS_RESTART_PING': (
+ "SIGUSR1[soft,ping-restart]",),
+ 'INITIALIZATION_COMPLETED': (
+ "Initialization Sequence Completed",),
+ }
+
+ def __init__(self, qtsigs):
+ """
+ Initializer. Keeps a reference to the passed qtsigs object
+ :param qtsigs: an object containing the different qt signals to
+ be used to communicate with different parts of
+ the application (the EIP state machine, for instance).
+ """
+ self._qtsigs = qtsigs
+
+ def watch(self, line):
+ """
+ Inspects line searching for the different patterns. If a match
+ is found, try to emit the corresponding signal.
+
+ :param line: a line of openvpn output
+ :type line: str
+ """
+ chained_iter = chain(*[
+ zip(repeat(key, len(l)), l)
+ for key, l in self._events.iteritems()])
+ for event, pattern in chained_iter:
+ if pattern in line:
+ logger.debug('pattern matched! %s' % pattern)
+ break
+ else:
+ return
+
+ sig = self._get_signal(event)
+ if sig:
+ sig.emit()
+ return
+ else:
+ logger.debug(
+ 'We got %s event from openvpn output but we '
+ 'could not find a matching signal for it.'
+ % event)
+
+ def _get_signal(self, event):
+ """
+ Tries to get the matching signal from the eip signals
+ objects based on the name of the passed event (in lowercase)
+
+ :param event: the name of the event that we want to get a signal
+ for
+ :type event: str
+ :returns: a QtSignal, or None
+ :rtype: QtSignal or None
+ """
+ return getattr(self._qtsigs, event.lower(), None)
+
+
class OpenVPNAlreadyRunning(Exception):
message = ("Another openvpn instance is already running, and could "
"not be stopped.")
@@ -160,10 +241,14 @@ class VPN(object):
tries += 1
reactor.callLater(self.TERMINATE_WAIT,
self._kill_if_left_alive, tries)
+ return
# after running out of patience, we try a killProcess
logger.debug("Process did not died. Sending a SIGKILL.")
- self.killit()
+ try:
+ self.killit()
+ except OSError:
+ logger.error("Could not kill process!")
def killit(self):
"""
@@ -703,8 +788,12 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
self._last_status = None
self._alive = False
+ # XXX use flags, maybe, instead of passing
+ # the parameter around.
self._openvpn_verb = openvpn_verb
+ self._vpn_observer = VPNObserver(qtsigs)
+
# processProtocol methods
def connectionMade(self):
@@ -726,8 +815,9 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
.. seeAlso: `http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ProcessProtocol.html` # noqa
"""
# truncate the newline
- # should send this to the logging window
- vpnlog.info(data[:-1])
+ line = data[:-1]
+ vpnlog.info(line)
+ self._vpn_observer.watch(line)
def processExited(self, reason):
"""
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 7968dd6a..4619ba80 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -34,6 +34,7 @@ from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper
from leap.bitmask.services.soledad.soledadconfig import SoledadConfig
from leap.bitmask.util import is_file, is_empty_file
from leap.bitmask.util import get_path_prefix
+from leap.bitmask.platform_init import IS_WIN
from leap.common.check import leap_assert, leap_assert_type, leap_check
from leap.common.files import which
from leap.keymanager import KeyManager, openpgp
@@ -264,6 +265,10 @@ class SoledadBootstrapper(AbstractBootstrapper):
logger.error("Error while initializing soledad "
"(unauthorized).")
self.soledad_failed.emit()
+ except u1db_errors.HTTPError as exc:
+ logger.exception("Error whie initializing soledad "
+ "(HTTPError)")
+ self.soledad_failed.emit()
except Exception as exc:
logger.exception("Unhandled error while initializating "
"soledad: %r" % (exc,))
@@ -315,11 +320,12 @@ class SoledadBootstrapper(AbstractBootstrapper):
:returns: the gpg binary path
:rtype: str
"""
- # TODO: Fix for Windows
gpgbin = None
if flags.STANDALONE:
gpgbin = os.path.join(
get_path_prefix(), "..", "apps", "mail", "gpg")
+ if IS_WIN:
+ gpgbin += ".exe"
else:
try:
gpgbin_options = which("gpg")
diff --git a/src/leap/bitmask/util/leap_argparse.py b/src/leap/bitmask/util/leap_argparse.py
index afe5be48..e8a9fda9 100644
--- a/src/leap/bitmask/util/leap_argparse.py
+++ b/src/leap/bitmask/util/leap_argparse.py
@@ -33,8 +33,7 @@ Launches Bitmask""", epilog=epilog)
parser.add_argument('-d', '--debug', action="store_true",
help=("Launches Bitmask in debug mode, writing debug"
"info to stdout"))
- # TODO: when we are ready to disable the --danger flag remove 'True or '
- if True or not IS_RELEASE_VERSION:
+ if not IS_RELEASE_VERSION:
help_text = "Bypasses the certificate check for bootstrap"
parser.add_argument('--danger', action="store_true", help=help_text)
diff --git a/src/leap/bitmask/util/leap_log_handler.py b/src/leap/bitmask/util/leap_log_handler.py
index 98924c12..1ab62331 100644
--- a/src/leap/bitmask/util/leap_log_handler.py
+++ b/src/leap/bitmask/util/leap_log_handler.py
@@ -52,7 +52,8 @@ class LogHandler(logging.Handler):
:param logging_level: the debug level to define the color.
:type logging_level: str.
"""
- log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
+ log_format = ('%(asctime)s - %(name)s:%(funcName)s:L#%(lineno)s '
+ '- %(levelname)s - %(message)s')
formatter = logging.Formatter(log_format)
return formatter