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 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 42 ConfigurationPolicyHandler::ConfigurationPolicyHandler() { 43 } 44 45 ConfigurationPolicyHandler::~ConfigurationPolicyHandler() { 46 } 47 48 void ConfigurationPolicyHandler::PrepareForDisplaying( 49 PolicyMap* policies) const {} 50 51 void ConfigurationPolicyHandler::ApplyPolicySettings( 52 const policy::PolicyMap& policies, 53 PrefValueMap* prefs) { 54 NOTREACHED(); 55 } 56 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 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 73 TypeCheckingPolicyHandler::~TypeCheckingPolicyHandler() { 74 } 75 76 const char* TypeCheckingPolicyHandler::policy_name() const { 77 return policy_name_; 78 } 79 80 bool TypeCheckingPolicyHandler::CheckPolicySettings(const PolicyMap& policies, 81 PolicyErrorMap* errors) { 82 const base::Value* value = NULL; 83 return CheckAndGetValue(policies, errors, &value); 84 } 85 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 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 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 120 IntRangePolicyHandlerBase::~IntRangePolicyHandlerBase() { 121 } 122 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 156 StringMappingListPolicyHandler::MappingEntry::MappingEntry( 157 const char* policy_value, scoped_ptr<base::Value> map) 158 : enum_value(policy_value), mapped_value(map.Pass()) {} 159 160 StringMappingListPolicyHandler::MappingEntry::~MappingEntry() {} 161 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 170 StringMappingListPolicyHandler::~StringMappingListPolicyHandler() {} 171 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 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 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 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 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 261 IntRangePolicyHandler::~IntRangePolicyHandler() { 262 } 263 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->SetInteger(pref_path_, value_in_range); 272 } 273 274 275 // IntPercentageToDoublePolicyHandler implementation --------------------------- 276 277 IntPercentageToDoublePolicyHandler::IntPercentageToDoublePolicyHandler( 278 const char* policy_name, 279 const char* pref_path, 280 int min, 281 int max, 282 bool clamp) 283 : IntRangePolicyHandlerBase(policy_name, min, max, clamp), 284 pref_path_(pref_path) { 285 } 286 287 IntPercentageToDoublePolicyHandler::~IntPercentageToDoublePolicyHandler() { 288 } 289 290 void IntPercentageToDoublePolicyHandler::ApplyPolicySettings( 291 const PolicyMap& policies, 292 PrefValueMap* prefs) { 293 if (!pref_path_) 294 return; 295 const base::Value* value = policies.GetValue(policy_name()); 296 int percentage; 297 if (value && EnsureInRange(value, &percentage, NULL)) 298 prefs->SetDouble(pref_path_, static_cast<double>(percentage) / 100.); 299 } 300 301 302 // SimplePolicyHandler implementation ------------------------------------------ 303 304 SimplePolicyHandler::SimplePolicyHandler( 305 const char* policy_name, 306 const char* pref_path, 307 base::Value::Type value_type) 308 : TypeCheckingPolicyHandler(policy_name, value_type), 309 pref_path_(pref_path) { 310 } 311 312 SimplePolicyHandler::~SimplePolicyHandler() { 313 } 314 315 void SimplePolicyHandler::ApplyPolicySettings(const PolicyMap& policies, 316 PrefValueMap* prefs) { 317 if (!pref_path_) 318 return; 319 const base::Value* value = policies.GetValue(policy_name()); 320 if (value) 321 prefs->SetValue(pref_path_, value->DeepCopy()); 322 } 323 324 325 // SchemaValidatingPolicyHandler implementation -------------------------------- 326 327 SchemaValidatingPolicyHandler::SchemaValidatingPolicyHandler( 328 const char* policy_name, 329 Schema schema, 330 SchemaOnErrorStrategy strategy) 331 : policy_name_(policy_name), schema_(schema), strategy_(strategy) { 332 DCHECK(schema_.valid()); 333 } 334 335 SchemaValidatingPolicyHandler::~SchemaValidatingPolicyHandler() { 336 } 337 338 const char* SchemaValidatingPolicyHandler::policy_name() const { 339 return policy_name_; 340 } 341 342 bool SchemaValidatingPolicyHandler::CheckPolicySettings( 343 const PolicyMap& policies, 344 PolicyErrorMap* errors) { 345 const base::Value* value = policies.GetValue(policy_name()); 346 if (!value) 347 return true; 348 349 std::string error_path; 350 std::string error; 351 bool result = schema_.Validate(*value, strategy_, &error_path, &error); 352 353 if (errors && !error.empty()) { 354 if (error_path.empty()) 355 error_path = "(ROOT)"; 356 errors->AddError(policy_name_, error_path, error); 357 } 358 359 return result; 360 } 361 362 bool SchemaValidatingPolicyHandler::CheckAndGetValue( 363 const PolicyMap& policies, 364 PolicyErrorMap* errors, 365 scoped_ptr<base::Value>* output) { 366 const base::Value* value = policies.GetValue(policy_name()); 367 if (!value) 368 return true; 369 370 output->reset(value->DeepCopy()); 371 std::string error_path; 372 std::string error; 373 bool result = 374 schema_.Normalize(output->get(), strategy_, &error_path, &error, NULL); 375 376 if (errors && !error.empty()) { 377 if (error_path.empty()) 378 error_path = "(ROOT)"; 379 errors->AddError(policy_name_, error_path, error); 380 } 381 382 return result; 383 } 384 385 // SimpleSchemaValidatingPolicyHandler implementation -------------------------- 386 387 SimpleSchemaValidatingPolicyHandler::SimpleSchemaValidatingPolicyHandler( 388 const char* policy_name, 389 const char* pref_path, 390 Schema schema, 391 SchemaOnErrorStrategy strategy, 392 RecommendedPermission recommended_permission, 393 MandatoryPermission mandatory_permission) 394 : SchemaValidatingPolicyHandler(policy_name, 395 schema.GetKnownProperty(policy_name), 396 strategy), 397 pref_path_(pref_path), 398 allow_recommended_(recommended_permission == RECOMMENDED_ALLOWED), 399 allow_mandatory_(mandatory_permission == MANDATORY_ALLOWED) { 400 } 401 402 SimpleSchemaValidatingPolicyHandler::~SimpleSchemaValidatingPolicyHandler() { 403 } 404 405 bool SimpleSchemaValidatingPolicyHandler::CheckPolicySettings( 406 const PolicyMap& policies, 407 PolicyErrorMap* errors) { 408 const PolicyMap::Entry* policy_entry = policies.Get(policy_name()); 409 if (!policy_entry) 410 return true; 411 if ((policy_entry->level == policy::POLICY_LEVEL_MANDATORY && 412 !allow_mandatory_) || 413 (policy_entry->level == policy::POLICY_LEVEL_RECOMMENDED && 414 !allow_recommended_)) { 415 if (errors) 416 errors->AddError(policy_name(), IDS_POLICY_LEVEL_ERROR); 417 return false; 418 } 419 420 return SchemaValidatingPolicyHandler::CheckPolicySettings(policies, errors); 421 } 422 423 void SimpleSchemaValidatingPolicyHandler::ApplyPolicySettings( 424 const PolicyMap& policies, 425 PrefValueMap* prefs) { 426 if (!pref_path_) 427 return; 428 const base::Value* value = policies.GetValue(policy_name()); 429 if (value) 430 prefs->SetValue(pref_path_, value->DeepCopy()); 431 } 432 433 // LegacyPoliciesDeprecatingPolicyHandler implementation ----------------------- 434 435 // TODO(binjin): Add a new common base class for SchemaValidatingPolicyHandler 436 // and TypeCheckingPolicyHandler representing policy handlers for a single 437 // policy, and use it as the type of |new_policy_handler|. 438 // http://crbug.com/345299 439 LegacyPoliciesDeprecatingPolicyHandler::LegacyPoliciesDeprecatingPolicyHandler( 440 ScopedVector<ConfigurationPolicyHandler> legacy_policy_handlers, 441 scoped_ptr<SchemaValidatingPolicyHandler> new_policy_handler) 442 : legacy_policy_handlers_(legacy_policy_handlers.Pass()), 443 new_policy_handler_(new_policy_handler.Pass()) { 444 } 445 446 LegacyPoliciesDeprecatingPolicyHandler:: 447 ~LegacyPoliciesDeprecatingPolicyHandler() { 448 } 449 450 bool LegacyPoliciesDeprecatingPolicyHandler::CheckPolicySettings( 451 const PolicyMap& policies, 452 PolicyErrorMap* errors) { 453 if (policies.Get(new_policy_handler_->policy_name())) { 454 return new_policy_handler_->CheckPolicySettings(policies, errors); 455 } else { 456 // The new policy is not set, fall back to legacy ones. 457 ScopedVector<ConfigurationPolicyHandler>::iterator handler; 458 bool valid_policy_found = false; 459 for (handler = legacy_policy_handlers_.begin(); 460 handler != legacy_policy_handlers_.end(); 461 ++handler) { 462 if ((*handler)->CheckPolicySettings(policies, errors)) 463 valid_policy_found = true; 464 } 465 return valid_policy_found; 466 } 467 } 468 469 void LegacyPoliciesDeprecatingPolicyHandler::ApplyPolicySettings( 470 const PolicyMap& policies, 471 PrefValueMap* prefs) { 472 if (policies.Get(new_policy_handler_->policy_name())) { 473 new_policy_handler_->ApplyPolicySettings(policies, prefs); 474 } else { 475 // The new policy is not set, fall back to legacy ones. 476 PolicyErrorMap scoped_errors; 477 ScopedVector<ConfigurationPolicyHandler>::iterator handler; 478 for (handler = legacy_policy_handlers_.begin(); 479 handler != legacy_policy_handlers_.end(); 480 ++handler) { 481 if ((*handler)->CheckPolicySettings(policies, &scoped_errors)) 482 (*handler)->ApplyPolicySettings(policies, prefs); 483 } 484 } 485 } 486 487 } // namespace policy 488