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 #include "components/policy/core/browser/configuration_policy_handler.h"
6
7 #include <algorithm>
8
9 #include "base/callback.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/prefs/pref_value_map.h"
13 #include "base/strings/string16.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_util.h"
16 #include "components/policy/core/browser/policy_error_map.h"
17 #include "components/policy/core/common/policy_map.h"
18 #include "grit/components_strings.h"
19 #include "url/gurl.h"
20
21 namespace policy {
22
23 // ConfigurationPolicyHandler implementation -----------------------------------
24
25 // static
ValueTypeToString(base::Value::Type type)26 std::string ConfigurationPolicyHandler::ValueTypeToString(
27 base::Value::Type type) {
28 static const char* strings[] = {
29 "null",
30 "boolean",
31 "integer",
32 "double",
33 "string",
34 "binary",
35 "dictionary",
36 "list"
37 };
38 CHECK(static_cast<size_t>(type) < arraysize(strings));
39 return std::string(strings[type]);
40 }
41
ConfigurationPolicyHandler()42 ConfigurationPolicyHandler::ConfigurationPolicyHandler() {
43 }
44
~ConfigurationPolicyHandler()45 ConfigurationPolicyHandler::~ConfigurationPolicyHandler() {
46 }
47
PrepareForDisplaying(PolicyMap * policies) const48 void ConfigurationPolicyHandler::PrepareForDisplaying(
49 PolicyMap* policies) const {}
50
ApplyPolicySettings(const policy::PolicyMap & policies,PrefValueMap * prefs)51 void ConfigurationPolicyHandler::ApplyPolicySettings(
52 const policy::PolicyMap& policies,
53 PrefValueMap* prefs) {
54 NOTREACHED();
55 }
56
ApplyPolicySettingsWithParameters(const PolicyMap & policies,const PolicyHandlerParameters & parameters,PrefValueMap * prefs)57 void ConfigurationPolicyHandler::ApplyPolicySettingsWithParameters(
58 const PolicyMap& policies,
59 const PolicyHandlerParameters& parameters,
60 PrefValueMap* prefs) {
61 ApplyPolicySettings(policies, prefs);
62 }
63
64 // TypeCheckingPolicyHandler implementation ------------------------------------
65
TypeCheckingPolicyHandler(const char * policy_name,base::Value::Type value_type)66 TypeCheckingPolicyHandler::TypeCheckingPolicyHandler(
67 const char* policy_name,
68 base::Value::Type value_type)
69 : policy_name_(policy_name),
70 value_type_(value_type) {
71 }
72
~TypeCheckingPolicyHandler()73 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() {
74 }
75
policy_name() const76 const char* TypeCheckingPolicyHandler::policy_name() const {
77 return policy_name_;
78 }
79
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)80 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
81 PolicyErrorMap* errors) {
82 const base::Value* value = NULL;
83 return CheckAndGetValue(policies, errors, &value);
84 }
85
CheckAndGetValue(const PolicyMap & policies,PolicyErrorMap * errors,const base::Value ** value)86 bool TypeCheckingPolicyHandler::CheckAndGetValue(const PolicyMap& policies,
87 PolicyErrorMap* errors,
88 const base::Value** value) {
89 *value = policies.GetValue(policy_name_);
90 if (*value && !(*value)->IsType(value_type_)) {
91 errors->AddError(policy_name_,
92 IDS_POLICY_TYPE_ERROR,
93 ValueTypeToString(value_type_));
94 return false;
95 }
96 return true;
97 }
98
99
100 // IntRangePolicyHandlerBase implementation ------------------------------------
101
IntRangePolicyHandlerBase(const char * policy_name,int min,int max,bool clamp)102 IntRangePolicyHandlerBase::IntRangePolicyHandlerBase(
103 const char* policy_name,
104 int min,
105 int max,
106 bool clamp)
107 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_INTEGER),
108 min_(min),
109 max_(max),
110 clamp_(clamp) {
111 }
112
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)113 bool IntRangePolicyHandlerBase::CheckPolicySettings(const PolicyMap& policies,
114 PolicyErrorMap* errors) {
115 const base::Value* value;
116 return CheckAndGetValue(policies, errors, &value) &&
117 EnsureInRange(value, NULL, errors);
118 }
119
~IntRangePolicyHandlerBase()120 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() {
121 }
122
EnsureInRange(const base::Value * input,int * output,PolicyErrorMap * errors)123 bool IntRangePolicyHandlerBase::EnsureInRange(const base::Value* input,
124 int* output,
125 PolicyErrorMap* errors) {
126 if (!input)
127 return true;
128
129 int value;
130 if (!input->GetAsInteger(&value)) {
131 NOTREACHED();
132 return false;
133 }
134
135 if (value < min_ || value > max_) {
136 if (errors) {
137 errors->AddError(policy_name(),
138 IDS_POLICY_OUT_OF_RANGE_ERROR,
139 base::IntToString(value));
140 }
141
142 if (!clamp_)
143 return false;
144
145 value = std::min(std::max(value, min_), max_);
146 }
147
148 if (output)
149 *output = value;
150 return true;
151 }
152
153
154 // StringMappingListPolicyHandler implementation -----------------------------
155
MappingEntry(const char * policy_value,scoped_ptr<base::Value> map)156 StringMappingListPolicyHandler::MappingEntry::MappingEntry(
157 const char* policy_value, scoped_ptr<base::Value> map)
158 : enum_value(policy_value), mapped_value(map.Pass()) {}
159
~MappingEntry()160 StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {}
161
StringMappingListPolicyHandler(const char * policy_name,const char * pref_path,const GenerateMapCallback & callback)162 StringMappingListPolicyHandler::StringMappingListPolicyHandler(
163 const char* policy_name,
164 const char* pref_path,
165 const GenerateMapCallback& callback)
166 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST),
167 pref_path_(pref_path),
168 map_getter_(callback) {}
169
~StringMappingListPolicyHandler()170 StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {}
171
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)172 bool StringMappingListPolicyHandler::CheckPolicySettings(
173 const PolicyMap& policies,
174 PolicyErrorMap* errors) {
175 const base::Value* value;
176 return CheckAndGetValue(policies, errors, &value) &&
177 Convert(value, NULL, errors);
178 }
179
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)180 void StringMappingListPolicyHandler::ApplyPolicySettings(
181 const PolicyMap& policies,
182 PrefValueMap* prefs) {
183 if (!pref_path_)
184 return;
185 const base::Value* value = policies.GetValue(policy_name());
186 scoped_ptr<base::ListValue> list(new base::ListValue());
187 if (value && Convert(value, list.get(), NULL))
188 prefs->SetValue(pref_path_, list.release());
189 }
190
Convert(const base::Value * input,base::ListValue * output,PolicyErrorMap * errors)191 bool StringMappingListPolicyHandler::Convert(const base::Value* input,
192 base::ListValue* output,
193 PolicyErrorMap* errors) {
194 if (!input)
195 return true;
196
197 const base::ListValue* list_value = NULL;
198 if (!input->GetAsList(&list_value)) {
199 NOTREACHED();
200 return false;
201 }
202
203 for (base::ListValue::const_iterator entry(list_value->begin());
204 entry != list_value->end(); ++entry) {
205 std::string entry_value;
206 if (!(*entry)->GetAsString(&entry_value)) {
207 if (errors) {
208 errors->AddError(policy_name(),
209 entry - list_value->begin(),
210 IDS_POLICY_TYPE_ERROR,
211 ValueTypeToString(base::Value::TYPE_STRING));
212 }
213 continue;
214 }
215
216 scoped_ptr<base::Value> mapped_value = Map(entry_value);
217 if (mapped_value) {
218 if (output)
219 output->Append(mapped_value.release());
220 } else {
221 if (errors) {
222 errors->AddError(policy_name(),
223 entry - list_value->begin(),
224 IDS_POLICY_OUT_OF_RANGE_ERROR);
225 }
226 }
227 }
228
229 return true;
230 }
231
Map(const std::string & entry_value)232 scoped_ptr<base::Value> StringMappingListPolicyHandler::Map(
233 const std::string& entry_value) {
234 // Lazily generate the map of policy strings to mapped values.
235 if (map_.empty())
236 map_getter_.Run(&map_);
237
238 scoped_ptr<base::Value> return_value;
239 for (ScopedVector<MappingEntry>::const_iterator it = map_.begin();
240 it != map_.end(); ++it) {
241 const MappingEntry* mapping_entry = *it;
242 if (mapping_entry->enum_value == entry_value) {
243 return_value = make_scoped_ptr(mapping_entry->mapped_value->DeepCopy());
244 break;
245 }
246 }
247 return return_value.Pass();
248 }
249
250 // IntRangePolicyHandler implementation ----------------------------------------
251
IntRangePolicyHandler(const char * policy_name,const char * pref_path,int min,int max,bool clamp)252 IntRangePolicyHandler::IntRangePolicyHandler(const char* policy_name,
253 const char* pref_path,
254 int min,
255 int max,
256 bool clamp)
257 : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
258 pref_path_(pref_path) {
259 }
260
~IntRangePolicyHandler()261 IntRangePolicyHandler::~IntRangePolicyHandler() {
262 }
263
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)264 void IntRangePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
265 PrefValueMap* prefs) {
266 if (!pref_path_)
267 return;
268 const base::Value* value = policies.GetValue(policy_name());
269 int value_in_range;
270 if (value && EnsureInRange(value, &value_in_range, NULL)) {
271 prefs->SetValue(pref_path_,
272 new base::FundamentalValue(value_in_range));
273 }
274 }
275
276
277 // IntPercentageToDoublePolicyHandler implementation ---------------------------
278
IntPercentageToDoublePolicyHandler(const char * policy_name,const char * pref_path,int min,int max,bool clamp)279 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler(
280 const char* policy_name,
281 const char* pref_path,
282 int min,
283 int max,
284 bool clamp)
285 : IntRangePolicyHandlerBase(policy_name, min, max, clamp),
286 pref_path_(pref_path) {
287 }
288
~IntPercentageToDoublePolicyHandler()289 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() {
290 }
291
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)292 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings(
293 const PolicyMap& policies,
294 PrefValueMap* prefs) {
295 if (!pref_path_)
296 return;
297 const base::Value* value = policies.GetValue(policy_name());
298 int percentage;
299 if (value && EnsureInRange(value, &percentage, NULL)) {
300 prefs->SetValue(pref_path_, base::Value::CreateDoubleValue(
301 static_cast<double>(percentage) / 100.));
302 }
303 }
304
305
306 // SimplePolicyHandler implementation ------------------------------------------
307
SimplePolicyHandler(const char * policy_name,const char * pref_path,base::Value::Type value_type)308 SimplePolicyHandler::SimplePolicyHandler(
309 const char* policy_name,
310 const char* pref_path,
311 base::Value::Type value_type)
312 : TypeCheckingPolicyHandler(policy_name, value_type),
313 pref_path_(pref_path) {
314 }
315
~SimplePolicyHandler()316 SimplePolicyHandler::~SimplePolicyHandler() {
317 }
318
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)319 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
320 PrefValueMap* prefs) {
321 if (!pref_path_)
322 return;
323 const base::Value* value = policies.GetValue(policy_name());
324 if (value)
325 prefs->SetValue(pref_path_, value->DeepCopy());
326 }
327
328
329 // SchemaValidatingPolicyHandler implementation --------------------------------
330
SchemaValidatingPolicyHandler(const char * policy_name,Schema schema,SchemaOnErrorStrategy strategy)331 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler(
332 const char* policy_name,
333 Schema schema,
334 SchemaOnErrorStrategy strategy)
335 : policy_name_(policy_name), schema_(schema), strategy_(strategy) {
336 DCHECK(schema_.valid());
337 }
338
~SchemaValidatingPolicyHandler()339 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() {
340 }
341
policy_name() const342 const char* SchemaValidatingPolicyHandler::policy_name() const {
343 return policy_name_;
344 }
345
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)346 bool SchemaValidatingPolicyHandler::CheckPolicySettings(
347 const PolicyMap& policies,
348 PolicyErrorMap* errors) {
349 const base::Value* value = policies.GetValue(policy_name());
350 if (!value)
351 return true;
352
353 std::string error_path;
354 std::string error;
355 bool result = schema_.Validate(*value, strategy_, &error_path, &error);
356
357 if (errors && !error.empty()) {
358 if (error_path.empty())
359 error_path = "(ROOT)";
360 errors->AddError(policy_name_, error_path, error);
361 }
362
363 return result;
364 }
365
CheckAndGetValue(const PolicyMap & policies,PolicyErrorMap * errors,scoped_ptr<base::Value> * output)366 bool SchemaValidatingPolicyHandler::CheckAndGetValue(
367 const PolicyMap& policies,
368 PolicyErrorMap* errors,
369 scoped_ptr<base::Value>* output) {
370 const base::Value* value = policies.GetValue(policy_name());
371 if (!value)
372 return true;
373
374 output->reset(value->DeepCopy());
375 std::string error_path;
376 std::string error;
377 bool result =
378 schema_.Normalize(output->get(), strategy_, &error_path, &error, NULL);
379
380 if (errors && !error.empty()) {
381 if (error_path.empty())
382 error_path = "(ROOT)";
383 errors->AddError(policy_name_, error_path, error);
384 }
385
386 return result;
387 }
388
389 // SimpleSchemaValidatingPolicyHandler implementation --------------------------
390
SimpleSchemaValidatingPolicyHandler(const char * policy_name,const char * pref_path,Schema schema,SchemaOnErrorStrategy strategy,RecommendedPermission recommended_permission,MandatoryPermission mandatory_permission)391 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler(
392 const char* policy_name,
393 const char* pref_path,
394 Schema schema,
395 SchemaOnErrorStrategy strategy,
396 RecommendedPermission recommended_permission,
397 MandatoryPermission mandatory_permission)
398 : SchemaValidatingPolicyHandler(policy_name,
399 schema.GetKnownProperty(policy_name),
400 strategy),
401 pref_path_(pref_path),
402 allow_recommended_(recommended_permission == RECOMMENDED_ALLOWED),
403 allow_mandatory_(mandatory_permission == MANDATORY_ALLOWED) {
404 }
405
~SimpleSchemaValidatingPolicyHandler()406 SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() {
407 }
408
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)409 bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings(
410 const PolicyMap& policies,
411 PolicyErrorMap* errors) {
412 const PolicyMap::Entry* policy_entry = policies.Get(policy_name());
413 if (!policy_entry)
414 return true;
415 if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY &&
416 !allow_mandatory_) ||
417 (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED &&
418 !allow_recommended_)) {
419 if (errors)
420 errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR);
421 return false;
422 }
423
424 return SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors);
425 }
426
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)427 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings(
428 const PolicyMap& policies,
429 PrefValueMap* prefs) {
430 if (!pref_path_)
431 return;
432 const base::Value* value = policies.GetValue(policy_name());
433 if (value)
434 prefs->SetValue(pref_path_, value->DeepCopy());
435 }
436
437 // LegacyPoliciesDeprecatingPolicyHandler implementation -----------------------
438
439 // TODO(binjin): Add a new common base class for SchemaValidatingPolicyHandler
440 // and TypeCheckingPolicyHandler representing policy handlers for a single
441 // policy, and use it as the type of |new_policy_handler|.
442 // http://crbug.com/345299
LegacyPoliciesDeprecatingPolicyHandler(ScopedVector<ConfigurationPolicyHandler> legacy_policy_handlers,scoped_ptr<SchemaValidatingPolicyHandler> new_policy_handler)443 LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler(
444 ScopedVector<ConfigurationPolicyHandler> legacy_policy_handlers,
445 scoped_ptr<SchemaValidatingPolicyHandler> new_policy_handler)
446 : legacy_policy_handlers_(legacy_policy_handlers.Pass()),
447 new_policy_handler_(new_policy_handler.Pass()) {
448 }
449
450 LegacyPoliciesDeprecatingPolicyHandler::
~LegacyPoliciesDeprecatingPolicyHandler()451 ~LegacyPoliciesDeprecatingPolicyHandler() {
452 }
453
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)454 bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings(
455 const PolicyMap& policies,
456 PolicyErrorMap* errors) {
457 if (policies.Get(new_policy_handler_->policy_name())) {
458 return new_policy_handler_->CheckPolicySettings(policies, errors);
459 } else {
460 // The new policy is not set, fall back to legacy ones.
461 ScopedVector<ConfigurationPolicyHandler>::iterator handler;
462 bool valid_policy_found = false;
463 for (handler = legacy_policy_handlers_.begin();
464 handler != legacy_policy_handlers_.end();
465 ++handler) {
466 if ((*handler)->CheckPolicySettings(policies, errors))
467 valid_policy_found = true;
468 }
469 return valid_policy_found;
470 }
471 }
472
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)473 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings(
474 const PolicyMap& policies,
475 PrefValueMap* prefs) {
476 if (policies.Get(new_policy_handler_->policy_name())) {
477 new_policy_handler_->ApplyPolicySettings(policies, prefs);
478 } else {
479 // The new policy is not set, fall back to legacy ones.
480 PolicyErrorMap scoped_errors;
481 ScopedVector<ConfigurationPolicyHandler>::iterator handler;
482 for (handler = legacy_policy_handlers_.begin();
483 handler != legacy_policy_handlers_.end();
484 ++handler) {
485 if ((*handler)->CheckPolicySettings(policies, &scoped_errors))
486 (*handler)->ApplyPolicySettings(policies, prefs);
487 }
488 }
489 }
490
491 } // namespace policy
492