diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts
index c86e69d48..d647e3c39 100644
--- a/share/translations/keepassxc_en.ts
+++ b/share/translations/keepassxc_en.ts
@@ -1122,6 +1122,14 @@ Do you want to delete the entry?
Select native messaging host folder location
+
+ Allow keepassxc-proxy to list all entries with their title, URL and UUID in connected databases.
+
+
+
+ Allow limited access to all entries in connected databases (ignores site access restrictions)
+
+
CloneDialog
@@ -7925,6 +7933,10 @@ Kernel: %3 %4
Invalid KDF
+
+ Access to all entries is denied
+
+
QtIOCompressor
diff --git a/src/browser/BrowserAction.cpp b/src/browser/BrowserAction.cpp
index b8b5b9879..8176e599a 100644
--- a/src/browser/BrowserAction.cpp
+++ b/src/browser/BrowserAction.cpp
@@ -17,6 +17,7 @@
#include "BrowserAction.h"
#include "BrowserService.h"
+#include "BrowserSettings.h"
#include "core/Global.h"
#include "core/Tools.h"
@@ -101,6 +102,8 @@ QJsonObject BrowserAction::handleAction(QLocalSocket* socket, const QJsonObject&
return handleDeleteEntry(json, action);
} else if (action.compare(BROWSER_REQUEST_REQUEST_AUTOTYPE) == 0) {
return handleGlobalAutoType(json, action);
+ } else if (action.compare("get-database-entries", Qt::CaseSensitive) == 0) {
+ return handleGetDatabaseEntries(json, action);
}
// Action was not recognized
@@ -376,6 +379,40 @@ QJsonObject BrowserAction::handleGetDatabaseGroups(const QJsonObject& json, cons
return buildResponse(action, browserRequest.incrementedNonce, params);
}
+QJsonObject BrowserAction::handleGetDatabaseEntries(const QJsonObject& json, const QString& action)
+{
+ const QString hash = browserService()->getDatabaseHash();
+ const QString nonce = json.value("nonce").toString();
+ const QString encrypted = json.value("message").toString();
+
+ if (!m_associated) {
+ return getErrorReply(action, ERROR_KEEPASS_ASSOCIATION_FAILED);
+ }
+
+ const auto browserRequest = decodeRequest(json);
+ if (browserRequest.isEmpty()) {
+ return getErrorReply(action, ERROR_KEEPASS_CANNOT_DECRYPT_MESSAGE);
+ }
+
+ const auto command = browserRequest.getString("action");
+ if (command.isEmpty() || command.compare("get-database-entries") != 0) {
+ return getErrorReply(action, ERROR_KEEPASS_INCORRECT_ACTION);
+ }
+
+ if (!browserSettings()->allowGetDatabaseEntriesRequest()) {
+ return getErrorReply(action, ERROR_KEEPASS_ACCESS_TO_ALL_ENTRIES_DENIED);
+ }
+
+ const QJsonArray entries = browserService()->getDatabaseEntries();
+ if (entries.isEmpty()) {
+ return getErrorReply(action, ERROR_KEEPASS_NO_GROUPS_FOUND);
+ }
+
+ const Parameters params{{"entries", entries}};
+
+ return buildResponse(action, browserRequest.incrementedNonce, params);
+}
+
QJsonObject BrowserAction::handleCreateNewGroup(const QJsonObject& json, const QString& action)
{
if (!m_associated) {
diff --git a/src/browser/BrowserAction.h b/src/browser/BrowserAction.h
index 5013f3d3b..fe65c977a 100644
--- a/src/browser/BrowserAction.h
+++ b/src/browser/BrowserAction.h
@@ -68,6 +68,7 @@ private:
QJsonObject handleSetLogin(const QJsonObject& json, const QString& action);
QJsonObject handleLockDatabase(const QJsonObject& json, const QString& action);
QJsonObject handleGetDatabaseGroups(const QJsonObject& json, const QString& action);
+ QJsonObject handleGetDatabaseEntries(const QJsonObject& json, const QString& action);
QJsonObject handleCreateNewGroup(const QJsonObject& json, const QString& action);
QJsonObject handleGetTotp(const QJsonObject& json, const QString& action);
QJsonObject handleDeleteEntry(const QJsonObject& json, const QString& action);
diff --git a/src/browser/BrowserMessageBuilder.cpp b/src/browser/BrowserMessageBuilder.cpp
index 4069ae29e..efbaf8cc2 100644
--- a/src/browser/BrowserMessageBuilder.cpp
+++ b/src/browser/BrowserMessageBuilder.cpp
@@ -123,6 +123,8 @@ QString BrowserMessageBuilder::getErrorMessage(const int errorCode) const
return QObject::tr("Cannot create new group");
case ERROR_KEEPASS_NO_VALID_UUID_PROVIDED:
return QObject::tr("No valid UUID provided");
+ case ERROR_KEEPASS_ACCESS_TO_ALL_ENTRIES_DENIED:
+ return QObject::tr("Access to all entries is denied");
default:
return QObject::tr("Unknown error");
}
diff --git a/src/browser/BrowserMessageBuilder.h b/src/browser/BrowserMessageBuilder.h
index c8605ab58..1248522af 100644
--- a/src/browser/BrowserMessageBuilder.h
+++ b/src/browser/BrowserMessageBuilder.h
@@ -47,7 +47,8 @@ namespace
ERROR_KEEPASS_NO_LOGINS_FOUND = 15,
ERROR_KEEPASS_NO_GROUPS_FOUND = 16,
ERROR_KEEPASS_CANNOT_CREATE_NEW_GROUP = 17,
- ERROR_KEEPASS_NO_VALID_UUID_PROVIDED = 18
+ ERROR_KEEPASS_NO_VALID_UUID_PROVIDED = 18,
+ ERROR_KEEPASS_ACCESS_TO_ALL_ENTRIES_DENIED = 19
};
}
diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp
index 50b1a5cc3..07273540c 100644
--- a/src/browser/BrowserService.cpp
+++ b/src/browser/BrowserService.cpp
@@ -219,6 +219,35 @@ QJsonObject BrowserService::getDatabaseGroups()
return result;
}
+QJsonArray BrowserService::getDatabaseEntries()
+{
+ auto db = getDatabase();
+ if (!db) {
+ return {};
+ }
+
+ Group* rootGroup = db->rootGroup();
+ if (!rootGroup) {
+ return {};
+ }
+
+ QJsonArray entries;
+ for (const auto& group : rootGroup->groupsRecursive(true)) {
+ if (group == db->metadata()->recycleBin()) {
+ continue;
+ }
+
+ for (const auto& entry : group->entries()) {
+ QJsonObject jentry;
+ jentry["title"] = entry->resolveMultiplePlaceholders(entry->title());
+ jentry["uuid"] = entry->resolveMultiplePlaceholders(entry->uuidToHex());
+ jentry["url"] = entry->resolveMultiplePlaceholders(entry->url());
+ entries.push_back(jentry);
+ }
+ }
+ return entries;
+}
+
QJsonObject BrowserService::createNewGroup(const QString& groupName)
{
auto db = getDatabase();
diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h
index 82a8f6a1a..0d804bd91 100644
--- a/src/browser/BrowserService.h
+++ b/src/browser/BrowserService.h
@@ -76,6 +76,7 @@ public:
void lockDatabase();
QJsonObject getDatabaseGroups();
+ QJsonArray getDatabaseEntries();
QJsonObject createNewGroup(const QString& groupName);
QString getCurrentTotp(const QString& uuid);
void showPasswordGenerator(const KeyPairMessage& keyPairMessage);
diff --git a/src/browser/BrowserSettings.cpp b/src/browser/BrowserSettings.cpp
index 7b5704e78..329659c05 100644
--- a/src/browser/BrowserSettings.cpp
+++ b/src/browser/BrowserSettings.cpp
@@ -222,6 +222,16 @@ void BrowserSettings::setUpdateBinaryPath(bool enabled)
config()->set(Config::Browser_UpdateBinaryPath, enabled);
}
+bool BrowserSettings::allowGetDatabaseEntriesRequest()
+{
+ return config()->get(Config::Browser_AllowGetDatabaseEntriesRequest).toBool();
+}
+
+void BrowserSettings::setAllowGetDatabaseEntriesRequest(bool enabled)
+{
+ config()->set(Config::Browser_AllowGetDatabaseEntriesRequest, enabled);
+}
+
bool BrowserSettings::allowExpiredCredentials()
{
return config()->get(Config::Browser_AllowExpiredCredentials).toBool();
diff --git a/src/browser/BrowserSettings.h b/src/browser/BrowserSettings.h
index 18ededb4c..a961a56ae 100644
--- a/src/browser/BrowserSettings.h
+++ b/src/browser/BrowserSettings.h
@@ -63,6 +63,8 @@ public:
#endif
bool updateBinaryPath();
void setUpdateBinaryPath(bool enabled);
+ bool allowGetDatabaseEntriesRequest();
+ void setAllowGetDatabaseEntriesRequest(bool enabled);
bool allowExpiredCredentials();
void setAllowExpiredCredentials(bool enabled);
diff --git a/src/browser/BrowserSettingsWidget.cpp b/src/browser/BrowserSettingsWidget.cpp
index 8dd26d324..9ce4ae613 100644
--- a/src/browser/BrowserSettingsWidget.cpp
+++ b/src/browser/BrowserSettingsWidget.cpp
@@ -125,6 +125,7 @@ void BrowserSettingsWidget::loadSettings()
m_ui->useCustomProxy->setChecked(settings->useCustomProxy());
m_ui->customProxyLocation->setText(settings->replaceHomePath(settings->customProxyLocation()));
m_ui->updateBinaryPath->setChecked(settings->updateBinaryPath());
+ m_ui->allowGetDatabaseEntriesRequest->setChecked(settings->allowGetDatabaseEntriesRequest());
m_ui->allowExpiredCredentials->setChecked(settings->allowExpiredCredentials());
m_ui->chromeSupport->setChecked(settings->browserSupport(BrowserShared::CHROME));
m_ui->chromiumSupport->setChecked(settings->browserSupport(BrowserShared::CHROMIUM));
@@ -217,6 +218,7 @@ void BrowserSettingsWidget::saveSettings()
settings->setCustomProxyLocation(browserSettings()->replaceTildeHomePath(m_ui->customProxyLocation->text()));
settings->setUpdateBinaryPath(m_ui->updateBinaryPath->isChecked());
+ settings->setAllowGetDatabaseEntriesRequest(m_ui->allowGetDatabaseEntriesRequest->isChecked());
settings->setAllowExpiredCredentials(m_ui->allowExpiredCredentials->isChecked());
settings->setAlwaysAllowAccess(m_ui->alwaysAllowAccess->isChecked());
settings->setAlwaysAllowUpdate(m_ui->alwaysAllowUpdate->isChecked());
diff --git a/src/browser/BrowserSettingsWidget.ui b/src/browser/BrowserSettingsWidget.ui
index 1f8902be9..13af62a40 100644
--- a/src/browser/BrowserSettingsWidget.ui
+++ b/src/browser/BrowserSettingsWidget.ui
@@ -327,6 +327,16 @@
+ -
+
+
+ Allow keepassxc-proxy to list all entries with their title, URL and UUID in connected databases.
+
+
+ Allow limited access to all entries in connected databases (ignores site access restrictions)
+
+
+
-
diff --git a/src/core/Config.cpp b/src/core/Config.cpp
index 56bd92cbf..2e81ad771 100644
--- a/src/core/Config.cpp
+++ b/src/core/Config.cpp
@@ -155,6 +155,7 @@ static const QHash configStrings = {
{Config::Browser_UseCustomProxy, {QS("Browser/UseCustomProxy"), Roaming, false}},
{Config::Browser_CustomProxyLocation, {QS("Browser/CustomProxyLocation"), Roaming, {}}},
{Config::Browser_UpdateBinaryPath, {QS("Browser/UpdateBinaryPath"), Roaming, true}},
+ {Config::Browser_AllowGetDatabaseEntriesRequest, {QS("Browser/AllowGetDatabaseEntriesRequest"), Roaming, false}},
{Config::Browser_AllowExpiredCredentials, {QS("Browser/AllowExpiredCredentials"), Roaming, false}},
{Config::Browser_AlwaysAllowAccess, {QS("Browser/AlwaysAllowAccess"), Roaming, false}},
{Config::Browser_AlwaysAllowUpdate, {QS("Browser/AlwaysAllowUpdate"), Roaming, false}},
diff --git a/src/core/Config.h b/src/core/Config.h
index e0b42b35c..28a32545c 100644
--- a/src/core/Config.h
+++ b/src/core/Config.h
@@ -134,6 +134,7 @@ public:
Browser_UseCustomProxy,
Browser_CustomProxyLocation,
Browser_UpdateBinaryPath,
+ Browser_AllowGetDatabaseEntriesRequest,
Browser_AllowExpiredCredentials,
Browser_AlwaysAllowAccess,
Browser_AlwaysAllowUpdate,