diff options
-rw-r--r-- | src/leap/bitmask/gui/advanced_key_management.py | 185 | ||||
-rw-r--r-- | src/leap/bitmask/gui/ui/advanced_key_management.ui | 153 |
2 files changed, 338 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>. +""" +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("<span style='color:#0000FF;'>NOTE</span>: " + "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( + "<span style='color:#ff0000;'>WARNING</span>:<br>" + "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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AdvancedKeyManagement</class> + <widget class="QWidget" name="AdvancedKeyManagement"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>431</width> + <height>188</height> + </rect> + </property> + <property name="windowTitle"> + <string>Advanced Key Management</string> + </property> + <property name="windowIcon"> + <iconset resource="../../../../../data/resources/mainwindow.qrc"> + <normaloff>:/images/mask-icon.png</normaloff>:/images/mask-icon.png</iconset> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QWidget" name="container" native="true"> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>User:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="leUser"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>user_name@provider</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Key ID:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="leKeyID"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>key ID</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Key fingerprint:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="leFingerprint"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>fingerprint</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="4" column="0" colspan="2"> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="1"> + <widget class="QPushButton" name="pbExportKeys"> + <property name="text"> + <string>Export current key pair</string> + </property> + </widget> + </item> + <item row="1" column="0" rowspan="2"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="pbImportKeys"> + <property name="text"> + <string>Import custom key pair</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="lblStatus"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../../../../../data/resources/mainwindow.qrc"/> + </resources> + <connections/> +</ui> |