• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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