summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask/services')
-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
5 files changed, 125 insertions, 16 deletions
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")