Home | History | Annotate | Download | only in policy
      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/ui/ash/chrome_launcher_prefs.h"
     21 #include "chrome/common/pref_names.h"
     22 #include "chromeos/dbus/power_policy_controller.h"
     23 #include "chromeos/network/onc/onc_signature.h"
     24 #include "chromeos/network/onc/onc_utils.h"
     25 #include "chromeos/network/onc/onc_validator.h"
     26 #include "components/onc/onc_constants.h"
     27 #include "components/policy/core/browser/policy_error_map.h"
     28 #include "components/policy/core/common/external_data_fetcher.h"
     29 #include "components/policy/core/common/policy_map.h"
     30 #include "components/policy/core/common/schema.h"
     31 #include "crypto/sha2.h"
     32 #include "grit/components_strings.h"
     33 #include "policy/policy_constants.h"
     34 #include "url/gurl.h"
     35 
     36 namespace policy {
     37 
     38 namespace {
     39 
     40 const char kSubkeyURL[] = "url";
     41 const char kSubkeyHash[] = "hash";
     42 
     43 bool 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 const char kScreenDimDelayAC[] = "AC.Delays.ScreenDim";
     67 const char kScreenOffDelayAC[] = "AC.Delays.ScreenOff";
     68 const char kIdleWarningDelayAC[] = "AC.Delays.IdleWarning";
     69 const char kIdleDelayAC[] = "AC.Delays.Idle";
     70 const char kIdleActionAC[] = "AC.IdleAction";
     71 
     72 const char kScreenDimDelayBattery[] = "Battery.Delays.ScreenDim";
     73 const char kScreenOffDelayBattery[] = "Battery.Delays.ScreenOff";
     74 const char kIdleWarningDelayBattery[] = "Battery.Delays.IdleWarning";
     75 const char kIdleDelayBattery[] = "Battery.Delays.Idle";
     76 const char kIdleActionBattery[] = "Battery.IdleAction";
     77 
     78 const char kScreenLockDelayAC[] = "AC";
     79 const char kScreenLockDelayBattery[] = "Battery";
     80 
     81 const char kActionSuspend[] = "Suspend";
     82 const char kActionLogout[] = "Logout";
     83 const char kActionShutdown[]  = "Shutdown";
     84 const char kActionDoNothing[] = "DoNothing";
     85 
     86 scoped_ptr<base::Value> GetValue(const base::DictionaryValue* dict,
     87                                  const char* key) {
     88   const base::Value* value = NULL;
     89   if (!dict->Get(key, &value))
     90     return scoped_ptr<base::Value>();
     91   return scoped_ptr<base::Value>(value->DeepCopy());
     92 }
     93 
     94 scoped_ptr<base::Value> GetAction(const base::DictionaryValue* dict,
     95                                   const char* key) {
     96   scoped_ptr<base::Value> value = GetValue(dict, key);
     97   std::string action;
     98   if (!value || !value->GetAsString(&action))
     99     return scoped_ptr<base::Value>();
    100   if (action == kActionSuspend) {
    101     return scoped_ptr<base::Value>(new base::FundamentalValue(
    102         chromeos::PowerPolicyController::ACTION_SUSPEND));
    103   }
    104   if (action == kActionLogout) {
    105     return scoped_ptr<base::Value>(new base::FundamentalValue(
    106         chromeos::PowerPolicyController::ACTION_STOP_SESSION));
    107   }
    108   if (action == kActionShutdown) {
    109     return scoped_ptr<base::Value>(new base::FundamentalValue(
    110         chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
    111   }
    112   if (action == kActionDoNothing) {
    113     return scoped_ptr<base::Value>(new base::FundamentalValue(
    114         chromeos::PowerPolicyController::ACTION_DO_NOTHING));
    115   }
    116   return scoped_ptr<base::Value>();
    117 }
    118 
    119 }  // namespace
    120 
    121 ExternalDataPolicyHandler::ExternalDataPolicyHandler(const char* policy_name)
    122     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_DICTIONARY) {
    123 }
    124 
    125 ExternalDataPolicyHandler::~ExternalDataPolicyHandler() {
    126 }
    127 
    128 bool ExternalDataPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
    129                                                     PolicyErrorMap* errors) {
    130   if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors))
    131     return false;
    132 
    133   const std::string policy = policy_name();
    134   const base::Value* value = policies.GetValue(policy);
    135   if (!value)
    136     return true;
    137 
    138   const base::DictionaryValue* dict = NULL;
    139   value->GetAsDictionary(&dict);
    140   if (!dict) {
    141     NOTREACHED();
    142     return false;
    143   }
    144   std::string url_string;
    145   std::string hash_string;
    146   if (!GetSubkeyString(*dict, errors, policy, kSubkeyURL, &url_string) ||
    147       !GetSubkeyString(*dict, errors, policy, kSubkeyHash, &hash_string)) {
    148     return false;
    149   }
    150 
    151   const GURL url(url_string);
    152   if (!url.is_valid()) {
    153     errors->AddError(policy, kSubkeyURL, IDS_POLICY_VALUE_FORMAT_ERROR);
    154     return false;
    155   }
    156 
    157   std::vector<uint8> hash;
    158   if (!base::HexStringToBytes(hash_string, &hash) ||
    159       hash.size() != crypto::kSHA256Length) {
    160     errors->AddError(policy, kSubkeyHash, IDS_POLICY_VALUE_FORMAT_ERROR);
    161     return false;
    162   }
    163 
    164   return true;
    165 }
    166 
    167 void ExternalDataPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
    168                                                     PrefValueMap* prefs) {
    169 }
    170 
    171 // static
    172 NetworkConfigurationPolicyHandler*
    173 NetworkConfigurationPolicyHandler::CreateForUserPolicy() {
    174   return new NetworkConfigurationPolicyHandler(
    175       key::kOpenNetworkConfiguration,
    176       onc::ONC_SOURCE_USER_POLICY,
    177       prefs::kOpenNetworkConfiguration);
    178 }
    179 
    180 // static
    181 NetworkConfigurationPolicyHandler*
    182 NetworkConfigurationPolicyHandler::CreateForDevicePolicy() {
    183   return new NetworkConfigurationPolicyHandler(
    184       key::kDeviceOpenNetworkConfiguration,
    185       onc::ONC_SOURCE_DEVICE_POLICY,
    186       prefs::kDeviceOpenNetworkConfiguration);
    187 }
    188 
    189 NetworkConfigurationPolicyHandler::~NetworkConfigurationPolicyHandler() {}
    190 
    191 bool NetworkConfigurationPolicyHandler::CheckPolicySettings(
    192     const PolicyMap& policies,
    193     PolicyErrorMap* errors) {
    194   const base::Value* value;
    195   if (!CheckAndGetValue(policies, errors, &value))
    196     return false;
    197 
    198   if (value) {
    199     std::string onc_blob;
    200     value->GetAsString(&onc_blob);
    201     scoped_ptr<base::DictionaryValue> root_dict =
    202         chromeos::onc::ReadDictionaryFromJson(onc_blob);
    203     if (root_dict.get() == NULL) {
    204       errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_PARSE_FAILED);
    205       return false;
    206     }
    207 
    208     // Validate the ONC dictionary. We are liberal and ignore unknown field
    209     // names and ignore invalid field names in kRecommended arrays.
    210     chromeos::onc::Validator validator(
    211         false,  // Ignore unknown fields.
    212         false,  // Ignore invalid recommended field names.
    213         true,   // Fail on missing fields.
    214         true);  // Validate for managed ONC
    215     validator.SetOncSource(onc_source_);
    216 
    217     // ONC policies are always unencrypted.
    218     chromeos::onc::Validator::Result validation_result;
    219     root_dict = validator.ValidateAndRepairObject(
    220         &chromeos::onc::kToplevelConfigurationSignature, *root_dict,
    221         &validation_result);
    222     if (validation_result == chromeos::onc::Validator::VALID_WITH_WARNINGS)
    223       errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_PARTIAL);
    224     else if (validation_result == chromeos::onc::Validator::INVALID)
    225       errors->AddError(policy_name(), IDS_POLICY_NETWORK_CONFIG_IMPORT_FAILED);
    226 
    227     // In any case, don't reject the policy as some networks or certificates
    228     // could still be applied.
    229   }
    230 
    231   return true;
    232 }
    233 
    234 void NetworkConfigurationPolicyHandler::ApplyPolicySettings(
    235     const PolicyMap& policies,
    236     PrefValueMap* prefs) {
    237   const base::Value* value = policies.GetValue(policy_name());
    238   if (!value)
    239     return;
    240 
    241   std::string onc_blob;
    242   value->GetAsString(&onc_blob);
    243 
    244   scoped_ptr<base::ListValue> network_configs(new base::ListValue);
    245   base::ListValue certificates;
    246   base::DictionaryValue global_network_config;
    247   chromeos::onc::ParseAndValidateOncForImport(onc_blob,
    248                                               onc_source_,
    249                                               "",
    250                                               network_configs.get(),
    251                                               &global_network_config,
    252                                               &certificates);
    253 
    254   // Currently, only the per-network configuration is stored in a pref. Ignore
    255   // |global_network_config| and |certificates|.
    256   prefs->SetValue(pref_path_, network_configs.release());
    257 }
    258 
    259 void NetworkConfigurationPolicyHandler::PrepareForDisplaying(
    260     PolicyMap* policies) const {
    261   const PolicyMap::Entry* entry = policies->Get(policy_name());
    262   if (!entry)
    263     return;
    264   base::Value* sanitized_config = SanitizeNetworkConfig(entry->value);
    265   if (!sanitized_config)
    266     sanitized_config = base::Value::CreateNullValue();
    267 
    268   policies->Set(policy_name(), entry->level, entry->scope,
    269                 sanitized_config, NULL);
    270 }
    271 
    272 NetworkConfigurationPolicyHandler::NetworkConfigurationPolicyHandler(
    273     const char* policy_name,
    274     onc::ONCSource onc_source,
    275     const char* pref_path)
    276     : TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_STRING),
    277       onc_source_(onc_source),
    278       pref_path_(pref_path) {
    279 }
    280 
    281 // static
    282 base::Value* NetworkConfigurationPolicyHandler::SanitizeNetworkConfig(
    283     const base::Value* config) {
    284   std::string json_string;
    285   if (!config->GetAsString(&json_string))
    286     return NULL;
    287 
    288   scoped_ptr<base::DictionaryValue> toplevel_dict =
    289       chromeos::onc::ReadDictionaryFromJson(json_string);
    290   if (!toplevel_dict)
    291     return NULL;
    292 
    293   // Placeholder to insert in place of the filtered setting.
    294   const char kPlaceholder[] = "********";
    295 
    296   toplevel_dict = chromeos::onc::MaskCredentialsInOncObject(
    297       chromeos::onc::kToplevelConfigurationSignature,
    298       *toplevel_dict,
    299       kPlaceholder);
    300 
    301   base::JSONWriter::WriteWithOptions(toplevel_dict.get(),
    302                                      base::JSONWriter::OPTIONS_PRETTY_PRINT,
    303                                      &json_string);
    304   return new base::StringValue(json_string);
    305 }
    306 
    307 PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler()
    308     : ExtensionListPolicyHandler(key::kPinnedLauncherApps,
    309                                  prefs::kPinnedLauncherApps,
    310                                  false) {}
    311 
    312 PinnedLauncherAppsPolicyHandler::~PinnedLauncherAppsPolicyHandler() {}
    313 
    314 void PinnedLauncherAppsPolicyHandler::ApplyPolicySettings(
    315     const PolicyMap& policies,
    316     PrefValueMap* prefs) {
    317   PolicyErrorMap errors;
    318   const base::Value* policy_value = policies.GetValue(policy_name());
    319   const base::ListValue* policy_list = NULL;
    320   if (policy_value && policy_value->GetAsList(&policy_list) && policy_list) {
    321     base::ListValue* pinned_apps_list = new base::ListValue();
    322     for (base::ListValue::const_iterator entry(policy_list->begin());
    323          entry != policy_list->end(); ++entry) {
    324       std::string id;
    325       if ((*entry)->GetAsString(&id)) {
    326         base::DictionaryValue* app_dict = new base::DictionaryValue();
    327         app_dict->SetString(ash::kPinnedAppsPrefAppIDPath, id);
    328         pinned_apps_list->Append(app_dict);
    329       }
    330     }
    331     prefs->SetValue(pref_path(), pinned_apps_list);
    332   }
    333 }
    334 
    335 ScreenMagnifierPolicyHandler::ScreenMagnifierPolicyHandler()
    336     : IntRangePolicyHandlerBase(key::kScreenMagnifierType,
    337                                 0, ash::MAGNIFIER_FULL, false) {
    338 }
    339 
    340 ScreenMagnifierPolicyHandler::~ScreenMagnifierPolicyHandler() {
    341 }
    342 
    343 void ScreenMagnifierPolicyHandler::ApplyPolicySettings(
    344     const PolicyMap& policies,
    345     PrefValueMap* prefs) {
    346   const base::Value* value = policies.GetValue(policy_name());
    347   int value_in_range;
    348   if (value && EnsureInRange(value, &value_in_range, NULL)) {
    349     prefs->SetValue(prefs::kAccessibilityScreenMagnifierEnabled,
    350                     new base::FundamentalValue(value_in_range != 0));
    351     prefs->SetValue(prefs::kAccessibilityScreenMagnifierType,
    352                     new base::FundamentalValue(value_in_range));
    353   }
    354 }
    355 
    356 LoginScreenPowerManagementPolicyHandler::
    357     LoginScreenPowerManagementPolicyHandler(const Schema& chrome_schema)
    358     : SchemaValidatingPolicyHandler(key::kDeviceLoginScreenPowerManagement,
    359                                     chrome_schema.GetKnownProperty(
    360                                         key::kDeviceLoginScreenPowerManagement),
    361                                     SCHEMA_ALLOW_UNKNOWN) {
    362 }
    363 
    364 LoginScreenPowerManagementPolicyHandler::
    365     ~LoginScreenPowerManagementPolicyHandler() {
    366 }
    367 
    368 void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings(
    369     const PolicyMap& policies,
    370     PrefValueMap* prefs) {
    371 }
    372 
    373 DeprecatedIdleActionHandler::DeprecatedIdleActionHandler()
    374     : IntRangePolicyHandlerBase(
    375           key::kIdleAction,
    376           chromeos::PowerPolicyController::ACTION_SUSPEND,
    377           chromeos::PowerPolicyController::ACTION_DO_NOTHING,
    378           false) {}
    379 
    380 DeprecatedIdleActionHandler::~DeprecatedIdleActionHandler() {}
    381 
    382 void DeprecatedIdleActionHandler::ApplyPolicySettings(const PolicyMap& policies,
    383                                                       PrefValueMap* prefs) {
    384   const base::Value* value = policies.GetValue(policy_name());
    385   if (value && EnsureInRange(value, NULL, NULL)) {
    386     if (!prefs->GetValue(prefs::kPowerAcIdleAction, NULL))
    387       prefs->SetValue(prefs::kPowerAcIdleAction, value->DeepCopy());
    388     if (!prefs->GetValue(prefs::kPowerBatteryIdleAction, NULL))
    389       prefs->SetValue(prefs::kPowerBatteryIdleAction, value->DeepCopy());
    390   }
    391 }
    392 
    393 PowerManagementIdleSettingsPolicyHandler::
    394     PowerManagementIdleSettingsPolicyHandler(const Schema& chrome_schema)
    395     : SchemaValidatingPolicyHandler(
    396           key::kPowerManagementIdleSettings,
    397           chrome_schema.GetKnownProperty(key::kPowerManagementIdleSettings),
    398           SCHEMA_ALLOW_UNKNOWN) {
    399 }
    400 
    401 PowerManagementIdleSettingsPolicyHandler::
    402     ~PowerManagementIdleSettingsPolicyHandler() {
    403 }
    404 
    405 void PowerManagementIdleSettingsPolicyHandler::ApplyPolicySettings(
    406     const PolicyMap& policies,
    407     PrefValueMap* prefs) {
    408   scoped_ptr<base::Value> policy_value;
    409   if (!CheckAndGetValue(policies, NULL, &policy_value))
    410     return;
    411   const base::DictionaryValue* dict = NULL;
    412   if (!policy_value->GetAsDictionary(&dict)) {
    413     NOTREACHED();
    414     return;
    415   }
    416   scoped_ptr<base::Value> value;
    417 
    418   value = GetValue(dict, kScreenDimDelayAC);
    419   if (value)
    420     prefs->SetValue(prefs::kPowerAcScreenDimDelayMs, value.release());
    421   value = GetValue(dict, kScreenOffDelayAC);
    422   if (value)
    423     prefs->SetValue(prefs::kPowerAcScreenOffDelayMs, value.release());
    424   value = GetValue(dict, kIdleWarningDelayAC);
    425   if (value)
    426     prefs->SetValue(prefs::kPowerAcIdleWarningDelayMs, value.release());
    427   value = GetValue(dict, kIdleDelayAC);
    428   if (value)
    429     prefs->SetValue(prefs::kPowerAcIdleDelayMs, value.release());
    430   value = GetAction(dict, kIdleActionAC);
    431   if (value)
    432     prefs->SetValue(prefs::kPowerAcIdleAction, value.release());
    433 
    434   value = GetValue(dict, kScreenDimDelayBattery);
    435   if (value)
    436     prefs->SetValue(prefs::kPowerBatteryScreenDimDelayMs, value.release());
    437   value = GetValue(dict, kScreenOffDelayBattery);
    438   if (value)
    439     prefs->SetValue(prefs::kPowerBatteryScreenOffDelayMs, value.release());
    440   value = GetValue(dict, kIdleWarningDelayBattery);
    441   if (value)
    442     prefs->SetValue(prefs::kPowerBatteryIdleWarningDelayMs, value.release());
    443   value = GetValue(dict, kIdleDelayBattery);
    444   if (value)
    445     prefs->SetValue(prefs::kPowerBatteryIdleDelayMs, value.release());
    446   value = GetAction(dict, kIdleActionBattery);
    447   if (value)
    448     prefs->SetValue(prefs::kPowerBatteryIdleAction, value.release());
    449 }
    450 
    451 ScreenLockDelayPolicyHandler::ScreenLockDelayPolicyHandler(
    452     const Schema& chrome_schema)
    453     : SchemaValidatingPolicyHandler(
    454           key::kScreenLockDelays,
    455           chrome_schema.GetKnownProperty(key::kScreenLockDelays),
    456           SCHEMA_ALLOW_UNKNOWN) {
    457 }
    458 
    459 ScreenLockDelayPolicyHandler::~ScreenLockDelayPolicyHandler() {
    460 }
    461 
    462 void ScreenLockDelayPolicyHandler::ApplyPolicySettings(
    463     const PolicyMap& policies,
    464     PrefValueMap* prefs) {
    465   scoped_ptr<base::Value> policy_value;
    466   if (!CheckAndGetValue(policies, NULL, &policy_value))
    467     return;
    468   const base::DictionaryValue* dict = NULL;
    469   if (!policy_value->GetAsDictionary(&dict)) {
    470     NOTREACHED();
    471     return;
    472   }
    473   scoped_ptr<base::Value> value;
    474 
    475   value = GetValue(dict, kScreenLockDelayAC);
    476   if (value)
    477     prefs->SetValue(prefs::kPowerAcScreenLockDelayMs, value.release());
    478   value = GetValue(dict, kScreenLockDelayBattery);
    479   if (value)
    480     prefs->SetValue(prefs::kPowerBatteryScreenLockDelayMs, value.release());
    481 }
    482 
    483 }  // namespace policy
    484