blob: 949f5c1e583bb6a67d0487860735d3b4ade8a58d [file] [log] [blame]
[email protected]ae7bf342014-08-06 18:03:471// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dcheng4af48582016-04-19 00:29:355#include <memory>
[email protected]ae7bf342014-08-06 18:03:476#include <string>
vabr9984ea62017-04-10 11:33:497#include <utility>
[email protected]ae7bf342014-08-06 18:03:478
blundell6e85b7c2015-09-29 12:33:359#include "base/base_switches.h"
[email protected]ae7bf342014-08-06 18:03:4710#include "base/command_line.h"
[email protected]ae7bf342014-08-06 18:03:4711#include "base/files/file_path.h"
thestig18dfb7a52014-08-26 10:44:0412#include "base/files/file_util.h"
[email protected]ae7bf342014-08-06 18:03:4713#include "base/json/json_file_value_serializer.h"
a-v-y38416862016-12-08 08:40:1314#include "base/json/json_reader.h"
[email protected]ae7bf342014-08-06 18:03:4715#include "base/metrics/histogram_base.h"
16#include "base/metrics/histogram_samples.h"
17#include "base/metrics/statistics_recorder.h"
18#include "base/path_service.h"
[email protected]ae7bf342014-08-06 18:03:4719#include "base/strings/string_number_conversions.h"
20#include "base/strings/string_util.h"
a-v-y38416862016-12-08 08:40:1321#include "base/strings/utf_string_conversions.h"
[email protected]ae7bf342014-08-06 18:03:4722#include "base/values.h"
23#include "build/build_config.h"
24#include "chrome/browser/extensions/extension_browsertest.h"
[email protected]ae7bf342014-08-06 18:03:4725#include "chrome/browser/prefs/chrome_pref_service_factory.h"
26#include "chrome/browser/prefs/profile_pref_store_manager.h"
27#include "chrome/browser/prefs/session_startup_pref.h"
28#include "chrome/browser/profiles/profile.h"
29#include "chrome/browser/ui/browser.h"
30#include "chrome/common/chrome_constants.h"
31#include "chrome/common/chrome_paths.h"
32#include "chrome/common/pref_names.h"
33#include "chrome/test/base/testing_profile.h"
David Bertoni58c113a2019-08-02 19:53:2634#include "components/prefs/pref_service.h"
35#include "components/prefs/scoped_user_pref_update.h"
[email protected]ae7bf342014-08-06 18:03:4736#include "components/search_engines/default_search_manager.h"
a-v-y38416862016-12-08 08:40:1337#include "components/search_engines/template_url_data.h"
Lei Zhangfd5e6f0a2017-11-28 18:24:2938#include "content/public/test/test_launcher.h"
[email protected]ae7bf342014-08-06 18:03:4739#include "extensions/browser/pref_names.h"
40#include "extensions/common/extension.h"
sammcfb473a872017-04-03 01:56:5941#include "services/preferences/public/cpp/tracked/tracked_preference_histogram_names.h"
[email protected]ae7bf342014-08-06 18:03:4742
43#if defined(OS_CHROMEOS)
Steven Bennetts38e9bde22019-01-03 17:31:1044#include "chromeos/constants/chromeos_switches.h"
[email protected]ae7bf342014-08-06 18:03:4745#endif
46
proberge269fd092016-10-04 22:13:4147#if defined(OS_WIN)
gab36b85522017-05-24 19:30:4548#include "base/win/registry.h"
49#include "chrome/install_static/install_util.h"
proberge269fd092016-10-04 22:13:4150#endif
51
[email protected]ae7bf342014-08-06 18:03:4752namespace {
53
54// Extension ID of chrome/test/data/extensions/good.crx
55const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
56
57// Explicit expectations from the caller of GetTrackedPrefHistogramCount(). This
58// enables detailed reporting of the culprit on failure.
59enum AllowedBuckets {
60 // Allow no samples in any buckets.
61 ALLOW_NONE = -1,
62 // Any integer between BEGIN_ALLOW_SINGLE_BUCKET and END_ALLOW_SINGLE_BUCKET
63 // indicates that only this specific bucket is allowed to have a sample.
64 BEGIN_ALLOW_SINGLE_BUCKET = 0,
65 END_ALLOW_SINGLE_BUCKET = 100,
66 // Allow any buckets (no extra verifications performed).
67 ALLOW_ANY
68};
69
proberge269fd092016-10-04 22:13:4170#if defined(OS_WIN)
71base::string16 GetRegistryPathForTestProfile() {
gab36b85522017-05-24 19:30:4572 // Cleanup follow-up to http://crbug.com/721245 for the previous location of
73 // this test key which had similar problems (to a lesser extent). It's
74 // redundant but harmless to have multiple callers hit this on the same
75 // machine. TODO(gab): remove this mid-june 2017.
76 base::win::RegKey key;
77 if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Chromium\\PrefHashBrowserTest",
78 KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
79 LONG result = key.DeleteKey(L"");
80 EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
81 }
82
proberge269fd092016-10-04 22:13:4183 base::FilePath profile_dir;
Avi Drissman9098f9002018-05-04 00:11:5284 EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
gab36b85522017-05-24 19:30:4585
86 // Use a location under the real PreferenceMACs path so that the backup
87 // cleanup logic in ChromeTestLauncherDelegate::PreSharding() for interrupted
88 // tests covers this test key as well.
89 return install_static::GetRegistryPath() +
90 L"\\PreferenceMACs\\PrefHashBrowserTest\\" +
proberge269fd092016-10-04 22:13:4191 profile_dir.BaseName().value();
92}
93#endif
94
[email protected]ae7bf342014-08-06 18:03:4795// Returns the number of times |histogram_name| was reported so far; adding the
96// results of the first 100 buckets (there are only ~19 reporting IDs as of this
97// writing; varies depending on the platform). |allowed_buckets| hints at extra
98// requirements verified in this method (see AllowedBuckets for details).
99int GetTrackedPrefHistogramCount(const char* histogram_name,
proberge269fd092016-10-04 22:13:41100 const char* histogram_suffix,
[email protected]ae7bf342014-08-06 18:03:47101 int allowed_buckets) {
proberge269fd092016-10-04 22:13:41102 std::string full_histogram_name(histogram_name);
103 if (*histogram_suffix)
104 full_histogram_name.append(".").append(histogram_suffix);
[email protected]ae7bf342014-08-06 18:03:47105 const base::HistogramBase* histogram =
proberge269fd092016-10-04 22:13:41106 base::StatisticsRecorder::FindHistogram(full_histogram_name);
[email protected]ae7bf342014-08-06 18:03:47107 if (!histogram)
108 return 0;
109
dcheng4af48582016-04-19 00:29:35110 std::unique_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
[email protected]ae7bf342014-08-06 18:03:47111 int sum = 0;
112 for (int i = 0; i < 100; ++i) {
113 int count_for_id = samples->GetCount(i);
114 EXPECT_GE(count_for_id, 0);
115 sum += count_for_id;
116
117 if (allowed_buckets == ALLOW_NONE ||
118 (allowed_buckets != ALLOW_ANY && i != allowed_buckets)) {
119 EXPECT_EQ(0, count_for_id) << "Unexpected reporting_id: " << i;
120 }
121 }
122 return sum;
123}
124
proberge269fd092016-10-04 22:13:41125// Helper function to call GetTrackedPrefHistogramCount with no external
126// validation suffix.
127int GetTrackedPrefHistogramCount(const char* histogram_name,
128 int allowed_buckets) {
129 return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets);
130}
131
dcheng4af48582016-04-19 00:29:35132std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
[email protected]ae7bf342014-08-06 18:03:47133 const base::FilePath& pref_file) {
prashhir54a994502015-03-05 09:30:57134 JSONFileValueDeserializer deserializer(pref_file);
135 int error_code = JSONFileValueDeserializer::JSON_NO_ERROR;
[email protected]ae7bf342014-08-06 18:03:47136 std::string error_str;
dcheng4af48582016-04-19 00:29:35137 std::unique_ptr<base::Value> prefs =
olli.raulaba045252015-10-16 06:16:40138 deserializer.Deserialize(&error_code, &error_str);
prashhir54a994502015-03-05 09:30:57139 if (!prefs || error_code != JSONFileValueDeserializer::JSON_NO_ERROR) {
[email protected]ae7bf342014-08-06 18:03:47140 ADD_FAILURE() << "Error #" << error_code << ": " << error_str;
dcheng4af48582016-04-19 00:29:35141 return std::unique_ptr<base::DictionaryValue>();
[email protected]ae7bf342014-08-06 18:03:47142 }
jdoerrie1f536b22017-10-23 17:15:11143 if (!prefs->is_dict()) {
[email protected]ae7bf342014-08-06 18:03:47144 ADD_FAILURE();
dcheng4af48582016-04-19 00:29:35145 return std::unique_ptr<base::DictionaryValue>();
[email protected]ae7bf342014-08-06 18:03:47146 }
dcheng4af48582016-04-19 00:29:35147 return std::unique_ptr<base::DictionaryValue>(
[email protected]ae7bf342014-08-06 18:03:47148 static_cast<base::DictionaryValue*>(prefs.release()));
149}
150
proberge269fd092016-10-04 22:13:41151// Returns whether external validation is supported on the platform through
152// storing MACs in the registry.
153bool SupportsRegistryValidation() {
154#if defined(OS_WIN)
155 return true;
156#else
157 return false;
158#endif
159}
160
Victor Costan0e45f27a2019-02-02 00:13:59161#define PREF_HASH_BROWSER_TEST(fixture, test_name) \
162 IN_PROC_BROWSER_TEST_P(fixture, PRE_##test_name) { SetupPreferences(); } \
163 IN_PROC_BROWSER_TEST_P(fixture, test_name) { VerifyReactionToPrefAttack(); } \
164 INSTANTIATE_TEST_SUITE_P( \
165 fixture##Instance, fixture, \
166 testing::Values( \
167 chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement, \
168 chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways, \
169 chrome_prefs::internals:: \
170 kSettingsEnforcementGroupEnforceAlwaysWithDSE, \
171 chrome_prefs::internals:: \
Nico Weber42c88d62019-02-11 03:09:25172 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE))
[email protected]ae7bf342014-08-06 18:03:47173
174// A base fixture designed such that implementations do two things:
175// 1) Override all three pure-virtual methods below to setup, attack, and
176// verify preferenes throughout the tests provided by this fixture.
177// 2) Instantiate their test via the PREF_HASH_BROWSER_TEST macro above.
178// Based on top of ExtensionBrowserTest to allow easy interaction with the
David Bertoni58c113a2019-08-02 19:53:26179// ExtensionRegistry.
[email protected]ae7bf342014-08-06 18:03:47180class PrefHashBrowserTestBase
Devlin Cronin836f545d2018-05-09 00:25:05181 : public extensions::ExtensionBrowserTest,
[email protected]ae7bf342014-08-06 18:03:47182 public testing::WithParamInterface<std::string> {
183 public:
184 // List of potential protection levels for this test in strict increasing
185 // order of protection levels.
186 enum SettingsProtectionLevel {
187 PROTECTION_DISABLED_ON_PLATFORM,
188 PROTECTION_DISABLED_FOR_GROUP,
189 PROTECTION_ENABLED_BASIC,
190 PROTECTION_ENABLED_DSE,
191 PROTECTION_ENABLED_EXTENSIONS,
192 // Represents the strongest level (i.e. always equivalent to the last one in
193 // terms of protection), leave this one last when adding new levels.
194 PROTECTION_ENABLED_ALL
195 };
196
197 PrefHashBrowserTestBase()
198 : protection_level_(GetProtectionLevelFromTrialGroup(GetParam())) {
199 }
200
avi556c05022014-12-22 23:31:43201 void SetUpCommandLine(base::CommandLine* command_line) override {
Devlin Cronin836f545d2018-05-09 00:25:05202 extensions::ExtensionBrowserTest::SetUpCommandLine(command_line);
[email protected]ae7bf342014-08-06 18:03:47203 EXPECT_FALSE(command_line->HasSwitch(switches::kForceFieldTrials));
204 command_line->AppendSwitchASCII(
205 switches::kForceFieldTrials,
206 std::string(chrome_prefs::internals::kSettingsEnforcementTrialName) +
207 "/" + GetParam() + "/");
208#if defined(OS_CHROMEOS)
209 command_line->AppendSwitch(
210 chromeos::switches::kIgnoreUserProfileMappingForTests);
211#endif
212 }
213
dcheng8f4b8622014-10-23 16:37:48214 bool SetUpUserDataDirectory() override {
[email protected]ae7bf342014-08-06 18:03:47215 // Do the normal setup in the PRE test and attack preferences in the main
216 // test.
Lei Zhangfd5e6f0a2017-11-28 18:24:29217 if (content::IsPreTest())
Devlin Cronin836f545d2018-05-09 00:25:05218 return extensions::ExtensionBrowserTest::SetUpUserDataDirectory();
[email protected]ae7bf342014-08-06 18:03:47219
220#if defined(OS_CHROMEOS)
221 // For some reason, the Preferences file does not exist in the location
222 // below on Chrome OS. Since protection is disabled on Chrome OS, it's okay
223 // to simply not attack preferences at all (and still assert that no
224 // hardening related histogram kicked in in VerifyReactionToPrefAttack()).
225 // TODO(gab): Figure out why there is no Preferences file in this location
226 // on Chrome OS (and re-enable the section disabled for OS_CHROMEOS further
227 // below).
228 EXPECT_EQ(PROTECTION_DISABLED_ON_PLATFORM, protection_level_);
229 return true;
230#endif
231
232 base::FilePath profile_dir;
Avi Drissman9098f9002018-05-04 00:11:52233 EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
[email protected]ae7bf342014-08-06 18:03:47234 profile_dir = profile_dir.AppendASCII(TestingProfile::kTestUserProfileDir);
235
236 // Sanity check that old protected pref file is never present in modern
237 // Chromes.
238 EXPECT_FALSE(base::PathExists(
sammcf420c16e2017-03-16 02:11:13239 profile_dir.Append(FILE_PATH_LITERAL("Protected Preferences"))));
[email protected]ae7bf342014-08-06 18:03:47240
241 // Read the preferences from disk.
242
243 const base::FilePath unprotected_pref_file =
244 profile_dir.Append(chrome::kPreferencesFilename);
245 EXPECT_TRUE(base::PathExists(unprotected_pref_file));
246
247 const base::FilePath protected_pref_file =
248 profile_dir.Append(chrome::kSecurePreferencesFilename);
249 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
250 base::PathExists(protected_pref_file));
251
dcheng4af48582016-04-19 00:29:35252 std::unique_ptr<base::DictionaryValue> unprotected_preferences(
[email protected]ae7bf342014-08-06 18:03:47253 ReadPrefsDictionary(unprotected_pref_file));
254 if (!unprotected_preferences)
255 return false;
256
dcheng4af48582016-04-19 00:29:35257 std::unique_ptr<base::DictionaryValue> protected_preferences;
[email protected]ae7bf342014-08-06 18:03:47258 if (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM) {
259 protected_preferences = ReadPrefsDictionary(protected_pref_file);
260 if (!protected_preferences)
261 return false;
262 }
263
264 // Let the underlying test modify the preferences.
265 AttackPreferencesOnDisk(unprotected_preferences.get(),
266 protected_preferences.get());
267
268 // Write the modified preferences back to disk.
269
270 JSONFileValueSerializer unprotected_prefs_serializer(unprotected_pref_file);
271 EXPECT_TRUE(
272 unprotected_prefs_serializer.Serialize(*unprotected_preferences));
273
274 if (protected_preferences) {
275 JSONFileValueSerializer protected_prefs_serializer(protected_pref_file);
276 EXPECT_TRUE(protected_prefs_serializer.Serialize(*protected_preferences));
277 }
278
279 return true;
280 }
281
gabbcdefd0cc2015-02-17 18:12:40282 void SetUpInProcessBrowserTestFixture() override {
Devlin Cronin836f545d2018-05-09 00:25:05283 extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
gabbcdefd0cc2015-02-17 18:12:40284
285 // Bots are on a domain, turn off the domain check for settings hardening in
286 // order to be able to test all SettingsEnforcement groups.
287 chrome_prefs::DisableDomainCheckForTesting();
proberge269fd092016-10-04 22:13:41288
289#if defined(OS_WIN)
290 // Avoid polluting prefs for the user and the bots by writing to a specific
291 // testing registry path.
292 registry_key_for_external_validation_ = GetRegistryPathForTestProfile();
293 ProfilePrefStoreManager::SetPreferenceValidationRegistryPathForTesting(
294 &registry_key_for_external_validation_);
295
296 // Keys should be unique, but to avoid flakes in the long run make sure an
297 // identical test key wasn't left behind by a previous test.
Lei Zhangfd5e6f0a2017-11-28 18:24:29298 if (content::IsPreTest()) {
proberge269fd092016-10-04 22:13:41299 base::win::RegKey key;
300 if (key.Open(HKEY_CURRENT_USER,
301 registry_key_for_external_validation_.c_str(),
302 KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
303 LONG result = key.DeleteKey(L"");
304 ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
305 }
306 }
307#endif
308 }
309
310 void TearDown() override {
311#if defined(OS_WIN)
312 // When done, delete the Registry key to avoid polluting the registry.
Lei Zhangfd5e6f0a2017-11-28 18:24:29313 if (!content::IsPreTest()) {
proberge269fd092016-10-04 22:13:41314 base::string16 registry_key = GetRegistryPathForTestProfile();
315 base::win::RegKey key;
316 if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
317 KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
318 LONG result = key.DeleteKey(L"");
319 ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
320 }
321 }
322#endif
Devlin Cronin836f545d2018-05-09 00:25:05323 extensions::ExtensionBrowserTest::TearDown();
gabbcdefd0cc2015-02-17 18:12:40324 }
325
[email protected]ae7bf342014-08-06 18:03:47326 // In the PRE_ test, find the number of tracked preferences that were
327 // initialized and save it to a file to be read back in the main test and used
328 // as the total number of tracked preferences.
dcheng8f4b8622014-10-23 16:37:48329 void SetUpOnMainThread() override {
Devlin Cronin836f545d2018-05-09 00:25:05330 extensions::ExtensionBrowserTest::SetUpOnMainThread();
[email protected]ae7bf342014-08-06 18:03:47331
332 // File in which the PRE_ test will save the number of tracked preferences
333 // on this platform.
334 const char kNumTrackedPrefFilename[] = "NumTrackedPrefs";
335
336 base::FilePath num_tracked_prefs_file;
337 ASSERT_TRUE(
Avi Drissman9098f9002018-05-04 00:11:52338 base::PathService::Get(chrome::DIR_USER_DATA, &num_tracked_prefs_file));
[email protected]ae7bf342014-08-06 18:03:47339 num_tracked_prefs_file =
340 num_tracked_prefs_file.AppendASCII(kNumTrackedPrefFilename);
341
Lei Zhangfd5e6f0a2017-11-28 18:24:29342 if (content::IsPreTest()) {
[email protected]ae7bf342014-08-06 18:03:47343 num_tracked_prefs_ = GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43344 user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
[email protected]ae7bf342014-08-06 18:03:47345 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
346 num_tracked_prefs_ > 0);
347
gab342aa6182014-10-02 21:59:00348 // Split tracked prefs are reported as Unchanged not as NullInitialized
[email protected]ae7bf342014-08-06 18:03:47349 // when an empty dictionary is encountered on first run (this should only
350 // hit for pref #5 in the current design).
351 int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43352 user_prefs::tracked::kTrackedPrefHistogramUnchanged,
353 BEGIN_ALLOW_SINGLE_BUCKET + 5);
[email protected]ae7bf342014-08-06 18:03:47354 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
355 num_split_tracked_prefs);
356
proberge269fd092016-10-04 22:13:41357 if (SupportsRegistryValidation()) {
358 // Same checks as above, but for the registry.
359 num_tracked_prefs_ = GetTrackedPrefHistogramCount(
360 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
361 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
362 ALLOW_ANY);
363 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
364 num_tracked_prefs_ > 0);
365
366 int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
367 user_prefs::tracked::kTrackedPrefHistogramUnchanged,
368 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
369 BEGIN_ALLOW_SINGLE_BUCKET + 5);
370 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
371 num_split_tracked_prefs);
372 }
373
[email protected]ae7bf342014-08-06 18:03:47374 num_tracked_prefs_ += num_split_tracked_prefs;
375
Raul Tambrefff51b752019-02-04 13:09:47376 std::string num_tracked_prefs_str =
377 base::NumberToString(num_tracked_prefs_);
[email protected]ae7bf342014-08-06 18:03:47378 EXPECT_EQ(static_cast<int>(num_tracked_prefs_str.size()),
379 base::WriteFile(num_tracked_prefs_file,
380 num_tracked_prefs_str.c_str(),
381 num_tracked_prefs_str.size()));
382 } else {
383 std::string num_tracked_prefs_str;
384 EXPECT_TRUE(base::ReadFileToString(num_tracked_prefs_file,
385 &num_tracked_prefs_str));
386 EXPECT_TRUE(
387 base::StringToInt(num_tracked_prefs_str, &num_tracked_prefs_));
388 }
389 }
390
391 protected:
392 // Called from the PRE_ test's body. Overrides should use it to setup
393 // preferences through Chrome.
394 virtual void SetupPreferences() = 0;
395
396 // Called prior to the main test launching its browser. Overrides should use
397 // it to attack preferences. |(un)protected_preferences| represent the state
398 // on disk prior to launching the main test, they can be modified by this
399 // method and modifications will be flushed back to disk before launching the
400 // main test. |unprotected_preferences| is never NULL, |protected_preferences|
401 // may be NULL if in PROTECTION_DISABLED_ON_PLATFORM mode.
402 virtual void AttackPreferencesOnDisk(
403 base::DictionaryValue* unprotected_preferences,
404 base::DictionaryValue* protected_preferences) = 0;
405
406 // Called from the body of the main test. Overrides should use it to verify
407 // that the browser had the desired reaction when faced when the attack
408 // orchestrated in AttackPreferencesOnDisk().
409 virtual void VerifyReactionToPrefAttack() = 0;
410
411 int num_tracked_prefs() const { return num_tracked_prefs_; }
412
413 const SettingsProtectionLevel protection_level_;
414
415 private:
[email protected]ae7bf342014-08-06 18:03:47416 SettingsProtectionLevel GetProtectionLevelFromTrialGroup(
417 const std::string& trial_group) {
418 if (!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking)
419 return PROTECTION_DISABLED_ON_PLATFORM;
420
421// Protection levels can't be adjusted via --force-fieldtrials in official
422// builds.
423#if defined(OFFICIAL_BUILD)
424
proberge2562e6f2017-04-10 17:46:57425#if defined(OS_WIN) || defined(OS_MACOSX)
426 // The strongest mode is enforced on Windows and MacOS in the absence of a
427 // field trial.
[email protected]ae7bf342014-08-06 18:03:47428 return PROTECTION_ENABLED_ALL;
429#else
430 return PROTECTION_DISABLED_FOR_GROUP;
Lei Zhangfd5e6f0a2017-11-28 18:24:29431#endif // defined(OS_WIN) || defined(OS_MACOSX)
[email protected]ae7bf342014-08-06 18:03:47432
433#else // defined(OFFICIAL_BUILD)
434
435 using namespace chrome_prefs::internals;
Lei Zhangfd5e6f0a2017-11-28 18:24:29436 if (trial_group == kSettingsEnforcementGroupNoEnforcement)
[email protected]ae7bf342014-08-06 18:03:47437 return PROTECTION_DISABLED_FOR_GROUP;
Lei Zhangfd5e6f0a2017-11-28 18:24:29438 if (trial_group == kSettingsEnforcementGroupEnforceAlways)
[email protected]ae7bf342014-08-06 18:03:47439 return PROTECTION_ENABLED_BASIC;
Lei Zhangfd5e6f0a2017-11-28 18:24:29440 if (trial_group == kSettingsEnforcementGroupEnforceAlwaysWithDSE)
[email protected]ae7bf342014-08-06 18:03:47441 return PROTECTION_ENABLED_DSE;
Lei Zhangfd5e6f0a2017-11-28 18:24:29442 if (trial_group ==
443 kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE) {
[email protected]ae7bf342014-08-06 18:03:47444 return PROTECTION_ENABLED_EXTENSIONS;
[email protected]ae7bf342014-08-06 18:03:47445 }
Lei Zhangfd5e6f0a2017-11-28 18:24:29446 ADD_FAILURE();
447 return static_cast<SettingsProtectionLevel>(-1);
[email protected]ae7bf342014-08-06 18:03:47448#endif // defined(OFFICIAL_BUILD)
[email protected]ae7bf342014-08-06 18:03:47449 }
450
451 int num_tracked_prefs_;
proberge269fd092016-10-04 22:13:41452
453#if defined(OS_WIN)
454 base::string16 registry_key_for_external_validation_;
455#endif
[email protected]ae7bf342014-08-06 18:03:47456};
457
458} // namespace
459
460// Verifies that nothing is reset when nothing is tampered with.
461// Also sanity checks that the expected preferences files are in place.
462class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase {
463 public:
dcheng8f4b8622014-10-23 16:37:48464 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47465 // Default Chrome setup.
466 }
467
dcheng8f4b8622014-10-23 16:37:48468 void AttackPreferencesOnDisk(
[email protected]ae7bf342014-08-06 18:03:47469 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17470 base::DictionaryValue* protected_preferences) override {
[email protected]ae7bf342014-08-06 18:03:47471 // No attack.
472 }
473
dcheng8f4b8622014-10-23 16:37:48474 void VerifyReactionToPrefAttack() override {
[email protected]ae7bf342014-08-06 18:03:47475 // Expect all prefs to be reported as Unchanged with no resets.
deepak.m113481c82015-12-16 05:21:43476 EXPECT_EQ(
477 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
478 ? num_tracked_prefs()
479 : 0,
480 GetTrackedPrefHistogramCount(
481 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
482 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
483 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
484 ALLOW_NONE));
[email protected]ae7bf342014-08-06 18:03:47485 EXPECT_EQ(0,
486 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43487 user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
[email protected]ae7bf342014-08-06 18:03:47488
489 // Nothing else should have triggered.
[email protected]ae7bf342014-08-06 18:03:47490 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43491 0, GetTrackedPrefHistogramCount(
492 user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
493 EXPECT_EQ(
494 0, GetTrackedPrefHistogramCount(
495 user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
496 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
497 user_prefs::tracked::kTrackedPrefHistogramInitialized,
498 ALLOW_NONE));
499 EXPECT_EQ(0,
500 GetTrackedPrefHistogramCount(
501 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
502 ALLOW_NONE));
503 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
504 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
505 ALLOW_NONE));
506 EXPECT_EQ(
507 0, GetTrackedPrefHistogramCount(
508 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
509 ALLOW_NONE));
proberge269fd092016-10-04 22:13:41510
511 if (SupportsRegistryValidation()) {
512 // Expect all prefs to be reported as Unchanged.
513 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
514 ? num_tracked_prefs()
515 : 0,
516 GetTrackedPrefHistogramCount(
517 user_prefs::tracked::kTrackedPrefHistogramUnchanged,
518 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
519 ALLOW_ANY));
520 }
[email protected]ae7bf342014-08-06 18:03:47521 }
522};
523
gab36b85522017-05-24 19:30:45524PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedDefault, UnchangedDefault);
[email protected]ae7bf342014-08-06 18:03:47525
526// Augments PrefHashBrowserTestUnchangedDefault to confirm that nothing is reset
527// when nothing is tampered with, even if Chrome itself wrote custom prefs in
528// its last run.
529class PrefHashBrowserTestUnchangedCustom
530 : public PrefHashBrowserTestUnchangedDefault {
531 public:
dcheng8f4b8622014-10-23 16:37:48532 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47533 profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
534
535 InstallExtensionWithUIAutoConfirm(
536 test_data_dir_.AppendASCII("good.crx"), 1, browser());
537 }
538
dcheng8f4b8622014-10-23 16:37:48539 void VerifyReactionToPrefAttack() override {
[email protected]ae7bf342014-08-06 18:03:47540 // Make sure the settings written in the last run stuck.
541 EXPECT_EQ("http://example.com",
542 profile()->GetPrefs()->GetString(prefs::kHomePage));
543
David Bertoni58c113a2019-08-02 19:53:26544 EXPECT_TRUE(extension_registry()->GetExtensionById(
545 kGoodCrxId, extensions::ExtensionRegistry::ENABLED));
[email protected]ae7bf342014-08-06 18:03:47546
547 // Reaction should be identical to unattacked default prefs.
548 PrefHashBrowserTestUnchangedDefault::VerifyReactionToPrefAttack();
549 }
550};
551
gab36b85522017-05-24 19:30:45552PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedCustom, UnchangedCustom);
[email protected]ae7bf342014-08-06 18:03:47553
554// Verifies that cleared prefs are reported.
555class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase {
556 public:
dcheng8f4b8622014-10-23 16:37:48557 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47558 profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
559 }
560
dcheng8f4b8622014-10-23 16:37:48561 void AttackPreferencesOnDisk(
[email protected]ae7bf342014-08-06 18:03:47562 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17563 base::DictionaryValue* protected_preferences) override {
[email protected]ae7bf342014-08-06 18:03:47564 base::DictionaryValue* selected_prefs =
565 protection_level_ >= PROTECTION_ENABLED_BASIC ? protected_preferences
566 : unprotected_preferences;
567 // |selected_prefs| should never be NULL under the protection level picking
568 // it.
569 EXPECT_TRUE(selected_prefs);
570 EXPECT_TRUE(selected_prefs->Remove(prefs::kHomePage, NULL));
571 }
572
dcheng8f4b8622014-10-23 16:37:48573 void VerifyReactionToPrefAttack() override {
[email protected]ae7bf342014-08-06 18:03:47574 // The clearance of homepage should have been noticed (as pref #2 being
575 // cleared), but shouldn't have triggered a reset (as there is nothing we
576 // can do when the pref is already gone).
577 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
[email protected]ae7bf342014-08-06 18:03:47578 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43579 user_prefs::tracked::kTrackedPrefHistogramCleared,
580 BEGIN_ALLOW_SINGLE_BUCKET + 2));
581 EXPECT_EQ(
582 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
583 ? num_tracked_prefs() - 1
584 : 0,
585 GetTrackedPrefHistogramCount(
586 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
587 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
588 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
589 ALLOW_NONE));
[email protected]ae7bf342014-08-06 18:03:47590 EXPECT_EQ(0,
591 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43592 user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
[email protected]ae7bf342014-08-06 18:03:47593
594 // Nothing else should have triggered.
[email protected]ae7bf342014-08-06 18:03:47595 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43596 0, GetTrackedPrefHistogramCount(
597 user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
598 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
599 user_prefs::tracked::kTrackedPrefHistogramInitialized,
600 ALLOW_NONE));
601 EXPECT_EQ(0,
602 GetTrackedPrefHistogramCount(
603 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
604 ALLOW_NONE));
605 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
606 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
607 ALLOW_NONE));
608 EXPECT_EQ(
609 0, GetTrackedPrefHistogramCount(
610 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
611 ALLOW_NONE));
proberge269fd092016-10-04 22:13:41612
613 if (SupportsRegistryValidation()) {
614 // Expect homepage clearance to have been noticed by registry validation.
615 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
616 GetTrackedPrefHistogramCount(
617 user_prefs::tracked::kTrackedPrefHistogramCleared,
618 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
619 BEGIN_ALLOW_SINGLE_BUCKET + 2));
620 }
[email protected]ae7bf342014-08-06 18:03:47621 }
622};
623
gab36b85522017-05-24 19:30:45624PREF_HASH_BROWSER_TEST(PrefHashBrowserTestClearedAtomic, ClearedAtomic);
[email protected]ae7bf342014-08-06 18:03:47625
626// Verifies that clearing the MACs results in untrusted Initialized pings for
627// non-null protected prefs.
628class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase {
629 public:
dcheng8f4b8622014-10-23 16:37:48630 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47631 // Explicitly set the DSE (it's otherwise NULL by default, preventing
632 // thorough testing of the PROTECTION_ENABLED_DSE level).
633 DefaultSearchManager default_search_manager(
634 profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
635 DefaultSearchManager::Source dse_source =
636 static_cast<DefaultSearchManager::Source>(-1);
637
638 const TemplateURLData* default_template_url_data =
639 default_search_manager.GetDefaultSearchEngine(&dse_source);
640 EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, dse_source);
641
642 default_search_manager.SetUserSelectedDefaultSearchEngine(
643 *default_template_url_data);
644
645 default_search_manager.GetDefaultSearchEngine(&dse_source);
646 EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
647
648 // Also explicitly set an atomic pref that falls under
649 // PROTECTION_ENABLED_BASIC.
650 profile()->GetPrefs()->SetInteger(prefs::kRestoreOnStartup,
651 SessionStartupPref::URLS);
652 }
653
dcheng8f4b8622014-10-23 16:37:48654 void AttackPreferencesOnDisk(
[email protected]ae7bf342014-08-06 18:03:47655 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17656 base::DictionaryValue* protected_preferences) override {
proberge574d7d92016-08-01 20:14:11657 unprotected_preferences->Remove("protection.macs", NULL);
[email protected]ae7bf342014-08-06 18:03:47658 if (protected_preferences)
proberge574d7d92016-08-01 20:14:11659 protected_preferences->Remove("protection.macs", NULL);
[email protected]ae7bf342014-08-06 18:03:47660 }
661
dcheng8f4b8622014-10-23 16:37:48662 void VerifyReactionToPrefAttack() override {
gab342aa6182014-10-02 21:59:00663 // Preferences that are NULL by default will be NullInitialized.
[email protected]ae7bf342014-08-06 18:03:47664 int num_null_values = GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43665 user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
[email protected]ae7bf342014-08-06 18:03:47666 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
667 num_null_values > 0);
668 if (num_null_values > 0) {
669 // This test requires that at least 3 prefs be non-null (extensions, DSE,
670 // and 1 atomic pref explictly set for this test above).
gab342aa6182014-10-02 21:59:00671 EXPECT_GE(num_tracked_prefs() - num_null_values, 3);
[email protected]ae7bf342014-08-06 18:03:47672 }
673
674 // Expect all non-null prefs to be reported as Initialized (with
675 // accompanying resets or wanted resets based on the current protection
676 // level).
deepak.m113481c82015-12-16 05:21:43677 EXPECT_EQ(
678 num_tracked_prefs() - num_null_values,
679 GetTrackedPrefHistogramCount(
680 user_prefs::tracked::kTrackedPrefHistogramInitialized, ALLOW_ANY));
[email protected]ae7bf342014-08-06 18:03:47681
682 int num_protected_prefs = 0;
683 // A switch statement falling through each protection level in decreasing
684 // levels of protection to add expectations for each level which augments
685 // the previous one.
686 switch (protection_level_) {
687 case PROTECTION_ENABLED_ALL:
[email protected]ae7bf342014-08-06 18:03:47688 case PROTECTION_ENABLED_EXTENSIONS:
689 ++num_protected_prefs;
Nico Weber1c64f9a2018-01-30 12:00:48690 FALLTHROUGH;
[email protected]ae7bf342014-08-06 18:03:47691 case PROTECTION_ENABLED_DSE:
692 ++num_protected_prefs;
Nico Weber1c64f9a2018-01-30 12:00:48693 FALLTHROUGH;
[email protected]ae7bf342014-08-06 18:03:47694 case PROTECTION_ENABLED_BASIC:
695 num_protected_prefs += num_tracked_prefs() - num_null_values - 2;
Nico Weber1c64f9a2018-01-30 12:00:48696 FALLTHROUGH;
[email protected]ae7bf342014-08-06 18:03:47697 case PROTECTION_DISABLED_FOR_GROUP:
[email protected]ae7bf342014-08-06 18:03:47698 case PROTECTION_DISABLED_ON_PLATFORM:
699 // No protection.
700 break;
701 }
702
deepak.m113481c82015-12-16 05:21:43703 EXPECT_EQ(
704 num_tracked_prefs() - num_null_values - num_protected_prefs,
705 GetTrackedPrefHistogramCount(
706 user_prefs::tracked::kTrackedPrefHistogramWantedReset, ALLOW_ANY));
[email protected]ae7bf342014-08-06 18:03:47707 EXPECT_EQ(num_protected_prefs,
deepak.m113481c82015-12-16 05:21:43708 GetTrackedPrefHistogramCount(
709 user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_ANY));
[email protected]ae7bf342014-08-06 18:03:47710
711 // Explicitly verify the result of reported resets.
712
713 DefaultSearchManager default_search_manager(
714 profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
715 DefaultSearchManager::Source dse_source =
716 static_cast<DefaultSearchManager::Source>(-1);
717 default_search_manager.GetDefaultSearchEngine(&dse_source);
718 EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_DSE
719 ? DefaultSearchManager::FROM_USER
720 : DefaultSearchManager::FROM_FALLBACK,
721 dse_source);
722
723 EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_BASIC,
724 profile()->GetPrefs()->GetInteger(prefs::kRestoreOnStartup) ==
725 SessionStartupPref::URLS);
726
727 // Nothing else should have triggered.
deepak.m113481c82015-12-16 05:21:43728 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
729 user_prefs::tracked::kTrackedPrefHistogramUnchanged,
730 ALLOW_NONE));
[email protected]ae7bf342014-08-06 18:03:47731 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43732 0, GetTrackedPrefHistogramCount(
733 user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
734 EXPECT_EQ(
735 0, GetTrackedPrefHistogramCount(
736 user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
737 EXPECT_EQ(
738 0, GetTrackedPrefHistogramCount(
739 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
740 ALLOW_NONE));
proberge269fd092016-10-04 22:13:41741
742 if (SupportsRegistryValidation()) {
743 // The MACs have been cleared but the preferences have not been tampered.
744 // The registry should report all prefs as unchanged.
745 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
746 ? num_tracked_prefs()
747 : 0,
748 GetTrackedPrefHistogramCount(
749 user_prefs::tracked::kTrackedPrefHistogramUnchanged,
750 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
751 ALLOW_ANY));
752 }
[email protected]ae7bf342014-08-06 18:03:47753 }
754};
755
756PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedInitialized,
gab36b85522017-05-24 19:30:45757 UntrustedInitialized);
[email protected]ae7bf342014-08-06 18:03:47758
759// Verifies that changing an atomic pref results in it being reported (and reset
760// if the protection level allows it).
761class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase {
762 public:
dcheng8f4b8622014-10-23 16:37:48763 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47764 profile()->GetPrefs()->SetInteger(prefs::kRestoreOnStartup,
765 SessionStartupPref::URLS);
766
767 ListPrefUpdate update(profile()->GetPrefs(),
768 prefs::kURLsToRestoreOnStartup);
769 update->AppendString("http://example.com");
770 }
771
dcheng8f4b8622014-10-23 16:37:48772 void AttackPreferencesOnDisk(
[email protected]ae7bf342014-08-06 18:03:47773 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17774 base::DictionaryValue* protected_preferences) override {
[email protected]ae7bf342014-08-06 18:03:47775 base::DictionaryValue* selected_prefs =
776 protection_level_ >= PROTECTION_ENABLED_BASIC ? protected_preferences
777 : unprotected_preferences;
778 // |selected_prefs| should never be NULL under the protection level picking
779 // it.
780 EXPECT_TRUE(selected_prefs);
781 base::ListValue* startup_urls;
782 EXPECT_TRUE(
783 selected_prefs->GetList(prefs::kURLsToRestoreOnStartup, &startup_urls));
784 EXPECT_TRUE(startup_urls);
785 EXPECT_EQ(1U, startup_urls->GetSize());
786 startup_urls->AppendString("http://example.org");
787 }
788
dcheng8f4b8622014-10-23 16:37:48789 void VerifyReactionToPrefAttack() override {
[email protected]ae7bf342014-08-06 18:03:47790 // Expect a single Changed event for tracked pref #4 (startup URLs).
791 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
[email protected]ae7bf342014-08-06 18:03:47792 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43793 user_prefs::tracked::kTrackedPrefHistogramChanged,
794 BEGIN_ALLOW_SINGLE_BUCKET + 4));
[email protected]ae7bf342014-08-06 18:03:47795 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43796 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
797 ? num_tracked_prefs() - 1
798 : 0,
799 GetTrackedPrefHistogramCount(
800 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
801
802 EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
803 protection_level_ < PROTECTION_ENABLED_BASIC)
804 ? 1
805 : 0,
806 GetTrackedPrefHistogramCount(
807 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
808 BEGIN_ALLOW_SINGLE_BUCKET + 4));
[email protected]ae7bf342014-08-06 18:03:47809 EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 1 : 0,
deepak.m113481c82015-12-16 05:21:43810 GetTrackedPrefHistogramCount(
811 user_prefs::tracked::kTrackedPrefHistogramReset,
812 BEGIN_ALLOW_SINGLE_BUCKET + 4));
[email protected]ae7bf342014-08-06 18:03:47813
814// TODO(gab): This doesn't work on OS_CHROMEOS because we fail to attack
815// Preferences.
816#if !defined(OS_CHROMEOS)
817 // Explicitly verify the result of reported resets.
818 EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 0U : 2U,
819 profile()
820 ->GetPrefs()
821 ->GetList(prefs::kURLsToRestoreOnStartup)
822 ->GetSize());
823#endif
824
825 // Nothing else should have triggered.
[email protected]ae7bf342014-08-06 18:03:47826 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43827 0, GetTrackedPrefHistogramCount(
828 user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
829 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
830 user_prefs::tracked::kTrackedPrefHistogramInitialized,
831 ALLOW_NONE));
832 EXPECT_EQ(0,
833 GetTrackedPrefHistogramCount(
834 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
835 ALLOW_NONE));
836 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
837 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
838 ALLOW_NONE));
839 EXPECT_EQ(
840 0, GetTrackedPrefHistogramCount(
841 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
842 ALLOW_NONE));
proberge269fd092016-10-04 22:13:41843
844 if (SupportsRegistryValidation()) {
845 // Expect a single Changed event for tracked pref #4 (startup URLs).
846 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
847 GetTrackedPrefHistogramCount(
848 user_prefs::tracked::kTrackedPrefHistogramChanged,
849 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
850 BEGIN_ALLOW_SINGLE_BUCKET + 4));
851 }
[email protected]ae7bf342014-08-06 18:03:47852 }
853};
854
gab36b85522017-05-24 19:30:45855PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedAtomic, ChangedAtomic);
[email protected]ae7bf342014-08-06 18:03:47856
857// Verifies that changing or adding an entry in a split pref results in both
858// items being reported (and remove if the protection level allows it).
859class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase {
860 public:
dcheng8f4b8622014-10-23 16:37:48861 void SetupPreferences() override {
[email protected]ae7bf342014-08-06 18:03:47862 InstallExtensionWithUIAutoConfirm(
863 test_data_dir_.AppendASCII("good.crx"), 1, browser());
864 }
865
dcheng8f4b8622014-10-23 16:37:48866 void AttackPreferencesOnDisk(
[email protected]ae7bf342014-08-06 18:03:47867 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17868 base::DictionaryValue* protected_preferences) override {
[email protected]ae7bf342014-08-06 18:03:47869 base::DictionaryValue* selected_prefs =
870 protection_level_ >= PROTECTION_ENABLED_EXTENSIONS
871 ? protected_preferences
872 : unprotected_preferences;
873 // |selected_prefs| should never be NULL under the protection level picking
874 // it.
875 EXPECT_TRUE(selected_prefs);
876 base::DictionaryValue* extensions_dict;
877 EXPECT_TRUE(selected_prefs->GetDictionary(
878 extensions::pref_names::kExtensions, &extensions_dict));
879 EXPECT_TRUE(extensions_dict);
880
881 // Tamper with any installed setting for good.crx
882 base::DictionaryValue* good_crx_dict;
883 EXPECT_TRUE(extensions_dict->GetDictionary(kGoodCrxId, &good_crx_dict));
884 int good_crx_state;
885 EXPECT_TRUE(good_crx_dict->GetInteger("state", &good_crx_state));
886 EXPECT_EQ(extensions::Extension::ENABLED, good_crx_state);
887 good_crx_dict->SetInteger("state", extensions::Extension::DISABLED);
888
889 // Drop a fake extension (for the purpose of this test, dropped settings
890 // don't need to be valid extension settings).
Jeremy Romanec48d7a2018-03-01 17:35:09891 auto fake_extension = std::make_unique<base::DictionaryValue>();
[email protected]ae7bf342014-08-06 18:03:47892 fake_extension->SetString("name", "foo");
vabr9984ea62017-04-10 11:33:49893 extensions_dict->Set(std::string(32, 'a'), std::move(fake_extension));
[email protected]ae7bf342014-08-06 18:03:47894 }
895
dcheng8f4b8622014-10-23 16:37:48896 void VerifyReactionToPrefAttack() override {
[email protected]ae7bf342014-08-06 18:03:47897 // Expect a single split pref changed report with a count of 2 for tracked
898 // pref #5 (extensions).
899 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
deepak.m113481c82015-12-16 05:21:43900 GetTrackedPrefHistogramCount(
901 user_prefs::tracked::kTrackedPrefHistogramChanged,
902 BEGIN_ALLOW_SINGLE_BUCKET + 5));
[email protected]ae7bf342014-08-06 18:03:47903 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
904 GetTrackedPrefHistogramCount(
905 "Settings.TrackedSplitPreferenceChanged.extensions.settings",
906 BEGIN_ALLOW_SINGLE_BUCKET + 2));
907
908 // Everything else should have remained unchanged.
[email protected]ae7bf342014-08-06 18:03:47909 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43910 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
911 ? num_tracked_prefs() - 1
912 : 0,
913 GetTrackedPrefHistogramCount(
914 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
915
916 EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
917 protection_level_ < PROTECTION_ENABLED_EXTENSIONS)
918 ? 1
919 : 0,
920 GetTrackedPrefHistogramCount(
921 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
922 BEGIN_ALLOW_SINGLE_BUCKET + 5));
[email protected]ae7bf342014-08-06 18:03:47923 EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_EXTENSIONS ? 1 : 0,
deepak.m113481c82015-12-16 05:21:43924 GetTrackedPrefHistogramCount(
925 user_prefs::tracked::kTrackedPrefHistogramReset,
926 BEGIN_ALLOW_SINGLE_BUCKET + 5));
[email protected]ae7bf342014-08-06 18:03:47927
928 EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_EXTENSIONS,
David Bertoni58c113a2019-08-02 19:53:26929 extension_registry()->GetExtensionById(
930 kGoodCrxId, extensions::ExtensionRegistry::COMPATIBILITY) !=
931 nullptr);
[email protected]ae7bf342014-08-06 18:03:47932
933 // Nothing else should have triggered.
[email protected]ae7bf342014-08-06 18:03:47934 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43935 0, GetTrackedPrefHistogramCount(
936 user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
937 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
938 user_prefs::tracked::kTrackedPrefHistogramInitialized,
939 ALLOW_NONE));
940 EXPECT_EQ(0,
941 GetTrackedPrefHistogramCount(
942 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
943 ALLOW_NONE));
944 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
945 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
946 ALLOW_NONE));
947 EXPECT_EQ(
948 0, GetTrackedPrefHistogramCount(
949 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
950 ALLOW_NONE));
proberge269fd092016-10-04 22:13:41951
952 if (SupportsRegistryValidation()) {
953 // Expect that the registry validation caught the invalid MAC in split
954 // pref #5 (extensions).
955 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
956 GetTrackedPrefHistogramCount(
957 user_prefs::tracked::kTrackedPrefHistogramChanged,
958 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
959 BEGIN_ALLOW_SINGLE_BUCKET + 5));
960 }
[email protected]ae7bf342014-08-06 18:03:47961 }
962};
963
gab36b85522017-05-24 19:30:45964PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedSplitPref, ChangedSplitPref);
gabb004a562014-09-16 12:45:22965
966// Verifies that adding a value to unprotected preferences for a key which is
967// still using the default (i.e. has no value stored in protected preferences)
968// doesn't allow that value to slip in with no valid MAC (regression test for
969// http://crbug.com/414554)
970class PrefHashBrowserTestUntrustedAdditionToPrefs
971 : public PrefHashBrowserTestBase {
972 public:
dcheng8f4b8622014-10-23 16:37:48973 void SetupPreferences() override {
gabb004a562014-09-16 12:45:22974 // Ensure there is no user-selected value for kRestoreOnStartup.
975 EXPECT_FALSE(
976 profile()->GetPrefs()->GetUserPrefValue(prefs::kRestoreOnStartup));
977 }
978
dcheng8f4b8622014-10-23 16:37:48979 void AttackPreferencesOnDisk(
gabb004a562014-09-16 12:45:22980 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:17981 base::DictionaryValue* protected_preferences) override {
gabb004a562014-09-16 12:45:22982 unprotected_preferences->SetInteger(prefs::kRestoreOnStartup,
983 SessionStartupPref::LAST);
984 }
985
dcheng8f4b8622014-10-23 16:37:48986 void VerifyReactionToPrefAttack() override {
gabb004a562014-09-16 12:45:22987 // Expect a single Changed event for tracked pref #3 (kRestoreOnStartup) if
988 // not protecting; if protection is enabled the change should be a no-op.
989 int changed_expected =
990 protection_level_ == PROTECTION_DISABLED_FOR_GROUP ? 1 : 0;
deepak.m113481c82015-12-16 05:21:43991 EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
992 protection_level_ < PROTECTION_ENABLED_BASIC)
993 ? changed_expected
994 : 0,
gabb004a562014-09-16 12:45:22995 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:43996 user_prefs::tracked::kTrackedPrefHistogramChanged,
997 BEGIN_ALLOW_SINGLE_BUCKET + 3));
gabb004a562014-09-16 12:45:22998 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:43999 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
1000 ? num_tracked_prefs() - changed_expected
1001 : 0,
1002 GetTrackedPrefHistogramCount(
1003 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
1004
1005 EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
1006 protection_level_ < PROTECTION_ENABLED_BASIC)
1007 ? 1
1008 : 0,
1009 GetTrackedPrefHistogramCount(
1010 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
1011 BEGIN_ALLOW_SINGLE_BUCKET + 3));
gabb004a562014-09-16 12:45:221012 EXPECT_EQ(0,
deepak.m113481c82015-12-16 05:21:431013 GetTrackedPrefHistogramCount(
1014 user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
gabb004a562014-09-16 12:45:221015
1016 // Nothing else should have triggered.
gabb004a562014-09-16 12:45:221017 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:431018 0, GetTrackedPrefHistogramCount(
1019 user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
1020 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
1021 user_prefs::tracked::kTrackedPrefHistogramInitialized,
1022 ALLOW_NONE));
1023 EXPECT_EQ(0,
1024 GetTrackedPrefHistogramCount(
1025 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
1026 ALLOW_NONE));
1027 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
1028 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
1029 ALLOW_NONE));
1030 EXPECT_EQ(
1031 0, GetTrackedPrefHistogramCount(
1032 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
1033 ALLOW_NONE));
proberge269fd092016-10-04 22:13:411034
1035 if (SupportsRegistryValidation()) {
1036 EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
1037 protection_level_ < PROTECTION_ENABLED_BASIC)
1038 ? changed_expected
1039 : 0,
1040 GetTrackedPrefHistogramCount(
1041 user_prefs::tracked::kTrackedPrefHistogramChanged,
1042 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
1043 BEGIN_ALLOW_SINGLE_BUCKET + 3));
1044 }
gabb004a562014-09-16 12:45:221045 }
1046};
1047
1048PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefs,
gab36b85522017-05-24 19:30:451049 UntrustedAdditionToPrefs);
erikwrightf4e02b72014-09-17 20:25:451050
1051// Verifies that adding a value to unprotected preferences while wiping a
1052// user-selected value from protected preferences doesn't allow that value to
1053// slip in with no valid MAC (regression test for http://crbug.com/414554).
1054class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe
1055 : public PrefHashBrowserTestBase {
1056 public:
dcheng8f4b8622014-10-23 16:37:481057 void SetupPreferences() override {
erikwrightf4e02b72014-09-17 20:25:451058 profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
1059 }
1060
dcheng8f4b8622014-10-23 16:37:481061 void AttackPreferencesOnDisk(
erikwrightf4e02b72014-09-17 20:25:451062 base::DictionaryValue* unprotected_preferences,
mostynb2b52d1db2014-10-07 02:47:171063 base::DictionaryValue* protected_preferences) override {
erikwrightf4e02b72014-09-17 20:25:451064 // Set or change the value in Preferences to the attacker's choice.
1065 unprotected_preferences->SetString(prefs::kHomePage, "http://example.net");
1066 // Clear the value in Secure Preferences, if any.
1067 if (protected_preferences)
1068 protected_preferences->Remove(prefs::kHomePage, NULL);
1069 }
1070
dcheng8f4b8622014-10-23 16:37:481071 void VerifyReactionToPrefAttack() override {
erikwrightf4e02b72014-09-17 20:25:451072 // Expect a single Changed event for tracked pref #2 (kHomePage) if
1073 // not protecting; if protection is enabled the change should be a Cleared.
1074 int changed_expected =
1075 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
1076 protection_level_ < PROTECTION_ENABLED_BASIC
1077 ? 1 : 0;
1078 int cleared_expected =
1079 protection_level_ >= PROTECTION_ENABLED_BASIC
1080 ? 1 : 0;
1081 EXPECT_EQ(changed_expected,
erikwrightf4e02b72014-09-17 20:25:451082 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:431083 user_prefs::tracked::kTrackedPrefHistogramChanged,
1084 BEGIN_ALLOW_SINGLE_BUCKET + 2));
1085 EXPECT_EQ(cleared_expected,
1086 GetTrackedPrefHistogramCount(
1087 user_prefs::tracked::kTrackedPrefHistogramCleared,
1088 BEGIN_ALLOW_SINGLE_BUCKET + 2));
erikwrightf4e02b72014-09-17 20:25:451089 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:431090 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
1091 ? num_tracked_prefs() - changed_expected - cleared_expected
1092 : 0,
1093 GetTrackedPrefHistogramCount(
1094 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
1095
1096 EXPECT_EQ(changed_expected,
1097 GetTrackedPrefHistogramCount(
1098 user_prefs::tracked::kTrackedPrefHistogramWantedReset,
1099 BEGIN_ALLOW_SINGLE_BUCKET + 2));
erikwrightf4e02b72014-09-17 20:25:451100 EXPECT_EQ(0,
deepak.m113481c82015-12-16 05:21:431101 GetTrackedPrefHistogramCount(
1102 user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
erikwrightf4e02b72014-09-17 20:25:451103
1104 // Nothing else should have triggered.
deepak.m113481c82015-12-16 05:21:431105 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
1106 user_prefs::tracked::kTrackedPrefHistogramInitialized,
1107 ALLOW_NONE));
erikwrightf4e02b72014-09-17 20:25:451108 EXPECT_EQ(0,
1109 GetTrackedPrefHistogramCount(
deepak.m113481c82015-12-16 05:21:431110 user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
1111 ALLOW_NONE));
1112 EXPECT_EQ(0, GetTrackedPrefHistogramCount(
1113 user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
1114 ALLOW_NONE));
erikwrightf4e02b72014-09-17 20:25:451115 EXPECT_EQ(
deepak.m113481c82015-12-16 05:21:431116 0, GetTrackedPrefHistogramCount(
1117 user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
1118 ALLOW_NONE));
proberge269fd092016-10-04 22:13:411119
1120 if (SupportsRegistryValidation()) {
1121 EXPECT_EQ(changed_expected,
1122 GetTrackedPrefHistogramCount(
1123 user_prefs::tracked::kTrackedPrefHistogramChanged,
1124 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
1125 BEGIN_ALLOW_SINGLE_BUCKET + 2));
1126 EXPECT_EQ(cleared_expected,
1127 GetTrackedPrefHistogramCount(
1128 user_prefs::tracked::kTrackedPrefHistogramCleared,
1129 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
1130 BEGIN_ALLOW_SINGLE_BUCKET + 2));
1131 }
erikwrightf4e02b72014-09-17 20:25:451132 }
1133};
1134
1135PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe,
gab36b85522017-05-24 19:30:451136 UntrustedAdditionToPrefsAfterWipe);
proberge269fd092016-10-04 22:13:411137
1138#if defined(OS_WIN)
1139class PrefHashBrowserTestRegistryValidationFailure
1140 : public PrefHashBrowserTestBase {
1141 public:
1142 void SetupPreferences() override {
1143 profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
1144 }
1145
1146 void AttackPreferencesOnDisk(
1147 base::DictionaryValue* unprotected_preferences,
1148 base::DictionaryValue* protected_preferences) override {
1149 base::string16 registry_key =
1150 GetRegistryPathForTestProfile() + L"\\PreferenceMACs\\Default";
1151 base::win::RegKey key;
1152 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
1153 KEY_SET_VALUE | KEY_WOW64_32KEY));
1154 // An incorrect hash should still have the correct size.
1155 ASSERT_EQ(ERROR_SUCCESS,
1156 key.WriteValue(L"homepage", base::string16(64, 'A').c_str()));
1157 }
1158
1159 void VerifyReactionToPrefAttack() override {
1160 EXPECT_EQ(
1161 protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
1162 ? num_tracked_prefs()
1163 : 0,
1164 GetTrackedPrefHistogramCount(
1165 user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
1166
1167 if (SupportsRegistryValidation()) {
1168 // Expect that the registry validation caught the invalid MAC for pref #2
1169 // (homepage).
1170 EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
1171 GetTrackedPrefHistogramCount(
1172 user_prefs::tracked::kTrackedPrefHistogramChanged,
1173 user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
1174 BEGIN_ALLOW_SINGLE_BUCKET + 2));
1175 }
1176 }
1177};
1178
1179PREF_HASH_BROWSER_TEST(PrefHashBrowserTestRegistryValidationFailure,
gab36b85522017-05-24 19:30:451180 RegistryValidationFailure);
proberge269fd092016-10-04 22:13:411181#endif
a-v-y38416862016-12-08 08:40:131182
1183// Verifies that all preferences related to choice of default search engine are
1184// protected.
1185class PrefHashBrowserTestDefaultSearch : public PrefHashBrowserTestBase {
1186 public:
1187 void SetupPreferences() override {
1188 // Set user selected default search engine.
1189 DefaultSearchManager default_search_manager(
1190 profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
1191 DefaultSearchManager::Source dse_source =
1192 static_cast<DefaultSearchManager::Source>(-1);
1193
1194 TemplateURLData user_dse;
1195 user_dse.SetKeyword(base::UTF8ToUTF16("userkeyword"));
1196 user_dse.SetShortName(base::UTF8ToUTF16("username"));
1197 user_dse.SetURL("http://user_default_engine/search?q=good_user_query");
1198 default_search_manager.SetUserSelectedDefaultSearchEngine(user_dse);
1199
1200 const TemplateURLData* current_dse =
1201 default_search_manager.GetDefaultSearchEngine(&dse_source);
1202 EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
1203 EXPECT_EQ(current_dse->keyword(), base::UTF8ToUTF16("userkeyword"));
1204 EXPECT_EQ(current_dse->short_name(), base::UTF8ToUTF16("username"));
1205 EXPECT_EQ(current_dse->url(),
1206 "http://user_default_engine/search?q=good_user_query");
1207 }
1208
1209 void AttackPreferencesOnDisk(
1210 base::DictionaryValue* unprotected_preferences,
1211 base::DictionaryValue* protected_preferences) override {
1212 static constexpr char default_search_provider_data[] = R"(
1213 {
1214 "default_search_provider_data" : {
1215 "template_url_data" : {
1216 "keyword" : "badkeyword",
1217 "short_name" : "badname",
1218 "url" : "http://bad_default_engine/search?q=dirty_user_query"
1219 }
1220 }
1221 })";
1222 static constexpr char search_provider_overrides[] = R"(
1223 {
1224 "search_provider_overrides" : [
1225 {
1226 "keyword" : "badkeyword",
1227 "name" : "badname",
1228 "search_url" : "http://bad_default_engine/search?q=dirty_user_query",
1229 "encoding" : "utf-8",
1230 "id" : 1
1231 }, {
1232 "keyword" : "badkeyword2",
1233 "name" : "badname2",
1234 "search_url" : "http://bad_default_engine2/search?q=dirty_user_query",
1235 "encoding" : "utf-8",
1236 "id" : 2
1237 }
1238 ]
1239 })";
a-v-y38416862016-12-08 08:40:131240
1241 // Try to override default search in all three of available preferences.
1242 auto attack1 = base::DictionaryValue::From(
Lei Zhang582ecd12019-02-13 20:28:541243 base::JSONReader::ReadDeprecated(default_search_provider_data));
a-v-y38416862016-12-08 08:40:131244 auto attack2 = base::DictionaryValue::From(
Lei Zhang582ecd12019-02-13 20:28:541245 base::JSONReader::ReadDeprecated(search_provider_overrides));
a-v-y38416862016-12-08 08:40:131246 unprotected_preferences->MergeDictionary(attack1.get());
1247 unprotected_preferences->MergeDictionary(attack2.get());
a-v-y38416862016-12-08 08:40:131248 if (protected_preferences) {
1249 // Override here, too.
1250 protected_preferences->MergeDictionary(attack1.get());
1251 protected_preferences->MergeDictionary(attack2.get());
a-v-y38416862016-12-08 08:40:131252 }
1253 }
1254
1255 void VerifyReactionToPrefAttack() override {
1256 DefaultSearchManager default_search_manager(
1257 profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
1258 DefaultSearchManager::Source dse_source =
1259 static_cast<DefaultSearchManager::Source>(-1);
1260
1261 const TemplateURLData* current_dse =
1262 default_search_manager.GetDefaultSearchEngine(&dse_source);
1263
1264 if (protection_level_ < PROTECTION_ENABLED_DSE) {
1265// This doesn't work on OS_CHROMEOS because we fail to attack Preferences.
1266#if !defined(OS_CHROMEOS)
1267 // Attack is successful.
1268 EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
1269 EXPECT_EQ(current_dse->keyword(), base::UTF8ToUTF16("badkeyword"));
1270 EXPECT_EQ(current_dse->short_name(), base::UTF8ToUTF16("badname"));
1271 EXPECT_EQ(current_dse->url(),
1272 "http://bad_default_engine/search?q=dirty_user_query");
1273#endif
1274 } else {
1275 // Attack fails.
1276 EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, dse_source);
1277 EXPECT_NE(current_dse->keyword(), base::UTF8ToUTF16("badkeyword"));
1278 EXPECT_NE(current_dse->short_name(), base::UTF8ToUTF16("badname"));
1279 EXPECT_NE(current_dse->url(),
1280 "http://bad_default_engine/search?q=dirty_user_query");
1281 }
1282 }
1283};
1284
gab36b85522017-05-24 19:30:451285PREF_HASH_BROWSER_TEST(PrefHashBrowserTestDefaultSearch, SearchProtected);