| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include "base/at_exit.h" |
| #include "base/check_op.h" |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/i18n/icu_util.h" |
| #include "base/logging.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/path_service.h" |
| #include "base/syslog_logging.h" |
| #include "base/test/task_environment.h" |
| #include "base/test/test_timeouts.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/ash/dbus/ash_dbus_helper.h" |
| #include "chrome/browser/ash/policy/core/device_policy_decoder.h" |
| #include "chrome/browser/ash/policy/fuzzer/policy_fuzzer.pb.h" |
| #include "chrome/browser/ash/settings/device_settings_provider.h" |
| #include "chrome/browser/ash/settings/device_settings_service.h" |
| #include "chrome/browser/policy/configuration_policy_handler_list_factory.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chromeos/ash/components/attestation/attestation_features.h" |
| #include "chromeos/ash/components/install_attributes/install_attributes.h" |
| #include "components/policy/core/browser/configuration_policy_handler_list.h" |
| #include "components/policy/core/browser/policy_conversions_client.h" |
| #include "components/policy/core/browser/policy_error_map.h" |
| #include "components/policy/core/common/chrome_schema.h" |
| #include "components/policy/core/common/cloud/cloud_external_data_manager.h" |
| #include "components/policy/core/common/external_data_manager.h" |
| #include "components/policy/core/common/policy_map.h" |
| #include "components/policy/core/common/policy_proto_decoders.h" |
| #include "components/policy/core/common/policy_types.h" |
| #include "components/policy/policy_constants.h" |
| #include "components/prefs/pref_value_map.h" |
| #include "testing/libfuzzer/proto/lpm_interface.h" |
| #include "ui/base/resource/resource_bundle.h" |
| #include "ui/base/ui_base_paths.h" |
| |
| namespace policy { |
| |
| namespace { |
| |
| constexpr logging::LogSeverity kLogSeverity = logging::LOGGING_FATAL; |
| |
| // A log handler that discards messages whose severity is lower than the |
| // threshold. It's needed in order to suppress unneeded syslog logging (which by |
| // default is exempt from the level set by `logging::SetMinLogLevel()`). |
| bool VoidifyingLogHandler(int severity, |
| const char* /*file*/, |
| int /*line*/, |
| size_t /*message_start*/, |
| const std::string& /*str*/) { |
| return severity < kLogSeverity; |
| } |
| |
| struct Environment { |
| Environment() { |
| // Discard all log messages, including the syslog ones, below the threshold. |
| logging::SetMinLogLevel(kLogSeverity); |
| logging::SetSyslogLoggingForTesting(/*logging_enabled=*/false); |
| logging::SetLogMessageHandler(&VoidifyingLogHandler); |
| |
| base::CommandLine::Init(0, nullptr); |
| TestTimeouts::Initialize(); |
| CHECK(scoped_temp_dir.CreateUniqueTempDir()); |
| CHECK(base::PathService::Override(chrome::DIR_USER_DATA, |
| scoped_temp_dir.GetPath())); |
| CHECK(base::i18n::InitializeICU()); |
| |
| ui::RegisterPathProvider(); |
| |
| base::FilePath ui_test_pak_path = |
| base::PathService::CheckedGet(ui::UI_TEST_PAK); |
| ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path); |
| |
| base::FilePath pak_path = base::PathService::CheckedGet(base::DIR_ASSETS); |
| ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( |
| pak_path.AppendASCII("components_tests_resources.pak"), |
| ui::kScaleFactorNone); |
| } |
| |
| ~Environment() { ui::ResourceBundle::CleanupSharedInstance(); } |
| |
| base::ScopedTempDir scoped_temp_dir; |
| base::AtExitManager exit_manager; |
| }; |
| |
| struct PerInputEnvironment { |
| PerInputEnvironment() { |
| policy_handler_list = BuildHandlerList(GetChromeSchema()); |
| ash::InitializeDBus(); |
| ash::InitializeFeatureListDependentDBus(); |
| } |
| |
| ~PerInputEnvironment() { |
| ash::ShutdownDBus(); |
| ash::InstallAttributes::Shutdown(); |
| ash::DeviceSettingsService::Shutdown(); |
| ash::attestation::AttestationFeatures::Shutdown(); |
| } |
| |
| base::test::TaskEnvironment task_environment; |
| std::unique_ptr<ConfigurationPolicyHandlerList> policy_handler_list; |
| }; |
| |
| void CheckPolicyMap(const PolicyMap& policy_map, |
| PolicyScope expected_policy_scope, |
| bool expected_is_device_policy) { |
| for (const auto& it : policy_map) { |
| const std::string& policy_name = it.first; |
| const PolicyMap::Entry& entry = it.second; |
| CHECK(entry.value_unsafe()) |
| << "Policy " << policy_name << " has an empty value"; |
| CHECK_EQ(entry.scope, expected_policy_scope) |
| << "Policy " << policy_name << " has wrong scope"; |
| |
| const PolicyDetails* policy_details = GetChromePolicyDetails(policy_name); |
| CHECK(policy_details) << "Policy " << policy_name |
| << " has no policy details"; |
| CHECK_EQ(policy_details->is_device_policy, expected_is_device_policy) |
| << "Policy " << policy_name << " is of unexpected type"; |
| } |
| } |
| |
| void CheckPolicyToPrefTranslation(const PolicyMap& policy_map, |
| const PerInputEnvironment& per_input_env) { |
| PrefValueMap prefs; |
| PolicyErrorMap errors; |
| PoliciesSet deprecated_policies; |
| PoliciesSet future_policies; |
| per_input_env.policy_handler_list->ApplyPolicySettings( |
| policy_map, &prefs, &errors, &deprecated_policies, &future_policies); |
| } |
| |
| void CheckPolicyToCrosSettingsTranslation( |
| const enterprise_management::ChromeDeviceSettingsProto& |
| chrome_device_settings) { |
| PrefValueMap cros_settings_prefs; |
| ash::DeviceSettingsProvider::DecodePolicies(chrome_device_settings, |
| &cros_settings_prefs); |
| |
| for (const auto& it : cros_settings_prefs) { |
| const std::string& pref_name = it.first; |
| CHECK(ash::DeviceSettingsProvider::IsDeviceSetting(pref_name)); |
| } |
| } |
| |
| } // namespace |
| |
| DEFINE_PROTO_FUZZER(const PolicyFuzzerProto& proto) { |
| static Environment env; |
| PerInputEnvironment per_input_env; |
| |
| if (proto.has_chrome_device_settings()) { |
| const enterprise_management::ChromeDeviceSettingsProto& |
| chrome_device_settings = proto.chrome_device_settings(); |
| base::WeakPtr<ExternalDataManager> data_manager; |
| PolicyMap policy_map; |
| DecodeDevicePolicy(chrome_device_settings, data_manager, &policy_map); |
| |
| CheckPolicyMap(policy_map, POLICY_SCOPE_MACHINE, |
| /*expected_is_device_policy=*/true); |
| CheckPolicyToPrefTranslation(policy_map, per_input_env); |
| CheckPolicyToCrosSettingsTranslation(chrome_device_settings); |
| } |
| |
| if (proto.has_cloud_policy_settings()) { |
| const enterprise_management::CloudPolicySettings& cloud_policy_settings = |
| proto.cloud_policy_settings(); |
| base::WeakPtr<CloudExternalDataManager> cloud_data_manager; |
| PolicyMap policy_map; |
| DecodeProtoFields(cloud_policy_settings, cloud_data_manager, |
| PolicySource::POLICY_SOURCE_CLOUD, |
| PolicyScope::POLICY_SCOPE_USER, &policy_map, |
| PolicyPerProfileFilter::kAny); |
| |
| CheckPolicyMap(policy_map, POLICY_SCOPE_USER, |
| /*expected_is_device_policy=*/false); |
| CheckPolicyToPrefTranslation(policy_map, per_input_env); |
| } |
| } |
| |
| } // namespace policy |