Chromium Code Reviews| Index: chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| diff --git a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| index 7703e89b68c07dd46165d956894f66885c52b3b6..05af222cdde0fb48f3e3e990ef59b495d83b6c13 100644 |
| --- a/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| +++ b/chrome/browser/prefs/tracked/pref_hash_browsertest.cc |
| @@ -38,6 +38,10 @@ |
| #include "chromeos/chromeos_switches.h" |
| #endif |
| +#if defined(OS_WIN) |
| +#include "base/test/test_reg_util_win.h" |
| +#endif |
| + |
| namespace { |
| // Extension ID of chrome/test/data/extensions/good.crx |
| @@ -56,14 +60,30 @@ enum AllowedBuckets { |
| ALLOW_ANY |
| }; |
| +#if defined(OS_WIN) |
| +// Prefix for the registry path. |
| +constexpr base::char16 kRegistryTestPathPrefix[] = |
| + L"SOFTWARE\\Chromium\\PrefHashBrowserTest\\"; |
|
gab
2016/09/30 19:25:27
Move as local variable in GetRegistryPathForTestPr
proberge
2016/09/30 21:32:17
Done.
|
| + |
| +base::string16 GetRegistryPathForTestProfile() { |
| + base::FilePath profile_dir; |
| + EXPECT_TRUE(PathService::Get(chrome::DIR_USER_DATA, &profile_dir)); |
| + return kRegistryTestPathPrefix + profile_dir.BaseName().value(); |
| +} |
| +#endif |
| + |
| // Returns the number of times |histogram_name| was reported so far; adding the |
| // results of the first 100 buckets (there are only ~19 reporting IDs as of this |
| // writing; varies depending on the platform). |allowed_buckets| hints at extra |
| // requirements verified in this method (see AllowedBuckets for details). |
| int GetTrackedPrefHistogramCount(const char* histogram_name, |
| + const char* histogram_suffix, |
| int allowed_buckets) { |
| + std::string full_histogram_name(histogram_name); |
| + if (*histogram_suffix) |
| + full_histogram_name.append(".").append(histogram_suffix); |
| const base::HistogramBase* histogram = |
| - base::StatisticsRecorder::FindHistogram(histogram_name); |
| + base::StatisticsRecorder::FindHistogram(full_histogram_name); |
| if (!histogram) |
| return 0; |
| @@ -82,6 +102,13 @@ int GetTrackedPrefHistogramCount(const char* histogram_name, |
| return sum; |
| } |
| +// Helper function to call GetTrackedPrefHistogramCount with no external |
| +// validation suffix. |
| +int GetTrackedPrefHistogramCount(const char* histogram_name, |
| + int allowed_buckets) { |
| + return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets); |
| +} |
| + |
| std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary( |
| const base::FilePath& pref_file) { |
| JSONFileValueDeserializer deserializer(pref_file); |
| @@ -101,6 +128,16 @@ std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary( |
| static_cast<base::DictionaryValue*>(prefs.release())); |
| } |
| +// Returns whether external validation is supported on the platform through |
| +// storing MACs in the registry. |
| +bool SupportsRegistryValidation() { |
| +#if defined(OS_WIN) |
| + return true; |
| +#else |
| + return false; |
| +#endif |
| +} |
| + |
| #define PREF_HASH_BROWSER_TEST(fixture, test_name) \ |
| IN_PROC_BROWSER_TEST_P(fixture, PRE_##test_name) { \ |
| SetupPreferences(); \ |
| @@ -233,6 +270,44 @@ class PrefHashBrowserTestBase |
| // Bots are on a domain, turn off the domain check for settings hardening in |
| // order to be able to test all SettingsEnforcement groups. |
| chrome_prefs::DisableDomainCheckForTesting(); |
| + |
| +#if defined(OS_WIN) |
| + // Avoid polluting prefs for the user and the bots by writing to a specific |
| + // testing registry path. |
| + registry_key_for_external_validation_ = GetRegistryPathForTestProfile(); |
| + ProfilePrefStoreManager::SetPreferenceValidationRegistryPathForTesting( |
| + ®istry_key_for_external_validation_); |
| + |
| + // Keys should be unique, but to avoid flakes in the long run make sure an |
| + // identical test key wasn't left behind by a previous test. |
| + if (IsPRETest()) { |
| + base::win::RegKey key; |
| + if (key.Open(HKEY_CURRENT_USER, |
| + registry_key_for_external_validation_.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { |
| + LONG result = key.DeleteKey(L""); |
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); |
| + } |
| + } |
| +#endif |
| + } |
| + |
| + void TearDown() override { |
| +#if defined(OS_WIN) |
| + // When done, delete the Registry key to avoid polluting the registry. |
| + // TODO(proberge): it would be nice to delete keys from interrupted tests |
| + // as well. |
| + if (!IsPRETest()) { |
| + base::string16 registry_key = GetRegistryPathForTestProfile(); |
| + base::win::RegKey key; |
| + if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) { |
| + LONG result = key.DeleteKey(L""); |
| + ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND); |
| + } |
| + } |
| +#endif |
| + ExtensionBrowserTest::TearDown(); |
| } |
| // In the PRE_ test, find the number of tracked preferences that were |
| @@ -266,6 +341,23 @@ class PrefHashBrowserTestBase |
| EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| num_split_tracked_prefs); |
| + if (SupportsRegistryValidation()) { |
| + // Same checks as above, but for the registry. |
| + num_tracked_prefs_ = GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramNullInitialized, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY); |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM, |
| + num_tracked_prefs_ > 0); |
| + |
| + int num_split_tracked_prefs = GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 5); |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + num_split_tracked_prefs); |
| + } |
| + |
| num_tracked_prefs_ += num_split_tracked_prefs; |
| std::string num_tracked_prefs_str = base::IntToString(num_tracked_prefs_); |
| @@ -353,6 +445,10 @@ class PrefHashBrowserTestBase |
| } |
| int num_tracked_prefs_; |
| + |
| +#if defined(OS_WIN) |
| + base::string16 registry_key_for_external_validation_; |
| +#endif |
| }; |
| } // namespace |
| @@ -407,6 +503,17 @@ class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect all prefs to be reported as Unchanged. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY)); |
| + } |
| } |
| }; |
| @@ -497,6 +604,15 @@ class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect homepage clearance to have been noticed by registry validation. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramCleared, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| } |
| }; |
| @@ -619,6 +735,18 @@ class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // The MACs have been cleared but the preferences have not been tampered. |
| + // The registry should report all prefs as unchanged. |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + ALLOW_ANY)); |
| + } |
| } |
| }; |
| @@ -709,6 +837,15 @@ class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect a single Changed event for tracked pref #4 (startup URLs). |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 4)); |
| + } |
| } |
| }; |
| @@ -806,6 +943,16 @@ class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase { |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect that the registry validation caught the invalid MAC in split |
| + // pref #5 (extensions). |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 5)); |
| + } |
| } |
| }; |
| @@ -879,6 +1026,17 @@ class PrefHashBrowserTestUntrustedAdditionToPrefs |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM && |
| + protection_level_ < PROTECTION_ENABLED_BASIC) |
| + ? changed_expected |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 3)); |
| + } |
| } |
| }; |
| @@ -953,8 +1111,66 @@ class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe |
| 0, GetTrackedPrefHistogramCount( |
| user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId, |
| ALLOW_NONE)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + EXPECT_EQ(changed_expected, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + EXPECT_EQ(cleared_expected, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramCleared, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| } |
| }; |
| PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe, |
| UntrustedAdditionToPrefsAfterWipe); |
| + |
| +#if defined(OS_WIN) |
| +class PrefHashBrowserTestRegistryValidationFailure |
| + : public PrefHashBrowserTestBase { |
| + public: |
| + void SetupPreferences() override { |
| + profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com"); |
| + } |
| + |
| + void AttackPreferencesOnDisk( |
| + base::DictionaryValue* unprotected_preferences, |
| + base::DictionaryValue* protected_preferences) override { |
| + base::string16 registry_key = |
| + GetRegistryPathForTestProfile() + L"\\PreferenceMACs\\Default"; |
| + base::win::RegKey key; |
| + ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, registry_key.c_str(), |
| + KEY_SET_VALUE | KEY_WOW64_32KEY)); |
| + // An incorrect hash should still have the correct size. |
| + ASSERT_EQ(ERROR_SUCCESS, |
| + key.WriteValue(L"homepage", base::string16(64, 'A').c_str())); |
| + } |
| + |
| + void VerifyReactionToPrefAttack() override { |
| + EXPECT_EQ( |
| + protection_level_ > PROTECTION_DISABLED_ON_PLATFORM |
| + ? num_tracked_prefs() |
| + : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY)); |
| + |
| + if (SupportsRegistryValidation()) { |
| + // Expect that the registry validation caught the invalid MAC for pref #2 |
| + // (homepage). |
| + EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0, |
| + GetTrackedPrefHistogramCount( |
| + user_prefs::tracked::kTrackedPrefHistogramChanged, |
| + user_prefs::tracked::kTrackedPrefRegistryValidationSuffix, |
| + BEGIN_ALLOW_SINGLE_BUCKET + 2)); |
| + } |
| + } |
| +}; |
| + |
| +PREF_HASH_BROWSER_TEST(PrefHashBrowserTestRegistryValidationFailure, |
| + RegistryValidationFailure); |
| +#endif |