policy_applicator.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/policy_applicator.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <utility> 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/bind.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/location.h" 114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/stl_util.h" 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/values.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/dbus/shill_profile_client.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/network_ui_data.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/onc/onc_signature.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/onc/onc_translator.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chromeos/network/policy_util.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/network/shill_property_util.h" 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/onc/onc_constants.h" 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "dbus/object_path.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace chromeos { 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace { 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid LogErrorMessage(const tracked_objects::Location& from_where, 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& error_name, 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& error_message) { 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << from_where.ToString() << ": " << error_message; 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const base::DictionaryValue* GetByGUID( 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const PolicyApplicator::GuidToPolicyMap& policies, 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& guid) { 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PolicyApplicator::GuidToPolicyMap::const_iterator it = policies.find(guid); 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (it == policies.end()) 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return it->second; 4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)PolicyApplicator::PolicyApplicator( 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::WeakPtr<ConfigurationHandler> handler, 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const NetworkProfile& profile, 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GuidToPolicyMap& all_policies, 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::DictionaryValue& global_network_config, 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::set<std::string>* modified_policies) 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : handler_(handler), profile_(profile) { 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) global_network_config_.MergeDictionary(&global_network_config); 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) remaining_policies_.swap(*modified_policies); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (GuidToPolicyMap::const_iterator it = all_policies.begin(); 578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) it != all_policies.end(); ++it) { 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy())); 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PolicyApplicator::Run() { 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DBusThreadManager::Get()->GetShillProfileClient()->GetProperties( 648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dbus::ObjectPath(profile_.path), 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this), 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&LogErrorMessage, FROM_HERE)); 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PolicyApplicator::GetProfilePropertiesCallback( 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::DictionaryValue& profile_properties) { 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!handler_) { 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Handler destructed during policy application to profile " 738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) << profile_.ToDebugString(); 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(2) << "Received properties for profile " << profile_.ToDebugString(); 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::ListValue* entries = NULL; 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!profile_properties.GetListWithoutPathExpansion( 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shill::kEntriesProperty, &entries)) { 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(ERROR) << "Profile " << profile_.ToDebugString() 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << " doesn't contain the property " 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << shill::kEntriesProperty; 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (base::ListValue::const_iterator it = entries->begin(); 888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) it != entries->end(); ++it) { 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string entry; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (*it)->GetAsString(&entry); 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DBusThreadManager::Get()->GetShillProfileClient()->GetEntry( 938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) dbus::ObjectPath(profile_.path), 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) entry, 95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&PolicyApplicator::GetEntryCallback, this, entry), 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::Bind(&LogErrorMessage, FROM_HERE)); 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void PolicyApplicator::GetEntryCallback( 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& entry, 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const base::DictionaryValue& entry_properties) { 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!handler_) { 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LOG(WARNING) << "Handler destructed during policy application to profile " 1058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) << profile_.ToDebugString(); 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(2) << "Received properties for entry " << entry << " of profile " 1108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) << profile_.ToDebugString(); 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::DictionaryValue> onc_part( 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) onc::TranslateShillServiceToONCPart(entry_properties, 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &onc::kNetworkWithStateSignature)); 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string old_guid; 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!onc_part->GetStringWithoutPathExpansion(::onc::network_config::kGUID, 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &old_guid)) { 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString() 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << " doesn't contain a GUID."; 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This might be an entry of an older ChromeOS version. Assume it to be 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // unmanaged. 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<NetworkUIData> ui_data = 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) shill_property_util::GetUIDataFromProperties(entry_properties); 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ui_data) { 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString() 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << " contains no or no valid UIData."; 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // This might be an entry of an older ChromeOS version. Assume it to be 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // unmanaged. It's an inconsistency if there is a GUID but no UIData, thus 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // clear the GUID just in case. 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) old_guid.clear(); 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool was_managed = !old_guid.empty() && ui_data && 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) (ui_data->onc_source() == 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ::onc::ONC_SOURCE_DEVICE_POLICY || 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ui_data->onc_source() == ::onc::ONC_SOURCE_USER_POLICY); 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::DictionaryValue* new_policy = NULL; 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (was_managed) { 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If we have a GUID that might match a current policy, do a lookup using 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // that GUID at first. In particular this is necessary, as some networks 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // can't be matched to policies by properties (e.g. VPN). 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new_policy = GetByGUID(all_policies_, old_guid); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!new_policy) { 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If we didn't find a policy by GUID, still a new policy might match. 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new_policy = policy_util::FindMatchingPolicy(all_policies_, *onc_part); 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (new_policy) { 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::string new_guid; 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new_policy->GetStringWithoutPathExpansion(::onc::network_config::kGUID, 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &new_guid); 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VLOG_IF(1, was_managed && old_guid != new_guid) 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "Updating configuration previously managed by policy " << old_guid 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << " with new policy " << new_guid << "."; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VLOG_IF(1, !was_managed) << "Applying policy " << new_guid 163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << " to previously unmanaged " 164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << "configuration."; 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (old_guid == new_guid && 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) remaining_policies_.find(new_guid) == remaining_policies_.end()) { 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) VLOG(1) << "Not updating existing managed configuration with guid " 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << new_guid << " because the policy didn't change."; 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::DictionaryValue* user_settings = 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ui_data ? ui_data->user_settings() : NULL; 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<base::DictionaryValue> new_shill_properties = 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) policy_util::CreateShillConfiguration( 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) profile_, new_guid, new_policy, user_settings); 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // A new policy has to be applied to this profile entry. In order to keep 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // implicit state of Shill like "connected successfully before", keep the 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // entry if a policy is reapplied (e.g. after reboot) or is updated. 179 // However, some Shill properties are used to identify the network and 180 // cannot be modified after initial configuration, so we have to delete 181 // the profile entry in these cases. Also, keeping Shill's state if the 182 // SSID changed might not be a good idea anyways. If the policy GUID 183 // changed, or there was no policy before, we delete the entry at first to 184 // ensure that no old configuration remains. 185 if (old_guid == new_guid && 186 shill_property_util::DoIdentifyingPropertiesMatch( 187 *new_shill_properties, entry_properties)) { 188 VLOG(1) << "Updating previously managed configuration with the " 189 << "updated policy " << new_guid << "."; 190 } else { 191 VLOG(1) << "Deleting profile entry before writing new policy " 192 << new_guid << " because of identifying properties changed."; 193 DeleteEntry(entry); 194 } 195 196 // In general, old entries should at first be deleted before new 197 // configurations are written to prevent inconsistencies. Therefore, we 198 // delay the writing of the new config here until ~PolicyApplicator. 199 // E.g. one problematic case is if a policy { {GUID=X, SSID=Y} } is 200 // applied to the profile entries 201 // { ENTRY1 = {GUID=X, SSID=X, USER_SETTINGS=X}, 202 // ENTRY2 = {SSID=Y, ... } }. 203 // At first ENTRY1 and ENTRY2 should be removed, then the new config be 204 // written and the result should be: 205 // { {GUID=X, SSID=Y, USER_SETTINGS=X} } 206 WriteNewShillConfiguration(*new_shill_properties, *new_policy, true); 207 remaining_policies_.erase(new_guid); 208 } 209 } else if (was_managed) { 210 VLOG(1) << "Removing configuration previously managed by policy " 211 << old_guid << ", because the policy was removed."; 212 213 // Remove the entry, because the network was managed but isn't anymore. 214 // Note: An alternative might be to preserve the user settings, but it's 215 // unclear which values originating the policy should be removed. 216 DeleteEntry(entry); 217 } else { 218 // The entry wasn't managed and doesn't match any current policy. Global 219 // network settings have to be applied. 220 base::DictionaryValue shill_properties_to_update; 221 GetPropertiesForUnmanagedEntry(entry_properties, 222 &shill_properties_to_update); 223 if (shill_properties_to_update.empty()) { 224 VLOG(2) << "Ignore unmanaged entry."; 225 // Calling a SetProperties of Shill with an empty dictionary is a no op. 226 } else { 227 VLOG(2) << "Apply global network config to unmanaged entry."; 228 handler_->UpdateExistingConfigurationWithPropertiesFromPolicy( 229 entry_properties, shill_properties_to_update); 230 } 231 } 232} 233 234void PolicyApplicator::DeleteEntry(const std::string& entry) { 235 DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry( 236 dbus::ObjectPath(profile_.path), 237 entry, 238 base::Bind(&base::DoNothing), 239 base::Bind(&LogErrorMessage, FROM_HERE)); 240} 241 242void PolicyApplicator::WriteNewShillConfiguration( 243 const base::DictionaryValue& shill_dictionary, 244 const base::DictionaryValue& policy, 245 bool write_later) { 246 // Ethernet (non EAP) settings, like GUID or UIData, cannot be stored per 247 // user. Abort in that case. 248 std::string type; 249 policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type); 250 if (type == ::onc::network_type::kEthernet && 251 profile_.type() == NetworkProfile::TYPE_USER) { 252 const base::DictionaryValue* ethernet = NULL; 253 policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet, 254 ðernet); 255 std::string auth; 256 ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, 257 &auth); 258 if (auth == ::onc::ethernet::kNone) 259 return; 260 } 261 262 if (write_later) 263 new_shill_configurations_.push_back(shill_dictionary.DeepCopy()); 264 else 265 handler_->CreateConfigurationFromPolicy(shill_dictionary); 266} 267 268void PolicyApplicator::GetPropertiesForUnmanagedEntry( 269 const base::DictionaryValue& entry_properties, 270 base::DictionaryValue* properties_to_update) const { 271 // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. 272 273 std::string type; 274 entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); 275 if (NetworkTypePattern::Ethernet().MatchesType(type)) 276 return; // Autoconnect for Ethernet cannot be configured. 277 278 // By default all networks are allowed to autoconnect. 279 bool only_policy_autoconnect = false; 280 global_network_config_.GetBooleanWithoutPathExpansion( 281 ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, 282 &only_policy_autoconnect); 283 if (!only_policy_autoconnect) 284 return; 285 286 bool old_autoconnect = false; 287 if (entry_properties.GetBooleanWithoutPathExpansion( 288 shill::kAutoConnectProperty, &old_autoconnect) && 289 !old_autoconnect) { 290 // Autoconnect is already explictly disabled. No need to set it again. 291 return; 292 } 293 // If autconnect is not explicitly set yet, it might automatically be enabled 294 // by Shill. To prevent that, disable it explicitly. 295 properties_to_update->SetBooleanWithoutPathExpansion( 296 shill::kAutoConnectProperty, false); 297} 298 299PolicyApplicator::~PolicyApplicator() { 300 ApplyRemainingPolicies(); 301 STLDeleteValues(&all_policies_); 302 // Notify the handler about all policies being applied, so that the network 303 // lists can be updated. 304 handler_->OnPoliciesApplied(); 305} 306 307void PolicyApplicator::ApplyRemainingPolicies() { 308 if (!handler_) { 309 LOG(WARNING) << "Handler destructed during policy application to profile " 310 << profile_.ToDebugString(); 311 return; 312 } 313 314 // Write all queued configurations now. 315 for (ScopedVector<base::DictionaryValue>::const_iterator it = 316 new_shill_configurations_.begin(); 317 it != new_shill_configurations_.end(); 318 ++it) { 319 handler_->CreateConfigurationFromPolicy(**it); 320 } 321 322 if (remaining_policies_.empty()) 323 return; 324 325 VLOG(2) << "Create new managed network configurations in profile" 326 << profile_.ToDebugString() << "."; 327 // All profile entries were compared to policies. |remaining_policies_| 328 // contains all modified policies that didn't match any entry. For these 329 // remaining policies, new configurations have to be created. 330 for (std::set<std::string>::iterator it = remaining_policies_.begin(); 331 it != remaining_policies_.end(); ++it) { 332 const base::DictionaryValue* policy = GetByGUID(all_policies_, *it); 333 DCHECK(policy); 334 335 VLOG(1) << "Creating new configuration managed by policy " << *it 336 << " in profile " << profile_.ToDebugString() << "."; 337 338 scoped_ptr<base::DictionaryValue> shill_dictionary = 339 policy_util::CreateShillConfiguration(profile_, *it, policy, NULL); 340 WriteNewShillConfiguration(*shill_dictionary, *policy, false); 341 } 342} 343 344} // namespace chromeos 345