mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-05-24 17:21:15 -04:00
SSH Agent: Show error messages if something fails
This commit is contained in:
parent
4ce0005711
commit
084758908a
5 changed files with 69 additions and 13 deletions
|
@ -198,6 +198,7 @@ MainWindow::MainWindow()
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_XC_SSHAGENT
|
#ifdef WITH_XC_SSHAGENT
|
||||||
SSHAgent::init(this);
|
SSHAgent::init(this);
|
||||||
|
connect(SSHAgent::instance(), SIGNAL(error(QString)), this, SLOT(showErrorMessage(QString)));
|
||||||
m_ui->settingsWidget->addSettingsPage(new AgentSettingsPage(m_ui->tabWidget));
|
m_ui->settingsWidget->addSettingsPage(new AgentSettingsPage(m_ui->tabWidget));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -454,6 +455,11 @@ void MainWindow::showKeePassHTTPDeprecationNotice()
|
||||||
disconnect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), this, SLOT(showKeePassHTTPDeprecationNotice()));
|
disconnect(m_ui->globalMessageWidget, SIGNAL(hideAnimationFinished()), this, SLOT(showKeePassHTTPDeprecationNotice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showErrorMessage(const QString& message)
|
||||||
|
{
|
||||||
|
m_ui->globalMessageWidget->showMessage(message, MessageWidget::Error);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::appExit()
|
void MainWindow::appExit()
|
||||||
{
|
{
|
||||||
m_appExitCalled = true;
|
m_appExitCalled = true;
|
||||||
|
|
|
@ -104,6 +104,7 @@ private slots:
|
||||||
void hideTabMessage();
|
void hideTabMessage();
|
||||||
void handleScreenLock();
|
void handleScreenLock();
|
||||||
void showKeePassHTTPDeprecationNotice();
|
void showKeePassHTTPDeprecationNotice();
|
||||||
|
void showErrorMessage(const QString& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0);
|
static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0);
|
||||||
|
|
|
@ -485,7 +485,10 @@ void EditEntryWidget::addKeyToAgent()
|
||||||
lifetime = m_sshAgentUi->lifetimeSpinBox->value();
|
lifetime = m_sshAgentUi->lifetimeSpinBox->value();
|
||||||
}
|
}
|
||||||
|
|
||||||
SSHAgent::instance()->addIdentity(key, lifetime, confirm);
|
if (!SSHAgent::instance()->addIdentity(key, lifetime, confirm)) {
|
||||||
|
showMessage(SSHAgent::instance()->errorString(), MessageWidget::Error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked()) {
|
if (m_sshAgentUi->removeKeyFromAgentCheckBox->isChecked()) {
|
||||||
SSHAgent::instance()->removeIdentityAtLock(key, m_entry->uuid());
|
SSHAgent::instance()->removeIdentityAtLock(key, m_entry->uuid());
|
||||||
|
@ -496,8 +499,13 @@ void EditEntryWidget::removeKeyFromAgent()
|
||||||
{
|
{
|
||||||
OpenSSHKey key;
|
OpenSSHKey key;
|
||||||
|
|
||||||
if (getOpenSSHKey(key)) {
|
if (!getOpenSSHKey(key)) {
|
||||||
SSHAgent::instance()->removeIdentity(key);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SSHAgent::instance()->removeIdentity(key)) {
|
||||||
|
showMessage(SSHAgent::instance()->errorString(), MessageWidget::Error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,11 @@ void SSHAgent::init(QObject* parent)
|
||||||
m_instance = new SSHAgent(parent);
|
m_instance = new SSHAgent(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString SSHAgent::errorString() const
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
bool SSHAgent::isAgentRunning() const
|
bool SSHAgent::isAgentRunning() const
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
|
@ -67,7 +72,7 @@ bool SSHAgent::isAgentRunning() const
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QLocalSocket socket;
|
QLocalSocket socket;
|
||||||
|
@ -75,6 +80,7 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
|
|
||||||
socket.connectToServer(m_socketPath);
|
socket.connectToServer(m_socketPath);
|
||||||
if (!socket.waitForConnected(500)) {
|
if (!socket.waitForConnected(500)) {
|
||||||
|
m_error = tr("Agent connection failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +88,7 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
stream.flush();
|
stream.flush();
|
||||||
|
|
||||||
if (!stream.readString(out)) {
|
if (!stream.readString(out)) {
|
||||||
|
m_error = tr("Agent protocol error.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,10 +99,12 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
HWND hWnd = FindWindowA("Pageant", "Pageant");
|
HWND hWnd = FindWindowA("Pageant", "Pageant");
|
||||||
|
|
||||||
if (!hWnd) {
|
if (!hWnd) {
|
||||||
|
m_error = tr("Agent connection failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<quint32>(in.length()) > AGENT_MAX_MSGLEN - 4) {
|
if (static_cast<quint32>(in.length()) > AGENT_MAX_MSGLEN - 4) {
|
||||||
|
m_error = tr("Agent connection failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +113,7 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
HANDLE handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapName.data());
|
HANDLE handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapName.data());
|
||||||
|
|
||||||
if (!handle) {
|
if (!handle) {
|
||||||
|
m_error = tr("Agent connection failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +121,7 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
|
|
||||||
if (!ptr) {
|
if (!ptr) {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
m_error = tr("Agent connection failed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +143,11 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
if (responseLength <= AGENT_MAX_MSGLEN) {
|
if (responseLength <= AGENT_MAX_MSGLEN) {
|
||||||
out.resize(responseLength);
|
out.resize(responseLength);
|
||||||
memcpy(out.data(), requestData, responseLength);
|
memcpy(out.data(), requestData, responseLength);
|
||||||
|
} else {
|
||||||
|
m_error = tr("Agent protocol error.");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
m_error = tr("Agent protocol error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
UnmapViewOfFile(ptr);
|
UnmapViewOfFile(ptr);
|
||||||
|
@ -143,8 +158,13 @@ bool SSHAgent::sendMessage(const QByteArray& in, QByteArray& out) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SSHAgent::addIdentity(OpenSSHKey& key, quint32 lifetime, bool confirm) const
|
bool SSHAgent::addIdentity(OpenSSHKey& key, quint32 lifetime, bool confirm)
|
||||||
{
|
{
|
||||||
|
if (!isAgentRunning()) {
|
||||||
|
m_error = tr("No agent running, cannot add identity.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray requestData;
|
QByteArray requestData;
|
||||||
BinaryStream request(&requestData);
|
BinaryStream request(&requestData);
|
||||||
|
|
||||||
|
@ -161,17 +181,25 @@ bool SSHAgent::addIdentity(OpenSSHKey& key, quint32 lifetime, bool confirm) cons
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray responseData;
|
QByteArray responseData;
|
||||||
sendMessage(requestData, responseData);
|
if (!sendMessage(requestData, responseData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (responseData.length() < 1 || static_cast<quint8>(responseData[0]) != SSH_AGENT_SUCCESS) {
|
if (responseData.length() < 1 || static_cast<quint8>(responseData[0]) != SSH_AGENT_SUCCESS) {
|
||||||
|
m_error = tr("Agent refused this identity.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSHAgent::removeIdentity(OpenSSHKey& key) const
|
bool SSHAgent::removeIdentity(OpenSSHKey& key)
|
||||||
{
|
{
|
||||||
|
if (!isAgentRunning()) {
|
||||||
|
m_error = tr("No agent running, cannot remove identity.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray requestData;
|
QByteArray requestData;
|
||||||
BinaryStream request(&requestData);
|
BinaryStream request(&requestData);
|
||||||
|
|
||||||
|
@ -183,9 +211,12 @@ bool SSHAgent::removeIdentity(OpenSSHKey& key) const
|
||||||
request.writeString(keyData);
|
request.writeString(keyData);
|
||||||
|
|
||||||
QByteArray responseData;
|
QByteArray responseData;
|
||||||
sendMessage(requestData, responseData);
|
if (!sendMessage(requestData, responseData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (responseData.length() < 1 || static_cast<quint8>(responseData[0]) != SSH_AGENT_SUCCESS) {
|
if (responseData.length() < 1 || static_cast<quint8>(responseData[0]) != SSH_AGENT_SUCCESS) {
|
||||||
|
m_error = tr("Agent does not have this identity.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +241,12 @@ void SSHAgent::databaseModeChanged(DatabaseWidget::Mode mode)
|
||||||
Uuid uuid = widget->database()->uuid();
|
Uuid uuid = widget->database()->uuid();
|
||||||
|
|
||||||
if (mode == DatabaseWidget::LockedMode && m_keys.contains(uuid.toHex())) {
|
if (mode == DatabaseWidget::LockedMode && m_keys.contains(uuid.toHex())) {
|
||||||
|
|
||||||
QSet<OpenSSHKey> keys = m_keys.take(uuid.toHex());
|
QSet<OpenSSHKey> keys = m_keys.take(uuid.toHex());
|
||||||
for (OpenSSHKey key : keys) {
|
for (OpenSSHKey key : keys) {
|
||||||
removeIdentity(key);
|
if (!removeIdentity(key)) {
|
||||||
|
emit error(m_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (mode == DatabaseWidget::ViewMode && !m_keys.contains(uuid.toHex())) {
|
} else if (mode == DatabaseWidget::ViewMode && !m_keys.contains(uuid.toHex())) {
|
||||||
for (Entry* e : widget->database()->rootGroup()->entriesRecursive()) {
|
for (Entry* e : widget->database()->rootGroup()->entriesRecursive()) {
|
||||||
|
@ -279,7 +313,9 @@ void SSHAgent::databaseModeChanged(DatabaseWidget::Mode mode)
|
||||||
lifetime = settings.lifetimeConstraintDuration();
|
lifetime = settings.lifetimeConstraintDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
addIdentity(key, lifetime, settings.useConfirmConstraintWhenAdding());
|
if (!addIdentity(key, lifetime, settings.useConfirmConstraintWhenAdding())) {
|
||||||
|
emit error(m_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,15 @@ public:
|
||||||
static SSHAgent* instance();
|
static SSHAgent* instance();
|
||||||
static void init(QObject* parent);
|
static void init(QObject* parent);
|
||||||
|
|
||||||
|
const QString errorString() const;
|
||||||
bool isAgentRunning() const;
|
bool isAgentRunning() const;
|
||||||
bool addIdentity(OpenSSHKey& key, quint32 lifetime = 0, bool confirm = false) const;
|
bool addIdentity(OpenSSHKey& key, quint32 lifetime = 0, bool confirm = false);
|
||||||
bool removeIdentity(OpenSSHKey& key) const;
|
bool removeIdentity(OpenSSHKey& key);
|
||||||
void removeIdentityAtLock(const OpenSSHKey& key, const Uuid& uuid);
|
void removeIdentityAtLock(const OpenSSHKey& key, const Uuid& uuid);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void error(const QString& message);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void databaseModeChanged(DatabaseWidget::Mode mode = DatabaseWidget::LockedMode);
|
void databaseModeChanged(DatabaseWidget::Mode mode = DatabaseWidget::LockedMode);
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ private:
|
||||||
explicit SSHAgent(QObject* parent = nullptr);
|
explicit SSHAgent(QObject* parent = nullptr);
|
||||||
~SSHAgent();
|
~SSHAgent();
|
||||||
|
|
||||||
bool sendMessage(const QByteArray& in, QByteArray& out) const;
|
bool sendMessage(const QByteArray& in, QByteArray& out);
|
||||||
|
|
||||||
static SSHAgent* m_instance;
|
static SSHAgent* m_instance;
|
||||||
|
|
||||||
|
@ -68,6 +72,7 @@ private:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMap<QString, QSet<OpenSSHKey>> m_keys;
|
QMap<QString, QSet<OpenSSHKey>> m_keys;
|
||||||
|
QString m_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AGENTCLIENT_H
|
#endif // AGENTCLIENT_H
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue