Chromium Code Reviews| Index: chromeos/network/policy_util.cc |
| diff --git a/chromeos/network/policy_util.cc b/chromeos/network/policy_util.cc |
| index 55fb320b5b7df6c77ab1c6a2d9185f0990f97f1c..e9afaddecb942270cf7fb8473261bf3e8fa6f2ea 100644 |
| --- a/chromeos/network/policy_util.cc |
| +++ b/chromeos/network/policy_util.cc |
| @@ -125,35 +125,179 @@ bool IsPolicyMatching(const base::DictionaryValue& policy, |
| return false; |
| } |
| +base::DictionaryValue* GetOrCreateDictionary(const std::string& key, |
| + base::DictionaryValue* dict) { |
| + base::DictionaryValue* inner_dict = NULL; |
| + if (!dict->GetDictionaryWithoutPathExpansion(key, &inner_dict)) { |
| + inner_dict = new base::DictionaryValue; |
| + dict->SetWithoutPathExpansion(key, inner_dict); |
| + } |
| + return inner_dict; |
| +} |
| + |
| +base::DictionaryValue* GetOrCreateNestedDictionary( |
| + const std::string& key1, |
| + const std::string& key2, |
| + base::DictionaryValue* dict) { |
| + base::DictionaryValue* inner_dict = GetOrCreateDictionary(key1, dict); |
| + return GetOrCreateDictionary(key2, inner_dict); |
| +} |
| + |
| +void ApplyGlobalAutoconnectPolicy( |
|
pneubeck (no reviews)
2014/08/28 16:09:49
this is approximately the function that you propos
stevenjb
2014/08/28 16:19:41
Acknowledged.
|
| + NetworkProfile::Type profile_type, |
| + base::DictionaryValue* augmented_onc_network) { |
| + std::string type; |
| + if (!augmented_onc_network->GetStringWithoutPathExpansion( |
| + ::onc::network_config::kType, &type)) { |
| + LOG(ERROR) << "ONC dictionary with no Type."; |
| + return; |
| + } |
| + |
| + // Managed dictionaries don't contain empty dictionaries (see onc_merger.cc), |
| + // so add the Autoconnect dictionary in case Shill didn't report a value. |
| + base::DictionaryValue* auto_connect_dictionary = NULL; |
| + if (type == ::onc::network_type::kWiFi) { |
| + auto_connect_dictionary = |
| + GetOrCreateNestedDictionary(::onc::network_config::kWiFi, |
| + ::onc::wifi::kAutoConnect, |
| + augmented_onc_network); |
| + } else if (type == ::onc::network_type::kVPN) { |
| + auto_connect_dictionary = |
| + GetOrCreateNestedDictionary(::onc::network_config::kVPN, |
| + ::onc::vpn::kAutoConnect, |
| + augmented_onc_network); |
| + } else { |
| + return; // Network type without auto-connect property. |
| + } |
| + |
| + std::string policy_source; |
| + if (profile_type == NetworkProfile::TYPE_USER) |
| + policy_source = ::onc::kAugmentationUserPolicy; |
| + else if(profile_type == NetworkProfile::TYPE_SHARED) |
| + policy_source = ::onc::kAugmentationDevicePolicy; |
| + else |
| + NOTREACHED(); |
| + |
| + auto_connect_dictionary->SetBooleanWithoutPathExpansion(policy_source, false); |
| + auto_connect_dictionary->SetStringWithoutPathExpansion( |
| + ::onc::kAugmentationEffectiveSetting, policy_source); |
| +} |
| + |
| } // namespace |
| +scoped_ptr<base::DictionaryValue> CreateManagedONC( |
| + const base::DictionaryValue* global_policy, |
| + const base::DictionaryValue* network_policy, |
| + const base::DictionaryValue* user_settings, |
| + const base::DictionaryValue* active_settings, |
| + const NetworkProfile* profile) { |
| + const base::DictionaryValue* user_policy = NULL; |
| + const base::DictionaryValue* device_policy = NULL; |
| + const base::DictionaryValue* nonshared_user_settings = NULL; |
| + const base::DictionaryValue* shared_user_settings = NULL; |
| + |
| + if (profile) { |
| + if (profile->type() == NetworkProfile::TYPE_SHARED) { |
| + device_policy = network_policy; |
| + shared_user_settings = user_settings; |
| + } else if (profile->type() == NetworkProfile::TYPE_USER) { |
| + user_policy = network_policy; |
| + nonshared_user_settings = user_settings; |
| + } else { |
| + NOTREACHED(); |
| + } |
| + } |
| + |
| + // This call also removes credentials from policies. |
| + scoped_ptr<base::DictionaryValue> augmented_onc_network = |
| + onc::MergeSettingsAndPoliciesToAugmented( |
| + onc::kNetworkConfigurationSignature, |
| + user_policy, |
| + device_policy, |
| + nonshared_user_settings, |
| + shared_user_settings, |
| + active_settings); |
| + |
| + // If present, apply the Autoconnect policy only to networks that are not |
| + // managed by policy. |
| + if (!network_policy && global_policy && profile) { |
| + bool allow_only_policy_autoconnect = false; |
| + global_policy->GetBooleanWithoutPathExpansion( |
| + ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, |
| + &allow_only_policy_autoconnect); |
| + if (allow_only_policy_autoconnect) { |
| + ApplyGlobalAutoconnectPolicy(profile->type(), |
| + augmented_onc_network.get()); |
| + } |
| + } |
| + |
| + return augmented_onc_network.Pass(); |
| +} |
| + |
| +void SetShillPropertiesForGlobalPolicy( |
| + const base::DictionaryValue& shill_dictionary, |
| + const base::DictionaryValue* global_network_policy, |
| + base::DictionaryValue* shill_properties_to_update) { |
| + if (!global_network_policy) |
| + return; |
| + |
| + // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. |
| + |
| + std::string type; |
| + shill_dictionary.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); |
| + if (NetworkTypePattern::Ethernet().MatchesType(type)) |
| + return; // Autoconnect for Ethernet cannot be configured. |
| + |
| + // By default all networks are allowed to autoconnect. |
| + bool only_policy_autoconnect = false; |
| + global_network_policy->GetBooleanWithoutPathExpansion( |
| + ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, |
| + &only_policy_autoconnect); |
| + if (!only_policy_autoconnect) |
| + return; |
| + |
| + bool old_autoconnect = false; |
| + if (shill_dictionary.GetBooleanWithoutPathExpansion( |
| + shill::kAutoConnectProperty, &old_autoconnect) && |
| + !old_autoconnect) { |
| + // Autoconnect is already explictly disabled. No need to set it again. |
| + return; |
| + } |
| + |
| + // If autconnect is not explicitly set yet, it might automatically be enabled |
| + // by Shill. To prevent that, disable it explicitly. |
| + shill_properties_to_update->SetBooleanWithoutPathExpansion( |
| + shill::kAutoConnectProperty, false); |
| +} |
| + |
| scoped_ptr<base::DictionaryValue> CreateShillConfiguration( |
| const NetworkProfile& profile, |
| const std::string& guid, |
| - const base::DictionaryValue* policy, |
| - const base::DictionaryValue* settings) { |
| + const base::DictionaryValue* global_policy, |
| + const base::DictionaryValue* network_policy, |
| + const base::DictionaryValue* user_settings) { |
| scoped_ptr<base::DictionaryValue> effective; |
| ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE; |
| - if (policy) { |
| + if (network_policy) { |
| if (profile.type() == NetworkProfile::TYPE_SHARED) { |
| effective = onc::MergeSettingsAndPoliciesToEffective( |
| NULL, // no user policy |
| - policy, // device policy |
| + network_policy, // device policy |
| NULL, // no user settings |
| - settings); // shared settings |
| + user_settings); // shared settings |
| onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; |
| } else if (profile.type() == NetworkProfile::TYPE_USER) { |
| effective = onc::MergeSettingsAndPoliciesToEffective( |
| - policy, // user policy |
| + network_policy, // user policy |
| NULL, // no device policy |
| - settings, // user settings |
| + user_settings, // user settings |
| NULL); // no shared settings |
| onc_source = ::onc::ONC_SOURCE_USER_POLICY; |
| } else { |
| NOTREACHED(); |
| } |
| - } else if (settings) { |
| - effective.reset(settings->DeepCopy()); |
| + } else if (user_settings) { |
| + effective.reset(user_settings->DeepCopy()); |
| // TODO(pneubeck): change to source ONC_SOURCE_USER |
| onc_source = ::onc::ONC_SOURCE_NONE; |
| } else { |
| @@ -178,9 +322,15 @@ scoped_ptr<base::DictionaryValue> CreateShillConfiguration( |
| shill_dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty, |
| profile.path); |
| + if (!network_policy) { |
| + // The network isn't managed. Global network policies have to be applied. |
| + SetShillPropertiesForGlobalPolicy( |
| + *shill_dictionary, global_policy, shill_dictionary.get()); |
| + } |
| + |
| scoped_ptr<NetworkUIData> ui_data(NetworkUIData::CreateFromONC(onc_source)); |
| - if (settings) { |
| + if (user_settings) { |
| // Shill doesn't know that sensitive data is contained in the UIData |
| // property and might write it into logs or other insecure places. Thus, we |
| // have to remove or mask credentials. |
| @@ -188,11 +338,11 @@ scoped_ptr<base::DictionaryValue> CreateShillConfiguration( |
| // Shill's GetProperties doesn't return credentials. Masking credentials |
| // instead of just removing them, allows remembering if a credential is set |
| // or not. |
| - scoped_ptr<base::DictionaryValue> sanitized_settings( |
| + scoped_ptr<base::DictionaryValue> sanitized_user_settings( |
| onc::MaskCredentialsInOncObject(onc::kNetworkConfigurationSignature, |
| - *settings, |
| + *user_settings, |
| kFakeCredential)); |
| - ui_data->set_user_settings(sanitized_settings.Pass()); |
| + ui_data->set_user_settings(sanitized_user_settings.Pass()); |
| } |
| shill_property_util::SetUIData(*ui_data, shill_dictionary.get()); |