summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/services
diff options
context:
space:
mode:
authorTomás Touceda <chiiph@leap.se>2013-11-01 10:50:38 -0300
committerTomás Touceda <chiiph@leap.se>2013-11-01 10:50:38 -0300
commit23e9034664edf6b2a01a677c4fa4e6efd880e364 (patch)
treefc90f154cf81cbaf48dd2d4a738a379591c4e7c7 /src/leap/bitmask/services
parenta06b5719f028e619a4b3800fb346ed3c984e4d25 (diff)
parent80fde752f0bf7946869361f6a77d1952f9339636 (diff)
Merge branch 'release-0.3.6'
Diffstat (limited to 'src/leap/bitmask/services')
-rw-r--r--src/leap/bitmask/services/__init__.py7
-rw-r--r--src/leap/bitmask/services/connections.py10
-rw-r--r--src/leap/bitmask/services/eip/connection.py2
-rw-r--r--src/leap/bitmask/services/eip/darwinvpnlauncher.py5
-rw-r--r--src/leap/bitmask/services/eip/linuxvpnlauncher.py5
-rw-r--r--src/leap/bitmask/services/eip/vpnlauncher.py3
-rw-r--r--src/leap/bitmask/services/eip/vpnprocess.py18
-rw-r--r--src/leap/bitmask/services/mail/conductor.py384
-rw-r--r--src/leap/bitmask/services/mail/connection.py103
-rw-r--r--src/leap/bitmask/services/mail/imap.py7
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py28
11 files changed, 539 insertions, 33 deletions
diff --git a/src/leap/bitmask/services/__init__.py b/src/leap/bitmask/services/__init__.py
index f9456159..e62277b6 100644
--- a/src/leap/bitmask/services/__init__.py
+++ b/src/leap/bitmask/services/__init__.py
@@ -19,6 +19,7 @@ Services module.
"""
import logging
import os
+import sys
from PySide import QtCore
@@ -135,8 +136,12 @@ def download_service_config(provider_config, service_config,
if token is not None:
headers["Authorization"] = 'Token token="{0}"'.format(token)
+ verify = provider_config.get_ca_cert_path()
+ if verify:
+ verify = verify.encode(sys.getfilesystemencoding())
+
res = session.get(config_uri,
- verify=provider_config.get_ca_cert_path(),
+ verify=verify,
headers=headers,
timeout=REQUEST_TIMEOUT,
cookies=cookies)
diff --git a/src/leap/bitmask/services/connections.py b/src/leap/bitmask/services/connections.py
index 8aeb4e0c..ecfd35ff 100644
--- a/src/leap/bitmask/services/connections.py
+++ b/src/leap/bitmask/services/connections.py
@@ -41,9 +41,6 @@ The different services should declare a ServiceConnection class that
inherits from AbstractLEAPConnection, so an instance of such class
can be used to inform the StateMachineBuilder of the particularities
of the state transitions for each particular connection.
-
-In the future, we will extend this class to allow composites in connections,
-so we can apply conditional logic to the transitions.
"""
@@ -79,12 +76,7 @@ class AbstractLEAPConnection(object):
"""
return self._qtsigs
- # XXX for conditional transitions with composites,
- # we might want to add
- # a field with dependencies: what this connection
- # needs for (ON) state.
- # XXX Look also at child states in the state machine.
- #depends = ()
+ components = None
# Signals that derived classes
# have to implement.
diff --git a/src/leap/bitmask/services/eip/connection.py b/src/leap/bitmask/services/eip/connection.py
index 962d9cf2..8a35d550 100644
--- a/src/leap/bitmask/services/eip/connection.py
+++ b/src/leap/bitmask/services/eip/connection.py
@@ -46,5 +46,5 @@ class EIPConnectionSignals(QtCore.QObject):
class EIPConnection(AbstractLEAPConnection):
def __init__(self):
- # XXX this should be public instead
self._qtsigs = EIPConnectionSignals()
+ self._connection_name = "Encrypted Internet"
diff --git a/src/leap/bitmask/services/eip/darwinvpnlauncher.py b/src/leap/bitmask/services/eip/darwinvpnlauncher.py
index f3b6bfc8..fe3fe4c1 100644
--- a/src/leap/bitmask/services/eip/darwinvpnlauncher.py
+++ b/src/leap/bitmask/services/eip/darwinvpnlauncher.py
@@ -21,6 +21,7 @@ import commands
import getpass
import logging
import os
+import sys
from leap.bitmask.services.eip.vpnlauncher import VPNLauncher
from leap.bitmask.services.eip.vpnlauncher import VPNLauncherException
@@ -185,6 +186,8 @@ class DarwinVPNLauncher(VPNLauncher):
:rtype: dict
"""
+ ld_library_path = os.path.join(get_path_prefix(), "..", "lib")
+ ld_library_path.encode(sys.getfilesystemencoding())
return {
- "DYLD_LIBRARY_PATH": os.path.join(get_path_prefix(), "..", "lib")
+ "DYLD_LIBRARY_PATH": ld_library_path
}
diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
index efb23285..d02f6f96 100644
--- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py
+++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py
@@ -21,6 +21,7 @@ import commands
import logging
import os
import subprocess
+import sys
import time
from leap.bitmask.config import flags
@@ -231,6 +232,8 @@ class LinuxVPNLauncher(VPNLauncher):
:rtype: dict
"""
+ ld_library_path = os.path.join(get_path_prefix(), "..", "lib")
+ ld_library_path.encode(sys.getfilesystemencoding())
return {
- "LD_LIBRARY_PATH": os.path.join(get_path_prefix(), "..", "lib")
+ "LD_LIBRARY_PATH": ld_library_path
}
diff --git a/src/leap/bitmask/services/eip/vpnlauncher.py b/src/leap/bitmask/services/eip/vpnlauncher.py
index bce3599b..07497814 100644
--- a/src/leap/bitmask/services/eip/vpnlauncher.py
+++ b/src/leap/bitmask/services/eip/vpnlauncher.py
@@ -250,9 +250,6 @@ class VPNLauncher(object):
'--ping-restart', '30']
command_and_args = [openvpn] + args
- logger.debug("Running VPN with command:")
- logger.debug(" ".join(command_and_args))
-
return command_and_args
@classmethod
diff --git a/src/leap/bitmask/services/eip/vpnprocess.py b/src/leap/bitmask/services/eip/vpnprocess.py
index 19e1aa7b..51f0f738 100644
--- a/src/leap/bitmask/services/eip/vpnprocess.py
+++ b/src/leap/bitmask/services/eip/vpnprocess.py
@@ -23,6 +23,7 @@ import psutil
import psutil.error
import shutil
import socket
+import sys
from itertools import chain, repeat
@@ -864,15 +865,26 @@ class VPNProcess(protocol.ProcessProtocol, VPNManager):
"""
Gets the vpn command from the aproppriate launcher.
- Might throw: VPNLauncherException, OpenVPNNotFoundException.
+ Might throw:
+ VPNLauncherException,
+ OpenVPNNotFoundException.
+
+ :rtype: list of str
"""
- cmd = self._launcher.get_vpn_command(
+ command = self._launcher.get_vpn_command(
eipconfig=self._eipconfig,
providerconfig=self._providerconfig,
socket_host=self._socket_host,
socket_port=self._socket_port,
openvpn_verb=self._openvpn_verb)
- return map(str, cmd)
+
+ encoding = sys.getfilesystemencoding()
+ for i, c in enumerate(command):
+ if not isinstance(c, str):
+ command[i] = c.encode(encoding)
+
+ logger.debug("Running VPN with command: {0}".format(command))
+ return command
# shutdown
diff --git a/src/leap/bitmask/services/mail/conductor.py b/src/leap/bitmask/services/mail/conductor.py
new file mode 100644
index 00000000..c294381b
--- /dev/null
+++ b/src/leap/bitmask/services/mail/conductor.py
@@ -0,0 +1,384 @@
+# -*- coding: utf-8 -*-
+# conductor.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Mail Services Conductor
+"""
+import logging
+import os
+
+from PySide import QtCore
+from zope.proxy import sameProxiedObjects
+
+from leap.bitmask.gui import statemachines
+from leap.bitmask.services.mail import imap
+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.util import is_file
+
+from leap.common.check import leap_assert
+
+from leap.common.events import register as leap_register
+from leap.common.events import events_pb2 as leap_events
+
+logger = logging.getLogger(__name__)
+
+
+class IMAPControl(object):
+ """
+ Methods related to IMAP control.
+ """
+ def __init__(self):
+ """
+ Initializes smtp variables.
+ """
+ self.imap_machine = None
+ self.imap_service = None
+ self.imap_port = None
+ self.imap_factory = 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)
+
+ def set_imap_connection(self, imap_connection):
+ """
+ Sets the imap connection to an initialized connection.
+
+ :param imap_connection: an initialized imap connection
+ :type imap_connection: IMAPConnection instance.
+ """
+ self.imap_connection = imap_connection
+
+ def start_imap_service(self):
+ """
+ Starts imap service.
+ """
+ logger.debug('Starting imap service')
+ leap_assert(sameProxiedObjects(self._soledad, None)
+ is not True,
+ "We need a non-null soledad for initializing imap service")
+ leap_assert(sameProxiedObjects(self._keymanager, None)
+ is not True,
+ "We need a non-null keymanager for initializing imap "
+ "service")
+
+ if self.imap_service is None:
+ # first time.
+ self.imap_service, \
+ self.imap_port, \
+ self.imap_factory = imap.start_imap_service(
+ self._soledad,
+ self._keymanager)
+ else:
+ # we have the fetcher. just start it.
+ self.imap_service.start_loop()
+
+ def stop_imap_service(self):
+ """
+ Stops imap service (fetcher, factory and port).
+ """
+ self.imap_connection.qtsigs.disconnecting_signal.emit()
+ # TODO We should homogenize both services.
+ if self.imap_service is not None:
+ logger.debug('Stopping imap service.')
+ # Stop the loop call in the fetcher
+ self.imap_service.stop()
+ # Stop listening on the IMAP port
+ self.imap_port.stopListening()
+ # Stop the protocol
+ self.imap_factory.doStop()
+
+ def fetch_incoming_mail(self):
+ """
+ Fetches incoming mail.
+ """
+ # TODO have a mutex over fetch operation.
+ if self.imap_service:
+ logger.debug('Client connected, fetching mail...')
+ self.imap_service.fetch()
+
+ # handle events
+
+ def _handle_imap_events(self, req):
+ """
+ Callback handler for the IMAP events
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ if req.event == leap_events.IMAP_SERVICE_STARTED:
+ self.on_imap_connected()
+ elif req.event == leap_events.IMAP_SERVICE_FAILED_TO_START:
+ self.on_imap_failed()
+
+ # emit connection signals
+
+ def on_imap_connecting(self):
+ """
+ Callback for IMAP connecting state.
+ """
+ self.imap_connection.qtsigs.connecting_signal.emit()
+
+ def on_imap_connected(self):
+ """
+ Callback for IMAP connected state.
+ """
+ self.imap_connection.qtsigs.connected_signal.emit()
+
+ def on_imap_failed(self):
+ """
+ Callback for IMAP failed state.
+ """
+ self.imap_connection.qtsigs.connetion_aborted_signal.emit()
+
+
+class SMTPControl(object):
+
+ PORT_KEY = "port"
+ IP_KEY = "ip_address"
+
+ def __init__(self):
+ """
+ Initializes smtp variables.
+ """
+ self.smtp_config = SMTPConfig()
+ self.smtp_connection = None
+ self.smtp_machine = None
+ self._smtp_service = None
+ self._smtp_port = None
+
+ self.smtp_bootstrapper = SMTPBootstrapper()
+ self.smtp_bootstrapper.download_config.connect(
+ self.smtp_bootstrapped_stage)
+
+ 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)
+
+ def set_smtp_connection(self, smtp_connection):
+ """
+ Sets the smtp connection to an initialized connection.
+ :param smtp_connection: an initialized smtp connection
+ :type smtp_connection: SMTPConnection instance.
+ """
+ self.smtp_connection = smtp_connection
+
+ def start_smtp_service(self, host, port, cert):
+ """
+ Starts the smtp service.
+
+ :param host: the hostname of the remove SMTP server.
+ :type host: str
+ :param port: the port of the remote SMTP server
+ :type port: str
+ :param cert: the client certificate for authentication
+ :type cert: str
+ """
+ # TODO Make the encrypted_only configurable
+ # TODO pick local smtp port in a better way
+ # TODO remove hard-coded port and let leap.mail set
+ # the specific default.
+ self.smtp_connection.qtsigs.connecting_signal.emit()
+ from leap.mail.smtp import setup_smtp_relay
+ self._smtp_service, self._smtp_port = setup_smtp_relay(
+ port=2013,
+ keymanager=self._keymanager,
+ smtp_host=host,
+ smtp_port=port,
+ smtp_cert=cert,
+ smtp_key=cert,
+ encrypted_only=False)
+
+ def stop_smtp_service(self):
+ """
+ Stops the smtp service (port and factory).
+ """
+ self.smtp_connection.qtsigs.disconnecting_signal.emit()
+ # TODO We should homogenize both services.
+ if self._smtp_service is not None:
+ logger.debug('Stopping smtp service.')
+ self._smtp_port.stopListening()
+ self._smtp_service.doStop()
+
+ @QtCore.Slot()
+ def smtp_bootstrapped_stage(self, data):
+ """
+ SLOT
+ TRIGGERS:
+ self.smtp_bootstrapper.download_config
+
+ If there was a problem, displays it, otherwise it does nothing.
+ This is used for intermediate bootstrapping stages, in case
+ they fail.
+
+ :param data: result from the bootstrapping stage for Soledad
+ :type data: dict
+ """
+ passed = data[self.smtp_bootstrapper.PASSED_KEY]
+ if not passed:
+ logger.error(data[self.smtp_bootstrapper.ERROR_KEY])
+ return
+ logger.debug("Done bootstrapping SMTP")
+ self.check_smtp_config()
+
+ def check_smtp_config(self):
+ """
+ Checks smtp config and tries to download smtp client cert if needed.
+ Currently called when smtp_bootstrapped_stage has successfuly finished.
+ """
+ logger.debug("Checking SMTP config...")
+ leap_assert(self.smtp_bootstrapper._provider_config,
+ "smtp bootstrapper does not have a provider_config")
+
+ provider_config = self.smtp_bootstrapper._provider_config
+ smtp_config = self.smtp_config
+ hosts = smtp_config.get_hosts()
+ # TODO handle more than one host and define how to choose
+ if len(hosts) > 0:
+ hostname = hosts.keys()[0]
+ logger.debug("Using hostname %s for SMTP" % (hostname,))
+ host = hosts[hostname][self.IP_KEY].encode("utf-8")
+ port = hosts[hostname][self.PORT_KEY]
+
+ client_cert = smtp_config.get_client_cert_path(
+ provider_config,
+ about_to_download=True)
+
+ # XXX change this logic!
+ # check_config should be called from within start_service,
+ # and not the other way around.
+ if not is_file(client_cert):
+ self.smtp_bootstrapper._download_client_certificates()
+ if os.path.isfile(client_cert):
+ self.start_smtp_service(host, port, client_cert)
+ else:
+ logger.warning("Tried to download email client "
+ "certificate, but could not find any")
+
+ else:
+ logger.warning("No smtp hosts configured")
+
+ # handle smtp events
+
+ def _handle_smtp_events(self, req):
+ """
+ Callback handler for the SMTP events.
+
+ :param req: Request type
+ :type req: leap.common.events.events_pb2.SignalRequest
+ """
+ if req.event == leap_events.SMTP_SERVICE_STARTED:
+ self.on_smtp_connected()
+ 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.
+ """
+ self.smtp_connection.qtsigs.connecting_signal.emit()
+
+ def on_smtp_connected(self):
+ """
+ Callback for SMTP connected state.
+ """
+ self.smtp_connection.qtsigs.connected_signal.emit()
+
+ def on_smtp_failed(self):
+ """
+ Callback for SMTP failed state.
+ """
+ self.smtp_connection.qtsigs.connection_aborted_signal.emit()
+
+
+class MailConductor(IMAPControl, SMTPControl):
+ """
+ This class encapsulates everything related to the initialization and
+ process control for the mail services.
+ Currently, it initializes IMAPConnection and SMPTConnection.
+ """
+ # XXX We could consider to use composition instead of inheritance here.
+
+ def __init__(self, soledad, keymanager):
+ """
+ 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 soledad: zope.proxy.ProxyBase
+ """
+ IMAPControl.__init__(self)
+ SMTPControl.__init__(self)
+ self._soledad = soledad
+ self._keymanager = keymanager
+
+ self._mail_machine = None
+
+ self._mail_connection = mail_connection.MailConnection()
+
+ def start_mail_machine(self, **kwargs):
+ """
+ Starts mail machine.
+ """
+ logger.debug("Starting mail state machine...")
+ builder = statemachines.ConnectionMachineBuilder(self._mail_connection)
+ (mail, (imap, smtp)) = builder.make_machine(**kwargs)
+
+ # we have instantiated the connections while building the composite
+ # machines, and we have to use the qtsigs instantiated there.
+ # XXX we could probably use a proxy here too to make the thing
+ # transparent.
+ self.set_imap_connection(imap.conn)
+ self.set_smtp_connection(smtp.conn)
+
+ self._mail_machine = mail
+ # XXX -------------------
+ # need to keep a reference?
+ #self._mail_events = mail.events
+ self._mail_machine.start()
+
+ self._imap_machine = imap
+ self._imap_machine.start()
+ self._smtp_machine = smtp
+ self._smtp_machine.start()
+
+ def connect_mail_signals(self, widget):
+ """
+ Connects the mail signals to the mail_status widget slots.
+
+ :param widget: the widget containing the slots.
+ :type widget: QtCore.QWidget
+ """
+ qtsigs = self._mail_connection.qtsigs
+ qtsigs.connected_signal.connect(widget.mail_state_connected)
+ qtsigs.connecting_signal.connect(widget.mail_state_connecting)
+ qtsigs.disconnecting_signal.connect(widget.mail_state_disconnecting)
+ qtsigs.disconnected_signal.connect(widget.mail_state_disconnected)
diff --git a/src/leap/bitmask/services/mail/connection.py b/src/leap/bitmask/services/mail/connection.py
new file mode 100644
index 00000000..29378f62
--- /dev/null
+++ b/src/leap/bitmask/services/mail/connection.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+# connection.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Email Connections
+"""
+from PySide import QtCore
+
+from leap.bitmask.services.connections import AbstractLEAPConnection
+
+
+class IMAPConnectionSignals(QtCore.QObject):
+ """
+ Qt Signals used by IMAPConnection
+ """
+ # commands
+ do_connect_signal = QtCore.Signal()
+ do_disconnect_signal = QtCore.Signal()
+
+ # intermediate stages
+ connecting_signal = QtCore.Signal()
+ disconnecting_signal = QtCore.Signal()
+
+ connected_signal = QtCore.Signal()
+ disconnected_signal = QtCore.Signal()
+
+ connection_died_signal = QtCore.Signal()
+ connection_aborted_signal = QtCore.Signal()
+
+
+class IMAPConnection(AbstractLEAPConnection):
+
+ _connection_name = "IMAP"
+
+ def __init__(self):
+ self._qtsigs = IMAPConnectionSignals()
+
+
+class SMTPConnectionSignals(QtCore.QObject):
+ """
+ Qt Signals used by SMTPConnection
+ """
+ # commands
+ do_connect_signal = QtCore.Signal()
+ do_disconnect_signal = QtCore.Signal()
+
+ # intermediate stages
+ connecting_signal = QtCore.Signal()
+ disconnecting_signal = QtCore.Signal()
+
+ connected_signal = QtCore.Signal()
+ disconnected_signal = QtCore.Signal()
+
+ connection_died_signal = QtCore.Signal()
+ connection_aborted_signal = QtCore.Signal()
+
+
+class SMTPConnection(AbstractLEAPConnection):
+
+ _connection_name = "IMAP"
+
+ def __init__(self):
+ self._qtsigs = SMTPConnectionSignals()
+
+
+class MailConnectionSignals(QtCore.QObject):
+ """
+ Qt Signals used by MailConnection
+ """
+ # commands
+ do_connect_signal = QtCore.Signal()
+ do_disconnect_signal = QtCore.Signal()
+
+ connecting_signal = QtCore.Signal()
+ disconnecting_signal = QtCore.Signal()
+
+ connected_signal = QtCore.Signal()
+ disconnected_signal = QtCore.Signal()
+
+ connection_died_signal = QtCore.Signal()
+ connection_aborted_signal = QtCore.Signal()
+
+
+class MailConnection(AbstractLEAPConnection):
+
+ components = IMAPConnection, SMTPConnection
+ _connection_name = "Mail"
+
+ def __init__(self):
+ self._qtsigs = MailConnectionSignals()
diff --git a/src/leap/bitmask/services/mail/imap.py b/src/leap/bitmask/services/mail/imap.py
index 4828180e..2667f156 100644
--- a/src/leap/bitmask/services/mail/imap.py
+++ b/src/leap/bitmask/services/mail/imap.py
@@ -41,9 +41,10 @@ def get_mail_check_period():
try:
period = int(period_str)
except (ValueError, TypeError):
- logger.warning("BAD value found for %s: %s" % (
- INCOMING_CHECK_PERIOD_ENV,
- period_str))
+ if period is not None:
+ logger.warning("BAD value found for %s: %s" % (
+ INCOMING_CHECK_PERIOD_ENV,
+ period_str))
except Exception as exc:
logger.warning("Unhandled error while getting %s: %r" % (
INCOMING_CHECK_PERIOD_ENV,
diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
index 4619ba80..54ef67eb 100644
--- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py
+++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py
@@ -20,11 +20,13 @@ Soledad bootstrapping
import logging
import os
import socket
+import sys
from ssl import SSLError
from PySide import QtCore
from u1db import errors as u1db_errors
+from zope.proxy import sameProxiedObjects
from leap.bitmask.config import flags
from leap.bitmask.config.providerconfig import ProviderConfig
@@ -39,7 +41,7 @@ from leap.common.check import leap_assert, leap_assert_type, leap_check
from leap.common.files import which
from leap.keymanager import KeyManager, openpgp
from leap.keymanager.errors import KeyNotFound
-from leap.soledad.client import Soledad
+from leap.soledad.client import Soledad, BootstrapSequenceError
logger = logging.getLogger(__name__)
@@ -190,8 +192,8 @@ class SoledadBootstrapper(AbstractBootstrapper):
# soledad-launcher in the gui.
raise
- leap_check(self._soledad is not None,
- "Null soledad, error while initializing")
+ leap_assert(not sameProxiedObjects(self._soledad, None),
+ "Null soledad, error while initializing")
# and now, let's sync
sync_tries = self.MAX_SYNC_RETRIES
@@ -239,14 +241,15 @@ class SoledadBootstrapper(AbstractBootstrapper):
"""
# TODO: If selected server fails, retry with another host
# (issue #3309)
+ encoding = sys.getfilesystemencoding()
try:
self._soledad = Soledad(
uuid,
- self._password.encode("utf-8"),
- secrets_path=secrets_path,
- local_db_path=local_db_path,
+ self._password,
+ secrets_path=secrets_path.encode(encoding),
+ local_db_path=local_db_path.encode(encoding),
server_url=server_url,
- cert_file=cert_file,
+ cert_file=cert_file.encode(encoding),
auth_token=auth_token)
# XXX All these errors should be handled by soledad itself,
@@ -257,7 +260,10 @@ class SoledadBootstrapper(AbstractBootstrapper):
logger.debug("SOLEDAD initialization TIMED OUT...")
self.soledad_timeout.emit()
except socket.error as exc:
- logger.error("Socket error while initializing soledad")
+ logger.warning("Socket error while initializing soledad")
+ self.soledad_timeout.emit()
+ except BootstrapSequenceError as exc:
+ logger.warning("Error while initializing soledad")
self.soledad_timeout.emit()
# unrecoverable
@@ -280,7 +286,7 @@ class SoledadBootstrapper(AbstractBootstrapper):
Raises SoledadSyncError if not successful.
"""
try:
- logger.error("trying to sync soledad....")
+ logger.debug("trying to sync soledad....")
self._soledad.sync()
except SSLError as exc:
logger.error("%r" % (exc,))
@@ -412,9 +418,9 @@ class SoledadBootstrapper(AbstractBootstrapper):
:param provider_config: Provider configuration
:type provider_config: ProviderConfig
:param user: User's login
- :type user: str
+ :type user: unicode
:param password: User's password
- :type password: str
+ :type password: unicode
:param download_if_needed: If True, it will only download
files if the have changed since the
time it was previously downloaded.