mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-12-04 15:39:34 +01:00
Sanitize username to prevent single-instance detection failure (#12559)
--------- Co-authored-by: Jonathan White <support@dmapps.us>
This commit is contained in:
@@ -426,6 +426,29 @@ namespace Tools
|
|||||||
return filename.trimmed();
|
return filename.trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString cleanUsername()
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
QString userName = qgetenv("USERNAME");
|
||||||
|
if (userName.isEmpty()) {
|
||||||
|
userName = qgetenv("USER");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
QString userName = qgetenv("USER");
|
||||||
|
if (userName.isEmpty()) {
|
||||||
|
userName = qgetenv("USERNAME");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Sanitize username for file safety
|
||||||
|
userName = userName.trimmed();
|
||||||
|
// Replace <>:"/\|?* with _
|
||||||
|
userName.replace(QRegularExpression(R"([<>:\"\/\\|?*])"), "_");
|
||||||
|
// Remove trailing dots and spaces
|
||||||
|
userName.replace(QRegularExpression(R"([.\s]+$)"), "");
|
||||||
|
|
||||||
|
return userName;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap qo2qvm(const QObject* object, const QStringList& ignoredProperties)
|
QVariantMap qo2qvm(const QObject* object, const QStringList& ignoredProperties)
|
||||||
{
|
{
|
||||||
QVariantMap result;
|
QVariantMap result;
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ namespace Tools
|
|||||||
QString envSubstitute(const QString& filepath,
|
QString envSubstitute(const QString& filepath,
|
||||||
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment());
|
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment());
|
||||||
QString cleanFilename(QString filename);
|
QString cleanFilename(QString filename);
|
||||||
|
QString cleanUsername();
|
||||||
|
|
||||||
template <class T> QSet<T> asSet(const QList<T>& a)
|
template <class T> QSet<T> asSet(const QList<T>& a)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
#include "core/Bootstrap.h"
|
#include "core/Bootstrap.h"
|
||||||
|
#include "core/Tools.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
#include "gui/osutils/OSUtils.h"
|
#include "gui/osutils/OSUtils.h"
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
#include <QLockFile>
|
#include <QLockFile>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
|
#include <QRegularExpression>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
@@ -63,20 +65,19 @@ Application::Application(int& argc, char** argv)
|
|||||||
registerUnixSignals();
|
registerUnixSignals();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QString userName = qgetenv("USER");
|
// Build identifier
|
||||||
if (userName.isEmpty()) {
|
auto identifier = QStringLiteral("keepassxc");
|
||||||
userName = qgetenv("USERNAME");
|
auto username = Tools::cleanUsername();
|
||||||
}
|
if (!username.isEmpty()) {
|
||||||
QString identifier = "keepassxc";
|
identifier += QChar('-') + username;
|
||||||
if (!userName.isEmpty()) {
|
|
||||||
identifier += "-" + userName;
|
|
||||||
}
|
}
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
// In DEBUG mode don't interfere with Release instances
|
// In DEBUG mode don’t interfere with Release instances
|
||||||
identifier += "-DEBUG";
|
identifier += QStringLiteral("-DEBUG");
|
||||||
#endif
|
#endif
|
||||||
QString lockName = identifier + ".lock";
|
|
||||||
m_socketName = identifier + ".socket";
|
QString lockName = identifier + QStringLiteral(".lock");
|
||||||
|
m_socketName = identifier + QStringLiteral(".socket");
|
||||||
|
|
||||||
// According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect
|
// According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect
|
||||||
// this and creates sockets in TempLocation, so let's be consistent.
|
// this and creates sockets in TempLocation, so let's be consistent.
|
||||||
|
|||||||
@@ -428,3 +428,26 @@ void TestTools::testIsTextMimeType()
|
|||||||
QVERIFY(!Tools::isTextMimeType(noText));
|
QVERIFY(!Tools::isTextMimeType(noText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test sanitization logic for Tools::cleanUsername
|
||||||
|
void TestTools::testCleanUsername()
|
||||||
|
{
|
||||||
|
// Test vars
|
||||||
|
QFETCH(QString, input);
|
||||||
|
QFETCH(QString, expected);
|
||||||
|
|
||||||
|
qputenv("USER", input.toUtf8());
|
||||||
|
qputenv("USERNAME", input.toUtf8());
|
||||||
|
QCOMPARE(Tools::cleanUsername(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestTools::testCleanUsername_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("input");
|
||||||
|
QTest::addColumn<QString>("expected");
|
||||||
|
|
||||||
|
QTest::newRow("Leading and trailing spaces") << " user " << "user";
|
||||||
|
QTest::newRow("Special characters") << R"(user<>:"/\|?*name)" << "user_________name";
|
||||||
|
QTest::newRow("Trailing dots and spaces") << "username... " << "username";
|
||||||
|
QTest::newRow("Combination of issues") << R"( user<>:"/\|?*name... )" << "user_________name";
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ private slots:
|
|||||||
void testGetMimeType();
|
void testGetMimeType();
|
||||||
void testGetMimeTypeByFileInfo();
|
void testGetMimeTypeByFileInfo();
|
||||||
void testIsTextMimeType();
|
void testIsTextMimeType();
|
||||||
|
void testCleanUsername();
|
||||||
|
void testCleanUsername_data();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_TESTTOOLS_H
|
#endif // KEEPASSX_TESTTOOLS_H
|
||||||
|
|||||||
Reference in New Issue
Block a user