Chromium Code Reviews| 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/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/stl_util.h" | |
| 15 #include "base/values.h" | 17 #include "base/values.h" |
| 16 #include "chromeos/dbus/dbus_method_call_status.h" | 18 #include "chromeos/dbus/dbus_method_call_status.h" |
| 17 #include "chromeos/dbus/dbus_thread_manager.h" | 19 #include "chromeos/dbus/dbus_thread_manager.h" |
| 18 #include "chromeos/dbus/shill_manager_client.h" | 20 #include "chromeos/dbus/shill_manager_client.h" |
| 21 #include "chromeos/dbus/shill_profile_client.h" | |
| 19 #include "chromeos/dbus/shill_service_client.h" | 22 #include "chromeos/dbus/shill_service_client.h" |
| 20 #include "chromeos/network/network_configuration_handler.h" | 23 #include "chromeos/network/network_configuration_handler.h" |
| 21 #include "chromeos/network/network_event_log.h" | 24 #include "chromeos/network/network_event_log.h" |
| 25 #include "chromeos/network/network_handler_callbacks.h" | |
| 22 #include "chromeos/network/network_state.h" | 26 #include "chromeos/network/network_state.h" |
| 23 #include "chromeos/network/network_state_handler.h" | 27 #include "chromeos/network/network_state_handler.h" |
| 28 #include "chromeos/network/network_ui_data.h" | |
| 24 #include "chromeos/network/onc/onc_constants.h" | 29 #include "chromeos/network/onc/onc_constants.h" |
| 30 #include "chromeos/network/onc/onc_merger.h" | |
| 25 #include "chromeos/network/onc/onc_signature.h" | 31 #include "chromeos/network/onc/onc_signature.h" |
| 26 #include "chromeos/network/onc/onc_translator.h" | 32 #include "chromeos/network/onc/onc_translator.h" |
| 27 #include "dbus/object_path.h" | 33 #include "chromeos/network/onc/onc_utils.h" |
| 34 #include "chromeos/network/onc/onc_validator.h" | |
| 28 #include "third_party/cros_system_api/dbus/service_constants.h" | 35 #include "third_party/cros_system_api/dbus/service_constants.h" |
| 29 | 36 |
| 30 namespace chromeos { | 37 namespace chromeos { |
| 31 | 38 |
| 32 namespace { | 39 namespace { |
| 33 | 40 |
| 34 ManagedNetworkConfigurationHandler* g_configuration_handler_instance = NULL; | 41 ManagedNetworkConfigurationHandler* g_configuration_handler_instance = NULL; |
| 35 | 42 |
| 36 const char kLogModule[] = "ManagedNetworkConfigurationHandler"; | 43 const char kLogModule[] = "ManagedNetworkConfigurationHandler"; |
| 37 | 44 |
| 38 // These are error strings used for error callbacks. None of these error | 45 // These are error strings used for error callbacks. None of these error |
| 39 // messages are user-facing: they should only appear in logs. | 46 // messages are user-facing: they should only appear in logs. |
| 47 const char kInvalidUserSettingsMessage[] = "User settings are invalid."; | |
| 48 const char kInvalidUserSettings[] = "Error.InvalidUserSettings"; | |
| 49 const char kNetworkAlreadyConfiguredMessage[] = | |
| 50 "Network is already configured."; | |
| 51 const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured"; | |
| 52 const char kPoliciesNotInitializedMessage[] = "Policies not initialized."; | |
| 53 const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized"; | |
| 40 const char kServicePath[] = "servicePath"; | 54 const char kServicePath[] = "servicePath"; |
| 41 const char kSetOnUnconfiguredNetworkMessage[] = | 55 const char kSetOnUnconfiguredNetworkMessage[] = |
| 42 "Unable to modify properties of an unconfigured network."; | 56 "Unable to modify properties of an unconfigured network."; |
| 43 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; | 57 const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork"; |
| 58 const char kUIDataErrorMessage[] = "UI data contains errors."; | |
| 59 const char kUIDataError[] = "Error.UIData"; | |
| 44 const char kUnknownServicePathMessage[] = "Service path is unknown."; | 60 const char kUnknownServicePathMessage[] = "Service path is unknown."; |
| 45 const char kUnknownServicePath[] = "Error.UnknownServicePath"; | 61 const char kUnknownServicePath[] = "Error.UnknownServicePath"; |
| 46 | 62 |
| 63 enum ProfileType { | |
| 64 PROFILE_NONE, // Not in any profile. | |
|
pastarmovj
2013/04/11 14:46:29
nit: Please align the comments for easier readabil
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 65 PROFILE_SHARED, // In the shared profile, shared by all users on device. | |
| 66 PROFILE_USER // In the user profile, not visible to other users. | |
| 67 }; | |
| 68 | |
| 69 const char kSharedProfilePath[] = "/profile/default"; | |
| 70 const char kUserProfilePath[] = "/profile/chronos/shill"; | |
| 71 | |
| 72 const char kFakeCredential[] = "FAKE_CREDENTIAL"; | |
|
pastarmovj
2013/04/11 14:46:29
It's highly unlikely but this can never be used as
pneubeck (no reviews)
2013/04/15 12:16:24
If find it to probable, that at some other place w
| |
| 73 | |
| 47 void RunErrorCallback(const std::string& service_path, | 74 void RunErrorCallback(const std::string& service_path, |
| 48 const std::string& error_name, | 75 const std::string& error_name, |
| 49 const std::string& error_message, | 76 const std::string& error_message, |
| 50 const network_handler::ErrorCallback& error_callback) { | 77 const network_handler::ErrorCallback& error_callback) { |
| 51 network_event_log::AddEntry(kLogModule, error_name, error_message); | 78 network_event_log::AddEntry(kLogModule, error_name, error_message); |
| 52 error_callback.Run( | 79 error_callback.Run( |
| 53 error_name, | 80 error_name, |
| 54 make_scoped_ptr( | 81 make_scoped_ptr( |
| 55 network_handler::CreateErrorData(service_path, | 82 network_handler::CreateErrorData(service_path, |
| 56 error_name, | 83 error_name, |
| 57 error_message))); | 84 error_message))); |
| 58 } | 85 } |
| 59 | 86 |
| 60 void TranslatePropertiesAndRunCallback( | 87 // Returns the NetworkUIData parsed from the UIData property of |
| 61 const network_handler::DictionaryResultCallback& callback, | 88 // |shill_dictionary|. If parsing fails or the field doesn't exist, returns |
| 62 const std::string& service_path, | 89 // NULL. |
| 63 const base::DictionaryValue& shill_properties) { | 90 scoped_ptr<NetworkUIData> GetUIData( |
| 64 scoped_ptr<base::DictionaryValue> onc_network( | 91 const base::DictionaryValue& shill_dictionary) { |
| 65 onc::TranslateShillServiceToONCPart( | 92 std::string ui_data_blob; |
| 66 shill_properties, | 93 if (shill_dictionary.GetStringWithoutPathExpansion( |
| 67 &onc::kNetworkWithStateSignature)); | 94 flimflam::kUIDataProperty, |
| 68 callback.Run(service_path, *onc_network); | 95 &ui_data_blob) && |
| 96 !ui_data_blob.empty()) { | |
| 97 scoped_ptr<base::DictionaryValue> ui_data_dict = | |
| 98 onc::ReadDictionaryFromJson(ui_data_blob); | |
| 99 if (ui_data_dict) { | |
| 100 return make_scoped_ptr(new NetworkUIData(*ui_data_dict)); | |
| 101 } else { | |
| 102 LOG(ERROR) << "UIData is not a valid JSON dictionary."; | |
| 103 } | |
|
stevenjb
2013/04/11 18:20:08
nit: no {}
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 104 } | |
| 105 return scoped_ptr<NetworkUIData>(); | |
| 106 } | |
| 107 | |
| 108 // Sets the UIData property in |shill_dictionary| to the serialization of | |
| 109 // |ui_data|. | |
| 110 void SetUIData(const NetworkUIData& ui_data, | |
| 111 base::DictionaryValue* shill_dictionary) { | |
| 112 base::DictionaryValue ui_data_dict; | |
| 113 ui_data.FillDictionary(&ui_data_dict); | |
| 114 std::string ui_data_blob; | |
| 115 base::JSONWriter::Write(&ui_data_dict, &ui_data_blob); | |
| 116 shill_dictionary->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, | |
| 117 ui_data_blob); | |
| 118 } | |
| 119 | |
| 120 // A dummy callback. | |
| 121 void DoNothing() { | |
| 122 } | |
| 123 | |
| 124 // A dummy callback. | |
| 125 void IgnoreString(const std::string& str) { | |
| 126 } | |
| 127 | |
| 128 // A dummy callback. | |
| 129 void IgnoreErrorDict(const std::string& error_name, | |
| 130 const scoped_ptr<base::DictionaryValue> error_data) { | |
| 131 } | |
| 132 | |
| 133 // A dummy callback. | |
| 134 void IgnoreErrorMessage(const std::string& error_name, | |
| 135 const std::string& error_message) { | |
|
stevenjb
2013/04/11 18:20:08
Do we really want to ignore these error messages i
pneubeck (no reviews)
2013/04/15 12:16:24
Normally, we shouldn't get errors.
However, if the
| |
| 136 } | |
| 137 | |
| 138 void LogError(const std::string& error) { | |
|
pastarmovj
2013/04/11 14:46:29
Why would you do that?
stevenjb
2013/04/11 18:20:08
This appears to be unused.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 139 LOG(ERROR) << error; | |
| 140 } | |
| 141 | |
| 142 // Removes all kFakeCredential values from sensitive fields (determined by | |
| 143 // onc::FieldIsCredential) of |onc_object|. | |
| 144 void RemoveFakeCredentials( | |
| 145 const onc::OncValueSignature& signature, | |
| 146 base::DictionaryValue* onc_object) { | |
| 147 base::DictionaryValue::Iterator it(*onc_object); | |
| 148 while (!it.IsAtEnd()) { | |
| 149 base::Value* value = NULL; | |
| 150 std::string field_name = it.key(); | |
| 151 onc_object->GetWithoutPathExpansion(field_name, &value); | |
|
pastarmovj
2013/04/11 14:46:29
Why not use it.value() here?
stevenjb
2013/04/11 18:20:08
value() returns a const&, and RemoveFakeCredential
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 152 // Advance before delete. | |
| 153 it.Advance(); | |
| 154 | |
| 155 base::DictionaryValue* nested_object = NULL; | |
| 156 std::string string_value; | |
| 157 if (value->GetAsDictionary(&nested_object)) { | |
|
stevenjb
2013/04/11 18:20:08
This is kind of confusing. While more verbose, I w
pneubeck (no reviews)
2013/04/15 12:16:24
This pattern is rather common and typesafe. Do you
stevenjb
2013/04/15 17:38:54
Well, I don't feel strongly enough about it to was
pneubeck (no reviews)
2013/04/16 07:50:06
Done.
| |
| 158 const onc::OncFieldSignature* field_signature = | |
| 159 onc::GetFieldSignature(signature, field_name); | |
| 160 | |
| 161 RemoveFakeCredentials(*field_signature->value_signature, | |
| 162 nested_object); | |
| 163 } else if (value->GetAsString(&string_value) && | |
| 164 onc::FieldIsCredential(signature, field_name)) { | |
| 165 if (string_value == kFakeCredential) { | |
| 166 // The value wasn't modified by the UI, thus we remove the field to keep | |
| 167 // the existing value that is stored in Shill. | |
| 168 onc_object->RemoveWithoutPathExpansion(field_name, NULL); | |
| 169 } | |
| 170 // Otherwise, the value is set and modified by the UI, thus we keep that | |
| 171 // value to overwrite whatever is stored in Shill. | |
| 172 } | |
| 173 } | |
| 174 } | |
| 175 | |
| 176 // Creates a Shill property dictionary from the given arguments. The resulting | |
| 177 // dictionary will be sent to Shill by the caller. | |
| 178 scoped_ptr<base::DictionaryValue> CreateShillConfiguration( | |
| 179 const std::string& profile_path, | |
| 180 const std::string& guid, | |
| 181 const base::DictionaryValue* policy, | |
| 182 const base::DictionaryValue* user_settings) { | |
| 183 scoped_ptr<base::DictionaryValue> effective; | |
| 184 | |
| 185 onc::ONCSource onc_source; | |
| 186 if (policy) { | |
| 187 if (profile_path == kSharedProfilePath) { | |
| 188 effective = onc::MergeSettingsAndPoliciesToEffective( | |
| 189 NULL, // no user policy | |
| 190 policy, // device policy | |
| 191 NULL, // no user settings | |
| 192 user_settings); // shared settings | |
|
stevenjb
2013/04/11 18:20:08
nit: Name 'settings' since may be user or shared?
pneubeck (no reviews)
2013/04/15 12:16:24
Ugh. Yes, the current naming is confusing without
| |
| 193 onc_source = onc::ONC_SOURCE_DEVICE_POLICY; | |
| 194 } else { | |
| 195 effective = onc::MergeSettingsAndPoliciesToEffective( | |
| 196 policy, // user policy | |
| 197 NULL, // no device policy | |
| 198 user_settings, // user settings | |
| 199 NULL); // no shared settings | |
| 200 onc_source = onc::ONC_SOURCE_USER_POLICY; | |
| 201 } | |
| 202 } else if (user_settings) { | |
| 203 effective.reset(user_settings->DeepCopy()); | |
| 204 // TODO(pneubeck): change to source ONC_SOURCE_USER | |
| 205 onc_source = onc::ONC_SOURCE_NONE; | |
| 206 } else { | |
| 207 NOTREACHED(); | |
| 208 onc_source = onc::ONC_SOURCE_NONE; | |
| 209 } | |
| 210 | |
| 211 RemoveFakeCredentials(onc::kNetworkConfigurationSignature, | |
| 212 effective.get()); | |
| 213 | |
| 214 effective->SetStringWithoutPathExpansion(onc::network_config::kGUID, guid); | |
| 215 | |
| 216 scoped_ptr<base::DictionaryValue> shill_dictionary( | |
| 217 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | |
| 218 *effective)); | |
| 219 | |
| 220 shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty, | |
| 221 profile_path); | |
| 222 | |
| 223 scoped_ptr<NetworkUIData> ui_data; | |
| 224 if (policy) { | |
| 225 ui_data = CreateUIDataFromONC(onc_source, *policy); | |
| 226 } else { | |
| 227 ui_data.reset(new NetworkUIData()); | |
| 228 } | |
|
stevenjb
2013/04/11 18:20:08
nit: no {}
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 229 | |
| 230 if (user_settings) { | |
| 231 // Shill doesn't know that sensitive data is contained in the UIData | |
| 232 // property and might write it into logs or other insecure places. Thus, we | |
| 233 // have to remove or mask credentials. | |
| 234 // | |
| 235 // Shill's GetProperties doesn't return credentials. Masking credentials | |
| 236 // instead of just removing them, allows remembering if a credential is set | |
| 237 // or not. | |
| 238 scoped_ptr<base::DictionaryValue> sanitized_user_settings( | |
| 239 onc::MaskCredentialsInOncObject(onc::kNetworkConfigurationSignature, | |
| 240 *user_settings, | |
| 241 kFakeCredential)); | |
| 242 ui_data->set_user_settings(sanitized_user_settings.Pass()); | |
| 243 } | |
| 244 | |
| 245 SetUIData(*ui_data, shill_dictionary.get()); | |
| 246 | |
| 247 VLOG(2) << "Created Shill properties: " << *shill_dictionary; | |
| 248 | |
| 249 return shill_dictionary.Pass(); | |
| 250 } | |
| 251 | |
| 252 // Returns if |policy| matches |onc_network_part|. This is should be the only | |
|
stevenjb
2013/04/11 18:20:08
s/Returns/Returns true/
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 253 // such matching function within Chrome. Shill does such matching in several | |
| 254 // functions for network identification. For compatibility, we currently should | |
| 255 // stick to Shill's matching behavior. | |
| 256 bool IsPolicyMatching(const base::DictionaryValue& policy, | |
| 257 const base::DictionaryValue& onc_network_part) { | |
| 258 std::string policy_type; | |
| 259 policy.GetStringWithoutPathExpansion(onc::network_config::kType, | |
| 260 &policy_type); | |
| 261 std::string network_type; | |
| 262 onc_network_part.GetStringWithoutPathExpansion(onc::network_config::kType, | |
| 263 &network_type); | |
| 264 if (policy_type != network_type) | |
|
pastarmovj
2013/04/11 14:46:29
Please be consistent in the file if you use or not
stevenjb
2013/04/11 18:20:08
Also while the style guide allows either, historic
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 265 return false; | |
| 266 | |
| 267 if (network_type != onc::network_type::kWiFi) | |
| 268 return false; | |
| 269 | |
| 270 std::string policy_ssid; | |
| 271 policy.GetStringWithoutPathExpansion(onc::wifi::kSSID, | |
| 272 &policy_ssid); | |
|
stevenjb
2013/04/11 18:20:08
nit: one line?
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 273 std::string network_ssid; | |
| 274 onc_network_part.GetStringWithoutPathExpansion(onc::wifi::kSSID, | |
| 275 &network_ssid); | |
| 276 return (policy_ssid == network_ssid); | |
| 277 } | |
| 278 | |
| 279 // Returns the policy of |policies| matching |onc_network_part|, if any | |
| 280 // exists. Returns NULL otherwise. | |
| 281 const base::DictionaryValue* FindMatchingPolicy( | |
| 282 const std::map<std::string, const base::DictionaryValue*> &policies, | |
|
stevenjb
2013/04/11 18:20:08
Use ManagedNetworkConfigurationHandler::PolicyMap
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
stevenjb
2013/04/15 17:38:54
Not done?
pneubeck (no reviews)
2013/04/16 07:50:06
Yeah, I had previously replaced all within Managed
| |
| 283 const base::DictionaryValue& onc_network_part) { | |
| 284 for (std::map<std::string, const base::DictionaryValue*>::const_iterator it = | |
| 285 policies.begin(); | |
| 286 it != policies.end(); | |
|
pastarmovj
2013/04/11 14:46:29
combine those two lines.
stevenjb
2013/04/11 18:20:08
In fact, I would suggest placing both line 286 and
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 287 ++it) { | |
| 288 if (IsPolicyMatching(*it->second, onc_network_part)) | |
| 289 return it->second; | |
| 290 } | |
| 291 return NULL; | |
| 69 } | 292 } |
| 70 | 293 |
| 71 } // namespace | 294 } // namespace |
| 72 | 295 |
| 73 // static | 296 // static |
| 74 void ManagedNetworkConfigurationHandler::Initialize() { | 297 void ManagedNetworkConfigurationHandler::Initialize() { |
| 75 CHECK(!g_configuration_handler_instance); | 298 CHECK(!g_configuration_handler_instance); |
| 76 g_configuration_handler_instance = new ManagedNetworkConfigurationHandler; | 299 g_configuration_handler_instance = new ManagedNetworkConfigurationHandler; |
| 77 } | 300 } |
| 78 | 301 |
| 79 // static | 302 // static |
| 80 bool ManagedNetworkConfigurationHandler::IsInitialized() { | 303 bool ManagedNetworkConfigurationHandler::IsInitialized() { |
| 81 return g_configuration_handler_instance; | 304 return g_configuration_handler_instance; |
| 82 } | 305 } |
| 83 | 306 |
| 84 // static | 307 // static |
| 85 void ManagedNetworkConfigurationHandler::Shutdown() { | 308 void ManagedNetworkConfigurationHandler::Shutdown() { |
| 86 CHECK(g_configuration_handler_instance); | 309 CHECK(g_configuration_handler_instance); |
| 87 delete g_configuration_handler_instance; | 310 delete g_configuration_handler_instance; |
| 88 g_configuration_handler_instance = NULL; | 311 g_configuration_handler_instance = NULL; |
| 89 } | 312 } |
| 90 | 313 |
| 91 // static | 314 // static |
| 92 ManagedNetworkConfigurationHandler* ManagedNetworkConfigurationHandler::Get() { | 315 ManagedNetworkConfigurationHandler* ManagedNetworkConfigurationHandler::Get() { |
| 93 CHECK(g_configuration_handler_instance); | 316 CHECK(g_configuration_handler_instance); |
| 94 return g_configuration_handler_instance; | 317 return g_configuration_handler_instance; |
| 95 } | 318 } |
| 96 | 319 |
| 320 void ManagedNetworkConfigurationHandler::GetManagedProperties( | |
| 321 const std::string& service_path, | |
| 322 const network_handler::DictionaryResultCallback& callback, | |
| 323 const network_handler::ErrorCallback& error_callback) { | |
| 324 if (!user_policies_by_guid_ || !device_policies_by_guid_) { | |
| 325 RunErrorCallback(service_path, | |
| 326 kPoliciesNotInitialized, | |
| 327 kPoliciesNotInitializedMessage, | |
| 328 error_callback); | |
| 329 return; | |
| 330 } | |
| 331 NetworkConfigurationHandler::Get()->GetProperties( | |
| 332 service_path, | |
| 333 base::Bind( | |
| 334 &ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback, | |
| 335 weak_ptr_factory_.GetWeakPtr(), | |
| 336 callback, | |
| 337 error_callback), | |
| 338 error_callback); | |
| 339 } | |
| 340 | |
| 341 void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback( | |
| 342 const network_handler::DictionaryResultCallback& callback, | |
| 343 const network_handler::ErrorCallback& error_callback, | |
| 344 const std::string& service_path, | |
| 345 const base::DictionaryValue& shill_properties) { | |
| 346 std::string profile_path; | |
| 347 ProfileType profile_type = PROFILE_NONE; | |
| 348 if (shill_properties.GetStringWithoutPathExpansion( | |
| 349 flimflam::kProfileProperty, | |
|
pastarmovj
2013/04/11 14:46:29
Combine those two lines better.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 350 &profile_path)) { | |
| 351 if (profile_path == kSharedProfilePath) | |
| 352 profile_type = PROFILE_SHARED; | |
| 353 else if (!profile_path.empty()) | |
| 354 profile_type = PROFILE_USER; | |
| 355 } else { | |
| 356 VLOG(1) << "No profile path for service " << service_path << "."; | |
| 357 } | |
| 358 | |
| 359 scoped_ptr<NetworkUIData> ui_data = GetUIData(shill_properties); | |
| 360 | |
| 361 base::DictionaryValue* user_settings = NULL; | |
| 362 base::DictionaryValue* shared_settings = NULL; | |
| 363 | |
| 364 if (ui_data) { | |
| 365 if (profile_type == PROFILE_SHARED) | |
| 366 shared_settings = ui_data->user_settings(); | |
| 367 else if (profile_type == PROFILE_USER) | |
| 368 user_settings = ui_data->user_settings(); | |
| 369 } else if (profile_type != PROFILE_NONE) { | |
| 370 LOG(WARNING) << "Service " << service_path << " of profile " | |
| 371 << profile_path << " contains no or no valid UIData."; | |
| 372 // TODO(pneubeck): add a conversion of user configured entries of old | |
| 373 // ChromeOS versions. We will have to use a heuristic to determine which | |
| 374 // properties _might_ be user configured. | |
| 375 } | |
| 376 | |
| 377 scoped_ptr<base::DictionaryValue> active_settings( | |
| 378 onc::TranslateShillServiceToONCPart( | |
| 379 shill_properties, | |
| 380 &onc::kNetworkWithStateSignature)); | |
| 381 | |
| 382 std::string guid; | |
| 383 active_settings->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 384 &guid); | |
| 385 | |
| 386 const base::DictionaryValue* user_policy = NULL; | |
| 387 const base::DictionaryValue* device_policy = NULL; | |
| 388 if (!guid.empty()) { | |
| 389 if (profile_type == PROFILE_SHARED) | |
| 390 device_policy = (*device_policies_by_guid_)[guid]; | |
| 391 else if (profile_type == PROFILE_USER) | |
| 392 user_policy = (*user_policies_by_guid_)[guid]; | |
| 393 } | |
| 394 | |
| 395 // This call also removes credentials from policies. | |
| 396 scoped_ptr<base::DictionaryValue> augmented_properties = | |
| 397 onc::MergeSettingsAndPoliciesToAugmented( | |
| 398 onc::kNetworkConfigurationSignature, | |
| 399 user_policy, | |
| 400 device_policy, | |
| 401 user_settings, | |
| 402 shared_settings, | |
| 403 active_settings.get()); | |
| 404 callback.Run(service_path, *augmented_properties); | |
| 405 } | |
| 406 | |
| 407 namespace { | |
|
stevenjb
2013/04/11 18:20:08
nit: I'd combine this with the anon namesapce at t
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 408 | |
| 409 void TranslatePropertiesAndRunCallback( | |
| 410 const network_handler::DictionaryResultCallback& callback, | |
| 411 const std::string& service_path, | |
| 412 const base::DictionaryValue& shill_properties) { | |
| 413 scoped_ptr<base::DictionaryValue> onc_network( | |
| 414 onc::TranslateShillServiceToONCPart( | |
| 415 shill_properties, | |
| 416 &onc::kNetworkWithStateSignature)); | |
| 417 callback.Run(service_path, *onc_network); | |
| 418 } | |
| 419 | |
| 420 } // namespace | |
| 421 | |
| 97 void ManagedNetworkConfigurationHandler::GetProperties( | 422 void ManagedNetworkConfigurationHandler::GetProperties( |
| 98 const std::string& service_path, | 423 const std::string& service_path, |
| 99 const network_handler::DictionaryResultCallback& callback, | 424 const network_handler::DictionaryResultCallback& callback, |
| 100 const network_handler::ErrorCallback& error_callback) const { | 425 const network_handler::ErrorCallback& error_callback) const { |
| 101 // TODO(pneubeck): Merge with policies. | |
| 102 NetworkConfigurationHandler::Get()->GetProperties( | 426 NetworkConfigurationHandler::Get()->GetProperties( |
| 103 service_path, | 427 service_path, |
| 104 base::Bind(&TranslatePropertiesAndRunCallback, callback), | 428 base::Bind(&TranslatePropertiesAndRunCallback, callback), |
| 105 error_callback); | 429 error_callback); |
| 106 } | 430 } |
| 107 | 431 |
| 108 void ManagedNetworkConfigurationHandler::SetProperties( | 432 void ManagedNetworkConfigurationHandler::SetProperties( |
| 109 const std::string& service_path, | 433 const std::string& service_path, |
| 110 const base::DictionaryValue& properties, | 434 const base::DictionaryValue& user_settings, |
| 111 const base::Closure& callback, | 435 const base::Closure& callback, |
| 112 const network_handler::ErrorCallback& error_callback) const { | 436 const network_handler::ErrorCallback& error_callback) const { |
| 113 const NetworkState* state = | 437 const NetworkState* state = |
| 114 NetworkStateHandler::Get()->GetNetworkState(service_path); | 438 NetworkStateHandler::Get()->GetNetworkState(service_path); |
| 115 | 439 |
| 116 if (!state) { | 440 if (!state) { |
| 117 RunErrorCallback(service_path, | 441 RunErrorCallback(service_path, |
| 118 kUnknownServicePath, | 442 kUnknownServicePath, |
| 119 kUnknownServicePathMessage, | 443 kUnknownServicePathMessage, |
| 120 error_callback); | 444 error_callback); |
| 445 return; | |
| 121 } | 446 } |
| 447 | |
| 122 std::string guid = state->guid(); | 448 std::string guid = state->guid(); |
| 123 if (guid.empty()) { | 449 if (guid.empty()) { |
| 450 // TODO(pneubeck): create an initial configuration in this case. As for | |
| 451 // CreateConfiguration, user settings from older ChromeOS versions have to | |
| 452 // determined here. | |
| 124 RunErrorCallback(service_path, | 453 RunErrorCallback(service_path, |
| 125 kSetOnUnconfiguredNetwork, | 454 kSetOnUnconfiguredNetwork, |
| 126 kSetOnUnconfiguredNetworkMessage, | 455 kSetOnUnconfiguredNetworkMessage, |
| 127 error_callback); | 456 error_callback); |
| 457 return; | |
| 128 } | 458 } |
| 129 | 459 |
| 130 // TODO(pneubeck): Enforce policies. | 460 // Validate the ONC dictionary. We are liberal and ignore unknown field |
| 461 // names. User settings are only partial ONC, thus we ignore missing fields. | |
| 462 onc::Validator validator(false, // Ignore unknown fields. | |
| 463 false, // Ignore invalid recommended field names. | |
| 464 false, // Ignore missing fields. | |
|
pastarmovj
2013/04/11 14:46:29
Almost aligned here.
pneubeck (no reviews)
2013/04/15 12:16:24
?
You want the comments to be aligned?
pastarmovj
2013/04/16 11:31:17
Yes, but you can leave it as is if you wish.
| |
| 465 false); // This ONC does not comes from policy. | |
| 466 | |
| 467 onc::Validator::Result validation_result; | |
| 468 scoped_ptr<base::DictionaryValue> validated_user_settings = | |
| 469 validator.ValidateAndRepairObject( | |
| 470 &onc::kNetworkConfigurationSignature, | |
| 471 user_settings, | |
| 472 &validation_result); | |
| 473 | |
| 474 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { | |
| 475 LOG(WARNING) << "Validation of ONC user settings produced warnings."; | |
| 476 } else if (validation_result == onc::Validator::INVALID) { | |
| 477 LOG(ERROR) << "ONC user settings are invalid and couldn't be repaired."; | |
| 478 RunErrorCallback(service_path, | |
| 479 kInvalidUserSettings, | |
| 480 kInvalidUserSettingsMessage, | |
| 481 error_callback); | |
| 482 return; | |
|
stevenjb
2013/04/11 18:20:08
nit: Put error clause with early exit above warnin
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 483 } | |
| 484 | |
| 485 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " | |
| 486 << state->profile_path(); | |
| 487 | |
| 488 const PolicyMap* policies_by_guid = | |
| 489 GetPoliciesForProfile(state->profile_path()); | |
| 490 | |
| 491 if (!policies_by_guid) { | |
| 492 RunErrorCallback(service_path, | |
| 493 kPoliciesNotInitialized, | |
| 494 kPoliciesNotInitializedMessage, | |
| 495 error_callback); | |
| 496 return; | |
| 497 } | |
| 498 | |
| 499 const base::DictionaryValue* policy = NULL; | |
| 500 std::map<std::string, const base::DictionaryValue*>::const_iterator it = | |
| 501 policies_by_guid->find(guid); | |
| 502 if (it != policies_by_guid->end()) | |
| 503 policy = it->second; | |
| 504 | |
| 505 VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; | |
| 131 | 506 |
| 132 scoped_ptr<base::DictionaryValue> shill_dictionary( | 507 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 133 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | 508 CreateShillConfiguration(state->profile_path(), guid, policy, |
| 134 properties)); | 509 &user_settings)); |
| 135 | 510 |
| 136 NetworkConfigurationHandler::Get()->SetProperties(service_path, | 511 NetworkConfigurationHandler::Get()->SetProperties(service_path, |
| 137 *shill_dictionary, | 512 *shill_dictionary, |
| 138 callback, | 513 callback, |
| 139 error_callback); | 514 error_callback); |
| 140 } | 515 } |
| 141 | 516 |
| 142 void ManagedNetworkConfigurationHandler::Connect( | 517 void ManagedNetworkConfigurationHandler::Connect( |
| 143 const std::string& service_path, | 518 const std::string& service_path, |
| 144 const base::Closure& callback, | 519 const base::Closure& callback, |
| 145 const network_handler::ErrorCallback& error_callback) const { | 520 const network_handler::ErrorCallback& error_callback) const { |
| 146 // TODO(pneubeck): Update the user profile with tracked/followed settings of | |
| 147 // the shared profile. | |
| 148 NetworkConfigurationHandler::Get()->Connect(service_path, | 521 NetworkConfigurationHandler::Get()->Connect(service_path, |
| 149 callback, | 522 callback, |
| 150 error_callback); | 523 error_callback); |
| 151 } | 524 } |
| 152 | 525 |
| 153 void ManagedNetworkConfigurationHandler::Disconnect( | 526 void ManagedNetworkConfigurationHandler::Disconnect( |
| 154 const std::string& service_path, | 527 const std::string& service_path, |
| 155 const base::Closure& callback, | 528 const base::Closure& callback, |
| 156 const network_handler::ErrorCallback& error_callback) const { | 529 const network_handler::ErrorCallback& error_callback) const { |
| 157 NetworkConfigurationHandler::Get()->Disconnect(service_path, | 530 NetworkConfigurationHandler::Get()->Disconnect(service_path, |
| 158 callback, | 531 callback, |
| 159 error_callback); | 532 error_callback); |
| 160 } | 533 } |
| 161 | 534 |
| 162 void ManagedNetworkConfigurationHandler::CreateConfiguration( | 535 void ManagedNetworkConfigurationHandler::CreateConfiguration( |
| 163 const base::DictionaryValue& properties, | 536 const base::DictionaryValue& properties, |
| 164 const network_handler::StringResultCallback& callback, | 537 const network_handler::StringResultCallback& callback, |
| 165 const network_handler::ErrorCallback& error_callback) const { | 538 const network_handler::ErrorCallback& error_callback) const { |
| 166 scoped_ptr<base::DictionaryValue> modified_properties( | 539 std::string profile_path = kUserProfilePath; |
| 167 properties.DeepCopy()); | 540 const PolicyMap* policies_by_guid = GetPoliciesForProfile(profile_path); |
| 168 | 541 |
| 169 // If there isn't already a GUID attached to these properties, then | 542 if (!policies_by_guid) { |
| 170 // generate one and add it. | 543 RunErrorCallback("", |
| 171 std::string guid; | 544 kPoliciesNotInitialized, |
| 172 if (!properties.GetString(onc::network_config::kGUID, &guid)) { | 545 kPoliciesNotInitializedMessage, |
| 173 guid = base::GenerateGUID(); | 546 error_callback); |
| 174 modified_properties->SetStringWithoutPathExpansion( | 547 return; |
| 175 onc::network_config::kGUID, guid); | |
| 176 } else { | |
| 177 NOTREACHED(); // TODO(pneubeck): Return an error using error_callback. | |
| 178 } | 548 } |
| 179 | 549 |
| 180 // TODO(pneubeck): Enforce policies. | 550 if (FindMatchingPolicy(*policies_by_guid, properties)) { |
| 551 RunErrorCallback("", | |
| 552 kNetworkAlreadyConfigured, | |
| 553 kNetworkAlreadyConfiguredMessage, | |
| 554 error_callback); | |
| 555 } | |
| 556 | |
| 557 // TODO(pneubeck): In case of WiFi, check that no other configuration for the | |
| 558 // same {SSID, mode, security} exists. We don't support such multiple | |
| 559 // configurations, yet. | |
| 560 | |
| 561 // Generate a new GUID for this configuration. Ignore the maybe provided GUID | |
| 562 // in |properties| as it is not our own and from an untrusted source. | |
| 563 std::string guid = base::GenerateGUID(); | |
| 181 | 564 |
| 182 scoped_ptr<base::DictionaryValue> shill_dictionary( | 565 scoped_ptr<base::DictionaryValue> shill_dictionary( |
| 183 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, | 566 CreateShillConfiguration(profile_path, guid, NULL /*no policy*/, |
| 184 properties)); | 567 &properties)); |
| 185 | 568 |
| 186 NetworkConfigurationHandler::Get()->CreateConfiguration(*shill_dictionary, | 569 NetworkConfigurationHandler::Get()->CreateConfiguration(*shill_dictionary, |
| 187 callback, | 570 callback, |
| 188 error_callback); | 571 error_callback); |
| 189 } | 572 } |
| 190 | 573 |
| 191 void ManagedNetworkConfigurationHandler::RemoveConfiguration( | 574 void ManagedNetworkConfigurationHandler::RemoveConfiguration( |
| 192 const std::string& service_path, | 575 const std::string& service_path, |
| 193 const base::Closure& callback, | 576 const base::Closure& callback, |
| 194 const network_handler::ErrorCallback& error_callback) const { | 577 const network_handler::ErrorCallback& error_callback) const { |
| 195 NetworkConfigurationHandler::Get()->RemoveConfiguration(service_path, | 578 NetworkConfigurationHandler::Get()->RemoveConfiguration(service_path, |
| 196 callback, | 579 callback, |
| 197 error_callback); | 580 error_callback); |
| 198 } | 581 } |
| 199 | 582 |
| 200 ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler() { | 583 // This class compares (entry point is Run()) |modified_policies| with the |
| 584 // existing entries in the provided Shill profile |profile|. It fetches all | |
| 585 // entries in parallel (GetProfileProperties), compares each entry with the | |
| 586 // current policies (GetEntry) and adds all missing policies | |
| 587 // (~PolicyApplicator). | |
| 588 class ManagedNetworkConfigurationHandler::PolicyApplicator | |
| 589 : public base::RefCounted<PolicyApplicator> { | |
| 590 public: | |
| 591 typedef ManagedNetworkConfigurationHandler::PolicyMap PolicyMap; | |
| 592 | |
| 593 PolicyApplicator(base::WeakPtr<ManagedNetworkConfigurationHandler> handler, | |
| 594 const std::string& profile, | |
| 595 scoped_ptr<std::set<std::string> > modified_policies) | |
| 596 : handler_(handler), | |
| 597 profile_path_(profile) { | |
| 598 remaining_policies_.swap(*modified_policies); | |
|
pastarmovj
2013/04/11 14:46:29
Hmm is this safe in all cases?
stevenjb
2013/04/11 18:20:08
This is confusing with a member and a scoped_ptr.
pneubeck (no reviews)
2013/04/15 12:16:24
Not if modified_policies is NULL, in which case it
pneubeck (no reviews)
2013/04/15 12:16:24
The scoped_ptr indicates that ownership is passed
stevenjb
2013/04/15 17:38:54
With swap(), I do prefer it changed with the comme
| |
| 599 } | |
| 600 | |
| 601 void Run() { | |
| 602 DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( | |
| 603 dbus::ObjectPath(profile_path_), | |
| 604 base::Bind( | |
| 605 &PolicyApplicator::GetProfileProperties, | |
| 606 this), | |
|
stevenjb
2013/04/11 18:20:08
nit: combine the above 3 lines?
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 607 base::Bind(&IgnoreErrorMessage)); | |
| 608 } | |
| 609 | |
| 610 private: | |
| 611 friend class base::RefCounted<PolicyApplicator>; | |
| 612 | |
| 613 void GetProfileProperties(const base::DictionaryValue& profile_properties) { | |
| 614 if (!handler_) { | |
| 615 LOG(WARNING) << "Handler destructed during policy application to profile " | |
| 616 << profile_path_; | |
| 617 return; | |
| 618 } | |
| 619 | |
| 620 VLOG(2) << "Received properties for profile " << profile_path_; | |
| 621 const base::ListValue* entries = NULL; | |
| 622 if (!profile_properties.GetListWithoutPathExpansion( | |
| 623 flimflam::kEntriesProperty, | |
| 624 &entries)) { | |
|
stevenjb
2013/04/11 18:20:08
nit: combine lines
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 625 LOG(ERROR) << "Profile " << profile_path_ | |
| 626 << " doesn't contain the property " | |
| 627 << flimflam::kEntriesProperty; | |
| 628 return; | |
| 629 } | |
| 630 | |
| 631 for (base::ListValue::const_iterator it = entries->begin(); | |
| 632 it != entries->end(); ++it) { | |
| 633 std::string entry; | |
| 634 (*it)->GetAsString(&entry); | |
| 635 | |
| 636 std::ostringstream entry_failure; | |
| 637 DBusThreadManager::Get()->GetShillProfileClient()->GetEntry( | |
| 638 dbus::ObjectPath(profile_path_), | |
| 639 entry, | |
| 640 base::Bind(&PolicyApplicator::GetEntry, | |
| 641 this, | |
| 642 entry), | |
| 643 base::Bind(&IgnoreErrorMessage)); | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 void GetEntry(const std::string& entry, | |
| 648 const base::DictionaryValue& entry_properties) { | |
| 649 if (!handler_) { | |
| 650 LOG(WARNING) << "Handler destructed during policy application to profile " | |
| 651 << profile_path_; | |
| 652 return; | |
| 653 } | |
| 654 | |
| 655 VLOG(2) << "Received properties for entry " << entry << " of profile " | |
| 656 << profile_path_; | |
| 657 | |
| 658 scoped_ptr<base::DictionaryValue> onc_part( | |
| 659 onc::TranslateShillServiceToONCPart( | |
| 660 entry_properties, | |
| 661 &onc::kNetworkWithStateSignature)); | |
| 662 | |
| 663 std::string old_guid; | |
| 664 if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 665 &old_guid)) { | |
|
pastarmovj
2013/04/11 14:46:29
align.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 666 LOG(WARNING) << "Entry " << entry << " of profile " << profile_path_ | |
|
pastarmovj
2013/04/11 14:46:29
align.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 667 << " doesn't contain a GUID."; | |
| 668 // This might be an entry of an older ChromeOS version. Assume it to be | |
| 669 // unmanaged. | |
| 670 return; | |
| 671 } | |
| 672 | |
| 673 scoped_ptr<NetworkUIData> ui_data = GetUIData(entry_properties); | |
| 674 if (!ui_data) { | |
| 675 VLOG(1) << "Entry " << entry << " of profile " << profile_path_ | |
| 676 << " contains no or no valid UIData."; | |
| 677 // This might be an entry of an older ChromeOS version. Assume it to be | |
| 678 // unmanaged. | |
| 679 return; | |
| 680 } | |
| 681 | |
| 682 bool was_managed = | |
| 683 (ui_data->onc_source() == onc::ONC_SOURCE_DEVICE_POLICY || | |
| 684 ui_data->onc_source() == onc::ONC_SOURCE_USER_POLICY); | |
| 685 | |
| 686 // The relevant policy must have been initialized, otherwise we hadn't Run | |
| 687 // this PolicyApplicator. | |
| 688 const PolicyMap& policies_by_guid = | |
| 689 *handler_->GetPoliciesForProfile(profile_path_); | |
| 690 | |
| 691 const base::DictionaryValue* new_policy = NULL; | |
| 692 if (was_managed) { | |
| 693 // If we have a GUID that might match a current policy, do a lookup using | |
| 694 // that GUID at first. In particular this is necessary, as some networks | |
| 695 // can't be matched to policies by properties (e.g. VPN). | |
| 696 PolicyMap::const_iterator it = policies_by_guid.find(old_guid); | |
| 697 if (it != policies_by_guid.end()) | |
| 698 new_policy = it->second; | |
| 699 } | |
| 700 | |
| 701 if (!new_policy) { | |
| 702 // If we didn't find a policy by GUID, still a new policy might match. | |
| 703 new_policy = FindMatchingPolicy(policies_by_guid, *onc_part); | |
| 704 } | |
| 705 | |
| 706 std::string new_guid; | |
| 707 if (new_policy) { | |
| 708 new_policy->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 709 &new_guid); | |
| 710 } | |
| 711 | |
| 712 if (new_policy) { | |
|
pastarmovj
2013/04/11 14:46:29
Combine those ifs they are the same.
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 713 VLOG_IF(1, was_managed && old_guid != new_guid) | |
| 714 << "Updating configuration previously managed by policy " << old_guid | |
| 715 << " with new policy " << new_guid << "."; | |
| 716 VLOG_IF(1, !was_managed) | |
| 717 << "Applying policy " << new_guid << " to previously unmanaged " | |
| 718 << "configuration."; | |
| 719 | |
| 720 if (old_guid == new_guid && | |
| 721 remaining_policies_.find(new_guid) == remaining_policies_.end()) { | |
| 722 VLOG(1) << "Not updating existing managed configuration with guid " | |
| 723 << new_guid << " because the policy didn't change."; | |
| 724 } else { | |
| 725 VLOG_IF(1, old_guid == new_guid) | |
| 726 << "Updating previously managed configuration with the updated " | |
| 727 << "policy " << new_guid << "."; | |
| 728 | |
| 729 // Update the existing configuration with the maybe changed | |
| 730 // policy. Thereby the GUID might change. | |
| 731 scoped_ptr<base::DictionaryValue> shill_dictionary = | |
| 732 CreateShillConfiguration(profile_path_, new_guid, new_policy, | |
| 733 ui_data->user_settings()); | |
| 734 NetworkConfigurationHandler::Get()->CreateConfiguration( | |
| 735 *shill_dictionary, | |
| 736 base::Bind(&IgnoreString), | |
| 737 base::Bind(&IgnoreErrorDict)); | |
| 738 remaining_policies_.erase(new_guid); | |
| 739 } | |
| 740 } else if (was_managed) { | |
| 741 VLOG(1) << "Removing configuration previously managed by policy " | |
| 742 << old_guid << ", because the policy was removed."; | |
| 743 | |
| 744 // Remove the entry, because the network was managed but isn't anymore. | |
| 745 // Note: An alternative might be to preserve the user settings, but it's | |
| 746 // unclear which values originating the policy should be removed. | |
| 747 DeleteEntry(entry); | |
| 748 } else { | |
| 749 VLOG(2) << "Ignore unmanaged entry."; | |
| 750 | |
| 751 // The entry wasn't managed and doesn't match any current policy. Thus | |
| 752 // leave it as it is. | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 void DeleteEntry(const std::string& entry) { | |
| 757 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( | |
| 758 dbus::ObjectPath(profile_path_), | |
| 759 entry, | |
| 760 base::Bind(&DoNothing), | |
| 761 base::Bind(&IgnoreErrorMessage)); | |
| 762 } | |
| 763 | |
| 764 virtual ~PolicyApplicator() { | |
| 765 if (remaining_policies_.empty()) | |
| 766 return; | |
| 767 | |
| 768 VLOG(2) << "Create new managed network configurations in profile" | |
| 769 << profile_path_ << "."; | |
| 770 // All profile entries were compared to policies. |configureGUIDs_| contains | |
| 771 // all matched policies. From the remainder of policies, new configurations | |
| 772 // have to be created. | |
| 773 | |
| 774 // The relevant policy must have been initialized, otherwise we hadn't Run | |
| 775 // this PolicyApplicator. | |
| 776 const PolicyMap& policies_by_guid = | |
| 777 *handler_->GetPoliciesForProfile(profile_path_); | |
| 778 | |
| 779 for (std::set<std::string>::iterator it = remaining_policies_.begin(); | |
| 780 it != remaining_policies_.end(); ++it) { | |
| 781 PolicyMap::const_iterator policy_it = policies_by_guid.find(*it); | |
| 782 if (policy_it == policies_by_guid.end()) { | |
| 783 LOG(ERROR) << "Policy " << *it << " doesn't exist anymore."; | |
| 784 continue; | |
| 785 } | |
| 786 | |
| 787 const base::DictionaryValue* policy = policy_it->second; | |
| 788 | |
| 789 VLOG(1) << "Creating new configuration managed by policy " << *it | |
| 790 << " in profile " << profile_path_ << "."; | |
| 791 | |
| 792 scoped_ptr<base::DictionaryValue> shill_dictionary = | |
| 793 CreateShillConfiguration(profile_path_, *it, policy, NULL); | |
| 794 NetworkConfigurationHandler::Get()->CreateConfiguration( | |
| 795 *shill_dictionary, | |
| 796 base::Bind(&IgnoreString), | |
| 797 base::Bind(&IgnoreErrorDict)); | |
| 798 } | |
| 799 } | |
| 800 | |
| 801 std::set<std::string> remaining_policies_; | |
| 802 base::WeakPtr<ManagedNetworkConfigurationHandler> handler_; | |
| 803 std::string profile_path_; | |
| 804 | |
| 805 DISALLOW_COPY_AND_ASSIGN(PolicyApplicator); | |
| 806 }; | |
| 807 | |
| 808 void ManagedNetworkConfigurationHandler::SetPolicy( | |
| 809 onc::ONCSource onc_source, | |
| 810 const base::DictionaryValue& onc_dict) { | |
| 811 VLOG(1) << "Setting policies for ONC source " | |
| 812 << onc::GetSourceAsString(onc_source) << "."; | |
| 813 | |
| 814 // Validate the ONC dictionary. We are liberal and ignore unknown field | |
| 815 // names and ignore invalid field names in kRecommended arrays. | |
| 816 onc::Validator validator(false, // Ignore unknown fields. | |
| 817 false, // Ignore invalid recommended field names. | |
| 818 true, // Fail on missing fields. | |
| 819 true); // This ONC comes from policy. | |
| 820 validator.SetOncSource(onc_source); | |
| 821 | |
| 822 onc::Validator::Result validation_result; | |
| 823 scoped_ptr<base::DictionaryValue> onc_validated = | |
| 824 validator.ValidateAndRepairObject( | |
| 825 &onc::kToplevelConfigurationSignature, | |
| 826 onc_dict, | |
| 827 &validation_result); | |
| 828 | |
| 829 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) { | |
| 830 LOG(WARNING) << "ONC from " << onc::GetSourceAsString(onc_source) | |
| 831 << " produced warnings."; | |
| 832 } else if (validation_result == onc::Validator::INVALID || | |
| 833 onc_validated == NULL) { | |
| 834 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) | |
|
pastarmovj
2013/04/11 14:46:29
It there a chance you are leaking here infromation
pneubeck (no reviews)
2013/04/15 12:16:24
Good point.
In most places I only log things like
| |
| 835 << " is invalid and couldn't be repaired."; | |
| 836 return; | |
| 837 } | |
| 838 | |
| 839 scoped_ptr<PolicyMap>* policies; | |
| 840 std::string profile; | |
| 841 if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY) { | |
| 842 policies = &user_policies_by_guid_; | |
| 843 profile = kUserProfilePath; | |
| 844 } else { | |
| 845 policies = &device_policies_by_guid_; | |
| 846 profile = kSharedProfilePath; | |
| 847 } | |
| 848 | |
| 849 if (!*policies) | |
| 850 policies->reset(new PolicyMap); | |
| 851 | |
| 852 PolicyMap old_policies; | |
| 853 scoped_ptr<std::set<std::string> > modified_policies( | |
| 854 new std::set<std::string>()); | |
|
stevenjb
2013/04/11 18:20:08
As noted above, this should just be 'std::set<std:
pneubeck (no reviews)
2013/04/15 12:16:24
Cannot move it much further, as it must stay in fr
| |
| 855 (*policies)->swap(old_policies); | |
| 856 | |
| 857 base::ListValue* network_configurations = NULL; | |
| 858 onc_validated->GetListWithoutPathExpansion( | |
| 859 onc::toplevel_config::kNetworkConfigurations, | |
| 860 &network_configurations); | |
| 861 | |
| 862 if (network_configurations) { | |
| 863 while (!network_configurations->empty()) { | |
| 864 base::Value* network_value = NULL; | |
| 865 // Passes ownership of network_value. | |
| 866 network_configurations->Remove(network_configurations->GetSize() - 1, | |
| 867 &network_value); | |
| 868 const base::DictionaryValue* network = NULL; | |
| 869 network_value->GetAsDictionary(&network); | |
| 870 std::string guid; | |
| 871 network->GetStringWithoutPathExpansion(onc::network_config::kGUID, | |
| 872 &guid); | |
| 873 | |
| 874 const base::DictionaryValue* old_entry = old_policies[guid]; | |
| 875 const base::DictionaryValue*& new_entry = (**policies)[guid]; | |
| 876 if (new_entry) { | |
| 877 LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source) | |
| 878 << " contains several entries for the same GUID " | |
| 879 << guid << "."; | |
| 880 delete new_entry; | |
| 881 } | |
| 882 new_entry = network; | |
| 883 | |
| 884 if (!old_entry || !old_entry->Equals(new_entry)) { | |
| 885 modified_policies->insert(guid); | |
| 886 } | |
| 887 } | |
| 888 } | |
| 889 | |
| 890 STLDeleteValues(&old_policies); | |
| 891 | |
| 892 (new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), | |
|
pastarmovj
2013/04/11 14:46:29
That a little bit too function-programming-y for C
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 893 profile, | |
| 894 modified_policies.Pass()))->Run(); | |
| 895 } | |
| 896 | |
| 897 const ManagedNetworkConfigurationHandler::PolicyMap* | |
| 898 ManagedNetworkConfigurationHandler::GetPoliciesForProfile( | |
| 899 const std::string& profile) const { | |
| 900 if (profile == kSharedProfilePath) { | |
| 901 return device_policies_by_guid_.get(); | |
| 902 } else { | |
| 903 return user_policies_by_guid_.get(); | |
| 904 } | |
|
stevenjb
2013/04/11 18:20:08
nit: no {}
pneubeck (no reviews)
2013/04/15 12:16:24
Done.
| |
| 905 } | |
| 906 | |
| 907 ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler() | |
| 908 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
| 201 } | 909 } |
| 202 | 910 |
| 203 ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() { | 911 ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() { |
| 912 STLDeleteValues(user_policies_by_guid_.get()); | |
| 913 STLDeleteValues(device_policies_by_guid_.get()); | |
| 204 } | 914 } |
| 205 | 915 |
| 206 } // namespace chromeos | 916 } // namespace chromeos |
| OLD | NEW |