From 5c37f0a24a5304b8b986385c023875e6a2bf6b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Mon, 19 May 2014 11:48:40 -0300 Subject: Add OPENVPN_BIN_PATH for OSX --- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index a03bfc44..41d75052 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -52,6 +52,8 @@ class DarwinVPNLauncher(VPNLauncher): OPENVPN_PATH = "%s/Contents/Resources/openvpn" % (INSTALL_PATH,) OPENVPN_PATH_ESCAPED = "%s/Contents/Resources/openvpn" % ( INSTALL_PATH_ESCAPED,) + OPENVPN_BIN_PATH = "%s/Contents/Resources/%s" % (INSTALL_PATH, + OPENVPN_BIN) UP_SCRIPT = "%s/client.up.sh" % (OPENVPN_PATH,) DOWN_SCRIPT = "%s/client.down.sh" % (OPENVPN_PATH,) -- cgit v1.2.3 From 62555000b628f3389370135a6f58a3deeb63ae22 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 19 May 2014 23:58:06 -0500 Subject: backward compat for psutil p.cmdline. Closes: #5689 --- src/leap/bitmask/services/eip/vpnprocess.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (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 1559ea8b..734b88df 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -30,9 +30,11 @@ import psutil try: # psutil < 2.0.0 from psutil.error import AccessDenied as psutil_AccessDenied + PSUTIL_2 = False except ImportError: # psutil >= 2.0.0 from psutil import AccessDenied as psutil_AccessDenied + PSUTIL_2 = True from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig @@ -676,7 +678,13 @@ class VPNManager(object): # we need to be able to filter out arguments in the form # --openvpn-foo, since otherwise we are shooting ourselves # in the feet. - if any(map(lambda s: s.find("LEAPOPENVPN") != -1, p.cmdline)): + + if PSUTIL_2: + cmdline = p.cmdline() + else: + cmdline = p.cmdline + if any(map(lambda s: s.find( + "LEAPOPENVPN") != -1, cmdline)): openvpn_process = p break except psutil_AccessDenied: -- cgit v1.2.3 From 72b7d49966637c019e97fae7f186774097e5e96f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 28 Apr 2014 18:19:36 -0300 Subject: Refactor SoledadBootstrapper to backend. --- src/leap/bitmask/services/mail/conductor.py | 6 +- .../services/soledad/soledadbootstrapper.py | 101 +++++++++++---------- 2 files changed, 56 insertions(+), 51 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 1766a39d..b4e97ac1 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -72,11 +72,9 @@ class IMAPControl(object): from leap.bitmask.config import flags logger.debug('Starting imap service') - leap_assert(sameProxiedObjects(self._soledad, None) - is not True, + leap_assert(not sameProxiedObjects(self._soledad, None), "We need a non-null soledad for initializing imap service") - leap_assert(sameProxiedObjects(self._keymanager, None) - is not True, + leap_assert(not sameProxiedObjects(self._keymanager, None), "We need a non-null keymanager for initializing imap " "service") diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 6bb7c036..c015f5b7 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -25,7 +25,6 @@ import sys from ssl import SSLError from sqlite3 import ProgrammingError as sqlite_ProgrammingError -from PySide import QtCore from u1db import errors as u1db_errors from twisted.internet import threads from zope.proxy import sameProxiedObjects @@ -134,16 +133,11 @@ class SoledadBootstrapper(AbstractBootstrapper): MAX_INIT_RETRIES = 10 MAX_SYNC_RETRIES = 10 - # All dicts returned are of the form - # {"passed": bool, "error": str} - download_config = QtCore.Signal(dict) - gen_key = QtCore.Signal(dict) - local_only_ready = QtCore.Signal(dict) - soledad_invalid_auth_token = QtCore.Signal() - soledad_failed = QtCore.Signal() + def __init__(self, signaler=None): + AbstractBootstrapper.__init__(self, signaler) - def __init__(self): - AbstractBootstrapper.__init__(self) + if signaler is not None: + self._cancel_signal = signaler.SOLEDAD_CANCELLED_BOOTSTRAP self._provider_config = None self._soledad_config = None @@ -181,16 +175,22 @@ class SoledadBootstrapper(AbstractBootstrapper): Instantiate Soledad for offline use. :param username: full user id (user@provider) - :type username: basestring + :type username: str or unicode :param password: the soledad passphrase :type password: unicode :param uuid: the user uuid - :type uuid: basestring + :type uuid: str or unicode """ print "UUID ", uuid self._address = username + self._password = password self._uuid = uuid - return self.load_and_sync_soledad(uuid, offline=True) + try: + self.load_and_sync_soledad(uuid, offline=True) + self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FINISHED) + except Exception: + # TODO: we should handle more specific exceptions in here + self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FAILED) def _get_soledad_local_params(self, uuid, offline=False): """ @@ -245,7 +245,7 @@ class SoledadBootstrapper(AbstractBootstrapper): 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 + Initialize soledad, retry if necessary and raise an exception if we can't succeed. :param uuid: user identifier @@ -263,19 +263,22 @@ class SoledadBootstrapper(AbstractBootstrapper): :param auth token: auth token :type auth_token: str """ - init_tries = self.MAX_INIT_RETRIES - while init_tries > 0: + init_tries = 1 + while init_tries <= self.MAX_INIT_RETRIES: try: + logger.debug("Trying to init soledad....") 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 + init_tries += 1 + msg = "Init failed, retrying... (retry {0} of {1})".format( + init_tries, self.MAX_INIT_RETRIES) + logger.warning(msg) continue - self.soledad_failed.emit() raise SoledadInitError() def load_and_sync_soledad(self, uuid=None, offline=False): @@ -306,9 +309,8 @@ class SoledadBootstrapper(AbstractBootstrapper): leap_assert(not sameProxiedObjects(self._soledad, None), "Null soledad, error while initializing") - if flags.OFFLINE is True: + if flags.OFFLINE: self._init_keymanager(self._address, token) - self.local_only_ready.emit({self.PASSED_KEY: True}) else: try: address = make_address( @@ -353,9 +355,10 @@ class SoledadBootstrapper(AbstractBootstrapper): Do several retries to get an initial soledad sync. """ # and now, let's sync - sync_tries = self.MAX_SYNC_RETRIES - while sync_tries > 0: + sync_tries = 1 + while sync_tries <= self.MAX_SYNC_RETRIES: try: + logger.debug("Trying to sync soledad....") self._try_soledad_sync() logger.debug("Soledad has been synced.") # so long, and thanks for all the fish @@ -368,19 +371,20 @@ class SoledadBootstrapper(AbstractBootstrapper): # retry strategy can be pushed to u1db, or at least # it's something worthy to talk about with the # ubuntu folks. - sync_tries -= 1 + sync_tries += 1 + msg = "Sync failed, retrying... (retry {0} of {1})".format( + sync_tries, self.MAX_SYNC_RETRIES) + logger.warning(msg) continue except InvalidAuthTokenError: - self.soledad_invalid_auth_token.emit() + self._signaler.signal( + self._signaler.SOLEDAD_INVALID_AUTH_TOKEN) raise except Exception as e: logger.exception("Unhandled error while syncing " "soledad: %r" % (e,)) break - # reached bottom, failed to sync - # and there's nothing we can do... - self.soledad_failed.emit() raise SoledadSyncError() def _try_soledad_init(self, uuid, secrets_path, local_db_path, @@ -443,7 +447,6 @@ class SoledadBootstrapper(AbstractBootstrapper): Raises SoledadSyncError if not successful. """ try: - logger.debug("trying to sync soledad....") self._soledad.sync() except SSLError as exc: logger.error("%r" % (exc,)) @@ -467,7 +470,6 @@ class SoledadBootstrapper(AbstractBootstrapper): """ Download the Soledad config for the given provider """ - leap_assert(self._provider_config, "We need a provider configuration!") logger.debug("Downloading Soledad config for %s" % @@ -480,14 +482,6 @@ class SoledadBootstrapper(AbstractBootstrapper): self._session, self._download_if_needed) - # soledad config is ok, let's proceed to load and sync soledad - # XXX but honestly, this is a pretty strange entry point for that. - # it feels like it should be the other way around: - # load_and_sync, and from there, if needed, call download_config - - uuid = self.srpauth.get_uuid() - self.load_and_sync_soledad(uuid) - def _get_gpg_bin_path(self): """ Return the path to gpg binary. @@ -574,7 +568,7 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.exception(exc) # but we do not raise - def _gen_key(self, _): + def _gen_key(self): """ Generates the key pair if needed, uploads it to the webapp and nickserver @@ -613,10 +607,7 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.debug("Key generated successfully.") - def run_soledad_setup_checks(self, - provider_config, - user, - password, + def run_soledad_setup_checks(self, provider_config, user, password, download_if_needed=False): """ Starts the checks needed for a new soledad setup @@ -640,9 +631,25 @@ class SoledadBootstrapper(AbstractBootstrapper): self._user = user self._password = password - cb_chain = [ - (self._download_config, self.download_config), - (self._gen_key, self.gen_key) - ] + if flags.OFFLINE: + signal_finished = self._signaler.SOLEDAD_OFFLINE_FINISHED + signal_failed = self._signaler.SOLEDAD_OFFLINE_FAILED + else: + signal_finished = self._signaler.SOLEDAD_BOOTSTRAP_FINISHED + signal_failed = self._signaler.SOLEDAD_BOOTSTRAP_FAILED + + try: + self._download_config() + + # soledad config is ok, let's proceed to load and sync soledad + uuid = self.srpauth.get_uuid() + self.load_and_sync_soledad(uuid) + + if not flags.OFFLINE: + self._gen_key() - return self.addCallbackChain(cb_chain) + self._signaler.signal(signal_finished) + except Exception as e: + # TODO: we should handle more specific exceptions in here + logger.exception("Error while bootstrapping Soledad: %r" % (e, )) + self._signaler.signal(signal_failed) -- cgit v1.2.3 From 2f57c31cda8208340322efd5c02f8b9120ce29aa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 6 May 2014 16:16:40 -0300 Subject: Separate imap/smtp logic from conductor. --- src/leap/bitmask/services/mail/conductor.py | 104 +++++++++-------------- src/leap/bitmask/services/mail/imapcontroller.py | 98 +++++++++++++++++++++ 2 files changed, 136 insertions(+), 66 deletions(-) create mode 100644 src/leap/bitmask/services/mail/imapcontroller.py (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 b4e97ac1..aa22afe4 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -19,15 +19,15 @@ Mail Services Conductor """ import logging -from zope.proxy import sameProxiedObjects +from twisted.internet import threads +from leap.bitmask.config import flags from leap.bitmask.gui import statemachines 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.services.mail.imapcontroller import IMAPController -from leap.common.check import leap_assert from leap.common.events import events_pb2 as leap_events from leap.common.events import register as leap_register @@ -39,15 +39,20 @@ class IMAPControl(object): """ Methods related to IMAP control. """ - def __init__(self): + def __init__(self, soledad, keymanager): """ Initializes smtp variables. + + :param soledad: a transparent proxy that eventually will point to a + Soledad Instance. + :type soledad: zope.proxy.ProxyBase + :param keymanager: a transparent proxy that eventually will point to a + Keymanager Instance. + :type keymanager: zope.proxy.ProxyBase """ self.imap_machine = None - self.imap_service = None - self.imap_port = None - self.imap_factory = None self.imap_connection = None + self._imap_controller = IMAPController(soledad, keymanager) leap_register(signal=leap_events.IMAP_SERVICE_STARTED, callback=self._handle_imap_events, @@ -55,10 +60,13 @@ class IMAPControl(object): leap_register(signal=leap_events.IMAP_SERVICE_FAILED_TO_START, callback=self._handle_imap_events, reqcbk=lambda req, resp: None) + leap_register(signal=leap_events.IMAP_CLIENT_LOGIN, + callback=self._handle_imap_events, + reqcbk=lambda req, resp: None) def set_imap_connection(self, imap_connection): """ - Sets the imap connection to an initialized connection. + Set the imap connection to an initialized connection. :param imap_connection: an initialized imap connection :type imap_connection: IMAPConnection instance. @@ -67,65 +75,23 @@ class IMAPControl(object): def start_imap_service(self): """ - Starts imap service. + Start imap service. """ - from leap.bitmask.config import flags - - logger.debug('Starting imap service') - leap_assert(not sameProxiedObjects(self._soledad, None), - "We need a non-null soledad for initializing imap service") - leap_assert(not sameProxiedObjects(self._keymanager, None), - "We need a non-null keymanager for initializing imap " - "service") - - offline = flags.OFFLINE - self.imap_service, self.imap_port, \ - self.imap_factory = imap.start_imap_service( - self._soledad, - self._keymanager, - userid=self.userid, - offline=offline) - - if offline is False: - logger.debug("Starting loop") - self.imap_service.start_loop() + threads.deferToThread(self._imap_controller.start_imap_service, + self.userid, flags.OFFLINE) def stop_imap_service(self, cv): """ - Stops imap service (fetcher, factory and port). + Stop imap service (fetcher, factory and port). :param cv: A condition variable to which we can signal when imap indeed stops. :type cv: threading.Condition """ self.imap_connection.qtsigs.disconnecting_signal.emit() - # TODO We should homogenize both services. - if self.imap_service is not None: - logger.debug('Stopping imap service.') - # Stop the loop call in the fetcher - self.imap_service.stop() - self.imap_service = None - # Stop listening on the IMAP port - self.imap_port.stopListening() - # Stop the protocol - self.imap_factory.theAccount.closed = True - self.imap_factory.doStop(cv) - else: - # main window does not have to wait because there's no service to - # be stopped, so we release the condition variable - cv.acquire() - cv.notify() - cv.release() - - def fetch_incoming_mail(self): - """ - Fetches incoming mail. - """ - if self.imap_service: - logger.debug('Client connected, fetching mail...') - self.imap_service.fetch() - - # handle events + logger.debug('Stopping imap service.') + + self._imap_controller.stop_imap_service(cv) def _handle_imap_events(self, req): """ @@ -135,25 +101,31 @@ class IMAPControl(object): :type req: leap.common.events.events_pb2.SignalRequest """ if req.event == leap_events.IMAP_SERVICE_STARTED: - self.on_imap_connected() + self._on_imap_connected() elif req.event == leap_events.IMAP_SERVICE_FAILED_TO_START: - self.on_imap_failed() + self._on_imap_failed() + elif req.event == leap_events.IMAP_CLIENT_LOGIN: + self._on_mail_client_logged_in() - # emit connection signals + def _on_mail_client_logged_in(self): + """ + On mail client logged in, fetch incoming mail. + """ + self._controller.imap_service_fetch() - def on_imap_connecting(self): + def _on_imap_connecting(self): """ Callback for IMAP connecting state. """ self.imap_connection.qtsigs.connecting_signal.emit() - def on_imap_connected(self): + def _on_imap_connected(self): """ Callback for IMAP connected state. """ self.imap_connection.qtsigs.connected_signal.emit() - def on_imap_failed(self): + def _on_imap_failed(self): """ Callback for IMAP failed state. """ @@ -197,7 +169,8 @@ class SMTPControl(object): :type download_if_needed: bool """ self.smtp_connection.qtsigs.connecting_signal.emit() - self.smtp_bootstrapper.start_smtp_service( + threads.deferToThread( + self.smtp_bootstrapper.start_smtp_service, provider_config, self.smtp_config, self._keymanager, self.userid, download_if_needed) @@ -258,12 +231,11 @@ class MailConductor(IMAPControl, SMTPControl): :param soledad: a transparent proxy that eventually will point to a Soledad Instance. :type soledad: zope.proxy.ProxyBase - :param keymanager: a transparent proxy that eventually will point to a Keymanager Instance. :type keymanager: zope.proxy.ProxyBase """ - IMAPControl.__init__(self) + IMAPControl.__init__(self, soledad, keymanager) SMTPControl.__init__(self) self._soledad = soledad self._keymanager = keymanager diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py new file mode 100644 index 00000000..efca5867 --- /dev/null +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# imapcontroller.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +IMAP service controller. +""" +import logging + +from leap.bitmask.services.mail import imap + + +logger = logging.getLogger(__name__) + + +class IMAPController(object): + """ + IMAP Controller. + """ + def __init__(self, soledad, keymanager): + """ + Initialize IMAP variables. + + :param soledad: a transparent proxy that eventually will point to a + Soledad Instance. + :type soledad: zope.proxy.ProxyBase + :param keymanager: a transparent proxy that eventually will point to a + Keymanager Instance. + :type keymanager: zope.proxy.ProxyBase + """ + self._soledad = soledad + self._keymanager = keymanager + + self.imap_service = None + self.imap_port = None + self.imap_factory = None + + def start_imap_service(self, userid, offline=False): + """ + Start IMAP service. + """ + logger.debug('Starting imap service') + + self.imap_service, self.imap_port, \ + self.imap_factory = imap.start_imap_service( + self._soledad, + self._keymanager, + userid=userid, + offline=offline) + + if offline is False: + logger.debug("Starting loop") + self.imap_service.start_loop() + + def stop_imap_service(self, cv): + """ + Stop IMAP service (fetcher, factory and port). + + :param cv: A condition variable to which we can signal when imap + indeed stops. + :type cv: threading.Condition + """ + if self.imap_service is not None: + # Stop the loop call in the fetcher + self.imap_service.stop() + self.imap_service = None + + # Stop listening on the IMAP port + self.imap_port.stopListening() + + # Stop the protocol + self.imap_factory.theAccount.closed = True + self.imap_factory.doStop(cv) + else: + # Release the condition variable so the caller doesn't have to wait + cv.acquire() + cv.notify() + cv.release() + + def fetch_incoming_mail(self): + """ + Fetch incoming mail. + """ + if self.imap_service: + logger.debug('Client connected, fetching mail...') + self.imap_service.fetch() -- cgit v1.2.3 From 3a81b31204680bf2ba0abe26467aef201cf030fa Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 14 May 2014 12:25:00 -0300 Subject: Move Mail logic to backend. --- src/leap/bitmask/services/mail/conductor.py | 56 +++++----------------- src/leap/bitmask/services/mail/imapcontroller.py | 5 ++ src/leap/bitmask/services/mail/smtpbootstrapper.py | 24 +++++----- .../services/soledad/soledadbootstrapper.py | 2 + 4 files changed, 33 insertions(+), 54 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 aa22afe4..67bc007e 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -19,14 +19,9 @@ Mail Services Conductor """ import logging -from twisted.internet import threads - from leap.bitmask.config import flags from leap.bitmask.gui import statemachines from leap.bitmask.services.mail import connection as mail_connection -from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper -from leap.bitmask.services.mail.smtpconfig import SMTPConfig -from leap.bitmask.services.mail.imapcontroller import IMAPController from leap.common.events import events_pb2 as leap_events from leap.common.events import register as leap_register @@ -39,20 +34,12 @@ class IMAPControl(object): """ Methods related to IMAP control. """ - def __init__(self, soledad, keymanager): + def __init__(self): """ Initializes smtp variables. - - :param soledad: a transparent proxy that eventually will point to a - Soledad Instance. - :type soledad: zope.proxy.ProxyBase - :param keymanager: a transparent proxy that eventually will point to a - Keymanager Instance. - :type keymanager: zope.proxy.ProxyBase """ self.imap_machine = None self.imap_connection = None - self._imap_controller = IMAPController(soledad, keymanager) leap_register(signal=leap_events.IMAP_SERVICE_STARTED, callback=self._handle_imap_events, @@ -77,12 +64,11 @@ class IMAPControl(object): """ Start imap service. """ - threads.deferToThread(self._imap_controller.start_imap_service, - self.userid, flags.OFFLINE) + self._backend.start_imap_service(self.userid, flags.OFFLINE) def stop_imap_service(self, cv): """ - Stop imap service (fetcher, factory and port). + Stop imap service. :param cv: A condition variable to which we can signal when imap indeed stops. @@ -91,7 +77,7 @@ class IMAPControl(object): self.imap_connection.qtsigs.disconnecting_signal.emit() logger.debug('Stopping imap service.') - self._imap_controller.stop_imap_service(cv) + self._backend.stop_imap_service(cv) def _handle_imap_events(self, req): """ @@ -137,12 +123,9 @@ class SMTPControl(object): """ Initializes smtp variables. """ - self.smtp_config = SMTPConfig() self.smtp_connection = None self.smtp_machine = None - self.smtp_bootstrapper = SMTPBootstrapper() - leap_register(signal=leap_events.SMTP_SERVICE_STARTED, callback=self._handle_smtp_events, reqcbk=lambda req, resp: None) @@ -158,30 +141,23 @@ class SMTPControl(object): """ self.smtp_connection = smtp_connection - def start_smtp_service(self, provider_config, download_if_needed=False): + def start_smtp_service(self, download_if_needed=False): """ Starts the SMTP service. - :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 """ self.smtp_connection.qtsigs.connecting_signal.emit() - threads.deferToThread( - self.smtp_bootstrapper.start_smtp_service, - provider_config, self.smtp_config, self._keymanager, - self.userid, download_if_needed) + self._backend.start_smtp_service(self.userid, download_if_needed) def stop_smtp_service(self): """ Stops the SMTP service. """ self.smtp_connection.qtsigs.disconnecting_signal.emit() - self.smtp_bootstrapper.stop_smtp_service() - - # handle smtp events + self._backend.stop_smtp_service() def _handle_smtp_events(self, req): """ @@ -195,8 +171,6 @@ class SMTPControl(object): elif req.event == leap_events.SMTP_SERVICE_FAILED_TO_START: self.on_smtp_failed() - # emit connection signals - def on_smtp_connecting(self): """ Callback for SMTP connecting state. @@ -224,21 +198,17 @@ class MailConductor(IMAPControl, SMTPControl): """ # XXX We could consider to use composition instead of inheritance here. - def __init__(self, soledad, keymanager): + def __init__(self, backend): """ Initializes the mail conductor. - :param soledad: a transparent proxy that eventually will point to a - Soledad Instance. - :type soledad: zope.proxy.ProxyBase - :param keymanager: a transparent proxy that eventually will point to a - Keymanager Instance. - :type keymanager: zope.proxy.ProxyBase + :param backend: Backend being used + :type backend: Backend """ - IMAPControl.__init__(self, soledad, keymanager) + IMAPControl.__init__(self) SMTPControl.__init__(self) - self._soledad = soledad - self._keymanager = keymanager + + self._backend = backend self._mail_machine = None self._mail_connection = mail_connection.MailConnection() diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index efca5867..d0bf4c34 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -50,6 +50,11 @@ class IMAPController(object): def start_imap_service(self, userid, offline=False): """ Start IMAP service. + + :param userid: user id, in the form "user@provider" + :type userid: str + :param offline: whether imap should start in offline mode or not. + :type offline: bool """ logger.debug('Starting imap service') diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 7ecf8134..785fe404 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -28,7 +28,7 @@ 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.check import leap_assert from leap.common.files import check_and_fix_urw_only logger = logging.getLogger(__name__) @@ -38,6 +38,10 @@ class NoSMTPHosts(Exception): """This is raised when there is no SMTP host to use.""" +class MalformedUserId(Exception): + """This is raised when an userid does not have the form user@provider.""" + + class SMTPBootstrapper(AbstractBootstrapper): """ SMTP init procedure @@ -126,15 +130,10 @@ class SMTPBootstrapper(AbstractBootstrapper): smtp_key=client_cert_path, encrypted_only=False) - def start_smtp_service(self, provider_config, smtp_config, keymanager, - userid, download_if_needed=False): + def start_smtp_service(self, keymanager, userid, download_if_needed=False): """ 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 @@ -144,12 +143,15 @@ class SMTPBootstrapper(AbstractBootstrapper): for the file :type download_if_needed: bool """ - leap_assert_type(provider_config, ProviderConfig) - leap_assert_type(smtp_config, SMTPConfig) + try: + username, domain = userid.split('@') + except ValueError: + logger.critical("Malformed userid parameter!") + raise MalformedUserId() - self._provider_config = provider_config + self._provider_config = ProviderConfig.get_provider_config(domain) self._keymanager = keymanager - self._smtp_config = smtp_config + self._smtp_config = SMTPConfig() self._useid = userid self._download_if_needed = download_if_needed diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index c015f5b7..2bdad7e2 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -651,5 +651,7 @@ class SoledadBootstrapper(AbstractBootstrapper): self._signaler.signal(signal_finished) except Exception as e: # TODO: we should handle more specific exceptions in here + self._soledad = None + self._keymanager = None logger.exception("Error while bootstrapping Soledad: %r" % (e, )) self._signaler.signal(signal_failed) -- cgit v1.2.3 From 10cf84e5f8be978574b7a7e1a145903b37801753 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 16 May 2014 16:17:14 -0300 Subject: Move waiting logic for imap stop to the backend. Also, improve quit and cleanup calls. --- src/leap/bitmask/services/mail/conductor.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 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 67bc007e..87c4621e 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -66,18 +66,14 @@ class IMAPControl(object): """ self._backend.start_imap_service(self.userid, flags.OFFLINE) - def stop_imap_service(self, cv): + def stop_imap_service(self): """ Stop imap service. - - :param cv: A condition variable to which we can signal when imap - indeed stops. - :type cv: threading.Condition """ self.imap_connection.qtsigs.disconnecting_signal.emit() logger.debug('Stopping imap service.') - self._backend.stop_imap_service(cv) + self._backend.stop_imap_service() def _handle_imap_events(self, req): """ @@ -249,6 +245,13 @@ class MailConductor(IMAPControl, SMTPControl): self._smtp_machine = smtp self._smtp_machine.start() + def stop_mail_services(self): + """ + Stop the IMAP and SMTP services. + """ + self.stop_imap_service() + self.stop_smtp_service() + def connect_mail_signals(self, widget): """ Connects the mail signals to the mail_status widget slots. -- cgit v1.2.3 From baeb605e53c2e8a7dceee86035f6d4cc6b49e131 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Mon, 19 May 2014 17:51:58 -0300 Subject: Improve wait and quit process. Refactor logic from backend to the vpnprocess. --- src/leap/bitmask/services/eip/vpnprocess.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (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 734b88df..81eac6d9 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -17,6 +17,7 @@ """ VPN Manager, spawned in a custom processProtocol. """ +import commands import logging import os import shutil @@ -232,6 +233,17 @@ class VPN(object): BM_ROOT, "firewall", "start"] + gateways) return True if exitCode is 0 else False + def is_fw_down(self): + """ + Return whether the firewall is down or not. + + :rtype: bool + """ + BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT + fw_up_cmd = "pkexec {0} firewall isup".format(BM_ROOT) + fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 + return fw_is_down() + def _tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. -- cgit v1.2.3 From a61889110118d04703b023936048b44517947516 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 21 May 2014 13:58:26 -0300 Subject: Rename backend methods for consistency. --- src/leap/bitmask/services/mail/conductor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 87c4621e..7fc19f1c 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -64,7 +64,7 @@ class IMAPControl(object): """ Start imap service. """ - self._backend.start_imap_service(self.userid, flags.OFFLINE) + self._backend.imap_start_service(self.userid, flags.OFFLINE) def stop_imap_service(self): """ @@ -73,7 +73,7 @@ class IMAPControl(object): self.imap_connection.qtsigs.disconnecting_signal.emit() logger.debug('Stopping imap service.') - self._backend.stop_imap_service() + self._backend.imap_stop_service() def _handle_imap_events(self, req): """ @@ -146,14 +146,14 @@ class SMTPControl(object): :type download_if_needed: bool """ self.smtp_connection.qtsigs.connecting_signal.emit() - self._backend.start_smtp_service(self.userid, download_if_needed) + self._backend.smtp_start_service(self.userid, download_if_needed) def stop_smtp_service(self): """ Stops the SMTP service. """ self.smtp_connection.qtsigs.disconnecting_signal.emit() - self._backend.stop_smtp_service() + self._backend.smtp_stop_service() def _handle_smtp_events(self, req): """ @@ -249,8 +249,8 @@ class MailConductor(IMAPControl, SMTPControl): """ Stop the IMAP and SMTP services. """ - self.stop_imap_service() - self.stop_smtp_service() + self.imap_stop_service() + self.smtp_stop_service() def connect_mail_signals(self, widget): """ -- cgit v1.2.3 From 100848992f96f8edd32433dd8f5efc7dc1230079 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 19 May 2014 11:11:31 -0500 Subject: do not tear fw down during restarts --- src/leap/bitmask/services/eip/vpnprocess.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 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 81eac6d9..b068066f 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -300,19 +300,24 @@ class VPN(object): self._vpnproc.aborted = True self._vpnproc.killProcess() - def terminate(self, shutdown=False): + def terminate(self, shutdown=False, restart=False): """ Stops the openvpn subprocess. Attempts to send a SIGTERM first, and after a timeout it sends a SIGKILL. + + :param shutdown: whether this is the final shutdown + :type shutdown: bool + :param restart: whether this stop is part of a hard restart. + :type restart: bool """ from twisted.internet import reactor self._stop_pollers() - # We assume that the only valid shutodowns are initiated - # by an user action. - self._user_stopped = shutdown + # We assume that the only valid stops are initiated + # by an user action, not hard restarts + self._user_stopped = not restart # First we try to be polite and send a SIGTERM... if self._vpnproc: @@ -324,13 +329,12 @@ class VPN(object): 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") + 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): """ -- cgit v1.2.3 From b77d7c5d2a27ee45b88e6c06152c9c06847e868f Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 22 May 2014 16:04:53 -0300 Subject: Fix method names. --- src/leap/bitmask/services/mail/conductor.py | 4 ++-- 1 file changed, 2 insertions(+), 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 7fc19f1c..98b40929 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -249,8 +249,8 @@ class MailConductor(IMAPControl, SMTPControl): """ Stop the IMAP and SMTP services. """ - self.imap_stop_service() - self.smtp_stop_service() + self.stop_imap_service() + self.stop_smtp_service() def connect_mail_signals(self, widget): """ -- cgit v1.2.3 From 37353a2c57a759e160a7060c412b15d30ebde4bb Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 22 May 2014 17:34:24 -0300 Subject: Refactor cleanup, ProviderConfig to backend. --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (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 2bdad7e2..db12fd80 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -188,8 +188,9 @@ class SoledadBootstrapper(AbstractBootstrapper): try: self.load_and_sync_soledad(uuid, offline=True) self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FINISHED) - except Exception: + except Exception as e: # TODO: we should handle more specific exceptions in here + logger.exception(e) self._signaler.signal(self._signaler.SOLEDAD_OFFLINE_FAILED) def _get_soledad_local_params(self, uuid, offline=False): -- cgit v1.2.3 From 8d5fba55ee399aa7cf0d6e000f806cce7279a1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 28 May 2014 11:19:59 -0300 Subject: Properly set userid for SMTP --- src/leap/bitmask/services/mail/smtpbootstrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 785fe404..3ef755e8 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -152,7 +152,7 @@ class SMTPBootstrapper(AbstractBootstrapper): self._provider_config = ProviderConfig.get_provider_config(domain) self._keymanager = keymanager self._smtp_config = SMTPConfig() - self._useid = userid + self._userid = userid self._download_if_needed = download_if_needed try: -- cgit v1.2.3 From ccc8973bdc5cc0858906751eada622de74fd5d37 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 21 May 2014 18:42:05 -0500 Subject: refactor eip start/stop control to conductor and cleanup a little bit of the signal mess. --- src/leap/bitmask/services/eip/conductor.py | 269 ++++++++++++++++++++++++++++ src/leap/bitmask/services/eip/vpnprocess.py | 15 +- 2 files changed, 279 insertions(+), 5 deletions(-) create mode 100644 src/leap/bitmask/services/eip/conductor.py (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py new file mode 100644 index 00000000..253f76c0 --- /dev/null +++ b/src/leap/bitmask/services/eip/conductor.py @@ -0,0 +1,269 @@ +# -*- coding: utf-8 -*- +# conductor.py +# Copyright (C) 2014 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +EIP Conductor module. +""" +import logging + +from PySide import QtCore + +from leap.bitmask.gui import statemachines +from leap.bitmask.services import EIP_SERVICE +from leap.bitmask.services import get_service_display_name +from leap.bitmask.services.eip.connection import EIPConnection +from leap.bitmask.platform_init import IS_MAC +from leap.bitmask.util import make_address + +QtDelayedCall = QtCore.QTimer.singleShot +logger = logging.getLogger(__name__) + + +class EIPConductor(object): + + def __init__(self, settings, backend, **kwargs): + """ + Initializes EIP Conductor. + + :param settings: + :type settings: + + :param backend: + :type backend: + """ + self.eip_connection = EIPConnection() + self.eip_name = get_service_display_name(EIP_SERVICE) + self._settings = settings + self._backend = backend + + self._eip_status = None + + @property + def qtsigs(self): + return self.eip_connection.qtsigs + + def add_eip_widget(self, widget): + """ + Keep a reference to the passed eip status widget. + + :param widget: the EIP Status widget. + :type widget: QWidget + """ + self._eip_status = widget + + def connect_signals(self): + """ + Connect signals. + """ + self.qtsigs.connecting_signal.connect(self._start_eip) + self.qtsigs.disconnecting_signal.connect(self._stop_eip) + self.qtsigs.disconnected_signal.connect(self._eip_status.eip_stopped) + + def connect_backend_signals(self): + """ + Connect to backend signals. + """ + signaler = self._backend.signaler + + # for conductor + signaler.eip_process_restart_tls.connect(self._do_eip_restart) + signaler.eip_process_restart_ping.connect(self._do_eip_restart) + signaler.eip_process_finished.connect(self._eip_finished) + + # for widget + self._eip_status.connect_backend_signals() + + def start_eip_machine(self, action): + """ + Initializes and starts the EIP state machine. + Needs the reference to the eip_status widget not to be empty. + + :action: QtAction + """ + action = action + button = self._eip_status.eip_button + label = self._eip_status.eip_label + + builder = statemachines.ConnectionMachineBuilder(self.eip_connection) + eip_machine = builder.make_machine(button=button, + action=action, + label=label) + self.eip_machine = eip_machine + self.eip_machine.start() + logger.debug('eip machine started') + + def do_connect(self): + """ + Start the connection procedure. + Emits a signal that triggers the OFF -> Connecting sequence. + This will call _start_eip via the state machine. + """ + self.qtsigs.do_connect_signal.emit() + + @QtCore.Slot() + def _start_eip(self): + """ + Starts EIP. + """ + # FIXME --- pass is_restart parameter to here ??? + is_restart = self._eip_status and self._eip_status.is_restart + + def reconnect(): + self.qtsigs.disconnecting_signal.connect(self._stop_eip) + + if is_restart: + QtDelayedCall(0, reconnect) + else: + self._eip_status.eip_pre_up() + self.user_stopped_eip = False + + # Until we set an option in the preferences window, we'll assume that + # by default we try to autostart. If we switch it off manually, it + # won't try the next time. + self._settings.set_autostart_eip(True) + self._eip_status.is_restart = False + + # DO the backend call! + self._backend.eip_start() + + @QtCore.Slot() + def _stop_eip(self, restart=False): + """ + TRIGGERS: + self.qsigs.do_disconnect_signal (via state machine) + + Stops vpn process and makes gui adjustments to reflect + the change of state. + + :param restart: whether this is part of a eip restart. + :type restart: bool + """ + self._eip_status.is_restart = restart + self.user_stopped_eip = not restart + + def reconnect_stop_signal(): + self.qtsigs.disconnecting_signal.connect(self._stop_eip) + + def on_disconnected_do_restart(): + # hard restarts + eip_status_label = self._eip_status.tr("{0} is restarting") + eip_status_label = eip_status_label.format(self.eip_name) + self._eip_status.eip_stopped(restart=True) + self._eip_status.set_eip_status(eip_status_label, error=False) + + QtDelayedCall(1000, self.qtsigs.do_connect_signal.emit) + + if restart: + # we bypass the on_eip_disconnected here + #qtsigs.disconnected_signal.disconnect() + self.qtsigs.disconnected_signal.connect(on_disconnected_do_restart) + QtDelayedCall(0, self.qtsigs.disconnected_signal.emit) + + # Call to the backend. + self._backend.eip_stop(restart=restart) + + self._eip_status.set_eipstatus_off(False) + self._already_started_eip = False + + logger.debug('Setting autostart to: False') + self._settings.set_autostart_eip(False) + + if self._logged_user: + self._eip_status.set_provider( + make_address( + self._logged_user, + self._get_best_provider_config().get_domain())) + + self._eip_status.eip_stopped(restart=restart) + + if restart: + QtDelayedCall(50000, reconnect_stop_signal) + + @QtCore.Slot() + def _do_eip_restart(self): + """ + TRIGGERS: + self._eip_connection.qtsigs.process_restart + + Restart the connection. + """ + if self._eip_status is not None: + self._eip_status.is_restart = True + try: + self.qtsigs.disconnecting_signal.disconnect() + except Exception: + logger.error("cannot disconnect signals") + + def do_stop(*args): + self._stop_eip(restart=True) + + self.qtsigs.disconnecting_signal.connect(do_stop) + self.qtsigs.do_disconnect_signal.emit() + + @QtCore.Slot(int) + def _eip_finished(self, exitCode): + """ + TRIGGERS: + Signaler.eip_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. + + :param exitCode: the exit code of the eip process. + :type exitCode: int + """ + # 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,)) + + signal = self.qtsigs.disconnected_signal + + # XXX check if these exitCodes are pkexec/cocoasudo specific + if exitCode in (126, 127): + eip_status_label = self._eip_status.tr( + "{0} could not be launched " + "because you did not authenticate properly.") + eip_status_label = eip_status_label.format(self.eip_name) + self._eip_status.set_eip_status(eip_status_label, error=True) + signal = self.qtsigs.connection_aborted_signal + self._backend.eip_terminate() + + # XXX FIXME --- check exitcode is != 0 really + if exitCode != 0 and not self.user_stopped_eip: + eip_status_label = self._eip_status.tr( + "{0} finished in an unexpected manner!") + eip_status_label = eip_status_label.format(self.eip_name) + self._eip_status.eip_stopped() + self._eip_status.set_eip_status_icon("error") + self._eip_status.set_eip_status(eip_status_label, + error=True) + signal = self.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() diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index b068066f..6eef05af 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -116,10 +116,12 @@ class VPNObserver(object): :returns: a Signaler signal or None :rtype: str or None """ + sig = self._signaler 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, + "network_unreachable": sig.EIP_NETWORK_UNREACHABLE, + "process_restart_tls": sig.EIP_PROCESS_RESTART_TLS, + "process_restart_ping": sig.EIP_PROCESS_RESTART_PING, + "initialization_completed": sig.EIP_CONNECTED } return signals.get(event.lower()) @@ -318,6 +320,7 @@ class VPN(object): # We assume that the only valid stops are initiated # by an user action, not hard restarts self._user_stopped = not restart + self._vpnproc.is_restart = restart # First we try to be polite and send a SIGTERM... if self._vpnproc: @@ -755,7 +758,7 @@ class VPNManager(object): # However, that should be a rare case right now. self._send_command("signal SIGTERM") self._close_management_socket(announce=True) - except Exception as e: + except (Exception, AssertionError) as e: logger.warning("Problem trying to terminate OpenVPN: %r" % (e,)) else: @@ -824,6 +827,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): self._openvpn_verb = openvpn_verb self._vpn_observer = VPNObserver(signaler) + self.is_restart = False # processProtocol methods @@ -859,7 +863,8 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): exit_code = reason.value.exitCode if isinstance(exit_code, int): logger.debug("processExited, status %d" % (exit_code,)) - self._signaler.signal(self._signaler.EIP_PROCESS_FINISHED, exit_code) + self._signaler.signal( + self._signaler.EIP_PROCESS_FINISHED, exit_code) self._alive = False def processEnded(self, reason): -- cgit v1.2.3 From b85d6ed72460f15b6029f36ccfef3bccd57e530c Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 28 May 2014 16:29:42 -0500 Subject: fix non-existing logged_user caused by a bad rebase. --- src/leap/bitmask/services/eip/conductor.py | 58 ++++++++++++++++++------------ 1 file changed, 36 insertions(+), 22 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 253f76c0..7cc80014 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -69,6 +69,7 @@ class EIPConductor(object): Connect signals. """ self.qtsigs.connecting_signal.connect(self._start_eip) + self.qtsigs.disconnecting_signal.connect(self._stop_eip) self.qtsigs.disconnected_signal.connect(self._eip_status.eip_stopped) @@ -154,43 +155,55 @@ class EIPConductor(object): self._eip_status.is_restart = restart self.user_stopped_eip = not restart - def reconnect_stop_signal(): - self.qtsigs.disconnecting_signal.connect(self._stop_eip) - def on_disconnected_do_restart(): # hard restarts + logger.debug("HARD RESTART") eip_status_label = self._eip_status.tr("{0} is restarting") eip_status_label = eip_status_label.format(self.eip_name) self._eip_status.eip_stopped(restart=True) self._eip_status.set_eip_status(eip_status_label, error=False) - QtDelayedCall(1000, self.qtsigs.do_connect_signal.emit) + QtDelayedCall(2000, self.do_connect) + + def plug_restart_on_disconnected(): + #print "PLUGGING RESTART ON DISCONNECTED" + self.qtsigs.disconnected_signal.connect(on_disconnected_do_restart) + + def reconnect_disconnected_signal(): + #print "RECONNECTING DISCONNECTED SIGNAL" + self.qtsigs.disconnected_signal.disconnect( + on_disconnected_do_restart) + + def do_stop(*args): + self._stop_eip(restart=False) + + def reconnect_stop_signal(): + #print "RECONNECTING StOP SIGNAL" + self.qtsigs.disconnecting_signal.disconnect() + self.qtsigs.disconnecting_signal.connect(do_stop) if restart: # we bypass the on_eip_disconnected here - #qtsigs.disconnected_signal.disconnect() - self.qtsigs.disconnected_signal.connect(on_disconnected_do_restart) - QtDelayedCall(0, self.qtsigs.disconnected_signal.emit) + plug_restart_on_disconnected() + self.qtsigs.disconnected_signal.emit() + #QtDelayedCall(0, self.qtsigs.disconnected_signal.emit) + # ...and reconnect the original signal again, after having used the + # diversion + QtDelayedCall(500, reconnect_disconnected_signal) + else: + logger.debug('Setting autostart to: False') + self._settings.set_autostart_eip(False) # Call to the backend. self._backend.eip_stop(restart=restart) - self._eip_status.set_eipstatus_off(False) self._already_started_eip = False - - logger.debug('Setting autostart to: False') - self._settings.set_autostart_eip(False) - - if self._logged_user: - self._eip_status.set_provider( - make_address( - self._logged_user, - self._get_best_provider_config().get_domain())) - + self._eip_status.set_eipstatus_off(False) self._eip_status.eip_stopped(restart=restart) + # XXX needed? if restart: - QtDelayedCall(50000, reconnect_stop_signal) + QtDelayedCall(3000, reconnect_stop_signal) @QtCore.Slot() def _do_eip_restart(self): @@ -202,14 +215,15 @@ class EIPConductor(object): """ if self._eip_status is not None: self._eip_status.is_restart = True + + def do_stop(*args): + self._stop_eip(restart=True) + try: self.qtsigs.disconnecting_signal.disconnect() except Exception: logger.error("cannot disconnect signals") - def do_stop(*args): - self._stop_eip(restart=True) - self.qtsigs.disconnecting_signal.connect(do_stop) self.qtsigs.do_disconnect_signal.emit() -- cgit v1.2.3 From 5f6e44241b4858f1c407f0babfc41f40a06405f1 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 29 May 2014 12:45:46 -0500 Subject: display restart error after SIGTERM[soft,tls-error] - fix tls-error: is SIGTERM now - connect to connection-died signal - display error to user --- src/leap/bitmask/services/eip/conductor.py | 33 +++++++++++++++++++++++------ src/leap/bitmask/services/eip/vpnprocess.py | 2 +- 2 files changed, 27 insertions(+), 8 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 7cc80014..0cd4c95c 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -81,6 +81,7 @@ class EIPConductor(object): # for conductor signaler.eip_process_restart_tls.connect(self._do_eip_restart) + signaler.eip_process_restart_tls.connect(self._do_eip_failed) signaler.eip_process_restart_ping.connect(self._do_eip_restart) signaler.eip_process_finished.connect(self._eip_finished) @@ -141,7 +142,7 @@ class EIPConductor(object): self._backend.eip_start() @QtCore.Slot() - def _stop_eip(self, restart=False): + def _stop_eip(self, restart=False, failed=False): """ TRIGGERS: self.qsigs.do_disconnect_signal (via state machine) @@ -151,9 +152,12 @@ class EIPConductor(object): :param restart: whether this is part of a eip restart. :type restart: bool + + :param failed: whether this is the final step of a retry sequence + :type failed: bool """ self._eip_status.is_restart = restart - self.user_stopped_eip = not restart + self.user_stopped_eip = not restart and not failed def on_disconnected_do_restart(): # hard restarts @@ -166,11 +170,9 @@ class EIPConductor(object): QtDelayedCall(2000, self.do_connect) def plug_restart_on_disconnected(): - #print "PLUGGING RESTART ON DISCONNECTED" self.qtsigs.disconnected_signal.connect(on_disconnected_do_restart) def reconnect_disconnected_signal(): - #print "RECONNECTING DISCONNECTED SIGNAL" self.qtsigs.disconnected_signal.disconnect( on_disconnected_do_restart) @@ -178,7 +180,6 @@ class EIPConductor(object): self._stop_eip(restart=False) def reconnect_stop_signal(): - #print "RECONNECTING StOP SIGNAL" self.qtsigs.disconnecting_signal.disconnect() self.qtsigs.disconnecting_signal.connect(do_stop) @@ -190,6 +191,10 @@ class EIPConductor(object): # ...and reconnect the original signal again, after having used the # diversion QtDelayedCall(500, reconnect_disconnected_signal) + + elif failed: + self.qtsigs.disconnected_signal.emit() + else: logger.debug('Setting autostart to: False') self._settings.set_autostart_eip(False) @@ -197,9 +202,11 @@ class EIPConductor(object): # Call to the backend. self._backend.eip_stop(restart=restart) - self._already_started_eip = False + # ... and inform the status widget self._eip_status.set_eipstatus_off(False) - self._eip_status.eip_stopped(restart=restart) + self._eip_status.eip_stopped(restart=restart, failed=failed) + + self._already_started_eip = False # XXX needed? if restart: @@ -227,6 +234,18 @@ class EIPConductor(object): self.qtsigs.disconnecting_signal.connect(do_stop) self.qtsigs.do_disconnect_signal.emit() + @QtCore.Slot() + def _do_eip_failed(self): + """ + Stop EIP after a failure to start. + + TRIGGERS + signaler.eip_process_restart_tls + """ + logger.debug("TLS Error: eip_stop (failed)") + self.qtsigs.connection_died_signal.emit() + QtDelayedCall(1000, self._eip_status.eip_failed_to_restart) + @QtCore.Slot(int) def _eip_finished(self, exitCode): """ diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 6eef05af..098619be 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -70,7 +70,7 @@ class VPNObserver(object): 'NETWORK_UNREACHABLE': ( 'Network is unreachable (code=101)',), 'PROCESS_RESTART_TLS': ( - "SIGUSR1[soft,tls-error]",), + "SIGTERM[soft,tls-error]",), 'PROCESS_RESTART_PING': ( "SIGTERM[soft,ping-restart]",), 'INITIALIZATION_COMPLETED': ( -- cgit v1.2.3 From d4d6b0c5476b45629d632debe4527f9d6cb3cb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 29 May 2014 16:44:25 -0300 Subject: Check openvpn bin path before starting openvpn --- src/leap/bitmask/services/eip/conductor.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 0cd4c95c..53b1fde9 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -26,7 +26,6 @@ from leap.bitmask.services import EIP_SERVICE from leap.bitmask.services import get_service_display_name from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.platform_init import IS_MAC -from leap.bitmask.util import make_address QtDelayedCall = QtCore.QTimer.singleShot logger = logging.getLogger(__name__) -- cgit v1.2.3 From e723927a9a5a1b6e40553499e9d5148df10fcc46 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 30 May 2014 11:22:25 -0300 Subject: Do nothing if the vpnprocess is not started. We were trying to access the `is_restart` attribute that causes a failure if the vpnprocess is not instantiated. --- src/leap/bitmask/services/eip/vpnprocess.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 098619be..1de4a851 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -317,13 +317,13 @@ class VPN(object): from twisted.internet import reactor self._stop_pollers() - # We assume that the only valid stops are initiated - # by an user action, not hard restarts - self._user_stopped = not restart - self._vpnproc.is_restart = restart - # First we try to be polite and send a SIGTERM... - if self._vpnproc: + if self._vpnproc is not None: + # We assume that the only valid stops are initiated + # by an user action, not hard restarts + self._user_stopped = not restart + self._vpnproc.is_restart = restart + self._sentterm = True self._vpnproc.terminate_openvpn(shutdown=shutdown) -- cgit v1.2.3 From 687e1a87da9321b27ad966907db0f58f1c25b157 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 2 Jun 2014 15:45:06 -0500 Subject: add restore clearnet button. Closes: #5726 --- src/leap/bitmask/services/eip/conductor.py | 27 +++++++++++++++++++++------ src/leap/bitmask/services/eip/vpnprocess.py | 21 +++++++++++++-------- 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 53b1fde9..3c031952 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -114,6 +114,12 @@ class EIPConductor(object): """ self.qtsigs.do_connect_signal.emit() + def tear_fw_down(self): + """ + Tear the firewall down. + """ + self._backend.tear_fw_down() + @QtCore.Slot() def _start_eip(self): """ @@ -130,6 +136,7 @@ class EIPConductor(object): else: self._eip_status.eip_pre_up() self.user_stopped_eip = False + self._eip_status.hide_fw_down_button() # Until we set an option in the preferences window, we'll assume that # by default we try to autostart. If we switch it off manually, it @@ -138,7 +145,19 @@ class EIPConductor(object): self._eip_status.is_restart = False # DO the backend call! - self._backend.eip_start() + self._backend.eip_start(restart=is_restart) + + def reconnect_stop_signal(self): + """ + Restore the original behaviour associated with the disconnecting + signal, this is, trigger a normal stop, and not a restart one. + """ + + def do_stop(*args): + self._stop_eip(restart=False) + + self.qtsigs.disconnecting_signal.disconnect() + self.qtsigs.disconnecting_signal.connect(do_stop) @QtCore.Slot() def _stop_eip(self, restart=False, failed=False): @@ -178,10 +197,6 @@ class EIPConductor(object): def do_stop(*args): self._stop_eip(restart=False) - def reconnect_stop_signal(): - self.qtsigs.disconnecting_signal.disconnect() - self.qtsigs.disconnecting_signal.connect(do_stop) - if restart: # we bypass the on_eip_disconnected here plug_restart_on_disconnected() @@ -209,7 +224,7 @@ class EIPConductor(object): # XXX needed? if restart: - QtDelayedCall(3000, reconnect_stop_signal) + QtDelayedCall(2000, self.reconnect_stop_signal) @QtCore.Slot() def _do_eip_restart(self): diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 1de4a851..f56d464e 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -183,6 +183,8 @@ class VPN(object): kwargs['openvpn_verb'] = self._openvpn_verb kwargs['signaler'] = self._signaler + restart = kwargs.pop('restart', False) + # start the main vpn subprocess vpnproc = VPNProcess(*args, **kwargs) @@ -193,8 +195,9 @@ class VPN(object): # we try to bring the firewall up if IS_LINUX: gateways = vpnproc.getGateways() - firewall_up = self._launch_firewall(gateways) - if not firewall_up: + firewall_up = self._launch_firewall(gateways, + restart=restart) + if not restart and not firewall_up: logger.error("Could not bring firewall up, " "aborting openvpn launch.") return @@ -216,7 +219,7 @@ class VPN(object): self._pollers.extend(poll_list) self._start_pollers() - def _launch_firewall(self, gateways): + def _launch_firewall(self, gateways, restart=False): """ Launch the firewall using the privileged wrapper. @@ -231,8 +234,10 @@ class VPN(object): # XXX could check that the iptables rules are in place. BM_ROOT = linuxvpnlauncher.LinuxVPNLauncher.BITMASK_ROOT - exitCode = subprocess.call(["pkexec", - BM_ROOT, "firewall", "start"] + gateways) + cmd = ["pkexec", BM_ROOT, "firewall", "start"] + if restart: + cmd.append("restart") + exitCode = subprocess.call(cmd + gateways) return True if exitCode is 0 else False def is_fw_down(self): @@ -246,7 +251,7 @@ class VPN(object): fw_is_down = lambda: commands.getstatusoutput(fw_up_cmd)[0] == 256 return fw_is_down() - def _tear_down_firewall(self): + def tear_down_firewall(self): """ Tear the firewall down using the privileged wrapper. """ @@ -270,7 +275,7 @@ class VPN(object): # we try to tear the firewall down if IS_LINUX and self._user_stopped: - firewall_down = self._tear_down_firewall() + firewall_down = self.tear_down_firewall() if firewall_down: logger.debug("Firewall down") else: @@ -333,7 +338,7 @@ class VPN(object): self.TERMINATE_WAIT, self._kill_if_left_alive) if IS_LINUX and self._user_stopped: - firewall_down = self._tear_down_firewall() + firewall_down = self.tear_down_firewall() if firewall_down: logger.debug("Firewall down") else: -- cgit v1.2.3 From 0626d6349472bdcd934328165cfe1a0e7d891bfe Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 4 Jun 2014 10:11:46 -0500 Subject: catch openvpn unexpected ending show also the back-to-clearnet button on that case. --- src/leap/bitmask/services/eip/conductor.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 3c031952..4c01225f 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -297,8 +297,11 @@ class EIPConductor(object): signal = self.qtsigs.connection_aborted_signal self._backend.eip_terminate() - # XXX FIXME --- check exitcode is != 0 really - if exitCode != 0 and not self.user_stopped_eip: + # XXX FIXME --- check exitcode is != 0 really. + # bitmask-root is masking the exitcode, so we might need + # to fix it on that side. + #if exitCode != 0 and not self.user_stopped_eip: + if not self.user_stopped_eip: eip_status_label = self._eip_status.tr( "{0} finished in an unexpected manner!") eip_status_label = eip_status_label.format(self.eip_name) @@ -307,6 +310,9 @@ class EIPConductor(object): self._eip_status.set_eip_status(eip_status_label, error=True) signal = self.qtsigs.connection_died_signal + self._eip_status.show_fw_down_button() + msg = self._eip_status.tr("Outgoing traffic is blocked") + self._eip_status.set_eip_message(msg) if exitCode == 0 and IS_MAC: # XXX remove this warning after I fix cocoasudo. -- cgit v1.2.3 From aba3ea21d83e6e073baf01643b68832530a6f4d0 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 4 Jun 2014 12:18:18 -0500 Subject: tear down fw on cold starts. Closes: ##5727 --- src/leap/bitmask/services/eip/conductor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 4c01225f..cde53631 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -125,8 +125,8 @@ class EIPConductor(object): """ Starts EIP. """ - # FIXME --- pass is_restart parameter to here ??? - is_restart = self._eip_status and self._eip_status.is_restart + st = self._eip_status + is_restart = st and st.is_restart def reconnect(): self.qtsigs.disconnecting_signal.connect(self._stop_eip) -- cgit v1.2.3 From 6e19fd7c55ae1c4520536cb272b1ffcb6e8abd4c Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 5 Jun 2014 10:23:44 -0300 Subject: Add support for gnome-shell polkit agent. The gnome-shell desktop does not uses a separate process as others do. It uses an agent within its own process so we need to check for gnome-shell and then assume that its polkit is working. --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (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 1f0813e0..54845a8a 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -71,7 +71,20 @@ def _is_auth_agent_running(): 'ps aux | grep "[l]xpolkit"' ] is_running = [commands.getoutput(cmd) for cmd in polkit_options] - return any(is_running) + + # gnome-shell does not uses a separate process for the polkit-agent, it + # uses a polkit-agent within its own process so we can't ps-grep it. + is_running = any(is_running) + if not is_running: + is_gnome_shell = commands.getoutput('ps aux | grep [g]nome-shell') + + # $DESKTOP_SESSION == 'gnome' -> gnome-shell + # $DESKTOP_SESSION == 'gnome-fallback' -> gnome-shell fallback mode, + # uses polkit-gnome... + if is_gnome_shell and os.getenv("DESKTOP_SESSION") == 'gnome': + is_running = True + + return is_running def _try_to_launch_agent(): -- cgit v1.2.3 From e1f3552c9c368661f9cc1c8be3ddef6017557402 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 5 Jun 2014 17:14:08 -0300 Subject: Grep for gnome-shell as it were a polkit agent. The $DESKTOP_SESSION is not reliable since is set to 'default' in any case that you choose as your default desktop environment. Also, after some tests, I've seen that the `gnome-shell` process is not launched in the fallback mode, so we use it as a condition for the polkit agent present. --- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 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 54845a8a..955768d1 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -63,28 +63,21 @@ def _is_auth_agent_running(): :return: True if it's running, False if it's not. :rtype: boolean """ + # Note that gnome-shell does not uses a separate process for the + # polkit-agent, it uses a polkit-agent within its own process so we can't + # ps-grep a polkit process, we can ps-grep gnome-shell itself. + # 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 "[l]xpolkit"', + 'ps aux | grep "[g]nome-shell"', ] is_running = [commands.getoutput(cmd) for cmd in polkit_options] - # gnome-shell does not uses a separate process for the polkit-agent, it - # uses a polkit-agent within its own process so we can't ps-grep it. - is_running = any(is_running) - if not is_running: - is_gnome_shell = commands.getoutput('ps aux | grep [g]nome-shell') - - # $DESKTOP_SESSION == 'gnome' -> gnome-shell - # $DESKTOP_SESSION == 'gnome-fallback' -> gnome-shell fallback mode, - # uses polkit-gnome... - if is_gnome_shell and os.getenv("DESKTOP_SESSION") == 'gnome': - is_running = True - - return is_running + return any(is_running) def _try_to_launch_agent(): -- cgit v1.2.3 From bc60662ccc740d191cf8a1d368e66459dd1c4ae5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 15:38:09 -0500 Subject: change elements naming --- src/leap/bitmask/services/eip/conductor.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index cde53631..a8821160 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -258,7 +258,7 @@ class EIPConductor(object): """ logger.debug("TLS Error: eip_stop (failed)") self.qtsigs.connection_died_signal.emit() - QtDelayedCall(1000, self._eip_status.eip_failed_to_restart) + QtDelayedCall(1000, self._eip_status.eip_failed_to_connect) @QtCore.Slot(int) def _eip_finished(self, exitCode): @@ -311,8 +311,7 @@ class EIPConductor(object): error=True) signal = self.qtsigs.connection_died_signal self._eip_status.show_fw_down_button() - msg = self._eip_status.tr("Outgoing traffic is blocked") - self._eip_status.set_eip_message(msg) + self._eip_status.eip_failed_to_connect() if exitCode == 0 and IS_MAC: # XXX remove this warning after I fix cocoasudo. -- cgit v1.2.3 From 57aa4d51e37228333e56e98d9af3bfe7b278e2d1 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Jun 2014 16:38:56 -0500 Subject: add icons for the vpn exit nodes --- src/leap/bitmask/services/eip/eipconfig.py | 28 ++++++++++++++++++++++++---- src/leap/bitmask/services/eip/vpnlauncher.py | 9 ++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index 09a3d257..e7419b22 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -110,7 +110,7 @@ class VPNGatewaySelector(object): def get_gateways_list(self): """ - Returns the existing gateways, sorted by timezone proximity. + Return the existing gateways, sorted by timezone proximity. :rtype: list of tuples (location, ip) (str, IPv4Address or IPv6Address object) @@ -148,16 +148,36 @@ class VPNGatewaySelector(object): def get_gateways(self): """ - Returns the 4 best gateways, sorted by timezone proximity. + Return the 4 best gateways, sorted by timezone proximity. :rtype: list of IPv4Address or IPv6Address object. """ gateways = [ip for location, ip in self.get_gateways_list()][:4] return gateways + def get_gateways_country_code(self): + """ + Return a dict with ipaddress -> country code mapping. + + :rtype: dict + """ + country_codes = {} + + locations = self._eipconfig.get_locations() + gateways = self._eipconfig.get_gateways() + + for idx, gateway in enumerate(gateways): + gateway_location = gateway.get('location') + + ip = self._eipconfig.get_gateway_ip(idx) + if gateway_location is not None: + ccode = locations[gateway['location']]['country_code'] + country_codes[ip] = ccode + return country_codes + def _get_timezone_distance(self, offset): ''' - Returns the distance between the local timezone and + Return the distance between the local timezone and the one with offset 'offset'. :param offset: the distance of a timezone to GMT. @@ -179,7 +199,7 @@ class VPNGatewaySelector(object): def _get_local_offset(self): ''' - Returns the distance between GMT and the local timezone. + Return the distance between GMT and the local timezone. :rtype: int ''' diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index dcb48e8a..9629afae 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -25,6 +25,7 @@ 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 @@ -122,9 +123,9 @@ class VPNLauncher(object): leap_settings = LeapSettings() domain = providerconfig.get_domain() gateway_conf = leap_settings.get_selected_gateway(domain) + gateway_selector = VPNGatewaySelector(eipconfig) if gateway_conf == leap_settings.GATEWAY_AUTOMATIC: - gateway_selector = VPNGatewaySelector(eipconfig) gateways = gateway_selector.get_gateways() else: gateways = [gateway_conf] @@ -133,6 +134,12 @@ class VPNLauncher(object): logger.error('No gateway was found!') raise VPNLauncherException('No gateway was found!') + # this only works for selecting the first gateway, as we're + # currently doing. + ccodes = gateway_selector.get_gateways_country_code() + gateway_ccode = ccodes[gateways[0]] + flags.CURRENT_VPN_COUNTRY = gateway_ccode + logger.debug("Using gateways ips: {0}".format(', '.join(gateways))) return gateways -- cgit v1.2.3