Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: chromeos/network/policy_applicator.cc

Issue 23522004: Separate PolicyApplicator from ManagedNetworkConfigurationHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix clang compilation. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos/network/policy_applicator.h ('k') | chromeos/network/policy_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/managed_network_configuration_handler_impl.h" 5 #include "chromeos/network/policy_applicator.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector>
9 8
10 #include "base/bind.h" 9 #include "base/bind.h"
11 #include "base/guid.h"
12 #include "base/location.h" 10 #include "base/location.h"
13 #include "base/logging.h" 11 #include "base/logging.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/stl_util.h" 12 #include "base/stl_util.h"
16 #include "base/strings/string_util.h"
17 #include "base/values.h" 13 #include "base/values.h"
18 #include "chromeos/dbus/dbus_method_call_status.h"
19 #include "chromeos/dbus/dbus_thread_manager.h" 14 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/shill_manager_client.h"
21 #include "chromeos/dbus/shill_profile_client.h" 15 #include "chromeos/dbus/shill_profile_client.h"
22 #include "chromeos/dbus/shill_service_client.h"
23 #include "chromeos/network/network_configuration_handler.h"
24 #include "chromeos/network/network_event_log.h"
25 #include "chromeos/network/network_policy_observer.h"
26 #include "chromeos/network/network_profile.h"
27 #include "chromeos/network/network_profile_handler.h"
28 #include "chromeos/network/network_state.h"
29 #include "chromeos/network/network_state_handler.h"
30 #include "chromeos/network/network_ui_data.h" 16 #include "chromeos/network/network_ui_data.h"
31 #include "chromeos/network/onc/onc_constants.h" 17 #include "chromeos/network/onc/onc_constants.h"
32 #include "chromeos/network/onc/onc_merger.h"
33 #include "chromeos/network/onc/onc_normalizer.h"
34 #include "chromeos/network/onc/onc_signature.h" 18 #include "chromeos/network/onc/onc_signature.h"
35 #include "chromeos/network/onc/onc_translator.h" 19 #include "chromeos/network/onc/onc_translator.h"
36 #include "chromeos/network/onc/onc_utils.h" 20 #include "chromeos/network/policy_util.h"
37 #include "chromeos/network/onc/onc_validator.h"
38 #include "chromeos/network/shill_property_util.h" 21 #include "chromeos/network/shill_property_util.h"
39 #include "dbus/object_path.h" 22 #include "dbus/object_path.h"
40 #include "third_party/cros_system_api/dbus/service_constants.h" 23 #include "third_party/cros_system_api/dbus/service_constants.h"
41 24
42 namespace chromeos { 25 namespace chromeos {
43 26
44 namespace { 27 namespace {
45 28
46 // These are error strings used for error callbacks. None of these error
47 // messages are user-facing: they should only appear in logs.
48 const char kInvalidUserSettingsMessage[] = "User settings are invalid.";
49 const char kInvalidUserSettings[] = "Error.InvalidUserSettings";
50 const char kNetworkAlreadyConfiguredMessage[] =
51 "Network is already configured.";
52 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured";
53 const char kPoliciesNotInitializedMessage[] = "Policies not initialized.";
54 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized";
55 const char kProfileNotInitializedMessage[] = "Profile not initialized.";
56 const char kProfileNotInitialized[] = "Error.ProflieNotInitialized";
57 const char kSetOnUnconfiguredNetworkMessage[] =
58 "Unable to modify properties of an unconfigured network.";
59 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork";
60 const char kUnknownProfilePathMessage[] = "Profile path is unknown.";
61 const char kUnknownProfilePath[] = "Error.UnknownProfilePath";
62 const char kUnknownServicePathMessage[] = "Service path is unknown.";
63 const char kUnknownServicePath[] = "Error.UnknownServicePath";
64
65 // This fake credential contains a random postfix which is extremly unlikely to
66 // be used by any user.
67 const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x";
68
69 std::string ToDebugString(onc::ONCSource source,
70 const std::string& userhash) {
71 return source == onc::ONC_SOURCE_USER_POLICY ?
72 ("user policy of " + userhash) : "device policy";
73 }
74
75 void RunErrorCallback(const std::string& service_path,
76 const std::string& error_name,
77 const std::string& error_message,
78 const network_handler::ErrorCallback& error_callback) {
79 NET_LOG_ERROR(error_name, error_message);
80 error_callback.Run(
81 error_name,
82 make_scoped_ptr(
83 network_handler::CreateErrorData(service_path,
84 error_name,
85 error_message)));
86 }
87
88 void LogErrorWithDict(const tracked_objects::Location& from_where,
89 const std::string& error_name,
90 scoped_ptr<base::DictionaryValue> error_data) {
91 LOG(ERROR) << from_where.ToString() << ": " << error_name;
92 }
93
94 void LogErrorMessage(const tracked_objects::Location& from_where, 29 void LogErrorMessage(const tracked_objects::Location& from_where,
95 const std::string& error_name, 30 const std::string& error_name,
96 const std::string& error_message) { 31 const std::string& error_message) {
97 LOG(ERROR) << from_where.ToString() << ": " << error_message; 32 LOG(ERROR) << from_where.ToString() << ": " << error_message;
98 } 33 }
99 34
100 // Removes all kFakeCredential values from sensitive fields (determined by
101 // onc::FieldIsCredential) of |onc_object|.
102 void RemoveFakeCredentials(
103 const onc::OncValueSignature& signature,
104 base::DictionaryValue* onc_object) {
105 base::DictionaryValue::Iterator it(*onc_object);
106 while (!it.IsAtEnd()) {
107 base::Value* value = NULL;
108 std::string field_name = it.key();
109 // We need the non-const entry to remove nested values but DictionaryValue
110 // has no non-const iterator.
111 onc_object->GetWithoutPathExpansion(field_name, &value);
112 // Advance before delete.
113 it.Advance();
114
115 // If |value| is a dictionary, recurse.
116 base::DictionaryValue* nested_object = NULL;
117 if (value->GetAsDictionary(&nested_object)) {
118 const onc::OncFieldSignature* field_signature =
119 onc::GetFieldSignature(signature, field_name);
120
121 RemoveFakeCredentials(*field_signature->value_signature,
122 nested_object);
123 continue;
124 }
125
126 // If |value| is a string, check if it is a fake credential.
127 std::string string_value;
128 if (value->GetAsString(&string_value) &&
129 onc::FieldIsCredential(signature, field_name)) {
130 if (string_value == kFakeCredential) {
131 // The value wasn't modified by the UI, thus we remove the field to keep
132 // the existing value that is stored in Shill.
133 onc_object->RemoveWithoutPathExpansion(field_name, NULL);
134 }
135 // Otherwise, the value is set and modified by the UI, thus we keep that
136 // value to overwrite whatever is stored in Shill.
137 }
138 }
139 }
140
141 // Creates a Shill property dictionary from the given arguments. The resulting
142 // dictionary will be sent to Shill by the caller. Depending on the profile
143 // type, |policy| is interpreted as the user or device policy and |settings| as
144 // the user or shared settings. |policy| or |settings| can be NULL, but not
145 // both.
146 scoped_ptr<base::DictionaryValue> CreateShillConfiguration(
147 const NetworkProfile& profile,
148 const std::string& guid,
149 const base::DictionaryValue* policy,
150 const base::DictionaryValue* settings) {
151 scoped_ptr<base::DictionaryValue> effective;
152 onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
153 if (policy) {
154 if (profile.type() == NetworkProfile::TYPE_SHARED) {
155 effective = onc::MergeSettingsAndPoliciesToEffective(
156 NULL, // no user policy
157 policy, // device policy
158 NULL, // no user settings
159 settings); // shared settings
160 onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
161 } else if (profile.type() == NetworkProfile::TYPE_USER) {
162 effective = onc::MergeSettingsAndPoliciesToEffective(
163 policy, // user policy
164 NULL, // no device policy
165 settings, // user settings
166 NULL); // no shared settings
167 onc_source = onc::ONC_SOURCE_USER_POLICY;
168 } else {
169 NOTREACHED();
170 }
171 } else if (settings) {
172 effective.reset(settings->DeepCopy());
173 // TODO(pneubeck): change to source ONC_SOURCE_USER
174 onc_source = onc::ONC_SOURCE_NONE;
175 } else {
176 NOTREACHED();
177 onc_source = onc::ONC_SOURCE_NONE;
178 }
179
180 RemoveFakeCredentials(onc::kNetworkConfigurationSignature,
181 effective.get());
182
183 effective->SetStringWithoutPathExpansion(onc::network_config::kGUID, guid);
184
185 // Remove irrelevant fields.
186 onc::Normalizer normalizer(true /* remove recommended fields */);
187 effective = normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature,
188 *effective);
189
190 scoped_ptr<base::DictionaryValue> shill_dictionary(
191 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature,
192 *effective));
193
194 shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
195 profile.path);
196
197 scoped_ptr<NetworkUIData> ui_data;
198 if (policy)
199 ui_data = NetworkUIData::CreateFromONC(onc_source, *policy);
200 else
201 ui_data.reset(new NetworkUIData());
202
203 if (settings) {
204 // Shill doesn't know that sensitive data is contained in the UIData
205 // property and might write it into logs or other insecure places. Thus, we
206 // have to remove or mask credentials.
207 //
208 // Shill's GetProperties doesn't return credentials. Masking credentials
209 // instead of just removing them, allows remembering if a credential is set
210 // or not.
211 scoped_ptr<base::DictionaryValue> sanitized_settings(
212 onc::MaskCredentialsInOncObject(onc::kNetworkConfigurationSignature,
213 *settings,
214 kFakeCredential));
215 ui_data->set_user_settings(sanitized_settings.Pass());
216 }
217
218 shill_property_util::SetUIData(*ui_data, shill_dictionary.get());
219
220 VLOG(2) << "Created Shill properties: " << *shill_dictionary;
221
222 return shill_dictionary.Pass();
223 }
224
225 // Returns true if |policy| matches |actual_network|, which must be part of a
226 // ONC NetworkConfiguration. This should be the only such matching function
227 // within Chrome. Shill does such matching in several functions for network
228 // identification. For compatibility, we currently should stick to Shill's
229 // matching behavior.
230 bool IsPolicyMatching(const base::DictionaryValue& policy,
231 const base::DictionaryValue& actual_network) {
232 std::string policy_type;
233 policy.GetStringWithoutPathExpansion(onc::network_config::kType,
234 &policy_type);
235 std::string network_type;
236 actual_network.GetStringWithoutPathExpansion(onc::network_config::kType,
237 &network_type);
238 if (policy_type != network_type)
239 return false;
240
241 if (network_type != onc::network_type::kWiFi)
242 return false;
243
244 const base::DictionaryValue* policy_wifi = NULL;
245 policy.GetDictionaryWithoutPathExpansion(onc::network_config::kWiFi,
246 &policy_wifi);
247 const base::DictionaryValue* actual_wifi = NULL;
248 actual_network.GetDictionaryWithoutPathExpansion(onc::network_config::kWiFi,
249 &actual_wifi);
250 if (!policy_wifi || !actual_wifi)
251 return false;
252
253 std::string policy_ssid;
254 policy_wifi->GetStringWithoutPathExpansion(onc::wifi::kSSID, &policy_ssid);
255 std::string actual_ssid;
256 actual_wifi->GetStringWithoutPathExpansion(onc::wifi::kSSID, &actual_ssid);
257 return (policy_ssid == actual_ssid);
258 }
259
260 // Returns the policy from |policies| matching |actual_network|, if any exists.
261 // Returns NULL otherwise. |actual_network| must be part of a ONC
262 // NetworkConfiguration.
263 const base::DictionaryValue* FindMatchingPolicy(
264 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap& policies,
265 const base::DictionaryValue& actual_network) {
266 for (ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap::const_iterator
267 it = policies.begin();
268 it != policies.end(); ++it) {
269 if (IsPolicyMatching(*it->second, actual_network))
270 return it->second;
271 }
272 return NULL;
273 }
274
275 const base::DictionaryValue* GetByGUID( 35 const base::DictionaryValue* GetByGUID(
276 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap& policies, 36 const PolicyApplicator::GuidToPolicyMap& policies,
277 const std::string& guid) { 37 const std::string& guid) {
278 ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap::const_iterator it = 38 PolicyApplicator::GuidToPolicyMap::const_iterator it = policies.find(guid);
279 policies.find(guid);
280 if (it == policies.end()) 39 if (it == policies.end())
281 return NULL; 40 return NULL;
282 return it->second; 41 return it->second;
283 } 42 }
284 43
285 void TranslatePropertiesToOncAndRunCallback(
286 const network_handler::DictionaryResultCallback& callback,
287 const std::string& service_path,
288 const base::DictionaryValue& shill_properties) {
289 scoped_ptr<base::DictionaryValue> onc_network(
290 onc::TranslateShillServiceToONCPart(
291 shill_properties,
292 &onc::kNetworkWithStateSignature));
293 callback.Run(service_path, *onc_network);
294 }
295
296 } // namespace 44 } // namespace
297 45
298 // This class compares (entry point is Run()) |modified_policies| with the 46 PolicyApplicator::PolicyApplicator(base::WeakPtr<ConfigurationHandler> handler,
299 // existing entries in the provided Shill profile |profile|. It fetches all 47 const NetworkProfile& profile,
300 // entries in parallel (GetProfilePropertiesCallback), compares each entry with 48 const GuidToPolicyMap& all_policies,
301 // the current policies (GetEntryCallback) and adds all missing policies 49 std::set<std::string>* modified_policies)
302 // (~PolicyApplicator).
303 class ManagedNetworkConfigurationHandlerImpl::PolicyApplicator
304 : public base::RefCounted<PolicyApplicator> {
305 public:
306 typedef ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap
307 GuidToPolicyMap;
308
309 // |modified_policies| must not be NULL and will be empty afterwards.
310 PolicyApplicator(
311 base::WeakPtr<ManagedNetworkConfigurationHandlerImpl> handler,
312 const NetworkProfile& profile,
313 const GuidToPolicyMap& all_policies,
314 std::set<std::string>* modified_policies);
315
316 void Run();
317
318 private:
319 friend class base::RefCounted<PolicyApplicator>;
320
321 // Called with the properties of the profile |profile_|. Requests the
322 // properties of each entry, which are processed by GetEntryCallback.
323 void GetProfilePropertiesCallback(
324 const base::DictionaryValue& profile_properties);
325
326 // Called with the properties of the profile entry |entry|. Checks whether the
327 // entry was previously managed, whether a current policy applies and then
328 // either updates, deletes or not touches the entry.
329 void GetEntryCallback(const std::string& entry,
330 const base::DictionaryValue& entry_properties);
331
332 // Sends Shill the command to delete profile entry |entry| from |profile_|.
333 void DeleteEntry(const std::string& entry);
334
335 // Creates a Shill configuration from the given parameters and sends them to
336 // Shill. |user_settings| can be NULL if none exist.
337 void CreateAndWriteNewShillConfiguration(
338 const std::string& guid,
339 const base::DictionaryValue& policy,
340 const base::DictionaryValue* user_settings);
341
342 // Called once all Profile entries are processed. Calls
343 // ApplyRemainingPolicies.
344 virtual ~PolicyApplicator();
345
346 // Creates new entries for all remaining policies, i.e. for which no matching
347 // Profile entry was found.
348 void ApplyRemainingPolicies();
349
350 std::set<std::string> remaining_policies_;
351 base::WeakPtr<ManagedNetworkConfigurationHandlerImpl> handler_;
352 NetworkProfile profile_;
353 GuidToPolicyMap all_policies_;
354
355 DISALLOW_COPY_AND_ASSIGN(PolicyApplicator);
356 };
357
358 void ManagedNetworkConfigurationHandlerImpl::AddObserver(
359 NetworkPolicyObserver* observer) {
360 observers_.AddObserver(observer);
361 }
362
363 void ManagedNetworkConfigurationHandlerImpl::RemoveObserver(
364 NetworkPolicyObserver* observer) {
365 observers_.RemoveObserver(observer);
366 }
367
368 void ManagedNetworkConfigurationHandlerImpl::GetManagedProperties(
369 const std::string& userhash,
370 const std::string& service_path,
371 const network_handler::DictionaryResultCallback& callback,
372 const network_handler::ErrorCallback& error_callback) {
373 if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
374 RunErrorCallback(service_path,
375 kPoliciesNotInitialized,
376 kPoliciesNotInitializedMessage,
377 error_callback);
378 return;
379 }
380 network_configuration_handler_->GetProperties(
381 service_path,
382 base::Bind(
383 &ManagedNetworkConfigurationHandlerImpl::GetManagedPropertiesCallback,
384 weak_ptr_factory_.GetWeakPtr(),
385 callback,
386 error_callback),
387 error_callback);
388 }
389
390 void ManagedNetworkConfigurationHandlerImpl::GetManagedPropertiesCallback(
391 const network_handler::DictionaryResultCallback& callback,
392 const network_handler::ErrorCallback& error_callback,
393 const std::string& service_path,
394 const base::DictionaryValue& shill_properties) {
395 std::string profile_path;
396 shill_properties.GetStringWithoutPathExpansion(flimflam::kProfileProperty,
397 &profile_path);
398 const NetworkProfile* profile =
399 network_profile_handler_->GetProfileForPath(profile_path);
400 if (!profile) {
401 LOG(ERROR) << "No or no known profile received for service "
402 << service_path << ".";
403 }
404
405 scoped_ptr<NetworkUIData> ui_data =
406 shill_property_util::GetUIDataFromProperties(shill_properties);
407
408 const base::DictionaryValue* user_settings = NULL;
409 const base::DictionaryValue* shared_settings = NULL;
410
411 if (ui_data && profile) {
412 if (profile->type() == NetworkProfile::TYPE_SHARED)
413 shared_settings = ui_data->user_settings();
414 else if (profile->type() == NetworkProfile::TYPE_USER)
415 user_settings = ui_data->user_settings();
416 else
417 NOTREACHED();
418 } else if (profile) {
419 LOG(WARNING) << "Service " << service_path << " of profile "
420 << profile_path << " contains no or no valid UIData.";
421 // TODO(pneubeck): add a conversion of user configured entries of old
422 // ChromeOS versions. We will have to use a heuristic to determine which
423 // properties _might_ be user configured.
424 }
425
426 scoped_ptr<base::DictionaryValue> active_settings(
427 onc::TranslateShillServiceToONCPart(
428 shill_properties,
429 &onc::kNetworkWithStateSignature));
430
431 std::string guid;
432 active_settings->GetStringWithoutPathExpansion(onc::network_config::kGUID,
433 &guid);
434
435 const base::DictionaryValue* user_policy = NULL;
436 const base::DictionaryValue* device_policy = NULL;
437 if (!guid.empty() && profile) {
438 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
439 if (!policies) {
440 RunErrorCallback(service_path,
441 kPoliciesNotInitialized,
442 kPoliciesNotInitializedMessage,
443 error_callback);
444 return;
445 }
446 const base::DictionaryValue* policy = GetByGUID(*policies, guid);
447 if (profile->type() == NetworkProfile::TYPE_SHARED)
448 device_policy = policy;
449 else if (profile->type() == NetworkProfile::TYPE_USER)
450 user_policy = policy;
451 else
452 NOTREACHED();
453 }
454
455 // This call also removes credentials from policies.
456 scoped_ptr<base::DictionaryValue> augmented_properties =
457 onc::MergeSettingsAndPoliciesToAugmented(
458 onc::kNetworkConfigurationSignature,
459 user_policy,
460 device_policy,
461 user_settings,
462 shared_settings,
463 active_settings.get());
464 callback.Run(service_path, *augmented_properties);
465 }
466
467 void ManagedNetworkConfigurationHandlerImpl::GetProperties(
468 const std::string& service_path,
469 const network_handler::DictionaryResultCallback& callback,
470 const network_handler::ErrorCallback& error_callback) const {
471 network_configuration_handler_->GetProperties(
472 service_path,
473 base::Bind(&TranslatePropertiesToOncAndRunCallback, callback),
474 error_callback);
475 }
476
477 void ManagedNetworkConfigurationHandlerImpl::SetProperties(
478 const std::string& service_path,
479 const base::DictionaryValue& user_settings,
480 const base::Closure& callback,
481 const network_handler::ErrorCallback& error_callback) const {
482 const NetworkState* state =
483 network_state_handler_->GetNetworkState(service_path);
484
485 if (!state) {
486 RunErrorCallback(service_path,
487 kUnknownServicePath,
488 kUnknownServicePathMessage,
489 error_callback);
490 return;
491 }
492
493 std::string guid = state->guid();
494 if (guid.empty()) {
495 // TODO(pneubeck): create an initial configuration in this case. As for
496 // CreateConfiguration, user settings from older ChromeOS versions have to
497 // determined here.
498 RunErrorCallback(service_path,
499 kSetOnUnconfiguredNetwork,
500 kSetOnUnconfiguredNetworkMessage,
501 error_callback);
502 return;
503 }
504
505 const std::string& profile_path = state->profile_path();
506 const NetworkProfile *profile =
507 network_profile_handler_->GetProfileForPath(profile_path);
508 if (!profile) {
509 RunErrorCallback(service_path,
510 kUnknownProfilePath,
511 kUnknownProfilePathMessage,
512 error_callback);
513 return;
514 }
515
516 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
517 << profile->ToDebugString();
518
519 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
520 if (!policies) {
521 RunErrorCallback(service_path,
522 kPoliciesNotInitialized,
523 kPoliciesNotInitializedMessage,
524 error_callback);
525 return;
526 }
527
528 // Validate the ONC dictionary. We are liberal and ignore unknown field
529 // names. User settings are only partial ONC, thus we ignore missing fields.
530 onc::Validator validator(false, // Ignore unknown fields.
531 false, // Ignore invalid recommended field names.
532 false, // Ignore missing fields.
533 false); // This ONC does not come from policy.
534
535 onc::Validator::Result validation_result;
536 scoped_ptr<base::DictionaryValue> validated_user_settings =
537 validator.ValidateAndRepairObject(
538 &onc::kNetworkConfigurationSignature,
539 user_settings,
540 &validation_result);
541
542 if (validation_result == onc::Validator::INVALID) {
543 RunErrorCallback(service_path,
544 kInvalidUserSettings,
545 kInvalidUserSettingsMessage,
546 error_callback);
547 return;
548 }
549 if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
550 LOG(WARNING) << "Validation of ONC user settings produced warnings.";
551
552 const base::DictionaryValue* policy = GetByGUID(*policies, guid);
553 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed.";
554
555 scoped_ptr<base::DictionaryValue> shill_dictionary(CreateShillConfiguration(
556 *profile, guid, policy, validated_user_settings.get()));
557
558 network_configuration_handler_->SetProperties(
559 service_path, *shill_dictionary, callback, error_callback);
560 }
561
562 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration(
563 const std::string& userhash,
564 const base::DictionaryValue& properties,
565 const network_handler::StringResultCallback& callback,
566 const network_handler::ErrorCallback& error_callback) const {
567 const GuidToPolicyMap* policies = GetPoliciesForUser(userhash);
568 if (!policies) {
569 RunErrorCallback("",
570 kPoliciesNotInitialized,
571 kPoliciesNotInitializedMessage,
572 error_callback);
573 return;
574 }
575
576 if (FindMatchingPolicy(*policies, properties)) {
577 RunErrorCallback("",
578 kNetworkAlreadyConfigured,
579 kNetworkAlreadyConfiguredMessage,
580 error_callback);
581 }
582
583 const NetworkProfile* profile =
584 network_profile_handler_->GetProfileForUserhash(userhash);
585 if (!profile) {
586 RunErrorCallback("",
587 kProfileNotInitialized,
588 kProfileNotInitializedMessage,
589 error_callback);
590 }
591
592 // TODO(pneubeck): In case of WiFi, check that no other configuration for the
593 // same {SSID, mode, security} exists. We don't support such multiple
594 // configurations, yet.
595
596 // Generate a new GUID for this configuration. Ignore the maybe provided GUID
597 // in |properties| as it is not our own and from an untrusted source.
598 std::string guid = base::GenerateGUID();
599 scoped_ptr<base::DictionaryValue> shill_dictionary(
600 CreateShillConfiguration(*profile, guid, NULL /*no policy*/,
601 &properties));
602
603 network_configuration_handler_->CreateConfiguration(
604 *shill_dictionary, callback, error_callback);
605 }
606
607 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration(
608 const std::string& service_path,
609 const base::Closure& callback,
610 const network_handler::ErrorCallback& error_callback) const {
611 network_configuration_handler_->RemoveConfiguration(
612 service_path, callback, error_callback);
613 }
614
615 void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
616 onc::ONCSource onc_source,
617 const std::string& userhash,
618 const base::ListValue& network_configs_onc) {
619 VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
620 << ".";
621
622 // |userhash| must be empty for device policies.
623 DCHECK(onc_source != chromeos::onc::ONC_SOURCE_DEVICE_POLICY ||
624 userhash.empty());
625 GuidToPolicyMap& policies = policies_by_user_[userhash];
626
627 GuidToPolicyMap old_policies;
628 policies.swap(old_policies);
629
630 // This stores all GUIDs of policies that have changed or are new.
631 std::set<std::string> modified_policies;
632
633 for (base::ListValue::const_iterator it = network_configs_onc.begin();
634 it != network_configs_onc.end(); ++it) {
635 const base::DictionaryValue* network = NULL;
636 (*it)->GetAsDictionary(&network);
637 DCHECK(network);
638
639 std::string guid;
640 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid);
641 DCHECK(!guid.empty());
642
643 if (policies.count(guid) > 0) {
644 LOG(ERROR) << "ONC from " << ToDebugString(onc_source, userhash)
645 << " contains several entries for the same GUID "
646 << guid << ".";
647 delete policies[guid];
648 }
649 const base::DictionaryValue* new_entry = network->DeepCopy();
650 policies[guid] = new_entry;
651
652 const base::DictionaryValue* old_entry = old_policies[guid];
653 if (!old_entry || !old_entry->Equals(new_entry))
654 modified_policies.insert(guid);
655 }
656
657 STLDeleteValues(&old_policies);
658
659 const NetworkProfile* profile =
660 network_profile_handler_->GetProfileForUserhash(userhash);
661 if (!profile) {
662 VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
663 << "policy application.";
664 return;
665 }
666
667 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
668 weak_ptr_factory_.GetWeakPtr(), *profile, policies, &modified_policies);
669 applicator->Run();
670 }
671
672 void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
673 const NetworkProfile& profile) {
674 VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";
675
676 const GuidToPolicyMap* policies = GetPoliciesForProfile(profile);
677 if (!policies) {
678 VLOG(1) << "The relevant policy is not initialized, "
679 << "postponing policy application.";
680 return;
681 }
682
683 std::set<std::string> policy_guids;
684 for (GuidToPolicyMap::const_iterator it = policies->begin();
685 it != policies->end(); ++it) {
686 policy_guids.insert(it->first);
687 }
688
689 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
690 weak_ptr_factory_.GetWeakPtr(), profile, *policies, &policy_guids);
691 applicator->Run();
692 }
693
694 const base::DictionaryValue*
695 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID(
696 const std::string userhash,
697 const std::string& guid,
698 onc::ONCSource* onc_source) const {
699 *onc_source = onc::ONC_SOURCE_NONE;
700
701 if (!userhash.empty()) {
702 const GuidToPolicyMap* user_policies = GetPoliciesForUser(userhash);
703 if (user_policies) {
704 GuidToPolicyMap::const_iterator found = user_policies->find(guid);
705 if (found != user_policies->end()) {
706 *onc_source = onc::ONC_SOURCE_USER_POLICY;
707 return found->second;
708 }
709 }
710 }
711
712 const GuidToPolicyMap* device_policies = GetPoliciesForUser(std::string());
713 if (device_policies) {
714 GuidToPolicyMap::const_iterator found = device_policies->find(guid);
715 if (found != device_policies->end()) {
716 *onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
717 return found->second;
718 }
719 }
720
721 return NULL;
722 }
723
724 const base::DictionaryValue*
725 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile(
726 const std::string& guid,
727 const std::string& profile_path) const {
728 const NetworkProfile* profile =
729 network_profile_handler_->GetProfileForPath(profile_path);
730 if (!profile) {
731 LOG(ERROR) << "Profile path unknown: " << profile_path;
732 return NULL;
733 }
734
735 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
736 if (!policies)
737 return NULL;
738
739 GuidToPolicyMap::const_iterator it = policies->find(guid);
740 if (it == policies->end())
741 return NULL;
742 return it->second;
743 }
744
745 void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved(
746 const NetworkProfile& profile) {
747 // Nothing to do in this case.
748 }
749
750 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap*
751 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser(
752 const std::string& userhash) const {
753 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
754 if (it == policies_by_user_.end())
755 return NULL;
756 return &it->second;
757 }
758
759 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap*
760 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile(
761 const NetworkProfile& profile) const {
762 DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
763 profile.userhash.empty());
764 return GetPoliciesForUser(profile.userhash);
765 }
766
767 ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl()
768 : network_state_handler_(NULL),
769 network_profile_handler_(NULL),
770 network_configuration_handler_(NULL),
771 weak_ptr_factory_(this) {}
772
773 ManagedNetworkConfigurationHandlerImpl::
774 ~ManagedNetworkConfigurationHandlerImpl() {
775 network_profile_handler_->RemoveObserver(this);
776 for (UserToPoliciesMap::iterator it = policies_by_user_.begin();
777 it != policies_by_user_.end(); ++it) {
778 STLDeleteValues(&it->second);
779 }
780 }
781
782 void ManagedNetworkConfigurationHandlerImpl::Init(
783 NetworkStateHandler* network_state_handler,
784 NetworkProfileHandler* network_profile_handler,
785 NetworkConfigurationHandler* network_configuration_handler) {
786 network_state_handler_ = network_state_handler;
787 network_profile_handler_ = network_profile_handler;
788 network_configuration_handler_ = network_configuration_handler;
789 network_profile_handler_->AddObserver(this);
790 }
791
792 void ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied(
793 const std::string& service_path) {
794 if (service_path.empty())
795 return;
796 FOR_EACH_OBSERVER(
797 NetworkPolicyObserver, observers_, PolicyApplied(service_path));
798 }
799
800 ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::PolicyApplicator(
801 base::WeakPtr<ManagedNetworkConfigurationHandlerImpl> handler,
802 const NetworkProfile& profile,
803 const GuidToPolicyMap& all_policies,
804 std::set<std::string>* modified_policies)
805 : handler_(handler), profile_(profile) { 50 : handler_(handler), profile_(profile) {
806 remaining_policies_.swap(*modified_policies); 51 remaining_policies_.swap(*modified_policies);
807 for (GuidToPolicyMap::const_iterator it = all_policies.begin(); 52 for (GuidToPolicyMap::const_iterator it = all_policies.begin();
808 it != all_policies.end(); ++it) { 53 it != all_policies.end(); ++it) {
809 all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy())); 54 all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy()));
810 } 55 }
811 } 56 }
812 57
813 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::Run() { 58 void PolicyApplicator::Run() {
814 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( 59 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
815 dbus::ObjectPath(profile_.path), 60 dbus::ObjectPath(profile_.path),
816 base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this), 61 base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this),
817 base::Bind(&LogErrorMessage, FROM_HERE)); 62 base::Bind(&LogErrorMessage, FROM_HERE));
818 } 63 }
819 64
820 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: 65 void PolicyApplicator::GetProfilePropertiesCallback(
821 GetProfilePropertiesCallback( 66 const base::DictionaryValue& profile_properties) {
822 const base::DictionaryValue& profile_properties) {
823 if (!handler_) { 67 if (!handler_) {
824 LOG(WARNING) << "Handler destructed during policy application to profile " 68 LOG(WARNING) << "Handler destructed during policy application to profile "
825 << profile_.ToDebugString(); 69 << profile_.ToDebugString();
826 return; 70 return;
827 } 71 }
828 72
829 VLOG(2) << "Received properties for profile " << profile_.ToDebugString(); 73 VLOG(2) << "Received properties for profile " << profile_.ToDebugString();
830 const base::ListValue* entries = NULL; 74 const base::ListValue* entries = NULL;
831 if (!profile_properties.GetListWithoutPathExpansion( 75 if (!profile_properties.GetListWithoutPathExpansion(
832 flimflam::kEntriesProperty, &entries)) { 76 flimflam::kEntriesProperty, &entries)) {
833 LOG(ERROR) << "Profile " << profile_.ToDebugString() 77 LOG(ERROR) << "Profile " << profile_.ToDebugString()
834 << " doesn't contain the property " 78 << " doesn't contain the property "
835 << flimflam::kEntriesProperty; 79 << flimflam::kEntriesProperty;
836 return; 80 return;
837 } 81 }
838 82
839 for (base::ListValue::const_iterator it = entries->begin(); 83 for (base::ListValue::const_iterator it = entries->begin();
840 it != entries->end(); 84 it != entries->end(); ++it) {
841 ++it) {
842 std::string entry; 85 std::string entry;
843 (*it)->GetAsString(&entry); 86 (*it)->GetAsString(&entry);
844 87
845 DBusThreadManager::Get()->GetShillProfileClient() 88 DBusThreadManager::Get()->GetShillProfileClient()->GetEntry(
846 ->GetEntry(dbus::ObjectPath(profile_.path), 89 dbus::ObjectPath(profile_.path),
847 entry, 90 entry,
848 base::Bind(&PolicyApplicator::GetEntryCallback, this, entry), 91 base::Bind(&PolicyApplicator::GetEntryCallback, this, entry),
849 base::Bind(&LogErrorMessage, FROM_HERE)); 92 base::Bind(&LogErrorMessage, FROM_HERE));
850 } 93 }
851 } 94 }
852 95
853 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::GetEntryCallback( 96 void PolicyApplicator::GetEntryCallback(
854 const std::string& entry, 97 const std::string& entry,
855 const base::DictionaryValue& entry_properties) { 98 const base::DictionaryValue& entry_properties) {
856 if (!handler_) { 99 if (!handler_) {
857 LOG(WARNING) << "Handler destructed during policy application to profile " 100 LOG(WARNING) << "Handler destructed during policy application to profile "
858 << profile_.ToDebugString(); 101 << profile_.ToDebugString();
859 return; 102 return;
860 } 103 }
861 104
862 VLOG(2) << "Received properties for entry " << entry << " of profile " 105 VLOG(2) << "Received properties for entry " << entry << " of profile "
863 << profile_.ToDebugString(); 106 << profile_.ToDebugString();
(...skipping 29 matching lines...) Expand all
893 const base::DictionaryValue* new_policy = NULL; 136 const base::DictionaryValue* new_policy = NULL;
894 if (was_managed) { 137 if (was_managed) {
895 // If we have a GUID that might match a current policy, do a lookup using 138 // If we have a GUID that might match a current policy, do a lookup using
896 // that GUID at first. In particular this is necessary, as some networks 139 // that GUID at first. In particular this is necessary, as some networks
897 // can't be matched to policies by properties (e.g. VPN). 140 // can't be matched to policies by properties (e.g. VPN).
898 new_policy = GetByGUID(all_policies_, old_guid); 141 new_policy = GetByGUID(all_policies_, old_guid);
899 } 142 }
900 143
901 if (!new_policy) { 144 if (!new_policy) {
902 // If we didn't find a policy by GUID, still a new policy might match. 145 // If we didn't find a policy by GUID, still a new policy might match.
903 new_policy = FindMatchingPolicy(all_policies_, *onc_part); 146 new_policy = policy_util::FindMatchingPolicy(all_policies_, *onc_part);
904 } 147 }
905 148
906 if (new_policy) { 149 if (new_policy) {
907 std::string new_guid; 150 std::string new_guid;
908 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID, 151 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID,
909 &new_guid); 152 &new_guid);
910 153
911 VLOG_IF(1, was_managed && old_guid != new_guid) 154 VLOG_IF(1, was_managed && old_guid != new_guid)
912 << "Updating configuration previously managed by policy " << old_guid 155 << "Updating configuration previously managed by policy " << old_guid
913 << " with new policy " << new_guid << "."; 156 << " with new policy " << new_guid << ".";
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 // unclear which values originating the policy should be removed. 190 // unclear which values originating the policy should be removed.
948 DeleteEntry(entry); 191 DeleteEntry(entry);
949 } else { 192 } else {
950 VLOG(2) << "Ignore unmanaged entry."; 193 VLOG(2) << "Ignore unmanaged entry.";
951 194
952 // The entry wasn't managed and doesn't match any current policy. Thus 195 // The entry wasn't managed and doesn't match any current policy. Thus
953 // leave it as it is. 196 // leave it as it is.
954 } 197 }
955 } 198 }
956 199
957 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::DeleteEntry( 200 void PolicyApplicator::DeleteEntry(const std::string& entry) {
958 const std::string& entry) {
959 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( 201 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
960 dbus::ObjectPath(profile_.path), 202 dbus::ObjectPath(profile_.path),
961 entry, 203 entry,
962 base::Bind(&base::DoNothing), 204 base::Bind(&base::DoNothing),
963 base::Bind(&LogErrorMessage, FROM_HERE)); 205 base::Bind(&LogErrorMessage, FROM_HERE));
964 } 206 }
965 207
966 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: 208 void PolicyApplicator::CreateAndWriteNewShillConfiguration(
967 CreateAndWriteNewShillConfiguration( 209 const std::string& guid,
968 const std::string& guid, 210 const base::DictionaryValue& policy,
969 const base::DictionaryValue& policy, 211 const base::DictionaryValue* user_settings) {
970 const base::DictionaryValue* user_settings) {
971 scoped_ptr<base::DictionaryValue> shill_dictionary = 212 scoped_ptr<base::DictionaryValue> shill_dictionary =
972 CreateShillConfiguration(profile_, guid, &policy, user_settings); 213 policy_util::CreateShillConfiguration(
973 handler_->network_configuration_handler()->CreateConfiguration( 214 profile_, guid, &policy, user_settings);
974 *shill_dictionary, 215 handler_->CreateConfigurationFromPolicy(*shill_dictionary);
975 base::Bind(&ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied,
976 handler_),
977 base::Bind(&LogErrorWithDict, FROM_HERE));
978 } 216 }
979 217
980 ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::~PolicyApplicator() { 218 PolicyApplicator::~PolicyApplicator() {
981 ApplyRemainingPolicies(); 219 ApplyRemainingPolicies();
982 STLDeleteValues(&all_policies_); 220 STLDeleteValues(&all_policies_);
983 } 221 }
984 222
985 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: 223 void PolicyApplicator::ApplyRemainingPolicies() {
986 ApplyRemainingPolicies() {
987 if (!handler_) { 224 if (!handler_) {
988 LOG(WARNING) << "Handler destructed during policy application to profile " 225 LOG(WARNING) << "Handler destructed during policy application to profile "
989 << profile_.ToDebugString(); 226 << profile_.ToDebugString();
990 return; 227 return;
991 } 228 }
992 229
993 if (remaining_policies_.empty()) 230 if (remaining_policies_.empty())
994 return; 231 return;
995 232
996 VLOG(2) << "Create new managed network configurations in profile" 233 VLOG(2) << "Create new managed network configurations in profile"
997 << profile_.ToDebugString() << "."; 234 << profile_.ToDebugString() << ".";
998 // All profile entries were compared to policies. |remaining_policies_| 235 // All profile entries were compared to policies. |remaining_policies_|
999 // contains all modified policies that didn't match any entry. For these 236 // contains all modified policies that didn't match any entry. For these
1000 // remaining policies, new configurations have to be created. 237 // remaining policies, new configurations have to be created.
1001
1002 for (std::set<std::string>::iterator it = remaining_policies_.begin(); 238 for (std::set<std::string>::iterator it = remaining_policies_.begin();
1003 it != remaining_policies_.end(); 239 it != remaining_policies_.end(); ++it) {
1004 ++it) {
1005 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it); 240 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it);
1006 DCHECK(policy); 241 DCHECK(policy);
1007 242
1008 VLOG(1) << "Creating new configuration managed by policy " << *it 243 VLOG(1) << "Creating new configuration managed by policy " << *it
1009 << " in profile " << profile_.ToDebugString() << "."; 244 << " in profile " << profile_.ToDebugString() << ".";
1010 245
1011 CreateAndWriteNewShillConfiguration( 246 CreateAndWriteNewShillConfiguration(
1012 *it, *policy, NULL /* no user settings */); 247 *it, *policy, NULL /* no user settings */);
1013 } 248 }
1014 } 249 }
1015 250
1016 } // namespace chromeos 251 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/policy_applicator.h ('k') | chromeos/network/policy_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698