This source file includes following definitions.
- LogErrorMessage
- GetByGUID
- profile_
- Run
- GetProfilePropertiesCallback
- GetEntryCallback
- DeleteEntry
- WriteNewShillConfiguration
- GetPropertiesForUnmanagedEntry
- ApplyRemainingPolicies
#include "chromeos/network/policy_applicator.h"
#include <utility>
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/policy_util.h"
#include "chromeos/network/shill_property_util.h"
#include "components/onc/onc_constants.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace {
void LogErrorMessage(const tracked_objects::Location& from_where,
const std::string& error_name,
const std::string& error_message) {
LOG(ERROR) << from_where.ToString() << ": " << error_message;
}
const base::DictionaryValue* GetByGUID(
const PolicyApplicator::GuidToPolicyMap& policies,
const std::string& guid) {
PolicyApplicator::GuidToPolicyMap::const_iterator it = policies.find(guid);
if (it == policies.end())
return NULL;
return it->second;
}
}
PolicyApplicator::PolicyApplicator(
base::WeakPtr<ConfigurationHandler> handler,
const NetworkProfile& profile,
const GuidToPolicyMap& all_policies,
const base::DictionaryValue& global_network_config,
std::set<std::string>* modified_policies)
: handler_(handler), profile_(profile) {
global_network_config_.MergeDictionary(&global_network_config);
remaining_policies_.swap(*modified_policies);
for (GuidToPolicyMap::const_iterator it = all_policies.begin();
it != all_policies.end(); ++it) {
all_policies_.insert(std::make_pair(it->first, it->second->DeepCopy()));
}
}
void PolicyApplicator::Run() {
DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
dbus::ObjectPath(profile_.path),
base::Bind(&PolicyApplicator::GetProfilePropertiesCallback, this),
base::Bind(&LogErrorMessage, FROM_HERE));
}
void PolicyApplicator::GetProfilePropertiesCallback(
const base::DictionaryValue& profile_properties) {
if (!handler_) {
LOG(WARNING) << "Handler destructed during policy application to profile "
<< profile_.ToDebugString();
return;
}
VLOG(2) << "Received properties for profile " << profile_.ToDebugString();
const base::ListValue* entries = NULL;
if (!profile_properties.GetListWithoutPathExpansion(
shill::kEntriesProperty, &entries)) {
LOG(ERROR) << "Profile " << profile_.ToDebugString()
<< " doesn't contain the property "
<< shill::kEntriesProperty;
return;
}
for (base::ListValue::const_iterator it = entries->begin();
it != entries->end(); ++it) {
std::string entry;
(*it)->GetAsString(&entry);
DBusThreadManager::Get()->GetShillProfileClient()->GetEntry(
dbus::ObjectPath(profile_.path),
entry,
base::Bind(&PolicyApplicator::GetEntryCallback, this, entry),
base::Bind(&LogErrorMessage, FROM_HERE));
}
}
void PolicyApplicator::GetEntryCallback(
const std::string& entry,
const base::DictionaryValue& entry_properties) {
if (!handler_) {
LOG(WARNING) << "Handler destructed during policy application to profile "
<< profile_.ToDebugString();
return;
}
VLOG(2) << "Received properties for entry " << entry << " of profile "
<< profile_.ToDebugString();
scoped_ptr<base::DictionaryValue> onc_part(
onc::TranslateShillServiceToONCPart(entry_properties,
&onc::kNetworkWithStateSignature));
std::string old_guid;
if (!onc_part->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
&old_guid)) {
VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
<< " doesn't contain a GUID.";
}
scoped_ptr<NetworkUIData> ui_data =
shill_property_util::GetUIDataFromProperties(entry_properties);
if (!ui_data) {
VLOG(1) << "Entry " << entry << " of profile " << profile_.ToDebugString()
<< " contains no or no valid UIData.";
old_guid.clear();
}
bool was_managed = !old_guid.empty() && ui_data &&
(ui_data->onc_source() ==
::onc::ONC_SOURCE_DEVICE_POLICY ||
ui_data->onc_source() == ::onc::ONC_SOURCE_USER_POLICY);
const base::DictionaryValue* new_policy = NULL;
if (was_managed) {
new_policy = GetByGUID(all_policies_, old_guid);
}
if (!new_policy) {
new_policy = policy_util::FindMatchingPolicy(all_policies_, *onc_part);
}
if (new_policy) {
std::string new_guid;
new_policy->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
&new_guid);
VLOG_IF(1, was_managed && old_guid != new_guid)
<< "Updating configuration previously managed by policy " << old_guid
<< " with new policy " << new_guid << ".";
VLOG_IF(1, !was_managed) << "Applying policy " << new_guid
<< " to previously unmanaged "
<< "configuration.";
if (old_guid == new_guid &&
remaining_policies_.find(new_guid) == remaining_policies_.end()) {
VLOG(1) << "Not updating existing managed configuration with guid "
<< new_guid << " because the policy didn't change.";
} else {
const base::DictionaryValue* user_settings =
ui_data ? ui_data->user_settings() : NULL;
scoped_ptr<base::DictionaryValue> new_shill_properties =
policy_util::CreateShillConfiguration(
profile_, new_guid, new_policy, user_settings);
if (old_guid == new_guid &&
shill_property_util::DoIdentifyingPropertiesMatch(
*new_shill_properties, entry_properties)) {
VLOG(1) << "Updating previously managed configuration with the "
<< "updated policy " << new_guid << ".";
} else {
VLOG(1) << "Deleting profile entry before writing new policy "
<< new_guid << " because of identifying properties changed.";
DeleteEntry(entry);
}
WriteNewShillConfiguration(*new_shill_properties, *new_policy, true);
remaining_policies_.erase(new_guid);
}
} else if (was_managed) {
VLOG(1) << "Removing configuration previously managed by policy "
<< old_guid << ", because the policy was removed.";
DeleteEntry(entry);
} else {
base::DictionaryValue shill_properties_to_update;
GetPropertiesForUnmanagedEntry(entry_properties,
&shill_properties_to_update);
if (shill_properties_to_update.empty()) {
VLOG(2) << "Ignore unmanaged entry.";
} else {
VLOG(2) << "Apply global network config to unmanaged entry.";
handler_->UpdateExistingConfigurationWithPropertiesFromPolicy(
entry_properties, shill_properties_to_update);
}
}
}
void PolicyApplicator::DeleteEntry(const std::string& entry) {
DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
dbus::ObjectPath(profile_.path),
entry,
base::Bind(&base::DoNothing),
base::Bind(&LogErrorMessage, FROM_HERE));
}
void PolicyApplicator::WriteNewShillConfiguration(
const base::DictionaryValue& shill_dictionary,
const base::DictionaryValue& policy,
bool write_later) {
std::string type;
policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type);
if (type == ::onc::network_type::kEthernet &&
profile_.type() == NetworkProfile::TYPE_USER) {
const base::DictionaryValue* ethernet = NULL;
policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet,
ðernet);
std::string auth;
ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
&auth);
if (auth == ::onc::ethernet::kNone)
return;
}
if (write_later)
new_shill_configurations_.push_back(shill_dictionary.DeepCopy());
else
handler_->CreateConfigurationFromPolicy(shill_dictionary);
}
void PolicyApplicator::GetPropertiesForUnmanagedEntry(
const base::DictionaryValue& entry_properties,
base::DictionaryValue* properties_to_update) const {
std::string type;
entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
if (NetworkTypePattern::Ethernet().MatchesType(type))
return;
bool only_policy_autoconnect = false;
global_network_config_.GetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
&only_policy_autoconnect);
if (!only_policy_autoconnect)
return;
bool old_autoconnect = false;
if (entry_properties.GetBooleanWithoutPathExpansion(
shill::kAutoConnectProperty, &old_autoconnect) &&
!old_autoconnect) {
return;
}
properties_to_update->SetBooleanWithoutPathExpansion(
shill::kAutoConnectProperty, false);
}
PolicyApplicator::~PolicyApplicator() {
ApplyRemainingPolicies();
STLDeleteValues(&all_policies_);
if (handler_)
handler_->OnPoliciesApplied();
}
void PolicyApplicator::ApplyRemainingPolicies() {
if (!handler_) {
LOG(WARNING) << "Handler destructed during policy application to profile "
<< profile_.ToDebugString();
return;
}
for (ScopedVector<base::DictionaryValue>::const_iterator it =
new_shill_configurations_.begin();
it != new_shill_configurations_.end();
++it) {
handler_->CreateConfigurationFromPolicy(**it);
}
if (remaining_policies_.empty())
return;
VLOG(2) << "Create new managed network configurations in profile"
<< profile_.ToDebugString() << ".";
for (std::set<std::string>::iterator it = remaining_policies_.begin();
it != remaining_policies_.end(); ++it) {
const base::DictionaryValue* policy = GetByGUID(all_policies_, *it);
DCHECK(policy);
VLOG(1) << "Creating new configuration managed by policy " << *it
<< " in profile " << profile_.ToDebugString() << ".";
scoped_ptr<base::DictionaryValue> shill_dictionary =
policy_util::CreateShillConfiguration(profile_, *it, policy, NULL);
WriteNewShillConfiguration(*shill_dictionary, *policy, false);
}
}
}