From 6fc7be78eae3de21d94ff49465ac03246cd3164b Mon Sep 17 00:00:00 2001 From: Toni Spets Date: Sat, 2 Nov 2019 11:25:13 +0200 Subject: [PATCH] Implement SSH key file path env substitution Supports all platforms, including Windows with %FOO% syntax. Fixes #3523 --- src/core/Tools.cpp | 23 +++++++++++++++++++++++ src/core/Tools.h | 3 +++ src/sshagent/KeeAgentSettings.cpp | 8 +++++++- src/sshagent/KeeAgentSettings.h | 1 + tests/TestTools.cpp | 21 +++++++++++++++++++++ tests/TestTools.h | 1 + 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 5d42bc799..5d8889fae 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -324,6 +324,29 @@ namespace Tools return QUuid::fromRfc4122(QByteArray::fromHex(uuid.toLatin1())); } + QString envSubstitute(const QString& filepath, QProcessEnvironment environment) + { + QString subbed = filepath; + +#if defined(Q_OS_WIN) + QRegularExpression varRe("\\%([A-Za-z][A-Za-z0-9_]*)\\%"); +#else + QRegularExpression varRe("\\$([A-Za-z][A-Za-z0-9_]*)"); + subbed.replace("~", environment.value("HOME")); +#endif + + QRegularExpressionMatch match; + + do { + match = varRe.match(subbed); + if (match.hasMatch()) { + subbed.replace(match.capturedStart(), match.capturedLength(), environment.value(match.captured(1))); + } + } while (match.hasMatch()); + + return subbed; + } + Buffer::Buffer() : raw(nullptr) , size(0) diff --git a/src/core/Tools.h b/src/core/Tools.h index 455b879c2..e56a25189 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -22,6 +22,7 @@ #include "core/Global.h" #include +#include #include #include @@ -48,6 +49,8 @@ namespace Tools bool useWildcards = false, bool exactMatch = false, bool caseSensitive = false); + QString envSubstitute(const QString& filepath, + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment()); template RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) diff --git a/src/sshagent/KeeAgentSettings.cpp b/src/sshagent/KeeAgentSettings.cpp index b914263c1..72a2f66da 100644 --- a/src/sshagent/KeeAgentSettings.cpp +++ b/src/sshagent/KeeAgentSettings.cpp @@ -17,6 +17,7 @@ */ #include "KeeAgentSettings.h" +#include "core/Tools.h" KeeAgentSettings::KeeAgentSettings() : m_lifetimeConstraintDuration(600) @@ -115,6 +116,11 @@ const QString KeeAgentSettings::fileName() const return m_fileName; } +const QString KeeAgentSettings::fileNameEnvSubst(QProcessEnvironment environment) const +{ + return Tools::envSubstitute(m_fileName, environment); +} + void KeeAgentSettings::setAllowUseOfSshKey(bool allowUseOfSshKey) { m_allowUseOfSshKey = allowUseOfSshKey; @@ -361,7 +367,7 @@ bool KeeAgentSettings::toOpenSSHKey(const Entry* entry, OpenSSHKey& key, bool de fileName = m_attachmentName; privateKeyData = entry->attachments()->value(fileName); } else { - QFile localFile(m_fileName); + QFile localFile(fileNameEnvSubst()); QFileInfo localFileInfo(localFile); fileName = localFileInfo.fileName(); diff --git a/src/sshagent/KeeAgentSettings.h b/src/sshagent/KeeAgentSettings.h index 357c69528..ed776e741 100644 --- a/src/sshagent/KeeAgentSettings.h +++ b/src/sshagent/KeeAgentSettings.h @@ -54,6 +54,7 @@ public: const QString attachmentName() const; bool saveAttachmentToTempFile() const; const QString fileName() const; + const QString fileNameEnvSubst(QProcessEnvironment environment = QProcessEnvironment::systemEnvironment()) const; void setAllowUseOfSshKey(bool allowUseOfSshKey); void setAddAtDatabaseOpen(bool addAtDatabaseOpen); diff --git a/tests/TestTools.cpp b/tests/TestTools.cpp index 100eb6306..4809a8bc9 100644 --- a/tests/TestTools.cpp +++ b/tests/TestTools.cpp @@ -64,3 +64,24 @@ void TestTools::testIsBase64() QVERIFY(not Tools::isBase64(QByteArray("abc_"))); QVERIFY(not Tools::isBase64(QByteArray("123"))); } + +void TestTools::testEnvSubstitute() +{ + QProcessEnvironment environment; + +#if defined(Q_OS_WIN) + environment.insert("HOMEDRIVE", "C:"); + environment.insert("HOMEPATH", "\\Users\\User"); + + QCOMPARE(Tools::envSubstitute("%HOMEDRIVE%%HOMEPATH%\\.ssh\\id_rsa", environment), + QString("C:\\Users\\User\\.ssh\\id_rsa")); + QCOMPARE(Tools::envSubstitute("start%EMPTY%%EMPTY%%%HOMEDRIVE%%end", environment), QString("start%C:%end")); +#else + environment.insert("HOME", QString("/home/user")); + environment.insert("USER", QString("user")); + + QCOMPARE(Tools::envSubstitute("~/.ssh/id_rsa", environment), QString("/home/user/.ssh/id_rsa")); + QCOMPARE(Tools::envSubstitute("$HOME/.ssh/id_rsa", environment), QString("/home/user/.ssh/id_rsa")); + QCOMPARE(Tools::envSubstitute("start/$EMPTY$$EMPTY$HOME/end", environment), QString("start/$/home/user/end")); +#endif +} diff --git a/tests/TestTools.h b/tests/TestTools.h index 56d354eca..dd646fcc4 100644 --- a/tests/TestTools.h +++ b/tests/TestTools.h @@ -27,6 +27,7 @@ private slots: void testHumanReadableFileSize(); void testIsHex(); void testIsBase64(); + void testEnvSubstitute(); }; #endif // KEEPASSX_TESTTOOLS_H