configuration_policy_handler_chromeos.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h" 6 7#include <string> 8#include <vector> 9 10#include "ash/magnifier/magnifier_constants.h" 11#include "base/callback.h" 12#include "base/json/json_reader.h" 13#include "base/json/json_writer.h" 14#include "base/logging.h" 15#include "base/memory/scoped_ptr.h" 16#include "base/prefs/pref_value_map.h" 17#include "base/strings/string_number_conversions.h" 18#include "base/strings/string_util.h" 19#include "base/values.h" 20#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h" 21#include "chrome/browser/ui/ash/chrome_launcher_prefs.h" 22#include "chrome/common/pref_names.h" 23#include "chromeos/dbus/power_policy_controller.h" 24#include "chromeos/network/onc/onc_signature.h" 25#include "chromeos/network/onc/onc_utils.h" 26#include "chromeos/network/onc/onc_validator.h" 27#include "components/onc/onc_constants.h" 28#include "components/policy/core/browser/policy_error_map.h" 29#include "components/policy/core/common/external_data_fetcher.h" 30#include "components/policy/core/common/policy_map.h" 31#include "components/policy/core/common/schema.h" 32#include "crypto/sha2.h" 33#include "grit/component_strings.h" 34#include "policy/policy_constants.h" 35#include "url/gurl.h" 36 37namespace policy { 38 39namespace { 40 41const char kSubkeyURL[] = "url"; 42const char kSubkeyHash[] = "hash"; 43 44bool GetSubkeyString(const base::DictionaryValue& dict, 45 policy::PolicyErrorMap* errors, 46 const std::string& policy, 47 const std::string& subkey, 48 std::string* value) { 49 const base::Value* raw_value = NULL; 50 if (!dict.GetWithoutPathExpansion(subkey, &raw_value)) { 51 errors->AddError(policy, subkey, IDS_POLICY_NOT_SPECIFIED_ERROR); 52 return false; 53 } 54 std::string string_value; 55 if (!raw_value->GetAsString(&string_value)) { 56 errors->AddError(policy, subkey, IDS_POLICY_TYPE_ERROR, "string"); 57 return false; 58 } 59 if (string_value.empty()) { 60 errors->AddError(policy, subkey, IDS_POLICY_NOT_SPECIFIED_ERROR); 61 return false; 62 } 63 *value = string_value; 64 return true; 65} 66 67const char kScreenDimDelayAC[] = "AC.Delays.ScreenDim"; 68const char kScreenOffDelayAC[] = "AC.Delays.ScreenOff"; 69const char kIdleWarningDelayAC[] = "AC.Delays.IdleWarning"; 70const char kIdleDelayAC[] = "AC.Delays.Idle"; 71const char kIdleActionAC[] = "AC.IdleAction"; 72 73const char kScreenDimDelayBattery[] = "Battery.Delays.ScreenDim"; 74const char kScreenOffDelayBattery[] = "Battery.Delays.ScreenOff"; 75const char kIdleWarningDelayBattery[] = "Battery.Delays.IdleWarning"; 76const char kIdleDelayBattery[] = "Battery.Delays.Idle"; 77const char kIdleActionBattery[] = "Battery.IdleAction"; 78 79const char kScreenLockDelayAC[] = "AC"; 80const char kScreenLockDelayBattery[] = "Battery"; 81 82const char kActionSuspend[] = "Suspend"; 83const char kActionLogout[] = "Logout"; 84const char kActionShutdown[] = "Shutdown"; 85const char kActionDoNothing[] = "DoNothing"; 86 87scoped_ptr<base::Value> GetValue(const base::DictionaryValue* dict, 88 const char* key) { 89 const base::Value* value = NULL; 90 if (!dict->Get(key, &value)) 91 return scoped_ptr<base::Value>(); 92 return scoped_ptr<base::Value>(value->DeepCopy()); 93} 94 95scoped_ptr<base::Value> GetAction(const base::DictionaryValue* dict, 96 const char* key) { 97 scoped_ptr<base::Value> value = GetValue(dict, key); 98 std::string action; 99 if (!value || !value->GetAsString(&action)) 100 return scoped_ptr<base::Value>(); 101 if (action == kActionSuspend) { 102 return scoped_ptr<base::Value>(new base::FundamentalValue( 103 chromeos::PowerPolicyController::ACTION_SUSPEND)); 104 } 105 if (action == kActionLogout) { 106 return scoped_ptr<base::Value>(new base::FundamentalValue( 107 chromeos::PowerPolicyController::ACTION_STOP_SESSION)); 108 } 109 if (action == kActionShutdown) { 110 return scoped_ptr<base::Value>(new base::FundamentalValue( 111 chromeos::PowerPolicyController::ACTION_SHUT_DOWN)); 112 } 113 if (action == kActionDoNothing) { 114 return scoped_ptr<base::Value>(new base::FundamentalValue( 115 chromeos::PowerPolicyController::ACTION_DO_NOTHING)); 116 } 117 return scoped_ptr<base::Value>(); 118} 119 120} // namespace 121 122ExternalDataPolicyHandler::ExternalDataPolicyHandler(const char* policy_name) 123 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_DICTIONARY) { 124} 125 126ExternalDataPolicyHandler::~ExternalDataPolicyHandler() { 127} 128 129bool ExternalDataPolicyHandler::CheckPolicySettings(const PolicyMap& policies, 130 PolicyErrorMap* errors) { 131 if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors)) 132 return false; 133 134 const std::string policy = policy_name(); 135 const base::Value* value = policies.GetValue(policy); 136 if (!value) 137 return true; 138 139 const base::DictionaryValue* dict = NULL; 140 value->GetAsDictionary(&dict); 141 if (!dict) { 142 NOTREACHED(); 143 return false; 144 } 145 std::string url_string; 146 std::string hash_string; 147 if (!GetSubkeyString(*dict, errors, policy, kSubkeyURL, &url_string) || 148 !GetSubkeyString(*dict, errors, policy, kSubkeyHash, &hash_string)) { 149 return false; 150 } 151 152 const GURL url(url_string); 153 if (!url.is_valid()) { 154 errors->AddError(policy, kSubkeyURL, IDS_POLICY_VALUE_FORMAT_ERROR); 155 return false; 156 } 157 158 std::vector<uint8> hash; 159 if (!base::HexStringToBytes(hash_string, &hash) || 160 hash.size() != crypto::kSHA256Length) { 161 errors->AddError(policy, kSubkeyHash, IDS_POLICY_VALUE_FORMAT_ERROR); 162 return false; 163 } 164 165 return true; 166} 167 168void ExternalDataPolicyHandler::ApplyPolicySettings(const PolicyMap& policies, 169 PrefValueMap* prefs) { 170} 171 172// static 173NetworkConfigurationPolicyHandler* 174NetworkConfigurationPolicyHandler::CreateForUserPolicy() { 175 return new NetworkConfigurationPolicyHandler( 176 key::kOpenNetworkConfiguration, 177 onc::ONC_SOURCE_USER_POLICY, 178 prefs::kOpenNetworkConfiguration); 179} 180 181// static 182NetworkConfigurationPolicyHandler* 183NetworkConfigurationPolicyHandler::CreateForDevicePolicy() { 184 return new NetworkConfigurationPolicyHandler( 185 key::kDeviceOpenNetworkConfiguration, 186 onc::ONC_SOURCE_DEVICE_POLICY, 187 prefs::kDeviceOpenNetworkConfiguration); 188} 189 190NetworkConfigurationPolicyHandler::~NetworkConfigurationPolicyHandler() {} 191 192bool NetworkConfigurationPolicyHandler::CheckPolicySettings( 193 const PolicyMap& policies, 194 PolicyErrorMap* errors) { 195 const base::Value* value; 196 if (!CheckAndGetValue(policies, errors, &value)) 197 return false; 198 199 if (value) { 200 std::string onc_blob; 201 value->GetAsString(&onc_blob); 202 scoped_ptr<base::DictionaryValue> root_dict = 203 chromeos::onc::ReadDictionaryFromJson(onc_blob); 204 if (root_dict.get() == NULL) { 205 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED); 206 return false; 207 } 208 209 // Validate the ONC dictionary. We are liberal and ignore unknown field 210 // names and ignore invalid field names in kRecommended arrays. 211 chromeos::onc::Validator validator( 212 false, // Ignore unknown fields. 213 false, // Ignore invalid recommended field names. 214 true, // Fail on missing fields. 215 true); // Validate for managed ONC 216 validator.SetOncSource(onc_source_); 217 218 // ONC policies are always unencrypted. 219 chromeos::onc::Validator::Result validation_result; 220 root_dict = validator.ValidateAndRepairObject( 221 &chromeos::onc::kToplevelConfigurationSignature, *root_dict, 222 &validation_result); 223 if (validation_result == chromeos::onc::Validator::VALID_WITH_WARNINGS) 224 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_PARTIAL); 225 else if (validation_result == chromeos::onc::Validator::INVALID) 226 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_FAILED); 227 228 // In any case, don't reject the policy as some networks or certificates 229 // could still be applied. 230 } 231 232 return true; 233} 234 235void NetworkConfigurationPolicyHandler::ApplyPolicySettings( 236 const PolicyMap& policies, 237 PrefValueMap* prefs) { 238 const base::Value* value = policies.GetValue(policy_name()); 239 if (!value) 240 return; 241 242 std::string onc_blob; 243 value->GetAsString(&onc_blob); 244 245 scoped_ptr<base::ListValue> network_configs(new base::ListValue); 246 base::ListValue certificates; 247 base::DictionaryValue global_network_config; 248 chromeos::onc::ParseAndValidateOncForImport(onc_blob, 249 onc_source_, 250 "", 251 network_configs.get(), 252 &global_network_config, 253 &certificates); 254 255 // Currently, only the per-network configuration is stored in a pref. Ignore 256 // |global_network_config| and |certificates|. 257 prefs->SetValue(pref_path_, network_configs.release()); 258} 259 260void NetworkConfigurationPolicyHandler::PrepareForDisplaying( 261 PolicyMap* policies) const { 262 const PolicyMap::Entry* entry = policies->Get(policy_name()); 263 if (!entry) 264 return; 265 base::Value* sanitized_config = SanitizeNetworkConfig(entry->value); 266 if (!sanitized_config) 267 sanitized_config = base::Value::CreateNullValue(); 268 269 policies->Set(policy_name(), entry->level, entry->scope, 270 sanitized_config, NULL); 271} 272 273NetworkConfigurationPolicyHandler::NetworkConfigurationPolicyHandler( 274 const char* policy_name, 275 onc::ONCSource onc_source, 276 const char* pref_path) 277 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_STRING), 278 onc_source_(onc_source), 279 pref_path_(pref_path) { 280} 281 282// static 283base::Value* NetworkConfigurationPolicyHandler::SanitizeNetworkConfig( 284 const base::Value* config) { 285 std::string json_string; 286 if (!config->GetAsString(&json_string)) 287 return NULL; 288 289 scoped_ptr<base::DictionaryValue> toplevel_dict = 290 chromeos::onc::ReadDictionaryFromJson(json_string); 291 if (!toplevel_dict) 292 return NULL; 293 294 // Placeholder to insert in place of the filtered setting. 295 const char kPlaceholder[] = "********"; 296 297 toplevel_dict = chromeos::onc::MaskCredentialsInOncObject( 298 chromeos::onc::kToplevelConfigurationSignature, 299 *toplevel_dict, 300 kPlaceholder); 301 302 base::JSONWriter::WriteWithOptions(toplevel_dict.get(), 303 base::JSONWriter::OPTIONS_PRETTY_PRINT, 304 &json_string); 305 return base::Value::CreateStringValue(json_string); 306} 307 308PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler() 309 : ExtensionListPolicyHandler(key::kPinnedLauncherApps, 310 prefs::kPinnedLauncherApps, 311 false) {} 312 313PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {} 314 315void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings( 316 const PolicyMap& policies, 317 PrefValueMap* prefs) { 318 PolicyErrorMap errors; 319 const base::Value* policy_value = policies.GetValue(policy_name()); 320 const base::ListValue* policy_list = NULL; 321 if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) { 322 base::ListValue* pinned_apps_list = new base::ListValue(); 323 for (base::ListValue::const_iterator entry(policy_list->begin()); 324 entry != policy_list->end(); ++entry) { 325 std::string id; 326 if ((*entry)->GetAsString(&id)) { 327 base::DictionaryValue* app_dict = new base::DictionaryValue(); 328 app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id); 329 pinned_apps_list->Append(app_dict); 330 } 331 } 332 prefs->SetValue(pref_path(), pinned_apps_list); 333 } 334} 335 336ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler() 337 : IntRangePolicyHandlerBase(key::kScreenMagnifierType, 338 0, ash::MAGNIFIER_FULL, false) { 339} 340 341ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() { 342} 343 344void ScreenMagnifierPolicyHandler::ApplyPolicySettings( 345 const PolicyMap& policies, 346 PrefValueMap* prefs) { 347 const base::Value* value = policies.GetValue(policy_name()); 348 int value_in_range; 349 if (value && EnsureInRange(value, &value_in_range, NULL)) { 350 prefs->SetValue(prefs::kScreenMagnifierEnabled, 351 base::Value::CreateBooleanValue(value_in_range != 0)); 352 prefs->SetValue(prefs::kScreenMagnifierType, 353 base::Value::CreateIntegerValue(value_in_range)); 354 } 355} 356 357LoginScreenPowerManagementPolicyHandler:: 358 LoginScreenPowerManagementPolicyHandler() 359 : TypeCheckingPolicyHandler(key::kDeviceLoginScreenPowerManagement, 360 base::Value::TYPE_STRING) { 361} 362 363LoginScreenPowerManagementPolicyHandler:: 364 ~LoginScreenPowerManagementPolicyHandler() { 365} 366 367bool LoginScreenPowerManagementPolicyHandler::CheckPolicySettings( 368 const PolicyMap& policies, 369 PolicyErrorMap* errors) { 370 const base::Value* value; 371 if (!CheckAndGetValue(policies, errors, &value)) 372 return false; 373 374 if (!value) 375 return true; 376 377 std::string json; 378 value->GetAsString(&json); 379 return LoginScreenPowerManagementPolicy().Init(json, errors); 380} 381 382void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings( 383 const PolicyMap& policies, 384 PrefValueMap* prefs) { 385} 386 387DeprecatedIdleActionHandler::DeprecatedIdleActionHandler() 388 : IntRangePolicyHandlerBase( 389 key::kIdleAction, 390 chromeos::PowerPolicyController::ACTION_SUSPEND, 391 chromeos::PowerPolicyController::ACTION_DO_NOTHING, 392 false) {} 393 394DeprecatedIdleActionHandler::~DeprecatedIdleActionHandler() {} 395 396void DeprecatedIdleActionHandler::ApplyPolicySettings(const PolicyMap& policies, 397 PrefValueMap* prefs) { 398 const base::Value* value = policies.GetValue(policy_name()); 399 if (value && EnsureInRange(value, NULL, NULL)) { 400 if (!prefs->GetValue(prefs::kPowerAcIdleAction, NULL)) 401 prefs->SetValue(prefs::kPowerAcIdleAction, value->DeepCopy()); 402 if (!prefs->GetValue(prefs::kPowerBatteryIdleAction, NULL)) 403 prefs->SetValue(prefs::kPowerBatteryIdleAction, value->DeepCopy()); 404 } 405} 406 407PowerManagementIdleSettingsPolicyHandler:: 408 PowerManagementIdleSettingsPolicyHandler(const Schema& chrome_schema) 409 : SchemaValidatingPolicyHandler( 410 key::kPowerManagementIdleSettings, 411 chrome_schema.GetKnownProperty(key::kPowerManagementIdleSettings), 412 SCHEMA_ALLOW_UNKNOWN) { 413} 414 415PowerManagementIdleSettingsPolicyHandler:: 416 ~PowerManagementIdleSettingsPolicyHandler() { 417} 418 419void PowerManagementIdleSettingsPolicyHandler::ApplyPolicySettings( 420 const PolicyMap& policies, 421 PrefValueMap* prefs) { 422 scoped_ptr<base::Value> policy_value; 423 if (!CheckAndGetValue(policies, NULL, &policy_value)) 424 return; 425 const base::DictionaryValue* dict = NULL; 426 if (!policy_value->GetAsDictionary(&dict)) { 427 NOTREACHED(); 428 return; 429 } 430 scoped_ptr<base::Value> value; 431 432 value = GetValue(dict, kScreenDimDelayAC); 433 if (value) 434 prefs->SetValue(prefs::kPowerAcScreenDimDelayMs, value.release()); 435 value = GetValue(dict, kScreenOffDelayAC); 436 if (value) 437 prefs->SetValue(prefs::kPowerAcScreenOffDelayMs, value.release()); 438 value = GetValue(dict, kIdleWarningDelayAC); 439 if (value) 440 prefs->SetValue(prefs::kPowerAcIdleWarningDelayMs, value.release()); 441 value = GetValue(dict, kIdleDelayAC); 442 if (value) 443 prefs->SetValue(prefs::kPowerAcIdleDelayMs, value.release()); 444 value = GetAction(dict, kIdleActionAC); 445 if (value) 446 prefs->SetValue(prefs::kPowerAcIdleAction, value.release()); 447 448 value = GetValue(dict, kScreenDimDelayBattery); 449 if (value) 450 prefs->SetValue(prefs::kPowerBatteryScreenDimDelayMs, value.release()); 451 value = GetValue(dict, kScreenOffDelayBattery); 452 if (value) 453 prefs->SetValue(prefs::kPowerBatteryScreenOffDelayMs, value.release()); 454 value = GetValue(dict, kIdleWarningDelayBattery); 455 if (value) 456 prefs->SetValue(prefs::kPowerBatteryIdleWarningDelayMs, value.release()); 457 value = GetValue(dict, kIdleDelayBattery); 458 if (value) 459 prefs->SetValue(prefs::kPowerBatteryIdleDelayMs, value.release()); 460 value = GetAction(dict, kIdleActionBattery); 461 if (value) 462 prefs->SetValue(prefs::kPowerBatteryIdleAction, value.release()); 463} 464 465ScreenLockDelayPolicyHandler::ScreenLockDelayPolicyHandler( 466 const Schema& chrome_schema) 467 : SchemaValidatingPolicyHandler( 468 key::kScreenLockDelays, 469 chrome_schema.GetKnownProperty(key::kScreenLockDelays), 470 SCHEMA_ALLOW_UNKNOWN) { 471} 472 473ScreenLockDelayPolicyHandler::~ScreenLockDelayPolicyHandler() { 474} 475 476void ScreenLockDelayPolicyHandler::ApplyPolicySettings( 477 const PolicyMap& policies, 478 PrefValueMap* prefs) { 479 scoped_ptr<base::Value> policy_value; 480 if (!CheckAndGetValue(policies, NULL, &policy_value)) 481 return; 482 const base::DictionaryValue* dict = NULL; 483 if (!policy_value->GetAsDictionary(&dict)) { 484 NOTREACHED(); 485 return; 486 } 487 scoped_ptr<base::Value> value; 488 489 value = GetValue(dict, kScreenLockDelayAC); 490 if (value) 491 prefs->SetValue(prefs::kPowerAcScreenLockDelayMs, value.release()); 492 value = GetValue(dict, kScreenLockDelayBattery); 493 if (value) 494 prefs->SetValue(prefs::kPowerBatteryScreenLockDelayMs, value.release()); 495} 496 497} // namespace policy 498