From c68ebd49ba82b2594be0291a881fe44bb1502552 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 7 Apr 2014 15:50:32 -0300 Subject: Add support for Mate's polkit agent. --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index d24e7ae7..8747daa6 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -66,6 +66,7 @@ def _is_auth_agent_running(): polkit_options = [ 'ps aux | grep polkit-[g]nome-authentication-agent-1', 'ps aux | grep polkit-[k]de-authentication-agent-1', + 'ps aux | grep polkit-[m]ate-authentication-agent-1', 'ps aux | grep [l]xpolkit' ] is_running = [commands.getoutput(cmd) for cmd in polkit_options] -- cgit v1.2.3 From e2ea44e2b042e86c0eb3a02eb52a92457b6bf179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 20 Mar 2014 10:41:48 -0300 Subject: Refactor EIPBootstrapper to the backend --- src/leap/bitmask/services/abstractbootstrapper.py | 4 +++- src/leap/bitmask/services/eip/eipbootstrapper.py | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/abstractbootstrapper.py b/src/leap/bitmask/services/abstractbootstrapper.py index fc6bd3e9..77929b75 100644 --- a/src/leap/bitmask/services/abstractbootstrapper.py +++ b/src/leap/bitmask/services/abstractbootstrapper.py @@ -78,6 +78,7 @@ class AbstractBootstrapper(QtCore.QObject): self._signal_to_emit = None self._err_msg = None self._signaler = signaler + self._cancel_signal = None def _gui_errback(self, failure): """ @@ -95,7 +96,8 @@ class AbstractBootstrapper(QtCore.QObject): if failure.check(CancelledError): logger.debug("Defer cancelled.") failure.trap(Exception) - self._signaler.signal(self._signaler.PROV_CANCELLED_SETUP) + if self._signaler is not None and self._cancel_signal is not None: + self._signaler.signal(self._cancel_signal) return if self._signal_to_emit: diff --git a/src/leap/bitmask/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index 5a238a1c..aacf3b7e 100644 --- a/src/leap/bitmask/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -20,8 +20,6 @@ EIP bootstrapping import logging import os -from PySide import QtCore - from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.certs import download_client_cert from leap.bitmask.services import download_service_config @@ -41,17 +39,21 @@ class EIPBootstrapper(AbstractBootstrapper): If a check fails, the subsequent checks are not executed """ - # All dicts returned are of the form - # {"passed": bool, "error": str} - download_config = QtCore.Signal(dict) - download_client_certificate = QtCore.Signal(dict) + def __init__(self, signaler=None): + """ + Constructor for the EIP bootstrapper object - def __init__(self): - AbstractBootstrapper.__init__(self) + :param signaler: Signaler object used to receive notifications + from the backend + :type signaler: Signaler + """ + AbstractBootstrapper.__init__(self, signaler) self._provider_config = None self._eip_config = None self._download_if_needed = False + if signaler is not None: + self._cancel_signal = signaler.EIP_CANCELLED_SETUP def _download_config(self, *args): """ @@ -114,9 +116,9 @@ class EIPBootstrapper(AbstractBootstrapper): self._download_if_needed = download_if_needed cb_chain = [ - (self._download_config, self.download_config), + (self._download_config, self._signaler.EIP_DOWNLOAD_CONFIG), (self._download_client_certificates, - self.download_client_certificate) + self._signaler.EIP_DOWNLOAD_CLIENT_CERTIFICATE) ] return self.addCallbackChain(cb_chain) -- cgit v1.2.3 From 733dc642962c14cd664aba694e4d3b5300e69d8b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 28 Mar 2014 11:37:13 -0300 Subject: Move openvpn_verb to config.flags --- src/leap/bitmask/services/eip/vpnprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 5c100036..4f797722 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -35,6 +35,7 @@ except ImportError: from PySide import QtCore +from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services.eip import get_vpn_launcher from leap.bitmask.services.eip.eipconfig import EIPConfig @@ -183,8 +184,7 @@ class VPN(object): self._reactor = reactor self._qtsigs = VPNSignals() - # XXX should get it from config.flags - self._openvpn_verb = kwargs.get(self.OPENVPN_VERB, None) + self._openvpn_verb = flags.OPENVPN_VERBOSITY @property def qtsigs(self): -- cgit v1.2.3 From a73c432400eb6a614706fc615a505ed78d4031e3 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 27 Mar 2014 17:16:04 -0300 Subject: Move EIP to the backend. - Add backend eip management - Connect gui with new eip signals - remove old unused code - remove Qt dependency from backend services. - use Signaler to emit status/state changes from openvpn --- src/leap/bitmask/services/eip/vpnprocess.py | 167 +++++++++------------------- 1 file changed, 52 insertions(+), 115 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 4f797722..a17d94d2 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -33,8 +33,6 @@ except ImportError: # psutil >= 2.0.0 from psutil import AccessDenied as psutil_AccessDenied -from PySide import QtCore - from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services.eip import get_vpn_launcher @@ -53,28 +51,6 @@ from twisted.internet import error as internet_error from twisted.internet.task import LoopingCall -class VPNSignals(QtCore.QObject): - """ - These are the signals that we use to let the UI know - about the events we are polling. - 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 @@ -96,14 +72,8 @@ class VPNObserver(object): "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 __init__(self, signaler=None): + self._signaler = signaler def watch(self, line): """ @@ -124,27 +94,29 @@ class VPNObserver(object): return sig = self._get_signal(event) - if sig: - sig.emit() + if sig is not None: + self._signaler.signal(sig) return else: - logger.debug( - 'We got %s event from openvpn output but we ' - 'could not find a matching signal for it.' - % event) + 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 + :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 + :returns: a Signaler signal or None + :rtype: str or None """ - return getattr(self._qtsigs, event.lower(), None) + signals = { + "network_unreachable": self._signaler.EIP_NETWORK_UNREACHABLE, + "process_restart_tls": self._signaler.EIP_PROCESS_RESTART_TLS, + "process_restart_ping": self._signaler.EIP_PROCESS_RESTART_PING, + } + return signals.get(event.lower()) class OpenVPNAlreadyRunning(Exception): @@ -182,14 +154,10 @@ class VPN(object): self._vpnproc = None self._pollers = [] self._reactor = reactor - self._qtsigs = VPNSignals() + self._signaler = kwargs['signaler'] self._openvpn_verb = flags.OPENVPN_VERBOSITY - @property - def qtsigs(self): - return self._qtsigs - def start(self, *args, **kwargs): """ Starts the openvpn subprocess. @@ -200,14 +168,13 @@ class VPN(object): :param kwargs: kwargs to be passed to the VPNProcess :type kwargs: dict """ + logger.debug('VPN: start') self._stop_pollers() - kwargs['qtsigs'] = self.qtsigs kwargs['openvpn_verb'] = self._openvpn_verb + kwargs['signaler'] = self._signaler # start the main vpn subprocess vpnproc = VPNProcess(*args, **kwargs) - #qtsigs=self.qtsigs, - #openvpn_verb=self._openvpn_verb) if vpnproc.get_openvpn_process(): logger.info("Another vpn process is running. Will try to stop it.") @@ -328,36 +295,20 @@ class VPNManager(object): POLL_TIME = 2.5 if IS_MAC else 1.0 CONNECTION_RETRY_TIME = 1 - TS_KEY = "ts" - STATUS_STEP_KEY = "status_step" - OK_KEY = "ok" - IP_KEY = "ip" - REMOTE_KEY = "remote" - - TUNTAP_READ_KEY = "tun_tap_read" - TUNTAP_WRITE_KEY = "tun_tap_write" - TCPUDP_READ_KEY = "tcp_udp_read" - TCPUDP_WRITE_KEY = "tcp_udp_write" - AUTH_READ_KEY = "auth_read" - - def __init__(self, qtsigs=None): + def __init__(self, signaler=None): """ Initializes the VPNManager. - :param qtsigs: a QObject containing the Qt signals used by the UI - to give feedback about state changes. - :type qtsigs: QObject + :param signaler: Signaler object used to send notifications to the + backend + :type signaler: backend.Signaler """ from twisted.internet import reactor self._reactor = reactor self._tn = None - self._qtsigs = qtsigs + self._signaler = signaler self._aborted = False - @property - def qtsigs(self): - return self._qtsigs - @property def aborted(self): return self._aborted @@ -552,17 +503,10 @@ class VPNManager(object): continue ts, status_step, ok, ip, remote = parts - state_dict = { - self.TS_KEY: ts, - self.STATUS_STEP_KEY: status_step, - self.OK_KEY: ok, - self.IP_KEY: ip, - self.REMOTE_KEY: remote - } - - if state_dict != self._last_state: - self.qtsigs.state_changed.emit(state_dict) - self._last_state = state_dict + state = status_step + if state != self._last_state: + self._signaler.signal(self._signaler.EIP_STATE_CHANGED, state) + self._last_state = state def _parse_status_and_notify(self, output): """ @@ -575,9 +519,7 @@ class VPNManager(object): """ tun_tap_read = "" tun_tap_write = "" - tcp_udp_read = "" - tcp_udp_write = "" - auth_read = "" + for line in output: stripped = line.strip() if stripped.endswith("STATISTICS") or stripped == "END": @@ -585,28 +527,24 @@ class VPNManager(object): parts = stripped.split(",") if len(parts) < 2: continue - if parts[0].strip() == "TUN/TAP read bytes": - tun_tap_read = parts[1] - elif parts[0].strip() == "TUN/TAP write bytes": - tun_tap_write = parts[1] - elif parts[0].strip() == "TCP/UDP read bytes": - tcp_udp_read = parts[1] - elif parts[0].strip() == "TCP/UDP write bytes": - tcp_udp_write = parts[1] - elif parts[0].strip() == "Auth read bytes": - auth_read = parts[1] - - status_dict = { - self.TUNTAP_READ_KEY: tun_tap_read, - self.TUNTAP_WRITE_KEY: tun_tap_write, - self.TCPUDP_READ_KEY: tcp_udp_read, - self.TCPUDP_WRITE_KEY: tcp_udp_write, - self.AUTH_READ_KEY: auth_read - } - if status_dict != self._last_status: - self.qtsigs.status_changed.emit(status_dict) - self._last_status = status_dict + text, value = parts + # text can be: + # "TUN/TAP read bytes" + # "TUN/TAP write bytes" + # "TCP/UDP read bytes" + # "TCP/UDP write bytes" + # "Auth read bytes" + + if text == "TUN/TAP read bytes": + tun_tap_read = value + elif text == "TUN/TAP write bytes": + tun_tap_write = value + + status = (tun_tap_write, tun_tap_read) + if status != self._last_status: + self._signaler.signal(self._signaler.EIP_STATUS_CHANGED, status) + self._last_status = status def get_state(self): """ @@ -754,7 +692,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): """ def __init__(self, eipconfig, providerconfig, socket_host, socket_port, - qtsigs, openvpn_verb): + signaler, openvpn_verb): """ :param eipconfig: eip configuration object :type eipconfig: EIPConfig @@ -769,18 +707,17 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): socket, or port otherwise :type socket_port: str - :param qtsigs: a QObject containing the Qt signals used to notify the - UI. - :type qtsigs: QObject + :param signaler: Signaler object used to receive notifications to the + backend + :type signaler: backend.Signaler :param openvpn_verb: the desired level of verbosity in the openvpn invocation :type openvpn_verb: int """ - VPNManager.__init__(self, qtsigs=qtsigs) + VPNManager.__init__(self, signaler=signaler) leap_assert_type(eipconfig, EIPConfig) leap_assert_type(providerconfig, ProviderConfig) - leap_assert_type(qtsigs, QtCore.QObject) #leap_assert(not self.isRunning(), "Starting process more than once!") @@ -799,7 +736,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): # the parameter around. self._openvpn_verb = openvpn_verb - self._vpn_observer = VPNObserver(qtsigs) + self._vpn_observer = VPNObserver(signaler) # processProtocol methods @@ -835,7 +772,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): exit_code = reason.value.exitCode if isinstance(exit_code, int): logger.debug("processExited, status %d" % (exit_code,)) - self.qtsigs.process_finished.emit(exit_code) + self._signaler.signal(self._signaler.EIP_PROCESS_FINISHED, exit_code) self._alive = False def processEnded(self, reason): -- cgit v1.2.3 From c45558a1b96917e00b931c58034c2d3db187d63b Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 10 Apr 2014 15:30:48 -0300 Subject: Handle trying to kill a non running process. --- src/leap/bitmask/services/eip/vpnprocess.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index a17d94d2..9986526a 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -229,8 +229,11 @@ class VPN(object): Sends a kill signal to the process. """ self._stop_pollers() - self._vpnproc.aborted = True - self._vpnproc.killProcess() + if self._vpnproc is None: + logger.debug("There's no vpn process running to kill.") + else: + self._vpnproc.aborted = True + self._vpnproc.killProcess() def terminate(self, shutdown=False): """ -- cgit v1.2.3 From 37577fdf037f2987ae3eb9493457dd8d4447aaf7 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 14 Apr 2014 15:35:16 -0300 Subject: Use less confusing signal names. Renames: eip_download_config -> eip_config_ready eip_download_client_certificate -> eip_client_certificate_ready --- src/leap/bitmask/services/eip/eipbootstrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index aacf3b7e..c77977ce 100644 --- a/src/leap/bitmask/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -116,9 +116,9 @@ class EIPBootstrapper(AbstractBootstrapper): self._download_if_needed = download_if_needed cb_chain = [ - (self._download_config, self._signaler.EIP_DOWNLOAD_CONFIG), + (self._download_config, self._signaler.EIP_CONFIG_READY), (self._download_client_certificates, - self._signaler.EIP_DOWNLOAD_CLIENT_CERTIFICATE) + self._signaler.EIP_CLIENT_CERTIFICATE_READY) ] return self.addCallbackChain(cb_chain) -- cgit v1.2.3 From d5d90c59759da24fa6751f3195f0800892b2ccb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 16 Apr 2014 12:59:32 -0300 Subject: Let OpenVPN handle ping-restarts --- src/leap/bitmask/services/eip/vpnprocess.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 9986526a..a9444489 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -66,8 +66,9 @@ class VPNObserver(object): 'Network is unreachable (code=101)',), 'PROCESS_RESTART_TLS': ( "SIGUSR1[soft,tls-error]",), - 'PROCESS_RESTART_PING': ( - "SIGUSR1[soft,ping-restart]",), + # Let ping-restart work as it should + # 'PROCESS_RESTART_PING': ( + # "SIGUSR1[soft,ping-restart]",), 'INITIALIZATION_COMPLETED': ( "Initialization Sequence Completed",), } -- cgit v1.2.3 From def537bb5a78e046a75a9e13ea75449eec2b34c8 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 16 Apr 2014 14:48:53 -0300 Subject: Use Slot decorator instead of SLOT docstring. --- src/leap/bitmask/services/mail/conductor.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 79f324dc..4448d5d0 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -238,10 +238,9 @@ class SMTPControl(object): self._smtp_port.stopListening() self._smtp_service.doStop() - @QtCore.Slot() + @QtCore.Slot(dict) def smtp_bootstrapped_stage(self, data): """ - SLOT TRIGGERS: self.smtp_bootstrapper.download_config -- cgit v1.2.3 From 5218fda6b524cb8e694113e123e7b0d05b205ddc Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 16 Apr 2014 15:25:41 -0300 Subject: Use consistent wording for triggers documentation. --- src/leap/bitmask/services/mail/conductor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 4448d5d0..c1761afa 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -242,7 +242,7 @@ class SMTPControl(object): def smtp_bootstrapped_stage(self, data): """ TRIGGERS: - self.smtp_bootstrapper.download_config + self.smtp_bootstrapper.download_config If there was a problem, displays it, otherwise it does nothing. This is used for intermediate bootstrapping stages, in case -- cgit v1.2.3 From 58a1381764b16ebe01639020c73d4c96632cadfa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 23 Apr 2014 12:54:29 -0300 Subject: Swap upload/download data strings. Closes #5563. --- src/leap/bitmask/services/eip/vpnprocess.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 9986526a..6e4580ac 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -540,11 +540,11 @@ class VPNManager(object): # "Auth read bytes" if text == "TUN/TAP read bytes": - tun_tap_read = value + tun_tap_read = value # download elif text == "TUN/TAP write bytes": - tun_tap_write = value + tun_tap_write = value # upload - status = (tun_tap_write, tun_tap_read) + status = (tun_tap_read, tun_tap_write) if status != self._last_status: self._signaler.signal(self._signaler.EIP_STATUS_CHANGED, status) self._last_status = status -- cgit v1.2.3 From 1b5e1e5356c2dc4d7a56604801aaf5a0378c9bff Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 30 Apr 2014 13:35:15 -0300 Subject: Handle retries in the soledad bootstrapper object. --- .../services/soledad/soledadbootstrapper.py | 96 +++++++++++----------- 1 file changed, 47 insertions(+), 49 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index ad5ee4d0..6bb7c036 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -139,7 +139,6 @@ class SoledadBootstrapper(AbstractBootstrapper): download_config = QtCore.Signal(dict) gen_key = QtCore.Signal(dict) local_only_ready = QtCore.Signal(dict) - soledad_timeout = QtCore.Signal() soledad_invalid_auth_token = QtCore.Signal() soledad_failed = QtCore.Signal() @@ -159,8 +158,6 @@ class SoledadBootstrapper(AbstractBootstrapper): self._srpauth = None self._soledad = None - self._soledad_retries = 0 - @property def keymanager(self): return self._keymanager @@ -177,26 +174,6 @@ class SoledadBootstrapper(AbstractBootstrapper): "We need a provider config") return SRPAuth(self._provider_config) - # retries - - def cancel_bootstrap(self): - self._soledad_retries = self.MAX_INIT_RETRIES - - def should_retry_initialization(self): - """ - Return True if we should retry the initialization. - """ - logger.debug("current retries: %s, max retries: %s" % ( - self._soledad_retries, - self.MAX_INIT_RETRIES)) - return self._soledad_retries < self.MAX_INIT_RETRIES - - def increment_retries_count(self): - """ - Increment the count of initialization retries. - """ - self._soledad_retries += 1 - # initialization def load_offline_soledad(self, username, password, uuid): @@ -265,6 +242,41 @@ class SoledadBootstrapper(AbstractBootstrapper): # in the case of an invalid token we have already turned off mail and # warned the user in _do_soledad_sync() + def _do_soledad_init(self, uuid, secrets_path, local_db_path, + server_url, cert_file, token): + """ + Initialize soledad, retry if necessary and emit soledad_failed if we + can't succeed. + + :param uuid: user identifier + :type uuid: str + :param secrets_path: path to secrets file + :type secrets_path: str + :param local_db_path: path to local db file + :type local_db_path: str + :param server_url: soledad server uri + :type server_url: str + :param cert_file: path to the certificate of the ca used + to validate the SSL certificate used by the remote + soledad server. + :type cert_file: str + :param auth token: auth token + :type auth_token: str + """ + init_tries = self.MAX_INIT_RETRIES + while init_tries > 0: + try: + self._try_soledad_init( + uuid, secrets_path, local_db_path, + server_url, cert_file, token) + logger.debug("Soledad has been initialized.") + return + except Exception: + init_tries -= 1 + continue + + self.soledad_failed.emit() + raise SoledadInitError() def load_and_sync_soledad(self, uuid=None, offline=False): """ @@ -283,10 +295,9 @@ class SoledadBootstrapper(AbstractBootstrapper): server_url, cert_file = remote_param try: - self._try_soledad_init( - uuid, secrets_path, local_db_path, - server_url, cert_file, token) - except Exception: + self._do_soledad_init(uuid, secrets_path, local_db_path, + server_url, cert_file, token) + except SoledadInitError: # re-raise the exceptions from try_init, # we're currently handling the retries from the # soledad-launcher in the gui. @@ -378,9 +389,13 @@ class SoledadBootstrapper(AbstractBootstrapper): Try to initialize soledad. :param uuid: user identifier + :type uuid: str :param secrets_path: path to secrets file + :type secrets_path: str :param local_db_path: path to local db file + :type local_db_path: str :param server_url: soledad server uri + :type server_url: str :param cert_file: path to the certificate of the ca used to validate the SSL certificate used by the remote soledad server. @@ -409,34 +424,17 @@ class SoledadBootstrapper(AbstractBootstrapper): # and return a subclass of SoledadInitializationFailed # recoverable, will guarantee retries - except socket.timeout: - logger.debug("SOLEDAD initialization TIMED OUT...") - self.soledad_timeout.emit() - raise - except socket.error as exc: - logger.warning("Socket error while initializing soledad") - self.soledad_timeout.emit() - raise - except BootstrapSequenceError as exc: - logger.warning("Error while initializing soledad") - self.soledad_timeout.emit() + except (socket.timeout, socket.error, BootstrapSequenceError): + logger.warning("Error while initializing Soledad") raise # unrecoverable - except u1db_errors.Unauthorized: - logger.error("Error while initializing soledad " - "(unauthorized).") - self.soledad_failed.emit() - raise - except u1db_errors.HTTPError as exc: - logger.exception("Error while initializing soledad " - "(HTTPError)") - self.soledad_failed.emit() + except (u1db_errors.Unauthorized, u1db_errors.HTTPError): + logger.error("Error while initializing Soledad (u1db error).") raise except Exception as exc: logger.exception("Unhandled error while initializating " - "soledad: %r" % (exc,)) - self.soledad_failed.emit() + "Soledad: %r" % (exc,)) raise def _try_soledad_sync(self): -- cgit v1.2.3 From 31c524e2abb98ca13ea993ebc2ec26e9f3d81975 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 7 May 2014 17:27:27 -0300 Subject: Organize smtp logic in the bootstrapper. --- src/leap/bitmask/services/mail/conductor.py | 118 +++--------------- src/leap/bitmask/services/mail/smtpbootstrapper.py | 135 ++++++++++++++------- 2 files changed, 107 insertions(+), 146 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index c1761afa..1766a39d 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -18,22 +18,18 @@ Mail Services Conductor """ import logging -import os -from PySide import QtCore from zope.proxy import sameProxiedObjects from leap.bitmask.gui import statemachines -from leap.bitmask.services.mail import imap from leap.bitmask.services.mail import connection as mail_connection +from leap.bitmask.services.mail import imap from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper from leap.bitmask.services.mail.smtpconfig import SMTPConfig -from leap.bitmask.util import is_file from leap.common.check import leap_assert - -from leap.common.events import register as leap_register from leap.common.events import events_pb2 as leap_events +from leap.common.events import register as leap_register logger = logging.getLogger(__name__) @@ -167,10 +163,6 @@ class IMAPControl(object): class SMTPControl(object): - - PORT_KEY = "port" - IP_KEY = "ip_address" - def __init__(self): """ Initializes smtp variables. @@ -178,12 +170,8 @@ class SMTPControl(object): self.smtp_config = SMTPConfig() self.smtp_connection = None self.smtp_machine = None - self._smtp_service = None - self._smtp_port = None self.smtp_bootstrapper = SMTPBootstrapper() - self.smtp_bootstrapper.download_config.connect( - self.smtp_bootstrapped_stage) leap_register(signal=leap_events.SMTP_SERVICE_STARTED, callback=self._handle_smtp_events, @@ -200,100 +188,27 @@ class SMTPControl(object): """ self.smtp_connection = smtp_connection - def start_smtp_service(self, host, port, cert): + def start_smtp_service(self, provider_config, download_if_needed=False): """ - Starts the smtp service. + Starts the SMTP service. - :param host: the hostname of the remove SMTP server. - :type host: str - :param port: the port of the remote SMTP server - :type port: str - :param cert: the client certificate for authentication - :type cert: str + :param provider_config: Provider configuration + :type provider_config: ProviderConfig + :param download_if_needed: True if it should check for mtime + for the file + :type download_if_needed: bool """ - # TODO Make the encrypted_only configurable - # TODO pick local smtp port in a better way - # TODO remove hard-coded port and let leap.mail set - # the specific default. self.smtp_connection.qtsigs.connecting_signal.emit() - from leap.mail.smtp import setup_smtp_gateway - self._smtp_service, self._smtp_port = setup_smtp_gateway( - port=2013, - userid=self.userid, - keymanager=self._keymanager, - smtp_host=host, - smtp_port=port, - smtp_cert=cert, - smtp_key=cert, - encrypted_only=False) + self.smtp_bootstrapper.start_smtp_service( + provider_config, self.smtp_config, self._keymanager, + self.userid, download_if_needed) def stop_smtp_service(self): """ - Stops the smtp service (port and factory). + Stops the SMTP service. """ self.smtp_connection.qtsigs.disconnecting_signal.emit() - # TODO We should homogenize both services. - if self._smtp_service is not None: - logger.debug('Stopping smtp service.') - self._smtp_port.stopListening() - self._smtp_service.doStop() - - @QtCore.Slot(dict) - def smtp_bootstrapped_stage(self, data): - """ - TRIGGERS: - self.smtp_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. - - :param data: result from the bootstrapping stage for Soledad - :type data: dict - """ - passed = data[self.smtp_bootstrapper.PASSED_KEY] - if not passed: - logger.error(data[self.smtp_bootstrapper.ERROR_KEY]) - return - logger.debug("Done bootstrapping SMTP") - self.check_smtp_config() - - def check_smtp_config(self): - """ - Checks smtp config and tries to download smtp client cert if needed. - Currently called when smtp_bootstrapped_stage has successfuly finished. - """ - logger.debug("Checking SMTP config...") - leap_assert(self.smtp_bootstrapper._provider_config, - "smtp bootstrapper does not have a provider_config") - - provider_config = self.smtp_bootstrapper._provider_config - smtp_config = self.smtp_config - hosts = smtp_config.get_hosts() - # TODO handle more than one host and define how to choose - if len(hosts) > 0: - hostname = hosts.keys()[0] - logger.debug("Using hostname %s for SMTP" % (hostname,)) - host = hosts[hostname][self.IP_KEY].encode("utf-8") - port = hosts[hostname][self.PORT_KEY] - - client_cert = smtp_config.get_client_cert_path( - provider_config, - about_to_download=True) - - # XXX change this logic! - # check_config should be called from within start_service, - # and not the other way around. - if not is_file(client_cert): - self.smtp_bootstrapper._download_client_certificates() - if os.path.isfile(client_cert): - self.start_smtp_service(host, port, client_cert) - else: - logger.warning("Tried to download email client " - "certificate, but could not find any") - - else: - logger.warning("No smtp hosts configured") + self.smtp_bootstrapper.stop_smtp_service() # handle smtp events @@ -348,7 +263,7 @@ class MailConductor(IMAPControl, SMTPControl): :param keymanager: a transparent proxy that eventually will point to a Keymanager Instance. - :type soledad: zope.proxy.ProxyBase + :type keymanager: zope.proxy.ProxyBase """ IMAPControl.__init__(self) SMTPControl.__init__(self) @@ -406,4 +321,5 @@ class MailConductor(IMAPControl, SMTPControl): qtsigs.connecting_signal.connect(widget.mail_state_connecting) qtsigs.disconnecting_signal.connect(widget.mail_state_disconnecting) qtsigs.disconnected_signal.connect(widget.mail_state_disconnected) - qtsigs.soledad_invalid_auth_token.connect(widget.soledad_invalid_auth_token) + qtsigs.soledad_invalid_auth_token.connect( + widget.soledad_invalid_auth_token) diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 032d6357..7ecf8134 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -20,12 +20,13 @@ SMTP bootstrapping import logging import os -from PySide import QtCore - from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.certs import download_client_cert from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper +from leap.bitmask.services.mail.smtpconfig import SMTPConfig +from leap.bitmask.util import is_file + from leap.common import certs as leap_certs from leap.common.check import leap_assert, leap_assert_type from leap.common.files import check_and_fix_urw_only @@ -33,27 +34,33 @@ from leap.common.files import check_and_fix_urw_only logger = logging.getLogger(__name__) +class NoSMTPHosts(Exception): + """This is raised when there is no SMTP host to use.""" + + class SMTPBootstrapper(AbstractBootstrapper): """ SMTP init procedure """ - # All dicts returned are of the form - # {"passed": bool, "error": str} - download_config = QtCore.Signal(dict) + PORT_KEY = "port" + IP_KEY = "ip_address" def __init__(self): AbstractBootstrapper.__init__(self) self._provider_config = None self._smtp_config = None + self._userid = None self._download_if_needed = False - def _download_config(self, *args): + self._smtp_service = None + self._smtp_port = None + + def _download_config_and_cert(self): """ - Downloads the SMTP config for the given provider + Downloads the SMTP config and cert for the given provider. """ - leap_assert(self._provider_config, "We need a provider configuration!") @@ -66,63 +73,101 @@ class SMTPBootstrapper(AbstractBootstrapper): self._session, self._download_if_needed) - def _download_client_certificates(self, *args): - """ - Downloads the SMTP client certificate for the given provider + hosts = self._smtp_config.get_hosts() - We actually are downloading the certificate for the same uri as - for the EIP config, but we duplicate these bits to allow mail - service to be working in a provider that does not offer EIP. - """ - # TODO factor out with eipboostrapper.download_client_certificates - # TODO this shouldn't be a private method, it's called from - # mainwindow. - leap_assert(self._provider_config, "We need a provider configuration!") - leap_assert(self._smtp_config, "We need an smtp configuration!") + if len(hosts) == 0: + raise NoSMTPHosts() - logger.debug("Downloading SMTP client certificate for %s" % - (self._provider_config.get_domain(),)) + # TODO handle more than one host and define how to choose + hostname = hosts.keys()[0] + logger.debug("Using hostname %s for SMTP" % (hostname,)) - client_cert_path = self._smtp_config.\ - get_client_cert_path(self._provider_config, - about_to_download=True) + client_cert_path = self._smtp_config.get_client_cert_path( + self._provider_config, about_to_download=True) - # For re-download if something is wrong with the cert - self._download_if_needed = self._download_if_needed and \ - not leap_certs.should_redownload(client_cert_path) + if not is_file(client_cert_path): + # For re-download if something is wrong with the cert + self._download_if_needed = ( + self._download_if_needed and + not leap_certs.should_redownload(client_cert_path)) - if self._download_if_needed and \ - os.path.isfile(client_cert_path): - check_and_fix_urw_only(client_cert_path) - return + if self._download_if_needed and os.path.isfile(client_cert_path): + check_and_fix_urw_only(client_cert_path) + return - download_client_cert(self._provider_config, - client_cert_path, - self._session) + download_client_cert(self._provider_config, + client_cert_path, + self._session) - def run_smtp_setup_checks(self, - provider_config, - smtp_config, - download_if_needed=False): + def _start_smtp_service(self): + """ + Start the smtp service using the downloaded configurations. + """ + # TODO Make the encrypted_only configurable + # TODO pick local smtp port in a better way + # TODO remove hard-coded port and let leap.mail set + # the specific default. + # TODO handle more than one host and define how to choose + hosts = self._smtp_config.get_hosts() + hostname = hosts.keys()[0] + host = hosts[hostname][self.IP_KEY].encode("utf-8") + port = hosts[hostname][self.PORT_KEY] + client_cert_path = self._smtp_config.get_client_cert_path( + self._provider_config, about_to_download=True) + + from leap.mail.smtp import setup_smtp_gateway + self._smtp_service, self._smtp_port = setup_smtp_gateway( + port=2013, + userid=self._userid, + keymanager=self._keymanager, + smtp_host=host, + smtp_port=port, + smtp_cert=client_cert_path, + smtp_key=client_cert_path, + encrypted_only=False) + + def start_smtp_service(self, provider_config, smtp_config, keymanager, + userid, download_if_needed=False): """ - Starts the checks needed for a new smtp setup + Starts the SMTP service. :param provider_config: Provider configuration :type provider_config: ProviderConfig :param smtp_config: SMTP configuration to populate :type smtp_config: SMTPConfig + :param keymanager: a transparent proxy that eventually will point to a + Keymanager Instance. + :type keymanager: zope.proxy.ProxyBase + :param userid: the user id, in the form "user@provider" + :type userid: str :param download_if_needed: True if it should check for mtime for the file :type download_if_needed: bool """ leap_assert_type(provider_config, ProviderConfig) + leap_assert_type(smtp_config, SMTPConfig) self._provider_config = provider_config + self._keymanager = keymanager self._smtp_config = smtp_config + self._useid = userid self._download_if_needed = download_if_needed - cb_chain = [ - (self._download_config, self.download_config), - ] - - self.addCallbackChain(cb_chain) + try: + self._download_config_and_cert() + logger.debug("Starting SMTP service.") + self._start_smtp_service() + except NoSMTPHosts: + logger.warning("There is no SMTP host to use.") + except Exception as e: + # TODO: we should handle more specific exceptions in here + logger.exception("Error while bootstrapping SMTP: %r" % (e, )) + + def stop_smtp_service(self): + """ + Stops the smtp service (port and factory). + """ + if self._smtp_service is not None: + logger.debug('Stopping SMTP service.') + self._smtp_port.stopListening() + self._smtp_service.doStop() -- cgit v1.2.3 From a733e83ae0bcbcc9daa0cba0aa4704f499406394 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 29 Apr 2014 10:40:48 -0500 Subject: add elijah's root-wrapper in python --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 48 +++++++++++++++++------ src/leap/bitmask/services/eip/vpnlauncher.py | 5 +++ 2 files changed, 40 insertions(+), 13 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 8747daa6..988970a5 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -36,6 +36,8 @@ from leap.bitmask.util import first logger = logging.getLogger(__name__) +COM = commands + class EIPNoPolkitAuthAgentAvailable(VPNLauncherException): pass @@ -64,12 +66,13 @@ def _is_auth_agent_running(): """ # 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 polkit-[m]ate-authentication-agent-1', - 'ps aux | grep [l]xpolkit' + 'ps aux | grep "polkit-[g]nome-authentication-agent-1"', + 'ps aux | grep "polkit-[k]de-authentication-agent-1"', + 'ps aux | grep "polkit-[m]ate-authentication-agent-1"', + 'ps aux | grep "[l]xpolkit"' ] is_running = [commands.getoutput(cmd) for cmd in polkit_options] + print "IS RUNNING ->", is_running return any(is_running) @@ -85,22 +88,23 @@ def _try_to_launch_agent(): # will do "sh -c 'foo'", so if we do not quoute it we'll end # up with a invocation to the python interpreter. And that # is bad. + logger.debug("Trying to launch polkit agent") subprocess.call(["python -m leap.bitmask.util.polkit_agent"], shell=True, env=env) except Exception as exc: logger.exception(exc) +SYSTEM_CONFIG = "/etc/leap" +leapfile = lambda f: "%s/%s" % (SYSTEM_CONFIG, f) + + class LinuxVPNLauncher(VPNLauncher): PKEXEC_BIN = 'pkexec' OPENVPN_BIN = 'openvpn' OPENVPN_BIN_PATH = os.path.join( get_path_prefix(), "..", "apps", "eip", OPENVPN_BIN) - SYSTEM_CONFIG = "/etc/leap" - UP_DOWN_FILE = "resolv-update" - UP_DOWN_PATH = "%s/%s" % (SYSTEM_CONFIG, UP_DOWN_FILE) - # We assume this is there by our openvpn dependency, and # we will put it there on the bundle too. # TODO adapt to the bundle path. @@ -110,10 +114,23 @@ class LinuxVPNLauncher(VPNLauncher): OPENVPN_DOWN_ROOT_BASE, OPENVPN_DOWN_ROOT_FILE) - UP_SCRIPT = DOWN_SCRIPT = UP_DOWN_PATH - UPDOWN_FILES = (UP_DOWN_PATH,) + UPDOWN_FILE = "vpn-updown" + + # vpn-up and vpn-down are hard-links to vpn-updown + UP_FILE = "vpn-up" + DOWN_FILE = "vpn-down" + UP_SCRIPT = leapfile(UP_FILE) + DOWN_SCRIPT = leapfile(DOWN_FILE) + + RESOLV_UPDATE_FILE = "resolv-update" + RESOLV_UPDATE_SCRIPT = leapfile(RESOLV_UPDATE_FILE) + + RESOLVCONF_FILE = "update-resolv-conf" + RESOLVCONF_SCRIPT = leapfile(RESOLVCONF_FILE) + + UPDOWN_FILES = (UP_SCRIPT, DOWN_SCRIPT) POLKIT_PATH = LinuxPolicyChecker.get_polkit_path() - OTHER_FILES = (POLKIT_PATH, ) + OTHER_FILES = (POLKIT_PATH, RESOLV_UPDATE_SCRIPT, RESOLVCONF_SCRIPT) @classmethod def maybe_pkexec(kls): @@ -131,7 +148,7 @@ class LinuxVPNLauncher(VPNLauncher): if _is_pkexec_in_system(): if not _is_auth_agent_running(): _try_to_launch_agent() - time.sleep(0.5) + time.sleep(2) if _is_auth_agent_running(): pkexec_possibilities = which(kls.PKEXEC_BIN) leap_assert(len(pkexec_possibilities) > 0, @@ -158,6 +175,7 @@ class LinuxVPNLauncher(VPNLauncher): """ # we use `super` in order to send the class to use missing = super(LinuxVPNLauncher, kls).missing_other_files() + print "MISSING OTHER", missing if flags.STANDALONE: polkit_file = LinuxPolicyChecker.get_polkit_path() @@ -221,7 +239,11 @@ class LinuxVPNLauncher(VPNLauncher): cmd = '#!/bin/sh\n' cmd += 'mkdir -p "%s"\n' % (to, ) - cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.UP_DOWN_FILE, to) + cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.UPDOWN_FILE, to) + cmd += 'ln -f %s/%s %s/%s\n' % (to, kls.UPDOWN_FILE, to, kls.UP_FILE) + cmd += 'ln -f %s/%s %s/%s\n' % (to, kls.UPDOWN_FILE, to, kls.DOWN_FILE) + cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.RESOLVCONF_FILE, to) + cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.RESOLV_UDATE_FILE, to) cmd += 'cp "%s" "%s"\n' % (pol_file, kls.POLKIT_PATH) cmd += 'chmod 644 "%s"\n' % (kls.POLKIT_PATH, ) diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index 99cae7f9..ab423bcd 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -226,6 +226,11 @@ class VPNLauncher(object): '--down', '\"%s\"' % (kls.DOWN_SCRIPT,) ] + args += [ + '--up-restart', + '--persist-tun' + ] + ########################################################### # For the time being we are disabling the usage of the # down-root plugin, because it doesn't quite work as -- cgit v1.2.3 From 0c2f23bd8a76ec8e36639c965ccc15303bd66b10 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 5 May 2014 12:18:09 -0500 Subject: use bitmask-root to bring up the firewall --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 23 ++++++++++------- src/leap/bitmask/services/eip/vpnprocess.py | 30 ++++++++++++++++++++++- 2 files changed, 43 insertions(+), 10 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 988970a5..ef670303 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -101,7 +101,12 @@ leapfile = lambda f: "%s/%s" % (SYSTEM_CONFIG, f) class LinuxVPNLauncher(VPNLauncher): PKEXEC_BIN = 'pkexec' + + # FIXME should get the absolute path to openvpn. See #5592 OPENVPN_BIN = 'openvpn' + BITMASK_ROOT = "/usr/sbin/bitmask-root" + + # FIXME get ABSOLUTE PATH OPENVPN_BIN_PATH = os.path.join( get_path_prefix(), "..", "apps", "eip", OPENVPN_BIN) @@ -114,23 +119,23 @@ class LinuxVPNLauncher(VPNLauncher): OPENVPN_DOWN_ROOT_BASE, OPENVPN_DOWN_ROOT_FILE) - UPDOWN_FILE = "vpn-updown" - - # vpn-up and vpn-down are hard-links to vpn-updown - UP_FILE = "vpn-up" - DOWN_FILE = "vpn-down" - UP_SCRIPT = leapfile(UP_FILE) - DOWN_SCRIPT = leapfile(DOWN_FILE) - + # XXX Should be able to pick the right resolvconf script + # on the fly. RESOLV_UPDATE_FILE = "resolv-update" RESOLV_UPDATE_SCRIPT = leapfile(RESOLV_UPDATE_FILE) RESOLVCONF_FILE = "update-resolv-conf" RESOLVCONF_SCRIPT = leapfile(RESOLVCONF_FILE) + UP_SCRIPT = RESOLVCONF_SCRIPT + DOWN_SCRIPT = RESOLVCONF_SCRIPT + UPDOWN_FILES = (UP_SCRIPT, DOWN_SCRIPT) + + # XXX GET BOTH POLKIT FILES: the one for vpn and the other for the wrapper POLKIT_PATH = LinuxPolicyChecker.get_polkit_path() - OTHER_FILES = (POLKIT_PATH, RESOLV_UPDATE_SCRIPT, RESOLVCONF_SCRIPT) + OTHER_FILES = (POLKIT_PATH, RESOLV_UPDATE_SCRIPT, RESOLVCONF_SCRIPT, + BITMASK_ROOT) @classmethod def maybe_pkexec(kls): diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index c7b8071c..71a21cdb 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -21,6 +21,7 @@ import logging import os import shutil import socket +import subprocess import sys from itertools import chain, repeat @@ -36,10 +37,11 @@ except ImportError: from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.services.eip import get_vpn_launcher +from leap.bitmask.services.eip import linuxvpnlauncher from leap.bitmask.services.eip.eipconfig import EIPConfig from leap.bitmask.services.eip.udstelnet import UDSTelnet from leap.bitmask.util import first -from leap.bitmask.platform_init import IS_MAC +from leap.bitmask.platform_init import IS_MAC, IS_LINUX from leap.common.check import leap_assert, leap_assert_type logger = logging.getLogger(__name__) @@ -181,6 +183,14 @@ class VPN(object): logger.info("Another vpn process is running. Will try to stop it.") vpnproc.stop_if_already_running() + # XXX we try to bring the firewall up + if IS_LINUX: + firewall_up = self._launch_firewall() + if not firewall_up: + logger.error("Could not bring firewall up, " + "aborting openvpn launch.") + return + cmd = vpnproc.getCommand() env = os.environ for key, val in vpnproc.vpn_env.items(): @@ -198,6 +208,24 @@ class VPN(object): self._pollers.extend(poll_list) self._start_pollers() + def _launch_firewall(self): + """ + Launch the firewall using the privileged wrapper. + + :returns: True if the exitcode of calling the root helper in a + subprocess is 0. + :rtype: bool + """ + # XXX this is a temporary solution for being able to use the root + # helper while we still control the openvpn process. + + # XXX could check for wrapper existence, check it's root owned etc. + # XXX could check that the iptables rules are in place. + + BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT + exitCode = subprocess.call([BM_ROOT, "firewall", "start"]) + return True if exitCode is 0 else False + def _kill_if_left_alive(self, tries=0): """ Check if the process is still alive, and sends a -- cgit v1.2.3 From 120fd991719897c9a62a797842036a030246ff7c Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 6 May 2014 20:14:39 -0500 Subject: pass gateways to firewall up --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 1 + src/leap/bitmask/services/eip/vpnlauncher.py | 52 +++++++++++++++-------- src/leap/bitmask/services/eip/vpnprocess.py | 16 +++++-- 3 files changed, 49 insertions(+), 20 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index ef670303..e1c8e680 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -220,6 +220,7 @@ class LinuxVPNLauncher(VPNLauncher): # we use `super` in order to send the class to use command = super(LinuxVPNLauncher, kls).get_vpn_command( eipconfig, providerconfig, socket_host, socket_port, openvpn_verb) + command.insert(0, kls.BITMASK_ROOT + "openvpn start") pkexec = kls.maybe_pkexec() if pkexec: diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index ab423bcd..c95545a2 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -105,12 +105,45 @@ class VPNLauncher(object): UP_SCRIPT = None DOWN_SCRIPT = None + @classmethod + @abstractmethod + def get_gateways(kls, eipconfig, providerconfig): + """ + Return the selected gateways for a given provider, looking at the EIP + config file. + + :param eipconfig: eip configuration object + :type eipconfig: EIPConfig + + :param providerconfig: provider specific configuration + :type providerconfig: ProviderConfig + + :rtype: list + """ + gateways = [] + leap_settings = LeapSettings() + domain = providerconfig.get_domain() + gateway_conf = leap_settings.get_selected_gateway(domain) + + if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: + gateway_selector = VPNGatewaySelector(eipconfig) + gateways = gateway_selector.get_gateways() + else: + gateways = [gateway_conf] + + if not gateways: + logger.error('No gateway was found!') + raise VPNLauncherException('No gateway was found!') + + logger.debug("Using gateways ips: {0}".format(', '.join(gateways))) + return gateways + @classmethod @abstractmethod def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port, openvpn_verb=1): """ - Returns the platform dependant vpn launching command + Return the platform-dependant vpn command for launching openvpn. Might raise: OpenVPNNotFoundException, @@ -154,22 +187,7 @@ class VPNLauncher(object): if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] - gateways = [] - leap_settings = LeapSettings() - domain = providerconfig.get_domain() - gateway_conf = leap_settings.get_selected_gateway(domain) - - if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: - gateway_selector = VPNGatewaySelector(eipconfig) - gateways = gateway_selector.get_gateways() - else: - gateways = [gateway_conf] - - if not gateways: - logger.error('No gateway was found!') - raise VPNLauncherException('No gateway was found!') - - logger.debug("Using gateways ips: {0}".format(', '.join(gateways))) + gateways = kls.get_gateways(providerconfig) for gw in gateways: args += ['--remote', gw, '1194', 'udp'] diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 71a21cdb..cbcdd5c6 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -185,7 +185,8 @@ class VPN(object): # XXX we try to bring the firewall up if IS_LINUX: - firewall_up = self._launch_firewall() + gateways = vpnproc.getGateways() + firewall_up = self._launch_firewall(gateways) if not firewall_up: logger.error("Could not bring firewall up, " "aborting openvpn launch.") @@ -208,10 +209,13 @@ class VPN(object): self._pollers.extend(poll_list) self._start_pollers() - def _launch_firewall(self): + def _launch_firewall(self, gateways): """ Launch the firewall using the privileged wrapper. + :param gateways: + :type gateways: list + :returns: True if the exitcode of calling the root helper in a subprocess is 0. :rtype: bool @@ -223,7 +227,7 @@ class VPN(object): # XXX could check that the iptables rules are in place. BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT - exitCode = subprocess.call([BM_ROOT, "firewall", "start"]) + exitCode = subprocess.call([BM_ROOT, "firewall", "start"] + gateways) return True if exitCode is 0 else False def _kill_if_left_alive(self, tries=0): @@ -861,6 +865,12 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): logger.debug("Running VPN with command: {0}".format(command)) return command + def getGateways(self): + gateways = self._launcher.get_gateways( + self._eipconfig, self._providerconfig) + print "getGateways --> ", gateways + return gateways + # shutdown def killProcess(self): -- cgit v1.2.3 From 6d18c78b384dc6624cde25cb41a998587661ffa5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 6 May 2014 21:16:18 -0500 Subject: use bitmask-root with pkexec --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 7 ++++--- src/leap/bitmask/services/eip/vpnlauncher.py | 5 ++++- src/leap/bitmask/services/eip/vpnprocess.py | 8 ++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index e1c8e680..791c318c 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -72,7 +72,6 @@ def _is_auth_agent_running(): 'ps aux | grep "[l]xpolkit"' ] is_running = [commands.getoutput(cmd) for cmd in polkit_options] - print "IS RUNNING ->", is_running return any(is_running) @@ -180,7 +179,6 @@ class LinuxVPNLauncher(VPNLauncher): """ # we use `super` in order to send the class to use missing = super(LinuxVPNLauncher, kls).missing_other_files() - print "MISSING OTHER", missing if flags.STANDALONE: polkit_file = LinuxPolicyChecker.get_polkit_path() @@ -220,7 +218,10 @@ class LinuxVPNLauncher(VPNLauncher): # we use `super` in order to send the class to use command = super(LinuxVPNLauncher, kls).get_vpn_command( eipconfig, providerconfig, socket_host, socket_port, openvpn_verb) - command.insert(0, kls.BITMASK_ROOT + "openvpn start") + + command.insert(0, kls.BITMASK_ROOT) + command.insert(1, "openvpn") + command.insert(2, "start") pkexec = kls.maybe_pkexec() if pkexec: diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index c95545a2..20b4d87d 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -125,8 +125,11 @@ class VPNLauncher(object): domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) + print "GETTING GATEWAYS -----" + if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: gateway_selector = VPNGatewaySelector(eipconfig) + print "auto: getting from selector" gateways = gateway_selector.get_gateways() else: gateways = [gateway_conf] @@ -187,7 +190,7 @@ class VPNLauncher(object): if openvpn_verb is not None: args += ['--verb', '%d' % (openvpn_verb,)] - gateways = kls.get_gateways(providerconfig) + gateways = kls.get_gateways(eipconfig, providerconfig) for gw in gateways: args += ['--remote', gw, '1194', 'udp'] diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index cbcdd5c6..beb33db8 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -226,8 +226,11 @@ class VPN(object): # XXX could check for wrapper existence, check it's root owned etc. # XXX could check that the iptables rules are in place. + print "LAUNCHING FIREWALL --", gateways + BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT - exitCode = subprocess.call([BM_ROOT, "firewall", "start"] + gateways) + exitCode = subprocess.call(["pkexec", + BM_ROOT, "firewall", "start"] + gateways) return True if exitCode is 0 else False def _kill_if_left_alive(self, tries=0): @@ -862,7 +865,8 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): if not isinstance(c, str): command[i] = c.encode(encoding) - logger.debug("Running VPN with command: {0}".format(command)) + logger.debug("Running VPN with command: ") + logger.debug("{0}".format(" ".join(command))) return command def getGateways(self): -- cgit v1.2.3 From d8d7d2b781aea558d7e39d397a85c15ac9839abb Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 08:14:01 -0500 Subject: tear the firewall down when openvpn is finished --- src/leap/bitmask/services/eip/vpnprocess.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index beb33db8..c09daf78 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -183,7 +183,7 @@ class VPN(object): logger.info("Another vpn process is running. Will try to stop it.") vpnproc.stop_if_already_running() - # XXX we try to bring the firewall up + # we try to bring the firewall up if IS_LINUX: gateways = vpnproc.getGateways() firewall_up = self._launch_firewall(gateways) @@ -226,13 +226,20 @@ class VPN(object): # XXX could check for wrapper existence, check it's root owned etc. # XXX could check that the iptables rules are in place. - print "LAUNCHING FIREWALL --", gateways - BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT exitCode = subprocess.call(["pkexec", BM_ROOT, "firewall", "start"] + gateways) return True if exitCode is 0 else False + def _tear_down_firewall(self): + """ + Tear the firewall down using the privileged wrapper. + """ + BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT + exitCode = subprocess.call(["pkexec", + BM_ROOT, "firewall", "stop"]) + return True if exitCode is 0 else False + def _kill_if_left_alive(self, tries=0): """ Check if the process is still alive, and sends a @@ -245,6 +252,17 @@ class VPN(object): while tries < self.TERMINATE_MAXTRIES: if self._vpnproc.transport.pid is None: logger.debug("Process has been happily terminated.") + + # we try to bring the firewall up + # XXX We could keep some state to be sure it was the + # user who did turn EIP off. + if IS_LINUX: + firewall_down = self._tear_down_firewall() + if firewall_down: + logger.debug("Firewall down") + else: + logger.warning("Could not tear firewall down") + return else: logger.debug("Process did not die, waiting...") -- cgit v1.2.3 From 2f47053b631df231e4fcceafef227cf905b660cc Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 09:18:23 -0500 Subject: only switch the fw down if user asked for eip down --- src/leap/bitmask/services/eip/vpnlauncher.py | 2 -- src/leap/bitmask/services/eip/vpnprocess.py | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index 20b4d87d..af3116f2 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -125,8 +125,6 @@ class VPNLauncher(object): domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) - print "GETTING GATEWAYS -----" - if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: gateway_selector = VPNGatewaySelector(eipconfig) print "auto: getting from selector" diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index c09daf78..a8b833d0 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -161,6 +161,8 @@ class VPN(object): self._signaler = kwargs['signaler'] self._openvpn_verb = flags.OPENVPN_VERBOSITY + self._user_stopped = False + def start(self, *args, **kwargs): """ Starts the openvpn subprocess. @@ -172,6 +174,7 @@ class VPN(object): :type kwargs: dict """ logger.debug('VPN: start') + self._user_stopped = False self._stop_pollers() kwargs['openvpn_verb'] = self._openvpn_verb kwargs['signaler'] = self._signaler @@ -242,7 +245,7 @@ class VPN(object): def _kill_if_left_alive(self, tries=0): """ - Check if the process is still alive, and sends a + Check if the process is still alive, and send a SIGKILL after a timeout period. :param tries: counter of tries, used in recursion @@ -256,7 +259,7 @@ class VPN(object): # we try to bring the firewall up # XXX We could keep some state to be sure it was the # user who did turn EIP off. - if IS_LINUX: + if IS_LINUX and self._user_stopped: firewall_down = self._tear_down_firewall() if firewall_down: logger.debug("Firewall down") @@ -298,6 +301,7 @@ class VPN(object): """ from twisted.internet import reactor self._stop_pollers() + self._user_stopped = True # First we try to be polite and send a SIGTERM... if self._vpnproc: -- cgit v1.2.3 From 14b208105a6417aefd351f5b38f33bb89358ddcd Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 11:24:53 -0500 Subject: hardcode openvpn binary for bundle --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 36 +++++------------------ src/leap/bitmask/services/eip/vpnlauncher.py | 35 ++++++++++++---------- 2 files changed, 27 insertions(+), 44 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 791c318c..6d54c27b 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -100,41 +100,19 @@ leapfile = lambda f: "%s/%s" % (SYSTEM_CONFIG, f) class LinuxVPNLauncher(VPNLauncher): PKEXEC_BIN = 'pkexec' - - # FIXME should get the absolute path to openvpn. See #5592 - OPENVPN_BIN = 'openvpn' BITMASK_ROOT = "/usr/sbin/bitmask-root" - # FIXME get ABSOLUTE PATH - OPENVPN_BIN_PATH = os.path.join( - get_path_prefix(), "..", "apps", "eip", OPENVPN_BIN) - # We assume this is there by our openvpn dependency, and # we will put it there on the bundle too. - # TODO adapt to the bundle path. - OPENVPN_DOWN_ROOT_BASE = "/usr/lib/openvpn/" - OPENVPN_DOWN_ROOT_FILE = "openvpn-plugin-down-root.so" - OPENVPN_DOWN_ROOT_PATH = "%s/%s" % ( - OPENVPN_DOWN_ROOT_BASE, - OPENVPN_DOWN_ROOT_FILE) - - # XXX Should be able to pick the right resolvconf script - # on the fly. - RESOLV_UPDATE_FILE = "resolv-update" - RESOLV_UPDATE_SCRIPT = leapfile(RESOLV_UPDATE_FILE) - - RESOLVCONF_FILE = "update-resolv-conf" - RESOLVCONF_SCRIPT = leapfile(RESOLVCONF_FILE) - - UP_SCRIPT = RESOLVCONF_SCRIPT - DOWN_SCRIPT = RESOLVCONF_SCRIPT - - UPDOWN_FILES = (UP_SCRIPT, DOWN_SCRIPT) + if flags.STANDALONE: + OPENVPN_BIN_PATH = "/usr/sbin/leap-openvpn" + else: + OPENVPN_BIN_PATH = "/usr/sbin/openvpn" - # XXX GET BOTH POLKIT FILES: the one for vpn and the other for the wrapper POLKIT_PATH = LinuxPolicyChecker.get_polkit_path() - OTHER_FILES = (POLKIT_PATH, RESOLV_UPDATE_SCRIPT, RESOLVCONF_SCRIPT, - BITMASK_ROOT) + + # XXX openvpn binary TOO + OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT) @classmethod def maybe_pkexec(kls): diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index af3116f2..ed49ba59 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -168,16 +168,19 @@ class VPNLauncher(object): leap_assert_type(eipconfig, EIPConfig) leap_assert_type(providerconfig, ProviderConfig) - kwargs = {} - if flags.STANDALONE: - kwargs['path_extension'] = os.path.join( - get_path_prefix(), "..", "apps", "eip") - - openvpn_possibilities = which(kls.OPENVPN_BIN, **kwargs) - if len(openvpn_possibilities) == 0: + # XXX this still has to be changed on osx and windows accordingly + #kwargs = {} + #openvpn_possibilities = which(kls.OPENVPN_BIN, **kwargs) + #if not openvpn_possibilities: + #raise OpenVPNNotFoundException() + #openvpn = first(openvpn_possibilities) + # ----------------------------------------- + if not os.path.isfile(kls.OPENVPN_BIN_PATH): + logger.warning("Could not find openvpn bin in path %s" % ( + kls.OPENVPN_BIN_PATH)) raise OpenVPNNotFoundException() - openvpn = first(openvpn_possibilities) + openvpn = kls.OPENVPN_BIN_PATH args = [] args += [ @@ -295,13 +298,15 @@ class VPNLauncher(object): :rtype: list """ - leap_assert(kls.UPDOWN_FILES is not None, - "Need to define UPDOWN_FILES for this particular " - "launcher before calling this method") - file_exist = partial(_has_updown_scripts, warn=False) - zipped = zip(kls.UPDOWN_FILES, map(file_exist, kls.UPDOWN_FILES)) - missing = filter(lambda (path, exists): exists is False, zipped) - return [path for path, exists in missing] + # XXX remove when we ditch UPDOWN in osx and win too + #leap_assert(kls.UPDOWN_FILES is not None, + #"Need to define UPDOWN_FILES for this particular " + #"launcher before calling this method") + #file_exist = partial(_has_updown_scripts, warn=False) + #zipped = zip(kls.UPDOWN_FILES, map(file_exist, kls.UPDOWN_FILES)) + #missing = filter(lambda (path, exists): exists is False, zipped) + #return [path for path, exists in missing] + return [] @classmethod def missing_other_files(kls): -- cgit v1.2.3 From ca0e9b85a831f716a0959c5fdb9dbb571515de97 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 15:42:56 -0500 Subject: tear down fw on quit-action too --- src/leap/bitmask/services/eip/vpnprocess.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index a8b833d0..420db971 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -223,9 +223,6 @@ class VPN(object): subprocess is 0. :rtype: bool """ - # XXX this is a temporary solution for being able to use the root - # helper while we still control the openvpn process. - # XXX could check for wrapper existence, check it's root owned etc. # XXX could check that the iptables rules are in place. @@ -257,8 +254,6 @@ class VPN(object): logger.debug("Process has been happily terminated.") # we try to bring the firewall up - # XXX We could keep some state to be sure it was the - # user who did turn EIP off. if IS_LINUX and self._user_stopped: firewall_down = self._tear_down_firewall() if firewall_down: @@ -310,12 +305,17 @@ class VPN(object): # ...but we also trigger a countdown to be unpolite # if strictly needed. - - # XXX Watch out! This will fail NOW since we are running - # openvpn as root as a workaround for some connection issues. reactor.callLater( self.TERMINATE_WAIT, self._kill_if_left_alive) + if shutdown: + if IS_LINUX and self._user_stopped: + firewall_down = self._tear_down_firewall() + if firewall_down: + logger.debug("Firewall down") + else: + logger.warning("Could not tear firewall down") + def _start_pollers(self): """ Iterate through the registered observers @@ -892,9 +892,13 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): return command def getGateways(self): + """ + Get the gateways from the appropiate launcher. + + :rtype: list + """ gateways = self._launcher.get_gateways( self._eipconfig, self._providerconfig) - print "getGateways --> ", gateways return gateways # shutdown -- cgit v1.2.3 From d68e35c611638a57bbda99665f9685e5ae6fcd23 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 7 May 2014 17:24:12 -0500 Subject: introduce delay on shutdown after resolvconf was daemonized --- src/leap/bitmask/services/eip/vpnlauncher.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index ed49ba59..dc72f276 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -127,7 +127,6 @@ class VPNLauncher(object): if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: gateway_selector = VPNGatewaySelector(eipconfig) - print "auto: getting from selector" gateways = gateway_selector.get_gateways() else: gateways = [gateway_conf] -- cgit v1.2.3 From 745ae7f55836ff331d9176b52cc98df451a3c2ef Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 8 May 2014 10:41:55 -0500 Subject: change paths for installing the latest helpers --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 83 +++++++++++++---------- 1 file changed, 48 insertions(+), 35 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 6d54c27b..9e6176cb 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -25,7 +25,6 @@ import sys import time from leap.bitmask.config import flags -from leap.bitmask.util import privilege_policies from leap.bitmask.util.privilege_policies import LinuxPolicyChecker from leap.common.files import which from leap.bitmask.services.eip.vpnlauncher import VPNLauncher @@ -111,8 +110,15 @@ class LinuxVPNLauncher(VPNLauncher): POLKIT_PATH = LinuxPolicyChecker.get_polkit_path() + if flags.STANDALONE: + RESOLVCONF_BIN_PATH = "/usr/local/sbin/leap-resolvconf" + else: + # this only will work with debian/ubuntu distros. + RESOLVCONF_BIN_PATH = "/sbin/resolvconf" + # XXX openvpn binary TOO - OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT) + OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT, OPENVPN_BIN_PATH, + RESOLVCONF_BIN_PATH) @classmethod def maybe_pkexec(kls): @@ -144,27 +150,20 @@ class LinuxVPNLauncher(VPNLauncher): logger.warning("System has no pkexec") raise EIPNoPkexecAvailable() - @classmethod - def missing_other_files(kls): - """ - 'Extend' the VPNLauncher's missing_other_files to check if the polkit - 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 - """ + #@classmethod + #def missing_other_files(kls): + #""" + #'Extend' the VPNLauncher's missing_other_files to check if the polkit + #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() - - 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 + #missing = super(LinuxVPNLauncher, kls).missing_other_files() + #return missing @classmethod def get_vpn_command(kls, eipconfig, providerconfig, socket_host, @@ -208,30 +207,44 @@ class LinuxVPNLauncher(VPNLauncher): return command @classmethod - def cmd_for_missing_scripts(kls, frompath, pol_file): + def cmd_for_missing_scripts(kls, frompath): """ Returns a sh script that can copy the missing files. - :param frompath: The path where the up/down scripts live + :param frompath: The path where the helper files live :type frompath: str - :param pol_file: The path where the dynamically generated - policy file lives - :type pol_file: str :rtype: str """ - to = kls.SYSTEM_CONFIG + # no system config for now + # sys_config = kls.SYSTEM_CONFIG + (polkit_file, openvpn_bin_file, + bitmask_root_file, resolvconf_bin_file) = map( + lambda p: os.path.split(p)[-1], + (kls.POLKIT_PATH, kls.OPENVPN_BIN_PATH, + kls.BITMASK_ROOT, kls.RESOLVCONF_BIN_PATH)) cmd = '#!/bin/sh\n' - cmd += 'mkdir -p "%s"\n' % (to, ) - cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.UPDOWN_FILE, to) - cmd += 'ln -f %s/%s %s/%s\n' % (to, kls.UPDOWN_FILE, to, kls.UP_FILE) - cmd += 'ln -f %s/%s %s/%s\n' % (to, kls.UPDOWN_FILE, to, kls.DOWN_FILE) - cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.RESOLVCONF_FILE, to) - cmd += 'cp "%s/%s" "%s"\n' % (frompath, kls.RESOLV_UDATE_FILE, to) - cmd += 'cp "%s" "%s"\n' % (pol_file, kls.POLKIT_PATH) + cmd += 'mkdir -p /usr/local/sbin\n' + + cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, polkit_file), + kls.POLKIT_PATH) cmd += 'chmod 644 "%s"\n' % (kls.POLKIT_PATH, ) + cmd += 'cp "%s" "%s"\n' % (os.path.join(frompath, bitmask_root_file), + kls.BITMASK_ROOT) + cmd += 'chmod 744 "%s"\n' % (kls.BITMASK_ROOT, ) + + if flags.STANDALONE: + cmd += 'cp "%s" "%s"\n' % ( + os.path.join(frompath, openvpn_bin_file), + kls.OPENVPN_BIN_PATH) + cmd += 'chmod 744 "%s"\n' % (kls.POLKIT_PATH, ) + + cmd += 'cp "%s" "%s"\n' % ( + os.path.join(frompath, resolvconf_bin_file), + kls.RESOLVCONF_BIN_PATH) + cmd += 'chmod 744 "%s"\n' % (kls.POLKIT_PATH, ) return cmd @classmethod -- cgit v1.2.3 From 8a4b9c176a5ca9c9236283b1d6191872c0d3582b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 15 May 2014 08:43:53 -0500 Subject: remove commented block, fix typo --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 15 --------------- src/leap/bitmask/services/eip/vpnprocess.py | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 9e6176cb..1f0813e0 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -150,21 +150,6 @@ class LinuxVPNLauncher(VPNLauncher): logger.warning("System has no pkexec") raise EIPNoPkexecAvailable() - #@classmethod - #def missing_other_files(kls): - #""" - #'Extend' the VPNLauncher's missing_other_files to check if the polkit - #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() - #return missing - @classmethod def get_vpn_command(kls, eipconfig, providerconfig, socket_host, socket_port="unix", openvpn_verb=1): diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 420db971..d57eafe2 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -253,7 +253,7 @@ class VPN(object): if self._vpnproc.transport.pid is None: logger.debug("Process has been happily terminated.") - # we try to bring the firewall up + # we try to tear the firewall down if IS_LINUX and self._user_stopped: firewall_down = self._tear_down_firewall() if firewall_down: -- cgit v1.2.3 From 825ac1fcb8bf5a0ac3ae44442e287d207374ca14 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 15 May 2014 08:46:49 -0500 Subject: remove up-restart option. Related: #5669 --- src/leap/bitmask/services/eip/vpnlauncher.py | 33 ---------------------------- 1 file changed, 33 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index dc72f276..1498632a 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -198,11 +198,6 @@ class VPNLauncher(object): args += [ '--client', '--dev', 'tun', - ############################################################## - # persist-tun makes ping-restart fail because it leaves a - # broken routing table - ############################################################## - # '--persist-tun', '--persist-key', '--tls-client', '--remote-cert-tls', @@ -215,15 +210,6 @@ class VPNLauncher(object): user = getpass.getuser() - ############################################################## - # The down-root plugin fails in some situations, so we don't - # drop privs for the time being - ############################################################## - # args += [ - # '--user', user, - # '--group', grp.getgrgid(os.getgroups()[-1]).gr_name - # ] - if socket_port == "unix": # that's always the case for linux args += [ '--management-client-user', user @@ -247,25 +233,6 @@ class VPNLauncher(object): '--down', '\"%s\"' % (kls.DOWN_SCRIPT,) ] - args += [ - '--up-restart', - '--persist-tun' - ] - - ########################################################### - # For the time being we are disabling the usage of the - # down-root plugin, because it doesn't quite work as - # expected (i.e. it doesn't run route -del as root - # when finishing, so it fails to properly - # restart/quit) - ########################################################### - # if _has_updown_scripts(kls.OPENVPN_DOWN_PLUGIN): - # args += [ - # '--plugin', kls.OPENVPN_DOWN_ROOT, - # '\'%s\'' % kls.DOWN_SCRIPT # for OSX - # '\'script_type=down %s\'' % kls.DOWN_SCRIPT # for Linux - # ] - args += [ '--cert', eipconfig.get_client_cert_path(providerconfig), '--key', eipconfig.get_client_cert_path(providerconfig), -- cgit v1.2.3 From 19391a9eb7ac4b09dd86c4d722291dbda140dde0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 15 May 2014 08:50:07 -0500 Subject: allow osx and win to continue with updown scripts for the time being --- src/leap/bitmask/services/eip/vpnlauncher.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index 1498632a..dcb48e8a 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -25,14 +25,12 @@ import stat from abc import ABCMeta, abstractmethod from functools import partial -from leap.bitmask.config import flags from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.platform_init import IS_LINUX from leap.bitmask.services.eip.eipconfig import EIPConfig, VPNGatewaySelector -from leap.bitmask.util import first -from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type -from leap.common.files import which + logger = logging.getLogger(__name__) @@ -264,15 +262,18 @@ class VPNLauncher(object): :rtype: list """ - # XXX remove when we ditch UPDOWN in osx and win too - #leap_assert(kls.UPDOWN_FILES is not None, - #"Need to define UPDOWN_FILES for this particular " - #"launcher before calling this method") - #file_exist = partial(_has_updown_scripts, warn=False) - #zipped = zip(kls.UPDOWN_FILES, map(file_exist, kls.UPDOWN_FILES)) - #missing = filter(lambda (path, exists): exists is False, zipped) - #return [path for path, exists in missing] - return [] + # FIXME + # XXX remove method when we ditch UPDOWN in osx and win too + if IS_LINUX: + return [] + else: + leap_assert(kls.UPDOWN_FILES is not None, + "Need to define UPDOWN_FILES for this particular " + "launcher before calling this method") + file_exist = partial(_has_updown_scripts, warn=False) + zipped = zip(kls.UPDOWN_FILES, map(file_exist, kls.UPDOWN_FILES)) + missing = filter(lambda (path, exists): exists is False, zipped) + return [path for path, exists in missing] @classmethod def missing_other_files(kls): -- cgit v1.2.3 From dfbe8c4f0158366e91ea5118e5aa68c07d28ddbf Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 15 May 2014 09:25:25 -0500 Subject: avoid openvp soft-restart. Closes: #5669 --- src/leap/bitmask/services/eip/vpnprocess.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index d57eafe2..1559ea8b 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -68,9 +68,8 @@ class VPNObserver(object): 'Network is unreachable (code=101)',), 'PROCESS_RESTART_TLS': ( "SIGUSR1[soft,tls-error]",), - # Let ping-restart work as it should - # 'PROCESS_RESTART_PING': ( - # "SIGUSR1[soft,ping-restart]",), + 'PROCESS_RESTART_PING': ( + "SIGTERM[soft,ping-restart]",), 'INITIALIZATION_COMPLETED': ( "Initialization Sequence Completed",), } @@ -296,7 +295,10 @@ class VPN(object): """ from twisted.internet import reactor self._stop_pollers() - self._user_stopped = True + + # We assume that the only valid shutodowns are initiated + # by an user action. + self._user_stopped = shutdown # First we try to be polite and send a SIGTERM... if self._vpnproc: -- cgit v1.2.3