diff options
author | pneubeck <pneubeck@chromium.org> | 2014-09-03 00:27:34 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-03 07:30:11 +0000 |
commit | fe3e74f327f252a00b0fb7c5291bd916e9feba85 (patch) | |
tree | f506bba6af3a008c5603d89bb8706385898c5678 | |
parent | 4423aeda2e5bcfef62cea3b08be9175f81bf5499 (diff) | |
download | chromium_src-fe3e74f327f252a00b0fb7c5291bd916e9feba85.zip chromium_src-fe3e74f327f252a00b0fb7c5291bd916e9feba85.tar.gz chromium_src-fe3e74f327f252a00b0fb7c5291bd916e9feba85.tar.bz2 |
Apply global auto connect ONC policy in GetManagedProperties.
BUG=279351
Review URL: https://codereview.chromium.org/510123004
Cr-Commit-Position: refs/heads/master@{#293091}
-rw-r--r-- | chromeos/network/managed_network_configuration_handler_impl.cc | 59 | ||||
-rw-r--r-- | chromeos/network/managed_network_configuration_handler_unittest.cc | 104 | ||||
-rw-r--r-- | chromeos/network/policy_applicator.cc | 59 | ||||
-rw-r--r-- | chromeos/network/policy_applicator.h | 8 | ||||
-rw-r--r-- | chromeos/network/policy_util.cc | 160 | ||||
-rw-r--r-- | chromeos/network/policy_util.h | 30 | ||||
-rw-r--r-- | chromeos/test/data/network/policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc | 21 |
7 files changed, 347 insertions, 94 deletions
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc index 21c225a..a2a58ca 100644 --- a/chromeos/network/managed_network_configuration_handler_impl.cc +++ b/chromeos/network/managed_network_configuration_handler_impl.cc @@ -149,15 +149,9 @@ void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties( shill_property_util::GetUIDataFromProperties(*shill_properties); const base::DictionaryValue* user_settings = NULL; - const base::DictionaryValue* shared_settings = NULL; if (ui_data && profile) { - if (profile->type() == NetworkProfile::TYPE_SHARED) - shared_settings = ui_data->user_settings(); - else if (profile->type() == NetworkProfile::TYPE_USER) - user_settings = ui_data->user_settings(); - else - NOTREACHED(); + user_settings = ui_data->user_settings(); } else if (profile) { NET_LOG_ERROR("Service contains empty or invalid UIData", service_path); // TODO(pneubeck): add a conversion of user configured entries of old @@ -174,34 +168,26 @@ void ManagedNetworkConfigurationHandlerImpl::SendManagedProperties( active_settings->GetStringWithoutPathExpansion(::onc::network_config::kGUID, &guid); - const base::DictionaryValue* user_policy = NULL; - const base::DictionaryValue* device_policy = NULL; - if (!guid.empty() && profile) { + const base::DictionaryValue* network_policy = NULL; + const base::DictionaryValue* global_policy = NULL; + if (profile) { const Policies* policies = GetPoliciesForProfile(*profile); if (!policies) { InvokeErrorCallback( service_path, error_callback, kPoliciesNotInitialized); return; } - const base::DictionaryValue* policy = - GetByGUID(policies->per_network_config, guid); - if (profile->type() == NetworkProfile::TYPE_SHARED) - device_policy = policy; - else if (profile->type() == NetworkProfile::TYPE_USER) - user_policy = policy; - else - NOTREACHED(); + if (!guid.empty()) + network_policy = GetByGUID(policies->per_network_config, guid); + global_policy = &policies->global_network_config; } - // This call also removes credentials from policies. - scoped_ptr<base::DictionaryValue> augmented_properties = - onc::MergeSettingsAndPoliciesToAugmented( - onc::kNetworkConfigurationSignature, - user_policy, - device_policy, - user_settings, - shared_settings, - active_settings.get()); + scoped_ptr<base::DictionaryValue> augmented_properties( + policy_util::CreateManagedONC(global_policy, + network_policy, + user_settings, + active_settings.get(), + profile)); callback.Run(service_path, *augmented_properties); } @@ -297,13 +283,17 @@ void ManagedNetworkConfigurationHandlerImpl::SetProperties( if (validation_result == onc::Validator::VALID_WITH_WARNINGS) LOG(WARNING) << "Validation of ONC user settings produced warnings."; - const base::DictionaryValue* policy = + const base::DictionaryValue* network_policy = GetByGUID(policies->per_network_config, guid); - VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed."; + VLOG(2) << "This configuration is " << (network_policy ? "" : "not ") + << "managed."; scoped_ptr<base::DictionaryValue> shill_dictionary( - policy_util::CreateShillConfiguration( - *profile, guid, policy, validated_user_settings.get())); + policy_util::CreateShillConfiguration(*profile, + guid, + &policies->global_network_config, + network_policy, + validated_user_settings.get())); network_configuration_handler_->SetProperties( service_path, *shill_dictionary, callback, error_callback); @@ -341,8 +331,11 @@ void ManagedNetworkConfigurationHandlerImpl::CreateConfiguration( // in |properties| as it is not our own and from an untrusted source. std::string guid = base::GenerateGUID(); scoped_ptr<base::DictionaryValue> shill_dictionary( - policy_util::CreateShillConfiguration( - *profile, guid, NULL /*no policy*/, &properties)); + policy_util::CreateShillConfiguration(*profile, + guid, + NULL, // no global policy + NULL, // no network policy + &properties)); network_configuration_handler_->CreateConfiguration( *shill_dictionary, callback, error_callback); diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc index b4ec1cc..7a32886 100644 --- a/chromeos/network/managed_network_configuration_handler_unittest.cc +++ b/chromeos/network/managed_network_configuration_handler_unittest.cc @@ -14,6 +14,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/mock_shill_manager_client.h" #include "chromeos/dbus/mock_shill_profile_client.h" +#include "chromeos/dbus/mock_shill_service_client.h" #include "chromeos/dbus/shill_client_helper.h" #include "chromeos/network/managed_network_configuration_handler_impl.h" #include "chromeos/network/network_configuration_handler.h" @@ -130,6 +131,27 @@ class ShillProfileTestClient { std::map<std::string, std::string> profile_to_user_; }; +class ShillServiceTestClient { + public: + typedef ShillClientHelper::DictionaryValueCallback DictionaryValueCallback; + void SetFakeProperties(const base::DictionaryValue& service_properties) { + service_properties_.Clear(); + service_properties_.MergeDictionary(&service_properties); + } + + void GetProperties(const dbus::ObjectPath& service_path, + const DictionaryValueCallback& callback) { + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(callback, + DBUS_METHOD_CALL_SUCCESS, + base::ConstRef(service_properties_))); + } + + protected: + base::DictionaryValue service_properties_; +}; + class TestNetworkProfileHandler : public NetworkProfileHandler { public: TestNetworkProfileHandler() { @@ -151,7 +173,8 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { public: ManagedNetworkConfigurationHandlerTest() : mock_manager_client_(NULL), - mock_profile_client_(NULL) { + mock_profile_client_(NULL), + mock_service_client_(NULL) { } virtual ~ManagedNetworkConfigurationHandlerTest() { @@ -162,10 +185,13 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { DBusThreadManager::GetSetterForTesting(); mock_manager_client_ = new StrictMock<MockShillManagerClient>(); mock_profile_client_ = new StrictMock<MockShillProfileClient>(); + mock_service_client_ = new StrictMock<MockShillServiceClient>(); dbus_setter->SetShillManagerClient( scoped_ptr<ShillManagerClient>(mock_manager_client_).Pass()); dbus_setter->SetShillProfileClient( scoped_ptr<ShillProfileClient>(mock_profile_client_).Pass()); + dbus_setter->SetShillServiceClient( + scoped_ptr<ShillServiceClient>(mock_service_client_).Pass()); SetNetworkConfigurationHandlerExpectations(); @@ -177,6 +203,10 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { .WillByDefault(Invoke(&profiles_stub_, &ShillProfileTestClient::GetEntry)); + ON_CALL(*mock_service_client_, GetProperties(_,_)) + .WillByDefault(Invoke(&services_stub_, + &ShillServiceTestClient::GetProperties)); + network_profile_handler_.reset(new TestNetworkProfileHandler()); network_configuration_handler_.reset( NetworkConfigurationHandler::InitializeForTest( @@ -209,9 +239,12 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { profiles_stub_.AddProfile(kUser1ProfilePath, kUser1); network_profile_handler_-> AddProfileForTest(NetworkProfile(kUser1ProfilePath, kUser1)); - network_profile_handler_-> - AddProfileForTest(NetworkProfile( - NetworkProfileHandler::GetSharedProfilePath(), std::string())); + + profiles_stub_.AddProfile(NetworkProfileHandler::GetSharedProfilePath(), + std::string() /* no userhash */); + network_profile_handler_->AddProfileForTest( + NetworkProfile(NetworkProfileHandler::GetSharedProfilePath(), + std::string() /* no userhash */)); } void SetUpEntry(const std::string& path_to_shill_json, @@ -259,16 +292,44 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test { return managed_network_configuration_handler_.get(); } + void GetManagedProperties(const std::string& userhash, + const std::string& service_path) { + managed_handler()->GetManagedProperties( + userhash, + service_path, + base::Bind( + &ManagedNetworkConfigurationHandlerTest::GetPropertiesCallback, + base::Unretained(this)), + base::Bind(&ManagedNetworkConfigurationHandlerTest::UnexpectedError)); + } + + void GetPropertiesCallback(const std::string& service_path, + const base::DictionaryValue& dictionary) { + get_properties_service_path_ = service_path; + get_properties_result_.Clear(); + get_properties_result_.MergeDictionary(&dictionary); + } + + static void UnexpectedError(const std::string& error_name, + scoped_ptr<base::DictionaryValue> error_data) { + ASSERT_FALSE(true); + } + protected: MockShillManagerClient* mock_manager_client_; MockShillProfileClient* mock_profile_client_; + MockShillServiceClient* mock_service_client_; ShillProfileTestClient profiles_stub_; + ShillServiceTestClient services_stub_; scoped_ptr<TestNetworkProfileHandler> network_profile_handler_; scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_; scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_network_configuration_handler_; base::MessageLoop message_loop_; + std::string get_properties_service_path_; + base::DictionaryValue get_properties_result_; + private: DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest); }; @@ -660,10 +721,13 @@ TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmanaged) { TEST_F(ManagedNetworkConfigurationHandlerTest, AutoConnectDisallowed) { InitializeStandardProfiles(); + // Setup an unmanaged network. SetUpEntry("policy/shill_unmanaged_wifi2.json", kUser1ProfilePath, "wifi2_entry_path"); + // Apply the user policy with global autoconnect config and expect that + // autoconnect is disabled in the network's profile entry. EXPECT_CALL(*mock_profile_client_, GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _)); @@ -685,6 +749,38 @@ TEST_F(ManagedNetworkConfigurationHandlerTest, AutoConnectDisallowed) { kUser1, "policy/policy_disallow_autoconnect.onc"); message_loop_.RunUntilIdle(); + + // Verify that GetManagedProperties correctly augments the properties with the + // global config from the user policy. + + // GetManagedProperties requires the device policy to be set or explicitly + // unset. + EXPECT_CALL(*mock_profile_client_, + GetProperties(dbus::ObjectPath( + NetworkProfileHandler::GetSharedProfilePath()), + _, + _)); + managed_handler()->SetPolicy( + ::onc::ONC_SOURCE_DEVICE_POLICY, + std::string(), // no userhash + base::ListValue(), // no device network policy + base::DictionaryValue()); // no device global config + + services_stub_.SetFakeProperties(*expected_shill_properties); + EXPECT_CALL(*mock_service_client_, + GetProperties(dbus::ObjectPath( + "wifi2"),_)); + + GetManagedProperties(kUser1, "wifi2"); + message_loop_.RunUntilIdle(); + + EXPECT_EQ("wifi2", get_properties_service_path_); + + scoped_ptr<base::DictionaryValue> expected_managed_onc = + test_utils::ReadTestDictionary( + "policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc"); + EXPECT_TRUE(onc::test_utils::Equals(expected_managed_onc.get(), + &get_properties_result_)); } TEST_F(ManagedNetworkConfigurationHandlerTest, LateProfileLoading) { diff --git a/chromeos/network/policy_applicator.cc b/chromeos/network/policy_applicator.cc index 8b45c40..bd81d7d 100644 --- a/chromeos/network/policy_applicator.cc +++ b/chromeos/network/policy_applicator.cc @@ -172,8 +172,11 @@ void PolicyApplicator::GetEntryCallback( 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); + policy_util::CreateShillConfiguration(profile_, + new_guid, + &global_network_config_, + new_policy, + user_settings); // A new policy has to be applied to this profile entry. In order to keep // implicit state of Shill like "connected successfully before", keep the // entry if a policy is reapplied (e.g. after reboot) or is updated. @@ -204,7 +207,8 @@ void PolicyApplicator::GetEntryCallback( // At first ENTRY1 and ENTRY2 should be removed, then the new config be // written and the result should be: // { {GUID=X, SSID=Y, USER_SETTINGS=X} } - WriteNewShillConfiguration(*new_shill_properties, *new_policy, true); + WriteNewShillConfiguration( + *new_shill_properties, *new_policy, true /* write later */); remaining_policies_.erase(new_guid); } } else if (was_managed) { @@ -219,8 +223,8 @@ void PolicyApplicator::GetEntryCallback( // The entry wasn't managed and doesn't match any current policy. Global // network settings have to be applied. base::DictionaryValue shill_properties_to_update; - GetPropertiesForUnmanagedEntry(entry_properties, - &shill_properties_to_update); + policy_util::SetShillPropertiesForGlobalPolicy( + entry_properties, global_network_config_, &shill_properties_to_update); if (shill_properties_to_update.empty()) { VLOG(2) << "Ignore unmanaged entry."; // Calling a SetProperties of Shill with an empty dictionary is a no op. @@ -266,37 +270,6 @@ void PolicyApplicator::WriteNewShillConfiguration( handler_->CreateConfigurationFromPolicy(shill_dictionary); } -void PolicyApplicator::GetPropertiesForUnmanagedEntry( - const base::DictionaryValue& entry_properties, - base::DictionaryValue* properties_to_update) const { - // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. - - std::string type; - entry_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); - if (NetworkTypePattern::Ethernet().MatchesType(type)) - return; // Autoconnect for Ethernet cannot be configured. - - // By default all networks are allowed to autoconnect. - 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) { - // Autoconnect is already explictly disabled. No need to set it again. - return; - } - // If autconnect is not explicitly set yet, it might automatically be enabled - // by Shill. To prevent that, disable it explicitly. - properties_to_update->SetBooleanWithoutPathExpansion( - shill::kAutoConnectProperty, false); -} - PolicyApplicator::~PolicyApplicator() { ApplyRemainingPolicies(); STLDeleteValues(&all_policies_); @@ -331,16 +304,20 @@ void PolicyApplicator::ApplyRemainingPolicies() { // remaining policies, new configurations have to be created. 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); + const base::DictionaryValue* network_policy = GetByGUID(all_policies_, *it); + DCHECK(network_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 /* no user settings */); - WriteNewShillConfiguration(*shill_dictionary, *policy, false); + policy_util::CreateShillConfiguration(profile_, + *it, + &global_network_config_, + network_policy, + NULL /* no user settings */); + WriteNewShillConfiguration( + *shill_dictionary, *network_policy, false /* write now */); } } diff --git a/chromeos/network/policy_applicator.h b/chromeos/network/policy_applicator.h index db9ed52..b9401a4 100644 --- a/chromeos/network/policy_applicator.h +++ b/chromeos/network/policy_applicator.h @@ -80,14 +80,6 @@ class PolicyApplicator : public base::RefCounted<PolicyApplicator> { const base::DictionaryValue& policy, bool write_later); - // Adds properties to |properties_to_update|, which are enforced on an - // unamaged network by the global network config of the policy. - // |entry_properties| are the network's current properties read from its - // profile entry. - void GetPropertiesForUnmanagedEntry( - const base::DictionaryValue& entry_properties, - base::DictionaryValue* properties_to_update) const; - // Called once all Profile entries are processed. Calls // ApplyRemainingPolicies. virtual ~PolicyApplicator(); diff --git a/chromeos/network/policy_util.cc b/chromeos/network/policy_util.cc index 7e27d97..33fc05a 100644 --- a/chromeos/network/policy_util.cc +++ b/chromeos/network/policy_util.cc @@ -125,26 +125,172 @@ bool IsPolicyMatching(const base::DictionaryValue& policy, return false; } +base::DictionaryValue* GetOrCreateDictionary(const std::string& key, + base::DictionaryValue* dict) { + base::DictionaryValue* inner_dict = NULL; + if (!dict->GetDictionaryWithoutPathExpansion(key, &inner_dict)) { + inner_dict = new base::DictionaryValue; + dict->SetWithoutPathExpansion(key, inner_dict); + } + return inner_dict; +} + +base::DictionaryValue* GetOrCreateNestedDictionary( + const std::string& key1, + const std::string& key2, + base::DictionaryValue* dict) { + base::DictionaryValue* inner_dict = GetOrCreateDictionary(key1, dict); + return GetOrCreateDictionary(key2, inner_dict); +} + +void ApplyGlobalAutoconnectPolicy( + NetworkProfile::Type profile_type, + base::DictionaryValue* augmented_onc_network) { + base::DictionaryValue* type_dictionary = NULL; + augmented_onc_network->GetDictionaryWithoutPathExpansion( + ::onc::network_config::kType, &type_dictionary); + std::string type; + if (!type_dictionary || + !type_dictionary->GetStringWithoutPathExpansion( + ::onc::kAugmentationActiveSetting, &type) || + type.empty()) { + LOG(ERROR) << "ONC dictionary with no Type."; + return; + } + + // Managed dictionaries don't contain empty dictionaries (see onc_merger.cc), + // so add the Autoconnect dictionary in case Shill didn't report a value. + base::DictionaryValue* auto_connect_dictionary = NULL; + if (type == ::onc::network_type::kWiFi) { + auto_connect_dictionary = + GetOrCreateNestedDictionary(::onc::network_config::kWiFi, + ::onc::wifi::kAutoConnect, + augmented_onc_network); + } else if (type == ::onc::network_type::kVPN) { + auto_connect_dictionary = + GetOrCreateNestedDictionary(::onc::network_config::kVPN, + ::onc::vpn::kAutoConnect, + augmented_onc_network); + } else { + return; // Network type without auto-connect property. + } + + std::string policy_source; + if (profile_type == NetworkProfile::TYPE_USER) + policy_source = ::onc::kAugmentationUserPolicy; + else if(profile_type == NetworkProfile::TYPE_SHARED) + policy_source = ::onc::kAugmentationDevicePolicy; + else + NOTREACHED(); + + auto_connect_dictionary->SetBooleanWithoutPathExpansion(policy_source, false); + auto_connect_dictionary->SetStringWithoutPathExpansion( + ::onc::kAugmentationEffectiveSetting, policy_source); +} + } // namespace +scoped_ptr<base::DictionaryValue> CreateManagedONC( + const base::DictionaryValue* global_policy, + const base::DictionaryValue* network_policy, + const base::DictionaryValue* user_settings, + const base::DictionaryValue* active_settings, + const NetworkProfile* profile) { + const base::DictionaryValue* user_policy = NULL; + const base::DictionaryValue* device_policy = NULL; + const base::DictionaryValue* nonshared_user_settings = NULL; + const base::DictionaryValue* shared_user_settings = NULL; + + if (profile) { + if (profile->type() == NetworkProfile::TYPE_SHARED) { + device_policy = network_policy; + shared_user_settings = user_settings; + } else if (profile->type() == NetworkProfile::TYPE_USER) { + user_policy = network_policy; + nonshared_user_settings = user_settings; + } else { + NOTREACHED(); + } + } + + // This call also removes credentials from policies. + scoped_ptr<base::DictionaryValue> augmented_onc_network = + onc::MergeSettingsAndPoliciesToAugmented( + onc::kNetworkConfigurationSignature, + user_policy, + device_policy, + nonshared_user_settings, + shared_user_settings, + active_settings); + + // If present, apply the Autoconnect policy only to networks that are not + // managed by policy. + if (!network_policy && global_policy && profile) { + bool allow_only_policy_autoconnect = false; + global_policy->GetBooleanWithoutPathExpansion( + ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, + &allow_only_policy_autoconnect); + if (allow_only_policy_autoconnect) { + ApplyGlobalAutoconnectPolicy(profile->type(), + augmented_onc_network.get()); + } + } + + return augmented_onc_network.Pass(); +} + +void SetShillPropertiesForGlobalPolicy( + const base::DictionaryValue& shill_dictionary, + const base::DictionaryValue& global_network_policy, + base::DictionaryValue* shill_properties_to_update) { + // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config. + + std::string type; + shill_dictionary.GetStringWithoutPathExpansion(shill::kTypeProperty, &type); + if (NetworkTypePattern::Ethernet().MatchesType(type)) + return; // Autoconnect for Ethernet cannot be configured. + + // By default all networks are allowed to autoconnect. + bool only_policy_autoconnect = false; + global_network_policy.GetBooleanWithoutPathExpansion( + ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect, + &only_policy_autoconnect); + if (!only_policy_autoconnect) + return; + + bool old_autoconnect = false; + if (shill_dictionary.GetBooleanWithoutPathExpansion( + shill::kAutoConnectProperty, &old_autoconnect) && + !old_autoconnect) { + // Autoconnect is already explictly disabled. No need to set it again. + return; + } + + // If autconnect is not explicitly set yet, it might automatically be enabled + // by Shill. To prevent that, disable it explicitly. + shill_properties_to_update->SetBooleanWithoutPathExpansion( + shill::kAutoConnectProperty, false); +} + scoped_ptr<base::DictionaryValue> CreateShillConfiguration( const NetworkProfile& profile, const std::string& guid, - const base::DictionaryValue* policy, + const base::DictionaryValue* global_policy, + const base::DictionaryValue* network_policy, const base::DictionaryValue* user_settings) { scoped_ptr<base::DictionaryValue> effective; ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE; - if (policy) { + if (network_policy) { if (profile.type() == NetworkProfile::TYPE_SHARED) { effective = onc::MergeSettingsAndPoliciesToEffective( NULL, // no user policy - policy, // device policy + network_policy, // device policy NULL, // no user settings user_settings); // shared settings onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY; } else if (profile.type() == NetworkProfile::TYPE_USER) { effective = onc::MergeSettingsAndPoliciesToEffective( - policy, // user policy + network_policy, // user policy NULL, // no device policy user_settings, // user settings NULL); // no shared settings @@ -178,6 +324,12 @@ scoped_ptr<base::DictionaryValue> CreateShillConfiguration( shill_dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty, profile.path); + if (!network_policy && global_policy) { + // The network isn't managed. Global network policies have to be applied. + SetShillPropertiesForGlobalPolicy( + *shill_dictionary, *global_policy, shill_dictionary.get()); + } + scoped_ptr<NetworkUIData> ui_data(NetworkUIData::CreateFromONC(onc_source)); if (user_settings) { diff --git a/chromeos/network/policy_util.h b/chromeos/network/policy_util.h index 73701e3..841c001 100644 --- a/chromeos/network/policy_util.h +++ b/chromeos/network/policy_util.h @@ -22,15 +22,37 @@ namespace policy_util { typedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap; +// Creates a managed ONC dictionary from the given arguments. Depending on the +// profile type, the policies are assumed to come from the user or device policy +// and and |user_settings| to be the user's non-shared or shared settings. +// Each of the arguments can be NULL. +// TODO(pneubeck): Add documentation of the returned format, see +// https://crbug.com/408990 . +scoped_ptr<base::DictionaryValue> CreateManagedONC( + const base::DictionaryValue* global_policy, + const base::DictionaryValue* network_policy, + const base::DictionaryValue* user_settings, + const base::DictionaryValue* active_settings, + const NetworkProfile* profile); + +// Adds properties to |shill_properties_to_update|, which are enforced on an +// unamaged network by the global config |global_network_policy| of the policy. +// |shill_dictionary| are the network's current properties read from Shill. +void SetShillPropertiesForGlobalPolicy( + const base::DictionaryValue& shill_dictionary, + const base::DictionaryValue& global_network_policy, + base::DictionaryValue* shill_properties_to_update); + // Creates a Shill property dictionary from the given arguments. The resulting // dictionary will be sent to Shill by the caller. Depending on the profile -// type, |policy| is interpreted as the user or device policy and -// |user_settings| as the user or shared settings. |policy| or |user_settings| -// can be NULL, but not both. +// type, |network_policy| is interpreted as the user or device policy and +// |user_settings| as the user or shared settings. |network_policy| or +// |user_settings| can be NULL, but not both. scoped_ptr<base::DictionaryValue> CreateShillConfiguration( const NetworkProfile& profile, const std::string& guid, - const base::DictionaryValue* policy, + const base::DictionaryValue* global_policy, + const base::DictionaryValue* network_policy, const base::DictionaryValue* user_settings); // Returns the policy from |policies| matching |actual_network|, if any exists. diff --git a/chromeos/test/data/network/policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc b/chromeos/test/data/network/policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc new file mode 100644 index 0000000..d8c252a9 --- /dev/null +++ b/chromeos/test/data/network/policy/managed_onc_disallow_autoconnect_on_unmanaged_wifi2.onc @@ -0,0 +1,21 @@ +{ + "Name": { + "Active": "wifi2" + }, + "Type": { + "Active": "WiFi" + }, + "WiFi": { + "AutoConnect": { + "Active": false, + "Effective": "UserPolicy", + "UserPolicy": false + }, + "SSID": { + "Active": "wifi2" + }, + "Security": { + "Active": "WPA-PSK" + } + } +} |