diff options
| -rw-r--r-- | changes/feature_decrypt-inline-bootstrap | 1 | ||||
| -rw-r--r-- | src/leap/bitmask/app.py | 67 | ||||
| -rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 5 | ||||
| -rw-r--r-- | src/leap/bitmask/services/mail/plumber.py | 3 | ||||
| -rw-r--r-- | src/leap/bitmask/services/soledad/soledadbootstrapper.py | 28 | 
5 files changed, 72 insertions, 32 deletions
| diff --git a/changes/feature_decrypt-inline-bootstrap b/changes/feature_decrypt-inline-bootstrap new file mode 100644 index 00000000..092d98ea --- /dev/null +++ b/changes/feature_decrypt-inline-bootstrap @@ -0,0 +1 @@ +- Use inline decrypting for initial soledad syncrhonization, to wait for secrets. diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index 6a7d6ff1..d0906b7c 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -49,7 +49,6 @@ from PySide import QtCore, QtGui  from leap.bitmask import __version__ as VERSION  from leap.bitmask.config import flags -from leap.bitmask.gui import locale_rc  # noqa - silence pylint  from leap.bitmask.gui.mainwindow import MainWindow  from leap.bitmask.logs.utils import create_logger  from leap.bitmask.platform_init.locks import we_are_the_one_and_only @@ -67,16 +66,39 @@ import codecs  codecs.register(lambda name: codecs.lookup('utf-8')                  if name == 'cp65001' else None) +import psutil + + +def kill_the_children(): +    """ +    Make sure no lingering subprocesses are left in case of a bad termination. +    """ +    me = os.getpid() +    parent = psutil.Process(me) +    print "Killing all the children processes..." +    for child in parent.get_children(recursive=True): +        try: +            child.terminate() +        except Exception as exc: +            print exc + +# XXX This is currently broken, but we need to fix it to avoid +# orphaned processes in case of a crash. +#atexit.register(kill_the_children) +  def sigint_handler(*args, **kwargs):      """      Signal handler for SIGINT      """      logger = kwargs.get('logger', None) -    if logger: -        logger.debug("SIGINT catched. shutting down...") -    mainwindow = args[0] -    mainwindow.quit() +    parentpid = kwargs.get('parentpid', None) +    pid = os.getpid() +    if parentpid == pid: +        if logger: +            logger.debug("SIGINT catched. shutting down...") +        mainwindow = args[0] +        mainwindow.quit()  def sigterm_handler(*args, **kwargs): @@ -85,10 +107,13 @@ def sigterm_handler(*args, **kwargs):      This handler is actually passed to twisted reactor      """      logger = kwargs.get('logger', None) -    if logger: -        logger.debug("SIGTERM catched. shutting down...") -    mainwindow = args[0] -    mainwindow.quit() +    parentpid = kwargs.get('parentpid', None) +    pid = os.getpid() +    if parentpid == pid: +        if logger: +            logger.debug("SIGTERM catched. shutting down...") +        mainwindow = args[0] +        mainwindow.quit()  def do_display_version(opts): @@ -203,32 +228,26 @@ def main():      app.setApplicationName("leap")      app.setOrganizationDomain("leap.se") -    # XXX --------------------------------------------------------- -    # In quarantine, looks like we don't need it anymore. -    # This dummy timer ensures that control is given to the outside -    # loop, so we can hook our sigint handler. -    #timer = QtCore.QTimer() -    #timer.start(500) -    #timer.timeout.connect(lambda: None) -    # XXX --------------------------------------------------------- -      window = MainWindow(bypass_checks=bypass_checks,                          start_hidden=start_hidden) -    sigint_window = partial(sigint_handler, window, logger=logger) +    mainpid = os.getpid() +    sigint_window = partial(sigint_handler, window, +                            logger=logger, parentpid=mainpid)      signal.signal(signal.SIGINT, sigint_window)      # callable used in addSystemEventTrigger to handle SIGTERM -    sigterm_window = partial(sigterm_handler, window, logger=logger) - -    l = LoopingCall(QtCore.QCoreApplication.processEvents, 0, 10) -    l.start(0.01) - +    sigterm_window = partial(sigterm_handler, window, +                             logger=logger, parentpid=mainpid)      # SIGTERM can't be handled the same way SIGINT is, since it's      # caught by twisted. See _handleSignals method in      # twisted/internet/base.py#L1150. So, addSystemEventTrigger      # reactor's method is used.      reactor.addSystemEventTrigger('before', 'shutdown', sigterm_window) + +    l = LoopingCall(QtCore.QCoreApplication.processEvents, 0, 10) +    l.start(0.01) +      reactor.run()  if __name__ == "__main__": diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 8a5b8275..e53ab7f3 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1786,7 +1786,6 @@ class MainWindow(QtGui.QMainWindow):          Final steps to quit the app, starting from here we don't care about          running services or user interaction, just quitting.          """ -        logger.debug('Final quit...')          # We can reach here because all the services are stopped or because a          # timeout was triggered. Since we want to run this only once, we exit @@ -1796,6 +1795,10 @@ class MainWindow(QtGui.QMainWindow):          self._finally_quitting = True +        logger.debug('Closing soledad...') +        self._backend.soledad_close() +        logger.debug('Final quit...') +          # Remove lockfiles on a clean shutdown.          logger.debug('Cleaning pidfiles')          if IS_WIN: diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py index c16a1fed..1ef0543e 100644 --- a/src/leap/bitmask/services/mail/plumber.py +++ b/src/leap/bitmask/services/mail/plumber.py @@ -83,7 +83,8 @@ def initialize_soledad(uuid, email, passwd,          secrets,          localdb,          server_url, -        cert_file) +        cert_file, +        defer_encryption=True)      return soledad diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index db12fd80..b9243add 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -21,6 +21,7 @@ import logging  import os  import socket  import sys +import time  from ssl import SSLError  from sqlite3 import ProgrammingError as sqlite_ProgrammingError @@ -132,6 +133,9 @@ class SoledadBootstrapper(AbstractBootstrapper):      MAX_INIT_RETRIES = 10      MAX_SYNC_RETRIES = 10 +    WAIT_MAX_SECONDS = 600 +    #WAIT_STEP_SECONDS = 1 +    WAIT_STEP_SECONDS = 5      def __init__(self, signaler=None):          AbstractBootstrapper.__init__(self, signaler) @@ -181,7 +185,6 @@ class SoledadBootstrapper(AbstractBootstrapper):          :param uuid: the user uuid          :type uuid: str or unicode          """ -        print "UUID ", uuid          self._address = username          self._password = password          self._uuid = uuid @@ -356,12 +359,20 @@ class SoledadBootstrapper(AbstractBootstrapper):          Do several retries to get an initial soledad sync.          """          # and now, let's sync -        sync_tries = 1 -        while sync_tries <= self.MAX_SYNC_RETRIES: +        sync_tries = self.MAX_SYNC_RETRIES +        step = self.WAIT_STEP_SECONDS +        max_wait = self.WAIT_MAX_SECONDS +        while sync_tries > 0: +            wait = 0              try:                  logger.debug("Trying to sync soledad....")                  self._try_soledad_sync() -                logger.debug("Soledad has been synced.") +                while self.soledad.syncing: +                    time.sleep(step) +                    wait += step +                    if wait >= max_wait: +                        raise SoledadSyncError("timeout!") +                logger.debug("Soledad has been synced!")                  # so long, and thanks for all the fish                  return              except SoledadSyncError: @@ -382,6 +393,7 @@ class SoledadBootstrapper(AbstractBootstrapper):                      self._signaler.SOLEDAD_INVALID_AUTH_TOKEN)                  raise              except Exception as e: +                # XXX release syncing lock                  logger.exception("Unhandled error while syncing "                                   "soledad: %r" % (e,))                  break @@ -423,7 +435,8 @@ class SoledadBootstrapper(AbstractBootstrapper):                  local_db_path=local_db_path.encode(encoding),                  server_url=server_url,                  cert_file=cert_file.encode(encoding), -                auth_token=auth_token) +                auth_token=auth_token, +                defer_encryption=True)          # XXX All these errors should be handled by soledad itself,          # and return a subclass of SoledadInitializationFailed @@ -448,7 +461,10 @@ class SoledadBootstrapper(AbstractBootstrapper):          Raises SoledadSyncError if not successful.          """          try: -            self._soledad.sync() +            logger.debug("BOOTSTRAPPER: trying to sync Soledad....") +            # pass defer_decryption=False to get inline decryption +            # for debugging. +            self._soledad.sync(defer_decryption=True)          except SSLError as exc:              logger.error("%r" % (exc,))              raise SoledadSyncError("Failed to sync soledad") | 
