11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2013 The Chromium Authors. All rights reserved. 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Use of this source code is governed by a BSD-style license that can be 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// found in the LICENSE file. 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/managed_network_configuration_handler_impl.h" 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <set> 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <vector> 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/bind.h" 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/guid.h" 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/location.h" 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/logging.h" 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/memory/ref_counted.h" 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/memory/scoped_ptr.h" 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/stl_util.h" 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/values.h" 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/dbus/shill_manager_client.h" 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/dbus/shill_profile_client.h" 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/dbus/shill_service_client.h" 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/device_state.h" 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_configuration_handler.h" 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_device_handler.h" 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_event_log.h" 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_policy_observer.h" 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_profile.h" 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_profile_handler.h" 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_state.h" 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_state_handler.h" 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/network_ui_data.h" 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/onc/onc_merger.h" 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/onc/onc_signature.h" 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/onc/onc_translator.h" 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/onc/onc_validator.h" 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/policy_util.h" 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chromeos/network/shill_property_util.h" 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "components/onc/onc_constants.h" 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "third_party/cros_system_api/dbus/service_constants.h" 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertnamespace chromeos { 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertnamespace { 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringerttypedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap; 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// These are error strings used for error callbacks. None of these error 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// messages are user-facing: they should only appear in logs. 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kInvalidUserSettings[] = "InvalidUserSettings"; 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kNetworkAlreadyConfigured[] = "NetworkAlreadyConfigured"; 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kPoliciesNotInitialized[] = "PoliciesNotInitialized"; 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kProfileNotInitialized[] = "ProflieNotInitialized"; 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kSetOnUnconfiguredNetwork[] = "SetCalledOnUnconfiguredNetwork"; 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kUnknownProfilePath[] = "UnknownProfilePath"; 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst char kUnknownNetwork[] = "UnknownNetwork"; 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstd::string ToDebugString(::onc::ONCSource source, 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& userhash) { 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return source == ::onc::ONC_SOURCE_USER_POLICY ? 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ("user policy of " + userhash) : "device policy"; 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid InvokeErrorCallback(const std::string& service_path, 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const network_handler::ErrorCallback& error_callback, 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& error_name) { 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert std::string error_msg = "ManagedConfig Error: " + error_name; 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NET_LOG_ERROR(error_msg, service_path); 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert network_handler::RunErrorCallback( 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert error_callback, service_path, error_name, error_msg); 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid LogErrorWithDict(const tracked_objects::Location& from_where, 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& error_name, 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert scoped_ptr<base::DictionaryValue> error_data) { 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert network_event_log::internal::AddEntry( 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert from_where.file_name(), from_where.line_number(), 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert network_event_log::LOG_LEVEL_ERROR, 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert error_name, ""); 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies, 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& guid) { 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GuidToPolicyMap::const_iterator it = policies.find(guid); 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (it == policies.end()) 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return NULL; 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return it->second; 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} // namespace 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstruct ManagedNetworkConfigurationHandlerImpl::Policies { 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert ~Policies(); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert GuidToPolicyMap per_network_config; 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert base::DictionaryValue global_network_config; 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}; 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn BringertManagedNetworkConfigurationHandlerImpl::Policies::~Policies() { 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert STLDeleteValues(&per_network_config); 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid ManagedNetworkConfigurationHandlerImpl::AddObserver( 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NetworkPolicyObserver* observer) { 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert observers_.AddObserver(observer); 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid ManagedNetworkConfigurationHandlerImpl::RemoveObserver( 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert NetworkPolicyObserver* observer) { 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert observers_.RemoveObserver(observer); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// GetManagedProperties 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid ManagedNetworkConfigurationHandlerImpl::GetManagedProperties( 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& userhash, 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& service_path, 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const network_handler::DictionaryResultCallback& callback, 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const network_handler::ErrorCallback& error_callback) { 1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) { 1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); 1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return; 1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert network_configuration_handler_->GetProperties( 1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert service_path, 1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert base::Bind( 1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, 1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert weak_ptr_factory_.GetWeakPtr(), 1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert base::Bind( 1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert &ManagedNetworkConfigurationHandlerImpl::SendManagedProperties, 1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert weak_ptr_factory_.GetWeakPtr(), 1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert userhash, 1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert callback, 1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert error_callback)), 1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert error_callback); 1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid ManagedNetworkConfigurationHandlerImpl::SendManagedProperties( 1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& userhash, 1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const network_handler::DictionaryResultCallback& callback, 1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const network_handler::ErrorCallback& error_callback, 1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::string& service_path, 1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert scoped_ptr<base::DictionaryValue> shill_properties) { 1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert std::string profile_path; 143 shill_properties->GetStringWithoutPathExpansion(shill::kProfileProperty, 144 &profile_path); 145 const NetworkProfile* profile = 146 network_profile_handler_->GetProfileForPath(profile_path); 147 if (!profile) 148 NET_LOG_ERROR("No profile for service: " + profile_path, service_path); 149 150 scoped_ptr<NetworkUIData> ui_data = 151 shill_property_util::GetUIDataFromProperties(*shill_properties); 152 153 const base::DictionaryValue* user_settings = NULL; 154 155 if (ui_data && profile) { 156 user_settings = ui_data->user_settings(); 157 } else if (profile) { 158 NET_LOG_ERROR("Service contains empty or invalid UIData", service_path); 159 // TODO(pneubeck): add a conversion of user configured entries of old 160 // ChromeOS versions. We will have to use a heuristic to determine which 161 // properties _might_ be user configured. 162 } 163 164 std::string guid; 165 shill_properties->GetStringWithoutPathExpansion(shill::kGuidProperty, &guid); 166 167 ::onc::ONCSource onc_source; 168 FindPolicyByGUID(userhash, guid, &onc_source); 169 scoped_ptr<base::DictionaryValue> active_settings( 170 onc::TranslateShillServiceToONCPart( 171 *shill_properties, onc_source, &onc::kNetworkWithStateSignature)); 172 173 const base::DictionaryValue* network_policy = NULL; 174 const base::DictionaryValue* global_policy = NULL; 175 if (profile) { 176 const Policies* policies = GetPoliciesForProfile(*profile); 177 if (!policies) { 178 InvokeErrorCallback( 179 service_path, error_callback, kPoliciesNotInitialized); 180 return; 181 } 182 if (!guid.empty()) 183 network_policy = GetByGUID(policies->per_network_config, guid); 184 global_policy = &policies->global_network_config; 185 } 186 187 scoped_ptr<base::DictionaryValue> augmented_properties( 188 policy_util::CreateManagedONC(global_policy, 189 network_policy, 190 user_settings, 191 active_settings.get(), 192 profile)); 193 callback.Run(service_path, *augmented_properties); 194} 195 196// GetProperties 197 198void ManagedNetworkConfigurationHandlerImpl::GetProperties( 199 const std::string& service_path, 200 const network_handler::DictionaryResultCallback& callback, 201 const network_handler::ErrorCallback& error_callback) { 202 network_configuration_handler_->GetProperties( 203 service_path, 204 base::Bind( 205 &ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback, 206 weak_ptr_factory_.GetWeakPtr(), 207 base::Bind(&ManagedNetworkConfigurationHandlerImpl::SendProperties, 208 weak_ptr_factory_.GetWeakPtr(), 209 callback, 210 error_callback)), 211 error_callback); 212} 213 214void ManagedNetworkConfigurationHandlerImpl::SendProperties( 215 const network_handler::DictionaryResultCallback& callback, 216 const network_handler::ErrorCallback& error_callback, 217 const std::string& service_path, 218 scoped_ptr<base::DictionaryValue> shill_properties) { 219 scoped_ptr<base::DictionaryValue> onc_network( 220 onc::TranslateShillServiceToONCPart( 221 *shill_properties, ::onc::ONC_SOURCE_UNKNOWN, 222 &onc::kNetworkWithStateSignature)); 223 callback.Run(service_path, *onc_network); 224} 225 226// SetProperties 227 228void ManagedNetworkConfigurationHandlerImpl::SetProperties( 229 const std::string& service_path, 230 const base::DictionaryValue& user_settings, 231 const base::Closure& callback, 232 const network_handler::ErrorCallback& error_callback) const { 233 const NetworkState* state = 234 network_state_handler_->GetNetworkStateFromServicePath( 235 service_path, true /* configured_only */); 236 if (!state) { 237 InvokeErrorCallback(service_path, error_callback, kUnknownNetwork); 238 return; 239 } 240 241 std::string guid = state->guid(); 242 if (guid.empty()) { 243 // TODO(pneubeck): create an initial configuration in this case. As for 244 // CreateConfiguration, user settings from older ChromeOS versions have to 245 // determined here. 246 InvokeErrorCallback( 247 service_path, error_callback, kSetOnUnconfiguredNetwork); 248 return; 249 } 250 251 const std::string& profile_path = state->profile_path(); 252 const NetworkProfile *profile = 253 network_profile_handler_->GetProfileForPath(profile_path); 254 if (!profile) { 255 InvokeErrorCallback(service_path, error_callback, kUnknownProfilePath); 256 return; 257 } 258 259 VLOG(2) << "SetProperties: Found GUID " << guid << " and profile " 260 << profile->ToDebugString(); 261 262 const Policies* policies = GetPoliciesForProfile(*profile); 263 if (!policies) { 264 InvokeErrorCallback(service_path, error_callback, kPoliciesNotInitialized); 265 return; 266 } 267 268 // Validate the ONC dictionary. We are liberal and ignore unknown field 269 // names. User settings are only partial ONC, thus we ignore missing fields. 270 onc::Validator validator(false, // Ignore unknown fields. 271 false, // Ignore invalid recommended field names. 272 false, // Ignore missing fields. 273 false); // This ONC does not come from policy. 274 275 onc::Validator::Result validation_result; 276 scoped_ptr<base::DictionaryValue> validated_user_settings = 277 validator.ValidateAndRepairObject( 278 &onc::kNetworkConfigurationSignature, 279 user_settings, 280 &validation_result); 281 282 if (validation_result == onc::Validator::INVALID) { 283 InvokeErrorCallback(service_path, error_callback, kInvalidUserSettings); 284 return; 285 } 286 if (validation_result == onc::Validator::VALID_WITH_WARNINGS) 287 LOG(WARNING) << "Validation of ONC user settings produced warnings."; 288 289 const base::DictionaryValue* network_policy = 290 GetByGUID(policies->per_network_config, guid); 291 VLOG(2) << "This configuration is " << (network_policy ? "" : "not ") 292 << "managed."; 293 294 scoped_ptr<base::DictionaryValue> shill_dictionary( 295 policy_util::CreateShillConfiguration(*profile, 296 guid, 297 &policies->global_network_config, 298 network_policy, 299 validated_user_settings.get())); 300 301 network_configuration_handler_->SetProperties( 302 service_path, *shill_dictionary, callback, error_callback); 303} 304 305void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( 306 const std::string& userhash, 307 const base::DictionaryValue& properties, 308 const network_handler::StringResultCallback& callback, 309 const network_handler::ErrorCallback& error_callback) const { 310 const Policies* policies = GetPoliciesForUser(userhash); 311 if (!policies) { 312 InvokeErrorCallback("", error_callback, kPoliciesNotInitialized); 313 return; 314 } 315 316 if (policy_util::FindMatchingPolicy(policies->per_network_config, 317 properties)) { 318 InvokeErrorCallback("", error_callback, kNetworkAlreadyConfigured); 319 return; 320 } 321 322 const NetworkProfile* profile = 323 network_profile_handler_->GetProfileForUserhash(userhash); 324 if (!profile) { 325 InvokeErrorCallback("", error_callback, kProfileNotInitialized); 326 return; 327 } 328 329 // TODO(pneubeck): In case of WiFi, check that no other configuration for the 330 // same {SSID, mode, security} exists. We don't support such multiple 331 // configurations, yet. 332 333 // Generate a new GUID for this configuration. Ignore the maybe provided GUID 334 // in |properties| as it is not our own and from an untrusted source. 335 std::string guid = base::GenerateGUID(); 336 scoped_ptr<base::DictionaryValue> shill_dictionary( 337 policy_util::CreateShillConfiguration(*profile, 338 guid, 339 NULL, // no global policy 340 NULL, // no network policy 341 &properties)); 342 343 network_configuration_handler_->CreateConfiguration( 344 *shill_dictionary, callback, error_callback); 345} 346 347void ManagedNetworkConfigurationHandlerImpl::RemoveConfiguration( 348 const std::string& service_path, 349 const base::Closure& callback, 350 const network_handler::ErrorCallback& error_callback) const { 351 network_configuration_handler_->RemoveConfiguration( 352 service_path, callback, error_callback); 353} 354 355void ManagedNetworkConfigurationHandlerImpl::SetPolicy( 356 ::onc::ONCSource onc_source, 357 const std::string& userhash, 358 const base::ListValue& network_configs_onc, 359 const base::DictionaryValue& global_network_config) { 360 VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash) 361 << "."; 362 363 // |userhash| must be empty for device policies. 364 DCHECK(onc_source != ::onc::ONC_SOURCE_DEVICE_POLICY || 365 userhash.empty()); 366 Policies* policies = NULL; 367 if (ContainsKey(policies_by_user_, userhash)) { 368 policies = policies_by_user_[userhash].get(); 369 } else { 370 policies = new Policies; 371 policies_by_user_[userhash] = make_linked_ptr(policies); 372 } 373 374 policies->global_network_config.MergeDictionary(&global_network_config); 375 376 GuidToPolicyMap old_per_network_config; 377 policies->per_network_config.swap(old_per_network_config); 378 379 // This stores all GUIDs of policies that have changed or are new. 380 std::set<std::string> modified_policies; 381 382 for (base::ListValue::const_iterator it = network_configs_onc.begin(); 383 it != network_configs_onc.end(); ++it) { 384 const base::DictionaryValue* network = NULL; 385 (*it)->GetAsDictionary(&network); 386 DCHECK(network); 387 388 std::string guid; 389 network->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid); 390 DCHECK(!guid.empty()); 391 392 if (policies->per_network_config.count(guid) > 0) { 393 NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) + 394 " contains several entries for the same GUID ", guid); 395 delete policies->per_network_config[guid]; 396 } 397 const base::DictionaryValue* new_entry = network->DeepCopy(); 398 policies->per_network_config[guid] = new_entry; 399 400 const base::DictionaryValue* old_entry = old_per_network_config[guid]; 401 if (!old_entry || !old_entry->Equals(new_entry)) 402 modified_policies.insert(guid); 403 } 404 405 STLDeleteValues(&old_per_network_config); 406 407 const NetworkProfile* profile = 408 network_profile_handler_->GetProfileForUserhash(userhash); 409 if (profile) { 410 scoped_refptr<PolicyApplicator> applicator = 411 new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), 412 *profile, 413 policies->per_network_config, 414 policies->global_network_config, 415 &modified_policies); 416 applicator->Run(); 417 } else { 418 VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing " 419 << "policy application."; 420 // See OnProfileAdded. 421 } 422 423 FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash)); 424} 425 426void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded( 427 const NetworkProfile& profile) { 428 VLOG(1) << "Adding profile " << profile.ToDebugString() << "'."; 429 430 const Policies* policies = GetPoliciesForProfile(profile); 431 if (!policies) { 432 VLOG(1) << "The relevant policy is not initialized, " 433 << "postponing policy application."; 434 // See SetPolicy. 435 return; 436 } 437 438 std::set<std::string> policy_guids; 439 for (GuidToPolicyMap::const_iterator it = 440 policies->per_network_config.begin(); 441 it != policies->per_network_config.end(); ++it) { 442 policy_guids.insert(it->first); 443 } 444 445 scoped_refptr<PolicyApplicator> applicator = 446 new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(), 447 profile, 448 policies->per_network_config, 449 policies->global_network_config, 450 &policy_guids); 451 applicator->Run(); 452} 453 454void ManagedNetworkConfigurationHandlerImpl::OnProfileRemoved( 455 const NetworkProfile& profile) { 456 // Nothing to do in this case. 457} 458 459void ManagedNetworkConfigurationHandlerImpl::CreateConfigurationFromPolicy( 460 const base::DictionaryValue& shill_properties) { 461 network_configuration_handler_->CreateConfiguration( 462 shill_properties, 463 base::Bind( 464 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, 465 weak_ptr_factory_.GetWeakPtr()), 466 base::Bind(&LogErrorWithDict, FROM_HERE)); 467} 468 469void ManagedNetworkConfigurationHandlerImpl:: 470 UpdateExistingConfigurationWithPropertiesFromPolicy( 471 const base::DictionaryValue& existing_properties, 472 const base::DictionaryValue& new_properties) { 473 base::DictionaryValue shill_properties; 474 475 std::string profile; 476 existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty, 477 &profile); 478 if (profile.empty()) { 479 NET_LOG_ERROR("Missing profile property", 480 shill_property_util::GetNetworkIdFromProperties( 481 existing_properties)); 482 return; 483 } 484 shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty, 485 profile); 486 487 if (!shill_property_util::CopyIdentifyingProperties( 488 existing_properties, 489 true /* properties were read from Shill */, 490 &shill_properties)) { 491 NET_LOG_ERROR("Missing identifying properties", 492 shill_property_util::GetNetworkIdFromProperties( 493 existing_properties)); 494 } 495 496 shill_properties.MergeDictionary(&new_properties); 497 498 network_configuration_handler_->CreateConfiguration( 499 shill_properties, 500 base::Bind( 501 &ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork, 502 weak_ptr_factory_.GetWeakPtr()), 503 base::Bind(&LogErrorWithDict, FROM_HERE)); 504} 505 506void ManagedNetworkConfigurationHandlerImpl::OnPoliciesApplied() { 507} 508 509const base::DictionaryValue* 510ManagedNetworkConfigurationHandlerImpl::FindPolicyByGUID( 511 const std::string userhash, 512 const std::string& guid, 513 ::onc::ONCSource* onc_source) const { 514 *onc_source = ::onc::ONC_SOURCE_NONE; 515 516 if (!userhash.empty()) { 517 const Policies* user_policies = GetPoliciesForUser(userhash); 518 if (user_policies) { 519 const base::DictionaryValue* policy = 520 GetByGUID(user_policies->per_network_config, guid); 521 if (policy) { 522 *onc_source = ::onc::ONC_SOURCE_USER_POLICY; 523 return policy; 524 } 525 } 526 } 527 528 const Policies* device_policies = GetPoliciesForUser(std::string()); 529 if (device_policies) { 530 const base::DictionaryValue* policy = 531 GetByGUID(device_policies->per_network_config, guid); 532 if (policy) { 533 *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; 534 return policy; 535 } 536 } 537 538 return NULL; 539} 540 541const base::DictionaryValue* 542ManagedNetworkConfigurationHandlerImpl::GetGlobalConfigFromPolicy( 543 const std::string userhash) const { 544 const Policies* policies = GetPoliciesForUser(userhash); 545 if (!policies) 546 return NULL; 547 548 return &policies->global_network_config; 549} 550const base::DictionaryValue* 551ManagedNetworkConfigurationHandlerImpl::FindPolicyByGuidAndProfile( 552 const std::string& guid, 553 const std::string& profile_path) const { 554 const NetworkProfile* profile = 555 network_profile_handler_->GetProfileForPath(profile_path); 556 if (!profile) { 557 NET_LOG_ERROR("Profile path unknown:" + profile_path, guid); 558 return NULL; 559 } 560 561 const Policies* policies = GetPoliciesForProfile(*profile); 562 if (!policies) 563 return NULL; 564 565 return GetByGUID(policies->per_network_config, guid); 566} 567 568const ManagedNetworkConfigurationHandlerImpl::Policies* 569ManagedNetworkConfigurationHandlerImpl::GetPoliciesForUser( 570 const std::string& userhash) const { 571 UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash); 572 if (it == policies_by_user_.end()) 573 return NULL; 574 return it->second.get(); 575} 576 577const ManagedNetworkConfigurationHandlerImpl::Policies* 578ManagedNetworkConfigurationHandlerImpl::GetPoliciesForProfile( 579 const NetworkProfile& profile) const { 580 DCHECK(profile.type() != NetworkProfile::TYPE_SHARED || 581 profile.userhash.empty()); 582 return GetPoliciesForUser(profile.userhash); 583} 584 585ManagedNetworkConfigurationHandlerImpl::ManagedNetworkConfigurationHandlerImpl() 586 : network_state_handler_(NULL), 587 network_profile_handler_(NULL), 588 network_configuration_handler_(NULL), 589 network_device_handler_(NULL), 590 weak_ptr_factory_(this) {} 591 592ManagedNetworkConfigurationHandlerImpl:: 593 ~ManagedNetworkConfigurationHandlerImpl() { 594 network_profile_handler_->RemoveObserver(this); 595} 596 597void ManagedNetworkConfigurationHandlerImpl::Init( 598 NetworkStateHandler* network_state_handler, 599 NetworkProfileHandler* network_profile_handler, 600 NetworkConfigurationHandler* network_configuration_handler, 601 NetworkDeviceHandler* network_device_handler) { 602 network_state_handler_ = network_state_handler; 603 network_profile_handler_ = network_profile_handler; 604 network_configuration_handler_ = network_configuration_handler; 605 network_device_handler_ = network_device_handler; 606 network_profile_handler_->AddObserver(this); 607} 608 609void ManagedNetworkConfigurationHandlerImpl::OnPolicyAppliedToNetwork( 610 const std::string& service_path) { 611 if (service_path.empty()) 612 return; 613 FOR_EACH_OBSERVER( 614 NetworkPolicyObserver, observers_, PolicyApplied(service_path)); 615} 616 617// Get{Managed}Properties helpers 618 619void ManagedNetworkConfigurationHandlerImpl::GetDeviceStateProperties( 620 const std::string& service_path, 621 base::DictionaryValue* properties) { 622 std::string connection_state; 623 properties->GetStringWithoutPathExpansion( 624 shill::kStateProperty, &connection_state); 625 if (!NetworkState::StateIsConnected(connection_state)) 626 return; 627 628 // Get the IPConfig properties from the device and store them in "IPConfigs" 629 // (plural) in the properties dictionary. (Note: Shill only provides a single 630 // "IPConfig" property for a network service, but a consumer of this API may 631 // want information about all ipv4 and ipv6 IPConfig properties. 632 std::string device; 633 properties->GetStringWithoutPathExpansion(shill::kDeviceProperty, &device); 634 const DeviceState* device_state = 635 network_state_handler_->GetDeviceState(device); 636 if (!device_state) { 637 NET_LOG_ERROR("GetDeviceProperties: no device: " + device, service_path); 638 return; 639 } 640 641 // Get the hardware MAC address from the DeviceState. 642 if (!device_state->mac_address().empty()) { 643 properties->SetStringWithoutPathExpansion( 644 shill::kAddressProperty, device_state->mac_address()); 645 } 646 647 // Convert IPConfig dictionary to a ListValue. 648 base::ListValue* ip_configs = new base::ListValue; 649 for (base::DictionaryValue::Iterator iter(device_state->ip_configs()); 650 !iter.IsAtEnd(); iter.Advance()) { 651 ip_configs->Append(iter.value().DeepCopy()); 652 } 653 properties->SetWithoutPathExpansion(shill::kIPConfigsProperty, ip_configs); 654} 655 656void ManagedNetworkConfigurationHandlerImpl::GetPropertiesCallback( 657 GetDevicePropertiesCallback send_callback, 658 const std::string& service_path, 659 const base::DictionaryValue& shill_properties) { 660 scoped_ptr<base::DictionaryValue> shill_properties_copy( 661 shill_properties.DeepCopy()); 662 663 // Add associated Device properties before the ONC translation. 664 GetDeviceStateProperties(service_path, shill_properties_copy.get()); 665 666 // Only request Device properties for Cellular networks with a valid device. 667 std::string type, device_path; 668 if (!network_device_handler_ || 669 !shill_properties_copy->GetStringWithoutPathExpansion( 670 shill::kTypeProperty, &type) || 671 type != shill::kTypeCellular || 672 !shill_properties_copy->GetStringWithoutPathExpansion( 673 shill::kDeviceProperty, &device_path) || 674 device_path.empty()) { 675 send_callback.Run(service_path, shill_properties_copy.Pass()); 676 return; 677 } 678 679 // Request the device properties. On success or failure pass (a possibly 680 // modified) |shill_properties| to |send_callback|. 681 scoped_ptr<base::DictionaryValue> shill_properties_copy_error_copy( 682 shill_properties_copy->DeepCopy()); 683 network_device_handler_->GetDeviceProperties( 684 device_path, 685 base::Bind(&ManagedNetworkConfigurationHandlerImpl:: 686 GetDevicePropertiesSuccess, 687 weak_ptr_factory_.GetWeakPtr(), 688 service_path, 689 base::Passed(&shill_properties_copy), 690 send_callback), 691 base::Bind(&ManagedNetworkConfigurationHandlerImpl:: 692 GetDevicePropertiesFailure, 693 weak_ptr_factory_.GetWeakPtr(), 694 service_path, 695 base::Passed(&shill_properties_copy_error_copy), 696 send_callback)); 697} 698 699void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesSuccess( 700 const std::string& service_path, 701 scoped_ptr<base::DictionaryValue> network_properties, 702 GetDevicePropertiesCallback send_callback, 703 const std::string& device_path, 704 const base::DictionaryValue& device_properties) { 705 // Create a "Device" dictionary in |network_properties|. 706 network_properties->SetWithoutPathExpansion( 707 shill::kDeviceProperty, device_properties.DeepCopy()); 708 send_callback.Run(service_path, network_properties.Pass()); 709} 710 711void ManagedNetworkConfigurationHandlerImpl::GetDevicePropertiesFailure( 712 const std::string& service_path, 713 scoped_ptr<base::DictionaryValue> network_properties, 714 GetDevicePropertiesCallback send_callback, 715 const std::string& error_name, 716 scoped_ptr<base::DictionaryValue> error_data) { 717 NET_LOG_ERROR("Error getting device properties", service_path); 718 send_callback.Run(service_path, network_properties.Pass()); 719} 720 721 722} // namespace chromeos 723