From 9363f0b7c7bfcf5257a47892b7ca4f8dabf92c59 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Wed, 8 Dec 2021 18:13:39 +0100 Subject: [PATCH] Make nheko usable without a secret storage service This change adds the ability to run Nheko without a secrets storage service[1]. The secrets are stored in plaintext under the [secrets] section of nheko.conf. Since this is a "I know what I'm doing" type of feature, it's disabled by default and can only be enabled with an hidden setting `run_without_secure_secrets_service=true`. Fixes issue #705. [1]: https://freedesktop.org/wiki/Specifications/secret-storage-spec --- src/Cache.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/src/Cache.cpp b/src/Cache.cpp index dd26157c..54b28e2a 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -349,18 +349,39 @@ secretName(std::string name, bool internal) void Cache::loadSecrets(std::vector> toLoad) { + + auto settings = UserSettings::instance()->qsettings(); + if (toLoad.empty()) { this->databaseReady_ = true; emit databaseReady(); + nhlog::db()->debug("Database ready"); return; } + if (settings->value("run_without_secure_secrets_service", false).toBool()) { + for (auto &[name_, internal] : toLoad) { + auto name = secretName(name_, internal); + auto value = settings->value("secrets/" + name).toString(); + if (value.isEmpty()) { + nhlog::db()->info("Restored empty secret '{}'.", name.toStdString()); + } else { + std::unique_lock lock(secret_storage.mtx); + secret_storage.secrets[name.toStdString()] = value.toStdString(); + } + } + // if we emit the databaseReady signal directly it won't be received + QTimer::singleShot(0, [this] { loadSecrets({}); }); + return; + } + + auto [name_, internal] = toLoad.front(); auto job = new QKeychain::ReadPasswordJob(QCoreApplication::applicationName()); job->setAutoDelete(true); job->setInsecureFallback(true); - job->setSettings(UserSettings::instance()->qsettings()); + job->setSettings(settings); auto name = secretName(name_, internal); job->setKey(name); @@ -414,11 +435,19 @@ Cache::storeSecret(const std::string name_, const std::string secret, bool inter secret_storage.secrets[name.toStdString()] = secret; } - auto settings = UserSettings::instance(); - auto job = new QKeychain::WritePasswordJob(QCoreApplication::applicationName()); + auto settings = UserSettings::instance()->qsettings(); + if (settings->value("run_without_secure_secrets_service", false).toBool()) { + settings->setValue("secrets/" + name, QString::fromStdString(secret)); + // if we emit the signal directly it won't be received + QTimer::singleShot(0, [this, name_] { emit secretChanged(name_); }); + nhlog::db()->info("Storing secret '{}' successful", name_); + return; + } + + auto job = new QKeychain::WritePasswordJob(QCoreApplication::applicationName()); job->setAutoDelete(true); job->setInsecureFallback(true); - job->setSettings(UserSettings::instance()->qsettings()); + job->setSettings(settings); job->setKey(name); @@ -453,11 +482,18 @@ Cache::deleteSecret(const std::string name, bool internal) secret_storage.secrets.erase(name_.toStdString()); } - auto settings = UserSettings::instance(); - auto job = new QKeychain::DeletePasswordJob(QCoreApplication::applicationName()); + auto settings = UserSettings::instance()->qsettings(); + if (settings->value("run_without_secure_secrets_service", false).toBool()) { + settings->remove("secrets/" + name_); + // if we emit the signal directly it won't be received + QTimer::singleShot(0, [this, name] { emit secretChanged(name); }); + return; + } + + auto job = new QKeychain::DeletePasswordJob(QCoreApplication::applicationName()); job->setAutoDelete(true); job->setInsecureFallback(true); - job->setSettings(UserSettings::instance()->qsettings()); + job->setSettings(settings); job->setKey(name_);