summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2015-12-08 21:04:11 -0400
committerKali Kaneko <kali@leap.se>2015-12-15 12:31:04 -0400
commit98384361a7c49ad4e0ff0127fd923a8b72cc910a (patch)
treec315b65397ac97210d6f1a3ee5e521b4d8917678
parent6c0299e7e2df65651ff8738fa18acbc08af18c32 (diff)
[feat] adapt to use cred-based authentication for imap
This includes getting the token for the imap authentication, and displaying it on the help window. - Resolves: #4469 - Releases: 0.10.0
-rw-r--r--changes/next-changelog.rst5
-rw-r--r--src/leap/bitmask/backend/api.py2
-rw-r--r--src/leap/bitmask/backend/components.py23
-rw-r--r--src/leap/bitmask/backend/leapbackend.py7
-rw-r--r--src/leap/bitmask/backend/leapsignaler.py1
-rw-r--r--src/leap/bitmask/gui/mainwindow.py18
-rw-r--r--src/leap/bitmask/services/mail/imap.py31
-rw-r--r--src/leap/bitmask/services/mail/imapcontroller.py8
8 files changed, 71 insertions, 24 deletions
diff --git a/changes/next-changelog.rst b/changes/next-changelog.rst
index 77094e78..c359b4e2 100644
--- a/changes/next-changelog.rst
+++ b/changes/next-changelog.rst
@@ -1,4 +1,4 @@
-0.9.2 - xxx
+0.10.0 - xxx
+++++++++++++++++++++++++++++++
Please add lines to this file, they will be moved to the CHANGELOG.rst during
@@ -11,8 +11,9 @@ I've added a new category `Misc` so we can track doc/style/packaging stuff.
Features
~~~~~~~~
- `#7552 <https://leap.se/code/issues/7552>`_: Improve UI message and add some margin above the msg box.
-- `#7552 <https://leap.se/code/issues/7552>`_: Improve UI message and add some margin above the msg box.
- `#7656 <https://leap.se/code/issues/7656>`_: Adapt to multi-user aware events.
+- `#4469 <https://leap.se/code/issues/4469>`_: Display randomly generated service token on the Help Window.
+- `#1234 <https://leap.se/code/issues/1234>`_: Description of the new feature corresponding with issue #1234.
- New feature without related issue number.
Bugfixes
diff --git a/src/leap/bitmask/backend/api.py b/src/leap/bitmask/backend/api.py
index 48aa2090..134a2d56 100644
--- a/src/leap/bitmask/backend/api.py
+++ b/src/leap/bitmask/backend/api.py
@@ -57,6 +57,7 @@ API = (
"soledad_change_password",
"soledad_close",
"soledad_load_offline",
+ "soledad_get_service_token",
"tear_fw_down",
"bitmask_root_vpn_down",
"user_cancel_login",
@@ -135,6 +136,7 @@ SIGNALS = (
"soledad_offline_finished",
"soledad_password_change_error",
"soledad_password_change_ok",
+ "soledad_got_service_token",
"srp_auth_bad_user_or_password",
"srp_auth_connection_error",
"srp_auth_error",
diff --git a/src/leap/bitmask/backend/components.py b/src/leap/bitmask/backend/components.py
index 5f34d290..a07d3bad 100644
--- a/src/leap/bitmask/backend/components.py
+++ b/src/leap/bitmask/backend/components.py
@@ -763,6 +763,7 @@ class Soledad(object):
self._signaler = signaler
self._soledad_bootstrapper = SoledadBootstrapper(signaler)
self._soledad_defer = None
+ self._service_tokens = {}
def bootstrap(self, username, domain, password):
"""
@@ -786,6 +787,7 @@ class Soledad(object):
provider_config, username, password,
download_if_needed=True)
self._soledad_defer.addCallback(self._set_proxies_cb)
+ self._soledad_defer.addCallback(self._set_service_tokens_cb)
else:
if self._signaler is not None:
self._signaler.signal(self._signaler.soledad_bootstrap_failed)
@@ -793,6 +795,21 @@ class Soledad(object):
return self._soledad_defer
+ def _set_service_tokens_cb(self, result):
+
+ def register_imap_token(imap_token):
+ self._service_tokens['imap'] = imap_token
+ if self._signaler is not None:
+ self._signaler.signal(
+ self._signaler.soledad_got_service_token,
+ ('imap', imap_token))
+
+ sol = self._soledad_bootstrapper.soledad
+ d = sol.get_or_create_service_token('imap')
+ d.addCallback(register_imap_token)
+ d.addCallback(lambda _: result)
+ return d
+
def _set_proxies_cb(self, _):
"""
Update the soledad and keymanager proxies to reference the ones created
@@ -803,6 +820,12 @@ class Soledad(object):
zope.proxy.setProxiedObject(self._keymanager_proxy,
self._soledad_bootstrapper.keymanager)
+ def get_service_token(self, service):
+ """
+ Get an authentication token for a given service.
+ """
+ return self._service_tokens.get(service, '')
+
def load_offline(self, username, password, uuid):
"""
Load the soledad database in offline mode.
diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py
index cf45c4f8..d0668a1c 100644
--- a/src/leap/bitmask/backend/leapbackend.py
+++ b/src/leap/bitmask/backend/leapbackend.py
@@ -35,6 +35,7 @@ class LeapBackend(Backend):
"""
Backend server subclass, used to implement the API methods.
"""
+
def __init__(self, bypass_checks=False, frontend_pid=None):
"""
Constructor for the backend.
@@ -438,6 +439,12 @@ class LeapBackend(Backend):
"""
self._soledad.load_offline(username, password, uuid)
+ def soledad_get_service_token(self, service):
+ """
+ Attempt to get an authentication token for a given service.
+ """
+ self._soledad.get_service_token(service)
+
def soledad_cancel_bootstrap(self):
"""
Cancel the ongoing soledad bootstrapping process (if any).
diff --git a/src/leap/bitmask/backend/leapsignaler.py b/src/leap/bitmask/backend/leapsignaler.py
index 1ac51f5e..13a9fa5f 100644
--- a/src/leap/bitmask/backend/leapsignaler.py
+++ b/src/leap/bitmask/backend/leapsignaler.py
@@ -97,6 +97,7 @@ class LeapSignaler(SignalerQt):
soledad_offline_finished = QtCore.Signal()
soledad_password_change_error = QtCore.Signal()
soledad_password_change_ok = QtCore.Signal()
+ soledad_got_service_token = QtCore.Signal(object)
srp_auth_bad_user_or_password = QtCore.Signal()
srp_auth_connection_error = QtCore.Signal()
diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py
index a8a4e41d..189a6295 100644
--- a/src/leap/bitmask/gui/mainwindow.py
+++ b/src/leap/bitmask/gui/mainwindow.py
@@ -407,6 +407,10 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
sig.soledad_invalid_auth_token.connect(
self._mail_status.set_soledad_invalid_auth_token)
+ self._service_tokens = {}
+ sig.soledad_got_service_token.connect(
+ self._set_service_tokens)
+
# TODO: connect this with something
# sig.soledad_cancelled_bootstrap.connect()
@@ -1033,6 +1037,13 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
msg = msg.format(ver=VERSION, ver_hash=VERSION_HASH[:10], greet=greet)
QtGui.QMessageBox.about(self, title, msg)
+ def _set_service_tokens(self, data):
+ """
+ Set the received service token.
+ """
+ service, token = data
+ self._service_tokens[service] = token
+
def _help(self):
"""
TRIGGERS:
@@ -1063,7 +1074,12 @@ class MainWindow(QtGui.QMainWindow, SignalTracker):
manual_imap = self.tr("IMAP: localhost, port {0}".format(IMAP_PORT))
manual_smtp = self.tr("SMTP: localhost, port {0}".format(smtp_port))
manual_username = self.tr("Username: your full email address")
- manual_password = self.tr("Password: any non-empty text")
+
+ # TODO this should be a widget that allows to be copied to the
+ # clipboard.
+ imap_token = (self._service_tokens.get('imap', None)
+ or "??? (log in to unlock)")
+ manual_password = self.tr("Password: ") + "%s" % (imap_token, )
msg = help_url + self.tr(
"<p><strong>{0}</strong></p>"
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index b06c1d4a..54935f8c 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -20,11 +20,14 @@ Initialization of imap service
import os
import sys
+from twisted.python import log
+
from leap.bitmask.logs.utils import get_logger
from leap.mail.constants import INBOX_NAME
from leap.mail.imap.service import imap
from leap.mail.incoming.service import IncomingMail, INCOMING_CHECK_PERIOD
-from twisted.python import log
+from leap.mail.mail import Account
+
logger = get_logger()
@@ -57,11 +60,13 @@ def get_mail_check_period():
return period
-def start_imap_service(*args, **kwargs):
+def start_imap_service(soledad_sessions):
"""
Initializes and run imap service.
- :returns: LeapIMAPFactory instance
+ :returns: the port as returned by the reactor when starts listening, and
+ the factory for the protocol.
+ :rtype: tuple
"""
from leap.bitmask.config import flags
logger.debug('Launching imap service')
@@ -70,10 +75,10 @@ def start_imap_service(*args, **kwargs):
log.startLogging(open(flags.MAIL_LOGFILE, 'w'))
log.startLogging(sys.stdout)
- return imap.run_service(*args, **kwargs)
+ return imap.run_service(soledad_sessions)
-def start_incoming_mail_service(keymanager, soledad, imap_factory, userid):
+def start_incoming_mail_service(keymanager, soledad, userid):
"""
Initalizes and starts the incomming mail service.
@@ -81,19 +86,13 @@ def start_incoming_mail_service(keymanager, soledad, imap_factory, userid):
"""
def setUpIncomingMail(inbox):
incoming_mail = IncomingMail(
- keymanager,
- soledad,
- inbox.collection,
- userid,
+ keymanager, soledad,
+ inbox, userid,
check_period=get_mail_check_period())
return incoming_mail
- # XXX: do I really need to know here how to get a mailbox??
- # XXX: ideally, the parent service in mail would take care of initializing
- # the account, and passing the mailbox to the incoming service.
- # In an even better world, we just would subscribe to a channel that would
- # pass us the serialized object to be inserted.
- acc = imap_factory.theAccount
- d = acc.callWhenReady(lambda _: acc.getMailbox(INBOX_NAME))
+ acc = Account(soledad)
+ d = acc.callWhenReady(lambda _: acc.get_collection_by_mailbox(INBOX_NAME))
d.addCallback(setUpIncomingMail)
+ d.addErrback(log.err)
return d
diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py
index 5053d897..855fb74b 100644
--- a/src/leap/bitmask/services/mail/imapcontroller.py
+++ b/src/leap/bitmask/services/mail/imapcontroller.py
@@ -60,9 +60,9 @@ class IMAPController(object):
"""
logger.debug('Starting imap service')
+ soledad_sessions = {userid: self._soledad}
self.imap_port, self.imap_factory = imap.start_imap_service(
- self._soledad,
- userid=userid)
+ soledad_sessions)
def start_and_assign_incoming_service(incoming_mail):
# this returns a deferred that will be called when the looping call
@@ -74,9 +74,7 @@ class IMAPController(object):
if offline is False:
d = imap.start_incoming_mail_service(
- self._keymanager,
- self._soledad,
- self.imap_factory,
+ self._keymanager, self._soledad,
userid)
d.addCallback(start_and_assign_incoming_service)
d.addErrback(lambda f: logger.error(f.printTraceback()))