OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/network/policy_applicator.h" | 5 #include "chromeos/network/policy_applicator.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/values.h" | 14 #include "base/values.h" |
14 #include "chromeos/dbus/dbus_thread_manager.h" | 15 #include "chromeos/dbus/dbus_thread_manager.h" |
15 #include "chromeos/dbus/shill_profile_client.h" | 16 #include "chromeos/dbus/shill_profile_client.h" |
16 #include "chromeos/network/network_ui_data.h" | 17 #include "chromeos/network/network_ui_data.h" |
17 #include "chromeos/network/onc/onc_signature.h" | 18 #include "chromeos/network/onc/onc_signature.h" |
18 #include "chromeos/network/onc/onc_translator.h" | 19 #include "chromeos/network/onc/onc_translator.h" |
19 #include "chromeos/network/policy_util.h" | 20 #include "chromeos/network/policy_util.h" |
20 #include "chromeos/network/shill_property_util.h" | 21 #include "chromeos/network/shill_property_util.h" |
21 #include "components/onc/onc_constants.h" | 22 #include "components/onc/onc_constants.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 << " with new policy " << new_guid << "."; | 161 << " with new policy " << new_guid << "."; |
161 VLOG_IF(1, !was_managed) << "Applying policy " << new_guid | 162 VLOG_IF(1, !was_managed) << "Applying policy " << new_guid |
162 << " to previously unmanaged " | 163 << " to previously unmanaged " |
163 << "configuration."; | 164 << "configuration."; |
164 | 165 |
165 if (old_guid == new_guid && | 166 if (old_guid == new_guid && |
166 remaining_policies_.find(new_guid) == remaining_policies_.end()) { | 167 remaining_policies_.find(new_guid) == remaining_policies_.end()) { |
167 VLOG(1) << "Not updating existing managed configuration with guid " | 168 VLOG(1) << "Not updating existing managed configuration with guid " |
168 << new_guid << " because the policy didn't change."; | 169 << new_guid << " because the policy didn't change."; |
169 } else { | 170 } else { |
170 // Delete the entry to ensure that no old configuration remains. | 171 const base::DictionaryValue* user_settings = |
171 // Don't do this if a policy is reapplied (e.g. after reboot) or updated | 172 ui_data ? ui_data->user_settings() : NULL; |
172 // (i.e. the GUID didn't change), in order to keep implicit state of | 173 scoped_ptr<base::DictionaryValue> new_shill_properties = |
173 // Shill like "connected successfully before". | 174 policy_util::CreateShillConfiguration( |
174 if (old_guid == new_guid) { | 175 profile_, new_guid, new_policy, user_settings); |
| 176 // A new policy has to be applied to this profile entry. In order to keep |
| 177 // implicit state of Shill like "connected successfully before", keep the |
| 178 // entry if a policy is reapplied (e.g. after reboot) or is updated. |
| 179 // However, some Shill properties are used to identify the network and |
| 180 // cannot be modified after initial configuration, so we have to delete |
| 181 // the profile entry in these cases. Also, keeping Shill's state if the |
| 182 // SSID changed might not be a good idea anyways. If the policy GUID |
| 183 // changed, or there was no policy before, we delete the entry at first to |
| 184 // ensure that no old configuration remains. |
| 185 if (old_guid == new_guid && |
| 186 shill_property_util::DoIdentifyingPropertiesMatch( |
| 187 *new_shill_properties, entry_properties)) { |
175 VLOG(1) << "Updating previously managed configuration with the " | 188 VLOG(1) << "Updating previously managed configuration with the " |
176 << "updated policy " << new_guid << "."; | 189 << "updated policy " << new_guid << "."; |
177 } else { | 190 } else { |
| 191 VLOG(1) << "Deleting profile entry before writing new policy " |
| 192 << new_guid << " because of identifying properties changed."; |
178 DeleteEntry(entry); | 193 DeleteEntry(entry); |
179 } | 194 } |
180 | 195 |
181 const base::DictionaryValue* user_settings = | 196 WriteNewShillConfiguration(*new_shill_properties, *new_policy); |
182 ui_data ? ui_data->user_settings() : NULL; | |
183 | |
184 // Write the new configuration. | |
185 CreateAndWriteNewShillConfiguration(new_guid, *new_policy, user_settings); | |
186 remaining_policies_.erase(new_guid); | 197 remaining_policies_.erase(new_guid); |
187 } | 198 } |
188 } else if (was_managed) { | 199 } else if (was_managed) { |
189 VLOG(1) << "Removing configuration previously managed by policy " | 200 VLOG(1) << "Removing configuration previously managed by policy " |
190 << old_guid << ", because the policy was removed."; | 201 << old_guid << ", because the policy was removed."; |
191 | 202 |
192 // Remove the entry, because the network was managed but isn't anymore. | 203 // Remove the entry, because the network was managed but isn't anymore. |
193 // Note: An alternative might be to preserve the user settings, but it's | 204 // Note: An alternative might be to preserve the user settings, but it's |
194 // unclear which values originating the policy should be removed. | 205 // unclear which values originating the policy should be removed. |
195 DeleteEntry(entry); | 206 DeleteEntry(entry); |
196 } else { | 207 } else { |
197 // The entry wasn't managed and doesn't match any current policy. Global | 208 // The entry wasn't managed and doesn't match any current policy. Global |
198 // network settings have to be applied. | 209 // network settings have to be applied. |
199 | |
200 base::DictionaryValue shill_properties_to_update; | 210 base::DictionaryValue shill_properties_to_update; |
201 GetPropertiesForUnmanagedEntry(entry_properties, | 211 GetPropertiesForUnmanagedEntry(entry_properties, |
202 &shill_properties_to_update); | 212 &shill_properties_to_update); |
203 if (shill_properties_to_update.empty()) { | 213 if (shill_properties_to_update.empty()) { |
204 VLOG(2) << "Ignore unmanaged entry."; | 214 VLOG(2) << "Ignore unmanaged entry."; |
205 // Calling a SetProperties of Shill with an empty dictionary is a no op. | 215 // Calling a SetProperties of Shill with an empty dictionary is a no op. |
206 } else { | 216 } else { |
207 VLOG(2) << "Apply global network config to unmanaged entry."; | 217 VLOG(2) << "Apply global network config to unmanaged entry."; |
208 handler_->UpdateExistingConfigurationWithPropertiesFromPolicy( | 218 handler_->UpdateExistingConfigurationWithPropertiesFromPolicy( |
209 entry_properties, shill_properties_to_update); | 219 entry_properties, shill_properties_to_update); |
210 } | 220 } |
211 } | 221 } |
212 } | 222 } |
213 | 223 |
214 void PolicyApplicator::DeleteEntry(const std::string& entry) { | 224 void PolicyApplicator::DeleteEntry(const std::string& entry) { |
215 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( | 225 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( |
216 dbus::ObjectPath(profile_.path), | 226 dbus::ObjectPath(profile_.path), |
217 entry, | 227 entry, |
218 base::Bind(&base::DoNothing), | 228 base::Bind(&base::DoNothing), |
219 base::Bind(&LogErrorMessage, FROM_HERE)); | 229 base::Bind(&LogErrorMessage, FROM_HERE)); |
220 } | 230 } |
221 | 231 |
222 void PolicyApplicator::CreateAndWriteNewShillConfiguration( | 232 void PolicyApplicator::WriteNewShillConfiguration( |
223 const std::string& guid, | 233 const base::DictionaryValue& shill_dictionary, |
224 const base::DictionaryValue& policy, | 234 const base::DictionaryValue& policy) { |
225 const base::DictionaryValue* user_settings) { | |
226 // Ethernet (non EAP) settings, like GUID or UIData, cannot be stored per | 235 // Ethernet (non EAP) settings, like GUID or UIData, cannot be stored per |
227 // user. Abort in that case. | 236 // user. Abort in that case. |
228 std::string type; | 237 std::string type; |
229 policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type); | 238 policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type); |
230 if (type == ::onc::network_type::kEthernet && | 239 if (type == ::onc::network_type::kEthernet && |
231 profile_.type() == NetworkProfile::TYPE_USER) { | 240 profile_.type() == NetworkProfile::TYPE_USER) { |
232 const base::DictionaryValue* ethernet = NULL; | 241 const base::DictionaryValue* ethernet = NULL; |
233 policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet, | 242 policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet, |
234 ðernet); | 243 ðernet); |
235 std::string auth; | 244 std::string auth; |
236 ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, | 245 ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, |
237 &auth); | 246 &auth); |
238 if (auth == ::onc::ethernet::kNone) | 247 if (auth == ::onc::ethernet::kNone) |
239 return; | 248 return; |
240 } | 249 } |
241 | 250 |
242 scoped_ptr<base::DictionaryValue> shill_dictionary = | 251 handler_->CreateConfigurationFromPolicy(shill_dictionary); |
243 policy_util::CreateShillConfiguration( | |
244 profile_, guid, &policy, user_settings); | |
245 handler_->CreateConfigurationFromPolicy(*shill_dictionary); | |
246 } | 252 } |
247 | 253 |
248 void PolicyApplicator::GetPropertiesForUnmanagedEntry( | 254 void PolicyApplicator::GetPropertiesForUnmanagedEntry( |
249 const base::DictionaryValue& entry_properties, | 255 const base::DictionaryValue& entry_properties, |
250 base::DictionaryValue* properties_to_update) const { | 256 base::DictionaryValue* properties_to_update) const { |
251 // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. | 257 // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. |
252 | 258 |
253 std::string type; | 259 std::string type; |
254 entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); | 260 entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); |
255 if (NetworkTypePattern::Ethernet().MatchesType(type)) | 261 if (NetworkTypePattern::Ethernet().MatchesType(type)) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 // contains all modified policies that didn't match any entry. For these | 303 // contains all modified policies that didn't match any entry. For these |
298 // remaining policies, new configurations have to be created. | 304 // remaining policies, new configurations have to be created. |
299 for (std::set<std::string>::iterator it = remaining_policies_.begin(); | 305 for (std::set<std::string>::iterator it = remaining_policies_.begin(); |
300 it != remaining_policies_.end(); ++it) { | 306 it != remaining_policies_.end(); ++it) { |
301 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it); | 307 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it); |
302 DCHECK(policy); | 308 DCHECK(policy); |
303 | 309 |
304 VLOG(1) << "Creating new configuration managed by policy " << *it | 310 VLOG(1) << "Creating new configuration managed by policy " << *it |
305 << " in profile " << profile_.ToDebugString() << "."; | 311 << " in profile " << profile_.ToDebugString() << "."; |
306 | 312 |
307 CreateAndWriteNewShillConfiguration( | 313 scoped_ptr<base::DictionaryValue> shill_dictionary = |
308 *it, *policy, NULL /* no user settings */); | 314 policy_util::CreateShillConfiguration(profile_, *it, policy, NULL); |
| 315 WriteNewShillConfiguration(*shill_dictionary, *policy); |
309 } | 316 } |
310 } | 317 } |
311 | 318 |
312 } // namespace chromeos | 319 } // namespace chromeos |
OLD | NEW |