| 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/managed_network_configuration_handler_impl.h" | 5 #include "chromeos/network/managed_network_configuration_handler_impl.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <set> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/guid.h" | 11 #include "base/guid.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/scoped_ptr.h" |
| 15 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 16 #include "base/strings/string_util.h" | |
| 17 #include "base/values.h" | 17 #include "base/values.h" |
| 18 #include "chromeos/dbus/dbus_method_call_status.h" | |
| 19 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 20 #include "chromeos/dbus/shill_manager_client.h" | 18 #include "chromeos/dbus/shill_manager_client.h" |
| 21 #include "chromeos/dbus/shill_profile_client.h" | 19 #include "chromeos/dbus/shill_profile_client.h" |
| 22 #include "chromeos/dbus/shill_service_client.h" | 20 #include "chromeos/dbus/shill_service_client.h" |
| 23 #include "chromeos/network/network_configuration_handler.h" | 21 #include "chromeos/network/network_configuration_handler.h" |
| 24 #include "chromeos/network/network_event_log.h" | 22 #include "chromeos/network/network_event_log.h" |
| 25 #include "chromeos/network/network_policy_observer.h" | 23 #include "chromeos/network/network_policy_observer.h" |
| 26 #include "chromeos/network/network_profile.h" | 24 #include "chromeos/network/network_profile.h" |
| 27 #include "chromeos/network/network_profile_handler.h" | 25 #include "chromeos/network/network_profile_handler.h" |
| 28 #include "chromeos/network/network_state.h" | 26 #include "chromeos/network/network_state.h" |
| 29 #include "chromeos/network/network_state_handler.h" | 27 #include "chromeos/network/network_state_handler.h" |
| 30 #include "chromeos/network/network_ui_data.h" | 28 #include "chromeos/network/network_ui_data.h" |
| 31 #include "chromeos/network/onc/onc_constants.h" | 29 #include "chromeos/network/onc/onc_constants.h" |
| 32 #include "chromeos/network/onc/onc_merger.h" | 30 #include "chromeos/network/onc/onc_merger.h" |
| 33 #include "chromeos/network/onc/onc_normalizer.h" | |
| 34 #include "chromeos/network/onc/onc_signature.h" | 31 #include "chromeos/network/onc/onc_signature.h" |
| 35 #include "chromeos/network/onc/onc_translator.h" | 32 #include "chromeos/network/onc/onc_translator.h" |
| 36 #include "chromeos/network/onc/onc_utils.h" | |
| 37 #include "chromeos/network/onc/onc_validator.h" | 33 #include "chromeos/network/onc/onc_validator.h" |
| 34 #include "chromeos/network/policy_util.h" |
| 38 #include "chromeos/network/shill_property_util.h" | 35 #include "chromeos/network/shill_property_util.h" |
| 39 #include "dbus/object_path.h" | |
| 40 #include "third_party/cros_system_api/dbus/service_constants.h" | 36 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 41 | 37 |
| 42 namespace chromeos { | 38 namespace chromeos { |
| 43 | 39 |
| 44 namespace { | 40 namespace { |
| 45 | 41 |
| 46 // These are error strings used for error callbacks. None of these error | 42 // These are error strings used for error callbacks. None of these error |
| 47 // messages are user-facing: they should only appear in logs. | 43 // messages are user-facing: they should only appear in logs. |
| 48 const char kInvalidUserSettingsMessage[] = "User settings are invalid."; | 44 const char kInvalidUserSettingsMessage[] = "User settings are invalid."; |
| 49 const char kInvalidUserSettings[] = "Error.InvalidUserSettings"; | 45 const char kInvalidUserSettings[] = "Error.InvalidUserSettings"; |
| 50 const char kNetworkAlreadyConfiguredMessage[] = | 46 const char kNetworkAlreadyConfiguredMessage[] = |
| 51 "Network is already configured."; | 47 "Network is already configured."; |
| 52 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured"; | 48 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured"; |
| 53 const char kPoliciesNotInitializedMessage[] = "Policies not initialized."; | 49 const char kPoliciesNotInitializedMessage[] = "Policies not initialized."; |
| 54 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized"; | 50 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized"; |
| 55 const char kProfileNotInitializedMessage[] = "Profile not initialized."; | 51 const char kProfileNotInitializedMessage[] = "Profile not initialized."; |
| 56 const char kProfileNotInitialized[] = "Error.ProflieNotInitialized"; | 52 const char kProfileNotInitialized[] = "Error.ProflieNotInitialized"; |
| 57 const char kSetOnUnconfiguredNetworkMessage[] = | 53 const char kSetOnUnconfiguredNetworkMessage[] = |
| 58 "Unable to modify properties of an unconfigured network."; | 54 "Unable to modify properties of an unconfigured network."; |
| 59 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; | 55 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; |
| 60 const char kUnknownProfilePathMessage[] = "Profile path is unknown."; | 56 const char kUnknownProfilePathMessage[] = "Profile path is unknown."; |
| 61 const char kUnknownProfilePath[] = "Error.UnknownProfilePath"; | 57 const char kUnknownProfilePath[] = "Error.UnknownProfilePath"; |
| 62 const char kUnknownServicePathMessage[] = "Service path is unknown."; | 58 const char kUnknownServicePathMessage[] = "Service path is unknown."; |
| 63 const char kUnknownServicePath[] = "Error.UnknownServicePath"; | 59 const char kUnknownServicePath[] = "Error.UnknownServicePath"; |
| 64 | 60 |
| 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, | 61 std::string ToDebugString(onc::ONCSource source, |
| 70 const std::string& userhash) { | 62 const std::string& userhash) { |
| 71 return source == onc::ONC_SOURCE_USER_POLICY ? | 63 return source == onc::ONC_SOURCE_USER_POLICY ? |
| 72 ("user policy of " + userhash) : "device policy"; | 64 ("user policy of " + userhash) : "device policy"; |
| 73 } | 65 } |
| 74 | 66 |
| 75 void RunErrorCallback(const std::string& service_path, | 67 void RunErrorCallback(const std::string& service_path, |
| 76 const std::string& error_name, | 68 const std::string& error_name, |
| 77 const std::string& error_message, | 69 const std::string& error_message, |
| 78 const network_handler::ErrorCallback& error_callback) { | 70 const network_handler::ErrorCallback& error_callback) { |
| 79 NET_LOG_ERROR(error_name, error_message); | 71 NET_LOG_ERROR(error_name, error_message); |
| 80 error_callback.Run( | 72 error_callback.Run( |
| 81 error_name, | 73 error_name, |
| 82 make_scoped_ptr( | 74 make_scoped_ptr( |
| 83 network_handler::CreateErrorData(service_path, | 75 network_handler::CreateErrorData(service_path, |
| 84 error_name, | 76 error_name, |
| 85 error_message))); | 77 error_message))); |
| 86 } | 78 } |
| 87 | 79 |
| 88 void LogErrorWithDict(const tracked_objects::Location& from_where, | 80 void LogErrorWithDict(const tracked_objects::Location& from_where, |
| 89 const std::string& error_name, | 81 const std::string& error_name, |
| 90 scoped_ptr<base::DictionaryValue> error_data) { | 82 scoped_ptr<base::DictionaryValue> error_data) { |
| 91 LOG(ERROR) << from_where.ToString() << ": " << error_name; | 83 LOG(ERROR) << from_where.ToString() << ": " << error_name; |
| 92 } | 84 } |
| 93 | 85 |
| 94 void LogErrorMessage(const tracked_objects::Location& from_where, | |
| 95 const std::string& error_name, | |
| 96 const std::string& error_message) { | |
| 97 LOG(ERROR) << from_where.ToString() << ": " << error_message; | |
| 98 } | |
| 99 | |
| 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( | 86 const base::DictionaryValue* GetByGUID( |
| 276 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap& policies, | 87 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap& policies, |
| 277 const std::string& guid) { | 88 const std::string& guid) { |
| 278 ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap::const_iterator it = | 89 ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap::const_iterator it = |
| 279 policies.find(guid); | 90 policies.find(guid); |
| 280 if (it == policies.end()) | 91 if (it == policies.end()) |
| 281 return NULL; | 92 return NULL; |
| 282 return it->second; | 93 return it->second; |
| 283 } | 94 } |
| 284 | 95 |
| 285 void TranslatePropertiesToOncAndRunCallback( | 96 void TranslatePropertiesToOncAndRunCallback( |
| 286 const network_handler::DictionaryResultCallback& callback, | 97 const network_handler::DictionaryResultCallback& callback, |
| 287 const std::string& service_path, | 98 const std::string& service_path, |
| 288 const base::DictionaryValue& shill_properties) { | 99 const base::DictionaryValue& shill_properties) { |
| 289 scoped_ptr<base::DictionaryValue> onc_network( | 100 scoped_ptr<base::DictionaryValue> onc_network( |
| 290 onc::TranslateShillServiceToONCPart( | 101 onc::TranslateShillServiceToONCPart( |
| 291 shill_properties, | 102 shill_properties, |
| 292 &onc::kNetworkWithStateSignature)); | 103 &onc::kNetworkWithStateSignature)); |
| 293 callback.Run(service_path, *onc_network); | 104 callback.Run(service_path, *onc_network); |
| 294 } | 105 } |
| 295 | 106 |
| 296 } // namespace | 107 } // namespace |
| 297 | 108 |
| 298 // This class compares (entry point is Run()) |modified_policies| with the | |
| 299 // existing entries in the provided Shill profile |profile|. It fetches all | |
| 300 // entries in parallel (GetProfilePropertiesCallback), compares each entry with | |
| 301 // the current policies (GetEntryCallback) and adds all missing 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( | 109 void ManagedNetworkConfigurationHandlerImpl::AddObserver( |
| 359 NetworkPolicyObserver* observer) { | 110 NetworkPolicyObserver* observer) { |
| 360 observers_.AddObserver(observer); | 111 observers_.AddObserver(observer); |
| 361 } | 112 } |
| 362 | 113 |
| 363 void ManagedNetworkConfigurationHandlerImpl::RemoveObserver( | 114 void ManagedNetworkConfigurationHandlerImpl::RemoveObserver( |
| 364 NetworkPolicyObserver* observer) { | 115 NetworkPolicyObserver* observer) { |
| 365 observers_.RemoveObserver(observer); | 116 observers_.RemoveObserver(observer); |
| 366 } | 117 } |
| 367 | 118 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 kInvalidUserSettingsMessage, | 296 kInvalidUserSettingsMessage, |
| 546 error_callback); | 297 error_callback); |
| 547 return; | 298 return; |
| 548 } | 299 } |
| 549 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) | 300 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) |
| 550 LOG(WARNING) << "Validation of ONC user settings produced warnings."; | 301 LOG(WARNING) << "Validation of ONC user settings produced warnings."; |
| 551 | 302 |
| 552 const base::DictionaryValue* policy = GetByGUID(*policies, guid); | 303 const base::DictionaryValue* policy = GetByGUID(*policies, guid); |
| 553 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; | 304 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; |
| 554 | 305 |
| 555 scoped_ptr<base::DictionaryValue> shill_dictionary(CreateShillConfiguration( | 306 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 556 *profile, guid, policy, validated_user_settings.get())); | 307 policy_util::CreateShillConfiguration( |
| 308 *profile, guid, policy, validated_user_settings.get())); |
| 557 | 309 |
| 558 network_configuration_handler_->SetProperties( | 310 network_configuration_handler_->SetProperties( |
| 559 service_path, *shill_dictionary, callback, error_callback); | 311 service_path, *shill_dictionary, callback, error_callback); |
| 560 } | 312 } |
| 561 | 313 |
| 562 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( | 314 void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( |
| 563 const std::string& userhash, | 315 const std::string& userhash, |
| 564 const base::DictionaryValue& properties, | 316 const base::DictionaryValue& properties, |
| 565 const network_handler::StringResultCallback& callback, | 317 const network_handler::StringResultCallback& callback, |
| 566 const network_handler::ErrorCallback& error_callback) const { | 318 const network_handler::ErrorCallback& error_callback) const { |
| 567 const GuidToPolicyMap* policies = GetPoliciesForUser(userhash); | 319 const GuidToPolicyMap* policies = GetPoliciesForUser(userhash); |
| 568 if (!policies) { | 320 if (!policies) { |
| 569 RunErrorCallback("", | 321 RunErrorCallback("", |
| 570 kPoliciesNotInitialized, | 322 kPoliciesNotInitialized, |
| 571 kPoliciesNotInitializedMessage, | 323 kPoliciesNotInitializedMessage, |
| 572 error_callback); | 324 error_callback); |
| 573 return; | 325 return; |
| 574 } | 326 } |
| 575 | 327 |
| 576 if (FindMatchingPolicy(*policies, properties)) { | 328 if (policy_util::FindMatchingPolicy(*policies, properties)) { |
| 577 RunErrorCallback("", | 329 RunErrorCallback("", |
| 578 kNetworkAlreadyConfigured, | 330 kNetworkAlreadyConfigured, |
| 579 kNetworkAlreadyConfiguredMessage, | 331 kNetworkAlreadyConfiguredMessage, |
| 580 error_callback); | 332 error_callback); |
| 581 } | 333 } |
| 582 | 334 |
| 583 const NetworkProfile* profile = | 335 const NetworkProfile* profile = |
| 584 network_profile_handler_->GetProfileForUserhash(userhash); | 336 network_profile_handler_->GetProfileForUserhash(userhash); |
| 585 if (!profile) { | 337 if (!profile) { |
| 586 RunErrorCallback("", | 338 RunErrorCallback("", |
| 587 kProfileNotInitialized, | 339 kProfileNotInitialized, |
| 588 kProfileNotInitializedMessage, | 340 kProfileNotInitializedMessage, |
| 589 error_callback); | 341 error_callback); |
| 590 } | 342 } |
| 591 | 343 |
| 592 // TODO(pneubeck): In case of WiFi, check that no other configuration for the | 344 // 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 | 345 // same {SSID, mode, security} exists. We don't support such multiple |
| 594 // configurations, yet. | 346 // configurations, yet. |
| 595 | 347 |
| 596 // Generate a new GUID for this configuration. Ignore the maybe provided GUID | 348 // 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. | 349 // in |properties| as it is not our own and from an untrusted source. |
| 598 std::string guid = base::GenerateGUID(); | 350 std::string guid = base::GenerateGUID(); |
| 599 scoped_ptr<base::DictionaryValue> shill_dictionary( | 351 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 600 CreateShillConfiguration(*profile, guid, NULL /*no policy*/, | 352 policy_util::CreateShillConfiguration( |
| 601 &properties)); | 353 *profile, guid, NULL /*no policy*/, &properties)); |
| 602 | 354 |
| 603 network_configuration_handler_->CreateConfiguration( | 355 network_configuration_handler_->CreateConfiguration( |
| 604 *shill_dictionary, callback, error_callback); | 356 *shill_dictionary, callback, error_callback); |
| 605 } | 357 } |
| 606 | 358 |
| 607 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration( | 359 void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration( |
| 608 const std::string& service_path, | 360 const std::string& service_path, |
| 609 const base::Closure& callback, | 361 const base::Closure& callback, |
| 610 const network_handler::ErrorCallback& error_callback) const { | 362 const network_handler::ErrorCallback& error_callback) const { |
| 611 network_configuration_handler_->RemoveConfiguration( | 363 network_configuration_handler_->RemoveConfiguration( |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 for (GuidToPolicyMap::const_iterator it = policies->begin(); | 436 for (GuidToPolicyMap::const_iterator it = policies->begin(); |
| 685 it != policies->end(); ++it) { | 437 it != policies->end(); ++it) { |
| 686 policy_guids.insert(it->first); | 438 policy_guids.insert(it->first); |
| 687 } | 439 } |
| 688 | 440 |
| 689 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator( | 441 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator( |
| 690 weak_ptr_factory_.GetWeakPtr(), profile, *policies, &policy_guids); | 442 weak_ptr_factory_.GetWeakPtr(), profile, *policies, &policy_guids); |
| 691 applicator->Run(); | 443 applicator->Run(); |
| 692 } | 444 } |
| 693 | 445 |
| 446 void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( |
| 447 const NetworkProfile& profile) { |
| 448 // Nothing to do in this case. |
| 449 } |
| 450 |
| 451 void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy( |
| 452 const base::DictionaryValue& shill_properties) { |
| 453 network_configuration_handler_->CreateConfiguration( |
| 454 shill_properties, |
| 455 base::Bind(&ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied, |
| 456 weak_ptr_factory_.GetWeakPtr()), |
| 457 base::Bind(&LogErrorWithDict, FROM_HERE)); |
| 458 } |
| 459 |
| 694 const base::DictionaryValue* | 460 const base::DictionaryValue* |
| 695 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID( | 461 ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID( |
| 696 const std::string userhash, | 462 const std::string userhash, |
| 697 const std::string& guid, | 463 const std::string& guid, |
| 698 onc::ONCSource* onc_source) const { | 464 onc::ONCSource* onc_source) const { |
| 699 *onc_source = onc::ONC_SOURCE_NONE; | 465 *onc_source = onc::ONC_SOURCE_NONE; |
| 700 | 466 |
| 701 if (!userhash.empty()) { | 467 if (!userhash.empty()) { |
| 702 const GuidToPolicyMap* user_policies = GetPoliciesForUser(userhash); | 468 const GuidToPolicyMap* user_policies = GetPoliciesForUser(userhash); |
| 703 if (user_policies) { | 469 if (user_policies) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile); | 501 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile); |
| 736 if (!policies) | 502 if (!policies) |
| 737 return NULL; | 503 return NULL; |
| 738 | 504 |
| 739 GuidToPolicyMap::const_iterator it = policies->find(guid); | 505 GuidToPolicyMap::const_iterator it = policies->find(guid); |
| 740 if (it == policies->end()) | 506 if (it == policies->end()) |
| 741 return NULL; | 507 return NULL; |
| 742 return it->second; | 508 return it->second; |
| 743 } | 509 } |
| 744 | 510 |
| 745 void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( | |
| 746 const NetworkProfile& profile) { | |
| 747 // Nothing to do in this case. | |
| 748 } | |
| 749 | |
| 750 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap* | 511 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap* |
| 751 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser( | 512 ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser( |
| 752 const std::string& userhash) const { | 513 const std::string& userhash) const { |
| 753 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); | 514 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); |
| 754 if (it == policies_by_user_.end()) | 515 if (it == policies_by_user_.end()) |
| 755 return NULL; | 516 return NULL; |
| 756 return &it->second; | 517 return &it->second; |
| 757 } | 518 } |
| 758 | 519 |
| 759 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap* | 520 const ManagedNetworkConfigurationHandlerImpl::GuidToPolicyMap* |
| (...skipping 30 matching lines...) Expand all Loading... |
| 790 } | 551 } |
| 791 | 552 |
| 792 void ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied( | 553 void ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied( |
| 793 const std::string& service_path) { | 554 const std::string& service_path) { |
| 794 if (service_path.empty()) | 555 if (service_path.empty()) |
| 795 return; | 556 return; |
| 796 FOR_EACH_OBSERVER( | 557 FOR_EACH_OBSERVER( |
| 797 NetworkPolicyObserver, observers_, PolicyApplied(service_path)); | 558 NetworkPolicyObserver, observers_, PolicyApplied(service_path)); |
| 798 } | 559 } |
| 799 | 560 |
| 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) { | |
| 806 remaining_policies_.swap(*modified_policies); | |
| 807 for (GuidToPolicyMap::const_iterator it = all_policies.begin(); | |
| 808 it != all_policies.end(); ++it) { | |
| 809 all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy())); | |
| 810 } | |
| 811 } | |
| 812 | |
| 813 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::Run() { | |
| 814 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( | |
| 815 dbus::ObjectPath(profile_.path), | |
| 816 base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this), | |
| 817 base::Bind(&LogErrorMessage, FROM_HERE)); | |
| 818 } | |
| 819 | |
| 820 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: | |
| 821 GetProfilePropertiesCallback( | |
| 822 const base::DictionaryValue& profile_properties) { | |
| 823 if (!handler_) { | |
| 824 LOG(WARNING) << "Handler destructed during policy application to profile " | |
| 825 << profile_.ToDebugString(); | |
| 826 return; | |
| 827 } | |
| 828 | |
| 829 VLOG(2) << "Received properties for profile " << profile_.ToDebugString(); | |
| 830 const base::ListValue* entries = NULL; | |
| 831 if (!profile_properties.GetListWithoutPathExpansion( | |
| 832 flimflam::kEntriesProperty, &entries)) { | |
| 833 LOG(ERROR) << "Profile " << profile_.ToDebugString() | |
| 834 << " doesn't contain the property " | |
| 835 << flimflam::kEntriesProperty; | |
| 836 return; | |
| 837 } | |
| 838 | |
| 839 for (base::ListValue::const_iterator it = entries->begin(); | |
| 840 it != entries->end(); | |
| 841 ++it) { | |
| 842 std::string entry; | |
| 843 (*it)->GetAsString(&entry); | |
| 844 | |
| 845 DBusThreadManager::Get()->GetShillProfileClient() | |
| 846 ->GetEntry(dbus::ObjectPath(profile_.path), | |
| 847 entry, | |
| 848 base::Bind(&PolicyApplicator::GetEntryCallback, this, entry), | |
| 849 base::Bind(&LogErrorMessage, FROM_HERE)); | |
| 850 } | |
| 851 } | |
| 852 | |
| 853 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::GetEntryCallback( | |
| 854 const std::string& entry, | |
| 855 const base::DictionaryValue& entry_properties) { | |
| 856 if (!handler_) { | |
| 857 LOG(WARNING) << "Handler destructed during policy application to profile " | |
| 858 << profile_.ToDebugString(); | |
| 859 return; | |
| 860 } | |
| 861 | |
| 862 VLOG(2) << "Received properties for entry " << entry << " of profile " | |
| 863 << profile_.ToDebugString(); | |
| 864 | |
| 865 scoped_ptr<base::DictionaryValue> onc_part( | |
| 866 onc::TranslateShillServiceToONCPart(entry_properties, | |
| 867 &onc::kNetworkWithStateSignature)); | |
| 868 | |
| 869 std::string old_guid; | |
| 870 if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 871 &old_guid)) { | |
| 872 VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString() | |
| 873 << " doesn't contain a GUID."; | |
| 874 // This might be an entry of an older ChromeOS version. Assume it to be | |
| 875 // unmanaged. | |
| 876 } | |
| 877 | |
| 878 scoped_ptr<NetworkUIData> ui_data = | |
| 879 shill_property_util::GetUIDataFromProperties(entry_properties); | |
| 880 if (!ui_data) { | |
| 881 VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString() | |
| 882 << " contains no or no valid UIData."; | |
| 883 // This might be an entry of an older ChromeOS version. Assume it to be | |
| 884 // unmanaged. It's an inconsistency if there is a GUID but no UIData, thus | |
| 885 // clear the GUID just in case. | |
| 886 old_guid.clear(); | |
| 887 } | |
| 888 | |
| 889 bool was_managed = !old_guid.empty() && ui_data && | |
| 890 (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || | |
| 891 ui_data->onc_source() == onc::ONC_SOURCE_USER_POLICY); | |
| 892 | |
| 893 const base::DictionaryValue* new_policy = NULL; | |
| 894 if (was_managed) { | |
| 895 // 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 | |
| 897 // can't be matched to policies by properties (e.g. VPN). | |
| 898 new_policy = GetByGUID(all_policies_, old_guid); | |
| 899 } | |
| 900 | |
| 901 if (!new_policy) { | |
| 902 // If we didn't find a policy by GUID, still a new policy might match. | |
| 903 new_policy = FindMatchingPolicy(all_policies_, *onc_part); | |
| 904 } | |
| 905 | |
| 906 if (new_policy) { | |
| 907 std::string new_guid; | |
| 908 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 909 &new_guid); | |
| 910 | |
| 911 VLOG_IF(1, was_managed && old_guid != new_guid) | |
| 912 << "Updating configuration previously managed by policy " << old_guid | |
| 913 << " with new policy " << new_guid << "."; | |
| 914 VLOG_IF(1, !was_managed) << "Applying policy " << new_guid | |
| 915 << " to previously unmanaged " | |
| 916 << "configuration."; | |
| 917 | |
| 918 if (old_guid == new_guid && | |
| 919 remaining_policies_.find(new_guid) == remaining_policies_.end()) { | |
| 920 VLOG(1) << "Not updating existing managed configuration with guid " | |
| 921 << new_guid << " because the policy didn't change."; | |
| 922 } else { | |
| 923 // Delete the entry to ensure that no old configuration remains. | |
| 924 // Don't do this if a policy is reapplied (e.g. after reboot) or updated | |
| 925 // (i.e. the GUID didn't change), in order to keep implicit state of | |
| 926 // Shill like "connected successfully before". | |
| 927 if (old_guid == new_guid) { | |
| 928 VLOG(1) << "Updating previously managed configuration with the " | |
| 929 << "updated policy " << new_guid << "."; | |
| 930 } else { | |
| 931 DeleteEntry(entry); | |
| 932 } | |
| 933 | |
| 934 const base::DictionaryValue* user_settings = | |
| 935 ui_data ? ui_data->user_settings() : NULL; | |
| 936 | |
| 937 // Write the new configuration. | |
| 938 CreateAndWriteNewShillConfiguration(new_guid, *new_policy, user_settings); | |
| 939 remaining_policies_.erase(new_guid); | |
| 940 } | |
| 941 } else if (was_managed) { | |
| 942 VLOG(1) << "Removing configuration previously managed by policy " | |
| 943 << old_guid << ", because the policy was removed."; | |
| 944 | |
| 945 // Remove the entry, because the network was managed but isn't anymore. | |
| 946 // Note: An alternative might be to preserve the user settings, but it's | |
| 947 // unclear which values originating the policy should be removed. | |
| 948 DeleteEntry(entry); | |
| 949 } else { | |
| 950 VLOG(2) << "Ignore unmanaged entry."; | |
| 951 | |
| 952 // The entry wasn't managed and doesn't match any current policy. Thus | |
| 953 // leave it as it is. | |
| 954 } | |
| 955 } | |
| 956 | |
| 957 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::DeleteEntry( | |
| 958 const std::string& entry) { | |
| 959 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( | |
| 960 dbus::ObjectPath(profile_.path), | |
| 961 entry, | |
| 962 base::Bind(&base::DoNothing), | |
| 963 base::Bind(&LogErrorMessage, FROM_HERE)); | |
| 964 } | |
| 965 | |
| 966 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: | |
| 967 CreateAndWriteNewShillConfiguration( | |
| 968 const std::string& guid, | |
| 969 const base::DictionaryValue& policy, | |
| 970 const base::DictionaryValue* user_settings) { | |
| 971 scoped_ptr<base::DictionaryValue> shill_dictionary = | |
| 972 CreateShillConfiguration(profile_, guid, &policy, user_settings); | |
| 973 handler_->network_configuration_handler()->CreateConfiguration( | |
| 974 *shill_dictionary, | |
| 975 base::Bind(&ManagedNetworkConfigurationHandlerImpl::OnPolicyApplied, | |
| 976 handler_), | |
| 977 base::Bind(&LogErrorWithDict, FROM_HERE)); | |
| 978 } | |
| 979 | |
| 980 ManagedNetworkConfigurationHandlerImpl::PolicyApplicator::~PolicyApplicator() { | |
| 981 ApplyRemainingPolicies(); | |
| 982 STLDeleteValues(&all_policies_); | |
| 983 } | |
| 984 | |
| 985 void ManagedNetworkConfigurationHandlerImpl::PolicyApplicator:: | |
| 986 ApplyRemainingPolicies() { | |
| 987 if (!handler_) { | |
| 988 LOG(WARNING) << "Handler destructed during policy application to profile " | |
| 989 << profile_.ToDebugString(); | |
| 990 return; | |
| 991 } | |
| 992 | |
| 993 if (remaining_policies_.empty()) | |
| 994 return; | |
| 995 | |
| 996 VLOG(2) << "Create new managed network configurations in profile" | |
| 997 << profile_.ToDebugString() << "."; | |
| 998 // All profile entries were compared to policies. |remaining_policies_| | |
| 999 // contains all modified policies that didn't match any entry. For these | |
| 1000 // remaining policies, new configurations have to be created. | |
| 1001 | |
| 1002 for (std::set<std::string>::iterator it = remaining_policies_.begin(); | |
| 1003 it != remaining_policies_.end(); | |
| 1004 ++it) { | |
| 1005 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it); | |
| 1006 DCHECK(policy); | |
| 1007 | |
| 1008 VLOG(1) << "Creating new configuration managed by policy " << *it | |
| 1009 << " in profile " << profile_.ToDebugString() << "."; | |
| 1010 | |
| 1011 CreateAndWriteNewShillConfiguration( | |
| 1012 *it, *policy, NULL /* no user settings */); | |
| 1013 } | |
| 1014 } | |
| 1015 | |
| 1016 } // namespace chromeos | 561 } // namespace chromeos |
| OLD | NEW |