1 // Copyright (c) 2012 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
5 // Most of this code is copied from:
6 // src/chrome/browser/policy/asynchronous_policy_loader.{h,cc}
7
8 #include "remoting/host/policy_hack/policy_watcher.h"
9
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/location.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "remoting/host/dns_blackhole_checker.h"
19
20 #if !defined(NDEBUG)
21 #include "base/json/json_reader.h"
22 #endif
23
24 namespace remoting {
25 namespace policy_hack {
26
27 namespace {
28
29 // The time interval for rechecking policy. This is our fallback in case the
30 // delegate never reports a change to the ReloadObserver.
31 const int kFallbackReloadDelayMinutes = 15;
32
33 // Copies all policy values from one dictionary to another, using values from
34 // |default| if they are not set in |from|, or values from |bad_type_values| if
35 // the value in |from| has the wrong type.
CopyGoodValuesAndAddDefaults(const base::DictionaryValue * from,const base::DictionaryValue * default_values,const base::DictionaryValue * bad_type_values)36 scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults(
37 const base::DictionaryValue* from,
38 const base::DictionaryValue* default_values,
39 const base::DictionaryValue* bad_type_values) {
40 scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy());
41 for (base::DictionaryValue::Iterator i(*default_values);
42 !i.IsAtEnd(); i.Advance()) {
43
44 const base::Value* value = NULL;
45
46 // If the policy isn't in |from|, use the default.
47 if (!from->Get(i.key(), &value)) {
48 continue;
49 }
50
51 // If the policy is the wrong type, use the value from |bad_type_values|.
52 if (!value->IsType(i.value().GetType())) {
53 CHECK(bad_type_values->Get(i.key(), &value));
54 }
55
56 to->Set(i.key(), value->DeepCopy());
57 }
58
59 #if !defined(NDEBUG)
60 // Replace values with those specified in DebugOverridePolicies, if present.
61 std::string policy_overrides;
62 if (from->GetString(PolicyWatcher::kHostDebugOverridePoliciesName,
63 &policy_overrides)) {
64 scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides));
65 const base::DictionaryValue* override_values;
66 if (value && value->GetAsDictionary(&override_values)) {
67 to->MergeDictionary(override_values);
68 }
69 }
70 #endif // defined(NDEBUG)
71
72 return to.Pass();
73 }
74
75 } // namespace
76
77 const char PolicyWatcher::kNatPolicyName[] =
78 "RemoteAccessHostFirewallTraversal";
79
80 const char PolicyWatcher::kHostRequireTwoFactorPolicyName[] =
81 "RemoteAccessHostRequireTwoFactor";
82
83 const char PolicyWatcher::kHostDomainPolicyName[] =
84 "RemoteAccessHostDomain";
85
86 const char PolicyWatcher::kHostMatchUsernamePolicyName[] =
87 "RemoteAccessHostMatchUsername";
88
89 const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] =
90 "RemoteAccessHostTalkGadgetPrefix";
91
92 const char PolicyWatcher::kHostRequireCurtainPolicyName[] =
93 "RemoteAccessHostRequireCurtain";
94
95 const char PolicyWatcher::kHostTokenUrlPolicyName[] =
96 "RemoteAccessHostTokenUrl";
97
98 const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] =
99 "RemoteAccessHostTokenValidationUrl";
100
101 const char PolicyWatcher::kHostAllowClientPairing[] =
102 "RemoteAccessHostAllowClientPairing";
103
104 const char PolicyWatcher::kHostDebugOverridePoliciesName[] =
105 "RemoteAccessHostDebugOverridePolicies";
106
PolicyWatcher(scoped_refptr<base::SingleThreadTaskRunner> task_runner)107 PolicyWatcher::PolicyWatcher(
108 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
109 : task_runner_(task_runner),
110 old_policies_(new base::DictionaryValue()),
111 default_values_(new base::DictionaryValue()),
112 weak_factory_(this) {
113 // Initialize the default values for each policy.
114 default_values_->SetBoolean(kNatPolicyName, true);
115 default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false);
116 default_values_->SetBoolean(kHostRequireCurtainPolicyName, false);
117 default_values_->SetBoolean(kHostMatchUsernamePolicyName, false);
118 default_values_->SetString(kHostDomainPolicyName, std::string());
119 default_values_->SetString(kHostTalkGadgetPrefixPolicyName,
120 kDefaultHostTalkGadgetPrefix);
121 default_values_->SetString(kHostTokenUrlPolicyName, std::string());
122 default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string());
123 default_values_->SetBoolean(kHostAllowClientPairing, true);
124 #if !defined(NDEBUG)
125 default_values_->SetString(kHostDebugOverridePoliciesName, std::string());
126 #endif
127
128 // Initialize the fall-back values to use for unreadable policies.
129 // For most policies these match the defaults.
130 bad_type_values_.reset(default_values_->DeepCopy());
131 bad_type_values_->SetBoolean(kNatPolicyName, false);
132 }
133
~PolicyWatcher()134 PolicyWatcher::~PolicyWatcher() {
135 }
136
StartWatching(const PolicyCallback & policy_callback)137 void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) {
138 if (!OnPolicyWatcherThread()) {
139 task_runner_->PostTask(FROM_HERE,
140 base::Bind(&PolicyWatcher::StartWatching,
141 base::Unretained(this),
142 policy_callback));
143 return;
144 }
145
146 policy_callback_ = policy_callback;
147 StartWatchingInternal();
148 }
149
StopWatching(base::WaitableEvent * done)150 void PolicyWatcher::StopWatching(base::WaitableEvent* done) {
151 if (!OnPolicyWatcherThread()) {
152 task_runner_->PostTask(FROM_HERE,
153 base::Bind(&PolicyWatcher::StopWatching,
154 base::Unretained(this), done));
155 return;
156 }
157
158 StopWatchingInternal();
159 weak_factory_.InvalidateWeakPtrs();
160 policy_callback_.Reset();
161
162 done->Signal();
163 }
164
ScheduleFallbackReloadTask()165 void PolicyWatcher::ScheduleFallbackReloadTask() {
166 DCHECK(OnPolicyWatcherThread());
167 ScheduleReloadTask(
168 base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes));
169 }
170
ScheduleReloadTask(const base::TimeDelta & delay)171 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) {
172 DCHECK(OnPolicyWatcherThread());
173 task_runner_->PostDelayedTask(
174 FROM_HERE,
175 base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()),
176 delay);
177 }
178
Defaults() const179 const base::DictionaryValue& PolicyWatcher::Defaults() const {
180 return *default_values_;
181 }
182
OnPolicyWatcherThread() const183 bool PolicyWatcher::OnPolicyWatcherThread() const {
184 return task_runner_->BelongsToCurrentThread();
185 }
186
UpdatePolicies(const base::DictionaryValue * new_policies_raw)187 void PolicyWatcher::UpdatePolicies(
188 const base::DictionaryValue* new_policies_raw) {
189 DCHECK(OnPolicyWatcherThread());
190
191 // Use default values for any missing policies.
192 scoped_ptr<base::DictionaryValue> new_policies =
193 CopyGoodValuesAndAddDefaults(
194 new_policies_raw, default_values_.get(), bad_type_values_.get());
195
196 // Find the changed policies.
197 scoped_ptr<base::DictionaryValue> changed_policies(
198 new base::DictionaryValue());
199 base::DictionaryValue::Iterator iter(*new_policies);
200 while (!iter.IsAtEnd()) {
201 base::Value* old_policy;
202 if (!(old_policies_->Get(iter.key(), &old_policy) &&
203 old_policy->Equals(&iter.value()))) {
204 changed_policies->Set(iter.key(), iter.value().DeepCopy());
205 }
206 iter.Advance();
207 }
208
209 // Save the new policies.
210 old_policies_.swap(new_policies);
211
212 // Notify our client of the changed policies.
213 if (!changed_policies->empty()) {
214 policy_callback_.Run(changed_policies.Pass());
215 }
216 }
217
218 } // namespace policy_hack
219 } // namespace remoting
220