diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index 1bc3afec6..a712f32f1 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -3410,6 +3410,10 @@ Would you like to correct it?
+
+
+
+
EditGroupWidget
@@ -6288,6 +6292,14 @@ Expect some bugs and minor issues, this version is meant for testing purposes.
+
+
+
+
+
+
+
+
ManageDatabase
@@ -9811,6 +9823,14 @@ This option is deprecated, use --set-key-file instead.
+
+
+
+
+
+
+
+
SearchHelpWidget
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 563f20a46..0182121fa 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -211,7 +211,10 @@ MainWindow::MainWindow()
#ifdef WITH_XC_SSHAGENT
connect(sshAgent(), SIGNAL(error(QString)), this, SLOT(showErrorMessage(QString)));
connect(sshAgent(), SIGNAL(enabledChanged(bool)), this, SLOT(agentEnabled(bool)));
+ connect(m_ui->actionClearSSHAgent, SIGNAL(triggered()), SLOT(clearSSHAgent()));
m_ui->settingsWidget->addSettingsPage(new AgentSettingsPage());
+#else
+ agentEnabled(false);
#endif
#if defined(WITH_XC_KEESHARE)
@@ -414,6 +417,7 @@ MainWindow::MainWindow()
m_ui->actionSettings->setIcon(icons()->icon("configure"));
m_ui->actionPasswordGenerator->setIcon(icons()->icon("password-generator"));
+ m_ui->actionClearSSHAgent->setIcon(icons()->icon("utilities-terminal"));
m_ui->actionAbout->setIcon(icons()->icon("help-about"));
m_ui->actionDonate->setIcon(icons()->icon("donate"));
@@ -970,6 +974,8 @@ void MainWindow::updateMenuActionState()
m_ui->actionEntryAddToAgent->setEnabled(hasSSHKey);
m_ui->actionEntryRemoveFromAgent->setVisible(hasSSHKey);
m_ui->actionEntryRemoveFromAgent->setEnabled(hasSSHKey);
+ m_ui->actionClearSSHAgent->setVisible(sshAgent()->isEnabled());
+ m_ui->actionClearSSHAgent->setEnabled(sshAgent()->isEnabled());
#endif
m_ui->actionGroupNew->setEnabled(groupSelected && !inRecycleBin);
@@ -1460,6 +1466,15 @@ void MainWindow::disableMenuAndToolbar()
m_ui->menubar->setDisabled(true);
}
+void MainWindow::clearSSHAgent()
+{
+#ifdef WITH_XC_SSHAGENT
+ auto agent = SSHAgent::instance();
+ auto ret = agent->clearAllAgentIdentities();
+ displayGlobalMessage(agent->errorString(), ret ? MessageWidget::Positive : KMessageWidget::Error, false);
+#endif
+}
+
void MainWindow::saveWindowInformation()
{
if (isVisible()) {
@@ -1585,6 +1600,8 @@ void MainWindow::agentEnabled(bool enabled)
{
m_ui->actionEntryAddToAgent->setVisible(enabled);
m_ui->actionEntryRemoveFromAgent->setVisible(enabled);
+ m_ui->actionClearSSHAgent->setEnabled(enabled);
+ m_ui->actionClearSSHAgent->setVisible(enabled);
}
void MainWindow::showEntryContextMenu(const QPoint& globalPos)
@@ -2078,6 +2095,7 @@ void MainWindow::initActionCollection()
m_ui->actionGroupEmptyRecycleBin,
// Tools Menu
m_ui->actionPasswordGenerator,
+ m_ui->actionClearSSHAgent,
m_ui->actionSettings,
// View Menu
m_ui->actionThemeAuto,
diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
index b607a4566..ecd98e03a 100644
--- a/src/gui/MainWindow.h
+++ b/src/gui/MainWindow.h
@@ -155,6 +155,7 @@ private slots:
void focusSearchWidget();
void enableMenuAndToolbar();
void disableMenuAndToolbar();
+ void clearSSHAgent();
private:
static const QString BaseWindowTitle;
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index c84727c3e..fc4c0b9d5 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -369,6 +369,7 @@
&Tools
+
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 9af9aa601..d2213a669 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -606,6 +606,7 @@ void EditEntryWidget::setupSSHAgent()
connect(m_sshAgentUi->browseButton, &QPushButton::clicked, this, &EditEntryWidget::browsePrivateKey);
connect(m_sshAgentUi->addToAgentButton, &QPushButton::clicked, this, &EditEntryWidget::addKeyToAgent);
connect(m_sshAgentUi->removeFromAgentButton, &QPushButton::clicked, this, &EditEntryWidget::removeKeyFromAgent);
+ connect(m_sshAgentUi->clearAgentButton, &QPushButton::clicked, this, &EditEntryWidget::clearAgent);
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);
@@ -719,6 +720,7 @@ void EditEntryWidget::updateSSHAgentKeyInfo()
if (sshAgent()->isAgentRunning()) {
m_sshAgentUi->addToAgentButton->setEnabled(true);
m_sshAgentUi->removeFromAgentButton->setEnabled(true);
+ m_sshAgentUi->clearAgentButton->setEnabled(true);
sshAgent()->setAutoRemoveOnLock(key, m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked());
}
@@ -821,6 +823,12 @@ void EditEntryWidget::removeKeyFromAgent()
}
}
+void EditEntryWidget::clearAgent()
+{
+ auto ret = sshAgent()->clearAllAgentIdentities();
+ showMessage(sshAgent()->errorString(), ret ? MessageWidget::Positive : KMessageWidget::Error);
+}
+
void EditEntryWidget::decryptPrivateKey()
{
OpenSSHKey key;
diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h
index 323a85b8f..3fce4d56d 100644
--- a/src/gui/entry/EditEntryWidget.h
+++ b/src/gui/entry/EditEntryWidget.h
@@ -135,6 +135,7 @@ private slots:
void browsePrivateKey();
void addKeyToAgent();
void removeKeyFromAgent();
+ void clearAgent();
void decryptPrivateKey();
void copyPublicKey();
void generatePrivateKey();
diff --git a/src/gui/entry/EditEntryWidgetSSHAgent.ui b/src/gui/entry/EditEntryWidgetSSHAgent.ui
index 3fa48baf3..3215c1a27 100644
--- a/src/gui/entry/EditEntryWidgetSSHAgent.ui
+++ b/src/gui/entry/EditEntryWidgetSSHAgent.ui
@@ -139,7 +139,7 @@
-
-
+
-
@@ -154,6 +154,13 @@
+ -
+
+
+ Clear agent
+
+
+
-
diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp
index 5c423cc75..a8aa695ce 100644
--- a/src/sshagent/SSHAgent.cpp
+++ b/src/sshagent/SSHAgent.cpp
@@ -363,6 +363,48 @@ bool SSHAgent::removeIdentity(OpenSSHKey& key)
return sendMessage(requestData, responseData);
}
+/**
+ * Remove all identities from the SSH agent.
+ *
+ * Since the agent might be forwarded, old or non-OpenSSH, when asked
+ * to remove all keys, attempt to remove both protocol v.1 and v.2
+ * keys.
+ *
+ * @return true on success
+ */
+bool SSHAgent::clearAllAgentIdentities()
+{
+ if (!isAgentRunning()) {
+ m_error = tr("No agent running, cannot remove identity.");
+ return false;
+ }
+
+ bool ret = true;
+ QByteArray requestData;
+ QByteArray responseData;
+ BinaryStream request(&requestData);
+
+ // SSH2 Identity Removal
+ request.write(SSH2_AGENTC_REMOVE_ALL_IDENTITIES);
+
+ if (!sendMessage(requestData, responseData)) {
+ m_error = tr("Failed to remove all SSH identities from agent.");
+ ret = false;
+ }
+
+ request.flush();
+ responseData.clear();
+
+ // SSH1 Identity Removal
+ request.write(SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES);
+
+ // ignore error-code for ssh1
+ sendMessage(requestData, responseData);
+
+ m_error = tr("All SSH identities removed from agent.");
+ return ret;
+}
+
/**
* Get a list of identities from the SSH agent.
*
diff --git a/src/sshagent/SSHAgent.h b/src/sshagent/SSHAgent.h
index 8ef6173a6..d3eeb4ebc 100644
--- a/src/sshagent/SSHAgent.h
+++ b/src/sshagent/SSHAgent.h
@@ -56,6 +56,7 @@ public:
bool checkIdentity(const OpenSSHKey& key, bool& loaded);
bool removeIdentity(OpenSSHKey& key);
void removeAllIdentities();
+ bool clearAllAgentIdentities();
void setAutoRemoveOnLock(const OpenSSHKey& key, bool autoRemove);
signals:
@@ -74,6 +75,8 @@ private:
const quint8 SSH_AGENTC_ADD_IDENTITY = 17;
const quint8 SSH_AGENTC_REMOVE_IDENTITY = 18;
const quint8 SSH_AGENTC_ADD_ID_CONSTRAINED = 25;
+ const quint8 SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES = 9;
+ const quint8 SSH2_AGENTC_REMOVE_ALL_IDENTITIES = 19;
const quint8 SSH_AGENT_CONSTRAIN_LIFETIME = 1;
const quint8 SSH_AGENT_CONSTRAIN_CONFIRM = 2;