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