From 7c659fed65f08f2b52f0320c99a456679749e3f3 Mon Sep 17 00:00:00 2001 From: kali Date: Fri, 5 Oct 2012 09:30:50 +0900 Subject: use keyring to store user password using a quite lame cryptedfile by the moment until dbus bug makes gnome-keyring usable again or we come up with the encrypted database solution. we might want to explore the option of using this python-keyring with the different native backends for win and macosx. for now: we generate a random secret that we store in the qsettings file. so, the whole thing is just to avoid plaintext stuff. for this, we could have done rot13, haha. --- pkg/requirements.pip | 2 ++ src/leap/crypto/__init__.py | 0 src/leap/crypto/leapkeyring.py | 63 ++++++++++++++++++++++++++++++++++++++++++ src/leap/gui/firstrunwizard.py | 34 ++++++++++++++++++++--- 4 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 src/leap/crypto/__init__.py create mode 100644 src/leap/crypto/leapkeyring.py diff --git a/pkg/requirements.pip b/pkg/requirements.pip index f244879b..d6c6713f 100644 --- a/pkg/requirements.pip +++ b/pkg/requirements.pip @@ -5,3 +5,5 @@ netifaces python-gnutls==1.1.9 # see https://bugs.launchpad.net/ubuntu/+source/python-gnutls/+bug/1027129 jsonschema srp +pycrypto +keyring diff --git a/src/leap/crypto/__init__.py b/src/leap/crypto/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/leap/crypto/leapkeyring.py b/src/leap/crypto/leapkeyring.py new file mode 100644 index 00000000..394142db --- /dev/null +++ b/src/leap/crypto/leapkeyring.py @@ -0,0 +1,63 @@ +import os + +import keyring + +############# +# Disclaimer +############# +# This currently is not a keyring, it's more like a joke. +# No, seriously. +# We're affected by this **bug** + +# https://bitbucket.org/kang/python-keyring-lib/issue/65/dbusexception-method-opensession-with + +# so using the gnome keyring does not seem feasible right now. +# I thought this was the next best option to store secrets in plain sight. + +# in the future we should move to use the gnome/kde/macosx/win keyrings. + + +class LeapCryptedFileKeyring(keyring.backend.CryptedFileKeyring): + + filename = os.path.expanduser("~/.config/leap/.secrets") + + def __init__(self, seed=None): + self.seed = seed + + def _get_new_password(self): + # XXX every time this method is called, + # $deity kills a kitten. + return "secret%s" % self.seed + + def _init_file(self): + self.keyring_key = self._get_new_password() + self.set_password('keyring_setting', 'pass_ref', 'pass_ref_value') + + def _unlock(self): + self.keyring_key = self._get_new_password() + print 'keyring key ', self.keyring_key + try: + ref_pw = self.get_password( + 'keyring_setting', + 'pass_ref') + print 'ref pw ', ref_pw + assert ref_pw == "pass_ref_value" + except AssertionError: + self._lock() + raise ValueError('Incorrect password') + + +def leap_set_password(key, value, seed="xxx"): + keyring.set_keyring(LeapCryptedFileKeyring(seed=seed)) + keyring.set_password('leap', key, value) + + +def leap_get_password(key, seed="xxx"): + keyring.set_keyring(LeapCryptedFileKeyring(seed=seed)) + return keyring.get_password('leap', key) + + +if __name__ == "__main__": + leap_set_password('test', 'bar') + passwd = leap_get_password('test') + assert passwd == 'bar' diff --git a/src/leap/gui/firstrunwizard.py b/src/leap/gui/firstrunwizard.py index 3b27985f..1012f64c 100755 --- a/src/leap/gui/firstrunwizard.py +++ b/src/leap/gui/firstrunwizard.py @@ -8,6 +8,7 @@ sip.setapi('QVariant', 2) from PyQt4 import QtCore from PyQt4 import QtGui +from leap.crypto import leapkeyring from leap.gui import mainwindow_rc logger = logging.getLogger(__name__) @@ -89,7 +90,9 @@ QLabel { color: red; class FirstRunWizard(QtGui.QWizard): - def __init__(self, parent=None, providers=None, success_cb=None): + def __init__( + self, parent=None, providers=None, + success_cb=None): super(FirstRunWizard, self).__init__( parent, QtCore.Qt.WindowStaysOnTopHint) @@ -126,6 +129,7 @@ class FirstRunWizard(QtGui.QWizard): QtGui.QWizard.setWindowFlags(self, flags) def focusOutEvent(self, event): + # needed ? self.setFocus(True) self.activateWindow() self.raise_() @@ -137,13 +141,27 @@ class FirstRunWizard(QtGui.QWizard): gather the info, update settings and call the success callback. """ - logger.debug('chosen provider: %s', self.get_provider()) - logger.debug('username: %s', self.field('userName')) - logger.debug('remember password: %s', self.field('rememberPassword')) + provider = self.get_provider() + username = self.field('userName') + password = self.field('userPassword') + remember_pass = self.field('rememberPassword') + + logger.debug('chosen provider: %s', provider) + logger.debug('username: %s', username) + logger.debug('remember password: %s', remember_pass) super(FirstRunWizard, self).accept() settings = QtCore.QSettings() settings.setValue("FirstRunWizardDone", True) + settings.setValue( + "eip_%s_username" % provider, + username) + settings.setValue("%s_remember_pass" % provider, remember_pass) + + seed = self.get_random_str(10) + settings.setValue("%s_seed" % provider, seed) + + leapkeyring.leap_set_password(username, password, seed=seed) logger.debug('First Run Wizard Done.') cb = self.success_cb @@ -154,6 +172,14 @@ class FirstRunWizard(QtGui.QWizard): provider = self.field('provider_index') return self.providers[provider] + def get_random_str(self, n): + from string import (ascii_uppercase, ascii_lowercase, digits) + from random import choice + return ''.join(choice( + ascii_uppercase + + ascii_lowercase + + digits) for x in range(n)) + class IntroPage(QtGui.QWizardPage): def __init__(self, parent=None): -- cgit v1.2.3