diff --git a/Userland/Libraries/LibConfig/Client.cpp b/Userland/Libraries/LibConfig/Client.cpp index 265c4b2e0a..a3c3bef4b3 100644 --- a/Userland/Libraries/LibConfig/Client.cpp +++ b/Userland/Libraries/LibConfig/Client.cpp @@ -19,6 +19,11 @@ Client& Client::the() return *s_the; } +void Client::pledge_domains(Vector const& domains) +{ + async_pledge_domains(domains); +} + String Client::read_string(StringView domain, StringView group, StringView key, StringView fallback) { return read_string_value(domain, group, key).value_or(fallback); diff --git a/Userland/Libraries/LibConfig/Client.h b/Userland/Libraries/LibConfig/Client.h index 6018145b03..395a3188fc 100644 --- a/Userland/Libraries/LibConfig/Client.h +++ b/Userland/Libraries/LibConfig/Client.h @@ -21,6 +21,8 @@ class Client final C_OBJECT(Client); public: + void pledge_domains(Vector const&); + String read_string(StringView domain, StringView group, StringView key, StringView fallback); i32 read_i32(StringView domain, StringView group, StringView key, i32 fallback); bool read_bool(StringView domain, StringView group, StringView key, bool fallback); @@ -68,4 +70,14 @@ inline void write_bool(StringView domain, StringView group, StringView key, bool Client::the().write_bool(domain, group, key, value); } +inline void pledge_domains(Vector const& domains) +{ + Client::the().pledge_domains(domains); +} + +inline void pledge_domains(String const& domains) +{ + Client::the().pledge_domains({ domains }); +} + } diff --git a/Userland/Services/ConfigServer/ClientConnection.cpp b/Userland/Services/ConfigServer/ClientConnection.cpp index e55879c74c..3551a1af5b 100644 --- a/Userland/Services/ConfigServer/ClientConnection.cpp +++ b/Userland/Services/ConfigServer/ClientConnection.cpp @@ -27,8 +27,32 @@ void ClientConnection::die() s_connections.remove(client_id()); } +void ClientConnection::pledge_domains(Vector const& domains) +{ + if (m_has_pledged) { + did_misbehave("Tried to pledge domains twice."); + return; + } + m_has_pledged = true; + for (auto& domain : domains) + m_pledged_domains.set(domain); +} + +bool ClientConnection::validate_access(String const& domain, String const& group, String const& key) +{ + if (!m_has_pledged) + return true; + if (m_pledged_domains.contains(domain)) + return true; + did_misbehave(String::formatted("Blocked attempt to access domain '{}', group={}, key={}", domain, group, key).characters()); + return false; +} + Messages::ConfigServer::ReadStringValueResponse ClientConnection::read_string_value(String const& domain, String const& group, String const& key) { + if (!validate_access(domain, group, key)) + return nullptr; + auto config = Core::ConfigFile::open_for_app(domain); if (!config->has_key(group, key)) return Optional {}; @@ -37,6 +61,9 @@ Messages::ConfigServer::ReadStringValueResponse ClientConnection::read_string_va Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(String const& domain, String const& group, String const& key) { + if (!validate_access(domain, group, key)) + return nullptr; + auto config = Core::ConfigFile::open_for_app(domain); if (!config->has_key(group, key)) return Optional {}; @@ -45,6 +72,9 @@ Messages::ConfigServer::ReadI32ValueResponse ClientConnection::read_i32_value(St Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value(String const& domain, String const& group, String const& key) { + if (!validate_access(domain, group, key)) + return nullptr; + auto config = Core::ConfigFile::open_for_app(domain); if (!config->has_key(group, key)) return Optional {}; @@ -53,18 +83,27 @@ Messages::ConfigServer::ReadBoolValueResponse ClientConnection::read_bool_value( void ClientConnection::write_string_value(String const& domain, String const& group, String const& key, String const& value) { + if (!validate_access(domain, group, key)) + return; + auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); config->write_entry(group, key, value); } void ClientConnection::write_i32_value(String const& domain, String const& group, String const& key, i32 value) { + if (!validate_access(domain, group, key)) + return; + auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); config->write_num_entry(group, key, value); } void ClientConnection::write_bool_value(String const& domain, String const& group, String const& key, bool value) { + if (!validate_access(domain, group, key)) + return; + auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes); config->write_bool_entry(group, key, value); } diff --git a/Userland/Services/ConfigServer/ClientConnection.h b/Userland/Services/ConfigServer/ClientConnection.h index df41d9647e..cdbc53ab64 100644 --- a/Userland/Services/ConfigServer/ClientConnection.h +++ b/Userland/Services/ConfigServer/ClientConnection.h @@ -23,12 +23,18 @@ public: private: explicit ClientConnection(NonnullRefPtr, int client_id); + virtual void pledge_domains(Vector const&) override; virtual Messages::ConfigServer::ReadStringValueResponse read_string_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; virtual Messages::ConfigServer::ReadI32ValueResponse read_i32_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; virtual Messages::ConfigServer::ReadBoolValueResponse read_bool_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key) override; virtual void write_string_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key, [[maybe_unused]] String const& value) override; virtual void write_i32_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key, [[maybe_unused]] i32 value) override; virtual void write_bool_value([[maybe_unused]] String const& domain, [[maybe_unused]] String const& group, [[maybe_unused]] String const& key, [[maybe_unused]] bool value) override; + + bool validate_access(String const& domain, String const& group, String const& key); + + bool m_has_pledged { false }; + HashTable m_pledged_domains; }; } diff --git a/Userland/Services/ConfigServer/ConfigServer.ipc b/Userland/Services/ConfigServer/ConfigServer.ipc index 7c0b725870..9ce1bbc70a 100644 --- a/Userland/Services/ConfigServer/ConfigServer.ipc +++ b/Userland/Services/ConfigServer/ConfigServer.ipc @@ -1,5 +1,7 @@ endpoint ConfigServer { + pledge_domains(Vector domains) =| + read_string_value(String domain, String group, String key) => (Optional value) read_i32_value(String domain, String group, String key) => (Optional value) read_bool_value(String domain, String group, String key) => (Optional value)