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

View File

@ -26,63 +26,6 @@
<property name="bottomMargin">
<number>0</number>
</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">
<layout class="QHBoxLayout" name="removeKeyLayout">
<item>
@ -118,15 +61,32 @@
</layout>
</item>
<item row="11" column="1">
<widget class="QLabel" name="commentLabel">
<widget class="QLabel" name="fingerprintLabel">
<property name="text">
<string>Comment</string>
<string>Fingerprint</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</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">
<widget class="QCheckBox" name="addKeyToAgentCheckBox">
<property name="text">
@ -134,26 +94,129 @@
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QComboBox" name="privateKeyComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="12" column="1">
<widget class="QLabel" name="commentLabel">
<property name="text">
<string>Comment</string>
</property>
<property name="editable">
<bool>true</bool>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QPushButton" name="browseButton">
<item row="12" column="4">
<widget class="QPushButton" name="decryptButton">
<property name="text">
<string>Browse...</string>
<string>Decrypt</string>
</property>
</widget>
</item>
<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">
<property name="text">
<string>Copy to clipboard</string>
</property>
</widget>
</item>
<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">
<item>
<widget class="QPushButton" name="addToAgentButton">
<property name="text">
<string>Add to agent</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeFromAgentButton">
<property name="text">
<string>Remove from agent</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1" colspan="2">
<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">
@ -162,43 +225,48 @@
</widget>
</item>
<item row="13" column="3" colspan="2">
<widget class="QPushButton" name="copyToClipboardButton">
<property name="text">
<string>Copy to clipboard</string>
<widget class="QPlainTextEdit" name="publicKeyEdit">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
</widget>
</item>
<item row="6" column="3">
<layout class="QHBoxLayout" name="agentActionsLayout" stretch="0,0">
<item>
<widget class="QPushButton" name="addToAgentButton">
<property name="text">
<string>Add to agent</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeFromAgentButton">
<property name="text">
<string>Remove from agent</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="11" column="3">
<widget class="QLineEdit" name="commentEdit">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="11" column="4">
<widget class="QPushButton" name="decryptButton">
<property name="text">
<string>Decrypt</string>
</property>
</widget>
<item row="12" column="3">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="commentTextLabel">
<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">
<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>
</widget>