blob: 380b7d2bbb88917a26ae7ea7ffa39153bb0b041c [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/net/secure_dns_policy_handler.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/common/pref_names.h"
#include "components/policy/core/browser/configuration_policy_handler.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
namespace policy {
class SecureDnsPolicyHandlerTest : public testing::Test {
protected:
void SetPolicyValue(const std::string& policy, base::Value value) {
policies_.Set(policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
POLICY_SOURCE_PLATFORM, std::move(value), nullptr);
}
bool CheckPolicySettings() {
return handler_.CheckPolicySettings(policies_, &errors_);
}
void ApplyPolicySettings() {
handler_.ApplyPolicySettings(policies_, &prefs_);
}
void CheckAndApplyPolicySettings() {
if (CheckPolicySettings())
ApplyPolicySettings();
}
PolicyErrorMap& errors() { return errors_; }
PrefValueMap& prefs() { return prefs_; }
private:
PolicyMap policies_;
PolicyErrorMap errors_;
PrefValueMap prefs_;
SecureDnsPolicyHandler handler_;
};
TEST_F(SecureDnsPolicyHandlerTest, PoliciesNotSet) {
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
// Prefs should not be set.
const base::Value* pref_value;
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsMode, &pref_value));
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsTemplates, &pref_value));
}
// Sanity check tests to ensure the policy errors have the correct name.
TEST_F(SecureDnsPolicyHandlerTest, ModePolicyErrorName) {
// Do anything that causes a policy error.
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(1));
CheckAndApplyPolicySettings();
// Should have an error
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->first, key::kDnsOverHttpsMode);
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyErrorName) {
// Do anything that causes a policy error.
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(1));
CheckAndApplyPolicySettings();
// Should have an error
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->first, key::kDnsOverHttpsTemplates);
}
TEST_F(SecureDnsPolicyHandlerTest, EmptyModePolicyValue) {
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(""));
CheckAndApplyPolicySettings();
// Should have an error
auto expected_error =
l10n_util::GetStringUTF16(IDS_POLICY_NOT_SPECIFIED_ERROR);
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should not be set.
const base::Value* pref_value;
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsMode, &pref_value));
}
TEST_F(SecureDnsPolicyHandlerTest, InvalidModePolicyValue) {
SetPolicyValue(key::kDnsOverHttpsMode, base::Value("invalid"));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error =
l10n_util::GetStringUTF16(IDS_POLICY_INVALID_SECURE_DNS_MODE_ERROR);
EXPECT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should not be set.
const base::Value* pref_value;
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsMode, &pref_value));
}
TEST_F(SecureDnsPolicyHandlerTest, InvalidModePolicyType) {
// Give an int to a string-enum policy.
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(1));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringFUTF16(
IDS_POLICY_TYPE_ERROR,
base::ASCIIToUTF16(base::Value::GetTypeName(base::Value::Type::STRING)));
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should not be set.
const base::Value* pref_value;
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsMode, &pref_value));
}
TEST_F(SecureDnsPolicyHandlerTest, ValidModePolicyValueOff) {
const std::string test_policy_value = SecureDnsConfig::kModeOff;
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
std::string mode;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsMode, &mode));
// Pref should now be the test value.
EXPECT_EQ(mode, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, ValidModePolicyValueAutomatic) {
const std::string test_policy_value = SecureDnsConfig::kModeAutomatic;
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
std::string mode;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsMode, &mode));
// Pref should now be the test value.
EXPECT_EQ(mode, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, ValidModePolicySecure) {
const std::string test_policy_value = SecureDnsConfig::kModeSecure;
SetPolicyValue(key::kDnsOverHttpsMode, base::Value(test_policy_value));
// The template policy requires a value if the mode is set to secure, so set
// it to anything.
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value("https://foo.test/"));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
std::string mode;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsMode, &mode));
// Pref should now be the test value.
EXPECT_EQ(mode, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, InvalidTemplatesPolicyValue) {
// The templates policy requires a valid Mode policy or it will give an error
// we're not testing for.
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeAutomatic));
const std::string test_policy_value = "invalid";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Should have an error
auto expected_error =
l10n_util::GetStringUTF16(IDS_POLICY_SECURE_DNS_TEMPLATES_INVALID_ERROR);
EXPECT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, InvalidTemplatesPolicyType) {
// The templates policy requires a valid Mode policy or it will give an error
// we're not testing for.
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeAutomatic));
// Give an int to a string policy.
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(1));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringFUTF16(
IDS_POLICY_TYPE_ERROR,
base::ASCIIToUTF16(base::Value::GetTypeName(base::Value::Type::STRING)));
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should not be set.
const base::Value* pref_value;
EXPECT_FALSE(prefs().GetValue(prefs::kDnsOverHttpsTemplates, &pref_value));
}
// Templates policy should error when the Mode makes its value irrelevant.
TEST_F(SecureDnsPolicyHandlerTest, IrrelevantTemplatesPolicyWithModeOff) {
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeOff));
// Set templates to anything.
const std::string test_policy_value = "https://foo.test/";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_IRRELEVANT_MODE_ERROR);
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesWithModeNotSet) {
// Don't set mode.
// Set templates to anything.
const std::string test_policy_value = "https://foo.test/";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_UNSET_MODE_ERROR);
ASSERT_EQ(errors().size(), 1U);
EXPECT_EQ(errors().begin()->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesWithModeInvalid) {
// Set mode so that it's invalid.
SetPolicyValue(key::kDnsOverHttpsMode, base::Value("foo"));
// Set templates to anything.
const std::string test_policy_value = "https://foo.test/";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Should have errors.
auto expected_error1 =
l10n_util::GetStringUTF16(IDS_POLICY_INVALID_SECURE_DNS_MODE_ERROR);
auto expected_error2 = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_INVALID_MODE_ERROR);
ASSERT_EQ(errors().size(), 2U);
auto it = errors().begin();
EXPECT_EQ(it++->second, expected_error1);
EXPECT_EQ(it->second, expected_error2);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesNotSetWithModeSecure) {
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeSecure));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
EXPECT_EQ(it->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Templates pref should be an empty string.
EXPECT_EQ(templates, "");
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesNotStringWithModeSecure) {
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeSecure));
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(1));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
EXPECT_EQ(it->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Templates pref should be an empty string.
EXPECT_EQ(templates, "");
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesEmptyWithModeSecure) {
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeSecure));
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(""));
CheckAndApplyPolicySettings();
// Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
EXPECT_EQ(it->second, expected_error);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Templates pref should be an empty string.
EXPECT_EQ(templates, "");
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesEmptyWithModeAutomatic) {
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeAutomatic));
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(""));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
// Pref should be set.
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, "");
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyWithModeAutomatic) {
// The templates policy requires a valid Mode policy or it will give an error
// we're not testing for.
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeAutomatic));
const std::string test_policy_value =
"https://foo.test/ https://bar.test/dns-query{?dns}";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyWithModeSecure) {
// The templates policy requires a valid Mode policy or it will give an error
// we're not testing for.
SetPolicyValue(key::kDnsOverHttpsMode,
base::Value(SecureDnsConfig::kModeSecure));
const std::string test_policy_value =
"https://foo.test/ https://bar.test/dns-query{?dns}";
SetPolicyValue(key::kDnsOverHttpsTemplates, base::Value(test_policy_value));
CheckAndApplyPolicySettings();
// Shouldn't error.
EXPECT_EQ(errors().size(), 0U);
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
// Pref should now be the test value.
EXPECT_EQ(templates, test_policy_value);
}
} // namespace policy