configuration_policy_handler_chromeos.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 9#include "base/json/json_reader.h" 10#include "base/json/json_writer.h" 11#include "base/memory/scoped_ptr.h" 12#include "base/prefs/pref_value_map.h" 13#include "base/string_util.h" 14#include "base/values.h" 15#include "chrome/browser/policy/policy_error_map.h" 16#include "chrome/browser/policy/policy_map.h" 17#include "chrome/browser/ui/ash/chrome_launcher_prefs.h" 18#include "chrome/common/pref_names.h" 19#include "chromeos/network/onc/onc_constants.h" 20#include "chromeos/network/onc/onc_signature.h" 21#include "chromeos/network/onc/onc_utils.h" 22#include "chromeos/network/onc/onc_validator.h" 23#include "grit/generated_resources.h" 24#include "policy/policy_constants.h" 25 26namespace onc = chromeos::onc; 27 28namespace { 29 30} // namespace 31 32namespace policy { 33 34NetworkConfigurationPolicyHandler::NetworkConfigurationPolicyHandler( 35 const char* policy_name, 36 chromeos::onc::ONCSource onc_source) 37 : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_STRING), 38 onc_source_(onc_source) {} 39 40NetworkConfigurationPolicyHandler::~NetworkConfigurationPolicyHandler() {} 41 42bool NetworkConfigurationPolicyHandler::CheckPolicySettings( 43 const PolicyMap& policies, 44 PolicyErrorMap* errors) { 45 const base::Value* value; 46 if (!CheckAndGetValue(policies, errors, &value)) 47 return false; 48 49 if (value) { 50 std::string onc_blob; 51 value->GetAsString(&onc_blob); 52 scoped_ptr<base::DictionaryValue> root_dict = 53 onc::ReadDictionaryFromJson(onc_blob); 54 if (root_dict.get() == NULL) { 55 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED); 56 return false; 57 } 58 59 // Validate the ONC dictionary. We are liberal and ignore unknown field 60 // names and ignore invalid field names in kRecommended arrays. 61 onc::Validator validator(false, // Ignore unknown fields. 62 false, // Ignore invalid recommended field names. 63 true, // Fail on missing fields. 64 true); // Validate for managed ONC 65 validator.SetOncSource(onc_source_); 66 67 // ONC policies are always unencrypted. 68 onc::Validator::Result validation_result; 69 root_dict = validator.ValidateAndRepairObject( 70 &onc::kToplevelConfigurationSignature, *root_dict, &validation_result); 71 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { 72 errors->AddError(policy_name(), 73 IDS_POLICY_NETWORK_CONFIG_IMPORT_PARTIAL); 74 } else if (validation_result == onc::Validator::INVALID) { 75 errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_FAILED); 76 } 77 78 // In any case, don't reject the policy as some networks or certificates 79 // could still be applied. 80 } 81 82 return true; 83} 84 85void NetworkConfigurationPolicyHandler::ApplyPolicySettings( 86 const PolicyMap& policies, 87 PrefValueMap* prefs) { 88 // Network policy is read directly from the provider and injected into 89 // NetworkLibrary, so no need to convert the policy settings into prefs. 90} 91 92void NetworkConfigurationPolicyHandler::PrepareForDisplaying( 93 PolicyMap* policies) const { 94 const PolicyMap::Entry* entry = policies->Get(policy_name()); 95 if (!entry) 96 return; 97 base::Value* sanitized_config = SanitizeNetworkConfig(entry->value); 98 if (!sanitized_config) 99 sanitized_config = base::Value::CreateNullValue(); 100 101 policies->Set(policy_name(), entry->level, entry->scope, sanitized_config); 102} 103 104// static 105base::Value* NetworkConfigurationPolicyHandler::SanitizeNetworkConfig( 106 const base::Value* config) { 107 std::string json_string; 108 if (!config->GetAsString(&json_string)) 109 return NULL; 110 111 scoped_ptr<base::Value> json_value( 112 base::JSONReader::Read(json_string, base::JSON_ALLOW_TRAILING_COMMAS)); 113 if (!json_value.get() || !json_value->IsType(base::Value::TYPE_DICTIONARY)) 114 return NULL; 115 116 base::DictionaryValue* config_dict = 117 static_cast<base::DictionaryValue*>(json_value.get()); 118 119 // Strip any sensitive information from the JSON dictionary. 120 base::ListValue* config_list = NULL; 121 if (config_dict->GetList("NetworkConfigurations", &config_list)) { 122 for (base::ListValue::const_iterator network_entry = config_list->begin(); 123 network_entry != config_list->end(); 124 ++network_entry) { 125 if ((*network_entry) && 126 (*network_entry)->IsType(base::Value::TYPE_DICTIONARY)) { 127 MaskSensitiveValues( 128 static_cast<base::DictionaryValue*>(*network_entry)); 129 } 130 } 131 } 132 133 // Convert back to a string, pretty printing the contents. 134 base::JSONWriter::WriteWithOptions(config_dict, 135 base::JSONWriter::OPTIONS_DO_NOT_ESCAPE | 136 base::JSONWriter::OPTIONS_PRETTY_PRINT, 137 &json_string); 138 return base::Value::CreateStringValue(json_string); 139} 140 141// static 142void NetworkConfigurationPolicyHandler::MaskSensitiveValues( 143 base::DictionaryValue* network_dict) { 144 // Paths of the properties to be replaced by the placeholder. Each entry 145 // specifies dictionary key paths. 146 static const int kMaxComponents = 3; 147 static const char* kFilteredSettings[][kMaxComponents] = { 148 { onc::network_config::kEthernet, onc::ethernet::kEAP, 149 onc::eap::kPassword }, 150 { onc::network_config::kVPN, onc::vpn::kIPsec, onc::vpn::kPSK }, 151 { onc::network_config::kVPN, onc::vpn::kL2TP, onc::vpn::kPassword }, 152 { onc::network_config::kVPN, onc::vpn::kOpenVPN, onc::vpn::kPassword }, 153 { onc::network_config::kVPN, onc::vpn::kOpenVPN, 154 onc::vpn::kTLSAuthContents }, 155 { onc::network_config::kWiFi, onc::wifi::kEAP, onc::eap::kPassword }, 156 { onc::network_config::kWiFi, onc::wifi::kPassphrase }, 157 }; 158 159 // Placeholder to insert in place of the filtered setting. 160 static const char kPlaceholder[] = "********"; 161 162 for (size_t i = 0; i < arraysize(kFilteredSettings); ++i) { 163 const char** path = kFilteredSettings[i]; 164 base::DictionaryValue* dict = network_dict; 165 int j = 0; 166 for (j = 0; path[j + 1] != NULL && j + 1 < kMaxComponents; ++j) { 167 if (!dict->GetDictionaryWithoutPathExpansion(path[j], &dict)) { 168 dict = NULL; 169 break; 170 } 171 } 172 if (dict && dict->RemoveWithoutPathExpansion(path[j], NULL)) { 173 dict->SetWithoutPathExpansion( 174 path[j], base::Value::CreateStringValue(kPlaceholder)); 175 } 176 } 177} 178 179PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler() 180 : ExtensionListPolicyHandler(key::kPinnedLauncherApps, 181 prefs::kPinnedLauncherApps, 182 false) {} 183 184PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {} 185 186void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings( 187 const PolicyMap& policies, 188 PrefValueMap* prefs) { 189 PolicyErrorMap errors; 190 const base::Value* policy_value = policies.GetValue(policy_name()); 191 const base::ListValue* policy_list = NULL; 192 if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) { 193 base::ListValue* pinned_apps_list = new base::ListValue(); 194 for (base::ListValue::const_iterator entry(policy_list->begin()); 195 entry != policy_list->end(); ++entry) { 196 std::string id; 197 if ((*entry)->GetAsString(&id)) { 198 base::DictionaryValue* app_dict = new base::DictionaryValue(); 199 app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id); 200 pinned_apps_list->Append(app_dict); 201 } 202 } 203 prefs->SetValue(pref_path(), pinned_apps_list); 204 } 205} 206 207} // namespace policy 208