Skip to content

Commit

Permalink
SSH Agent: Add support for certificates (keepassxreboot#5486)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexpFr committed May 5, 2024
1 parent 39be727 commit 955edeb
Show file tree
Hide file tree
Showing 9 changed files with 742 additions and 186 deletions.
52 changes: 52 additions & 0 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2669,6 +2669,10 @@ Would you like to correct it?</source>
<numerusform></numerusform>
</translation>
</message>
<message>
<source>Select certificate</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditEntryWidgetAdvanced</name>
Expand Down Expand Up @@ -3098,6 +3102,14 @@ Would you like to correct it?</source>
<source> seconds</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Use certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Certificate</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditGroupWidget</name>
Expand Down Expand Up @@ -4835,6 +4847,22 @@ Line %2, column %3</source>
<source>Failed to open private key</source>
<translation type="unfinished"></translation>
</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>
<name>KeePass1Reader</name>
Expand Down Expand Up @@ -6204,6 +6232,22 @@ We recommend you use the AppImage available on our downloads page.</source>
<source>Unexpected EOF when writing private key</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Invalid certificate file, expecting an OpenSSH certificate</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unsupported certificate file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;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>
<name>OpenSSHKeyGenDialog</name>
Expand Down Expand Up @@ -9253,6 +9297,14 @@ This option is deprecated, use --set-key-file instead.</source>
<source>No agent running, cannot list identities.</source>
<translation type="unfinished"></translation>
</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>
<name>SearchHelpWidget</name>
Expand Down
64 changes: 64 additions & 0 deletions src/gui/entry/EditEntryWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,12 @@ void EditEntryWidget::setupEntryUpdate()
connect(m_sshAgentUi->requireUserConfirmationCheckBox, 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->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

Expand Down Expand Up @@ -569,6 +575,15 @@ void EditEntryWidget::setupSSHAgent()
connect(m_sshAgentUi->decryptButton, &QPushButton::clicked, this, &EditEntryWidget::decryptPrivateKey);
connect(m_sshAgentUi->copyToClipboardButton, &QPushButton::clicked, this, &EditEntryWidget::copyPublicKey);
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,
this, &EditEntryWidget::updateSSHAgentAttachments);
Expand All @@ -591,6 +606,10 @@ void EditEntryWidget::blockSSHAgentSignals(const bool block)
m_sshAgentUi->externalFileRadioButton->blockSignals(block);
m_sshAgentUi->externalFileEdit->blockSignals(block);
m_attachments.data()->blockSignals(block);
m_sshAgentUi->attachmentCertificateRadioButton->blockSignals(block);
m_sshAgentUi->attachmentCertificateComboBox->blockSignals(block);
m_sshAgentUi->externalCertificateFileRadioButton->blockSignals(block);
m_sshAgentUi->externalCertificateFileEdit->blockSignals(block);
}

void EditEntryWidget::setSSHAgentSettings()
Expand All @@ -605,6 +624,8 @@ void EditEntryWidget::setSSHAgentSettings()
m_sshAgentUi->addToAgentButton->setEnabled(false);
m_sshAgentUi->removeFromAgentButton->setEnabled(false);
m_sshAgentUi->copyToClipboardButton->setEnabled(false);
m_sshAgentUi->addCertificateToAgentCheckBox->setChecked(m_sshAgentSettings.useCertificate()); // AlexpFr redondant ?
m_sshAgentUi->attachmentCertificateComboBox->clear(); // AlexpFr: why ?
blockSSHAgentSignals(false);
}

Expand Down Expand Up @@ -644,12 +665,16 @@ void EditEntryWidget::updateSSHAgentAttachments()
m_sshAgentUi->attachmentComboBox->clear();
m_sshAgentUi->attachmentComboBox->addItem("");

m_sshAgentUi->attachmentCertificateComboBox->clear();
m_sshAgentUi->attachmentCertificateComboBox->addItem("");

for (const QString& fileName : m_attachments->keys()) {
if (fileName == "KeeAgent.settings") {
continue;
}

m_sshAgentUi->attachmentComboBox->addItem(fileName);
m_sshAgentUi->attachmentCertificateComboBox->addItem(fileName);
}

m_sshAgentUi->attachmentComboBox->setCurrentText(m_sshAgentSettings.attachmentName());
Expand All @@ -660,6 +685,16 @@ void EditEntryWidget::updateSSHAgentAttachments()
} else {
m_sshAgentUi->externalFileRadioButton->setChecked(true);
}

m_sshAgentUi->attachmentCertificateComboBox->setCurrentText(m_sshAgentSettings.attachmentNameCertificate());
m_sshAgentUi->externalCertificateFileEdit->setText(m_sshAgentSettings.fileNameCertificate());

if (m_sshAgentSettings.selectedCertificateType() == "attachment") {
m_sshAgentUi->attachmentCertificateRadioButton->setChecked(true);
} else {
m_sshAgentUi->externalCertificateFileRadioButton->setChecked(true);
}

blockSSHAgentSignals(false);

updateSSHAgentKeyInfo();
Expand Down Expand Up @@ -736,6 +771,14 @@ void EditEntryWidget::toKeeAgentSettings(KeeAgentSettings& settings) const

// we don't use this either but we don't want it to dirty flag the config
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()
Expand Down Expand Up @@ -800,6 +843,25 @@ void EditEntryWidget::addKeyToAgent()
}
}

void EditEntryWidget::updateSSHAgentAttachmentCertificate()
{
m_sshAgentUi->attachmentCertificateRadioButton->setChecked(true);
updateSSHAgentKeyInfo();
}

void EditEntryWidget::browseCertificate()
{
blockSSHAgentSignals();
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();
}
blockSSHAgentSignals(false);
}

void EditEntryWidget::removeKeyFromAgent()
{
OpenSSHKey key;
Expand Down Expand Up @@ -1238,6 +1300,7 @@ bool EditEntryWidget::commitEntry()
void EditEntryWidget::acceptEntry()
{
if (commitEntry()) {
m_sshAgentUi->privateKeyTabWidget->setCurrentIndex(0);
clear();
emit editFinished(true);
}
Expand Down Expand Up @@ -1354,6 +1417,7 @@ void EditEntryWidget::cancel()
}
}

m_sshAgentUi->privateKeyTabWidget->setCurrentIndex(0);
clear();
emit editFinished(accepted);
}
Expand Down
4 changes: 4 additions & 0 deletions src/gui/entry/EditEntryWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ private slots:
void decryptPrivateKey();
void copyPublicKey();
void generatePrivateKey();
void updateSSHAgentAttachmentCertificate();
void browseCertificate();
#endif
#ifdef WITH_XC_BROWSER
void updateBrowserModified();
Expand Down Expand Up @@ -171,6 +173,8 @@ private slots:
#ifdef WITH_XC_SSHAGENT
KeeAgentSettings m_sshAgentSettings;
QString m_pendingPrivateKey;
QPointer<Entry> m_entryCertificate;
const QScopedPointer<EntryAttachments> m_attachmentsCertificate;
#endif
const QScopedPointer<Ui::EditEntryWidgetMain> m_mainUi;
const QScopedPointer<Ui::EditEntryWidgetAdvanced> m_advancedUi;
Expand Down
Loading

0 comments on commit 955edeb

Please sign in to comment.