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