SSH Agent: Split private key selection

This commit is contained in:
Toni Spets 2017-11-25 11:12:31 +02:00
parent d2a59c556e
commit 76e6d498cf
2 changed files with 214 additions and 140 deletions

View File

@ -47,6 +47,7 @@
#include "gui/FileDialog.h" #include "gui/FileDialog.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "gui/Clipboard.h" #include "gui/Clipboard.h"
#include "gui/Font.h"
#include "gui/entry/AutoTypeAssociationsModel.h" #include "gui/entry/AutoTypeAssociationsModel.h"
#include "gui/entry/EntryAttachmentsModel.h" #include "gui/entry/EntryAttachmentsModel.h"
#include "gui/entry/EntryAttributesModel.h" #include "gui/entry/EntryAttributesModel.h"
@ -267,7 +268,15 @@ void EditEntryWidget::setupSSHAgent()
{ {
m_sshAgentUi->setupUi(m_sshAgentWidget); m_sshAgentUi->setupUi(m_sshAgentWidget);
connect(m_sshAgentUi->privateKeyComboBox, SIGNAL(currentTextChanged(QString)), SLOT(updateSSHAgentKeyInfo())); QFont fixedFont = Font::fixedFont();
m_sshAgentUi->fingerprintTextLabel->setFont(fixedFont);
m_sshAgentUi->commentTextLabel->setFont(fixedFont);
m_sshAgentUi->publicKeyEdit->setFont(fixedFont);
connect(m_sshAgentUi->attachmentRadioButton, SIGNAL(clicked(bool)), SLOT(updateSSHAgentKeyInfo()));
connect(m_sshAgentUi->attachmentComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateSSHAgentKeyInfo()));
connect(m_sshAgentUi->externalFileRadioButton, SIGNAL(clicked(bool)), SLOT(updateSSHAgentKeyInfo()));
connect(m_sshAgentUi->externalFileEdit, SIGNAL(textChanged(QString)), SLOT(updateSSHAgentKeyInfo()));
connect(m_sshAgentUi->browseButton, SIGNAL(clicked()), SLOT(browsePrivateKey())); connect(m_sshAgentUi->browseButton, SIGNAL(clicked()), SLOT(browsePrivateKey()));
connect(m_sshAgentUi->addToAgentButton, SIGNAL(clicked()), SLOT(addKeyToAgent())); connect(m_sshAgentUi->addToAgentButton, SIGNAL(clicked()), SLOT(addKeyToAgent()));
connect(m_sshAgentUi->removeFromAgentButton, SIGNAL(clicked()), SLOT(removeKeyFromAgent())); connect(m_sshAgentUi->removeFromAgentButton, SIGNAL(clicked()), SLOT(removeKeyFromAgent()));
@ -279,8 +288,6 @@ void EditEntryWidget::setupSSHAgent()
void EditEntryWidget::updateSSHAgent() void EditEntryWidget::updateSSHAgent()
{ {
// TODO: unsafe use of translations
QString prefix = tr("Attachment") + ": ";
KeeAgentSettings settings; KeeAgentSettings settings;
settings.fromXml(m_entryAttachments->value("KeeAgent.settings")); settings.fromXml(m_entryAttachments->value("KeeAgent.settings"));
@ -289,29 +296,33 @@ void EditEntryWidget::updateSSHAgent()
m_sshAgentUi->requireUserConfirmationCheckBox->setChecked(settings.useConfirmConstraintWhenAdding()); m_sshAgentUi->requireUserConfirmationCheckBox->setChecked(settings.useConfirmConstraintWhenAdding());
m_sshAgentUi->lifetimeCheckBox->setChecked(settings.useLifetimeConstraintWhenAdding()); m_sshAgentUi->lifetimeCheckBox->setChecked(settings.useLifetimeConstraintWhenAdding());
m_sshAgentUi->lifetimeSpinBox->setValue(settings.lifetimeConstraintDuration()); m_sshAgentUi->lifetimeSpinBox->setValue(settings.lifetimeConstraintDuration());
m_sshAgentUi->privateKeyComboBox->clear(); m_sshAgentUi->attachmentComboBox->clear();
m_sshAgentUi->addToAgentButton->setEnabled(false); m_sshAgentUi->addToAgentButton->setEnabled(false);
m_sshAgentUi->removeFromAgentButton->setEnabled(false); m_sshAgentUi->removeFromAgentButton->setEnabled(false);
m_sshAgentUi->copyToClipboardButton->setEnabled(false); m_sshAgentUi->copyToClipboardButton->setEnabled(false);
m_sshAgentUi->attachmentComboBox->addItem("");
for (QString fileName : m_entryAttachments->keys()) { for (QString fileName : m_entryAttachments->keys()) {
if (fileName == "KeeAgent.settings") { if (fileName == "KeeAgent.settings") {
continue; continue;
} }
m_sshAgentUi->privateKeyComboBox->addItem(prefix + fileName); m_sshAgentUi->attachmentComboBox->addItem(fileName);
} }
m_sshAgentUi->attachmentComboBox->setCurrentText(settings.attachmentName());
m_sshAgentUi->externalFileEdit->setText(settings.fileName());
if (settings.selectedType() == "attachment") { if (settings.selectedType() == "attachment") {
m_sshAgentUi->privateKeyComboBox->setCurrentText(prefix + settings.attachmentName()); m_sshAgentUi->attachmentRadioButton->setChecked(true);
} else if (!settings.fileName().isEmpty()) {
m_sshAgentUi->privateKeyComboBox->addItem(settings.fileName());
m_sshAgentUi->privateKeyComboBox->setCurrentText(settings.fileName());
} else { } else {
m_sshAgentUi->privateKeyComboBox->setCurrentText(""); m_sshAgentUi->externalFileRadioButton->setChecked(true);
} }
m_sshAgentSettings = settings; m_sshAgentSettings = settings;
updateSSHAgentKeyInfo();
} }
void EditEntryWidget::updateSSHAgentKeyInfo() void EditEntryWidget::updateSSHAgentKeyInfo()
@ -319,28 +330,24 @@ void EditEntryWidget::updateSSHAgentKeyInfo()
m_sshAgentUi->addToAgentButton->setEnabled(false); m_sshAgentUi->addToAgentButton->setEnabled(false);
m_sshAgentUi->removeFromAgentButton->setEnabled(false); m_sshAgentUi->removeFromAgentButton->setEnabled(false);
m_sshAgentUi->copyToClipboardButton->setEnabled(false); m_sshAgentUi->copyToClipboardButton->setEnabled(false);
m_sshAgentUi->fingerprintEdit->setText(""); m_sshAgentUi->fingerprintTextLabel->setText(tr("n/a"));
m_sshAgentUi->commentEdit->setText(""); m_sshAgentUi->commentTextLabel->setText(tr("n/a"));
m_sshAgentUi->decryptButton->setEnabled(false); m_sshAgentUi->decryptButton->setEnabled(false);
m_sshAgentUi->publicKeyEdit->document()->setPlainText(""); m_sshAgentUi->publicKeyEdit->document()->setPlainText("");
if (m_sshAgentUi->privateKeyComboBox->currentText().isEmpty()) {
return;
}
OpenSSHKey key; OpenSSHKey key;
if (!getOpenSSHKey(key)) { if (!getOpenSSHKey(key)) {
return; return;
} }
m_sshAgentUi->fingerprintEdit->setText(key.fingerprint()); m_sshAgentUi->fingerprintTextLabel->setText(key.fingerprint());
if (key.encrypted()) { if (key.encrypted()) {
m_sshAgentUi->commentEdit->setText(tr("(encrypted)")); m_sshAgentUi->commentTextLabel->setText(tr("(encrypted)"));
m_sshAgentUi->decryptButton->setEnabled(true); m_sshAgentUi->decryptButton->setEnabled(true);
} else { } else {
m_sshAgentUi->commentEdit->setText(key.comment()); m_sshAgentUi->commentTextLabel->setText(key.comment());
} }
m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey()); m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey());
@ -357,7 +364,7 @@ void EditEntryWidget::updateSSHAgentKeyInfo()
void EditEntryWidget::saveSSHAgentConfig() void EditEntryWidget::saveSSHAgentConfig()
{ {
KeeAgentSettings settings; KeeAgentSettings settings;
QString privateKeyPath = m_sshAgentUi->privateKeyComboBox->currentText(); QString privateKeyPath = m_sshAgentUi->attachmentComboBox->currentText();
settings.setAddAtDatabaseOpen(m_sshAgentUi->addKeyToAgentCheckBox->isChecked()); settings.setAddAtDatabaseOpen(m_sshAgentUi->addKeyToAgentCheckBox->isChecked());
settings.setRemoveAtDatabaseClose(m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked()); settings.setRemoveAtDatabaseClose(m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked());
@ -365,17 +372,13 @@ void EditEntryWidget::saveSSHAgentConfig()
settings.setUseLifetimeConstraintWhenAdding(m_sshAgentUi->lifetimeCheckBox->isChecked()); settings.setUseLifetimeConstraintWhenAdding(m_sshAgentUi->lifetimeCheckBox->isChecked());
settings.setLifetimeConstraintDuration(m_sshAgentUi->lifetimeSpinBox->value()); settings.setLifetimeConstraintDuration(m_sshAgentUi->lifetimeSpinBox->value());
// TODO: unsafe use of translations if (m_sshAgentUi->attachmentRadioButton->isChecked()) {
QString prefix = tr("Attachment") + ": ";
if (privateKeyPath.startsWith(prefix)) {
settings.setSelectedType("attachment"); settings.setSelectedType("attachment");
settings.setAttachmentName(privateKeyPath.remove(0, prefix.length()));
settings.setFileName("");
} else { } else {
settings.setSelectedType("file"); settings.setSelectedType("file");
settings.setFileName(privateKeyPath);
settings.setAttachmentName("");
} }
settings.setAttachmentName(m_sshAgentUi->attachmentComboBox->currentText());
settings.setFileName(m_sshAgentUi->externalFileEdit->text());
// we don't use this as we don't run an agent but for compatibility we set it if necessary // we don't use this as we don't run an agent but for compatibility we set it if necessary
settings.setAllowUseOfSshKey(settings.addAtDatabaseOpen() || settings.removeAtDatabaseClose()); settings.setAllowUseOfSshKey(settings.addAtDatabaseOpen() || settings.removeAtDatabaseClose());
@ -396,23 +399,22 @@ void EditEntryWidget::browsePrivateKey()
{ {
QString fileName = QFileDialog::getOpenFileName(this, tr("Select private key"), ""); QString fileName = QFileDialog::getOpenFileName(this, tr("Select private key"), "");
if (!fileName.isEmpty()) { if (!fileName.isEmpty()) {
m_sshAgentUi->privateKeyComboBox->addItem(fileName); m_sshAgentUi->externalFileEdit->setText(fileName);
m_sshAgentUi->privateKeyComboBox->setCurrentText(fileName);
} }
} }
bool EditEntryWidget::getOpenSSHKey(OpenSSHKey& key) bool EditEntryWidget::getOpenSSHKey(OpenSSHKey& key)
{ {
QString privateKeyPath = m_sshAgentUi->privateKeyComboBox->currentText();
QByteArray privateKeyData; QByteArray privateKeyData;
// TODO: unsafe use of translations if (m_sshAgentUi->attachmentRadioButton->isChecked()) {
QString prefix = tr("Attachment") + ": "; privateKeyData = m_entryAttachments->value(m_sshAgentUi->attachmentComboBox->currentText());
if (privateKeyPath.startsWith(prefix)) {
QString attachmentName = privateKeyPath.remove(0, prefix.length());
privateKeyData = m_entryAttachments->value(attachmentName);
} else { } else {
QFile localFile(privateKeyPath); QFile localFile(m_sshAgentUi->externalFileEdit->text());
if (localFile.fileName().isEmpty()) {
return false;
}
if (localFile.size() > 1024 * 1024) { if (localFile.size() > 1024 * 1024) {
showMessage(tr("File too large to be a private key"), MessageWidget::Error); showMessage(tr("File too large to be a private key"), MessageWidget::Error);
@ -427,6 +429,10 @@ bool EditEntryWidget::getOpenSSHKey(OpenSSHKey& key)
privateKeyData = localFile.readAll(); privateKeyData = localFile.readAll();
} }
if (privateKeyData.length() == 0) {
return false;
}
if (!key.parse(privateKeyData)) { if (!key.parse(privateKeyData)) {
showMessage(key.errorString(), MessageWidget::Error); showMessage(key.errorString(), MessageWidget::Error);
return false; return false;
@ -446,7 +452,7 @@ void EditEntryWidget::addKeyToAgent()
if (!key.openPrivateKey(m_entry->password())) { if (!key.openPrivateKey(m_entry->password())) {
showMessage(key.errorString(), MessageWidget::Error); showMessage(key.errorString(), MessageWidget::Error);
} else { } else {
m_sshAgentUi->commentEdit->setText(key.comment()); m_sshAgentUi->commentTextLabel->setText(key.comment());
m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey()); m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey());
} }
@ -484,7 +490,7 @@ void EditEntryWidget::decryptPrivateKey()
if (!key.openPrivateKey(m_entry->password())) { if (!key.openPrivateKey(m_entry->password())) {
showMessage(key.errorString(), MessageWidget::Error); showMessage(key.errorString(), MessageWidget::Error);
} else { } else {
m_sshAgentUi->commentEdit->setText(key.comment()); m_sshAgentUi->commentTextLabel->setText(key.comment());
m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey()); m_sshAgentUi->publicKeyEdit->document()->setPlainText(key.publicKey());
} }
} }

View File

@ -26,63 +26,6 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="removeKeyFromAgentCheckBox">
<property name="text">
<string>Remove key from agent when database is closed/locked</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="fingerprintLabel">
<property name="text">
<string>Fingerprint</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="3" colspan="2">
<widget class="QPlainTextEdit" name="publicKeyEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="10" column="3" colspan="2">
<widget class="QLineEdit" name="fingerprintEdit">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="privateKeyLabel">
<property name="text">
<string>Private key</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLabel" name="publicKeyLabel">
<property name="text">
<string>Public key</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
<item row="3" column="1" colspan="4"> <item row="3" column="1" colspan="4">
<layout class="QHBoxLayout" name="removeKeyLayout"> <layout class="QHBoxLayout" name="removeKeyLayout">
<item> <item>
@ -118,15 +61,32 @@
</layout> </layout>
</item> </item>
<item row="11" column="1"> <item row="11" column="1">
<widget class="QLabel" name="commentLabel"> <widget class="QLabel" name="fingerprintLabel">
<property name="text"> <property name="text">
<string>Comment</string> <string>Fingerprint</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1" colspan="4">
<widget class="QCheckBox" name="removeKeyFromAgentCheckBox">
<property name="text">
<string>Remove key from agent when database is closed/locked</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QLabel" name="publicKeyLabel">
<property name="text">
<string>Public key</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="4"> <item row="0" column="1" colspan="4">
<widget class="QCheckBox" name="addKeyToAgentCheckBox"> <widget class="QCheckBox" name="addKeyToAgentCheckBox">
<property name="text"> <property name="text">
@ -134,41 +94,96 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="3"> <item row="12" column="1">
<widget class="QComboBox" name="privateKeyComboBox"> <widget class="QLabel" name="commentLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="browseButton">
<property name="text"> <property name="text">
<string>Browse...</string> <string>Comment</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="4"> <item row="12" column="4">
<widget class="QCheckBox" name="requireUserConfirmationCheckBox"> <widget class="QPushButton" name="decryptButton">
<property name="text"> <property name="text">
<string>Require user confirmation when this key is used</string> <string>Decrypt</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="3" colspan="2"> <item row="11" column="3" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="fingerprintTextLabel">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
<property name="text">
<string>n/a</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="14" column="3" colspan="2">
<widget class="QPushButton" name="copyToClipboardButton"> <widget class="QPushButton" name="copyToClipboardButton">
<property name="text"> <property name="text">
<string>Copy to clipboard</string> <string>Copy to clipboard</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="3"> <item row="4" column="1" colspan="4">
<widget class="QGroupBox" name="privateKeyGroupBox">
<property name="title">
<string>Private key</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="0">
<widget class="QRadioButton" name="externalFileRadioButton">
<property name="text">
<string>External file</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QPushButton" name="browseButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="attachmentRadioButton">
<property name="text">
<string>Attachment</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="externalFileEdit"/>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="agentActionsLayout" stretch="0,0"> <layout class="QHBoxLayout" name="agentActionsLayout" stretch="0,0">
<item> <item>
<widget class="QPushButton" name="addToAgentButton"> <widget class="QPushButton" name="addToAgentButton">
@ -186,20 +201,73 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="11" column="3"> <item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="commentEdit"> <widget class="QComboBox" name="attachmentComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1" colspan="4">
<widget class="QCheckBox" name="requireUserConfirmationCheckBox">
<property name="text">
<string>Require user confirmation when this key is used</string>
</property>
</widget>
</item>
<item row="13" column="3" colspan="2">
<widget class="QPlainTextEdit" name="publicKeyEdit">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="4"> <item row="12" column="3">
<widget class="QPushButton" name="decryptButton"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="commentTextLabel">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
<property name="text"> <property name="text">
<string>Decrypt</string> <string>n/a</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<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>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>