summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/leap/bitmask/backend.py137
-rw-r--r--src/leap/bitmask/gui/mainwindow.py8
-rw-r--r--src/leap/bitmask/services/mail/conductor.py56
-rw-r--r--src/leap/bitmask/services/mail/imapcontroller.py5
-rw-r--r--src/leap/bitmask/services/mail/smtpbootstrapper.py24
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py2
6 files changed, 163 insertions, 69 deletions
diff --git a/src/leap/bitmask/backend.py b/src/leap/bitmask/backend.py
index fd09929a..6a6b1065 100644
--- a/src/leap/bitmask/backend.py
+++ b/src/leap/bitmask/backend.py
@@ -46,7 +46,10 @@ from leap.bitmask.services.eip.eipbootstrapper import EIPBootstrapper
from leap.bitmask.services.eip import vpnlauncher, vpnprocess
from leap.bitmask.services.eip import linuxvpnlauncher, darwinvpnlauncher
-from leap.bitmask.services.mail import imap
+
+from leap.bitmask.services.mail.imapcontroller import IMAPController
+from leap.bitmask.services.mail.smtpbootstrapper import SMTPBootstrapper
+from leap.bitmask.services.mail.smtpconfig import SMTPConfig
from leap.bitmask.services.soledad.soledadbootstrapper import \
SoledadBootstrapper
@@ -557,15 +560,21 @@ class Soledad(object):
"""
zope.interface.implements(ILEAPComponent)
- def __init__(self, signaler=None):
+ def __init__(self, soledad_proxy, keymanager_proxy, signaler=None):
"""
Constructor for the Soledad component.
+ :param soledad_proxy: proxy to pass around a Soledad object.
+ :type soledad_proxy: zope.ProxyBase
+ :param keymanager_proxy: proxy to pass around a Keymanager object.
+ :type keymanager_proxy: zope.ProxyBase
:param signaler: Object in charge of handling communication
back to the frontend
:type signaler: Signaler
"""
self.key = "soledad"
+ self._soledad_proxy = soledad_proxy
+ self._keymanager_proxy = keymanager_proxy
self._signaler = signaler
self._soledad_bootstrapper = SoledadBootstrapper(signaler)
self._soledad_defer = None
@@ -591,6 +600,7 @@ class Soledad(object):
self._soledad_bootstrapper.run_soledad_setup_checks,
provider_config, username, password,
download_if_needed=True)
+ self._soledad_defer.addCallback(self._set_proxies_cb)
else:
if self._signaler is not None:
self._signaler.signal(self._signaler.SOLEDAD_BOOTSTRAP_FAILED)
@@ -598,6 +608,16 @@ class Soledad(object):
return self._soledad_defer
+ def _set_proxies_cb(self, _):
+ """
+ Update the soledad and keymanager proxies to reference the ones created
+ in the bootstrapper.
+ """
+ zope.proxy.setProxiedObject(self._soledad_proxy,
+ self._soledad_bootstrapper.soledad)
+ zope.proxy.setProxiedObject(self._keymanager_proxy,
+ self._soledad_bootstrapper.keymanager)
+
def load_offline(self, username, password, uuid):
"""
Load the soledad database in offline mode.
@@ -641,28 +661,70 @@ class Mail(object):
zope.interface.implements(ILEAPComponent)
- def __init__(self, signaler=None):
+ def __init__(self, soledad_proxy, keymanager_proxy, signaler=None):
"""
Constructor for the Mail component.
+ :param soledad_proxy: proxy to pass around a Soledad object.
+ :type soledad_proxy: zope.ProxyBase
+ :param keymanager_proxy: proxy to pass around a Keymanager object.
+ :type keymanager_proxy: zope.ProxyBase
:param signaler: Object in charge of handling communication
back to the frontend
:type signaler: Signaler
"""
self.key = "mail"
self._signaler = signaler
+ self._soledad_proxy = soledad_proxy
+ self._keymanager_proxy = keymanager_proxy
+ self._imap_controller = IMAPController(self._soledad_proxy,
+ self._keymanager_proxy)
+ self._smtp_bootstrapper = SMTPBootstrapper()
+ self._smtp_config = SMTPConfig()
- def start_smtp_service(self):
- pass
+ def start_smtp_service(self, full_user_id, download_if_needed=False):
+ """
+ Start the SMTP service.
- def start_imap_service(self, offline=False):
- pass
+ :param full_user_id: user id, in the form "user@provider"
+ :type full_user_id: str
+ :param download_if_needed: True if it should check for mtime
+ for the file
+ :type download_if_needed: bool
+ """
+ return threads.deferToThread(
+ self._smtp_bootstrapper.start_smtp_service,
+ self._keymanager_proxy, full_user_id, download_if_needed)
+
+ def start_imap_service(self, full_user_id, offline=False):
+ """
+ Start the IMAP service.
+
+ :param full_user_id: user id, in the form "user@provider"
+ :type full_user_id: str
+ :param offline: whether imap should start in offline mode or not.
+ :type offline: bool
+ """
+ return threads.deferToThread(
+ self._imap_controller.start_imap_service,
+ full_user_id, offline)
def stop_smtp_service(self):
- pass
+ """
+ Stop the SMTP service.
+ """
+ return threads.deferToThread(self._smtp_bootstrapper.stop_smtp_service)
- def stop_imap_service(self):
- pass
+ 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
+ """
+ return threads.deferToThread(
+ self._imap_controller.stop_imap_service, cv)
class Authenticate(object):
@@ -1075,12 +1137,22 @@ class Backend(object):
# Signaler object to translate commands into Qt signals
self._signaler = Signaler()
+ # Objects needed by several components, so we make a proxy and pass
+ # them around
+ self._soledad_proxy = zope.proxy.ProxyBase(None)
+ self._keymanager_proxy = zope.proxy.ProxyBase(None)
+
# Component registration
self._register(Provider(self._signaler, bypass_checks))
self._register(Register(self._signaler))
self._register(Authenticate(self._signaler))
self._register(EIP(self._signaler))
- self._register(Soledad(self._signaler))
+ self._register(Soledad(self._soledad_proxy,
+ self._keymanager_proxy,
+ self._signaler))
+ self._register(Mail(self._soledad_proxy,
+ self._keymanager_proxy,
+ self._signaler))
# We have a looping call on a thread executing all the
# commands in queue. Right now this queue is an actual Queue
@@ -1473,11 +1545,54 @@ class Backend(object):
"""
self._call_queue.put(("soledad", "close", None))
+ def start_smtp_service(self, full_user_id, download_if_needed=False):
+ """
+ Start the SMTP service.
+
+ :param full_user_id: user id, in the form "user@provider"
+ :type full_user_id: str
+ :param download_if_needed: True if it should check for mtime
+ for the file
+ :type download_if_needed: bool
+ """
+ self._call_queue.put(("mail", "start_smtp_service", None,
+ full_user_id, download_if_needed))
+
+ def start_imap_service(self, full_user_id, offline=False):
+ """
+ Start the IMAP service.
+
+ :param full_user_id: user id, in the form "user@provider"
+ :type full_user_id: str
+ :param offline: whether imap should start in offline mode or not.
+ :type offline: bool
+ """
+ self._call_queue.put(("mail", "start_imap_service", None,
+ full_user_id, offline))
+
+ def stop_smtp_service(self):
+ """
+ Stop the SMTP service.
+ """
+ self._call_queue.put(("mail", "stop_smtp_service", None))
+
+ def stop_imap_service(self, cv):
+ """
+ Stop imap service.
+
+ :param cv: A condition variable to which we can signal when imap
+ indeed stops.
+ :type cv: threading.Condition
+ """
+ self._call_queue.put(("mail", "stop_imap_service", None, cv))
+
###########################################################################
# XXX HACK: this section is meant to be a place to hold methods and
# variables needed in the meantime while we migrate all to the backend.
def get_provider_config(self):
+ # TODO: refactor the provider config into a singleton/global loading it
+ # every time from the file.
provider_config = self._components["provider"]._provider_config
return provider_config
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index bf76f574..370a9d43 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -282,8 +282,9 @@ class MainWindow(QtGui.QMainWindow):
self._soledad = ProxyBase(None)
self._keymanager = ProxyBase(None)
- self._mail_conductor = mail_conductor.MailConductor(
- self._soledad, self._keymanager)
+ self._mail_conductor = mail_conductor.MailConductor(self._backend)
+ # self._mail_conductor = mail_conductor.MailConductor(
+ # self._soledad, self._keymanager)
self._mail_conductor.connect_mail_signals(self._mail_status)
# Eip machine is a public attribute where the state machine for
@@ -1423,8 +1424,7 @@ class MainWindow(QtGui.QMainWindow):
return
if self._provides_mx_and_enabled():
- self._mail_conductor.start_smtp_service(self._provider_config,
- download_if_needed=True)
+ self._mail_conductor.start_smtp_service(download_if_needed=True)
# XXX --- should remove from here, and connecte directly to the state
# machine.
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)