From 97554d4c413dd60be4ed67c9553cb0976ce420b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 6 Mar 2013 15:37:07 -0300 Subject: Add SRP related code: authentication and registration --- src/leap/crypto/srpauth.py | 439 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 src/leap/crypto/srpauth.py (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py new file mode 100644 index 00000000..dbcc95cb --- /dev/null +++ b/src/leap/crypto/srpauth.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# srpauth.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 . + +import requests +import srp +import binascii +import logging + +from PySide import QtCore + +from leap.config.providerconfig import ProviderConfig + +logger = logging.getLogger(__name__) + + +class SRPAuthenticationError(Exception): + """ + Exception raised for authentication errors + """ + pass + + +class SRPAuth(QtCore.QThread): + """ + SRPAuth singleton + """ + + class __impl(object): + """ + Implementation of the SRPAuth interface + """ + + LOGIN_KEY = "login" + A_KEY = "A" + CLIENT_AUTH_KEY = "client_auth" + + def __init__(self, provider_config): + """ + Constructor for SRPAuth implementation + + @param server: Server to which we will authenticate + @type server: str + """ + assert provider_config, "We need a provider config to authenticate" + + self._provider_config = provider_config + + # **************************************************** # + # Dependency injection helpers, override this for more + # granular testing + self._fetcher = requests + self._srp = srp + self._hashfun = self._srp.SHA256 + self._ng = self._srp.NG_1024 + # **************************************************** # + + self._session = self._fetcher.session() + self._session_id = None + self._session_id_lock = QtCore.QMutex() + self._uid = None + self._uid_lock = QtCore.QMutex() + + self._srp_user = None + self._srp_a = None + + def _safe_unhexlify(self, val): + """ + Rounds the val to a multiple of 2 and returns the + unhexlified value + + @param val: hexlified value + @type val: str + + @rtype: binary hex data + @return: unhexlified val + """ + return binascii.unhexlify(val) \ + if (len(val) % 2 == 0) else binascii.unhexlify('0' + val) + + def _authentication_preprocessing(self, username, password): + """ + Generates the SRP.User to get the A SRP parameter + + @param username: username to login + @type username: str + @param password: password for the username + @type password: str + """ + logger.debug("Authentication preprocessing...") + self._srp_user = self._srp.User(username, + password, + self._hashfun, + self._ng) + _, A = self._srp_user.start_authentication() + + self._srp_a = A + + def _start_authentication(self, username, password): + """ + Sends the first request for authentication to retrieve the + salt and B parameter + + Might raise SRPAuthenticationError + + @param username: username to login + @type username: str + @param password: password for the username + @type password: str + + @return: salt and B parameters + @rtype: tuple + """ + logger.debug("Starting authentication process...") + try: + auth_data = { + self.LOGIN_KEY: username, + self.A_KEY: binascii.hexlify(self._srp_a) + } + sessions_url = "%s/%s/%s/" % \ + (self._provider_config.get_api_uri(), + self._provider_config.get_api_version(), + "sessions") + init_session = self._session.post(sessions_url, + data=auth_data, + verify=self._provider_config. + get_ca_cert_path()) + except requests.exceptions.ConnectionError as e: + logger.error("No connection made (salt): %r" % + (e,)) + raise SRPAuthenticationError("Could not establish a " + "connection") + except Exception as e: + logger.error("Unknown error: %r" % (e,)) + raise SRPAuthenticationError("Unknown error: %r" % + (e,)) + + if init_session.status_code not in (200,): + logger.error("No valid response (salt): " + "Status code = %r. Content: %r" % + (init_session.status_code, init_session.content)) + if init_session.status_code == 422: + raise SRPAuthenticationError("Unknown user") + salt = init_session.json().get("salt", None) + B = init_session.json().get("B", None) + + if salt is None: + logger.error("No salt parameter sent") + raise SRPAuthenticationError("The server did not send the " + + "salt parameter") + if B is None: + logger.error("No B parameter sent") + raise SRPAuthenticationError("The server did not send the " + + "B parameter") + + return salt, B + + 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 username: username for this session + @type username: str + + @return: the M2 SRP parameter + @rtype: str + """ + logger.debug("Processing challenge...") + try: + unhex_salt = self._safe_unhexlify(salt) + unhex_B = self._safe_unhexlify(B) + except TypeError as e: + logger.error("Bad data from server: %r" % (e,)) + raise SRPAuthenticationError("The data sent from the server " + "had errors") + M = self._srp_user.process_challenge(unhex_salt, unhex_B) + + auth_url = "%s/%s/%s/%s" % (self._provider_config.get_api_uri(), + self._provider_config. + get_api_version(), + "sessions", + username) + + auth_data = { + self.CLIENT_AUTH_KEY: binascii.hexlify(M) + } + + try: + auth_result = self._session.put(auth_url, + data=auth_data, + verify=self._provider_config. + get_ca_cert_path()) + except requests.exceptions.ConnectionError as e: + logger.error("No connection made (HAMK): %r" % (e,)) + raise SRPAuthenticationError("Could not connect to the server") + + if auth_result.status_code == 422: + logger.error("[%s] Wrong password (HAMK): [%s]" % + (auth_result.status_code, + auth_result.json(). + get("errors", ""))) + raise SRPAuthenticationError("Wrong password") + + if auth_result.status_code not in (200,): + logger.error("No valid response (HAMK): " + "Status code = %s. Content = %r" % + (auth_result.status_code, auth_result.content)) + raise SRPAuthenticationError("Unknown error (%s)" % + (auth_result.status_code,)) + + M2 = auth_result.json().get("M2", None) + self.set_uid(auth_result.json().get("id", None)) + + if M2 is None or self.get_uid() is None: + logger.error("Something went wrong. Content = %r" % + (auth_result.content,)) + raise SRPAuthenticationError("Problem getting data from" + " server") + + return M2 + + def _verify_session(self, M2): + """ + Verifies the session based on the M2 parameter. If the + verification succeeds, it sets the session_id for this + session + + Might throw SRPAuthenticationError + + @param M2: M2 SRP parameter + @type M2: str + """ + logger.debug("Verifying session...") + try: + unhex_M2 = self._safe_unhexlify(M2) + except TypeError: + logger.error("Bad data from server (HAWK)") + raise SRPAuthenticationError("Bad data from server") + + self._srp_user.verify_session(unhex_M2) + + if not self._srp_user.authenticated(): + logger.error("Auth verification failed") + raise SRPAuthenticationError("Auth verification failed") + logger.debug("Session verified.") + + self.set_session_id(self._session.cookies["_session_id"]) + + def authenticate(self, username, password): + """ + Executes the whole authentication process for a user + + Might raise SRPAuthenticationError + + @param username: username for this session + @type username: str + @param password: password for this user + @type password: str + """ + 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) + self._verify_session(M2) + + assert self.get_session_id(), "Something went wrong because" + \ + " we don't have the auth cookie afterwards" + + def logout(self): + """ + Logs out the current session. + Expects a session_id to exists, might raise AssertionError + """ + logger.debug("Starting logout...") + + assert self.get_session_id(), "Cannot logout an unexisting session" + + logout_url = "%s/%s/%s/" % (self._provider_config.get_api_uri(), + self._provider_config. + get_api_version(), + "sessions") + try: + self._session.delete(logout_url, + data=self.get_session_id(), + verify=self._provider_config. + get_ca_cert_path()) + except Exception as e: + logger.warning("Something went wrong with the logout: %r" % + (e,)) + + self.set_session_id(None) + self.set_uid(None) + # Also reset the session + self._session = self._fetcher.session() + logger.debug("Successfully logged out.") + + def set_session_id(self, session_id): + QtCore.QMutexLocker(self._session_id_lock) + self._session_id = session_id + + def get_session_id(self): + QtCore.QMutexLocker(self._session_id_lock) + return self._session_id + + def set_uid(self, uid): + QtCore.QMutexLocker(self._uid_lock) + self._uid = uid + + def get_uid(self): + QtCore.QMutexLocker(self._uid_lock) + return self._uid + + __instance = None + + 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 + """ + QtCore.QThread.__init__(self) + + # Check whether we already have an instance + if SRPAuth.__instance is None: + # Create and remember instance + SRPAuth.__instance = SRPAuth.__impl(provider_config) + + # 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 + + def authenticate(self, username, password): + """ + Executes the whole authentication process for a user + + Might raise SRPAuthenticationError + + @param username: username for this session + @type username: str + @param password: password for this user + @type password: str + """ + + with QtCore.QMutexLocker(self._should_login_lock): + self._should_login = self.DO_LOGIN + self._username = username + self._password = password + # Detach the start call to Qt's event loop + QtCore.QTimer.singleShot(0, self.start) + + def logout(self): + """ + Logs out the current session. + Expects a session_id to exists, might raise AssertionError + """ + QtCore.QMutexLocker(self._should_login_lock) + self._should_login = self.DO_LOGOUT + # Detach the start call to Qt's event loop + QtCore.QTimer.singleShot(0, self.start) + + def _runLogin(self, username, password): + try: + self.__instance.authenticate(username, password) + self.authentication_finished.emit(True, "Succeeded") + except Exception as e: + self.authentication_finished.emit(False, "%s" % (e,)) + + def _runLogout(self): + try: + self.__instance.logout() + self.logout_finished.emit(True, "Succeeded") + except Exception as e: + self.logout_finished.emit(False, "%s" % (e,)) + + def run(self): + QtCore.QMutexLocker(self._should_login_lock) + if self._should_login == self.DO_LOGIN: + self._runLogin(self._username, self._password) + elif self._should_login == self.DO_LOGOUT: + self._runLogout() + self._should_login = self.DO_NOTHING + + +if __name__ == "__main__": + logger = logging.getLogger(name='leap') + logger.setLevel(logging.DEBUG) + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + formatter = logging.Formatter( + '%(asctime)s ' + '- %(name)s - %(levelname)s - %(message)s') + console.setFormatter(formatter) + logger.addHandler(console) + + provider = ProviderConfig() + + if provider.load("leap/providers/bitmask.net/provider.json"): + # url = "%s/tickets" % (provider.get_api_uri(),) + # print url + # res = requests.session().get(url, verify=provider.get_ca_cert_path()) + # print res.content + # res.raise_for_status() + auth = SRPAuth(provider) + auth.start() + auth.authenticate("test2", "sarasaaaa") + res = requests.session().get("%s/cert" % (provider.get_api_uri(),), + verify=provider.get_ca_cert_path()) + print res.content + auth.logout() -- cgit v1.2.3 From 751638b4eb8208e1eaa1beaaed284da6b412bca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 7 Mar 2013 19:05:11 -0300 Subject: Change asserts for a custom leap_assert method Also: - Make SRPAuth and the Bootstrappers be a QObject instead of a QThread so we can use them inside another more generic thread - Add a generic CheckerThread that runs checks or whatever operation as long as it returns a boolean value - Closes the whole application if the wizard is rejected at the first run - Do not fail when the config directory doesn't exist - Set the wizard pixmap logo as LEAP's logo - Improve wizard checks - Make SRPRegister play nice with the CheckerThread --- src/leap/crypto/srpauth.py | 108 +++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 42 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index dbcc95cb..28e4f037 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -20,9 +20,11 @@ import srp import binascii import logging -from PySide import QtCore +from PySide import QtCore, QtGui from leap.config.providerconfig import ProviderConfig +from leap.util.check import leap_assert +from leap.util.checkerthread import CheckerThread logger = logging.getLogger(__name__) @@ -34,7 +36,7 @@ class SRPAuthenticationError(Exception): pass -class SRPAuth(QtCore.QThread): +class SRPAuth(QtCore.QObject): """ SRPAuth singleton """ @@ -55,7 +57,8 @@ class SRPAuth(QtCore.QThread): @param server: Server to which we will authenticate @type server: str """ - assert provider_config, "We need a provider config to authenticate" + leap_assert(provider_config, + "We need a provider config to authenticate") self._provider_config = provider_config @@ -277,15 +280,15 @@ class SRPAuth(QtCore.QThread): @param password: password for this user @type password: str """ - assert self.get_session_id() is None, "Already logged in" + 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) self._verify_session(M2) - assert self.get_session_id(), "Something went wrong because" + \ - " we don't have the auth cookie afterwards" + leap_assert(self.get_session_id(), "Something went wrong because" + " we don't have the auth cookie afterwards") def logout(self): """ @@ -294,7 +297,8 @@ class SRPAuth(QtCore.QThread): """ logger.debug("Starting logout...") - assert self.get_session_id(), "Cannot logout an unexisting session" + leap_assert(self.get_session_id(), + "Cannot logout an unexisting session") logout_url = "%s/%s/%s/" % (self._provider_config.get_api_uri(), self._provider_config. @@ -344,7 +348,7 @@ class SRPAuth(QtCore.QThread): """ Creates a singleton instance if needed """ - QtCore.QThread.__init__(self) + QtCore.QObject.__init__(self) # Check whether we already have an instance if SRPAuth.__instance is None: @@ -371,47 +375,47 @@ class SRPAuth(QtCore.QThread): @type password: str """ - with QtCore.QMutexLocker(self._should_login_lock): - self._should_login = self.DO_LOGIN - self._username = username - self._password = password - # Detach the start call to Qt's event loop - QtCore.QTimer.singleShot(0, self.start) - - def logout(self): - """ - Logs out the current session. - Expects a session_id to exists, might raise AssertionError - """ - QtCore.QMutexLocker(self._should_login_lock) - self._should_login = self.DO_LOGOUT - # Detach the start call to Qt's event loop - QtCore.QTimer.singleShot(0, self.start) - - def _runLogin(self, username, password): try: self.__instance.authenticate(username, password) + + logger.debug("Successful login!") self.authentication_finished.emit(True, "Succeeded") + return True except Exception as e: + logger.error("Error logging in %s" % (e,)) self.authentication_finished.emit(False, "%s" % (e,)) + return False - def _runLogout(self): + def logout(self): + """ + Logs out the current session. + Expects a session_id to exists, might raise AssertionError + """ try: self.__instance.logout() self.logout_finished.emit(True, "Succeeded") + return True except Exception as e: self.logout_finished.emit(False, "%s" % (e,)) - - def run(self): - QtCore.QMutexLocker(self._should_login_lock) - if self._should_login == self.DO_LOGIN: - self._runLogin(self._username, self._password) - elif self._should_login == self.DO_LOGOUT: - self._runLogout() - self._should_login = self.DO_NOTHING + return False if __name__ == "__main__": + import sys + from functools import partial + app = QtGui.QApplication(sys.argv) + + import signal + + def sigint_handler(*args, **kwargs): + logger.debug('SIGINT catched. shutting down...') + checker = args[0] + checker.set_should_quit() + QtGui.QApplication.quit() + + def signal_tester(d): + print d + logger = logging.getLogger(name='leap') logger.setLevel(logging.DEBUG) console = logging.StreamHandler() @@ -422,8 +426,23 @@ if __name__ == "__main__": console.setFormatter(formatter) logger.addHandler(console) - provider = ProviderConfig() + checker = CheckerThread() + + sigint = partial(sigint_handler, checker) + signal.signal(signal.SIGINT, sigint) + timer = QtCore.QTimer() + timer.start(500) + timer.timeout.connect(lambda: None) + app.connect(app, QtCore.SIGNAL("aboutToQuit()"), + checker.set_should_quit) + w = QtGui.QWidget() + w.resize(100, 100) + w.show() + + checker.start() + + provider = ProviderConfig() if provider.load("leap/providers/bitmask.net/provider.json"): # url = "%s/tickets" % (provider.get_api_uri(),) # print url @@ -431,9 +450,14 @@ if __name__ == "__main__": # print res.content # res.raise_for_status() auth = SRPAuth(provider) - auth.start() - auth.authenticate("test2", "sarasaaaa") - res = requests.session().get("%s/cert" % (provider.get_api_uri(),), - verify=provider.get_ca_cert_path()) - print res.content - auth.logout() + auth_instantiated = partial(auth.authenticate, "test2", "sarasaaaa") + + checker.add_checks([auth_instantiated, auth.logout]) + + #auth.authenticate("test2", "sarasaaaa") + #res = requests.session().get("%s/cert" % (provider.get_api_uri(),), + #verify=provider.get_ca_cert_path()) + #print res.content + #auth.logout() + + sys.exit(app.exec_()) -- cgit v1.2.3 From 926575bc811e8382100695a3396da7191fb43eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 8 Mar 2013 13:15:38 -0300 Subject: Add translation support Also: - Make OpenVPN use a random port every time - Logout in parallel so the UI doesn't block - Add the WAIT status from OpenVPN to the mainwindow displays - Support non-unix sockets in the LinuxVPNLauncher --- src/leap/crypto/srpauth.py | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 28e4f037..8530b7da 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -156,18 +156,18 @@ class SRPAuth(QtCore.QObject): "Status code = %r. Content: %r" % (init_session.status_code, init_session.content)) if init_session.status_code == 422: - raise SRPAuthenticationError("Unknown user") + raise SRPAuthenticationError(self.tr("Unknown user")) salt = init_session.json().get("salt", None) B = init_session.json().get("B", None) if salt is None: logger.error("No salt parameter sent") - raise SRPAuthenticationError("The server did not send the " + - "salt parameter") + raise SRPAuthenticationError(self.tr("The server did not send " + "the salt parameter")) if B is None: logger.error("No B parameter sent") - raise SRPAuthenticationError("The server did not send the " + - "B parameter") + raise SRPAuthenticationError(self.tr("The server did not send " + "the B parameter")) return salt, B @@ -194,8 +194,8 @@ class SRPAuth(QtCore.QObject): unhex_B = self._safe_unhexlify(B) except TypeError as e: logger.error("Bad data from server: %r" % (e,)) - raise SRPAuthenticationError("The data sent from the server " - "had errors") + raise SRPAuthenticationError(self.tr("The data sent from " + "the server had errors")) M = self._srp_user.process_challenge(unhex_salt, unhex_B) auth_url = "%s/%s/%s/%s" % (self._provider_config.get_api_uri(), @@ -215,20 +215,21 @@ class SRPAuth(QtCore.QObject): get_ca_cert_path()) except requests.exceptions.ConnectionError as e: logger.error("No connection made (HAMK): %r" % (e,)) - raise SRPAuthenticationError("Could not connect to the server") + raise SRPAuthenticationError(self.tr("Could not connect to " + "the server")) if auth_result.status_code == 422: logger.error("[%s] Wrong password (HAMK): [%s]" % (auth_result.status_code, auth_result.json(). get("errors", ""))) - raise SRPAuthenticationError("Wrong password") + raise SRPAuthenticationError(self.tr("Wrong password")) if auth_result.status_code not in (200,): logger.error("No valid response (HAMK): " "Status code = %s. Content = %r" % (auth_result.status_code, auth_result.content)) - raise SRPAuthenticationError("Unknown error (%s)" % + raise SRPAuthenticationError(self.tr("Unknown error (%s)") % (auth_result.status_code,)) M2 = auth_result.json().get("M2", None) @@ -237,8 +238,8 @@ class SRPAuth(QtCore.QObject): if M2 is None or self.get_uid() is None: logger.error("Something went wrong. Content = %r" % (auth_result.content,)) - raise SRPAuthenticationError("Problem getting data from" - " server") + raise SRPAuthenticationError(self.tr("Problem getting data " + "from server")) return M2 @@ -258,13 +259,14 @@ class SRPAuth(QtCore.QObject): unhex_M2 = self._safe_unhexlify(M2) except TypeError: logger.error("Bad data from server (HAWK)") - raise SRPAuthenticationError("Bad data from server") + raise SRPAuthenticationError(self.tr("Bad data from server")) self._srp_user.verify_session(unhex_M2) if not self._srp_user.authenticated(): logger.error("Auth verification failed") - raise SRPAuthenticationError("Auth verification failed") + raise SRPAuthenticationError(self.tr("Auth verification " + "failed")) logger.debug("Session verified.") self.set_session_id(self._session.cookies["_session_id"]) @@ -379,7 +381,7 @@ class SRPAuth(QtCore.QObject): self.__instance.authenticate(username, password) logger.debug("Successful login!") - self.authentication_finished.emit(True, "Succeeded") + self.authentication_finished.emit(True, self.tr("Succeeded")) return True except Exception as e: logger.error("Error logging in %s" % (e,)) @@ -393,7 +395,7 @@ class SRPAuth(QtCore.QObject): """ try: self.__instance.logout() - self.logout_finished.emit(True, "Succeeded") + self.logout_finished.emit(True, self.tr("Succeeded")) return True except Exception as e: self.logout_finished.emit(False, "%s" % (e,)) -- cgit v1.2.3 From e4e5f35c3fc7ff02bc20a6ef7eaffae09f485061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 8 Mar 2013 14:24:05 -0300 Subject: Add keyring and username/password saving capabilities Also: - Fix translations in SRPAuth - Support non-ascii passwords - Make the server check if the characters are allowed, just check for easy passwords --- src/leap/crypto/srpauth.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 8530b7da..2877efab 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -41,7 +41,7 @@ class SRPAuth(QtCore.QObject): SRPAuth singleton """ - class __impl(object): + class __impl(QtCore.QObject): """ Implementation of the SRPAuth interface """ @@ -57,6 +57,8 @@ class SRPAuth(QtCore.QObject): @param server: Server to which we will authenticate @type server: str """ + QtCore.QObject.__init__(self) + leap_assert(provider_config, "We need a provider config to authenticate") -- cgit v1.2.3 From a120904b512394346b286bb417adf34fc622e739 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 12 Mar 2013 14:26:38 -0300 Subject: Get eip cert with session_id when possible --- src/leap/crypto/srpauth.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 2877efab..c1964514 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -390,6 +390,9 @@ class SRPAuth(QtCore.QObject): self.authentication_finished.emit(False, "%s" % (e,)) return False + def get_session_id(self): + return self.__instance.get_session_id() + def logout(self): """ Logs out the current session. -- cgit v1.2.3 From 98699d1c1c9d4698faa6bd7b1c7cf5b576372381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 13 Mar 2013 11:39:06 -0300 Subject: Separate stdlibs from non-std in imports --- src/leap/crypto/srpauth.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index c1964514..e9c72408 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -15,11 +15,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import requests -import srp import binascii import logging +import requests +import srp + from PySide import QtCore, QtGui from leap.config.providerconfig import ProviderConfig -- cgit v1.2.3 From d0dfad6ac2af360de6421ce74a6831b5b81ad019 Mon Sep 17 00:00:00 2001 From: kali Date: Thu, 14 Mar 2013 07:08:31 +0900 Subject: namespace leap + leap.common split leap is a namespace package from here on. common folder will be deleted and moved to leap_pycommon repository. --- src/leap/crypto/srpauth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index e9c72408..152d77b5 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -23,8 +23,8 @@ import srp from PySide import QtCore, QtGui +from leap.common.check import leap_assert from leap.config.providerconfig import ProviderConfig -from leap.util.check import leap_assert from leap.util.checkerthread import CheckerThread logger = logging.getLogger(__name__) -- cgit v1.2.3 From d193fee401d606f6120ac11819a0127e7ee92458 Mon Sep 17 00:00:00 2001 From: kali Date: Tue, 26 Mar 2013 01:15:44 +0900 Subject: tests for srpregister and srpauth in this commit too, the twisted fake_provider implementation --- src/leap/crypto/srpauth.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 152d77b5..027ee0d7 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -272,7 +272,14 @@ class SRPAuth(QtCore.QObject): "failed")) logger.debug("Session verified.") - self.set_session_id(self._session.cookies["_session_id"]) + SESSION_ID_KEY = "_session_id" + session_id = self._session.cookies.get(SESSION_ID_KEY, None) + if not session_id: + logger.error("Bad cookie from server (missing _session_id)") + raise SRPAuthenticationError(self.tr("Session cookie " + "verification " + "failed")) + self.set_session_id(session_id) def authenticate(self, username, password): """ @@ -409,11 +416,18 @@ class SRPAuth(QtCore.QObject): if __name__ == "__main__": + import signal import sys + from functools import partial app = QtGui.QApplication(sys.argv) - import signal + if not len(sys.argv) == 3: + print 'Usage: srpauth.py ' + sys.exit(0) + + _user = sys.argv[1] + _pass = sys.argv[2] def sigint_handler(*args, **kwargs): logger.debug('SIGINT catched. shutting down...') @@ -452,20 +466,9 @@ if __name__ == "__main__": provider = ProviderConfig() if provider.load("leap/providers/bitmask.net/provider.json"): - # url = "%s/tickets" % (provider.get_api_uri(),) - # print url - # res = requests.session().get(url, verify=provider.get_ca_cert_path()) - # print res.content - # res.raise_for_status() auth = SRPAuth(provider) - auth_instantiated = partial(auth.authenticate, "test2", "sarasaaaa") + auth_instantiated = partial(auth.authenticate, _user, _pass) checker.add_checks([auth_instantiated, auth.logout]) - #auth.authenticate("test2", "sarasaaaa") - #res = requests.session().get("%s/cert" % (provider.get_api_uri(),), - #verify=provider.get_ca_cert_path()) - #print res.content - #auth.logout() - sys.exit(app.exec_()) -- cgit v1.2.3 From 42593d4c6bda51a544a72abc0f935633939dad49 Mon Sep 17 00:00:00 2001 From: kali Date: Mon, 8 Apr 2013 23:44:22 +0900 Subject: Several fixes as per review --- src/leap/crypto/srpauth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 027ee0d7..8028a6dc 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -50,6 +50,7 @@ class SRPAuth(QtCore.QObject): LOGIN_KEY = "login" A_KEY = "A" CLIENT_AUTH_KEY = "client_auth" + SESSION_ID_KEY = "_session_id" def __init__(self, provider_config): """ @@ -272,8 +273,7 @@ class SRPAuth(QtCore.QObject): "failed")) logger.debug("Session verified.") - SESSION_ID_KEY = "_session_id" - session_id = self._session.cookies.get(SESSION_ID_KEY, None) + session_id = self._session.cookies.get(self.SESSION_ID_KEY, None) if not session_id: logger.error("Bad cookie from server (missing _session_id)") raise SRPAuthenticationError(self.tr("Session cookie " -- cgit v1.2.3 From fd17db8aaeda0c5997a608fd2d2e0392eb0c68ae Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Wed, 10 Apr 2013 09:56:36 -0300 Subject: Emit session_id and uid through events --- src/leap/crypto/srpauth.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 8028a6dc..ba8ac3f5 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -26,6 +26,8 @@ from PySide import QtCore, QtGui from leap.common.check import leap_assert from leap.config.providerconfig import ProviderConfig from leap.util.checkerthread import CheckerThread +from leap.common.events import signal as events_signal +from leap.common.events import events_pb2 as proto logger = logging.getLogger(__name__) @@ -237,7 +239,11 @@ class SRPAuth(QtCore.QObject): (auth_result.status_code,)) M2 = auth_result.json().get("M2", None) - self.set_uid(auth_result.json().get("id", None)) + uid = auth_result.json().get("id", None) + + events_signal(proto.CLIENT_UID, content=uid) + + self.set_uid(uid) if M2 is None or self.get_uid() is None: logger.error("Something went wrong. Content = %r" % @@ -279,6 +285,9 @@ class SRPAuth(QtCore.QObject): raise SRPAuthenticationError(self.tr("Session cookie " "verification " "failed")) + + events_signal(proto.CLIENT_SESSION_ID, content=session_id) + self.set_session_id(session_id) def authenticate(self, username, password): -- cgit v1.2.3 From 2dae2703fb8c2ae7e721ce83020c0dd10ff9ca33 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 3 May 2013 02:59:22 +0900 Subject: updated documentation * documentation reviewed after rewrite, ready for 0.2.1 * updated docstrings format to fit sphinx autodoc --- src/leap/crypto/srpauth.py | 68 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index ba8ac3f5..9446cee8 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -58,8 +58,8 @@ class SRPAuth(QtCore.QObject): """ Constructor for SRPAuth implementation - @param server: Server to which we will authenticate - @type server: str + :param server: Server to which we will authenticate + :type server: str """ QtCore.QObject.__init__(self) @@ -91,11 +91,11 @@ class SRPAuth(QtCore.QObject): Rounds the val to a multiple of 2 and returns the unhexlified value - @param val: hexlified value - @type val: str + :param val: hexlified value + :type val: str - @rtype: binary hex data - @return: unhexlified val + :rtype: binary hex data + :return: unhexlified val """ return binascii.unhexlify(val) \ if (len(val) % 2 == 0) else binascii.unhexlify('0' + val) @@ -104,10 +104,10 @@ class SRPAuth(QtCore.QObject): """ Generates the SRP.User to get the A SRP parameter - @param username: username to login - @type username: str - @param password: password for the username - @type password: str + :param username: username to login + :type username: str + :param password: password for the username + :type password: str """ logger.debug("Authentication preprocessing...") self._srp_user = self._srp.User(username, @@ -125,13 +125,13 @@ class SRPAuth(QtCore.QObject): Might raise SRPAuthenticationError - @param username: username to login - @type username: str - @param password: password for the username - @type password: str + :param username: username to login + :type username: str + :param password: password for the username + :type password: str - @return: salt and B parameters - @rtype: tuple + :return: salt and B parameters + :rtype: tuple """ logger.debug("Starting authentication process...") try: @@ -184,15 +184,15 @@ class SRPAuth(QtCore.QObject): Might throw SRPAuthenticationError - @param salt: salt for the username - @type salt: str - @param B: B SRP parameter - @type B: str - @param username: username for this session - @type username: str + :param salt: salt for the username + :type salt: str + :param B: B SRP parameter + :type B: str + :param username: username for this session + :type username: str - @return: the M2 SRP parameter - @rtype: str + :return: the M2 SRP parameter + :rtype: str """ logger.debug("Processing challenge...") try: @@ -261,8 +261,8 @@ class SRPAuth(QtCore.QObject): Might throw SRPAuthenticationError - @param M2: M2 SRP parameter - @type M2: str + :param M2: M2 SRP parameter + :type M2: str """ logger.debug("Verifying session...") try: @@ -296,10 +296,10 @@ class SRPAuth(QtCore.QObject): Might raise SRPAuthenticationError - @param username: username for this session - @type username: str - @param password: password for this user - @type password: str + :param username: username for this session + :type username: str + :param password: password for this user + :type password: str """ leap_assert(self.get_session_id() is None, "Already logged in") @@ -390,10 +390,10 @@ class SRPAuth(QtCore.QObject): Might raise SRPAuthenticationError - @param username: username for this session - @type username: str - @param password: password for this user - @type password: str + :param username: username for this session + :type username: str + :param password: password for this user + :type password: str """ try: -- cgit v1.2.3 From c533900a43f5006e6b4cb9d070b4bd30fb67f0b5 Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Fri, 10 May 2013 16:41:42 -0300 Subject: Save auth token --- src/leap/crypto/srpauth.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 9446cee8..26bd0295 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -82,6 +82,8 @@ class SRPAuth(QtCore.QObject): self._session_id_lock = QtCore.QMutex() self._uid = None self._uid_lock = QtCore.QMutex() + self._token = None + self._token_lock = QtCore.QMutex() self._srp_user = None self._srp_a = None @@ -240,10 +242,12 @@ class SRPAuth(QtCore.QObject): M2 = auth_result.json().get("M2", None) uid = auth_result.json().get("id", None) + token = auth_result.json().get("token", None) events_signal(proto.CLIENT_UID, content=uid) self.set_uid(uid) + self.set_token(token) if M2 is None or self.get_uid() is None: logger.error("Something went wrong. Content = %r" % @@ -356,6 +360,14 @@ class SRPAuth(QtCore.QObject): QtCore.QMutexLocker(self._uid_lock) return self._uid + def set_token(self, token): + QtCore.QMutexLocker(self._token_lock) + self._token = token + + def get_token(self, token): + QtCore.QMutexLocker(self._token_lock) + return self._token + __instance = None authentication_finished = QtCore.Signal(bool, str) -- cgit v1.2.3 From 4e201329042d43c8d281c5737d3d5f6f8e2bf67f Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Fri, 10 May 2013 17:01:11 -0300 Subject: Add support for requests<1.0.0 --- src/leap/crypto/srpauth.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 26bd0295..dbaac01b 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -20,12 +20,14 @@ import logging import requests import srp +import json from PySide import QtCore, QtGui from leap.common.check import leap_assert from leap.config.providerconfig import ProviderConfig from leap.util.checkerthread import CheckerThread +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 @@ -159,14 +161,18 @@ class SRPAuth(QtCore.QObject): raise SRPAuthenticationError("Unknown error: %r" % (e,)) + content, mtime = get_content(init_session) + if init_session.status_code not in (200,): logger.error("No valid response (salt): " "Status code = %r. Content: %r" % - (init_session.status_code, init_session.content)) + (init_session.status_code, content)) if init_session.status_code == 422: raise SRPAuthenticationError(self.tr("Unknown user")) - salt = init_session.json().get("salt", None) - B = init_session.json().get("B", None) + + json_content = json.loads(content) + salt = json_content.get("salt", None) + B = json_content.get("B", None) if salt is None: logger.error("No salt parameter sent") @@ -226,22 +232,25 @@ class SRPAuth(QtCore.QObject): raise SRPAuthenticationError(self.tr("Could not connect to " "the server")) + content, mtime = get_content(auth_result) + if auth_result.status_code == 422: logger.error("[%s] Wrong password (HAMK): [%s]" % (auth_result.status_code, - auth_result.json(). + content. get("errors", ""))) raise SRPAuthenticationError(self.tr("Wrong password")) if auth_result.status_code not in (200,): logger.error("No valid response (HAMK): " "Status code = %s. Content = %r" % - (auth_result.status_code, auth_result.content)) + (auth_result.status_code, content)) raise SRPAuthenticationError(self.tr("Unknown error (%s)") % (auth_result.status_code,)) - M2 = auth_result.json().get("M2", None) - uid = auth_result.json().get("id", None) + json_content = json.loads(content) + M2 = json_content.get("M2", None) + uid = json_content.get("id", None) token = auth_result.json().get("token", None) events_signal(proto.CLIENT_UID, content=uid) @@ -251,7 +260,7 @@ class SRPAuth(QtCore.QObject): if M2 is None or self.get_uid() is None: logger.error("Something went wrong. Content = %r" % - (auth_result.content,)) + (content,)) raise SRPAuthenticationError(self.tr("Problem getting data " "from server")) -- cgit v1.2.3 From 8781a893aeaa62286633021e9d3eb8502bd129ee Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Sat, 11 May 2013 11:49:17 -0300 Subject: Support requests<1.0.0 for the token saving too --- src/leap/crypto/srpauth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index dbaac01b..ce6c28f4 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -251,7 +251,7 @@ class SRPAuth(QtCore.QObject): json_content = json.loads(content) M2 = json_content.get("M2", None) uid = json_content.get("id", None) - token = auth_result.json().get("token", None) + token = json_content.get("token", None) events_signal(proto.CLIENT_UID, content=uid) -- cgit v1.2.3 From b0abf507bb8eb570328172b659ab072bc4b08634 Mon Sep 17 00:00:00 2001 From: Tomas Touceda Date: Wed, 15 May 2013 16:16:32 -0300 Subject: Integrate soledad and keymanager in the client --- src/leap/crypto/srpauth.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index ce6c28f4..2f3cbd1c 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -373,7 +373,7 @@ class SRPAuth(QtCore.QObject): QtCore.QMutexLocker(self._token_lock) self._token = token - def get_token(self, token): + def get_token(self): QtCore.QMutexLocker(self._token_lock) return self._token @@ -431,6 +431,12 @@ class SRPAuth(QtCore.QObject): def get_session_id(self): return self.__instance.get_session_id() + def get_uid(self): + return self.__instance.get_uid() + + def get_token(self): + return self.__instance.get_token() + def logout(self): """ Logs out the current session. -- cgit v1.2.3 From 884d0e0f4dbba34b6f6f5afe6e27390a7606a7fa Mon Sep 17 00:00:00 2001 From: kali Date: Wed, 29 May 2013 04:02:43 +0900 Subject: make tests pass & fix pep8 --- src/leap/crypto/srpauth.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 2f3cbd1c..f1897e1d 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -22,6 +22,9 @@ import requests import srp import json +#this error is raised from requests +from simplejson.decoder import JSONDecodeError + from PySide import QtCore, QtGui from leap.common.check import leap_assert @@ -232,7 +235,10 @@ class SRPAuth(QtCore.QObject): raise SRPAuthenticationError(self.tr("Could not connect to " "the server")) - content, mtime = get_content(auth_result) + try: + content, mtime = get_content(auth_result) + except JSONDecodeError: + raise SRPAuthenticationError("Bad JSON content in auth result") if auth_result.status_code == 422: logger.error("[%s] Wrong password (HAMK): [%s]" % @@ -319,6 +325,7 @@ class SRPAuth(QtCore.QObject): self._authentication_preprocessing(username, password) salt, B = self._start_authentication(username, password) M2 = self._process_challenge(salt, B, username) + self._verify_session(M2) leap_assert(self.get_session_id(), "Something went wrong because" -- cgit v1.2.3 From 655cec1fec89eb30fc17bdc0a5f527e5a91ba5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 4 Jun 2013 12:56:17 -0300 Subject: Remove CheckerThread from SRPAuth Also, some pep8 fixes --- src/leap/crypto/srpauth.py | 60 ---------------------------------------------- 1 file changed, 60 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index f1897e1d..28086279 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -29,7 +29,6 @@ from PySide import QtCore, QtGui from leap.common.check import leap_assert from leap.config.providerconfig import ProviderConfig -from leap.util.checkerthread import CheckerThread 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 @@ -456,62 +455,3 @@ class SRPAuth(QtCore.QObject): except Exception as e: self.logout_finished.emit(False, "%s" % (e,)) return False - - -if __name__ == "__main__": - import signal - import sys - - from functools import partial - app = QtGui.QApplication(sys.argv) - - if not len(sys.argv) == 3: - print 'Usage: srpauth.py ' - sys.exit(0) - - _user = sys.argv[1] - _pass = sys.argv[2] - - def sigint_handler(*args, **kwargs): - logger.debug('SIGINT catched. shutting down...') - checker = args[0] - checker.set_should_quit() - QtGui.QApplication.quit() - - def signal_tester(d): - print d - - logger = logging.getLogger(name='leap') - logger.setLevel(logging.DEBUG) - console = logging.StreamHandler() - console.setLevel(logging.DEBUG) - formatter = logging.Formatter( - '%(asctime)s ' - '- %(name)s - %(levelname)s - %(message)s') - console.setFormatter(formatter) - logger.addHandler(console) - - checker = CheckerThread() - - sigint = partial(sigint_handler, checker) - signal.signal(signal.SIGINT, sigint) - - timer = QtCore.QTimer() - timer.start(500) - timer.timeout.connect(lambda: None) - app.connect(app, QtCore.SIGNAL("aboutToQuit()"), - checker.set_should_quit) - w = QtGui.QWidget() - w.resize(100, 100) - w.show() - - checker.start() - - provider = ProviderConfig() - if provider.load("leap/providers/bitmask.net/provider.json"): - auth = SRPAuth(provider) - auth_instantiated = partial(auth.authenticate, _user, _pass) - - checker.add_checks([auth_instantiated, auth.logout]) - - sys.exit(app.exec_()) -- cgit v1.2.3 From 40c1190ad556aee33d1b90a9c234b36ad0759861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Thu, 6 Jun 2013 11:39:57 -0300 Subject: Make the login process more granular with defers --- src/leap/crypto/srpauth.py | 73 ++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 29 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 28086279..3e47f679 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: @@ -318,17 +319,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): """ @@ -388,10 +394,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 @@ -406,8 +408,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 @@ -423,16 +423,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() -- cgit v1.2.3 From 029b4c2ac07fab41dbed9ab90e04e477938c3c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Tue, 11 Jun 2013 12:09:30 -0300 Subject: Merge systray icons Also, catch a possible problem with the login answer from the webapp and display a proper message --- src/leap/crypto/srpauth.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 28086279..82525d7f 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -254,9 +254,14 @@ class SRPAuth(QtCore.QObject): (auth_result.status_code,)) json_content = json.loads(content) - M2 = json_content.get("M2", None) - uid = json_content.get("id", None) - token = json_content.get("token", None) + + try: + M2 = json_content.get("M2", None) + uid = json_content.get("id", None) + token = json_content.get("token", None) + except Exception as e: + logger.error(e) + raise Exception("Something went wrong with the login") events_signal(proto.CLIENT_UID, content=uid) -- cgit v1.2.3 From 1ede2af0afb6db2265d7e32428c197605e74589e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Wed, 12 Jun 2013 10:57:20 -0300 Subject: Fix SRPAuth error reporting --- src/leap/crypto/srpauth.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index 52267b3b..bcd24de3 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -241,10 +241,17 @@ class SRPAuth(QtCore.QObject): raise SRPAuthenticationError("Bad JSON content in auth result") if auth_result.status_code == 422: + error = "" + try: + error = json.loads(content).get("errors", "") + except ValueError: + logger.error("Problem parsing the received response: %s" + % (content,)) + except AttributeError: + logger.error("Expecting a dict but something else was " + "received: %s", (content,)) logger.error("[%s] Wrong password (HAMK): [%s]" % - (auth_result.status_code, - content. - get("errors", ""))) + (auth_result.status_code, error)) raise SRPAuthenticationError(self.tr("Wrong password")) if auth_result.status_code not in (200,): -- cgit v1.2.3 From 1b670d268ee26fc06115702aff055884327f85ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 14 Jun 2013 11:08:39 -0300 Subject: Improve error messages in login --- src/leap/crypto/srpauth.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index bcd24de3..d089fa50 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -459,7 +459,8 @@ class SRPAuth(QtCore.QObject): :type failure: twisted.python.failure.Failure """ logger.error("Error logging in %s" % (failure,)) - self.authentication_finished.emit(False, "%s" % (failure,)) + self.authentication_finished.emit(False, "%s" % (failure.value,)) + failure.trap(Exception) def get_session_id(self): return self.__instance.get_session_id() -- cgit v1.2.3 From 8bee5f4e9a1bb0f7069fe41ab37dfec000487d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Touceda?= Date: Fri, 14 Jun 2013 12:45:08 -0300 Subject: Actually deferToThread all the things we expect to do in parallel --- src/leap/crypto/srpauth.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/leap/crypto/srpauth.py') diff --git a/src/leap/crypto/srpauth.py b/src/leap/crypto/srpauth.py index d089fa50..0e95ae64 100644 --- a/src/leap/crypto/srpauth.py +++ b/src/leap/crypto/srpauth.py @@ -24,6 +24,7 @@ import json #this error is raised from requests from simplejson.decoder import JSONDecodeError +from functools import partial from PySide import QtCore from twisted.internet import threads @@ -321,6 +322,9 @@ class SRPAuth(QtCore.QObject): self.set_session_id(session_id) + def _threader(self, cb, res, *args, **kwargs): + return threads.deferToThread(cb, res, *args, **kwargs) + def authenticate(self, username, password): """ Executes the whole authentication process for a user @@ -341,10 +345,17 @@ class SRPAuth(QtCore.QObject): username=username, password=password) - d.addCallback(self._start_authentication, username=username, - password=password) - d.addCallback(self._process_challenge, username=username) - d.addCallback(self._verify_session) + d.addCallback( + partial(self._threader, + self._start_authentication), + username=username, + password=password) + d.addCallback( + partial(self._threader, + self._process_challenge), + username=username) + d.addCallback(partial(self._threader, + self._verify_session)) return d -- cgit v1.2.3