configuration_policy_handler_chromeos.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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/sha1.h"
18#include "base/strings/string_number_conversions.h"
19#include "base/strings/string_util.h"
20#include "base/values.h"
21#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h"
22#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
23#include "chrome/common/pref_names.h"
24#include "chromeos/dbus/power_policy_controller.h"
25#include "chromeos/network/onc/onc_signature.h"
26#include "chromeos/network/onc/onc_utils.h"
27#include "chromeos/network/onc/onc_validator.h"
28#include "components/onc/onc_constants.h"
29#include "components/policy/core/browser/policy_error_map.h"
30#include "components/policy/core/common/external_data_fetcher.h"
31#include "components/policy/core/common/policy_map.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, 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 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() != base::kSHA1Length) {
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_DO_NOT_ESCAPE |
250                                         base::JSONWriter::OPTIONS_PRETTY_PRINT,
251                                     &json_string);
252  return base::Value::CreateStringValue(json_string);
253}
254
255PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler()
256    : ExtensionListPolicyHandler(key::kPinnedLauncherApps,
257                                 prefs::kPinnedLauncherApps,
258                                 false) {}
259
260PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {}
261
262void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings(
263    const PolicyMap& policies,
264    PrefValueMap* prefs) {
265  PolicyErrorMap errors;
266  const base::Value* policy_value = policies.GetValue(policy_name());
267  const base::ListValue* policy_list = NULL;
268  if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) {
269    base::ListValue* pinned_apps_list = new base::ListValue();
270    for (base::ListValue::const_iterator entry(policy_list->begin());
271         entry != policy_list->end(); ++entry) {
272      std::string id;
273      if ((*entry)->GetAsString(&id)) {
274        base::DictionaryValue* app_dict = new base::DictionaryValue();
275        app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id);
276        pinned_apps_list->Append(app_dict);
277      }
278    }
279    prefs->SetValue(pref_path(), pinned_apps_list);
280  }
281}
282
283ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler()
284    : IntRangePolicyHandlerBase(key::kScreenMagnifierType,
285                                0, ash::MAGNIFIER_FULL, false) {
286}
287
288ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() {
289}
290
291void ScreenMagnifierPolicyHandler::ApplyPolicySettings(
292    const PolicyMap& policies,
293    PrefValueMap* prefs) {
294  const base::Value* value = policies.GetValue(policy_name());
295  int value_in_range;
296  if (value && EnsureInRange(value, &value_in_range, NULL)) {
297    prefs->SetValue(prefs::kScreenMagnifierEnabled,
298                    base::Value::CreateBooleanValue(value_in_range != 0));
299    prefs->SetValue(prefs::kScreenMagnifierType,
300                    base::Value::CreateIntegerValue(value_in_range));
301  }
302}
303
304LoginScreenPowerManagementPolicyHandler::
305    LoginScreenPowerManagementPolicyHandler()
306    : TypeCheckingPolicyHandler(key::kDeviceLoginScreenPowerManagement,
307                                base::Value::TYPE_STRING) {
308}
309
310LoginScreenPowerManagementPolicyHandler::
311    ~LoginScreenPowerManagementPolicyHandler() {
312}
313
314bool LoginScreenPowerManagementPolicyHandler::CheckPolicySettings(
315    const PolicyMap& policies,
316    PolicyErrorMap* errors) {
317  const base::Value* value;
318  if (!CheckAndGetValue(policies, errors, &value))
319    return false;
320
321  if (!value)
322    return true;
323
324  std::string json;
325  value->GetAsString(&json);
326  return LoginScreenPowerManagementPolicy().Init(json, errors);
327}
328
329void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings(
330    const PolicyMap& policies,
331    PrefValueMap* prefs) {
332}
333
334DeprecatedIdleActionHandler::DeprecatedIdleActionHandler()
335    : IntRangePolicyHandlerBase(
336          key::kIdleAction,
337          chromeos::PowerPolicyController::ACTION_SUSPEND,
338          chromeos::PowerPolicyController::ACTION_DO_NOTHING,
339          false) {}
340
341DeprecatedIdleActionHandler::~DeprecatedIdleActionHandler() {}
342
343void DeprecatedIdleActionHandler::ApplyPolicySettings(const PolicyMap& policies,
344                                                      PrefValueMap* prefs) {
345  const base::Value* value = policies.GetValue(policy_name());
346  if (value && EnsureInRange(value, NULL, NULL)) {
347    if (!prefs->GetValue(prefs::kPowerAcIdleAction, NULL))
348      prefs->SetValue(prefs::kPowerAcIdleAction, value->DeepCopy());
349    if (!prefs->GetValue(prefs::kPowerBatteryIdleAction, NULL))
350      prefs->SetValue(prefs::kPowerBatteryIdleAction, value->DeepCopy());
351  }
352}
353
354}  // namespace policy
355