Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Unified Diff: remoting/host/policy_watcher.cc

Issue 966433002: Malformed PortRange or ThirdPartyAuthConfig trigger OnPolicyError. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing a Windows-specific, pre-processor-related build break. Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/policy_watcher.h ('k') | remoting/host/policy_watcher_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/policy_watcher.cc
diff --git a/remoting/host/policy_watcher.cc b/remoting/host/policy_watcher.cc
index 2cf7be8889425262c78ef45fb113b347959b9b5b..60f14c9ceb5becd41b0456177c3139fc9d82d670 100644
--- a/remoting/host/policy_watcher.cc
+++ b/remoting/host/policy_watcher.cc
@@ -21,6 +21,8 @@
#include "components/policy/core/common/schema_registry.h"
#include "policy/policy_constants.h"
#include "remoting/host/dns_blackhole_checker.h"
+#include "remoting/host/third_party_auth_config.h"
+#include "remoting/protocol/port_range.h"
#if !defined(NDEBUG)
#include "base/json/json_reader.h"
@@ -44,15 +46,15 @@ namespace {
// Copies all policy values from one dictionary to another, using values from
// |default_values| if they are not set in |from|.
scoped_ptr<base::DictionaryValue> CopyValuesAndAddDefaults(
- const base::DictionaryValue* from,
- const base::DictionaryValue* default_values) {
- scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy());
- for (base::DictionaryValue::Iterator i(*default_values); !i.IsAtEnd();
+ const base::DictionaryValue& from,
+ const base::DictionaryValue& default_values) {
+ scoped_ptr<base::DictionaryValue> to(default_values.DeepCopy());
+ for (base::DictionaryValue::Iterator i(default_values); !i.IsAtEnd();
i.Advance()) {
const base::Value* value = nullptr;
// If the policy isn't in |from|, use the default.
- if (!from->Get(i.key(), &value)) {
+ if (!from.Get(i.key(), &value)) {
continue;
}
@@ -63,8 +65,8 @@ scoped_ptr<base::DictionaryValue> CopyValuesAndAddDefaults(
#if !defined(NDEBUG)
// Replace values with those specified in DebugOverridePolicies, if present.
std::string policy_overrides;
- if (from->GetString(key::kRemoteAccessHostDebugOverridePolicies,
- &policy_overrides)) {
+ if (from.GetString(key::kRemoteAccessHostDebugOverridePolicies,
+ &policy_overrides)) {
scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides));
const base::DictionaryValue* override_values;
if (value && value->GetAsDictionary(&override_values)) {
@@ -92,6 +94,56 @@ scoped_ptr<policy::SchemaRegistry> CreateSchemaRegistry() {
return schema_registry.Pass();
}
+scoped_ptr<base::DictionaryValue> CopyChromotingPoliciesIntoDictionary(
+ const policy::PolicyMap& current) {
+ const char kPolicyNameSubstring[] = "RemoteAccessHost";
+ scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue());
+ for (auto it = current.begin(); it != current.end(); ++it) {
+ const std::string& key = it->first;
+ const base::Value* value = it->second.value;
+
+ // Copying only Chromoting-specific policies helps avoid false alarms
+ // raised by NormalizePolicies below (such alarms shutdown the host).
+ // TODO(lukasza): Removing this somewhat brittle filtering will be possible
+ // after having separate, Chromoting-specific schema.
+ if (key.find(kPolicyNameSubstring) != std::string::npos) {
+ policy_dict->Set(key, value->DeepCopy());
+ }
+ }
+
+ return policy_dict.Pass();
+}
+
+// Takes a dictionary containing only 1) recognized policy names and 2)
+// well-typed policy values and further verifies policy contents.
+bool VerifyWellformedness(const base::DictionaryValue& changed_policies) {
+ // Verify ThirdPartyAuthConfig policy.
+ ThirdPartyAuthConfig not_used;
+ switch (ThirdPartyAuthConfig::Parse(changed_policies, &not_used)) {
+ case ThirdPartyAuthConfig::NoPolicy:
+ case ThirdPartyAuthConfig::ParsingSuccess:
+ break; // Well-formed.
+ case ThirdPartyAuthConfig::InvalidPolicy:
+ return false; // Malformed.
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ // Verify UdpPortRange policy.
+ std::string udp_port_range_string;
+ PortRange udp_port_range;
+ if (changed_policies.GetString(policy::key::kRemoteAccessHostUdpPortRange,
+ &udp_port_range_string)) {
+ if (!PortRange::Parse(udp_port_range_string, &udp_port_range)) {
+ return false;
+ }
+ }
+
+ // Report that all the policies were well-formed.
+ return true;
+}
+
} // namespace
void PolicyWatcher::StartWatching(
@@ -114,36 +166,6 @@ void PolicyWatcher::StartWatching(
}
}
-void PolicyWatcher::UpdatePolicies(
- const base::DictionaryValue* new_policies_raw) {
- DCHECK(CalledOnValidThread());
-
- // Use default values for any missing policies.
- scoped_ptr<base::DictionaryValue> new_policies =
- CopyValuesAndAddDefaults(new_policies_raw, default_values_.get());
-
- // Find the changed policies.
- scoped_ptr<base::DictionaryValue> changed_policies(
- new base::DictionaryValue());
- base::DictionaryValue::Iterator iter(*new_policies);
- while (!iter.IsAtEnd()) {
- base::Value* old_policy;
- if (!(old_policies_->Get(iter.key(), &old_policy) &&
- old_policy->Equals(&iter.value()))) {
- changed_policies->Set(iter.key(), iter.value().DeepCopy());
- }
- iter.Advance();
- }
-
- // Save the new policies.
- old_policies_.swap(new_policies);
-
- // Notify our client of the changed policies.
- if (!changed_policies->empty()) {
- policy_updated_callback_.Run(changed_policies.Pass());
- }
-}
-
void PolicyWatcher::SignalPolicyError() {
old_policies_->Clear();
policy_error_callback_.Run();
@@ -201,24 +223,7 @@ const policy::Schema* PolicyWatcher::GetPolicySchema() const {
return owned_schema_registry_->schema_map()->GetSchema(GetPolicyNamespace());
}
-void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns,
- const policy::PolicyMap& previous,
- const policy::PolicyMap& current) {
- const char kPolicyNamePrefix[] = "RemoteAccessHost";
- scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue());
- for (auto it = current.begin(); it != current.end(); ++it) {
- const std::string& key = it->first;
- const base::Value* value = it->second.value;
-
- // Copying only Chromoting-specific policies helps avoid false alarms
- // raised by Schema::Normalize below (such alarms shutdown the host).
- // TODO(lukasza): Removing this somewhat brittle filtering will be possible
- // after having separate, Chromoting-specific schema.
- if (key.find(kPolicyNamePrefix) != std::string::npos) {
- policy_dict->Set(key, value->DeepCopy());
- }
- }
-
+bool PolicyWatcher::NormalizePolicies(base::DictionaryValue* policy_dict) {
// Allowing unrecognized policy names allows presence of
// 1) comments (i.e. JSON of the form: { "_comment": "blah", ... }),
// 2) policies intended for future/newer versions of the host,
@@ -231,16 +236,95 @@ void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns,
std::string error;
bool changed = false;
const policy::Schema* schema = GetPolicySchema();
- if (schema->Normalize(policy_dict.get(), strategy, &path, &error, &changed)) {
+ if (schema->Normalize(policy_dict, strategy, &path, &error, &changed)) {
if (changed) {
LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path
<< ": " << error;
}
- UpdatePolicies(policy_dict.get());
+ return true;
} else {
LOG(ERROR) << "Invalid policy contents: " << path << ": " << error;
+ return false;
+ }
+}
+
+namespace {
+void CopyDictionaryValue(const base::DictionaryValue& from,
+ base::DictionaryValue& to,
+ std::string key) {
+ const base::Value* value;
+ if (from.Get(key, &value)) {
+ to.Set(key, value->DeepCopy());
+ }
+}
+} // namespace
+
+scoped_ptr<base::DictionaryValue>
+PolicyWatcher::StoreNewAndReturnChangedPolicies(
+ scoped_ptr<base::DictionaryValue> new_policies) {
+ // Find the changed policies.
+ scoped_ptr<base::DictionaryValue> changed_policies(
+ new base::DictionaryValue());
+ base::DictionaryValue::Iterator iter(*new_policies);
+ while (!iter.IsAtEnd()) {
+ base::Value* old_policy;
+ if (!(old_policies_->Get(iter.key(), &old_policy) &&
+ old_policy->Equals(&iter.value()))) {
+ changed_policies->Set(iter.key(), iter.value().DeepCopy());
+ }
+ iter.Advance();
+ }
+
+ // If one of ThirdPartyAuthConfig policies changed, we need to include all.
+ if (changed_policies->HasKey(key::kRemoteAccessHostTokenUrl) ||
+ changed_policies->HasKey(key::kRemoteAccessHostTokenValidationUrl) ||
+ changed_policies->HasKey(
+ key::kRemoteAccessHostTokenValidationCertificateIssuer)) {
+ CopyDictionaryValue(*new_policies, *changed_policies,
+ key::kRemoteAccessHostTokenUrl);
+ CopyDictionaryValue(*new_policies, *changed_policies,
+ key::kRemoteAccessHostTokenValidationUrl);
+ CopyDictionaryValue(*new_policies, *changed_policies,
+ key::kRemoteAccessHostTokenValidationCertificateIssuer);
+ }
+
+ // Save the new policies.
+ old_policies_.swap(new_policies);
+
+ return changed_policies.Pass();
+}
+
+void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns,
+ const policy::PolicyMap& previous,
+ const policy::PolicyMap& current) {
+ scoped_ptr<base::DictionaryValue> new_policies =
+ CopyChromotingPoliciesIntoDictionary(current);
+
+ // Check for mistyped values and get rid of unknown policies.
+ if (!NormalizePolicies(new_policies.get())) {
+ SignalPolicyError();
+ return;
+ }
+
+ // Use default values for any missing policies.
+ scoped_ptr<base::DictionaryValue> filled_policies =
+ CopyValuesAndAddDefaults(*new_policies, *default_values_);
+
+ // Limit reporting to only the policies that were changed.
+ scoped_ptr<base::DictionaryValue> changed_policies =
+ StoreNewAndReturnChangedPolicies(filled_policies.Pass());
+ if (changed_policies->empty()) {
+ return;
+ }
+
+ // Verify that we are calling the callback with valid policies.
+ if (!VerifyWellformedness(*changed_policies)) {
SignalPolicyError();
+ return;
}
+
+ // Notify our client of the changed policies.
+ policy_updated_callback_.Run(changed_policies.Pass());
}
void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) {
« no previous file with comments | « remoting/host/policy_watcher.h ('k') | remoting/host/policy_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698