From 7e0c87218c64eb64d6d29e2dcbe34cb36de6ff50 Mon Sep 17 00:00:00 2001
From: Alexandre Petit <62973006+AlexpFr@users.noreply.github.com>
Date: Sat, 27 Apr 2024 23:22:08 +0200
Subject: [PATCH] SSH Agent: Add ssh-add -D function (#8346)
---
src/gui/DatabaseWidget.cpp | 10 ++++++
src/gui/DatabaseWidget.h | 1 +
src/gui/MainWindow.cpp | 6 ++++
src/gui/MainWindow.ui | 12 +++++++
src/gui/entry/EditEntryWidget.cpp | 12 +++++++
src/gui/entry/EditEntryWidget.h | 1 +
src/gui/entry/EditEntryWidgetSSHAgent.ui | 9 ++++-
src/sshagent/SSHAgent.cpp | 42 ++++++++++++++++++++++++
src/sshagent/SSHAgent.h | 3 ++
9 files changed, 95 insertions(+), 1 deletion(-)
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index 5e7f0c4b0a..46fb9eb893 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -810,6 +810,16 @@ void DatabaseWidget::removeFromAgent()
m_messageWidget->showMessage(settings.errorString(), MessageWidget::Error);
}
}
+
+void DatabaseWidget::flushSSHAgent()
+{
+ SSHAgent* agent = SSHAgent::instance();
+ if (!agent->flushAllAgentIdentities()) {
+ showMessage(agent->errorString(), MessageWidget::Error);
+ } else {
+ showMessage(agent->errorString(), MessageWidget::Positive);
+ }
+}
#endif
void DatabaseWidget::performAutoType(const QString& sequence)
diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h
index 6812600092..1b226818c5 100644
--- a/src/gui/DatabaseWidget.h
+++ b/src/gui/DatabaseWidget.h
@@ -186,6 +186,7 @@ public slots:
#ifdef WITH_XC_SSHAGENT
void addToAgent();
void removeFromAgent();
+ void flushSSHAgent();
#endif
void performAutoType(const QString& sequence = {});
void performAutoTypeUsername();
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index c89e08f0b9..8147c40b97 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -398,6 +398,7 @@ MainWindow::MainWindow()
m_ui->actionSettings->setIcon(icons()->icon("configure"));
m_ui->actionPasswordGenerator->setIcon(icons()->icon("password-generator"));
+ m_ui->actionFlushSSHAgent->setIcon(icons()->icon("utilities-terminal"));
m_ui->actionAbout->setIcon(icons()->icon("help-about"));
m_ui->actionDonate->setIcon(icons()->icon("donate"));
@@ -509,6 +510,7 @@ MainWindow::MainWindow()
#ifdef WITH_XC_SSHAGENT
m_actionMultiplexer.connect(m_ui->actionEntryAddToAgent, SIGNAL(triggered()), SLOT(addToAgent()));
m_actionMultiplexer.connect(m_ui->actionEntryRemoveFromAgent, SIGNAL(triggered()), SLOT(removeFromAgent()));
+ m_actionMultiplexer.connect(m_ui->actionFlushSSHAgent, SIGNAL(triggered()), SLOT(flushSSHAgent()));
#endif
m_actionMultiplexer.connect(m_ui->actionGroupNew, SIGNAL(triggered()), SLOT(createGroup()));
@@ -967,6 +969,8 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode)
m_ui->actionEntryAddToAgent->setEnabled(singleEntryHasSshKey);
m_ui->actionEntryRemoveFromAgent->setVisible(singleEntryHasSshKey);
m_ui->actionEntryRemoveFromAgent->setEnabled(singleEntryHasSshKey);
+ m_ui->actionFlushSSHAgent->setVisible(true);
+ m_ui->actionFlushSSHAgent->setEnabled(true);
#endif
m_searchWidgetAction->setEnabled(true);
@@ -1601,6 +1605,7 @@ void MainWindow::agentEnabled(bool enabled)
{
m_ui->actionEntryAddToAgent->setVisible(enabled);
m_ui->actionEntryRemoveFromAgent->setVisible(enabled);
+ m_ui->actionFlushSSHAgent->setVisible(enabled);
}
void MainWindow::showEntryContextMenu(const QPoint& globalPos)
@@ -2110,6 +2115,7 @@ void MainWindow::initActionCollection()
m_ui->actionGroupEmptyRecycleBin,
// Tools Menu
m_ui->actionPasswordGenerator,
+ m_ui->actionFlushSSHAgent,
m_ui->actionSettings,
// View Menu
m_ui->actionThemeAuto,
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index 69606b856e..2ebfc98ce3 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -364,6 +364,7 @@
&Tools
+
diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp
index 6620b08077..e2cd866480 100644
--- a/src/gui/entry/EditEntryWidget.cpp
+++ b/src/gui/entry/EditEntryWidget.cpp
@@ -565,6 +565,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->flushAgentButton, &QPushButton::clicked, this, &EditEntryWidget::flushAgent);
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);
@@ -684,6 +685,7 @@ void EditEntryWidget::updateSSHAgentKeyInfo()
if (sshAgent()->isAgentRunning()) {
m_sshAgentUi->addToAgentButton->setEnabled(true);
m_sshAgentUi->removeFromAgentButton->setEnabled(true);
+ m_sshAgentUi->flushAgentButton->setEnabled(true);
sshAgent()->setAutoRemoveOnLock(key, m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked());
}
@@ -786,6 +788,16 @@ void EditEntryWidget::removeKeyFromAgent()
}
}
+void EditEntryWidget::flushAgent()
+{
+ if (!sshAgent()->flushAllAgentIdentities()) {
+ showMessage(sshAgent()->errorString(), MessageWidget::Error);
+ return;
+ }
+
+ showMessage(sshAgent()->errorString(), MessageWidget::Positive);
+}
+
void EditEntryWidget::decryptPrivateKey()
{
OpenSSHKey key;
diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h
index 0507b5dfbc..050eea7a2f 100644
--- a/src/gui/entry/EditEntryWidget.h
+++ b/src/gui/entry/EditEntryWidget.h
@@ -122,6 +122,7 @@ private slots:
void browsePrivateKey();
void addKeyToAgent();
void removeKeyFromAgent();
+ void flushAgent();
void decryptPrivateKey();
void copyPublicKey();
void generatePrivateKey();
diff --git a/src/gui/entry/EditEntryWidgetSSHAgent.ui b/src/gui/entry/EditEntryWidgetSSHAgent.ui
index 3fa48baf33..faa6d62ef9 100644
--- a/src/gui/entry/EditEntryWidgetSSHAgent.ui
+++ b/src/gui/entry/EditEntryWidgetSSHAgent.ui
@@ -139,7 +139,7 @@
-
-
+
-
@@ -154,6 +154,13 @@
+ -
+
+
+ Flush agent
+
+
+
-
diff --git a/src/sshagent/SSHAgent.cpp b/src/sshagent/SSHAgent.cpp
index 5c423cc755..5e8514c412 100644
--- a/src/sshagent/SSHAgent.cpp
+++ b/src/sshagent/SSHAgent.cpp
@@ -363,6 +363,48 @@ bool SSHAgent::removeIdentity(OpenSSHKey& key)
return sendMessage(requestData, responseData);
}
+/**
+ * Flush 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::flushAllAgentIdentities()
+{
+ if (!isAgentRunning()) {
+ m_error = tr("No agent running, cannot remove identity.");
+ return false;
+ }
+
+ bool ret = true;
+ QByteArray requestData;
+ QByteArray responseData;
+ BinaryStream request(&requestData);
+
+ // Same request order as OpenBSD ssh-add: useful?
+ 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();
+
+ // Same request order as OpenBSD ssh-add: useful?
+ 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 8ef6173a64..eeb3bda103 100644
--- a/src/sshagent/SSHAgent.h
+++ b/src/sshagent/SSHAgent.h
@@ -56,6 +56,7 @@ class SSHAgent : public QObject
bool checkIdentity(const OpenSSHKey& key, bool& loaded);
bool removeIdentity(OpenSSHKey& key);
void removeAllIdentities();
+ bool flushAllAgentIdentities();
void setAutoRemoveOnLock(const OpenSSHKey& key, bool autoRemove);
signals:
@@ -74,6 +75,8 @@ public slots:
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;