fix(integrity): restore bootstrap runtime protection

This commit is contained in:
Comely
2026-07-12 17:36:53 -07:00
parent c5e8f34f75
commit b098792001
4 changed files with 45 additions and 35 deletions
+1
View File
@@ -7,6 +7,7 @@ set(_common_sources
ConfigHelper.cpp ConfigHelper.cpp
InitialStatePolicy.h InitialStatePolicy.h
ManifestBootstrapPolicy.h ManifestBootstrapPolicy.h
RuntimeProtectionPolicy.h
PolicyHelper.h PolicyHelper.h
PolicyHelper.cpp PolicyHelper.cpp
LocalStateHelper.h LocalStateHelper.h
+3 -15
View File
@@ -1,5 +1,6 @@
#include "IntegrityHelper.h" #include "IntegrityHelper.h"
#include "ConfigHelper.h" #include "ConfigHelper.h"
#include "RuntimeProtectionPolicy.h"
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDir> #include <QDir>
#include <QDirIterator> #include <QDirIterator>
@@ -33,21 +34,8 @@ bool IntegrityHelper::safeRelativePath(const QString& path) const
bool IntegrityHelper::runtimeProtectedPath(const QString& path) const bool IntegrityHelper::runtimeProtectedPath(const QString& path) const
{ {
const QString p = QDir::fromNativeSeparators(path).toCaseFolded(); return UpdateClient::isRuntimeProtectedPath(
QSet<QString> protectedPaths{ path, ConfigHelper::instance().runtimeRelativePath());
"client.ini", "config/app_config.json", "config/local_state.json",
"config/client_identity.dat", "config/version_policy.dat"
};
const QString runtimePrefix = ConfigHelper::instance().runtimeRelativePath().toCaseFolded();
if (!runtimePrefix.isEmpty()) {
const QStringList runtimeProtected{
"client.ini", "config/app_config.json", "config/local_state.json",
"config/client_identity.dat", "config/version_policy.dat"
};
for (const QString& protectedPath : runtimeProtected)
protectedPaths.insert(runtimePrefix + "/" + protectedPath);
}
return protectedPaths.contains(p);
} }
QString IntegrityHelper::sha256(const QString& filePath) const QString IntegrityHelper::sha256(const QString& filePath) const
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <QDir>
#include <QSet>
#include <QString>
namespace UpdateClient
{
inline bool isRuntimeProtectedPath(const QString& path,
const QString& runtimeRelativePath)
{
const QString normalizedPath =
QDir::cleanPath(QDir::fromNativeSeparators(path)).toCaseFolded();
static const QSet<QString> protectedPaths{
QStringLiteral("bootstrap.exe"),
QStringLiteral("client.ini"),
QStringLiteral("config/app_config.json"),
QStringLiteral("config/local_state.json"),
QStringLiteral("config/client_identity.dat"),
QStringLiteral("config/version_policy.dat")
};
if (protectedPaths.contains(normalizedPath))
return true;
QString runtimePrefix = QDir::cleanPath(
QDir::fromNativeSeparators(runtimeRelativePath)).toCaseFolded();
if (runtimePrefix.isEmpty() || runtimePrefix == QStringLiteral("."))
return false;
while (runtimePrefix.startsWith(QStringLiteral("./")))
runtimePrefix.remove(0, 2);
for (const QString& protectedPath : protectedPaths) {
if (normalizedPath == runtimePrefix + QLatin1Char('/') + protectedPath)
return true;
}
return false;
}
}
+3 -20
View File
@@ -19,6 +19,7 @@
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include "ConfigHelper.h" #include "ConfigHelper.h"
#include "RuntimeProtectionPolicy.h"
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
#include <openssl/pem.h> #include <openssl/pem.h>
@@ -810,26 +811,8 @@ bool UpdaterLogic::downloadSingleFile(const QString& url, const QString& savePat
bool UpdaterLogic::isRuntimeProtectedPath(const QString& path) const bool UpdaterLogic::isRuntimeProtectedPath(const QString& path) const
{ {
const QString normalized = QDir::fromNativeSeparators(path).toCaseFolded(); return UpdateClient::isRuntimeProtectedPath(
QSet<QString> protectedPaths{ path, ConfigHelper::instance().runtimeRelativePath());
QStringLiteral("bootstrap.exe"),
QStringLiteral("client.ini"),
QStringLiteral("config/app_config.json"),
QStringLiteral("config/local_state.json"),
QStringLiteral("config/client_identity.dat"),
QStringLiteral("config/version_policy.dat")
};
const QString runtimePrefix = ConfigHelper::instance().runtimeRelativePath().toCaseFolded();
if (!runtimePrefix.isEmpty()) {
const QStringList runtimeProtected{
QStringLiteral("bootstrap.exe"), QStringLiteral("client.ini"),
QStringLiteral("config/app_config.json"), QStringLiteral("config/local_state.json"),
QStringLiteral("config/client_identity.dat"), QStringLiteral("config/version_policy.dat")
};
for (const QString& protectedPath : runtimeProtected)
protectedPaths.insert(runtimePrefix + "/" + protectedPath);
}
return protectedPaths.contains(normalized);
} }
bool UpdaterLogic::isSafeRelativePath(const QString& path) const bool UpdaterLogic::isSafeRelativePath(const QString& path) const