summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/feature_granular_login2
-rw-r--r--changes/feature_saveprovider2
-rw-r--r--src/leap/config/leapsettings.py19
-rw-r--r--src/leap/crypto/srpauth.py73
-rw-r--r--src/leap/gui/mainwindow.py23
5 files changed, 86 insertions, 33 deletions
diff --git a/changes/feature_granular_login b/changes/feature_granular_login
new file mode 100644
index 00000000..8cef2c5e
--- /dev/null
+++ b/changes/feature_granular_login
@@ -0,0 +1,2 @@
+ o Make the login steps be a chain of defers in order to be able to
+ have more cancel points for the whole procedure. Closes #2571 \ No newline at end of file
diff --git a/changes/feature_saveprovider b/changes/feature_saveprovider
new file mode 100644
index 00000000..98c911c2
--- /dev/null
+++ b/changes/feature_saveprovider
@@ -0,0 +1,2 @@
+ o Save the default provider to be used for autostart EIP as
+ DefaultProvider in leap.conf. Closes #2793 \ No newline at end of file
diff --git a/src/leap/config/leapsettings.py b/src/leap/config/leapsettings.py
index 59a0a16d..006be851 100644
--- a/src/leap/config/leapsettings.py
+++ b/src/leap/config/leapsettings.py
@@ -65,6 +65,7 @@ class LeapSettings(object):
AUTOLOGIN_KEY = "AutoLogin"
PROPERPROVIDER_KEY = "ProperProvider"
REMEMBER_KEY = "RememberUserAndPass"
+ DEFAULTPROVIDER_KEY = "DefaultProvider"
def __init__(self, standalone=False):
"""
@@ -230,3 +231,21 @@ class LeapSettings(object):
"""
leap_assert_type(properprovider, bool)
self._settings.setValue(self.PROPERPROVIDER_KEY, properprovider)
+
+ def get_defaultprovider(self):
+ """
+ Returns the default provider to be used for autostarting EIP
+
+ :rtype: str or None
+ """
+ return self._settings.value(self.DEFAULTPROVIDER_KEY, None)
+
+ def set_defaultprovider(self, provider):
+ """
+ Sets the default provider to be used for autostarting EIP
+
+ :param provider: provider to use
+ :type provider: str
+ """
+ leap_assert(len(provider) > 0, "We cannot save an empty provider")
+ self._settings.setValue(self.DEFAULTPROVIDER_KEY, provider)
diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py
index 82525d7f..52267b3b 100644
--- a/src/leap/crypto/srpauth.py
+++ b/src/leap/crypto/srpauth.py
@@ -25,10 +25,10 @@ import json
#this error is raised from requests
from simplejson.decoder import JSONDecodeError
-from PySide import QtCore, QtGui
+from PySide import QtCore
+from twisted.internet import threads
from leap.common.check import leap_assert
-from leap.config.providerconfig import ProviderConfig
from leap.util.request_helpers import get_content
from leap.common.events import signal as events_signal
from leap.common.events import events_pb2 as proto
@@ -124,13 +124,15 @@ class SRPAuth(QtCore.QObject):
self._srp_a = A
- def _start_authentication(self, username, password):
+ def _start_authentication(self, _, username, password):
"""
Sends the first request for authentication to retrieve the
salt and B parameter
Might raise SRPAuthenticationError
+ :param _: IGNORED, output from the previous callback (None)
+ :type _: IGNORED
:param username: username to login
:type username: str
:param password: password for the username
@@ -187,17 +189,15 @@ class SRPAuth(QtCore.QObject):
return salt, B
- def _process_challenge(self, salt, B, username):
+ def _process_challenge(self, salt_B, username):
"""
Given the salt and B processes the auth challenge and
generates the M2 parameter
Might throw SRPAuthenticationError
- :param salt: salt for the username
- :type salt: str
- :param B: B SRP parameter
- :type B: str
+ :param salt_B: salt and B parameters for the username
+ :type salt_B: tuple
:param username: username for this session
:type username: str
@@ -206,6 +206,7 @@ class SRPAuth(QtCore.QObject):
"""
logger.debug("Processing challenge...")
try:
+ salt, B = salt_B
unhex_salt = self._safe_unhexlify(salt)
unhex_B = self._safe_unhexlify(B)
except TypeError as e:
@@ -323,17 +324,22 @@ class SRPAuth(QtCore.QObject):
:type username: str
:param password: password for this user
:type password: str
+
+ :returns: A defer on a different thread
+ :rtype: twisted.internet.defer.Deferred
"""
leap_assert(self.get_session_id() is None, "Already logged in")
- self._authentication_preprocessing(username, password)
- salt, B = self._start_authentication(username, password)
- M2 = self._process_challenge(salt, B, username)
+ d = threads.deferToThread(self._authentication_preprocessing,
+ username=username,
+ password=password)
- self._verify_session(M2)
+ d.addCallback(self._start_authentication, username=username,
+ password=password)
+ d.addCallback(self._process_challenge, username=username)
+ d.addCallback(self._verify_session)
- leap_assert(self.get_session_id(), "Something went wrong because"
- " we don't have the auth cookie afterwards")
+ return d
def logout(self):
"""
@@ -393,10 +399,6 @@ class SRPAuth(QtCore.QObject):
authentication_finished = QtCore.Signal(bool, str)
logout_finished = QtCore.Signal(bool, str)
- DO_NOTHING = 0
- DO_LOGIN = 1
- DO_LOGOUT = 2
-
def __init__(self, provider_config):
"""
Creates a singleton instance if needed
@@ -411,8 +413,6 @@ class SRPAuth(QtCore.QObject):
# Store instance reference as the only member in the handle
self.__dict__['_SRPAuth__instance'] = SRPAuth.__instance
- self._should_login = self.DO_NOTHING
- self._should_login_lock = QtCore.QMutex()
self._username = None
self._password = None
@@ -428,16 +428,31 @@ class SRPAuth(QtCore.QObject):
:type password: str
"""
- try:
- self.__instance.authenticate(username, password)
+ d = self.__instance.authenticate(username, password)
+ d.addCallback(self._gui_notify)
+ d.addErrback(self._errback)
+ return d
- logger.debug("Successful login!")
- self.authentication_finished.emit(True, self.tr("Succeeded"))
- return True
- except Exception as e:
- logger.error("Error logging in %s" % (e,))
- self.authentication_finished.emit(False, "%s" % (e,))
- return False
+ def _gui_notify(self, _):
+ """
+ Callback that notifies the UI with the proper signal.
+
+ :param _: IGNORED, output from the previous callback (None)
+ :type _: IGNORED
+ """
+ logger.debug("Successful login!")
+ self.authentication_finished.emit(True, self.tr("Succeeded"))
+
+ def _errback(self, failure):
+ """
+ General errback for the whole login process. Will notify the
+ UI with the proper signal.
+
+ :param failure: Failure object captured from a callback.
+ :type failure: twisted.python.failure.Failure
+ """
+ logger.error("Error logging in %s" % (failure,))
+ self.authentication_finished.emit(False, "%s" % (failure,))
def get_session_id(self):
return self.__instance.get_session_id()
diff --git a/src/leap/gui/mainwindow.py b/src/leap/gui/mainwindow.py
index fa49c55d..ea5bca1a 100644
--- a/src/leap/gui/mainwindow.py
+++ b/src/leap/gui/mainwindow.py
@@ -258,6 +258,8 @@ class MainWindow(QtGui.QMainWindow):
self._soledad = None
self._keymanager = None
+ self._login_defer = None
+
self._smtp_config = SMTPConfig()
if self._first_run():
@@ -725,10 +727,7 @@ class MainWindow(QtGui.QMainWindow):
self._srp_auth.logout_finished.connect(
self._done_logging_out)
- auth_partial = partial(self._srp_auth.authenticate,
- username,
- password)
- threads.deferToThread(auth_partial)
+ self._login_defer = self._srp_auth.authenticate(username, password)
else:
self._set_status(data[self._provider_bootstrapper.ERROR_KEY])
self._login_set_enabled(True)
@@ -748,6 +747,7 @@ class MainWindow(QtGui.QMainWindow):
# "Succeeded" message and then we switch to the EIP status
# panel
QtCore.QTimer.singleShot(1000, self._switch_to_status)
+ self._login_defer = None
else:
self._login_set_enabled(True)
@@ -880,12 +880,24 @@ class MainWindow(QtGui.QMainWindow):
return host, port
def _start_eip(self):
+ """
+ SLOT
+ TRIGGERS:
+ self.ui.btnEipStartStop.clicked
+ self._action_eip_startstop.triggered
+ or called from _finish_eip_bootstrap
+
+ Starts EIP
+ """
try:
host, port = self._get_socket_host()
self._vpn.start(eipconfig=self._eip_config,
providerconfig=self._provider_config,
socket_host=host,
socket_port=port)
+
+ self._settings.set_defaultprovider(
+ self._provider_config.get_domain())
self.ui.btnEipStartStop.setText(self.tr("Turn Encryption OFF"))
self.ui.btnEipStartStop.disconnect(self)
self.ui.btnEipStartStop.clicked.connect(
@@ -1162,6 +1174,9 @@ class MainWindow(QtGui.QMainWindow):
self.close()
+ if self._login_defer:
+ self._login_defer.cancel()
+
if self._quit_callback:
self._quit_callback()
logger.debug('Bye.')