configuration_policy_handler_chromeos.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "crypto/sha2.h" 32#include "grit/component_strings.h" 33#include "policy/policy_constants.h" 34#include "url/gurl.h" 35 36namespace policy { 37 38namespace { 39 40const char kSubkeyURL[] = "url"; 41const char kSubkeyHash[] = "hash"; 42 43bool 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} // namespace 67 68ExternalDataPolicyHandler::ExternalDataPolicyHandler(const char* policy_name) 69 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_DICTIONARY) { 70} 71 72ExternalDataPolicyHandler::~ExternalDataPolicyHandler() { 73} 74 75bool ExternalDataPolicyHandler::CheckPolicySettings(const PolicyMap& policies, 76 PolicyErrorMap* errors) { 77 if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors)) 78 return false; 79 80 const std::string policy = policy_name(); 81 const base::Value* value = policies.GetValue(policy); 82 if (!value) 83 return true; 84 85 const base::DictionaryValue* dict = NULL; 86 value->GetAsDictionary(&dict); 87 if (!dict) { 88 NOTREACHED(); 89 return false; 90 } 91 std::string url_string; 92 std::string hash_string; 93 if (!GetSubkeyString(*dict, errors, policy, kSubkeyURL, &url_string) || 94 !GetSubkeyString(*dict, errors, policy, kSubkeyHash, &hash_string)) { 95 return false; 96 } 97 98 const GURL url(url_string); 99 if (!url.is_valid()) { 100 errors->AddError(policy, kSubkeyURL, IDS_POLICY_VALUE_FORMAT_ERROR); 101 return false; 102 } 103 104 std::vector<uint8> hash; 105 if (!base::HexStringToBytes(hash_string, &hash) || 106 hash.size() != crypto::kSHA256Length) { 107 errors->AddError(policy, kSubkeyHash, IDS_POLICY_VALUE_FORMAT_ERROR); 108 return false; 109 } 110 111 return true; 112} 113 114void ExternalDataPolicyHandler::ApplyPolicySettings(const PolicyMap& policies, 115 PrefValueMap* prefs) { 116} 117 118// static 119NetworkConfigurationPolicyHandler* 120NetworkConfigurationPolicyHandler::CreateForUserPolicy() { 121 return new NetworkConfigurationPolicyHandler( 122 key::kOpenNetworkConfiguration, 123 onc::ONC_SOURCE_USER_POLICY, 124 prefs::kOpenNetworkConfiguration); 125} 126 127// static 128NetworkConfigurationPolicyHandler* 129NetworkConfigurationPolicyHandler::CreateForDevicePolicy() { 130 return new NetworkConfigurationPolicyHandler( 131 key::kDeviceOpenNetworkConfiguration, 132 onc::ONC_SOURCE_DEVICE_POLICY, 133 prefs::kDeviceOpenNetworkConfiguration); 134} 135 136NetworkConfigurationPolicyHandler::~NetworkConfigurationPolicyHandler() {} 137 138bool NetworkConfigurationPolicyHandler::CheckPolicySettings( 139 const PolicyMap& policies, 140 PolicyErrorMap* errors) { 141 const base::Value* value; 142 if (!CheckAndGetValue(policies, errors, &value)) 143 return false; 144 145 if (value) { 146 std::string onc_blob; 147 value->GetAsString(&onc_blob); 148 scoped_ptr<base::DictionaryValue> root_dict = 149 chromeos::onc::ReadDictionaryFromJson(onc_blob); 150 if (root_dict.get() == NULL) { 151 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED); 152 return false; 153 } 154 155 // Validate the ONC dictionary. We are liberal and ignore unknown field 156 // names and ignore invalid field names in kRecommended arrays. 157 chromeos::onc::Validator validator( 158 false, // Ignore unknown fields. 159 false, // Ignore invalid recommended field names. 160 true, // Fail on missing fields. 161 true); // Validate for managed ONC 162 validator.SetOncSource(onc_source_); 163 164 // ONC policies are always unencrypted. 165 chromeos::onc::Validator::Result validation_result; 166 root_dict = validator.ValidateAndRepairObject( 167 &chromeos::onc::kToplevelConfigurationSignature, *root_dict, 168 &validation_result); 169 if (validation_result == chromeos::onc::Validator::VALID_WITH_WARNINGS) 170 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_PARTIAL); 171 else if (validation_result == chromeos::onc::Validator::INVALID) 172 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_FAILED); 173 174 // In any case, don't reject the policy as some networks or certificates 175 // could still be applied. 176 } 177 178 return true; 179} 180 181void NetworkConfigurationPolicyHandler::ApplyPolicySettings( 182 const PolicyMap& policies, 183 PrefValueMap* prefs) { 184 const base::Value* value = policies.GetValue(policy_name()); 185 if (!value) 186 return; 187 188 std::string onc_blob; 189 value->GetAsString(&onc_blob); 190 191 scoped_ptr<base::ListValue> network_configs(new base::ListValue); 192 base::ListValue certificates; 193 base::DictionaryValue global_network_config; 194 chromeos::onc::ParseAndValidateOncForImport(onc_blob, 195 onc_source_, 196 "", 197 network_configs.get(), 198 &global_network_config, 199 &certificates); 200 201 // Currently, only the per-network configuration is stored in a pref. Ignore 202 // |global_network_config| and |certificates|. 203 prefs->SetValue(pref_path_, network_configs.release()); 204} 205 206void NetworkConfigurationPolicyHandler::PrepareForDisplaying( 207 PolicyMap* policies) const { 208 const PolicyMap::Entry* entry = policies->Get(policy_name()); 209 if (!entry) 210 return; 211 base::Value* sanitized_config = SanitizeNetworkConfig(entry->value); 212 if (!sanitized_config) 213 sanitized_config = base::Value::CreateNullValue(); 214 215 policies->Set(policy_name(), entry->level, entry->scope, 216 sanitized_config, NULL); 217} 218 219NetworkConfigurationPolicyHandler::NetworkConfigurationPolicyHandler( 220 const char* policy_name, 221 onc::ONCSource onc_source, 222 const char* pref_path) 223 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_STRING), 224 onc_source_(onc_source), 225 pref_path_(pref_path) { 226} 227 228// static 229base::Value* NetworkConfigurationPolicyHandler::SanitizeNetworkConfig( 230 const base::Value* config) { 231 std::string json_string; 232 if (!config->GetAsString(&json_string)) 233 return NULL; 234 235 scoped_ptr<base::DictionaryValue> toplevel_dict = 236 chromeos::onc::ReadDictionaryFromJson(json_string); 237 if (!toplevel_dict) 238 return NULL; 239 240 // Placeholder to insert in place of the filtered setting. 241 const char kPlaceholder[] = "********"; 242 243 toplevel_dict = chromeos::onc::MaskCredentialsInOncObject( 244 chromeos::onc::kToplevelConfigurationSignature, 245 *toplevel_dict, 246 kPlaceholder); 247 248 base::JSONWriter::WriteWithOptions(toplevel_dict.get(), 249 base::JSONWriter::OPTIONS_PRETTY_PRINT, 250 &json_string); 251 return base::Value::CreateStringValue(json_string); 252} 253 254PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler() 255 : ExtensionListPolicyHandler(key::kPinnedLauncherApps, 256 prefs::kPinnedLauncherApps, 257 false) {} 258 259PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {} 260 261void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings( 262 const PolicyMap& policies, 263 PrefValueMap* prefs) { 264 PolicyErrorMap errors; 265 const base::Value* policy_value = policies.GetValue(policy_name()); 266 const base::ListValue* policy_list = NULL; 267 if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) { 268 base::ListValue* pinned_apps_list = new base::ListValue(); 269 for (base::ListValue::const_iterator entry(policy_list->begin()); 270 entry != policy_list->end(); ++entry) { 271 std::string id; 272 if ((*entry)->GetAsString(&id)) { 273 base::DictionaryValue* app_dict = new base::DictionaryValue(); 274 app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id); 275 pinned_apps_list->Append(app_dict); 276 } 277 } 278 prefs->SetValue(pref_path(), pinned_apps_list); 279 } 280} 281 282ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler() 283 : IntRangePolicyHandlerBase(key::kScreenMagnifierType, 284 0, ash::MAGNIFIER_FULL, false) { 285} 286 287ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() { 288} 289 290void ScreenMagnifierPolicyHandler::ApplyPolicySettings( 291 const PolicyMap& policies, 292 PrefValueMap* prefs) { 293 const base::Value* value = policies.GetValue(policy_name()); 294 int value_in_range; 295 if (value && EnsureInRange(value, &value_in_range, NULL)) { 296 prefs->SetValue(prefs::kScreenMagnifierEnabled, 297 base::Value::CreateBooleanValue(value_in_range != 0)); 298 prefs->SetValue(prefs::kScreenMagnifierType, 299 base::Value::CreateIntegerValue(value_in_range)); 300 } 301} 302 303LoginScreenPowerManagementPolicyHandler:: 304 LoginScreenPowerManagementPolicyHandler() 305 : TypeCheckingPolicyHandler(key::kDeviceLoginScreenPowerManagement, 306 base::Value::TYPE_STRING) { 307} 308 309LoginScreenPowerManagementPolicyHandler:: 310 ~LoginScreenPowerManagementPolicyHandler() { 311} 312 313bool LoginScreenPowerManagementPolicyHandler::CheckPolicySettings( 314 const PolicyMap& policies, 315 PolicyErrorMap* errors) { 316 const base::Value* value; 317 if (!CheckAndGetValue(policies, errors, &value)) 318 return false; 319 320 if (!value) 321 return true; 322 323 std::string json; 324 value->GetAsString(&json); 325 return LoginScreenPowerManagementPolicy().Init(json, errors); 326} 327 328void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings( 329 const PolicyMap& policies, 330 PrefValueMap* prefs) { 331} 332 333DeprecatedIdleActionHandler::DeprecatedIdleActionHandler() 334 : IntRangePolicyHandlerBase( 335 key::kIdleAction, 336 chromeos::PowerPolicyController::ACTION_SUSPEND, 337 chromeos::PowerPolicyController::ACTION_DO_NOTHING, 338 false) {} 339 340DeprecatedIdleActionHandler::~DeprecatedIdleActionHandler() {} 341 342void DeprecatedIdleActionHandler::ApplyPolicySettings(const PolicyMap& policies, 343 PrefValueMap* prefs) { 344 const base::Value* value = policies.GetValue(policy_name()); 345 if (value && EnsureInRange(value, NULL, NULL)) { 346 if (!prefs->GetValue(prefs::kPowerAcIdleAction, NULL)) 347 prefs->SetValue(prefs::kPowerAcIdleAction, value->DeepCopy()); 348 if (!prefs->GetValue(prefs::kPowerBatteryIdleAction, NULL)) 349 prefs->SetValue(prefs::kPowerBatteryIdleAction, value->DeepCopy()); 350 } 351} 352 353} // namespace policy 354