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