From 2aa7cb8710a1e0d3a99698566a11db3d54818a41 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Thu, 4 Dec 2014 11:17:36 -0600 Subject: Use the new keymanager async API --- .../services/soledad/soledadbootstrapper.py | 117 ++++++++++++--------- 1 file changed, 68 insertions(+), 49 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 2044a27c..ac7ca836 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -27,7 +27,7 @@ from ssl import SSLError from sqlite3 import ProgrammingError as sqlite_ProgrammingError from u1db import errors as u1db_errors -from twisted.internet import threads +from twisted.internet import threads, defer from zope.proxy import sameProxiedObjects from pysqlcipher.dbapi2 import ProgrammingError as sqlcipher_ProgrammingError @@ -317,19 +317,26 @@ class SoledadBootstrapper(AbstractBootstrapper): if flags.OFFLINE: self._init_keymanager(self._address, token) else: - try: - address = make_address( - self._user, self._provider_config.get_domain()) - self._init_keymanager(address, token) - self._keymanager.get_key( + address = make_address( + self._user, self._provider_config.get_domain()) + + def key_not_found(failure): + if failure.check(KeyNotFound): + logger.debug("Key not found. Generating key for %s" % + (address,)) + self._do_soledad_sync() + else: + return failure + + d = self._init_keymanager(address, token) + d.addCallback( + lambda _: self._keymanager.get_key( address, openpgp.OpenPGPKey, - private=True, fetch_remote=False) - d = threads.deferToThread(self._do_soledad_sync) - d.addErrback(self._soledad_sync_errback) - except KeyNotFound: - logger.debug("Key not found. Generating key for %s" % - (address,)) - self._do_soledad_sync() + private=True, fetch_remote=False)) + d.addCallbacks( + lambda _: threads.deferToThread(self._do_soledad_sync), + key_not_found) + d.addErrback(self._soledad_sync_errback) def _pick_server(self, uuid): """ @@ -537,6 +544,7 @@ class SoledadBootstrapper(AbstractBootstrapper): :type address: str :param token: the auth token for accessing webapp. :type token: str + :rtype: Deferred """ srp_auth = self.srpauth logger.debug('initializing keymanager...') @@ -576,20 +584,27 @@ class SoledadBootstrapper(AbstractBootstrapper): if flags.OFFLINE is False: # make sure key is in server logger.debug('Trying to send key to server...') - try: - self._keymanager.send_key(openpgp.OpenPGPKey) - except KeyNotFound: - logger.debug('No key found for %s, will generate soon.' - % address) - except Exception as exc: - logger.error("Error sending key to server.") - logger.exception(exc) - # but we do not raise + + def send_errback(failure): + if failure.check(KeyNotFound): + logger.debug('No key found for %s, will generate soon.' + % address) + else: + logger.error("Error sending key to server.") + logger.exception(failure.value) + # but we do not raise + + d = self._keymanager.send_key(openpgp.OpenPGPKey) + d.addErrback(send_errback) + return d + else: + return defer.succeed(None) def _gen_key(self): """ Generates the key pair if needed, uploads it to the webapp and nickserver + :rtype: Deferred """ leap_assert(self._provider_config is not None, "We need a provider configuration!") @@ -600,30 +615,33 @@ class SoledadBootstrapper(AbstractBootstrapper): self._user, self._provider_config.get_domain()) logger.debug("Retrieving key for %s" % (address,)) - try: - self._keymanager.get_key( - address, openpgp.OpenPGPKey, private=True, fetch_remote=False) - return - except KeyNotFound: - logger.debug("Key not found. Generating key for %s" % (address,)) - - # generate key - try: - self._keymanager.gen_key(openpgp.OpenPGPKey) - except Exception as exc: - logger.error("Error while generating key!") - logger.exception(exc) - raise - - # send key - try: - self._keymanager.send_key(openpgp.OpenPGPKey) - except Exception as exc: - logger.error("Error while sending key!") - logger.exception(exc) - raise - - logger.debug("Key generated successfully.") + def if_not_found_generate(failure): + if failure.check(KeyNotFound): + logger.debug("Key not found. Generating key for %s" + % (address,)) + d = self._keymanager.gen_key(openpgp.OpenPGPKey) + d.addCallbacks(send_key, log_key_error("generating")) + return d + else: + return failure + + def send_key(_): + d = self._keymanager.send_key(openpgp.OpenPGPKey) + d.addCallbacks( + lambda _: logger.debug("Key generated successfully."), + log_key_error("sending")) + + def log_key_error(step): + def log_err(failure): + logger.error("Error while %s key!", (step,)) + logger.exception(failure.value) + return failure + return log_err + + d = self._keymanager.get_key( + address, openpgp.OpenPGPKey, private=True, fetch_remote=False) + d.addErrback(if_not_found_generate) + return d def run_soledad_setup_checks(self, provider_config, user, password, download_if_needed=False): @@ -664,9 +682,10 @@ class SoledadBootstrapper(AbstractBootstrapper): self.load_and_sync_soledad(uuid) if not flags.OFFLINE: - self._gen_key() - - self._signaler.signal(signal_finished) + d = self._gen_key() + d.addCallback(lambda _: self._signaler.signal(signal_finished)) + else: + self._signaler.signal(signal_finished) except Exception as e: # TODO: we should handle more specific exceptions in here self._soledad = None -- cgit v1.2.3 From 99a955c64266dc9dc596170beb024f84cd322254 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Thu, 15 Jan 2015 09:40:55 -0600 Subject: Use the incoming mail IService From kali: add some notes about the improper handling of the mailbox required to initialize the account, and draft some notes about how to improve this in next iterations. --- src/leap/bitmask/services/mail/conductor.py | 2 +- src/leap/bitmask/services/mail/imap.py | 40 ++++++++++++++++++--- src/leap/bitmask/services/mail/imapcontroller.py | 44 ++++++++++++++++-------- 3 files changed, 67 insertions(+), 19 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 0fb9f4fa..42bdd032 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -262,7 +262,7 @@ class MailConductor(IMAPControl, SMTPControl): if self._firewall is not None: self._firewall.start() if not offline: - logger.debug("not starting smtp in offline mode") + logger.debug("Starting smtp service...") self.start_smtp_service(download_if_needed=download_if_needed) self.start_imap_service() diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 5db18cb9..d044a600 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -21,7 +21,9 @@ import logging import os import sys +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 logger = logging.getLogger(__name__) @@ -49,6 +51,9 @@ def get_mail_check_period(): logger.warning("Unhandled error while getting %s: %r" % ( INCOMING_CHECK_PERIOD_ENV, exc)) + + if period is None: + period = INCOMING_CHECK_PERIOD return period @@ -61,12 +66,39 @@ def start_imap_service(*args, **kwargs): from leap.bitmask.config import flags logger.debug('Launching imap service') - override_period = get_mail_check_period() - if override_period: - kwargs['check_period'] = override_period - if flags.MAIL_LOGFILE: log.startLogging(open(flags.MAIL_LOGFILE, 'w')) log.startLogging(sys.stdout) return imap.run_service(*args, **kwargs) + + +def start_incoming_mail_service(keymanager, soledad, imap_factory, userid): + """ + Initalizes and starts the incomming mail service. + + :returns: a Deferred that will be fired with the IncomingMail instance + """ + def setUpIncomingMail(inbox): + incoming_mail = IncomingMail( + 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. + # XXX: I think we might be at risk here because the account top object + # currently just returns as many mailbox objects as it's asked for, so + # we should be careful about concurrent operations (ie, maybe just use + # this one to do inserts, or let account have an in-memory map of + # mailboxes, and just return references to them). + acc = imap_factory.theAccount + d = acc.callWhenReady(lambda _: acc.getMailbox(INBOX_NAME)) + d.addCallback(setUpIncomingMail) + return d diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index d0bf4c34..bb9eb9dc 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -43,9 +43,12 @@ class IMAPController(object): self._soledad = soledad self._keymanager = keymanager - self.imap_service = None + # XXX: this should live in its own controller + # or, better, just be managed by a composite Mail Service in + # leap.mail. self.imap_port = None self.imap_factory = None + self.incoming_mail_service = None def start_imap_service(self, userid, offline=False): """ @@ -58,16 +61,28 @@ class IMAPController(object): """ 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) + self.imap_port, self.imap_factory = imap.start_imap_service( + self._soledad, + userid=userid) + + def start_incoming_service(incoming_mail): + d = incoming_mail.startService() + d.addCallback(lambda started: incoming_mail) + return d + + def assign_incoming_service(incoming_mail): + self.incoming_mail_service = incoming_mail + return incoming_mail if offline is False: - logger.debug("Starting loop") - self.imap_service.start_loop() + d = imap.start_incoming_mail_service( + self._keymanager, + self._soledad, + self.imap_factory, + userid) + d.addCallback(start_incoming_service) + d.addCallback(assign_incoming_service) + d.addErrback(lambda f: logger.error(f.printTraceback())) def stop_imap_service(self, cv): """ @@ -77,11 +92,12 @@ class IMAPController(object): indeed stops. :type cv: threading.Condition """ - if self.imap_service is not None: + if self.incoming_mail_service is not None: # Stop the loop call in the fetcher - self.imap_service.stop() - self.imap_service = None + self.incoming_mail_service.stopService() + self.incoming_mail_service = None + if self.imap_port is not None: # Stop listening on the IMAP port self.imap_port.stopListening() @@ -98,6 +114,6 @@ class IMAPController(object): """ Fetch incoming mail. """ - if self.imap_service: + if self.incoming_mail_service is not None: logger.debug('Client connected, fetching mail...') - self.imap_service.fetch() + self.incoming_mail_service.fetch() -- cgit v1.2.3 From 39c0419cfa7e74e365c02091fc3cfe455da15404 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 16 Jan 2015 11:53:29 -0400 Subject: fix mail imports for new mail api (0.4.0) --- src/leap/bitmask/services/mail/plumber.py | 12 ++++-------- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 3 ++- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py index 1af65c5d..58625db5 100644 --- a/src/leap/bitmask/services/mail/plumber.py +++ b/src/leap/bitmask/services/mail/plumber.py @@ -17,6 +17,8 @@ """ Utils for manipulating local mailboxes. """ +# TODO --- this module has not yet catched up with 0.9.0 + import getpass import logging import os @@ -32,9 +34,7 @@ from leap.bitmask.provider import get_provider_path from leap.bitmask.services.soledad.soledadbootstrapper import get_db_paths from leap.bitmask.util import flatten, get_path_prefix -from leap.mail.imap.account import SoledadBackedAccount -from leap.mail.imap.memorystore import MemoryStore -from leap.mail.imap.soledadstore import SoledadStore +from leap.mail.imap.account import IMAPAccount from leap.soledad.client import Soledad logger = logging.getLogger(__name__) @@ -140,11 +140,7 @@ class MBOXPlumber(object): self.sol = initialize_soledad( self.uuid, self.userid, self.passwd, secrets, localdb, "/tmp", "/tmp") - memstore = MemoryStore( - permanent_store=SoledadStore(self.sol), - write_period=5) - self.acct = SoledadBackedAccount(self.userid, self.sol, - memstore=memstore) + self.acct = IMAPAccount(self.userid, self.sol) return True # diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index ac7ca836..045b2e19 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -45,7 +45,8 @@ from leap.common.files import which from leap.keymanager import KeyManager, openpgp from leap.keymanager.errors import KeyNotFound from leap.soledad.common.errors import InvalidAuthTokenError -from leap.soledad.client import Soledad, BootstrapSequenceError +from leap.soledad.client import Soledad +from leap.soledad.client.secrets import BootstrapSequenceError logger = logging.getLogger(__name__) -- cgit v1.2.3 From 46fabd42ad4cac7ce1b7f1818064f1c2e5c002c1 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 16 Jan 2015 20:01:40 -0400 Subject: pass userid correctly, and cast it to string --- src/leap/bitmask/services/mail/smtpbootstrapper.py | 3 ++- 1 file changed, 2 insertions(+), 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 9dd61488..6f45469b 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -120,6 +120,7 @@ class SMTPBootstrapper(AbstractBootstrapper): self._provider_config, about_to_download=True) from leap.mail.smtp import setup_smtp_gateway + self._smtp_service, self._smtp_port = setup_smtp_gateway( port=2013, userid=self._userid, @@ -152,7 +153,7 @@ class SMTPBootstrapper(AbstractBootstrapper): self._provider_config = ProviderConfig.get_provider_config(domain) self._keymanager = keymanager self._smtp_config = SMTPConfig() - self._userid = userid + self._userid = str(userid) self._download_if_needed = download_if_needed try: -- cgit v1.2.3 From 782fb8d66aabb29d68712e2fc220d967ef8dfcf5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 16 Jan 2015 20:03:11 -0400 Subject: remove use of threading.Condition we should deal with this with pure deferreds --- src/leap/bitmask/services/mail/imapcontroller.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index bb9eb9dc..1b39ef91 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -84,16 +84,16 @@ class IMAPController(object): d.addCallback(assign_incoming_service) d.addErrback(lambda f: logger.error(f.printTraceback())) - def stop_imap_service(self, cv): + def stop_imap_service(self): """ 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.incoming_mail_service is not None: # Stop the loop call in the fetcher + + # XXX BUG -- the deletion of the reference should be made + # after stopService() triggers its deferred (ie, cleanup has been + # made) self.incoming_mail_service.stopService() self.incoming_mail_service = None @@ -103,12 +103,7 @@ class IMAPController(object): # 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() + self.imap_factory.doStop() def fetch_incoming_mail(self): """ -- cgit v1.2.3 From 965d8a6bd4646fe6cc285e18355bbe2ce514b73b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 21 Jan 2015 11:03:28 -0400 Subject: do not terminate the session on the backend, moved to mail factory.do_Stop will handle this now. --- src/leap/bitmask/services/mail/imapcontroller.py | 1 - 1 file changed, 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index 1b39ef91..d374ac29 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -102,7 +102,6 @@ class IMAPController(object): self.imap_port.stopListening() # Stop the protocol - self.imap_factory.theAccount.closed = True self.imap_factory.doStop() def fetch_incoming_mail(self): -- cgit v1.2.3 From e52f9a239a146c06a0683e47eaf9d53f4deb332b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 11 Feb 2015 23:46:42 -0400 Subject: enable --offline mode for email again --- .../services/soledad/soledadbootstrapper.py | 116 +++++++++++---------- 1 file changed, 61 insertions(+), 55 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 045b2e19..e8946fa4 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -28,6 +28,7 @@ from sqlite3 import ProgrammingError as sqlite_ProgrammingError from u1db import errors as u1db_errors from twisted.internet import threads, defer +import zope.proxy from zope.proxy import sameProxiedObjects from pysqlcipher.dbapi2 import ProgrammingError as sqlcipher_ProgrammingError @@ -59,31 +60,6 @@ They should not be needed after we allow a null remote initialization in the soledad client, and a switch to remote sync-able mode during runtime. """ - -class Mock(object): - """ - A generic simple mock class - """ - def __init__(self, return_value=None): - self._return = return_value - - def __call__(self, *args, **kwargs): - return self._return - - -class MockSharedDB(object): - """ - Mocked SharedDB object to replace in soledad before - instantiating it in offline mode. - """ - get_doc = Mock() - put_doc = Mock() - lock = Mock(return_value=('atoken', 300)) - unlock = Mock(return_value=True) - - def __call__(self): - return self - # TODO these exceptions could be moved to soledad itself # after settling this down. @@ -146,7 +122,6 @@ class SoledadBootstrapper(AbstractBootstrapper): self._provider_config = None self._soledad_config = None - self._keymanager = None self._download_if_needed = False self._user = "" @@ -155,7 +130,9 @@ class SoledadBootstrapper(AbstractBootstrapper): self._uuid = "" self._srpauth = None - self._soledad = None + + self._soledad = zope.proxy.ProxyBase(None) + self._keymanager = zope.proxy.ProxyBase(None) @property def keymanager(self): @@ -190,9 +167,13 @@ class SoledadBootstrapper(AbstractBootstrapper): self._password = password self._uuid = uuid try: - self.load_and_sync_soledad(uuid, offline=True) - self._signaler.signal(self._signaler.soledad_offline_finished) + d = self.load_and_sync_soledad(uuid, offline=True) + d.addCallback( + lambda _: self._signaler.signal( + self._signaler.soledad_offline_finished)) + return d except Exception as e: + # XXX convert exception into failure.trap # TODO: we should handle more specific exceptions in here logger.exception(e) self._signaler.signal(self._signaler.soledad_offline_failed) @@ -248,7 +229,7 @@ class SoledadBootstrapper(AbstractBootstrapper): # warned the user in _do_soledad_sync() def _do_soledad_init(self, uuid, secrets_path, local_db_path, - server_url, cert_file, token): + server_url, cert_file, token, syncable): """ Initialize soledad, retry if necessary and raise an exception if we can't succeed. @@ -274,7 +255,7 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.debug("Trying to init soledad....") self._try_soledad_init( uuid, secrets_path, local_db_path, - server_url, cert_file, token) + server_url, cert_file, token, syncable) logger.debug("Soledad has been initialized.") return except Exception as exc: @@ -296,6 +277,8 @@ class SoledadBootstrapper(AbstractBootstrapper): :type uuid: unicode, or None. :param offline: whether to instantiate soledad for offline use. :type offline: bool + + :rtype: defer.Deferred """ local_param = self._get_soledad_local_params(uuid, offline) remote_param = self._get_soledad_server_params(uuid, offline) @@ -303,21 +286,26 @@ class SoledadBootstrapper(AbstractBootstrapper): secrets_path, local_db_path, token = local_param server_url, cert_file = remote_param - try: - self._do_soledad_init(uuid, secrets_path, local_db_path, - server_url, cert_file, token) - except SoledadInitError: - # re-raise the exceptions from try_init, - # we're currently handling the retries from the - # soledad-launcher in the gui. - raise - - leap_assert(not sameProxiedObjects(self._soledad, None), - "Null soledad, error while initializing") + if offline: + return self._load_soledad_nosync( + uuid, secrets_path, local_db_path, cert_file, token) - if flags.OFFLINE: - self._init_keymanager(self._address, token) else: + # We assume online operation from here on. + # XXX split in subfunction + syncable = True + try: + self._do_soledad_init(uuid, secrets_path, local_db_path, + server_url, cert_file, token, syncable) + except SoledadInitError: + # re-raise the exceptions from try_init, + # we're currently handling the retries from the + # soledad-launcher in the gui. + raise + + leap_assert(not sameProxiedObjects(self._soledad, None), + "Null soledad, error while initializing") + address = make_address( self._user, self._provider_config.get_domain()) @@ -335,9 +323,21 @@ class SoledadBootstrapper(AbstractBootstrapper): address, openpgp.OpenPGPKey, private=True, fetch_remote=False)) d.addCallbacks( + # XXX WTF --- FIXME remove this call to thread, soledad already + # does the sync in its own threadpool. -- kali lambda _: threads.deferToThread(self._do_soledad_sync), key_not_found) d.addErrback(self._soledad_sync_errback) + return d + + def _load_soledad_nosync(self, uuid, secrets_path, local_db_path, + cert_file, token): + + syncable = False + self._do_soledad_init(uuid, secrets_path, local_db_path, + "", cert_file, token, syncable) + d = self._init_keymanager(self._address, token) + return d def _pick_server(self, uuid): """ @@ -410,7 +410,7 @@ class SoledadBootstrapper(AbstractBootstrapper): raise SoledadSyncError() def _try_soledad_init(self, uuid, secrets_path, local_db_path, - server_url, cert_file, auth_token): + server_url, cert_file, auth_token, syncable): """ Try to initialize soledad. @@ -433,9 +433,6 @@ class SoledadBootstrapper(AbstractBootstrapper): # (issue #3309) encoding = sys.getfilesystemencoding() - # XXX We should get a flag in soledad itself - if flags.OFFLINE is True: - Soledad._shared_db = MockSharedDB() try: self._soledad = Soledad( uuid, @@ -445,7 +442,8 @@ class SoledadBootstrapper(AbstractBootstrapper): server_url=server_url, cert_file=cert_file.encode(encoding), auth_token=auth_token, - defer_encryption=True) + defer_encryption=True, + syncable=syncable) # XXX All these errors should be handled by soledad itself, # and return a subclass of SoledadInitializationFailed @@ -668,7 +666,9 @@ class SoledadBootstrapper(AbstractBootstrapper): self._user = user self._password = password - if flags.OFFLINE: + is_offline = flags.OFFLINE + + if is_offline: signal_finished = self._signaler.soledad_offline_finished signal_failed = self._signaler.soledad_offline_failed else: @@ -676,17 +676,23 @@ class SoledadBootstrapper(AbstractBootstrapper): signal_failed = self._signaler.soledad_bootstrap_failed try: - self._download_config() + if not is_offline: + # XXX FIXME make this async too! (use txrequests) + # Also, why the fuck would we want to download it *every time*? + # We should be fine by using last-time config, or at least + # trying it. + 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) + # 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: d = self._gen_key() d.addCallback(lambda _: self._signaler.signal(signal_finished)) + return d else: self._signaler.signal(signal_finished) + return defer.succeed(True) except Exception as e: # TODO: we should handle more specific exceptions in here self._soledad = None -- cgit v1.2.3 From 82652e174b4f38a29ce488421eb6c0067d0c657f Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Sat, 14 Feb 2015 17:52:27 -0600 Subject: Do the soledad sync the twisted way This closes: #6658 and #6691 --- .../services/soledad/soledadbootstrapper.py | 376 ++++++++++----------- 1 file changed, 172 insertions(+), 204 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index e8946fa4..f079b0cd 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -21,14 +21,12 @@ import logging import os import socket import sys -import time from ssl import SSLError from sqlite3 import ProgrammingError as sqlite_ProgrammingError from u1db import errors as u1db_errors -from twisted.internet import threads, defer -import zope.proxy +from twisted.internet import defer, reactor from zope.proxy import sameProxiedObjects from pysqlcipher.dbapi2 import ProgrammingError as sqlcipher_ProgrammingError @@ -60,9 +58,6 @@ They should not be needed after we allow a null remote initialization in the soledad client, and a switch to remote sync-able mode during runtime. """ -# TODO these exceptions could be moved to soledad itself -# after settling this down. - class SoledadSyncError(Exception): message = "Error while syncing Soledad" @@ -109,10 +104,6 @@ class SoledadBootstrapper(AbstractBootstrapper): PUBKEY_KEY = "user[public_key]" 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) @@ -125,30 +116,24 @@ class SoledadBootstrapper(AbstractBootstrapper): self._download_if_needed = False self._user = "" - self._password = "" + self._password = u"" self._address = "" self._uuid = "" self._srpauth = None - self._soledad = zope.proxy.ProxyBase(None) - self._keymanager = zope.proxy.ProxyBase(None) - - @property - def keymanager(self): - return self._keymanager - - @property - def soledad(self): - return self._soledad + self._soledad = None + self._keymanager = None @property def srpauth(self): if flags.OFFLINE is True: return None - leap_assert(self._provider_config is not None, - "We need a provider config") - return SRPAuth(self._provider_config) + if self._srpauth is None: + leap_assert(self._provider_config is not None, + "We need a provider config") + self._srpauth = SRPAuth(self._provider_config) + return self._srpauth # initialization @@ -166,18 +151,19 @@ class SoledadBootstrapper(AbstractBootstrapper): self._address = username self._password = password self._uuid = uuid - try: - d = self.load_and_sync_soledad(uuid, offline=True) - d.addCallback( - lambda _: self._signaler.signal( - self._signaler.soledad_offline_finished)) - return d - except Exception as e: - # XXX convert exception into failure.trap + + def error(failure): # TODO: we should handle more specific exceptions in here - logger.exception(e) + logger.exception(failure.value) self._signaler.signal(self._signaler.soledad_offline_failed) + d = self.load_and_sync_soledad(uuid, offline=True) + d.addCallback( + lambda _: self._signaler.signal( + self._signaler.soledad_offline_finished)) + d.addErrback(error) + return d + def _get_soledad_local_params(self, uuid, offline=False): """ Return the locals parameters needed for the soledad initialization. @@ -211,23 +197,17 @@ class SoledadBootstrapper(AbstractBootstrapper): :return: server_url, cert_file :rtype: tuple """ - if uuid is None: - uuid = self.srpauth.get_uuid() - if offline is True: server_url = "http://localhost:9999/" cert_file = "" else: + if uuid is None: + uuid = self.srpauth.get_uuid() server_url = self._pick_server(uuid) cert_file = self._provider_config.get_ca_cert_path() return server_url, cert_file - def _soledad_sync_errback(self, failure): - failure.trap(InvalidAuthTokenError) - # in the case of an invalid token we have already turned off mail and - # warned the user in _do_soledad_sync() - def _do_soledad_init(self, uuid, secrets_path, local_db_path, server_url, cert_file, token, syncable): """ @@ -268,16 +248,18 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.exception(exc) raise SoledadInitError() - def load_and_sync_soledad(self, uuid=None, offline=False): + def load_and_sync_soledad(self, uuid=u"", offline=False): """ Once everthing is in the right place, we instantiate and sync Soledad :param uuid: the uuid of the user, used in offline mode. - :type uuid: unicode, or None. + :type uuid: unicode. :param offline: whether to instantiate soledad for offline use. :type offline: bool + :return: A Deferred which fires when soledad is sync, or which fails + with SoledadInitError or SoledadSyncError :rtype: defer.Deferred """ local_param = self._get_soledad_local_params(uuid, offline) @@ -291,54 +273,46 @@ class SoledadBootstrapper(AbstractBootstrapper): uuid, secrets_path, local_db_path, cert_file, token) else: - # We assume online operation from here on. - # XXX split in subfunction - syncable = True - try: - self._do_soledad_init(uuid, secrets_path, local_db_path, - server_url, cert_file, token, syncable) - except SoledadInitError: - # re-raise the exceptions from try_init, - # we're currently handling the retries from the - # soledad-launcher in the gui. - raise + return self._load_soledad_online(uuid, secrets_path, local_db_path, + server_url, cert_file, token) - leap_assert(not sameProxiedObjects(self._soledad, None), - "Null soledad, error while initializing") + def _load_soledad_online(self, uuid, secrets_path, local_db_path, + server_url, cert_file, token): + syncable = True + try: + self._do_soledad_init(uuid, secrets_path, local_db_path, + server_url, cert_file, token, syncable) + except SoledadInitError as e: + # re-raise the exceptions from try_init, + # we're currently handling the retries from the + # soledad-launcher in the gui. + return defer.fail(e) - address = make_address( - self._user, self._provider_config.get_domain()) + leap_assert(not sameProxiedObjects(self._soledad, None), + "Null soledad, error while initializing") - def key_not_found(failure): - if failure.check(KeyNotFound): - logger.debug("Key not found. Generating key for %s" % - (address,)) - self._do_soledad_sync() - else: - return failure + address = make_address( + self._user, self._provider_config.get_domain()) + syncer = Syncer(self._soledad, self._signaler) - d = self._init_keymanager(address, token) - d.addCallback( - lambda _: self._keymanager.get_key( - address, openpgp.OpenPGPKey, - private=True, fetch_remote=False)) - d.addCallbacks( - # XXX WTF --- FIXME remove this call to thread, soledad already - # does the sync in its own threadpool. -- kali - lambda _: threads.deferToThread(self._do_soledad_sync), - key_not_found) - d.addErrback(self._soledad_sync_errback) - return d + d = self._init_keymanager(address, token) + d.addCallback(lambda _: syncer.sync()) + d.addErrback(self._soledad_sync_errback) + return d def _load_soledad_nosync(self, uuid, secrets_path, local_db_path, cert_file, token): - syncable = False self._do_soledad_init(uuid, secrets_path, local_db_path, "", cert_file, token, syncable) d = self._init_keymanager(self._address, token) return d + def _soledad_sync_errback(self, failure): + failure.trap(InvalidAuthTokenError) + # in the case of an invalid token we have already turned off mail and + # warned the user + def _pick_server(self, uuid): """ Choose a soledad server to sync against. @@ -363,52 +337,6 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.debug("Using soledad server url: %s" % (server_url,)) return server_url - def _do_soledad_sync(self): - """ - Do several retries to get an initial soledad sync. - """ - # and now, let's sync - 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() - 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: - # maybe it's my connection, but I'm getting - # ssl handshake timeouts and read errors quite often. - # A particularly big sync is a disaster. - # This deserves further investigation, maybe the - # retry strategy can be pushed to u1db, or at least - # it's something worthy to talk about with the - # ubuntu folks. - 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._signaler.signal( - 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 - - raise SoledadSyncError() - def _try_soledad_init(self, uuid, secrets_path, local_db_path, server_url, cert_file, auth_token, syncable): """ @@ -462,34 +390,6 @@ class SoledadBootstrapper(AbstractBootstrapper): "Soledad: %r" % (exc,)) raise - def _try_soledad_sync(self): - """ - Try to sync soledad. - Raises SoledadSyncError if not successful. - """ - try: - 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") - except u1db_errors.InvalidGeneration as exc: - logger.error("%r" % (exc,)) - raise SoledadSyncError("u1db: InvalidGeneration") - except (sqlite_ProgrammingError, sqlcipher_ProgrammingError) as e: - logger.exception("%r" % (e,)) - raise - except InvalidAuthTokenError: - # token is invalid, probably expired - logger.error('Invalid auth token while trying to sync Soledad') - raise - except Exception as exc: - logger.exception("Unhandled error while syncing " - "soledad: %r" % (exc,)) - raise SoledadSyncError("Failed to sync soledad") - def _download_config(self): """ Download the Soledad config for the given provider @@ -545,11 +445,10 @@ class SoledadBootstrapper(AbstractBootstrapper): :type token: str :rtype: Deferred """ - srp_auth = self.srpauth logger.debug('initializing keymanager...') - if flags.OFFLINE is True: - args = (address, "https://localhost", self._soledad) + if flags.OFFLINE: + nickserver_uri = "https://localhost" kwargs = { "ca_cert_path": "", "api_uri": "", @@ -558,27 +457,18 @@ class SoledadBootstrapper(AbstractBootstrapper): "gpgbinary": self._get_gpg_bin_path() } else: - args = ( - address, - "https://nicknym.%s:6425" % ( - self._provider_config.get_domain(),), - self._soledad - ) + nickserver_uri = "https://nicknym.%s:6425" % ( + self._provider_config.get_domain(),) kwargs = { "token": token, "ca_cert_path": self._provider_config.get_ca_cert_path(), "api_uri": self._provider_config.get_api_uri(), "api_version": self._provider_config.get_api_version(), - "uid": srp_auth.get_uuid(), + "uid": self.srpauth.get_uuid(), "gpgbinary": self._get_gpg_bin_path() } - try: - self._keymanager = KeyManager(*args, **kwargs) - except KeyNotFound: - logger.debug('key for %s not found.' % address) - except Exception as exc: - logger.exception(exc) - raise + self._keymanager = KeyManager(address, nickserver_uri, self._soledad, + **kwargs) if flags.OFFLINE is False: # make sure key is in server @@ -586,8 +476,9 @@ class SoledadBootstrapper(AbstractBootstrapper): def send_errback(failure): if failure.check(KeyNotFound): - logger.debug('No key found for %s, will generate soon.' - % address) + logger.debug( + 'No key found for %s, it might be because soledad not ' + 'synced yet or it will generate it soon.' % address) else: logger.error("Error sending key to server.") logger.exception(failure.value) @@ -615,14 +506,12 @@ class SoledadBootstrapper(AbstractBootstrapper): logger.debug("Retrieving key for %s" % (address,)) def if_not_found_generate(failure): - if failure.check(KeyNotFound): - logger.debug("Key not found. Generating key for %s" - % (address,)) - d = self._keymanager.gen_key(openpgp.OpenPGPKey) - d.addCallbacks(send_key, log_key_error("generating")) - return d - else: - return failure + failure.trap(KeyNotFound) + logger.debug("Key not found. Generating key for %s" + % (address,)) + d = self._keymanager.gen_key(openpgp.OpenPGPKey) + d.addCallbacks(send_key, log_key_error("generating")) + return d def send_key(_): d = self._keymanager.send_key(openpgp.OpenPGPKey) @@ -657,6 +546,8 @@ class SoledadBootstrapper(AbstractBootstrapper): files if the have changed since the time it was previously downloaded. :type download_if_needed: bool + + :return: Deferred """ leap_assert_type(provider_config, ProviderConfig) @@ -666,36 +557,113 @@ class SoledadBootstrapper(AbstractBootstrapper): self._user = user self._password = password - is_offline = flags.OFFLINE - - if is_offline: + 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 + self._signaler.signal(signal_finished) + return defer.succeed(True) + + signal_finished = self._signaler.soledad_bootstrap_finished + signal_failed = self._signaler.soledad_bootstrap_failed try: - if not is_offline: - # XXX FIXME make this async too! (use txrequests) - # Also, why the fuck would we want to download it *every time*? - # We should be fine by using last-time config, or at least - # trying it. - 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) - - d = self._gen_key() - d.addCallback(lambda _: self._signaler.signal(signal_finished)) - return d - else: - self._signaler.signal(signal_finished) - return defer.succeed(True) + # XXX FIXME make this async too! (use txrequests) + # Also, why the fuck would we want to download it *every time*? + # We should be fine by using last-time config, or at least + # trying it. + self._download_config() + uuid = self.srpauth.get_uuid() 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, )) + logger.exception("Error while bootstrapping Soledad: %r" % (e,)) self._signaler.signal(signal_failed) + return defer.succeed(None) + + # soledad config is ok, let's proceed to load and sync soledad + d = self.load_and_sync_soledad(uuid) + d.addCallback(lambda _: self._gen_key()) + d.addCallback(lambda _: self._signaler.signal(signal_finished)) + return d + + +class Syncer(object): + """ + Takes care of retries, timeouts and other issues while syncing + """ + # XXX: the timeout and proably all the stuff here should be moved to + # soledad + + MAX_SYNC_RETRIES = 10 + WAIT_MAX_SECONDS = 600 + + def __init__(self, soledad, signaler): + self._tries = 0 + self._soledad = soledad + self._signaler = signaler + + def sync(self): + self._callback_deferred = defer.Deferred() + self._try_sync() + return self._callback_deferred + + def _try_sync(self): + logger.debug("BOOTSTRAPPER: trying to self Soledad....") + # pass defer_decryption=False to get inline decryption + # for debugging. + self._sync_deferred = self._soledad.sync(defer_decryption=True) + self._sync_deferred.addCallbacks(self._success, self._error) + reactor.callLater(self.WAIT_MAX_SECONDS, self._timeout) + + def _success(self, result): + logger.debug("Soledad has been synced!") + self._callback_deferred.callback(result) + # so long, and thanks for all the fish + + def _error(self, failure): + if failure.check(InvalidAuthTokenError): + logger.error('Invalid auth token while trying to self Soledad') + self._signaler.signal( + self._signaler.soledad_invalid_auth_token) + self._callback_deferred.fail(failure) + elif failure.check(sqlite_ProgrammingError, + sqlcipher_ProgrammingError): + logger.exception("%r" % (failure.value,)) + self._callback_deferred.fail(failure) + elif failure.check(SSLError): + logger.error("%r" % (failure.value,)) + self._retry() + elif failure.check(u1db_errors.InvalidGeneration): + logger.error("%r" % (failure.value,)) + self._retry() + else: + logger.exception("Unhandled error while syncing " + "soledad: %r" % (failure.value,)) + self._retry() + + def _timeout(self): + if not self._soledad.syncing: + # timeout only if is still syncing + return + + # maybe it's my connection, but I'm getting + # ssl handshake timeouts and read errors quite often. + # A particularly big sync is a disaster. + # This deserves further investigation, maybe the + # retry strategy can be pushed to u1db, or at least + # it's something worthy to talk about with the + # ubuntu folks. + self._sync_deferred.cancel() + self._retry() + + def _retry(self): + self._tries += 1 + if self._tries > self.MAX_SYNC_RETRIES: + msg = "Sync failed, retrying... (retry {0} of {1})".format( + self._tries, self.MAX_SYNC_RETRIES) + logger.warning(msg) + self._try_sync() + else: + logger.error("Sync failed {0} times".format(self._tries)) + self._callback_deferred.fail( + SoledadSyncError("Too many retries")) -- cgit v1.2.3 From f605abccb3a41d32982ebbcb50ccc7ef0bc50abe Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 18 Feb 2015 14:50:29 -0400 Subject: Re-add public properties removed in previous commit the set_proxies_cb function in backend/components expects to have access to these public properties. --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 8 ++++++++ 1 file changed, 8 insertions(+) (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 f079b0cd..879ed1d0 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -135,6 +135,14 @@ class SoledadBootstrapper(AbstractBootstrapper): self._srpauth = SRPAuth(self._provider_config) return self._srpauth + @property + def soledad(self): + return self._soledad + + @property + def keymanager(self): + return self._keymanager + # initialization def load_offline_soledad(self, username, password, uuid): -- cgit v1.2.3 From 2a3d13c9734651ed8011029665c82ecdd63cad98 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 18 Feb 2015 11:34:13 -0600 Subject: Use the collection instead of the mailbox to initalize IncomingMail --- src/leap/bitmask/services/mail/imap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index d044a600..da753a0b 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -83,7 +83,7 @@ def start_incoming_mail_service(keymanager, soledad, imap_factory, userid): incoming_mail = IncomingMail( keymanager, soledad, - inbox, + inbox.collection, userid, check_period=get_mail_check_period()) return incoming_mail -- cgit v1.2.3 From e59e47675e92115f6c98b13cae518ede22e935eb Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Mon, 9 Mar 2015 14:39:46 +0100 Subject: [bug] Use Deferred.errback The code was using 'fail' which is not a Deferred method. - Resolves: #6772 --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 2 +- 1 file changed, 1 insertion(+), 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 879ed1d0..6cb4c116 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -673,5 +673,5 @@ class Syncer(object): self._try_sync() else: logger.error("Sync failed {0} times".format(self._tries)) - self._callback_deferred.fail( + self._callback_deferred.errback( SoledadSyncError("Too many retries")) -- cgit v1.2.3 From fb68d7f9047e88e9c5bfb5dd1c74a62e7c3c77b4 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Thu, 5 Mar 2015 12:26:51 -0400 Subject: [doc] Remove unneded comment about collection refs This concern is addressed by the following mail pullreq, that will be into 0.4.0 release: https://github.com/leapcode/leap_mail/pull/175 By the way, it is really funny that I cannot tell if this comment was written by meskio, as the blame says, or if I was the original author of the remark. I should stop drinking so much coffee. --- src/leap/bitmask/services/mail/imap.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index da753a0b..30646a63 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -93,11 +93,6 @@ def start_incoming_mail_service(keymanager, soledad, imap_factory, userid): # 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. - # XXX: I think we might be at risk here because the account top object - # currently just returns as many mailbox objects as it's asked for, so - # we should be careful about concurrent operations (ie, maybe just use - # this one to do inserts, or let account have an in-memory map of - # mailboxes, and just return references to them). acc = imap_factory.theAccount d = acc.callWhenReady(lambda _: acc.getMailbox(INBOX_NAME)) d.addCallback(setUpIncomingMail) -- cgit v1.2.3 From 3cb7948dafe3a9c9a65dcdbd1da1d5405e1ef459 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Wed, 4 Mar 2015 18:03:47 -0300 Subject: [bug] use ports specified in eip-service.json Replace the hardcoded port '1194' for the port specified in eip-service.json. Choose the best port to use according which one is enabled in the eip-service.json file Resolves: #6541 --- src/leap/bitmask/services/eip/eipconfig.py | 18 ++++++++++++++ src/leap/bitmask/services/eip/vpnlauncher.py | 35 +++++++++++++++++++++------- src/leap/bitmask/services/eip/vpnprocess.py | 6 +++-- 3 files changed, 49 insertions(+), 10 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 f4d6b216..d5947eb1 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -302,6 +302,24 @@ class EIPConfig(ServiceConfig): logger.error("Invalid ip address in config: %s" % (ip_addr_str,)) return None + def get_gateway_ports(self, index=0): + """ + Return the ports of the gateway. + + :param index: the gateway number to get the ports from + :type index: int + + :rtype: list of int + """ + gateways = self.get_gateways() + leap_assert(len(gateways) > 0, "We don't have any gateway!") + if index > len(gateways): + index = 0 + logger.warning("Provided an unknown gateway index %s, " + + "defaulting to 0") + + return gateways[index]["capabilities"]["ports"] + def get_client_cert_path(self, providerconfig=None, about_to_download=False): diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index 72e19413..7793d624 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -106,12 +106,15 @@ class VPNLauncher(object): UP_SCRIPT = None DOWN_SCRIPT = None + PREFERRED_PORTS = ("443", "80", "53", "1194") + @classmethod @abstractmethod def get_gateways(kls, eipconfig, providerconfig): """ - Return the selected gateways for a given provider, looking at the EIP - config file. + Return a list with the selected gateways for a given provider, looking + at the EIP config file. + Each item of the list is a tuple containing (gateway, port). :param eipconfig: eip configuration object :type eipconfig: EIPConfig @@ -122,21 +125,37 @@ class VPNLauncher(object): :rtype: list """ gateways = [] + settings = Settings() domain = providerconfig.get_domain() gateway_conf = settings.get_selected_gateway(domain) gateway_selector = VPNGatewaySelector(eipconfig) if gateway_conf == GATEWAY_AUTOMATIC: - gateways = gateway_selector.get_gateways() + gws = gateway_selector.get_gateways() else: - gateways = [gateway_conf] + gws = [gateway_conf] - if not gateways: + if not gws: logger.error('No gateway was found!') raise VPNLauncherException('No gateway was found!') - logger.debug("Using gateways ips: {0}".format(', '.join(gateways))) + for idx, gw in enumerate(gws): + ports = eipconfig.get_gateway_ports(idx) + + the_port = "1194" # default port + + # pick the port preferring this order: + for port in kls.PREFERRED_PORTS: + if port in ports: + the_port = port + break + else: + continue + + gateways.append((gw, the_port)) + + logger.debug("Using gateways (ip, port): {0!r}".format(gateways)) return gateways @classmethod @@ -194,8 +213,8 @@ class VPNLauncher(object): gateways = kls.get_gateways(eipconfig, providerconfig) - for gw in gateways: - args += ['--remote', gw, '1194', 'udp'] + for ip, port in gateways: + args += ['--remote', ip, port, 'udp'] args += [ '--client', diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 8dc6021f..3e46418c 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -961,9 +961,11 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): :rtype: list """ - gateways = self._launcher.get_gateways( + gateways_ports = self._launcher.get_gateways( self._eipconfig, self._providerconfig) - return gateways + + # filter out ports since we don't need that info + return [gateway for gateway, port in gateways_ports] # shutdown -- cgit v1.2.3 From 9515c944279e08221de1852ab373d24232dccbf1 Mon Sep 17 00:00:00 2001 From: Ruben Pollan Date: Wed, 29 Apr 2015 00:55:53 +0200 Subject: [bug] fix soledad bootstrap sync issues * Instead of checking if soledad is still syncing for the timeuot cancel the delayed call. * Count retries properly. * Now soledad sync only returns SoledadError (#6981). --- .../bitmask/services/soledad/soledadbootstrapper.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 6cb4c116..9864e4e1 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -22,7 +22,6 @@ import os import socket import sys -from ssl import SSLError from sqlite3 import ProgrammingError as sqlite_ProgrammingError from u1db import errors as u1db_errors @@ -621,14 +620,17 @@ class Syncer(object): # for debugging. self._sync_deferred = self._soledad.sync(defer_decryption=True) self._sync_deferred.addCallbacks(self._success, self._error) - reactor.callLater(self.WAIT_MAX_SECONDS, self._timeout) + self._timeout_delayed_call = reactor.callLater(self.WAIT_MAX_SECONDS, + self._timeout) def _success(self, result): logger.debug("Soledad has been synced!") + self._timeout_delayed_call.cancel() self._callback_deferred.callback(result) # so long, and thanks for all the fish def _error(self, failure): + self._timeout_delayed_call.cancel() if failure.check(InvalidAuthTokenError): logger.error('Invalid auth token while trying to self Soledad') self._signaler.signal( @@ -638,22 +640,11 @@ class Syncer(object): sqlcipher_ProgrammingError): logger.exception("%r" % (failure.value,)) self._callback_deferred.fail(failure) - elif failure.check(SSLError): - logger.error("%r" % (failure.value,)) - self._retry() - elif failure.check(u1db_errors.InvalidGeneration): - logger.error("%r" % (failure.value,)) - self._retry() else: - logger.exception("Unhandled error while syncing " - "soledad: %r" % (failure.value,)) + logger.error("%r" % (failure.value,)) self._retry() def _timeout(self): - if not self._soledad.syncing: - # timeout only if is still syncing - return - # maybe it's my connection, but I'm getting # ssl handshake timeouts and read errors quite often. # A particularly big sync is a disaster. @@ -666,7 +657,7 @@ class Syncer(object): def _retry(self): self._tries += 1 - if self._tries > self.MAX_SYNC_RETRIES: + if self._tries < self.MAX_SYNC_RETRIES: msg = "Sync failed, retrying... (retry {0} of {1})".format( self._tries, self.MAX_SYNC_RETRIES) logger.warning(msg) -- cgit v1.2.3 From 5a0de9fd25d783039345674680c67a2bd91815a5 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 7 May 2015 11:21:02 -0300 Subject: [feat] adapt to new events api on common - Related: #6359 --- src/leap/bitmask/services/mail/conductor.py | 53 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 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 42bdd032..b76ce436 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -24,7 +24,7 @@ from leap.bitmask.gui import statemachines from leap.bitmask.services.mail import connection as mail_connection from leap.bitmask.services.mail.emailfirewall import get_email_firewall -from leap.common.events import events_pb2 as leap_events +from leap.common.events import catalog from leap.common.events import register as leap_register @@ -42,15 +42,12 @@ class IMAPControl(object): self.imap_machine = None self.imap_connection = None - leap_register(signal=leap_events.IMAP_SERVICE_STARTED, - callback=self._handle_imap_events, - reqcbk=lambda req, resp: None) - 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) + leap_register(event=catalog.IMAP_SERVICE_STARTED, + callback=self._handle_imap_events) + leap_register(event=catalog.IMAP_SERVICE_FAILED_TO_START, + callback=self._handle_imap_events) + leap_register(event=catalog.IMAP_CLIENT_LOGIN, + callback=self._handle_imap_events) def set_imap_connection(self, imap_connection): """ @@ -77,18 +74,20 @@ class IMAPControl(object): self._backend.imap_stop_service() - def _handle_imap_events(self, req): + def _handle_imap_events(self, event, content): """ Callback handler for the IMAP events - :param req: Request type - :type req: leap.common.events.events_pb2.SignalRequest + :param event: The event that triggered the callback. + :type event: str + :param content: The content of the event. + :type content: list """ - if req.event == leap_events.IMAP_SERVICE_STARTED: + if event == catalog.IMAP_SERVICE_STARTED: self._on_imap_connected() - elif req.event == leap_events.IMAP_SERVICE_FAILED_TO_START: + elif event == catalog.IMAP_SERVICE_FAILED_TO_START: self._on_imap_failed() - elif req.event == leap_events.IMAP_CLIENT_LOGIN: + elif event == catalog.IMAP_CLIENT_LOGIN: self._on_mail_client_logged_in() def _on_mail_client_logged_in(self): @@ -124,12 +123,10 @@ class SMTPControl(object): self.smtp_connection = None self.smtp_machine = None - leap_register(signal=leap_events.SMTP_SERVICE_STARTED, - callback=self._handle_smtp_events, - reqcbk=lambda req, resp: None) - leap_register(signal=leap_events.SMTP_SERVICE_FAILED_TO_START, - callback=self._handle_smtp_events, - reqcbk=lambda req, resp: None) + leap_register(event=catalog.SMTP_SERVICE_STARTED, + callback=self._handle_smtp_events) + leap_register(event=catalog.SMTP_SERVICE_FAILED_TO_START, + callback=self._handle_smtp_events) def set_smtp_connection(self, smtp_connection): """ @@ -158,16 +155,18 @@ class SMTPControl(object): self.smtp_connection.qtsigs.disconnecting_signal.emit() self._backend.smtp_stop_service() - def _handle_smtp_events(self, req): + def _handle_smtp_events(self, event, content): """ Callback handler for the SMTP events. - :param req: Request type - :type req: leap.common.events.events_pb2.SignalRequest + :param event: The event that triggered the callback. + :type event: str + :param content: The content of the event. + :type content: list """ - if req.event == leap_events.SMTP_SERVICE_STARTED: + if event == catalog.SMTP_SERVICE_STARTED: self.on_smtp_connected() - elif req.event == leap_events.SMTP_SERVICE_FAILED_TO_START: + elif event == catalog.SMTP_SERVICE_FAILED_TO_START: self.on_smtp_failed() def on_smtp_connecting(self): -- cgit v1.2.3 From 4d33b0637ae1280ba818b40eb16003974666721b Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 8 Jun 2015 12:09:53 -0400 Subject: [bug] fix attribute error on mail conductor due to remaining bits that had not been changed after a refactor. - Resolves: #7093 --- src/leap/bitmask/services/mail/conductor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index b76ce436..2f1d20e6 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -94,7 +94,9 @@ class IMAPControl(object): """ On mail client logged in, fetch incoming mail. """ - self._controller.imap_service_fetch() + # XXX needs to be adapted to the new-ish incoming mail service. + # Doing nothing for now, this could be moved to mail package itself. + logger.debug("A MUA has logged in, should react by forcing a fetch.") def _on_imap_connecting(self): """ -- cgit v1.2.3 From 32658ae3108bc67a102cf6e0153d468b3a8ae1b0 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Fri, 12 Jun 2015 14:34:18 -0300 Subject: [feat] replace old log handler with new one Replace logging.getLogger with custom get_logger. Remove some unneeded dependencies and reorder other. --- src/leap/bitmask/services/__init__.py | 4 ++-- src/leap/bitmask/services/abstractbootstrapper.py | 5 ++--- src/leap/bitmask/services/eip/conductor.py | 5 ++--- src/leap/bitmask/services/eip/darwinvpnlauncher.py | 4 ++-- src/leap/bitmask/services/eip/eipbootstrapper.py | 4 ++-- src/leap/bitmask/services/eip/eipconfig.py | 3 ++- src/leap/bitmask/services/eip/linuxvpnlauncher.py | 4 ++-- src/leap/bitmask/services/eip/vpnlauncher.py | 4 ++-- src/leap/bitmask/services/eip/vpnprocess.py | 9 ++++----- src/leap/bitmask/services/eip/windowsvpnlauncher.py | 5 ++--- src/leap/bitmask/services/mail/conductor.py | 5 ++--- src/leap/bitmask/services/mail/imap.py | 4 ++-- src/leap/bitmask/services/mail/imapcontroller.py | 6 ++---- src/leap/bitmask/services/mail/plumber.py | 4 ++-- src/leap/bitmask/services/mail/smtpbootstrapper.py | 4 ++-- src/leap/bitmask/services/mail/smtpconfig.py | 4 ++-- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 4 ++-- src/leap/bitmask/services/soledad/soledadconfig.py | 5 ++--- 18 files changed, 38 insertions(+), 45 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py index ba12ba4e..54426669 100644 --- a/src/leap/bitmask/services/__init__.py +++ b/src/leap/bitmask/services/__init__.py @@ -17,7 +17,6 @@ """ Services module. """ -import logging import os import sys @@ -25,6 +24,7 @@ from PySide import QtCore from leap.bitmask.config import flags from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.logs.utils import get_logger from leap.bitmask.util.constants import REQUEST_TIMEOUT from leap.bitmask.util.privilege_policies import is_missing_policy_permissions from leap.bitmask.util.request_helpers import get_content @@ -34,7 +34,7 @@ from leap.common.check import leap_assert from leap.common.config.baseconfig import BaseConfig from leap.common.files import get_mtime -logger = logging.getLogger(__name__) +logger = get_logger() EIP_SERVICE = u"openvpn" diff --git a/src/leap/bitmask/services/abstractbootstrapper.py b/src/leap/bitmask/services/abstractbootstrapper.py index 77929b75..6a08f475 100644 --- a/src/leap/bitmask/services/abstractbootstrapper.py +++ b/src/leap/bitmask/services/abstractbootstrapper.py @@ -18,8 +18,6 @@ """ Abstract bootstrapper implementation """ -import logging - import requests from functools import partial @@ -30,9 +28,10 @@ from twisted.python import log from twisted.internet import threads from twisted.internet.defer import CancelledError +from leap.bitmask.logs.utils import get_logger from leap.common.check import leap_assert, leap_assert_type -logger = logging.getLogger(__name__) +logger = get_logger() class AbstractBootstrapper(QtCore.QObject): diff --git a/src/leap/bitmask/services/eip/conductor.py b/src/leap/bitmask/services/eip/conductor.py index 3fc88724..3386dddf 100644 --- a/src/leap/bitmask/services/eip/conductor.py +++ b/src/leap/bitmask/services/eip/conductor.py @@ -20,10 +20,9 @@ EIP Conductor module. This handles Qt Signals and triggers the calls to the backend, where the VPNProcess has been initialized. """ -import logging - from PySide import QtCore +from leap.bitmask.logs.utils import get_logger from leap.bitmask.gui import statemachines from leap.bitmask.services import EIP_SERVICE from leap.bitmask.services import get_service_display_name @@ -31,7 +30,7 @@ from leap.bitmask.services.eip.connection import EIPConnection from leap.bitmask.platform_init import IS_MAC QtDelayedCall = QtCore.QTimer.singleShot -logger = logging.getLogger(__name__) +logger = get_logger() class EIPConductor(object): diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py index f83e0170..17fc11c2 100644 --- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py +++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py @@ -19,15 +19,15 @@ Darwin VPN launcher implementation. """ import commands import getpass -import logging import os import sys +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services.eip.vpnlauncher import VPNLauncher from leap.bitmask.services.eip.vpnlauncher import VPNLauncherException from leap.bitmask.util import get_path_prefix -logger = logging.getLogger(__name__) +logger = get_logger() class EIPNoTunKextLoaded(VPNLauncherException): diff --git a/src/leap/bitmask/services/eip/eipbootstrapper.py b/src/leap/bitmask/services/eip/eipbootstrapper.py index f78113bc..7a331d71 100644 --- a/src/leap/bitmask/services/eip/eipbootstrapper.py +++ b/src/leap/bitmask/services/eip/eipbootstrapper.py @@ -17,11 +17,11 @@ """ EIP bootstrapping """ -import logging import os from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.certs import download_client_cert +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.eip.eipconfig import EIPConfig @@ -29,7 +29,7 @@ from leap.common import certs as leap_certs from leap.common.check import leap_assert, leap_assert_type from leap.common.files import check_and_fix_urw_only -logger = logging.getLogger(__name__) +logger = get_logger() class EIPBootstrapper(AbstractBootstrapper): diff --git a/src/leap/bitmask/services/eip/eipconfig.py b/src/leap/bitmask/services/eip/eipconfig.py index d5947eb1..b1d08393 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -26,12 +26,13 @@ import ipaddr from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import ServiceConfig from leap.bitmask.services.eip.eipspec import get_schema from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type -logger = logging.getLogger(__name__) +logger = get_logger() def get_eipconfig_path(domain, relative=True): diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index a3ab408b..cf14a8f9 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -18,11 +18,11 @@ Linux VPN launcher implementation. """ import commands -import logging import os import sys from leap.bitmask.config import flags +from leap.bitmask.logs.utils import get_logger from leap.bitmask.util.privilege_policies import LinuxPolicyChecker from leap.bitmask.util.privilege_policies import NoPolkitAuthAgentAvailable from leap.bitmask.util.privilege_policies import NoPkexecAvailable @@ -31,7 +31,7 @@ from leap.bitmask.services.eip.vpnlauncher import VPNLauncherException from leap.bitmask.util import get_path_prefix, force_eval from leap.bitmask.util import first -logger = logging.getLogger(__name__) +logger = get_logger() COM = commands diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py index 7793d624..c48f857c 100644 --- a/src/leap/bitmask/services/eip/vpnlauncher.py +++ b/src/leap/bitmask/services/eip/vpnlauncher.py @@ -19,7 +19,6 @@ Platform independant VPN launcher interface. """ import getpass import hashlib -import logging import os import stat @@ -27,6 +26,7 @@ from abc import ABCMeta, abstractmethod from functools import partial from leap.bitmask.config import flags +from leap.bitmask.logs.utils import get_logger from leap.bitmask.backend.settings import Settings, GATEWAY_AUTOMATIC from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.platform_init import IS_LINUX @@ -35,7 +35,7 @@ from leap.bitmask.util import force_eval from leap.common.check import leap_assert, leap_assert_type -logger = logging.getLogger(__name__) +logger = get_logger() class VPNLauncherException(Exception): diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py index 3e46418c..586b50f5 100644 --- a/src/leap/bitmask/services/eip/vpnprocess.py +++ b/src/leap/bitmask/services/eip/vpnprocess.py @@ -18,7 +18,6 @@ VPN Manager, spawned in a custom processProtocol. """ import commands -import logging import os import shutil import socket @@ -39,6 +38,7 @@ except ImportError: from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services.eip import get_vpn_launcher from leap.bitmask.services.eip import linuxvpnlauncher from leap.bitmask.services.eip.eipconfig import EIPConfig @@ -47,13 +47,12 @@ from leap.bitmask.util import first, force_eval from leap.bitmask.platform_init import IS_MAC, IS_LINUX from leap.common.check import leap_assert, leap_assert_type -logger = logging.getLogger(__name__) -vpnlog = logging.getLogger('leap.openvpn') - from twisted.internet import defer, protocol, reactor from twisted.internet import error as internet_error from twisted.internet.task import LoopingCall +logger = get_logger() + class VPNObserver(object): """ @@ -884,7 +883,7 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager): """ # truncate the newline line = data[:-1] - vpnlog.info(line) + logger.info(line) self._vpn_observer.watch(line) def processExited(self, reason): diff --git a/src/leap/bitmask/services/eip/windowsvpnlauncher.py b/src/leap/bitmask/services/eip/windowsvpnlauncher.py index 3f1ed43b..aaa3e45f 100644 --- a/src/leap/bitmask/services/eip/windowsvpnlauncher.py +++ b/src/leap/bitmask/services/eip/windowsvpnlauncher.py @@ -17,12 +17,11 @@ """ Windows VPN launcher implementation. """ -import logging - +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services.eip.vpnlauncher import VPNLauncher from leap.common.check import leap_assert -logger = logging.getLogger(__name__) +logger = get_logger() class WindowsVPNLauncher(VPNLauncher): diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py index 2f1d20e6..68197d9d 100644 --- a/src/leap/bitmask/services/mail/conductor.py +++ b/src/leap/bitmask/services/mail/conductor.py @@ -17,9 +17,8 @@ """ Mail Services Conductor """ -import logging - from leap.bitmask.config import flags +from leap.bitmask.logs.utils import get_logger from leap.bitmask.gui import statemachines from leap.bitmask.services.mail import connection as mail_connection from leap.bitmask.services.mail.emailfirewall import get_email_firewall @@ -28,7 +27,7 @@ from leap.common.events import catalog from leap.common.events import register as leap_register -logger = logging.getLogger(__name__) +logger = get_logger() class IMAPControl(object): diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py index 30646a63..5934756d 100644 --- a/src/leap/bitmask/services/mail/imap.py +++ b/src/leap/bitmask/services/mail/imap.py @@ -17,16 +17,16 @@ """ Initialization of imap service """ -import logging import os import sys +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 -logger = logging.getLogger(__name__) +logger = get_logger() # The name of the environment variable that has to be # set to override the default time value, in seconds. diff --git a/src/leap/bitmask/services/mail/imapcontroller.py b/src/leap/bitmask/services/mail/imapcontroller.py index d374ac29..e5313477 100644 --- a/src/leap/bitmask/services/mail/imapcontroller.py +++ b/src/leap/bitmask/services/mail/imapcontroller.py @@ -17,12 +17,10 @@ """ IMAP service controller. """ -import logging - +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services.mail import imap - -logger = logging.getLogger(__name__) +logger = get_logger() class IMAPController(object): diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py index 58625db5..43203f0c 100644 --- a/src/leap/bitmask/services/mail/plumber.py +++ b/src/leap/bitmask/services/mail/plumber.py @@ -30,6 +30,7 @@ from twisted.internet import defer from leap.bitmask.backend.settings import Settings from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.logs.utils import get_logger from leap.bitmask.provider import get_provider_path from leap.bitmask.services.soledad.soledadbootstrapper import get_db_paths from leap.bitmask.util import flatten, get_path_prefix @@ -37,8 +38,7 @@ from leap.bitmask.util import flatten, get_path_prefix from leap.mail.imap.account import IMAPAccount from leap.soledad.client import Soledad -logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG) +logger = get_logger() def initialize_soledad(uuid, email, passwd, diff --git a/src/leap/bitmask/services/mail/smtpbootstrapper.py b/src/leap/bitmask/services/mail/smtpbootstrapper.py index 6f45469b..cd871803 100644 --- a/src/leap/bitmask/services/mail/smtpbootstrapper.py +++ b/src/leap/bitmask/services/mail/smtpbootstrapper.py @@ -17,11 +17,11 @@ """ SMTP bootstrapping """ -import logging import os from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.certs import download_client_cert +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.mail.smtpconfig import SMTPConfig @@ -31,7 +31,7 @@ from leap.common import certs as leap_certs from leap.common.check import leap_assert from leap.common.files import check_and_fix_urw_only -logger = logging.getLogger(__name__) +logger = get_logger() class NoSMTPHosts(Exception): diff --git a/src/leap/bitmask/services/mail/smtpconfig.py b/src/leap/bitmask/services/mail/smtpconfig.py index 09f90314..2d8de411 100644 --- a/src/leap/bitmask/services/mail/smtpconfig.py +++ b/src/leap/bitmask/services/mail/smtpconfig.py @@ -17,16 +17,16 @@ """ SMTP configuration """ -import logging import os from leap.bitmask.config.providerconfig import ProviderConfig +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import ServiceConfig from leap.bitmask.services.mail.smtpspec import get_schema from leap.bitmask.util import get_path_prefix from leap.common.check import leap_assert, leap_assert_type -logger = logging.getLogger(__name__) +logger = get_logger() class SMTPConfig(ServiceConfig): diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 9864e4e1..242bfb3d 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -17,7 +17,6 @@ """ Soledad bootstrapping """ -import logging import os import socket import sys @@ -32,6 +31,7 @@ from pysqlcipher.dbapi2 import ProgrammingError as sqlcipher_ProgrammingError from leap.bitmask.config import flags from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import download_service_config from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.soledad.soledadconfig import SoledadConfig @@ -46,7 +46,7 @@ from leap.soledad.common.errors import InvalidAuthTokenError from leap.soledad.client import Soledad from leap.soledad.client.secrets import BootstrapSequenceError -logger = logging.getLogger(__name__) +logger = get_logger() """ These mocks are replicated from imap tests and the repair utility. diff --git a/src/leap/bitmask/services/soledad/soledadconfig.py b/src/leap/bitmask/services/soledad/soledadconfig.py index d3cc7da4..8052bcdb 100644 --- a/src/leap/bitmask/services/soledad/soledadconfig.py +++ b/src/leap/bitmask/services/soledad/soledadconfig.py @@ -17,12 +17,11 @@ """ Soledad configuration """ -import logging - +from leap.bitmask.logs.utils import get_logger from leap.bitmask.services import ServiceConfig from leap.bitmask.services.soledad.soledadspec import get_schema -logger = logging.getLogger(__name__) +logger = get_logger() class SoledadConfig(ServiceConfig): -- cgit v1.2.3 From 82f21a9fa05dc204be1f4c2b23d67f83acbe07ce Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 30 Jun 2015 00:15:23 -0400 Subject: [style] fix typo s/self/sync --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index 242bfb3d..1825d317 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -615,7 +615,7 @@ class Syncer(object): return self._callback_deferred def _try_sync(self): - logger.debug("BOOTSTRAPPER: trying to self Soledad....") + logger.debug("BOOTSTRAPPER: trying to sync Soledad....") # pass defer_decryption=False to get inline decryption # for debugging. self._sync_deferred = self._soledad.sync(defer_decryption=True) @@ -632,7 +632,7 @@ class Syncer(object): def _error(self, failure): self._timeout_delayed_call.cancel() if failure.check(InvalidAuthTokenError): - logger.error('Invalid auth token while trying to self Soledad') + logger.error('Invalid auth token while trying to sync Soledad') self._signaler.signal( self._signaler.soledad_invalid_auth_token) self._callback_deferred.fail(failure) -- cgit v1.2.3 From f5e150a4fe87b60316d278de6b4ead08357f2dba Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 5 Aug 2015 18:57:36 -0700 Subject: [feat] add path to gpg binary in the bundle --- src/leap/bitmask/services/soledad/soledadbootstrapper.py | 6 +++++- 1 file changed, 5 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 1825d317..57ae3849 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -37,7 +37,8 @@ from leap.bitmask.services.abstractbootstrapper import AbstractBootstrapper from leap.bitmask.services.soledad.soledadconfig import SoledadConfig from leap.bitmask.util import first, is_file, is_empty_file, make_address from leap.bitmask.util import get_path_prefix -from leap.bitmask.platform_init import IS_WIN +from leap.bitmask.util import here +from leap.bitmask.platform_init import IS_WIN, IS_MAC from leap.common.check import leap_assert, leap_assert_type, leap_check from leap.common.files import which from leap.keymanager import KeyManager, openpgp @@ -439,6 +440,9 @@ class SoledadBootstrapper(AbstractBootstrapper): except IndexError as e: logger.debug("Couldn't find the gpg binary!") logger.exception(e) + if IS_MAC: + gpgbin = os.path.abspath( + os.path.join(here(), "apps", "mail", "gpg")) leap_check(gpgbin is not None, "Could not find gpg binary") return gpgbin -- cgit v1.2.3 From 109af6218886ac4cdaf0d915675b1e912c68341e Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Wed, 5 Aug 2015 18:59:52 -0700 Subject: [bug] schedule signal emitting in reactor thread --- src/leap/bitmask/services/abstractbootstrapper.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/services') diff --git a/src/leap/bitmask/services/abstractbootstrapper.py b/src/leap/bitmask/services/abstractbootstrapper.py index 6a08f475..191309ba 100644 --- a/src/leap/bitmask/services/abstractbootstrapper.py +++ b/src/leap/bitmask/services/abstractbootstrapper.py @@ -25,7 +25,7 @@ from functools import partial from PySide import QtCore from twisted.python import log -from twisted.internet import threads +from twisted.internet import threads, reactor from twisted.internet.defer import CancelledError from leap.bitmask.logs.utils import get_logger @@ -155,7 +155,8 @@ class AbstractBootstrapper(QtCore.QObject): data = {self.PASSED_KEY: True, self.ERROR_KEY: ""} if isinstance(signal, basestring): if self._signaler is not None: - self._signaler.signal(signal, data) + reactor.callFromThread( + self._signaler.signal, signal, data) else: logger.warning("Tried to notify but no signaler found") else: -- cgit v1.2.3 From 182dd2738f077079a47d3f56033b78dac9204986 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 23 Jul 2015 18:45:08 -0300 Subject: [bug] handle eip-config not providing locations Is valid for a provider not to provide locations for their gateways. - Resolves: #7281 --- src/leap/bitmask/services/eip/eipconfig.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (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 b1d08393..43328af9 100644 --- a/src/leap/bitmask/services/eip/eipconfig.py +++ b/src/leap/bitmask/services/eip/eipconfig.py @@ -161,12 +161,17 @@ class VPNGatewaySelector(object): def get_gateways_country_code(self): """ Return a dict with ipaddress -> country code mapping. + Return None if there are no locations specified. - :rtype: dict + :rtype: dict or None """ country_codes = {} locations = self._eipconfig.get_locations() + + if not locations: + return + gateways = self._eipconfig.get_gateways() for idx, gateway in enumerate(gateways): -- cgit v1.2.3