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
This commit is contained in:
Michele Guerini Rocco 2021-12-08 18:13:39 +01:00
parent 3e8734dbd5
commit 9363f0b7c7
Signed by: rnhmjoj
GPG Key ID: BFBAF4C975F76450
1 changed files with 43 additions and 7 deletions

View File

@ -349,18 +349,39 @@ secretName(std::string name, bool internal)
void
Cache::loadSecrets(std::vector<std::pair<std::string, bool>> 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_);