| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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.h" | 5 #include "chromeos/network/managed_network_configuration_handler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 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/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/string_util.h" |
| 18 #include "base/values.h" | 19 #include "base/values.h" |
| 19 #include "chromeos/dbus/dbus_method_call_status.h" | 20 #include "chromeos/dbus/dbus_method_call_status.h" |
| 20 #include "chromeos/dbus/dbus_thread_manager.h" | 21 #include "chromeos/dbus/dbus_thread_manager.h" |
| 21 #include "chromeos/dbus/shill_manager_client.h" | 22 #include "chromeos/dbus/shill_manager_client.h" |
| 22 #include "chromeos/dbus/shill_profile_client.h" | 23 #include "chromeos/dbus/shill_profile_client.h" |
| 23 #include "chromeos/dbus/shill_service_client.h" | 24 #include "chromeos/dbus/shill_service_client.h" |
| 24 #include "chromeos/network/network_configuration_handler.h" | 25 #include "chromeos/network/network_configuration_handler.h" |
| 25 #include "chromeos/network/network_event_log.h" | 26 #include "chromeos/network/network_event_log.h" |
| 26 #include "chromeos/network/network_handler_callbacks.h" | 27 #include "chromeos/network/network_handler_callbacks.h" |
| 28 #include "chromeos/network/network_profile.h" |
| 29 #include "chromeos/network/network_profile_handler.h" |
| 27 #include "chromeos/network/network_state.h" | 30 #include "chromeos/network/network_state.h" |
| 28 #include "chromeos/network/network_state_handler.h" | 31 #include "chromeos/network/network_state_handler.h" |
| 29 #include "chromeos/network/network_ui_data.h" | 32 #include "chromeos/network/network_ui_data.h" |
| 30 #include "chromeos/network/onc/onc_constants.h" | 33 #include "chromeos/network/onc/onc_constants.h" |
| 31 #include "chromeos/network/onc/onc_merger.h" | 34 #include "chromeos/network/onc/onc_merger.h" |
| 32 #include "chromeos/network/onc/onc_signature.h" | 35 #include "chromeos/network/onc/onc_signature.h" |
| 33 #include "chromeos/network/onc/onc_translator.h" | 36 #include "chromeos/network/onc/onc_translator.h" |
| 34 #include "chromeos/network/onc/onc_utils.h" | 37 #include "chromeos/network/onc/onc_utils.h" |
| 35 #include "chromeos/network/onc/onc_validator.h" | 38 #include "chromeos/network/onc/onc_validator.h" |
| 36 #include "dbus/object_path.h" | 39 #include "dbus/object_path.h" |
| 37 #include "third_party/cros_system_api/dbus/service_constants.h" | 40 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 38 | 41 |
| 39 namespace chromeos { | 42 namespace chromeos { |
| 40 | 43 |
| 41 namespace { | 44 namespace { |
| 42 | 45 |
| 43 ManagedNetworkConfigurationHandler* g_configuration_handler_instance = NULL; | |
| 44 | |
| 45 const char kLogModule[] = "ManagedNetworkConfigurationHandler"; | 46 const char kLogModule[] = "ManagedNetworkConfigurationHandler"; |
| 46 | 47 |
| 47 // These are error strings used for error callbacks. None of these error | 48 // These are error strings used for error callbacks. None of these error |
| 48 // messages are user-facing: they should only appear in logs. | 49 // messages are user-facing: they should only appear in logs. |
| 49 const char kInvalidUserSettingsMessage[] = "User settings are invalid."; | 50 const char kInvalidUserSettingsMessage[] = "User settings are invalid."; |
| 50 const char kInvalidUserSettings[] = "Error.InvalidUserSettings"; | 51 const char kInvalidUserSettings[] = "Error.InvalidUserSettings"; |
| 51 const char kNetworkAlreadyConfiguredMessage[] = | 52 const char kNetworkAlreadyConfiguredMessage[] = |
| 52 "Network is already configured."; | 53 "Network is already configured."; |
| 53 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured"; | 54 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured"; |
| 54 const char kPoliciesNotInitializedMessage[] = "Policies not initialized."; | 55 const char kPoliciesNotInitializedMessage[] = "Policies not initialized."; |
| 55 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized"; | 56 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized"; |
| 56 const char kServicePath[] = "servicePath"; | 57 const char kProfileNotInitializedMessage[] = "Profile not initialized."; |
| 58 const char kProfileNotInitialized[] = "Error.ProflieNotInitialized"; |
| 57 const char kSetOnUnconfiguredNetworkMessage[] = | 59 const char kSetOnUnconfiguredNetworkMessage[] = |
| 58 "Unable to modify properties of an unconfigured network."; | 60 "Unable to modify properties of an unconfigured network."; |
| 59 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; | 61 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; |
| 60 const char kUIDataErrorMessage[] = "UI data contains errors."; | 62 const char kUnknownProfilePathMessage[] = "Profile path is unknown."; |
| 61 const char kUIDataError[] = "Error.UIData"; | 63 const char kUnknownProfilePath[] = "Error.UnknownProfilePath"; |
| 62 const char kUnknownServicePathMessage[] = "Service path is unknown."; | 64 const char kUnknownServicePathMessage[] = "Service path is unknown."; |
| 63 const char kUnknownServicePath[] = "Error.UnknownServicePath"; | 65 const char kUnknownServicePath[] = "Error.UnknownServicePath"; |
| 64 | 66 |
| 65 enum ProfileType { | |
| 66 PROFILE_NONE, // Not in any profile. | |
| 67 PROFILE_SHARED, // In the shared profile, shared by all users on device. | |
| 68 PROFILE_USER // In the user profile, not visible to other users. | |
| 69 }; | |
| 70 | |
| 71 const char kSharedProfilePath[] = "/profile/default"; | |
| 72 const char kUserProfilePath[] = "/profile/chronos/shill"; | |
| 73 | |
| 74 // This fake credential contains a random postfix which is extremly unlikely to | 67 // This fake credential contains a random postfix which is extremly unlikely to |
| 75 // be used by any user. | 68 // be used by any user. |
| 76 const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x"; | 69 const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x"; |
| 77 | 70 |
| 71 std::string ToDebugString(onc::ONCSource source, |
| 72 const std::string& userhash) { |
| 73 return source == onc::ONC_SOURCE_USER_POLICY ? |
| 74 ("user policy of " + userhash) : "device policy"; |
| 75 } |
| 76 |
| 78 void RunErrorCallback(const std::string& service_path, | 77 void RunErrorCallback(const std::string& service_path, |
| 79 const std::string& error_name, | 78 const std::string& error_name, |
| 80 const std::string& error_message, | 79 const std::string& error_message, |
| 81 const network_handler::ErrorCallback& error_callback) { | 80 const network_handler::ErrorCallback& error_callback) { |
| 82 network_event_log::AddEntry(kLogModule, error_name, error_message); | 81 network_event_log::AddEntry(kLogModule, error_name, error_message); |
| 83 error_callback.Run( | 82 error_callback.Run( |
| 84 error_name, | 83 error_name, |
| 85 make_scoped_ptr( | 84 make_scoped_ptr( |
| 86 network_handler::CreateErrorData(service_path, | 85 network_handler::CreateErrorData(service_path, |
| 87 error_name, | 86 error_name, |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 // value to overwrite whatever is stored in Shill. | 174 // value to overwrite whatever is stored in Shill. |
| 176 } | 175 } |
| 177 } | 176 } |
| 178 } | 177 } |
| 179 | 178 |
| 180 // Creates a Shill property dictionary from the given arguments. The resulting | 179 // Creates a Shill property dictionary from the given arguments. The resulting |
| 181 // dictionary will be sent to Shill by the caller. Depending on the profile | 180 // dictionary will be sent to Shill by the caller. Depending on the profile |
| 182 // path, |policy| is interpreted as the user or device policy and |settings| as | 181 // path, |policy| is interpreted as the user or device policy and |settings| as |
| 183 // the user or shared settings. | 182 // the user or shared settings. |
| 184 scoped_ptr<base::DictionaryValue> CreateShillConfiguration( | 183 scoped_ptr<base::DictionaryValue> CreateShillConfiguration( |
| 185 const std::string& profile_path, | 184 const NetworkProfile& profile, |
| 186 const std::string& guid, | 185 const std::string& guid, |
| 187 const base::DictionaryValue* policy, | 186 const base::DictionaryValue* policy, |
| 188 const base::DictionaryValue* settings) { | 187 const base::DictionaryValue* settings) { |
| 189 scoped_ptr<base::DictionaryValue> effective; | 188 scoped_ptr<base::DictionaryValue> effective; |
| 190 | |
| 191 onc::ONCSource onc_source; | 189 onc::ONCSource onc_source; |
| 192 if (policy) { | 190 if (policy) { |
| 193 if (profile_path == kSharedProfilePath) { | 191 if (profile.type() == NetworkProfile::TYPE_SHARED) { |
| 194 effective = onc::MergeSettingsAndPoliciesToEffective( | 192 effective = onc::MergeSettingsAndPoliciesToEffective( |
| 195 NULL, // no user policy | 193 NULL, // no user policy |
| 196 policy, // device policy | 194 policy, // device policy |
| 197 NULL, // no user settings | 195 NULL, // no user settings |
| 198 settings); // shared settings | 196 settings); // shared settings |
| 199 onc_source = onc::ONC_SOURCE_DEVICE_POLICY; | 197 onc_source = onc::ONC_SOURCE_DEVICE_POLICY; |
| 200 } else { | 198 } else if (profile.type() == NetworkProfile::TYPE_USER) { |
| 201 effective = onc::MergeSettingsAndPoliciesToEffective( | 199 effective = onc::MergeSettingsAndPoliciesToEffective( |
| 202 policy, // user policy | 200 policy, // user policy |
| 203 NULL, // no device policy | 201 NULL, // no device policy |
| 204 settings, // user settings | 202 settings, // user settings |
| 205 NULL); // no shared settings | 203 NULL); // no shared settings |
| 206 onc_source = onc::ONC_SOURCE_USER_POLICY; | 204 onc_source = onc::ONC_SOURCE_USER_POLICY; |
| 205 } else { |
| 206 NOTREACHED(); |
| 207 } | 207 } |
| 208 } else if (settings) { | 208 } else if (settings) { |
| 209 effective.reset(settings->DeepCopy()); | 209 effective.reset(settings->DeepCopy()); |
| 210 // TODO(pneubeck): change to source ONC_SOURCE_USER | 210 // TODO(pneubeck): change to source ONC_SOURCE_USER |
| 211 onc_source = onc::ONC_SOURCE_NONE; | 211 onc_source = onc::ONC_SOURCE_NONE; |
| 212 } else { | 212 } else { |
| 213 NOTREACHED(); | 213 NOTREACHED(); |
| 214 onc_source = onc::ONC_SOURCE_NONE; | 214 onc_source = onc::ONC_SOURCE_NONE; |
| 215 } | 215 } |
| 216 | 216 |
| 217 RemoveFakeCredentials(onc::kNetworkConfigurationSignature, | 217 RemoveFakeCredentials(onc::kNetworkConfigurationSignature, |
| 218 effective.get()); | 218 effective.get()); |
| 219 | 219 |
| 220 effective->SetStringWithoutPathExpansion(onc::network_config::kGUID, guid); | 220 effective->SetStringWithoutPathExpansion(onc::network_config::kGUID, guid); |
| 221 | 221 |
| 222 scoped_ptr<base::DictionaryValue> shill_dictionary( | 222 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 223 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | 223 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, |
| 224 *effective)); | 224 *effective)); |
| 225 | 225 |
| 226 shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty, | 226 shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty, |
| 227 profile_path); | 227 profile.path); |
| 228 | 228 |
| 229 scoped_ptr<NetworkUIData> ui_data; | 229 scoped_ptr<NetworkUIData> ui_data; |
| 230 if (policy) | 230 if (policy) |
| 231 ui_data = CreateUIDataFromONC(onc_source, *policy); | 231 ui_data = CreateUIDataFromONC(onc_source, *policy); |
| 232 else | 232 else |
| 233 ui_data.reset(new NetworkUIData()); | 233 ui_data.reset(new NetworkUIData()); |
| 234 | 234 |
| 235 if (settings) { | 235 if (settings) { |
| 236 // Shill doesn't know that sensitive data is contained in the UIData | 236 // Shill doesn't know that sensitive data is contained in the UIData |
| 237 // property and might write it into logs or other insecure places. Thus, we | 237 // property and might write it into logs or other insecure places. Thus, we |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 policy.GetStringWithoutPathExpansion(onc::wifi::kSSID, &policy_ssid); | 276 policy.GetStringWithoutPathExpansion(onc::wifi::kSSID, &policy_ssid); |
| 277 std::string network_ssid; | 277 std::string network_ssid; |
| 278 onc_network_part.GetStringWithoutPathExpansion(onc::wifi::kSSID, | 278 onc_network_part.GetStringWithoutPathExpansion(onc::wifi::kSSID, |
| 279 &network_ssid); | 279 &network_ssid); |
| 280 return (policy_ssid == network_ssid); | 280 return (policy_ssid == network_ssid); |
| 281 } | 281 } |
| 282 | 282 |
| 283 // Returns the policy of |policies| matching |onc_network_part|, if any | 283 // Returns the policy of |policies| matching |onc_network_part|, if any |
| 284 // exists. Returns NULL otherwise. | 284 // exists. Returns NULL otherwise. |
| 285 const base::DictionaryValue* FindMatchingPolicy( | 285 const base::DictionaryValue* FindMatchingPolicy( |
| 286 const ManagedNetworkConfigurationHandler::PolicyMap &policies, | 286 const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies, |
| 287 const base::DictionaryValue& onc_network_part) { | 287 const base::DictionaryValue& onc_network_part) { |
| 288 for (ManagedNetworkConfigurationHandler::PolicyMap::const_iterator it = | 288 for (ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it = |
| 289 policies.begin(); it != policies.end(); ++it) { | 289 policies.begin(); it != policies.end(); ++it) { |
| 290 if (IsPolicyMatching(*it->second, onc_network_part)) | 290 if (IsPolicyMatching(*it->second, onc_network_part)) |
| 291 return it->second; | 291 return it->second; |
| 292 } | 292 } |
| 293 return NULL; | 293 return NULL; |
| 294 } | 294 } |
| 295 | 295 |
| 296 const base::DictionaryValue* GetByGUID( |
| 297 const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies, |
| 298 const std::string& guid) { |
| 299 ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it = |
| 300 policies.find(guid); |
| 301 if (it == policies.end()) |
| 302 return NULL; |
| 303 return it->second; |
| 304 } |
| 305 |
| 296 void TranslatePropertiesToOncAndRunCallback( | 306 void TranslatePropertiesToOncAndRunCallback( |
| 297 const network_handler::DictionaryResultCallback& callback, | 307 const network_handler::DictionaryResultCallback& callback, |
| 298 const std::string& service_path, | 308 const std::string& service_path, |
| 299 const base::DictionaryValue& shill_properties) { | 309 const base::DictionaryValue& shill_properties) { |
| 300 scoped_ptr<base::DictionaryValue> onc_network( | 310 scoped_ptr<base::DictionaryValue> onc_network( |
| 301 onc::TranslateShillServiceToONCPart( | 311 onc::TranslateShillServiceToONCPart( |
| 302 shill_properties, | 312 shill_properties, |
| 303 &onc::kNetworkWithStateSignature)); | 313 &onc::kNetworkWithStateSignature)); |
| 304 callback.Run(service_path, *onc_network); | 314 callback.Run(service_path, *onc_network); |
| 305 } | 315 } |
| 306 | 316 |
| 307 } // namespace | 317 } // namespace |
| 308 | 318 |
| 319 static ManagedNetworkConfigurationHandler* |
| 320 g_configuration_handler_instance = NULL; |
| 321 |
| 309 // static | 322 // static |
| 310 void ManagedNetworkConfigurationHandler::Initialize() { | 323 void ManagedNetworkConfigurationHandler::Initialize( |
| 324 NetworkProfileHandler* profile_handler) { |
| 311 CHECK(!g_configuration_handler_instance); | 325 CHECK(!g_configuration_handler_instance); |
| 312 g_configuration_handler_instance = new ManagedNetworkConfigurationHandler; | 326 g_configuration_handler_instance = |
| 327 new ManagedNetworkConfigurationHandler(profile_handler); |
| 313 } | 328 } |
| 314 | 329 |
| 315 // static | 330 // static |
| 316 bool ManagedNetworkConfigurationHandler::IsInitialized() { | 331 bool ManagedNetworkConfigurationHandler::IsInitialized() { |
| 317 return g_configuration_handler_instance; | 332 return g_configuration_handler_instance; |
| 318 } | 333 } |
| 319 | 334 |
| 320 // static | 335 // static |
| 321 void ManagedNetworkConfigurationHandler::Shutdown() { | 336 void ManagedNetworkConfigurationHandler::Shutdown() { |
| 322 CHECK(g_configuration_handler_instance); | 337 CHECK(g_configuration_handler_instance); |
| 323 delete g_configuration_handler_instance; | 338 delete g_configuration_handler_instance; |
| 324 g_configuration_handler_instance = NULL; | 339 g_configuration_handler_instance = NULL; |
| 325 } | 340 } |
| 326 | 341 |
| 327 // static | 342 // static |
| 328 ManagedNetworkConfigurationHandler* ManagedNetworkConfigurationHandler::Get() { | 343 ManagedNetworkConfigurationHandler* ManagedNetworkConfigurationHandler::Get() { |
| 329 CHECK(g_configuration_handler_instance); | 344 CHECK(g_configuration_handler_instance); |
| 330 return g_configuration_handler_instance; | 345 return g_configuration_handler_instance; |
| 331 } | 346 } |
| 332 | 347 |
| 333 void ManagedNetworkConfigurationHandler::GetManagedProperties( | 348 void ManagedNetworkConfigurationHandler::GetManagedProperties( |
| 349 const std::string& userhash, |
| 334 const std::string& service_path, | 350 const std::string& service_path, |
| 335 const network_handler::DictionaryResultCallback& callback, | 351 const network_handler::DictionaryResultCallback& callback, |
| 336 const network_handler::ErrorCallback& error_callback) { | 352 const network_handler::ErrorCallback& error_callback) { |
| 337 if (!user_policies_initialized_ || !device_policies_initialized_) { | 353 if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) { |
| 338 RunErrorCallback(service_path, | 354 RunErrorCallback(service_path, |
| 339 kPoliciesNotInitialized, | 355 kPoliciesNotInitialized, |
| 340 kPoliciesNotInitializedMessage, | 356 kPoliciesNotInitializedMessage, |
| 341 error_callback); | 357 error_callback); |
| 342 return; | 358 return; |
| 343 } | 359 } |
| 344 NetworkConfigurationHandler::Get()->GetProperties( | 360 NetworkConfigurationHandler::Get()->GetProperties( |
| 345 service_path, | 361 service_path, |
| 346 base::Bind( | 362 base::Bind( |
| 347 &ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback, | 363 &ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback, |
| 348 weak_ptr_factory_.GetWeakPtr(), | 364 weak_ptr_factory_.GetWeakPtr(), |
| 349 callback, | 365 callback, |
| 350 error_callback), | 366 error_callback), |
| 351 error_callback); | 367 error_callback); |
| 352 } | 368 } |
| 353 | 369 |
| 354 void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback( | 370 void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback( |
| 355 const network_handler::DictionaryResultCallback& callback, | 371 const network_handler::DictionaryResultCallback& callback, |
| 356 const network_handler::ErrorCallback& error_callback, | 372 const network_handler::ErrorCallback& error_callback, |
| 357 const std::string& service_path, | 373 const std::string& service_path, |
| 358 const base::DictionaryValue& shill_properties) { | 374 const base::DictionaryValue& shill_properties) { |
| 359 std::string profile_path; | 375 std::string profile_path; |
| 360 ProfileType profile_type = PROFILE_NONE; | 376 shill_properties.GetStringWithoutPathExpansion(flimflam::kProfileProperty, |
| 361 if (shill_properties.GetStringWithoutPathExpansion( | 377 &profile_path); |
| 362 flimflam::kProfileProperty, &profile_path)) { | 378 const NetworkProfile* profile = |
| 363 if (profile_path == kSharedProfilePath) | 379 profile_handler_->GetProfileForPath(profile_path); |
| 364 profile_type = PROFILE_SHARED; | 380 if (!profile) { |
| 365 else if (!profile_path.empty()) | 381 VLOG(1) << "No or no known profile received for service " |
| 366 profile_type = PROFILE_USER; | 382 << service_path << "."; |
| 367 } else { | |
| 368 VLOG(1) << "No profile path for service " << service_path << "."; | |
| 369 } | 383 } |
| 370 | 384 |
| 371 scoped_ptr<NetworkUIData> ui_data = GetUIData(shill_properties); | 385 scoped_ptr<NetworkUIData> ui_data = GetUIData(shill_properties); |
| 372 | 386 |
| 373 const base::DictionaryValue* user_settings = NULL; | 387 const base::DictionaryValue* user_settings = NULL; |
| 374 const base::DictionaryValue* shared_settings = NULL; | 388 const base::DictionaryValue* shared_settings = NULL; |
| 375 | 389 |
| 376 if (ui_data) { | 390 if (ui_data && profile) { |
| 377 if (profile_type == PROFILE_SHARED) | 391 if (profile->type() == NetworkProfile::TYPE_SHARED) |
| 378 shared_settings = ui_data->user_settings(); | 392 shared_settings = ui_data->user_settings(); |
| 379 else if (profile_type == PROFILE_USER) | 393 else if (profile->type() == NetworkProfile::TYPE_USER) |
| 380 user_settings = ui_data->user_settings(); | 394 user_settings = ui_data->user_settings(); |
| 381 } else if (profile_type != PROFILE_NONE) { | 395 else |
| 396 NOTREACHED(); |
| 397 } else if (profile) { |
| 382 LOG(WARNING) << "Service " << service_path << " of profile " | 398 LOG(WARNING) << "Service " << service_path << " of profile " |
| 383 << profile_path << " contains no or no valid UIData."; | 399 << profile_path << " contains no or no valid UIData."; |
| 384 // TODO(pneubeck): add a conversion of user configured entries of old | 400 // TODO(pneubeck): add a conversion of user configured entries of old |
| 385 // ChromeOS versions. We will have to use a heuristic to determine which | 401 // ChromeOS versions. We will have to use a heuristic to determine which |
| 386 // properties _might_ be user configured. | 402 // properties _might_ be user configured. |
| 387 } | 403 } |
| 388 | 404 |
| 389 scoped_ptr<base::DictionaryValue> active_settings( | 405 scoped_ptr<base::DictionaryValue> active_settings( |
| 390 onc::TranslateShillServiceToONCPart( | 406 onc::TranslateShillServiceToONCPart( |
| 391 shill_properties, | 407 shill_properties, |
| 392 &onc::kNetworkWithStateSignature)); | 408 &onc::kNetworkWithStateSignature)); |
| 393 | 409 |
| 394 std::string guid; | 410 std::string guid; |
| 395 active_settings->GetStringWithoutPathExpansion(onc::network_config::kGUID, | 411 active_settings->GetStringWithoutPathExpansion(onc::network_config::kGUID, |
| 396 &guid); | 412 &guid); |
| 397 | 413 |
| 398 const base::DictionaryValue* user_policy = NULL; | 414 const base::DictionaryValue* user_policy = NULL; |
| 399 const base::DictionaryValue* device_policy = NULL; | 415 const base::DictionaryValue* device_policy = NULL; |
| 400 if (!guid.empty()) { | 416 if (!guid.empty() && profile) { |
| 401 // We already checked that the policies were initialized. No need to do that | 417 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile); |
| 402 // again. | 418 if (!policies) { |
| 403 if (profile_type == PROFILE_SHARED) | 419 RunErrorCallback(service_path, |
| 404 device_policy = device_policies_by_guid_[guid]; | 420 kPoliciesNotInitialized, |
| 405 else if (profile_type == PROFILE_USER) | 421 kPoliciesNotInitializedMessage, |
| 406 user_policy = user_policies_by_guid_[guid]; | 422 error_callback); |
| 423 return; |
| 424 } |
| 425 const base::DictionaryValue* policy = GetByGUID(*policies, guid); |
| 426 if (profile->type() == NetworkProfile::TYPE_SHARED) |
| 427 device_policy = policy; |
| 428 else if (profile->type() == NetworkProfile::TYPE_USER) |
| 429 user_policy = policy; |
| 430 else |
| 431 NOTREACHED(); |
| 407 } | 432 } |
| 408 | 433 |
| 409 // This call also removes credentials from policies. | 434 // This call also removes credentials from policies. |
| 410 scoped_ptr<base::DictionaryValue> augmented_properties = | 435 scoped_ptr<base::DictionaryValue> augmented_properties = |
| 411 onc::MergeSettingsAndPoliciesToAugmented( | 436 onc::MergeSettingsAndPoliciesToAugmented( |
| 412 onc::kNetworkConfigurationSignature, | 437 onc::kNetworkConfigurationSignature, |
| 413 user_policy, | 438 user_policy, |
| 414 device_policy, | 439 device_policy, |
| 415 user_settings, | 440 user_settings, |
| 416 shared_settings, | 441 shared_settings, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 // TODO(pneubeck): create an initial configuration in this case. As for | 474 // TODO(pneubeck): create an initial configuration in this case. As for |
| 450 // CreateConfiguration, user settings from older ChromeOS versions have to | 475 // CreateConfiguration, user settings from older ChromeOS versions have to |
| 451 // determined here. | 476 // determined here. |
| 452 RunErrorCallback(service_path, | 477 RunErrorCallback(service_path, |
| 453 kSetOnUnconfiguredNetwork, | 478 kSetOnUnconfiguredNetwork, |
| 454 kSetOnUnconfiguredNetworkMessage, | 479 kSetOnUnconfiguredNetworkMessage, |
| 455 error_callback); | 480 error_callback); |
| 456 return; | 481 return; |
| 457 } | 482 } |
| 458 | 483 |
| 484 const std::string& profile_path = state->profile_path(); |
| 485 const NetworkProfile *profile = |
| 486 profile_handler_->GetProfileForPath(profile_path); |
| 487 if (!profile) { |
| 488 RunErrorCallback(service_path, |
| 489 kUnknownProfilePath, |
| 490 kUnknownProfilePathMessage, |
| 491 error_callback); |
| 492 return; |
| 493 } |
| 494 |
| 495 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " |
| 496 << profile->ToDebugString(); |
| 497 |
| 498 const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile); |
| 499 if (!policies) { |
| 500 RunErrorCallback(service_path, |
| 501 kPoliciesNotInitialized, |
| 502 kPoliciesNotInitializedMessage, |
| 503 error_callback); |
| 504 return; |
| 505 } |
| 506 |
| 459 // Validate the ONC dictionary. We are liberal and ignore unknown field | 507 // Validate the ONC dictionary. We are liberal and ignore unknown field |
| 460 // names. User settings are only partial ONC, thus we ignore missing fields. | 508 // names. User settings are only partial ONC, thus we ignore missing fields. |
| 461 onc::Validator validator(false, // Ignore unknown fields. | 509 onc::Validator validator(false, // Ignore unknown fields. |
| 462 false, // Ignore invalid recommended field names. | 510 false, // Ignore invalid recommended field names. |
| 463 false, // Ignore missing fields. | 511 false, // Ignore missing fields. |
| 464 false); // This ONC does not comes from policy. | 512 false); // This ONC does not comes from policy. |
| 465 | 513 |
| 466 onc::Validator::Result validation_result; | 514 onc::Validator::Result validation_result; |
| 467 scoped_ptr<base::DictionaryValue> validated_user_settings = | 515 scoped_ptr<base::DictionaryValue> validated_user_settings = |
| 468 validator.ValidateAndRepairObject( | 516 validator.ValidateAndRepairObject( |
| 469 &onc::kNetworkConfigurationSignature, | 517 &onc::kNetworkConfigurationSignature, |
| 470 user_settings, | 518 user_settings, |
| 471 &validation_result); | 519 &validation_result); |
| 472 | 520 |
| 473 if (validation_result == onc::Validator::INVALID) { | 521 if (validation_result == onc::Validator::INVALID) { |
| 474 LOG(ERROR) << "ONC user settings are invalid and couldn't be repaired."; | |
| 475 RunErrorCallback(service_path, | 522 RunErrorCallback(service_path, |
| 476 kInvalidUserSettings, | 523 kInvalidUserSettings, |
| 477 kInvalidUserSettingsMessage, | 524 kInvalidUserSettingsMessage, |
| 478 error_callback); | 525 error_callback); |
| 479 return; | 526 return; |
| 480 } | 527 } |
| 481 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) | 528 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) |
| 482 LOG(WARNING) << "Validation of ONC user settings produced warnings."; | 529 LOG(WARNING) << "Validation of ONC user settings produced warnings."; |
| 483 | 530 |
| 484 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " | 531 const base::DictionaryValue* policy = GetByGUID(*policies, guid); |
| 485 << state->profile_path(); | |
| 486 | |
| 487 const PolicyMap* policies_by_guid = | |
| 488 GetPoliciesForProfile(state->profile_path()); | |
| 489 | |
| 490 if (!policies_by_guid) { | |
| 491 RunErrorCallback(service_path, | |
| 492 kPoliciesNotInitialized, | |
| 493 kPoliciesNotInitializedMessage, | |
| 494 error_callback); | |
| 495 return; | |
| 496 } | |
| 497 | |
| 498 const base::DictionaryValue* policy = NULL; | |
| 499 PolicyMap::const_iterator it = policies_by_guid->find(guid); | |
| 500 if (it != policies_by_guid->end()) | |
| 501 policy = it->second; | |
| 502 | |
| 503 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; | 532 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; |
| 504 | 533 |
| 505 scoped_ptr<base::DictionaryValue> shill_dictionary( | 534 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 506 CreateShillConfiguration(state->profile_path(), guid, policy, | 535 CreateShillConfiguration(*profile, guid, policy, &user_settings)); |
| 507 &user_settings)); | |
| 508 | 536 |
| 509 NetworkConfigurationHandler::Get()->SetProperties(service_path, | 537 NetworkConfigurationHandler::Get()->SetProperties(service_path, |
| 510 *shill_dictionary, | 538 *shill_dictionary, |
| 511 callback, | 539 callback, |
| 512 error_callback); | 540 error_callback); |
| 513 } | 541 } |
| 514 | 542 |
| 515 void ManagedNetworkConfigurationHandler::Connect( | 543 void ManagedNetworkConfigurationHandler::Connect( |
| 516 const std::string& service_path, | 544 const std::string& service_path, |
| 517 const base::Closure& callback, | 545 const base::Closure& callback, |
| 518 const network_handler::ErrorCallback& error_callback) const { | 546 const network_handler::ErrorCallback& error_callback) const { |
| 519 NetworkConfigurationHandler::Get()->Connect(service_path, | 547 NetworkConfigurationHandler::Get()->Connect(service_path, |
| 520 callback, | 548 callback, |
| 521 error_callback); | 549 error_callback); |
| 522 } | 550 } |
| 523 | 551 |
| 524 void ManagedNetworkConfigurationHandler::Disconnect( | 552 void ManagedNetworkConfigurationHandler::Disconnect( |
| 525 const std::string& service_path, | 553 const std::string& service_path, |
| 526 const base::Closure& callback, | 554 const base::Closure& callback, |
| 527 const network_handler::ErrorCallback& error_callback) const { | 555 const network_handler::ErrorCallback& error_callback) const { |
| 528 NetworkConfigurationHandler::Get()->Disconnect(service_path, | 556 NetworkConfigurationHandler::Get()->Disconnect(service_path, |
| 529 callback, | 557 callback, |
| 530 error_callback); | 558 error_callback); |
| 531 } | 559 } |
| 532 | 560 |
| 533 void ManagedNetworkConfigurationHandler::CreateConfiguration( | 561 void ManagedNetworkConfigurationHandler::CreateConfiguration( |
| 562 const std::string& userhash, |
| 534 const base::DictionaryValue& properties, | 563 const base::DictionaryValue& properties, |
| 535 const network_handler::StringResultCallback& callback, | 564 const network_handler::StringResultCallback& callback, |
| 536 const network_handler::ErrorCallback& error_callback) const { | 565 const network_handler::ErrorCallback& error_callback) const { |
| 537 std::string profile_path = kUserProfilePath; | 566 const GuidToPolicyMap* policies = GetPoliciesForUser(userhash); |
| 538 const PolicyMap* policies_by_guid = GetPoliciesForProfile(profile_path); | 567 if (!policies) { |
| 539 | |
| 540 if (!policies_by_guid) { | |
| 541 RunErrorCallback("", | 568 RunErrorCallback("", |
| 542 kPoliciesNotInitialized, | 569 kPoliciesNotInitialized, |
| 543 kPoliciesNotInitializedMessage, | 570 kPoliciesNotInitializedMessage, |
| 544 error_callback); | 571 error_callback); |
| 545 return; | 572 return; |
| 546 } | 573 } |
| 547 | 574 |
| 548 if (FindMatchingPolicy(*policies_by_guid, properties)) { | 575 if (FindMatchingPolicy(*policies, properties)) { |
| 549 RunErrorCallback("", | 576 RunErrorCallback("", |
| 550 kNetworkAlreadyConfigured, | 577 kNetworkAlreadyConfigured, |
| 551 kNetworkAlreadyConfiguredMessage, | 578 kNetworkAlreadyConfiguredMessage, |
| 552 error_callback); | 579 error_callback); |
| 553 } | 580 } |
| 554 | 581 |
| 582 const NetworkProfile* profile = |
| 583 profile_handler_->GetProfileForUserhash(userhash); |
| 584 if (!profile) { |
| 585 RunErrorCallback("", |
| 586 kProfileNotInitialized, |
| 587 kProfileNotInitializedMessage, |
| 588 error_callback); |
| 589 } |
| 590 |
| 555 // TODO(pneubeck): In case of WiFi, check that no other configuration for the | 591 // TODO(pneubeck): In case of WiFi, check that no other configuration for the |
| 556 // same {SSID, mode, security} exists. We don't support such multiple | 592 // same {SSID, mode, security} exists. We don't support such multiple |
| 557 // configurations, yet. | 593 // configurations, yet. |
| 558 | 594 |
| 559 // Generate a new GUID for this configuration. Ignore the maybe provided GUID | 595 // Generate a new GUID for this configuration. Ignore the maybe provided GUID |
| 560 // in |properties| as it is not our own and from an untrusted source. | 596 // in |properties| as it is not our own and from an untrusted source. |
| 561 std::string guid = base::GenerateGUID(); | 597 std::string guid = base::GenerateGUID(); |
| 562 | |
| 563 scoped_ptr<base::DictionaryValue> shill_dictionary( | 598 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 564 CreateShillConfiguration(profile_path, guid, NULL /*no policy*/, | 599 CreateShillConfiguration(*profile, guid, NULL /*no policy*/, |
| 565 &properties)); | 600 &properties)); |
| 566 | 601 |
| 567 NetworkConfigurationHandler::Get()->CreateConfiguration(*shill_dictionary, | 602 NetworkConfigurationHandler::Get()->CreateConfiguration(*shill_dictionary, |
| 568 callback, | 603 callback, |
| 569 error_callback); | 604 error_callback); |
| 570 } | 605 } |
| 571 | 606 |
| 572 void ManagedNetworkConfigurationHandler::RemoveConfiguration( | 607 void ManagedNetworkConfigurationHandler::RemoveConfiguration( |
| 573 const std::string& service_path, | 608 const std::string& service_path, |
| 574 const base::Closure& callback, | 609 const base::Closure& callback, |
| 575 const network_handler::ErrorCallback& error_callback) const { | 610 const network_handler::ErrorCallback& error_callback) const { |
| 576 NetworkConfigurationHandler::Get()->RemoveConfiguration(service_path, | 611 NetworkConfigurationHandler::Get()->RemoveConfiguration(service_path, |
| 577 callback, | 612 callback, |
| 578 error_callback); | 613 error_callback); |
| 579 } | 614 } |
| 580 | 615 |
| 581 // This class compares (entry point is Run()) |modified_policies| with the | 616 // This class compares (entry point is Run()) |modified_policies| with the |
| 582 // existing entries in the provided Shill profile |profile|. It fetches all | 617 // existing entries in the provided Shill profile |profile|. It fetches all |
| 583 // entries in parallel (GetProfileProperties), compares each entry with the | 618 // entries in parallel (GetProfileProperties), compares each entry with the |
| 584 // current policies (GetEntry) and adds all missing policies | 619 // current policies (GetEntry) and adds all missing policies |
| 585 // (~PolicyApplicator). | 620 // (~PolicyApplicator). |
| 586 class ManagedNetworkConfigurationHandler::PolicyApplicator | 621 class ManagedNetworkConfigurationHandler::PolicyApplicator |
| 587 : public base::RefCounted<PolicyApplicator> { | 622 : public base::RefCounted<PolicyApplicator> { |
| 588 public: | 623 public: |
| 589 typedef ManagedNetworkConfigurationHandler::PolicyMap PolicyMap; | 624 typedef ManagedNetworkConfigurationHandler::GuidToPolicyMap GuidToPolicyMap; |
| 590 | 625 |
| 591 // |modified_policies| must not be NULL and will be empty afterwards. | 626 // |modified_policies| must not be NULL and will be empty afterwards. |
| 592 PolicyApplicator(base::WeakPtr<ManagedNetworkConfigurationHandler> handler, | 627 PolicyApplicator(base::WeakPtr<ManagedNetworkConfigurationHandler> handler, |
| 593 const std::string& profile, | 628 const NetworkProfile& profile, |
| 594 std::set<std::string>* modified_policies) | 629 std::set<std::string>* modified_policies) |
| 595 : handler_(handler), | 630 : handler_(handler), |
| 596 profile_path_(profile) { | 631 profile_(profile) { |
| 597 remaining_policies_.swap(*modified_policies); | 632 remaining_policies_.swap(*modified_policies); |
| 598 } | 633 } |
| 599 | 634 |
| 600 void Run() { | 635 void Run() { |
| 601 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( | 636 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( |
| 602 dbus::ObjectPath(profile_path_), | 637 dbus::ObjectPath(profile_.path), |
| 603 base::Bind(&PolicyApplicator::GetProfileProperties, this), | 638 base::Bind(&PolicyApplicator::GetProfileProperties, this), |
| 604 base::Bind(&LogErrorMessage, FROM_HERE)); | 639 base::Bind(&LogErrorMessage, FROM_HERE)); |
| 605 } | 640 } |
| 606 | 641 |
| 607 private: | 642 private: |
| 608 friend class base::RefCounted<PolicyApplicator>; | 643 friend class base::RefCounted<PolicyApplicator>; |
| 609 | 644 |
| 610 void GetProfileProperties(const base::DictionaryValue& profile_properties) { | 645 void GetProfileProperties(const base::DictionaryValue& profile_properties) { |
| 611 if (!handler_) { | 646 if (!handler_) { |
| 612 LOG(WARNING) << "Handler destructed during policy application to profile " | 647 LOG(WARNING) << "Handler destructed during policy application to profile " |
| 613 << profile_path_; | 648 << profile_.ToDebugString(); |
| 614 return; | 649 return; |
| 615 } | 650 } |
| 616 | 651 |
| 617 VLOG(2) << "Received properties for profile " << profile_path_; | 652 VLOG(2) << "Received properties for profile " << profile_.ToDebugString(); |
| 618 const base::ListValue* entries = NULL; | 653 const base::ListValue* entries = NULL; |
| 619 if (!profile_properties.GetListWithoutPathExpansion( | 654 if (!profile_properties.GetListWithoutPathExpansion( |
| 620 flimflam::kEntriesProperty, &entries)) { | 655 flimflam::kEntriesProperty, &entries)) { |
| 621 LOG(ERROR) << "Profile " << profile_path_ | 656 LOG(ERROR) << "Profile " << profile_.ToDebugString() |
| 622 << " doesn't contain the property " | 657 << " doesn't contain the property " |
| 623 << flimflam::kEntriesProperty; | 658 << flimflam::kEntriesProperty; |
| 624 return; | 659 return; |
| 625 } | 660 } |
| 626 | 661 |
| 627 for (base::ListValue::const_iterator it = entries->begin(); | 662 for (base::ListValue::const_iterator it = entries->begin(); |
| 628 it != entries->end(); ++it) { | 663 it != entries->end(); ++it) { |
| 629 std::string entry; | 664 std::string entry; |
| 630 (*it)->GetAsString(&entry); | 665 (*it)->GetAsString(&entry); |
| 631 | 666 |
| 632 std::ostringstream entry_failure; | 667 std::ostringstream entry_failure; |
| 633 DBusThreadManager::Get()->GetShillProfileClient()->GetEntry( | 668 DBusThreadManager::Get()->GetShillProfileClient()->GetEntry( |
| 634 dbus::ObjectPath(profile_path_), | 669 dbus::ObjectPath(profile_.path), |
| 635 entry, | 670 entry, |
| 636 base::Bind(&PolicyApplicator::GetEntry, this, entry), | 671 base::Bind(&PolicyApplicator::GetEntry, this, entry), |
| 637 base::Bind(&LogErrorMessage, FROM_HERE)); | 672 base::Bind(&LogErrorMessage, FROM_HERE)); |
| 638 } | 673 } |
| 639 } | 674 } |
| 640 | 675 |
| 641 void GetEntry(const std::string& entry, | 676 void GetEntry(const std::string& entry, |
| 642 const base::DictionaryValue& entry_properties) { | 677 const base::DictionaryValue& entry_properties) { |
| 643 if (!handler_) { | 678 if (!handler_) { |
| 644 LOG(WARNING) << "Handler destructed during policy application to profile " | 679 LOG(WARNING) << "Handler destructed during policy application to profile " |
| 645 << profile_path_; | 680 << profile_.ToDebugString(); |
| 646 return; | 681 return; |
| 647 } | 682 } |
| 648 | 683 |
| 649 VLOG(2) << "Received properties for entry " << entry << " of profile " | 684 VLOG(2) << "Received properties for entry " << entry << " of profile " |
| 650 << profile_path_; | 685 << profile_.ToDebugString(); |
| 651 | 686 |
| 652 scoped_ptr<base::DictionaryValue> onc_part( | 687 scoped_ptr<base::DictionaryValue> onc_part( |
| 653 onc::TranslateShillServiceToONCPart( | 688 onc::TranslateShillServiceToONCPart( |
| 654 entry_properties, | 689 entry_properties, |
| 655 &onc::kNetworkWithStateSignature)); | 690 &onc::kNetworkWithStateSignature)); |
| 656 | 691 |
| 657 std::string old_guid; | 692 std::string old_guid; |
| 658 if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID, | 693 if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID, |
| 659 &old_guid)) { | 694 &old_guid)) { |
| 660 LOG(WARNING) << "Entry " << entry << " of profile " << profile_path_ | 695 LOG(WARNING) << "Entry " << entry << " of profile " |
| 661 << " doesn't contain a GUID."; | 696 << profile_.ToDebugString() << " doesn't contain a GUID."; |
| 662 // This might be an entry of an older ChromeOS version. Assume it to be | 697 // This might be an entry of an older ChromeOS version. Assume it to be |
| 663 // unmanaged. | 698 // unmanaged. |
| 664 return; | 699 return; |
| 665 } | 700 } |
| 666 | 701 |
| 667 scoped_ptr<NetworkUIData> ui_data = GetUIData(entry_properties); | 702 scoped_ptr<NetworkUIData> ui_data = GetUIData(entry_properties); |
| 668 if (!ui_data) { | 703 if (!ui_data) { |
| 669 VLOG(1) << "Entry " << entry << " of profile " << profile_path_ | 704 VLOG(1) << "Entry " << entry << " of profile " |
| 705 << profile_.ToDebugString() |
| 670 << " contains no or no valid UIData."; | 706 << " contains no or no valid UIData."; |
| 671 // This might be an entry of an older ChromeOS version. Assume it to be | 707 // This might be an entry of an older ChromeOS version. Assume it to be |
| 672 // unmanaged. | 708 // unmanaged. |
| 673 return; | 709 return; |
| 674 } | 710 } |
| 675 | 711 |
| 676 bool was_managed = | 712 bool was_managed = |
| 677 (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || | 713 (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || |
| 678 ui_data->onc_source() == onc::ONC_SOURCE_USER_POLICY); | 714 ui_data->onc_source() == onc::ONC_SOURCE_USER_POLICY); |
| 679 | 715 |
| 680 // The relevant policy must have been initialized, otherwise we hadn't Run | 716 // The relevant policy must have been initialized, otherwise we hadn't Run |
| 681 // this PolicyApplicator. | 717 // this PolicyApplicator. |
| 682 const PolicyMap& policies_by_guid = | 718 const GuidToPolicyMap& policies = |
| 683 *handler_->GetPoliciesForProfile(profile_path_); | 719 *handler_->GetPoliciesForProfile(profile_); |
| 684 | 720 |
| 685 const base::DictionaryValue* new_policy = NULL; | 721 const base::DictionaryValue* new_policy = NULL; |
| 686 if (was_managed) { | 722 if (was_managed) { |
| 687 // If we have a GUID that might match a current policy, do a lookup using | 723 // If we have a GUID that might match a current policy, do a lookup using |
| 688 // that GUID at first. In particular this is necessary, as some networks | 724 // that GUID at first. In particular this is necessary, as some networks |
| 689 // can't be matched to policies by properties (e.g. VPN). | 725 // can't be matched to policies by properties (e.g. VPN). |
| 690 PolicyMap::const_iterator it = policies_by_guid.find(old_guid); | 726 new_policy = GetByGUID(policies, old_guid); |
| 691 if (it != policies_by_guid.end()) | |
| 692 new_policy = it->second; | |
| 693 } | 727 } |
| 694 | 728 |
| 695 if (!new_policy) { | 729 if (!new_policy) { |
| 696 // If we didn't find a policy by GUID, still a new policy might match. | 730 // If we didn't find a policy by GUID, still a new policy might match. |
| 697 new_policy = FindMatchingPolicy(policies_by_guid, *onc_part); | 731 new_policy = FindMatchingPolicy(policies, *onc_part); |
| 698 } | 732 } |
| 699 | 733 |
| 700 if (new_policy) { | 734 if (new_policy) { |
| 701 std::string new_guid; | 735 std::string new_guid; |
| 702 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID, | 736 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID, |
| 703 &new_guid); | 737 &new_guid); |
| 704 | 738 |
| 705 VLOG_IF(1, was_managed && old_guid != new_guid) | 739 VLOG_IF(1, was_managed && old_guid != new_guid) |
| 706 << "Updating configuration previously managed by policy " << old_guid | 740 << "Updating configuration previously managed by policy " << old_guid |
| 707 << " with new policy " << new_guid << "."; | 741 << " with new policy " << new_guid << "."; |
| 708 VLOG_IF(1, !was_managed) | 742 VLOG_IF(1, !was_managed) |
| 709 << "Applying policy " << new_guid << " to previously unmanaged " | 743 << "Applying policy " << new_guid << " to previously unmanaged " |
| 710 << "configuration."; | 744 << "configuration."; |
| 711 | 745 |
| 712 if (old_guid == new_guid && | 746 if (old_guid == new_guid && |
| 713 remaining_policies_.find(new_guid) == remaining_policies_.end()) { | 747 remaining_policies_.find(new_guid) == remaining_policies_.end()) { |
| 714 VLOG(1) << "Not updating existing managed configuration with guid " | 748 VLOG(1) << "Not updating existing managed configuration with guid " |
| 715 << new_guid << " because the policy didn't change."; | 749 << new_guid << " because the policy didn't change."; |
| 716 } else { | 750 } else { |
| 717 VLOG_IF(1, old_guid == new_guid) | 751 VLOG_IF(1, old_guid == new_guid) |
| 718 << "Updating previously managed configuration with the updated " | 752 << "Updating previously managed configuration with the updated " |
| 719 << "policy " << new_guid << "."; | 753 << "policy " << new_guid << "."; |
| 720 | 754 |
| 721 // Update the existing configuration with the maybe changed | 755 // Update the existing configuration with the maybe changed |
| 722 // policy. Thereby the GUID might change. | 756 // policy. Thereby the GUID might change. |
| 723 scoped_ptr<base::DictionaryValue> shill_dictionary = | 757 scoped_ptr<base::DictionaryValue> shill_dictionary = |
| 724 CreateShillConfiguration(profile_path_, new_guid, new_policy, | 758 CreateShillConfiguration(profile_, new_guid, new_policy, |
| 725 ui_data->user_settings()); | 759 ui_data->user_settings()); |
| 726 NetworkConfigurationHandler::Get()->CreateConfiguration( | 760 NetworkConfigurationHandler::Get()->CreateConfiguration( |
| 727 *shill_dictionary, | 761 *shill_dictionary, |
| 728 base::Bind(&IgnoreString), | 762 base::Bind(&IgnoreString), |
| 729 base::Bind(&LogErrorWithDict, FROM_HERE)); | 763 base::Bind(&LogErrorWithDict, FROM_HERE)); |
| 730 remaining_policies_.erase(new_guid); | 764 remaining_policies_.erase(new_guid); |
| 731 } | 765 } |
| 732 } else if (was_managed) { | 766 } else if (was_managed) { |
| 733 VLOG(1) << "Removing configuration previously managed by policy " | 767 VLOG(1) << "Removing configuration previously managed by policy " |
| 734 << old_guid << ", because the policy was removed."; | 768 << old_guid << ", because the policy was removed."; |
| 735 | 769 |
| 736 // Remove the entry, because the network was managed but isn't anymore. | 770 // Remove the entry, because the network was managed but isn't anymore. |
| 737 // Note: An alternative might be to preserve the user settings, but it's | 771 // Note: An alternative might be to preserve the user settings, but it's |
| 738 // unclear which values originating the policy should be removed. | 772 // unclear which values originating the policy should be removed. |
| 739 DeleteEntry(entry); | 773 DeleteEntry(entry); |
| 740 } else { | 774 } else { |
| 741 VLOG(2) << "Ignore unmanaged entry."; | 775 VLOG(2) << "Ignore unmanaged entry."; |
| 742 | 776 |
| 743 // The entry wasn't managed and doesn't match any current policy. Thus | 777 // The entry wasn't managed and doesn't match any current policy. Thus |
| 744 // leave it as it is. | 778 // leave it as it is. |
| 745 } | 779 } |
| 746 } | 780 } |
| 747 | 781 |
| 748 void DeleteEntry(const std::string& entry) { | 782 void DeleteEntry(const std::string& entry) { |
| 749 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( | 783 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( |
| 750 dbus::ObjectPath(profile_path_), | 784 dbus::ObjectPath(profile_.path), |
| 751 entry, | 785 entry, |
| 752 base::Bind(&base::DoNothing), | 786 base::Bind(&base::DoNothing), |
| 753 base::Bind(&LogErrorMessage, FROM_HERE)); | 787 base::Bind(&LogErrorMessage, FROM_HERE)); |
| 754 } | 788 } |
| 755 | 789 |
| 756 virtual ~PolicyApplicator() { | 790 virtual ~PolicyApplicator() { |
| 791 if (!handler_) { |
| 792 LOG(WARNING) << "Handler destructed during policy application to profile " |
| 793 << profile_.ToDebugString(); |
| 794 return; |
| 795 } |
| 796 |
| 757 if (remaining_policies_.empty()) | 797 if (remaining_policies_.empty()) |
| 758 return; | 798 return; |
| 759 | 799 |
| 760 VLOG(2) << "Create new managed network configurations in profile" | 800 VLOG(2) << "Create new managed network configurations in profile" |
| 761 << profile_path_ << "."; | 801 << profile_.ToDebugString() << "."; |
| 762 // All profile entries were compared to policies. |configureGUIDs_| contains | 802 // All profile entries were compared to policies. |configureGUIDs_| contains |
| 763 // all matched policies. From the remainder of policies, new configurations | 803 // all matched policies. From the remainder of policies, new configurations |
| 764 // have to be created. | 804 // have to be created. |
| 765 | 805 |
| 766 // The relevant policy must have been initialized, otherwise we hadn't Run | 806 // The relevant policy must have been initialized, otherwise we hadn't Run |
| 767 // this PolicyApplicator. | 807 // this PolicyApplicator. |
| 768 const PolicyMap& policies_by_guid = | 808 const GuidToPolicyMap& policies = |
| 769 *handler_->GetPoliciesForProfile(profile_path_); | 809 *handler_->GetPoliciesForProfile(profile_); |
| 770 | 810 |
| 771 for (std::set<std::string>::iterator it = remaining_policies_.begin(); | 811 for (std::set<std::string>::iterator it = remaining_policies_.begin(); |
| 772 it != remaining_policies_.end(); ++it) { | 812 it != remaining_policies_.end(); ++it) { |
| 773 PolicyMap::const_iterator policy_it = policies_by_guid.find(*it); | 813 const base::DictionaryValue* policy = GetByGUID(policies, *it); |
| 774 if (policy_it == policies_by_guid.end()) { | 814 if (!policy) { |
| 775 LOG(ERROR) << "Policy " << *it << " doesn't exist anymore."; | 815 LOG(ERROR) << "Policy " << *it << " doesn't exist anymore."; |
| 776 continue; | 816 continue; |
| 777 } | 817 } |
| 778 | 818 |
| 779 const base::DictionaryValue* policy = policy_it->second; | |
| 780 | |
| 781 VLOG(1) << "Creating new configuration managed by policy " << *it | 819 VLOG(1) << "Creating new configuration managed by policy " << *it |
| 782 << " in profile " << profile_path_ << "."; | 820 << " in profile " << profile_.ToDebugString() << "."; |
| 783 | 821 |
| 784 scoped_ptr<base::DictionaryValue> shill_dictionary = | 822 scoped_ptr<base::DictionaryValue> shill_dictionary = |
| 785 CreateShillConfiguration(profile_path_, *it, policy, NULL); | 823 CreateShillConfiguration(profile_, *it, policy, |
| 824 NULL /* no user settings */); |
| 786 NetworkConfigurationHandler::Get()->CreateConfiguration( | 825 NetworkConfigurationHandler::Get()->CreateConfiguration( |
| 787 *shill_dictionary, | 826 *shill_dictionary, |
| 788 base::Bind(&IgnoreString), | 827 base::Bind(&IgnoreString), |
| 789 base::Bind(&LogErrorWithDict, FROM_HERE)); | 828 base::Bind(&LogErrorWithDict, FROM_HERE)); |
| 790 } | 829 } |
| 791 } | 830 } |
| 792 | 831 |
| 793 std::set<std::string> remaining_policies_; | 832 std::set<std::string> remaining_policies_; |
| 794 base::WeakPtr<ManagedNetworkConfigurationHandler> handler_; | 833 base::WeakPtr<ManagedNetworkConfigurationHandler> handler_; |
| 795 std::string profile_path_; | 834 NetworkProfile profile_; |
| 796 | 835 |
| 797 DISALLOW_COPY_AND_ASSIGN(PolicyApplicator); | 836 DISALLOW_COPY_AND_ASSIGN(PolicyApplicator); |
| 798 }; | 837 }; |
| 799 | 838 |
| 800 void ManagedNetworkConfigurationHandler::SetPolicy( | 839 void ManagedNetworkConfigurationHandler::SetPolicy( |
| 801 onc::ONCSource onc_source, | 840 onc::ONCSource onc_source, |
| 841 const std::string& userhash, |
| 802 const base::ListValue& network_configs_onc) { | 842 const base::ListValue& network_configs_onc) { |
| 803 VLOG(1) << "Setting policies for ONC source " | 843 VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash) |
| 804 << onc::GetSourceAsString(onc_source) << "."; | 844 << "."; |
| 805 | 845 |
| 806 PolicyMap* policies; | 846 // |userhash| must be empty for device policies. |
| 807 std::string profile; | 847 DCHECK(onc_source != chromeos::onc::ONC_SOURCE_DEVICE_POLICY || |
| 808 if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY) { | 848 userhash.empty()); |
| 809 policies = &user_policies_by_guid_; | 849 GuidToPolicyMap& policies = policies_by_user_[userhash]; |
| 810 profile = kUserProfilePath; | |
| 811 user_policies_initialized_ = true; | |
| 812 } else { | |
| 813 policies = &device_policies_by_guid_; | |
| 814 profile = kSharedProfilePath; | |
| 815 device_policies_initialized_ = true; | |
| 816 } | |
| 817 | 850 |
| 818 PolicyMap old_policies; | 851 GuidToPolicyMap old_policies; |
| 819 policies->swap(old_policies); | 852 policies.swap(old_policies); |
| 820 | 853 |
| 821 // This stores all GUIDs of policies that have changed or are new. | 854 // This stores all GUIDs of policies that have changed or are new. |
| 822 std::set<std::string> modified_policies; | 855 std::set<std::string> modified_policies; |
| 823 | 856 |
| 824 for (base::ListValue::const_iterator it = network_configs_onc.begin(); | 857 for (base::ListValue::const_iterator it = network_configs_onc.begin(); |
| 825 it != network_configs_onc.end(); ++it) { | 858 it != network_configs_onc.end(); ++it) { |
| 826 const base::DictionaryValue* network = NULL; | 859 const base::DictionaryValue* network = NULL; |
| 827 (*it)->GetAsDictionary(&network); | 860 (*it)->GetAsDictionary(&network); |
| 828 DCHECK(network); | 861 DCHECK(network); |
| 829 | 862 |
| 830 std::string guid; | 863 std::string guid; |
| 831 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); | 864 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid); |
| 832 DCHECK(!guid.empty()); | 865 DCHECK(!guid.empty()); |
| 833 | 866 |
| 834 if (policies->count(guid) > 0) { | 867 if (policies.count(guid) > 0) { |
| 835 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) | 868 LOG(ERROR) << "ONC from " << ToDebugString(onc_source, userhash) |
| 836 << " contains several entries for the same GUID " | 869 << " contains several entries for the same GUID " |
| 837 << guid << "."; | 870 << guid << "."; |
| 838 delete (*policies)[guid]; | 871 delete policies[guid]; |
| 839 } | 872 } |
| 840 const base::DictionaryValue* new_entry = network->DeepCopy(); | 873 const base::DictionaryValue* new_entry = network->DeepCopy(); |
| 841 (*policies)[guid] = new_entry; | 874 policies[guid] = new_entry; |
| 842 | 875 |
| 843 const base::DictionaryValue* old_entry = old_policies[guid]; | 876 const base::DictionaryValue* old_entry = old_policies[guid]; |
| 844 if (!old_entry || !old_entry->Equals(new_entry)) | 877 if (!old_entry || !old_entry->Equals(new_entry)) |
| 845 modified_policies.insert(guid); | 878 modified_policies.insert(guid); |
| 846 } | 879 } |
| 847 | 880 |
| 848 STLDeleteValues(&old_policies); | 881 STLDeleteValues(&old_policies); |
| 849 | 882 |
| 883 const NetworkProfile* profile = |
| 884 profile_handler_->GetProfileForUserhash(userhash); |
| 885 if (!profile) { |
| 886 VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing " |
| 887 << "policy application."; |
| 888 return; |
| 889 } |
| 890 |
| 891 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator( |
| 892 weak_ptr_factory_.GetWeakPtr(), |
| 893 *profile, |
| 894 &modified_policies); |
| 895 applicator->Run(); |
| 896 } |
| 897 |
| 898 void ManagedNetworkConfigurationHandler::OnProfileAdded( |
| 899 const NetworkProfile& profile) { |
| 900 VLOG(1) << "Adding profile " << profile.ToDebugString() << "'."; |
| 901 |
| 902 const GuidToPolicyMap* policies = GetPoliciesForProfile(profile); |
| 903 if (!policies) { |
| 904 VLOG(1) << "The relevant policy is not initialized, " |
| 905 << "postponing policy application."; |
| 906 return; |
| 907 } |
| 908 |
| 909 std::set<std::string> policy_guids; |
| 910 for (GuidToPolicyMap::const_iterator it = policies->begin(); |
| 911 it != policies->end(); ++it) { |
| 912 policy_guids.insert(it->first); |
| 913 } |
| 914 |
| 850 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator( | 915 scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator( |
| 851 weak_ptr_factory_.GetWeakPtr(), | 916 weak_ptr_factory_.GetWeakPtr(), |
| 852 profile, | 917 profile, |
| 853 &modified_policies); | 918 &policy_guids); |
| 854 applicator->Run(); | 919 applicator->Run(); |
| 855 } | 920 } |
| 856 | 921 |
| 857 const ManagedNetworkConfigurationHandler::PolicyMap* | 922 void ManagedNetworkConfigurationHandler::OnProfileRemoved( |
| 858 ManagedNetworkConfigurationHandler::GetPoliciesForProfile( | 923 const NetworkProfile& profile) { |
| 859 const std::string& profile) const { | 924 // Nothing to do in this case. |
| 860 if (profile == kSharedProfilePath) { | |
| 861 if (device_policies_initialized_) | |
| 862 return &device_policies_by_guid_; | |
| 863 } else if (user_policies_initialized_) { | |
| 864 return &user_policies_by_guid_; | |
| 865 } | |
| 866 return NULL; | |
| 867 } | 925 } |
| 868 | 926 |
| 869 ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler() | 927 const ManagedNetworkConfigurationHandler::GuidToPolicyMap* |
| 870 : user_policies_initialized_(false), | 928 ManagedNetworkConfigurationHandler::GetPoliciesForUser( |
| 871 device_policies_initialized_(false), | 929 const std::string& userhash) const { |
| 930 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); |
| 931 if (it == policies_by_user_.end()) |
| 932 return NULL; |
| 933 return &it->second; |
| 934 } |
| 935 |
| 936 const ManagedNetworkConfigurationHandler::GuidToPolicyMap* |
| 937 ManagedNetworkConfigurationHandler::GetPoliciesForProfile( |
| 938 const NetworkProfile& profile) const { |
| 939 DCHECK(profile.type() != NetworkProfile::TYPE_SHARED || |
| 940 profile.userhash.empty()); |
| 941 return GetPoliciesForUser(profile.userhash); |
| 942 } |
| 943 |
| 944 ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler( |
| 945 NetworkProfileHandler* profile_handler) |
| 946 : profile_handler_(profile_handler), |
| 872 weak_ptr_factory_(this) { | 947 weak_ptr_factory_(this) { |
| 948 profile_handler_->AddObserver(this); |
| 873 } | 949 } |
| 874 | 950 |
| 875 ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() { | 951 ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() { |
| 876 STLDeleteValues(&user_policies_by_guid_); | 952 profile_handler_->RemoveObserver(this); |
| 877 STLDeleteValues(&device_policies_by_guid_); | 953 for (UserToPoliciesMap::iterator it = policies_by_user_.begin(); |
| 954 it != policies_by_user_.end(); ++it) { |
| 955 STLDeleteValues(&it->second); |
| 956 } |
| 878 } | 957 } |
| 879 | 958 |
| 880 } // namespace chromeos | 959 } // namespace chromeos |
| OLD | NEW |