From 5273f6694bffbba0a07c34f19a5a6630382e4d48 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 14 Nov 2013 11:34:46 -0300 Subject: Add advanced key management dialog. --- src/leap/bitmask/gui/advanced_key_management.py | 185 +++++++++++++++++++++ src/leap/bitmask/gui/ui/advanced_key_management.ui | 153 +++++++++++++++++ 2 files changed, 338 insertions(+) create mode 100644 src/leap/bitmask/gui/advanced_key_management.py create mode 100644 src/leap/bitmask/gui/ui/advanced_key_management.ui (limited to 'src') diff --git a/src/leap/bitmask/gui/advanced_key_management.py b/src/leap/bitmask/gui/advanced_key_management.py new file mode 100644 index 00000000..2c0fa034 --- /dev/null +++ b/src/leap/bitmask/gui/advanced_key_management.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# advanced_key_management.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 . +""" +Advanced Key Management +""" +import logging + +from PySide import QtGui +from zope.proxy import sameProxiedObjects + +from leap.keymanager import openpgp +from leap.keymanager.errors import KeyAddressMismatch, KeyFingerprintMismatch +from leap.bitmask.services import get_service_display_name, MX_SERVICE +from ui_advanced_key_management import Ui_AdvancedKeyManagement + +logger = logging.getLogger(__name__) + + +class AdvancedKeyManagement(QtGui.QWidget): + """ + Advanced Key Management + """ + def __init__(self, user, keymanager, soledad): + """ + :param user: the current logged in user. + :type user: unicode + :param keymanager: the existing keymanager instance + :type keymanager: KeyManager + :param soledad: a loaded instance of Soledad + :type soledad: Soledad + """ + QtGui.QWidget.__init__(self) + + self.ui = Ui_AdvancedKeyManagement() + self.ui.setupUi(self) + + # if Soledad is not started yet + if sameProxiedObjects(soledad, None): + self.ui.container.setEnabled(False) + msg = self.tr("NOTE: " + "To use this, you need to enable/start {0}.") + msg = msg.format(get_service_display_name(MX_SERVICE)) + self.ui.lblStatus.setText(msg) + return + else: + msg = self.tr( + "WARNING:
" + "This is an experimental feature, you can lose access to " + "existing e-mails.") + self.ui.lblStatus.setText(msg) + + self._keymanager = keymanager + self._soledad = soledad + + self._key = keymanager.get_key(user, openpgp.OpenPGPKey) + self._key_priv = keymanager.get_key( + user, openpgp.OpenPGPKey, private=True) + + # show current key information + self.ui.leUser.setText(user) + self.ui.leKeyID.setText(self._key.key_id) + self.ui.leFingerprint.setText(self._key.fingerprint) + + # set up connections + self.ui.pbImportKeys.clicked.connect(self._import_keys) + self.ui.pbExportKeys.clicked.connect(self._export_keys) + + def _import_keys(self): + """ + Imports the user's key pair. + Those keys need to be ascii armored. + """ + fileName, filtr = QtGui.QFileDialog.getOpenFileName( + self, self.tr("Open keys file"), + options=QtGui.QFileDialog.DontUseNativeDialog) + + if fileName: + new_key = '' + try: + with open(fileName, 'r') as keys_file: + new_key = keys_file.read() + except IOError as e: + logger.error("IOError importing key. {0!r}".format(e)) + QtGui.QMessageBox.critical( + self, self.tr("Input/Output error"), + self.tr("There was an error accessing the file.\n" + "Import canceled.")) + return + + keymanager = self._keymanager + try: + public_key, private_key = keymanager.parse_openpgp_ascii_key( + new_key) + except (KeyAddressMismatch, KeyFingerprintMismatch) as e: + logger.error(repr(e)) + QtGui.QMessageBox.warning( + self, self.tr("Data mismatch"), + self.tr("The public and private key should have the " + "same address and fingerprint.\n" + "Import canceled.")) + return + + if public_key is None or private_key is None: + QtGui.QMessageBox.warning( + self, self.tr("Missing key"), + self.tr("You need to provide the public AND private " + "key in the same file.\n" + "Import canceled.")) + return + + if public_key.address != self._key.address: + logger.error("The key does not match the ID") + QtGui.QMessageBox.warning( + self, self.tr("Address mismatch"), + self.tr("The identity for the key needs to be the same " + "as your user address.\n" + "Import canceled.")) + return + + question = self.tr("Are you sure that you want to replace " + "the current key pair whith the imported?") + res = QtGui.QMessageBox.question( + None, "Change key pair", question, + QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, + QtGui.QMessageBox.No) # default No + + if res == QtGui.QMessageBox.No: + return + + keymanager.delete_key(self._key) + keymanager.delete_key(self._key_priv) + keymanager.put_key(public_key) + keymanager.put_key(private_key) + keymanager.send_key(openpgp.OpenPGPKey) + + logger.debug('Import ok') + + QtGui.QMessageBox.information( + self, self.tr("Import Successful"), + self.tr("The key pair was imported successfully.")) + else: + logger.debug('Import canceled by the user.') + + def _export_keys(self): + """ + Exports the user's key pair. + """ + fileName, filtr = QtGui.QFileDialog.getSaveFileName( + self, self.tr("Save keys file"), + options=QtGui.QFileDialog.DontUseNativeDialog) + + if fileName: + try: + with open(fileName, 'w') as keys_file: + keys_file.write(self._key.key_data) + keys_file.write(self._key_priv.key_data) + + logger.debug('Export ok') + QtGui.QMessageBox.information( + self, self.tr("Export Successful"), + self.tr("The key pair was exported successfully.\n" + "Please, store your private key in a safe place.")) + except IOError as e: + logger.error("IOError exporting key. {0!r}".format(e)) + QtGui.QMessageBox.critical( + self, self.tr("Input/Output error"), + self.tr("There was an error accessing the file.\n" + "Export canceled.")) + return + else: + logger.debug('Export canceled by the user.') diff --git a/src/leap/bitmask/gui/ui/advanced_key_management.ui b/src/leap/bitmask/gui/ui/advanced_key_management.ui new file mode 100644 index 00000000..d61aa87e --- /dev/null +++ b/src/leap/bitmask/gui/ui/advanced_key_management.ui @@ -0,0 +1,153 @@ + + + AdvancedKeyManagement + + + + 0 + 0 + 431 + 188 + + + + Advanced Key Management + + + + :/images/mask-icon.png:/images/mask-icon.png + + + + + + + + + User: + + + + + + + true + + + user_name@provider + + + Qt::AlignCenter + + + true + + + + + + + Key ID: + + + + + + + true + + + key ID + + + Qt::AlignCenter + + + true + + + + + + + Key fingerprint: + + + + + + + true + + + fingerprint + + + Qt::AlignCenter + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Export current key pair + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Import custom key pair + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From ed08a7619bd79a594d579b4bfbc7d4bdce3ccd7a Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 14 Nov 2013 11:39:41 -0300 Subject: Add the advanced key management to the main window --- src/leap/bitmask/gui/mainwindow.py | 19 +++++++++++++++++++ src/leap/bitmask/gui/ui/mainwindow.ui | 13 +++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index f3043809..39a08cfb 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -29,6 +29,7 @@ from leap.bitmask.config.leapsettings import LeapSettings from leap.bitmask.config.providerconfig import ProviderConfig from leap.bitmask.crypto.srpauth import SRPAuth from leap.bitmask.gui.loggerwindow import LoggerWindow +from leap.bitmask.gui.advanced_key_management import AdvancedKeyManagement from leap.bitmask.gui.login import LoginWidget from leap.bitmask.gui.preferenceswindow import PreferencesWindow from leap.bitmask.gui.eip_preferenceswindow import EIPPreferencesWindow @@ -252,6 +253,9 @@ class MainWindow(QtGui.QMainWindow): self.ui.action_create_new_account.triggered.connect( self._launch_wizard) + self.ui.action_advanced_key_management.triggered.connect( + self._show_AKM) + if IS_MAC: self.ui.menuFile.menuAction().setText(self.tr("File")) @@ -437,6 +441,20 @@ class MainWindow(QtGui.QMainWindow): else: self._logger_window.setVisible(not self._logger_window.isVisible()) + def _show_AKM(self): + """ + SLOT + TRIGGERS: + self.ui.action_advanced_key_management.triggered + + Displays the Advanced Key Management dialog. + """ + domain = self._login_widget.get_selected_provider() + logged_user = "{0}@{1}".format(self._logged_user, domain) + self._akm = AdvancedKeyManagement( + logged_user, self._keymanager, self._soledad) + self._akm.show() + def _show_preferences(self): """ SLOT @@ -1522,6 +1540,7 @@ class MainWindow(QtGui.QMainWindow): """ self._soledad_bootstrapper.cancel_bootstrap() + setProxiedObject(self._soledad, None) # XXX: If other defers are doing authenticated stuff, this # might conflict with those. CHECK! diff --git a/src/leap/bitmask/gui/ui/mainwindow.ui b/src/leap/bitmask/gui/ui/mainwindow.ui index badd291d..3b83788e 100644 --- a/src/leap/bitmask/gui/ui/mainwindow.ui +++ b/src/leap/bitmask/gui/ui/mainwindow.ui @@ -75,7 +75,7 @@ 0 0 524 - 636 + 651 @@ -380,7 +380,7 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb 0 0 524 - 22 + 21 @@ -388,6 +388,7 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb &Bitmask + @@ -439,6 +440,14 @@ background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgb Create a new account... + + + true + + + Advanced Key Management + + -- cgit v1.2.3