mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2026-03-11 08:54:48 +00:00
Merge 0cb2caa146 into a1cddad37c
This commit is contained in:
commit
48bde4f0ec
10 changed files with 783 additions and 225 deletions
|
|
@ -177,4 +177,10 @@ If you chose to not autoload the key on database unlock, you can manually make t
|
||||||
|
|
||||||
.SSH Agent Load Key from Context Menu
|
.SSH Agent Load Key from Context Menu
|
||||||
image::sshagent_context_menu.png[]
|
image::sshagent_context_menu.png[]
|
||||||
|
|
||||||
|
==== Associate certificate to SSH key
|
||||||
|
If you have an externally generated OpenSSH certificate file associated with your SSH key, you can configure it in the "Certificate" tab.
|
||||||
|
|
||||||
|
When the key is loaded, if "Use certificate" is checked, both the key and certificate are added to the agent.
|
||||||
|
|
||||||
// end::content[]
|
// end::content[]
|
||||||
|
|
|
||||||
|
|
@ -3095,6 +3095,10 @@ Would you like to correct it?</source>
|
||||||
<source>Failed to decrypt SSH key, ensure password is correct.</source>
|
<source>Failed to decrypt SSH key, ensure password is correct.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Select certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>EditEntryWidgetAdvanced</name>
|
<name>EditEntryWidgetAdvanced</name>
|
||||||
|
|
@ -3528,6 +3532,14 @@ Would you like to correct it?</source>
|
||||||
<source>Clear agent</source>
|
<source>Clear agent</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Use certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>EditGroupWidget</name>
|
<name>EditGroupWidget</name>
|
||||||
|
|
@ -5347,6 +5359,22 @@ Line %2, column %3</source>
|
||||||
<source>Failed to open private key</source>
|
<source>Failed to open private key</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Certificate is an attachment but no attachments provided.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Certificate is empty</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>File too large to be a certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Failed to open certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>KeePass1Reader</name>
|
<name>KeePass1Reader</name>
|
||||||
|
|
@ -6844,6 +6872,18 @@ Expect some bugs and minor issues, this version is meant for testing purposes.</
|
||||||
<source>Failed to read public key: %1</source>
|
<source>Failed to read public key: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Invalid or unsupported certificate file</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Can't write certificate as it is empty</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unexpected EOF when writing certificate</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>OpenSSHKeyGenDialog</name>
|
<name>OpenSSHKeyGenDialog</name>
|
||||||
|
|
@ -10043,6 +10083,14 @@ This option is deprecated, use --set-key-file instead.</source>
|
||||||
<source>All SSH identities removed from agent.</source>
|
<source>All SSH identities removed from agent.</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Agent refused this identity certificate. Possible reasons include:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Invalid or empty certificate.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SearchHelpWidget</name>
|
<name>SearchHelpWidget</name>
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
#include "core/PasswordGenerator.h"
|
#include "core/PasswordGenerator.h"
|
||||||
#include "core/TimeDelta.h"
|
#include "core/TimeDelta.h"
|
||||||
#ifdef WITH_XC_SSHAGENT
|
#ifdef WITH_XC_SSHAGENT
|
||||||
|
#include <QSignalBlocker>
|
||||||
#include "sshagent/OpenSSHKey.h"
|
#include "sshagent/OpenSSHKey.h"
|
||||||
#include "sshagent/OpenSSHKeyGenDialog.h"
|
#include "sshagent/OpenSSHKeyGenDialog.h"
|
||||||
#include "sshagent/SSHAgent.h"
|
#include "sshagent/SSHAgent.h"
|
||||||
|
|
@ -544,6 +545,12 @@ void EditEntryWidget::setupEntryUpdate()
|
||||||
connect(m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setModified()));
|
connect(m_sshAgentUi->requireUserConfirmationCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setModified()));
|
||||||
connect(m_sshAgentUi->lifetimeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setModified()));
|
connect(m_sshAgentUi->lifetimeCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setModified()));
|
||||||
connect(m_sshAgentUi->lifetimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setModified()));
|
connect(m_sshAgentUi->lifetimeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->attachmentCertificateRadioButton, SIGNAL(toggled(bool)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->externalCertificateFileRadioButton, SIGNAL(toggled(bool)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->attachmentCertificateComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->attachmentCertificateComboBox, SIGNAL(editTextChanged(QString)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->externalCertificateFileEdit, SIGNAL(textChanged(QString)), this, SLOT(setModified()));
|
||||||
|
connect(m_sshAgentUi->addCertificateToAgentCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setModified()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -621,6 +628,15 @@ void EditEntryWidget::setupSSHAgent()
|
||||||
connect(m_sshAgentUi->decryptButton, &QPushButton::clicked, this, &EditEntryWidget::decryptPrivateKey);
|
connect(m_sshAgentUi->decryptButton, &QPushButton::clicked, this, &EditEntryWidget::decryptPrivateKey);
|
||||||
connect(m_sshAgentUi->copyToClipboardButton, &QPushButton::clicked, this, &EditEntryWidget::copyPublicKey);
|
connect(m_sshAgentUi->copyToClipboardButton, &QPushButton::clicked, this, &EditEntryWidget::copyPublicKey);
|
||||||
connect(m_sshAgentUi->generateButton, &QPushButton::clicked, this, &EditEntryWidget::generatePrivateKey);
|
connect(m_sshAgentUi->generateButton, &QPushButton::clicked, this, &EditEntryWidget::generatePrivateKey);
|
||||||
|
connect(m_sshAgentUi->attachmentCertificateRadioButton, &QRadioButton::clicked,
|
||||||
|
this, &EditEntryWidget::updateSSHAgentKeyInfo);
|
||||||
|
connect(m_sshAgentUi->attachmentCertificateComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||||
|
this, &EditEntryWidget::updateSSHAgentAttachmentCertificate);
|
||||||
|
connect(m_sshAgentUi->externalCertificateFileRadioButton, &QRadioButton::clicked,
|
||||||
|
this, &EditEntryWidget::updateSSHAgentKeyInfo);
|
||||||
|
connect(m_sshAgentUi->externalCertificateFileEdit, &QLineEdit::textChanged,
|
||||||
|
this, &EditEntryWidget::updateSSHAgentKeyInfo);
|
||||||
|
connect(m_sshAgentUi->browseCertificateButton, &QPushButton::clicked, this, &EditEntryWidget::browseCertificate);
|
||||||
|
|
||||||
connect(m_attachments.data(), &EntryAttachments::modified,
|
connect(m_attachments.data(), &EntryAttachments::modified,
|
||||||
this, &EditEntryWidget::updateSSHAgentAttachments);
|
this, &EditEntryWidget::updateSSHAgentAttachments);
|
||||||
|
|
@ -636,10 +652,14 @@ void EditEntryWidget::setSSHAgentSettings()
|
||||||
m_sshAgentUi->requireUserConfirmationCheckBox->setChecked(m_sshAgentSettings.useConfirmConstraintWhenAdding());
|
m_sshAgentUi->requireUserConfirmationCheckBox->setChecked(m_sshAgentSettings.useConfirmConstraintWhenAdding());
|
||||||
m_sshAgentUi->lifetimeCheckBox->setChecked(m_sshAgentSettings.useLifetimeConstraintWhenAdding());
|
m_sshAgentUi->lifetimeCheckBox->setChecked(m_sshAgentSettings.useLifetimeConstraintWhenAdding());
|
||||||
m_sshAgentUi->lifetimeSpinBox->setValue(m_sshAgentSettings.lifetimeConstraintDuration());
|
m_sshAgentUi->lifetimeSpinBox->setValue(m_sshAgentSettings.lifetimeConstraintDuration());
|
||||||
|
QSignalBlocker sshAgent_attachmentComboBox_Blocker(m_sshAgentUi->attachmentComboBox);
|
||||||
m_sshAgentUi->attachmentComboBox->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->addCertificateToAgentCheckBox->setChecked(m_sshAgentSettings.useCertificate());
|
||||||
|
QSignalBlocker sshAgent_attachmentCertificateComboBox_Blocker(m_sshAgentUi->attachmentCertificateComboBox);
|
||||||
|
m_sshAgentUi->attachmentCertificateComboBox->clear(); // AlexpFr: why? attachmentCertificateComboBox init in updateSSHAgentAttachments(
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditEntryWidget::updateSSHAgent()
|
void EditEntryWidget::updateSSHAgent()
|
||||||
|
|
@ -672,18 +692,25 @@ void EditEntryWidget::updateSSHAgentAttachments()
|
||||||
setSSHAgentSettings();
|
setSSHAgentSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSignalBlocker sshAgent_attachmentComboBox_Blocker(m_sshAgentUi->attachmentComboBox);
|
||||||
m_sshAgentUi->attachmentComboBox->clear();
|
m_sshAgentUi->attachmentComboBox->clear();
|
||||||
m_sshAgentUi->attachmentComboBox->addItem("");
|
m_sshAgentUi->attachmentComboBox->addItem("");
|
||||||
|
|
||||||
|
QSignalBlocker sshAgent_attachmentCertificateComboBox_Blocker(m_sshAgentUi->attachmentCertificateComboBox);
|
||||||
|
m_sshAgentUi->attachmentCertificateComboBox->clear();
|
||||||
|
m_sshAgentUi->attachmentCertificateComboBox->addItem("");
|
||||||
|
|
||||||
for (const QString& fileName : m_attachments->keys()) {
|
for (const QString& fileName : m_attachments->keys()) {
|
||||||
if (fileName == "KeeAgent.settings") {
|
if (fileName == "KeeAgent.settings") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sshAgentUi->attachmentComboBox->addItem(fileName);
|
m_sshAgentUi->attachmentComboBox->addItem(fileName);
|
||||||
|
m_sshAgentUi->attachmentCertificateComboBox->addItem(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sshAgentUi->attachmentComboBox->setCurrentText(m_sshAgentSettings.attachmentName());
|
m_sshAgentUi->attachmentComboBox->setCurrentText(m_sshAgentSettings.attachmentName());
|
||||||
|
QSignalBlocker sshAgent_externalFileEdit_Blocker(m_sshAgentUi->externalFileEdit);
|
||||||
m_sshAgentUi->externalFileEdit->setText(m_sshAgentSettings.fileName());
|
m_sshAgentUi->externalFileEdit->setText(m_sshAgentSettings.fileName());
|
||||||
|
|
||||||
if (m_sshAgentSettings.selectedType() == "attachment") {
|
if (m_sshAgentSettings.selectedType() == "attachment") {
|
||||||
|
|
@ -692,6 +719,16 @@ void EditEntryWidget::updateSSHAgentAttachments()
|
||||||
m_sshAgentUi->externalFileRadioButton->setChecked(true);
|
m_sshAgentUi->externalFileRadioButton->setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_sshAgentUi->attachmentCertificateComboBox->setCurrentText(m_sshAgentSettings.attachmentNameCertificate());
|
||||||
|
QSignalBlocker sshAgent_externalCertificateFileEdit_Blocker(m_sshAgentUi->externalCertificateFileEdit);
|
||||||
|
m_sshAgentUi->externalCertificateFileEdit->setText(m_sshAgentSettings.fileNameCertificate());
|
||||||
|
|
||||||
|
if (m_sshAgentSettings.selectedCertificateType() == "attachment") {
|
||||||
|
m_sshAgentUi->attachmentCertificateRadioButton->setChecked(true);
|
||||||
|
} else {
|
||||||
|
m_sshAgentUi->externalCertificateFileRadioButton->setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
updateSSHAgentKeyInfo();
|
updateSSHAgentKeyInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -758,6 +795,14 @@ void EditEntryWidget::toKeeAgentSettings(KeeAgentSettings& settings) const
|
||||||
|
|
||||||
// we don't use this either but we don't want it to dirty flag the config
|
// we don't use this either but we don't want it to dirty flag the config
|
||||||
settings.setSaveAttachmentToTempFile(m_sshAgentSettings.saveAttachmentToTempFile());
|
settings.setSaveAttachmentToTempFile(m_sshAgentSettings.saveAttachmentToTempFile());
|
||||||
|
|
||||||
|
settings.setUseCertificate(m_sshAgentUi->addCertificateToAgentCheckBox->isChecked());
|
||||||
|
settings.setSelectedCertificateType(m_sshAgentUi->attachmentCertificateRadioButton->isChecked() ? "attachment" : "file");
|
||||||
|
settings.setAttachmentCertificateName(m_sshAgentUi->attachmentCertificateComboBox->currentText());
|
||||||
|
settings.setFileNameCertificate(m_sshAgentUi->externalCertificateFileEdit->text());
|
||||||
|
|
||||||
|
// we don't use this either but we don't want it to dirty flag the config
|
||||||
|
settings.setSaveAttachmentCertificateToTempFile(m_sshAgentSettings.saveAttachmentCertificateToTempFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditEntryWidget::updateTotp()
|
void EditEntryWidget::updateTotp()
|
||||||
|
|
@ -820,6 +865,23 @@ void EditEntryWidget::addKeyToAgent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditEntryWidget::updateSSHAgentAttachmentCertificate()
|
||||||
|
{
|
||||||
|
m_sshAgentUi->attachmentCertificateRadioButton->setChecked(true);
|
||||||
|
updateSSHAgentKeyInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditEntryWidget::browseCertificate()
|
||||||
|
{
|
||||||
|
auto fileName = fileDialog()->getOpenFileName(this, tr("Select certificate"), FileDialog::getLastDir("sshagent"));
|
||||||
|
if (!fileName.isEmpty()) {
|
||||||
|
FileDialog::saveLastDir("sshagent", fileName);
|
||||||
|
m_sshAgentUi->externalCertificateFileEdit->setText(fileName);
|
||||||
|
m_sshAgentUi->externalCertificateFileRadioButton->setChecked(true);
|
||||||
|
updateSSHAgentKeyInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EditEntryWidget::removeKeyFromAgent()
|
void EditEntryWidget::removeKeyFromAgent()
|
||||||
{
|
{
|
||||||
OpenSSHKey key;
|
OpenSSHKey key;
|
||||||
|
|
@ -966,6 +1028,9 @@ void EditEntryWidget::loadEntry(Entry* entry,
|
||||||
|
|
||||||
void EditEntryWidget::setForms(Entry* entry, bool restore)
|
void EditEntryWidget::setForms(Entry* entry, bool restore)
|
||||||
{
|
{
|
||||||
|
#ifdef WITH_XC_SSHAGENT
|
||||||
|
QSignalBlocker attachmentsBlocker(m_attachments.data());
|
||||||
|
#endif
|
||||||
m_attachments->copyDataFrom(entry->attachments());
|
m_attachments->copyDataFrom(entry->attachments());
|
||||||
m_customData->copyDataFrom(entry->customData());
|
m_customData->copyDataFrom(entry->customData());
|
||||||
|
|
||||||
|
|
@ -1244,6 +1309,7 @@ bool EditEntryWidget::commitEntry()
|
||||||
void EditEntryWidget::acceptEntry()
|
void EditEntryWidget::acceptEntry()
|
||||||
{
|
{
|
||||||
if (commitEntry()) {
|
if (commitEntry()) {
|
||||||
|
m_sshAgentUi->privateKeyTabWidget->setCurrentIndex(0);
|
||||||
clear();
|
clear();
|
||||||
emit editFinished(true);
|
emit editFinished(true);
|
||||||
}
|
}
|
||||||
|
|
@ -1363,6 +1429,7 @@ void EditEntryWidget::cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_sshAgentUi->privateKeyTabWidget->setCurrentIndex(0);
|
||||||
clear();
|
clear();
|
||||||
emit editFinished(accepted);
|
emit editFinished(accepted);
|
||||||
}
|
}
|
||||||
|
|
@ -1382,6 +1449,9 @@ void EditEntryWidget::clear()
|
||||||
m_mainUi->notesEdit->clear();
|
m_mainUi->notesEdit->clear();
|
||||||
|
|
||||||
m_entryAttributes->clear();
|
m_entryAttributes->clear();
|
||||||
|
#ifdef WITH_XC_SSHAGENT
|
||||||
|
QSignalBlocker attachmentsBlocker(m_attachments.data());
|
||||||
|
#endif
|
||||||
m_attachments->clear();
|
m_attachments->clear();
|
||||||
m_customData->clear();
|
m_customData->clear();
|
||||||
m_autoTypeAssoc->clear();
|
m_autoTypeAssoc->clear();
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,8 @@ private slots:
|
||||||
void decryptPrivateKey();
|
void decryptPrivateKey();
|
||||||
void copyPublicKey();
|
void copyPublicKey();
|
||||||
void generatePrivateKey();
|
void generatePrivateKey();
|
||||||
|
void updateSSHAgentAttachmentCertificate();
|
||||||
|
void browseCertificate();
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_XC_BROWSER
|
#ifdef WITH_XC_BROWSER
|
||||||
void updateBrowserModified();
|
void updateBrowserModified();
|
||||||
|
|
@ -186,6 +188,8 @@ private:
|
||||||
#ifdef WITH_XC_SSHAGENT
|
#ifdef WITH_XC_SSHAGENT
|
||||||
KeeAgentSettings m_sshAgentSettings;
|
KeeAgentSettings m_sshAgentSettings;
|
||||||
QString m_pendingPrivateKey;
|
QString m_pendingPrivateKey;
|
||||||
|
QPointer<Entry> m_entryCertificate;
|
||||||
|
const QScopedPointer<EntryAttachments> m_attachmentsCertificate;
|
||||||
#endif
|
#endif
|
||||||
const QScopedPointer<Ui::EditEntryWidgetMain> m_mainUi;
|
const QScopedPointer<Ui::EditEntryWidgetMain> m_mainUi;
|
||||||
const QScopedPointer<Ui::EditEntryWidgetAdvanced> m_advancedUi;
|
const QScopedPointer<Ui::EditEntryWidgetAdvanced> m_advancedUi;
|
||||||
|
|
|
||||||
|
|
@ -26,79 +26,35 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="1" colspan="4">
|
<item row="6" column="3">
|
||||||
<widget class="QCheckBox" name="removeKeyFromAgentCheckBox">
|
<layout class="QHBoxLayout" name="agentActionsLayout" stretch="0,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>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="clearAgentButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear agent</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="requireUserConfirmationCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remove key from agent when database is closed/locked</string>
|
<string>Require user confirmation when this key is used</string>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="1">
|
|
||||||
<widget class="QLabel" name="commentLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Comment</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="4">
|
|
||||||
<widget class="QCheckBox" name="addKeyToAgentCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add key to agent when database is opened/unlocked</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="15" column="3" colspan="2">
|
|
||||||
<widget class="QPlainTextEdit" name="publicKeyEdit">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="4">
|
|
||||||
<widget class="QPushButton" name="decryptButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Decrypt</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>10</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="13" 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="16" column="3" colspan="2">
|
|
||||||
<widget class="QPushButton" name="copyToClipboardButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Copy to clipboard</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
@ -112,108 +68,7 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" colspan="4">
|
<item row="14" column="2">
|
||||||
<widget class="QGroupBox" name="privateKeyGroupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Private key</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
|
||||||
<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="3">
|
|
||||||
<widget class="QLineEdit" name="externalFileEdit">
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::ClickFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="accessibleName">
|
|
||||||
<string>External key file</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="3">
|
|
||||||
<layout class="QHBoxLayout" name="agentActionsLayout" stretch="0,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>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="clearAgentButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Clear agent</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QRadioButton" name="externalFileRadioButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>External file</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="4">
|
|
||||||
<widget class="QPushButton" name="browseButton">
|
|
||||||
<property name="accessibleName">
|
|
||||||
<string>Browser for key file</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string extracomment="Button for opening file dialog">Browse…</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QPushButton" name="generateButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Generate</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QComboBox" name="attachmentComboBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="accessibleName">
|
|
||||||
<string>Select attachment file</string>
|
|
||||||
</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="14" column="3">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="commentTextLabel">
|
<widget class="QLabel" name="commentTextLabel">
|
||||||
|
|
@ -245,7 +100,291 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" colspan="4">
|
<item row="14" column="1">
|
||||||
|
<widget class="QLabel" name="commentLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Comment</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="13" 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="15" column="2" colspan="2">
|
||||||
|
<widget class="QPlainTextEdit" name="publicKeyEdit">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Monospace</family>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="14" column="3">
|
||||||
|
<widget class="QPushButton" name="decryptButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Decrypt</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="12" column="2">
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="13" column="2" 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="0" column="1" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="addKeyToAgentCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add key to agent when database is opened/unlocked</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="removeKeyFromAgentCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove key from agent when database is closed/locked</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1" colspan="3">
|
||||||
|
<widget class="QTabWidget" name="privateKeyTabWidget">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="privateKeyTabWidgetPage1" native="true">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Private key</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="addCertificateToAgentCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use certificate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QRadioButton" name="externalFileRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>External file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="4">
|
||||||
|
<widget class="QPushButton" name="browseButton">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Browser for key file</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string extracomment="Button for opening file dialog">Browse…</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QComboBox" name="attachmentComboBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Select attachment file</string>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</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="3">
|
||||||
|
<widget class="QLineEdit" name="externalFileEdit">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>External key file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QPushButton" name="generateButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Generate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="privateKeyTabWidgetPage2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Certificate</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QRadioButton" name="attachmentCertificateRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Attachment</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="attachmentCertificateComboBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Select attachment file</string>
|
||||||
|
</property>
|
||||||
|
<property name="editable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="externalCertificateFileEdit">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>External key file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QRadioButton" name="externalCertificateFileRadioButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>External file</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QPushButton" name="browseCertificateButton">
|
||||||
|
<property name="accessibleName">
|
||||||
|
<string>Browser for key file</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string extracomment="Button for opening file dialog">Browse…</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="16" column="2" colspan="2">
|
||||||
|
<widget class="QPushButton" name="copyToClipboardButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Copy to clipboard</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" colspan="3">
|
||||||
<layout class="QHBoxLayout" name="removeKeyLayout">
|
<layout class="QHBoxLayout" name="removeKeyLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="lifetimeCheckBox">
|
<widget class="QCheckBox" name="lifetimeCheckBox">
|
||||||
|
|
@ -282,54 +421,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="13" 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="12" column="3">
|
|
||||||
<spacer name="verticalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>10</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,12 @@ bool KeeAgentSettings::operator==(const KeeAgentSettings& other) const
|
||||||
&& m_selectedType == other.m_selectedType
|
&& m_selectedType == other.m_selectedType
|
||||||
&& m_attachmentName == other.m_attachmentName
|
&& m_attachmentName == other.m_attachmentName
|
||||||
&& m_saveAttachmentToTempFile == other.m_saveAttachmentToTempFile
|
&& m_saveAttachmentToTempFile == other.m_saveAttachmentToTempFile
|
||||||
&& m_fileName == other.m_fileName);
|
&& m_fileName == other.m_fileName
|
||||||
|
&& m_selectedCertificateType == other.m_selectedCertificateType
|
||||||
|
&& m_attachmentNameCertificate == other.m_attachmentNameCertificate
|
||||||
|
&& m_saveAttachmentCertificateToTempFile == other.m_saveAttachmentCertificateToTempFile
|
||||||
|
&& m_fileNameCertificate == other.m_fileNameCertificate
|
||||||
|
&& m_useCertificate == other.m_useCertificate);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,6 +88,11 @@ void KeeAgentSettings::reset()
|
||||||
m_saveAttachmentToTempFile = false;
|
m_saveAttachmentToTempFile = false;
|
||||||
m_fileName.clear();
|
m_fileName.clear();
|
||||||
m_error.clear();
|
m_error.clear();
|
||||||
|
m_selectedCertificateType = QStringLiteral("file");
|
||||||
|
m_attachmentNameCertificate.clear();
|
||||||
|
m_saveAttachmentCertificateToTempFile = false;
|
||||||
|
m_fileNameCertificate.clear();
|
||||||
|
m_useCertificate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -200,6 +210,61 @@ void KeeAgentSettings::setFileName(const QString& fileName)
|
||||||
m_fileName = fileName;
|
m_fileName = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString KeeAgentSettings::fileNameCertificateEnvSubst(QProcessEnvironment environment) const
|
||||||
|
{
|
||||||
|
return Tools::envSubstitute(m_fileNameCertificate, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeeAgentSettings::useCertificate() const
|
||||||
|
{
|
||||||
|
return m_useCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeeAgentSettings::setUseCertificate(bool useCertificate)
|
||||||
|
{
|
||||||
|
m_useCertificate = useCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString KeeAgentSettings::selectedCertificateType() const
|
||||||
|
{
|
||||||
|
return m_selectedCertificateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString KeeAgentSettings::attachmentNameCertificate() const
|
||||||
|
{
|
||||||
|
return m_attachmentNameCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeeAgentSettings::saveAttachmentCertificateToTempFile() const
|
||||||
|
{
|
||||||
|
return m_saveAttachmentCertificateToTempFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString KeeAgentSettings::fileNameCertificate() const
|
||||||
|
{
|
||||||
|
return m_fileNameCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeeAgentSettings::setSelectedCertificateType(const QString& selectedCertificateType)
|
||||||
|
{
|
||||||
|
m_selectedCertificateType = selectedCertificateType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeeAgentSettings::setAttachmentCertificateName(const QString& attachmentCertificateName)
|
||||||
|
{
|
||||||
|
m_attachmentNameCertificate = attachmentCertificateName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeeAgentSettings::setSaveAttachmentCertificateToTempFile(bool saveAttachmentCertificateToTempFile)
|
||||||
|
{
|
||||||
|
m_saveAttachmentCertificateToTempFile = saveAttachmentCertificateToTempFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeeAgentSettings::setFileNameCertificate(const QString& fileNameCertificate)
|
||||||
|
{
|
||||||
|
m_fileNameCertificate = fileNameCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
bool KeeAgentSettings::readBool(QXmlStreamReader& reader)
|
bool KeeAgentSettings::readBool(QXmlStreamReader& reader)
|
||||||
{
|
{
|
||||||
reader.readNext();
|
reader.readNext();
|
||||||
|
|
@ -273,6 +338,29 @@ bool KeeAgentSettings::fromXml(const QByteArray& ba)
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (reader.name() == "UseCertificate") {
|
||||||
|
m_useCertificate = readBool(reader);
|
||||||
|
} else if (reader.name() == "LocationCertificate") {
|
||||||
|
while (!reader.error() && reader.readNextStartElement()) {
|
||||||
|
if (reader.name() == "SelectedCertificateType") {
|
||||||
|
reader.readNext();
|
||||||
|
m_selectedCertificateType = reader.text().toString();
|
||||||
|
reader.readNext();
|
||||||
|
} else if (reader.name() == "AttachmentCertificateName") {
|
||||||
|
reader.readNext();
|
||||||
|
m_attachmentNameCertificate = reader.text().toString();
|
||||||
|
reader.readNext();
|
||||||
|
} else if (reader.name() == "SaveAttachmentCertificateToTempFile") {
|
||||||
|
m_saveAttachmentCertificateToTempFile = readBool(reader);
|
||||||
|
} else if (reader.name() == "FileNameCertificate") {
|
||||||
|
reader.readNext();
|
||||||
|
m_fileNameCertificate = reader.text().toString();
|
||||||
|
reader.readNext();
|
||||||
|
} else {
|
||||||
|
qWarning() << "Skipping location certificate element" << reader.name();
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Skipping element" << reader.name();
|
qWarning() << "Skipping element" << reader.name();
|
||||||
reader.skipCurrentElement();
|
reader.skipCurrentElement();
|
||||||
|
|
@ -328,6 +416,27 @@ QByteArray KeeAgentSettings::toXml() const
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeEndElement(); // Location
|
writer.writeEndElement(); // Location
|
||||||
|
|
||||||
|
writer.writeTextElement("UseCertificate", m_useCertificate ? "true" : "false");
|
||||||
|
writer.writeStartElement("LocationCertificate");
|
||||||
|
|
||||||
|
writer.writeTextElement("SelectedCertificateType", m_selectedCertificateType);
|
||||||
|
|
||||||
|
if (!m_attachmentNameCertificate.isEmpty()) {
|
||||||
|
writer.writeTextElement("AttachmentCertificateName", m_attachmentNameCertificate);
|
||||||
|
} else {
|
||||||
|
writer.writeEmptyElement("AttachmentCertificateName");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeTextElement("SaveAttachmentCertificateToTempFile", m_saveAttachmentCertificateToTempFile ? "true" : "false");
|
||||||
|
|
||||||
|
if (!m_fileNameCertificate.isEmpty()) {
|
||||||
|
writer.writeTextElement("FileNameCertificate", m_fileNameCertificate);
|
||||||
|
} else {
|
||||||
|
writer.writeEmptyElement("FileNameCertificate");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeEndElement(); // LocationCertificate
|
||||||
writer.writeEndElement(); // EntrySettings
|
writer.writeEndElement(); // EntrySettings
|
||||||
writer.writeEndDocument();
|
writer.writeEndDocument();
|
||||||
|
|
||||||
|
|
@ -493,5 +602,61 @@ bool KeeAgentSettings::toOpenSSHKey(const QString& username,
|
||||||
key.setComment(QString("%1@%2").arg(username, fileName));
|
key.setComment(QString("%1@%2").arg(username, fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_useCertificate) {
|
||||||
|
QString fileCertificateName;
|
||||||
|
QByteArray certificateData;
|
||||||
|
|
||||||
|
if (m_selectedCertificateType == "attachment") {
|
||||||
|
if (!attachments) {
|
||||||
|
m_error = QCoreApplication::translate("KeeAgentSettings",
|
||||||
|
"Certificate is an attachment but no attachments provided.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileCertificateName = m_attachmentNameCertificate;
|
||||||
|
certificateData = attachments->value(fileCertificateName);
|
||||||
|
} else {
|
||||||
|
QString fileNameCertificateSubst = fileNameCertificateEnvSubst();
|
||||||
|
QFileInfo localFileCertificateInfo(fileNameCertificateSubst);
|
||||||
|
|
||||||
|
// resolve relative certificate path from database location
|
||||||
|
if (localFileCertificateInfo.isRelative()) {
|
||||||
|
QFileInfo databaseFileCertificateInfo(databasePath);
|
||||||
|
localFileCertificateInfo = QFileInfo(databaseFileCertificateInfo.absolutePath() + QDir::separator() + fileNameCertificateSubst);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileCertificateName = localFileCertificateInfo.fileName();
|
||||||
|
|
||||||
|
QFile localCertificateFile(localFileCertificateInfo.absoluteFilePath());
|
||||||
|
|
||||||
|
if (localCertificateFile.fileName().isEmpty()) {
|
||||||
|
m_error = QCoreApplication::translate("KeeAgentSettings", "Certificate is empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localCertificateFile.size() > 1024 * 1024) {
|
||||||
|
m_error = QCoreApplication::translate("KeeAgentSettings", "File too large to be a certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!localCertificateFile.open(QIODevice::ReadOnly)) {
|
||||||
|
m_error = QCoreApplication::translate("KeeAgentSettings", "Failed to open certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
certificateData = localCertificateFile.readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certificateData.isEmpty()) {
|
||||||
|
m_error = QCoreApplication::translate("KeeAgentSettings", "Certificate is empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!key.parseCertificate(certificateData)) {
|
||||||
|
m_error = key.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,19 @@ public:
|
||||||
void setSaveAttachmentToTempFile(bool);
|
void setSaveAttachmentToTempFile(bool);
|
||||||
void setFileName(const QString& fileName);
|
void setFileName(const QString& fileName);
|
||||||
|
|
||||||
|
// Certificate
|
||||||
|
const QString fileNameCertificateEnvSubst(QProcessEnvironment environment = QProcessEnvironment::systemEnvironment()) const;
|
||||||
|
bool useCertificate() const;
|
||||||
|
void setUseCertificate(bool UseCertificate);
|
||||||
|
const QString selectedCertificateType() const;
|
||||||
|
const QString attachmentNameCertificate() const;
|
||||||
|
bool saveAttachmentCertificateToTempFile() const;
|
||||||
|
const QString fileNameCertificate() const;
|
||||||
|
void setSelectedCertificateType(const QString& certificateType);
|
||||||
|
void setAttachmentCertificateName(const QString& attachmentCertificateName);
|
||||||
|
void setSaveAttachmentCertificateToTempFile(bool);
|
||||||
|
void setFileNameCertificate(const QString& fileNameCertificate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool readBool(QXmlStreamReader& reader);
|
bool readBool(QXmlStreamReader& reader);
|
||||||
int readInt(QXmlStreamReader& reader);
|
int readInt(QXmlStreamReader& reader);
|
||||||
|
|
@ -94,6 +107,13 @@ private:
|
||||||
bool m_saveAttachmentToTempFile;
|
bool m_saveAttachmentToTempFile;
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
QString m_error;
|
QString m_error;
|
||||||
|
|
||||||
|
// Certificate
|
||||||
|
bool m_useCertificate;
|
||||||
|
QString m_selectedCertificateType;
|
||||||
|
QString m_attachmentNameCertificate;
|
||||||
|
bool m_saveAttachmentCertificateToTempFile;
|
||||||
|
QString m_fileNameCertificate;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEAGENTSETTINGS_H
|
#endif // KEEAGENTSETTINGS_H
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ OpenSSHKey::OpenSSHKey(QObject* parent)
|
||||||
, m_rawPrivateData(QByteArray())
|
, m_rawPrivateData(QByteArray())
|
||||||
, m_comment(QString())
|
, m_comment(QString())
|
||||||
, m_error(QString())
|
, m_error(QString())
|
||||||
|
, m_certificateType(QString())
|
||||||
|
, m_rawCertificateData(QByteArray())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,6 +65,8 @@ OpenSSHKey::OpenSSHKey(const OpenSSHKey& other)
|
||||||
, m_rawPrivateData(other.m_rawPrivateData)
|
, m_rawPrivateData(other.m_rawPrivateData)
|
||||||
, m_comment(other.m_comment)
|
, m_comment(other.m_comment)
|
||||||
, m_error(other.m_error)
|
, m_error(other.m_error)
|
||||||
|
, m_certificateType(other.m_certificateType)
|
||||||
|
, m_rawCertificateData(other.m_rawCertificateData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,6 +86,11 @@ const QString OpenSSHKey::type() const
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString OpenSSHKey::certificateType() const
|
||||||
|
{
|
||||||
|
return m_certificateType;
|
||||||
|
}
|
||||||
|
|
||||||
const QString OpenSSHKey::fingerprint(QCryptographicHash::Algorithm algo) const
|
const QString OpenSSHKey::fingerprint(QCryptographicHash::Algorithm algo) const
|
||||||
{
|
{
|
||||||
if (m_rawPublicData.isEmpty()) {
|
if (m_rawPublicData.isEmpty()) {
|
||||||
|
|
@ -660,6 +669,76 @@ bool OpenSSHKey::writePrivate(BinaryStream& stream)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenSSHKey::parseCertificate(QByteArray& data)
|
||||||
|
{
|
||||||
|
QString stringData = QString::fromLatin1(data);
|
||||||
|
QStringList elements = stringData.split(QRegularExpression("\\s+"), QString::SkipEmptyParts);
|
||||||
|
|
||||||
|
QStringList certificateTypeList = {
|
||||||
|
"ssh-ed25519-cert-v01@openssh.com",
|
||||||
|
"ssh-rsa-cert-v01@openssh.com",
|
||||||
|
"ssh-dss-cert-v01@openssh.com",
|
||||||
|
"sk-ssh-ed25519-cert-v01@openssh.com",
|
||||||
|
"sk-ssh-rsa-cert-v01@openssh.com",
|
||||||
|
"sk-ssh-dss-cert-v01@openssh.com",
|
||||||
|
"rsa-sha2-256-cert-v01@openssh.com",
|
||||||
|
"sk-rsa-sha2-256-cert-v01@openssh.com",
|
||||||
|
"rsa-sha2-512-cert-v01@openssh.com",
|
||||||
|
"sk-rsa-sha2-512-cert-v01@openssh.com",
|
||||||
|
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||||
|
"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||||
|
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
||||||
|
"sk-ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
||||||
|
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
|
||||||
|
"sk-ecdsa-sha2-nistp521-cert-v01@openssh.com",
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!certificateTypeList.contains(elements.first())) {
|
||||||
|
m_error = tr("Invalid or unsupported certificate file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_certificateType = elements.first();
|
||||||
|
m_rawCertificateData = QByteArray::fromBase64(elements[1].toLatin1());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenSSHKey::writeCertificate(BinaryStream& stream, const bool addCertificate)
|
||||||
|
{
|
||||||
|
if (m_rawCertificateData.isEmpty()) {
|
||||||
|
m_error = tr("Can't write certificate as it is empty");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addCertificate) {
|
||||||
|
if (!stream.writeString(m_rawCertificateData)) {
|
||||||
|
m_error = tr("Unexpected EOF when writing certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.writeString(m_certificateType);
|
||||||
|
|
||||||
|
if (!stream.writeString(m_rawCertificateData)) {
|
||||||
|
m_error = tr("Unexpected EOF when writing certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream.write(m_rawPrivateData)) {
|
||||||
|
m_error = tr("Unexpected EOF when writing certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stream.writeString(m_comment)) {
|
||||||
|
m_error = tr("Unexpected EOF when writing certificate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint qHash(const OpenSSHKey& key)
|
uint qHash(const OpenSSHKey& key)
|
||||||
{
|
{
|
||||||
return qHash(key.fingerprint());
|
return qHash(key.fingerprint());
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,10 @@ public:
|
||||||
static const QString TYPE_OPENSSH_PRIVATE;
|
static const QString TYPE_OPENSSH_PRIVATE;
|
||||||
static const QString OPENSSH_CIPHER_SUFFIX;
|
static const QString OPENSSH_CIPHER_SUFFIX;
|
||||||
|
|
||||||
|
bool parseCertificate(QByteArray& data);
|
||||||
|
bool writeCertificate(BinaryStream& stream, const bool addCertificate = true);
|
||||||
|
const QString certificateType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum KeyPart
|
enum KeyPart
|
||||||
{
|
{
|
||||||
|
|
@ -85,6 +89,8 @@ private:
|
||||||
QByteArray m_rawPrivateData;
|
QByteArray m_rawPrivateData;
|
||||||
QString m_comment;
|
QString m_comment;
|
||||||
QString m_error;
|
QString m_error;
|
||||||
|
QString m_certificateType;
|
||||||
|
QByteArray m_rawCertificateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint qHash(const OpenSSHKey& key);
|
uint qHash(const OpenSSHKey& key);
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,60 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, const KeeAgentSettings& settings, co
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.useCertificate()) {
|
||||||
|
QByteArray requestCertificateData;
|
||||||
|
BinaryStream requestCertificate(&requestCertificateData);
|
||||||
|
bool isSecurityCertificate = key.certificateType().startsWith("sk-");
|
||||||
|
|
||||||
|
requestCertificate.write(
|
||||||
|
(settings.useLifetimeConstraintWhenAdding() || settings.useConfirmConstraintWhenAdding() || isSecurityCertificate)
|
||||||
|
? SSH_AGENTC_ADD_ID_CONSTRAINED
|
||||||
|
: SSH_AGENTC_ADD_IDENTITY);
|
||||||
|
|
||||||
|
key.writeCertificate(requestCertificate);
|
||||||
|
|
||||||
|
if (settings.useLifetimeConstraintWhenAdding()) {
|
||||||
|
requestCertificate.write(SSH_AGENT_CONSTRAIN_LIFETIME);
|
||||||
|
requestCertificate.write(static_cast<quint32>(settings.lifetimeConstraintDuration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.useConfirmConstraintWhenAdding()) {
|
||||||
|
requestCertificate.write(SSH_AGENT_CONSTRAIN_CONFIRM);
|
||||||
|
}
|
||||||
|
|
||||||
|
// To be verified if useful with certificates
|
||||||
|
if (isSecurityCertificate) {
|
||||||
|
requestCertificate.write(SSH_AGENT_CONSTRAIN_EXTENSION);
|
||||||
|
requestCertificate.writeString(QString("sk-provider@openssh.com"));
|
||||||
|
requestCertificate.writeString(securityKeyProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray responseCertificateData;
|
||||||
|
if (!sendMessage(requestCertificateData, responseCertificateData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseCertificateData.length() < 1 || static_cast<quint8>(responseCertificateData[0]) != SSH_AGENT_SUCCESS) {
|
||||||
|
m_error =
|
||||||
|
tr("Agent refused this identity certificate. Possible reasons include:") + "\n" + tr("Invalid or empty certificate."); "\n" + tr("The key has already been added.");
|
||||||
|
|
||||||
|
if (settings.useLifetimeConstraintWhenAdding()) {
|
||||||
|
m_error += "\n" + tr("Restricted lifetime is not supported by the agent (check options).");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.useConfirmConstraintWhenAdding()) {
|
||||||
|
m_error += "\n" + tr("A confirmation request is not supported by the agent (check options).");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSecurityKey) {
|
||||||
|
m_error +=
|
||||||
|
"\n" + tr("Security keys are not supported by the agent or the security key provider is unavailable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OpenSSHKey keyCopy = key;
|
OpenSSHKey keyCopy = key;
|
||||||
keyCopy.clearPrivate();
|
keyCopy.clearPrivate();
|
||||||
m_addedKeys[keyCopy] = qMakePair(databaseUuid, settings.removeAtDatabaseClose());
|
m_addedKeys[keyCopy] = qMakePair(databaseUuid, settings.removeAtDatabaseClose());
|
||||||
|
|
@ -360,7 +414,22 @@ bool SSHAgent::removeIdentity(OpenSSHKey& key)
|
||||||
request.writeString(keyData);
|
request.writeString(keyData);
|
||||||
|
|
||||||
QByteArray responseData;
|
QByteArray responseData;
|
||||||
return sendMessage(requestData, responseData);
|
|
||||||
|
// Try to remove certificate
|
||||||
|
QByteArray requestCertificateData;
|
||||||
|
BinaryStream requestCertificate(&requestCertificateData);
|
||||||
|
|
||||||
|
QByteArray certificateData;
|
||||||
|
BinaryStream certificateStream(&certificateData);
|
||||||
|
key.writeCertificate(certificateStream, false);
|
||||||
|
|
||||||
|
requestCertificate.write(SSH_AGENTC_REMOVE_IDENTITY);
|
||||||
|
requestCertificate.write(certificateData);
|
||||||
|
|
||||||
|
QByteArray responseCertificateData;
|
||||||
|
|
||||||
|
return (sendMessage(requestData, responseData) &&
|
||||||
|
sendMessage(requestCertificateData, responseCertificateData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue