Commit f4a39626 authored by Alexander Hendrich's avatar Alexander Hendrich Committed by Commit Bot

Fix AutoConnectHandler for AllowOnlyPolicyNetworksTo[Auto]Connect

Fix1: If either AllowOnlyPolicyNetworksToConnect or
AllowOnlyPolicyNetworksToAutoconnect is enabled, this CL will
additionally remove the network configurations
(AllowOnlyPolicyNetworksToConnect) or disable auto-connect (for
AllowOnlyPolicyNetworksToAutoconnect) for the unmanaged networks to
prevent Shill from re-connecting when searching for a best service to
connect.

Fix2: Fixed missing disconnect, when AllowOnlyPolicyNetworksToConnect
gets enabled. This disconnect was incorrectly prevented by the
|applied_autoconnect_policy_| boolean before, which ensures that the
disconnect on AllowOnlyPolicyNetworksToAutoconnect only happens once.

Bug: 850550
Change-Id: I869ed49d58adb82707e8856e896c5a141f6f6625
Reviewed-on: https://chromium-review.googlesource.com/1091051Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Alexander Hendrich <hendrich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567199}
parent f223700c
...@@ -44,6 +44,32 @@ void DisconnectErrorCallback( ...@@ -44,6 +44,32 @@ void DisconnectErrorCallback(
<< "Error data: " << error_data_ss.str(); << "Error data: " << error_data_ss.str();
} }
void RemoveNetworkConfigurationErrorCallback(
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data) {
std::stringstream error_data_ss;
if (error_data)
error_data_ss << *error_data;
else
error_data_ss << "<none>";
NET_LOG(ERROR) << "AutoConnectHandler RemoveNetworkConfiguration failed. "
<< "Error name: \"" << error_name << "\", "
<< "Error data: " << error_data_ss.str();
}
void SetPropertiesErrorCallback(
const std::string& error_name,
std::unique_ptr<base::DictionaryValue> error_data) {
std::stringstream error_data_ss;
if (error_data)
error_data_ss << *error_data;
else
error_data_ss << "<none>";
NET_LOG(ERROR) << "AutoConnectHandler SetProperties failed. "
<< "Error name: \"" << error_name << "\", "
<< "Error data: " << error_data_ss.str();
}
std::string AutoConnectReasonsToString(int auto_connect_reasons) { std::string AutoConnectReasonsToString(int auto_connect_reasons) {
std::string result; std::string result;
...@@ -139,21 +165,15 @@ void AutoConnectHandler::ConnectToNetworkRequested( ...@@ -139,21 +165,15 @@ void AutoConnectHandler::ConnectToNetworkRequested(
request_best_connection_pending_ = false; request_best_connection_pending_ = false;
} }
void AutoConnectHandler::PoliciesChanged(const std::string& userhash) {
// Ignore user policies.
if (!userhash.empty())
return;
DisconnectIfPolicyRequires();
}
void AutoConnectHandler::PoliciesApplied(const std::string& userhash) { void AutoConnectHandler::PoliciesApplied(const std::string& userhash) {
if (userhash.empty()) { if (userhash.empty()) {
device_policy_applied_ = true; device_policy_applied_ = true;
} else { } else {
user_policy_applied_ = true; user_policy_applied_ = true;
DisconnectIfPolicyRequires();
} }
DisconnectIfPolicyRequires();
// Request to connect to the best network only if there is at least one // Request to connect to the best network only if there is at least one
// managed network. Otherwise only process existing requests. // managed network. Otherwise only process existing requests.
const ManagedNetworkConfigurationHandler::GuidToPolicyMap* managed_networks = const ManagedNetworkConfigurationHandler::GuidToPolicyMap* managed_networks =
...@@ -263,60 +283,98 @@ void AutoConnectHandler::CheckBestConnection() { ...@@ -263,60 +283,98 @@ void AutoConnectHandler::CheckBestConnection() {
} }
void AutoConnectHandler::DisconnectIfPolicyRequires() { void AutoConnectHandler::DisconnectIfPolicyRequires() {
if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn() || if (!LoginState::Get()->IsUserLoggedIn() || !user_policy_applied_)
!user_policy_applied_) {
return; return;
}
const base::DictionaryValue* global_network_config = const base::DictionaryValue* global_network_config =
managed_configuration_handler_->GetGlobalConfigFromPolicy( managed_configuration_handler_->GetGlobalConfigFromPolicy(
std::string() /* no username hash, device policy */); std::string() /* no username hash, device policy */);
if (!global_network_config) if (!global_network_config)
return; // Device policy is not set, yet. return; // Device policy is not set, yet.
applied_autoconnect_policy_ = true; const base::Value* connect_value = global_network_config->FindKeyOfType(
bool only_policy_autoconnect = false;
global_network_config->GetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
&only_policy_autoconnect);
bool only_policy_connect = false;
global_network_config->GetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect, ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect,
&only_policy_connect); base::Value::Type::BOOLEAN);
bool only_policy_connect = connect_value ? connect_value->GetBool() : false;
if (only_policy_autoconnect || only_policy_connect) const base::Value* autoconnect_value = global_network_config->FindKeyOfType(
DisconnectFromUnmanagedSharedWiFiNetworks(); ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
base::Value::Type::BOOLEAN);
bool only_policy_autoconnect =
autoconnect_value ? autoconnect_value->GetBool() : false;
// Reset |applied_autoconnect_policy_| if auto-connect policy is disabled.
if (!only_policy_autoconnect)
applied_autoconnect_policy_ = false;
if (only_policy_connect) {
// Disconnect and remove network configurations for all unmanaged networks.
DisconnectFromAllUnmanagedWiFiNetworks(true, false);
} else if (only_policy_autoconnect && !applied_autoconnect_policy_) {
// Disconnect and disable auto-connect for all unmanaged networks.
DisconnectFromAllUnmanagedWiFiNetworks(false, true);
applied_autoconnect_policy_ = true;
}
} }
void AutoConnectHandler::DisconnectFromUnmanagedSharedWiFiNetworks() { void AutoConnectHandler::DisconnectFromAllUnmanagedWiFiNetworks(
NET_LOG_DEBUG("DisconnectFromUnmanagedSharedWiFiNetworks", ""); bool remove_configuration,
bool disable_auto_connect) {
NET_LOG_DEBUG("DisconnectFromAllUnmanagedWiFiNetworks", "");
NetworkStateHandler::NetworkStateList networks; NetworkStateHandler::NetworkStateList networks;
network_state_handler_->GetVisibleNetworkListByType( network_state_handler_->GetNetworkListByType(NetworkTypePattern::WiFi(),
NetworkTypePattern::WiFi(), &networks); false, false, 0, &networks);
for (const NetworkState* network : networks) { for (const NetworkState* network : networks) {
if (!(network->IsConnectingState() || network->IsConnectedState())) const bool is_managed =
break; // Connected and connecting networks are listed first.
if (network->IsPrivate())
continue;
const bool network_is_policy_managed =
!network->profile_path().empty() && !network->guid().empty() && !network->profile_path().empty() && !network->guid().empty() &&
managed_configuration_handler_->FindPolicyByGuidAndProfile( managed_configuration_handler_->FindPolicyByGuidAndProfile(
network->guid(), network->profile_path(), nullptr /* onc_source */); network->guid(), network->profile_path(), nullptr /* onc_source */);
if (network_is_policy_managed)
if (is_managed)
continue; continue;
NET_LOG_EVENT("Disconnect Forced by Policy", network->path()); if (network->IsConnectingOrConnected())
network_connection_handler_->DisconnectNetwork( DisconnectNetwork(network->path());
network->path(), base::DoNothing(),
base::Bind(&DisconnectErrorCallback, network->path())); if (network->IsInProfile()) {
if (remove_configuration)
RemoveNetworkConfigurationForNetwork(network->path());
else if (disable_auto_connect)
DisableAutoconnectForWiFiNetwork(network->path());
}
} }
} }
void AutoConnectHandler::DisconnectNetwork(const std::string& service_path) {
NET_LOG_EVENT("Disconnect forced by policy", service_path);
network_connection_handler_->DisconnectNetwork(
service_path, base::DoNothing(),
base::Bind(&DisconnectErrorCallback, service_path));
}
void AutoConnectHandler::RemoveNetworkConfigurationForNetwork(
const std::string& service_path) {
NET_LOG_EVENT("Disconnect forced by policy", service_path);
managed_configuration_handler_->RemoveConfiguration(
service_path, base::DoNothing(),
base::Bind(&RemoveNetworkConfigurationErrorCallback));
}
void AutoConnectHandler::DisableAutoconnectForWiFiNetwork(
const std::string& service_path) {
NET_LOG_EVENT("Disable auto-connect forced by policy", service_path);
base::DictionaryValue properties;
properties.SetPath({::onc::network_config::kWiFi, ::onc::wifi::kAutoConnect},
base::Value(false));
managed_configuration_handler_->SetProperties(
service_path, properties, base::DoNothing(),
base::Bind(&SetPropertiesErrorCallback));
}
void AutoConnectHandler::CallShillConnectToBestServices() { void AutoConnectHandler::CallShillConnectToBestServices() {
NET_LOG(EVENT) << "ConnectToBestServices [" NET_LOG(EVENT) << "ConnectToBestServices ["
<< AutoConnectReasonsToString(auto_connect_reasons_) << "]"; << AutoConnectReasonsToString(auto_connect_reasons_) << "]";
......
...@@ -48,7 +48,6 @@ class CHROMEOS_EXPORT AutoConnectHandler : public LoginState::Observer, ...@@ -48,7 +48,6 @@ class CHROMEOS_EXPORT AutoConnectHandler : public LoginState::Observer,
void ConnectToNetworkRequested(const std::string& service_path) override; void ConnectToNetworkRequested(const std::string& service_path) override;
// NetworkPolicyObserver // NetworkPolicyObserver
void PoliciesChanged(const std::string& userhash) override;
void PoliciesApplied(const std::string& userhash) override; void PoliciesApplied(const std::string& userhash) override;
// NetworkStateHandlerObserver // NetworkStateHandlerObserver
...@@ -76,19 +75,38 @@ class CHROMEOS_EXPORT AutoConnectHandler : public LoginState::Observer, ...@@ -76,19 +75,38 @@ class CHROMEOS_EXPORT AutoConnectHandler : public LoginState::Observer,
void NotifyAutoConnectInitiated(int auto_connect_reasons); void NotifyAutoConnectInitiated(int auto_connect_reasons);
// If the user logged in already and the policy to prevent unmanaged & shared // This function is called whenever the logged in state changes or when a new
// networks to autoconnect is enabled, then disconnects all such networks // policy is applied. Once both device and user policy have been applied and
// except wired networks. It will do this only once after the user logged in // either of AllowOnlyPolicyNetworksToConnect or
// and the device policy and user policy was available. // AllowOnlyPolicyNetworksToAutoconnect is enabled, we disconnect from all
// This is enforced once after a user logs in 1) to allow mananged networks to // connecting/connected unmanaged networks and either remove the network
// autoconnect and 2) to prevent a previous user from foisting a network on // configuration (for AllowOnlyPolicyNetworksToConnect) or only disable
// the new user. Therefore, this function is called at login and when the // auto-connect (for AllowOnlyPolicyNetworksToAutoconnect) for all aunmanaged
// device policy is changed after user policy is fetched and applied. // networks (see |DisconnectFromAllUnmanagedWiFiNetworks(...)|).
// For the AllowOnlyPolicyNetworksToAutoconnect policy we only disconnect once
// to allow managed networks to auto-connect and prevent disconnects with
// manually connected unmanaged networks on every policy update.
void DisconnectIfPolicyRequires(); void DisconnectIfPolicyRequires();
// Disconnects from all unmanaged and shared WiFi networks that are currently // Disconnects from all currently connected/connecting unmanaged WiFis.
// connected or connecting. // When |remove_configuration|==true, we also remove the corresponding network
void DisconnectFromUnmanagedSharedWiFiNetworks(); // configuration for all unmanaged networks from Shill.
// When |disable_auto_connect|==true, we also disable auto-connect for all
// unmanaged networks in Shill.
// With both options we can prevent Shill from re-connecting to the unmanaged
// networks when looking for a best service to connect to.
void DisconnectFromAllUnmanagedWiFiNetworks(bool remove_configuration,
bool disable_auto_connect);
// Disconnects the connection to the network represented by |service_path|.
void DisconnectNetwork(const std::string& service_path);
// Removes the network configuration for the network represented by
// |service_path|.
void RemoveNetworkConfigurationForNetwork(const std::string& service_path);
// Sets WiFi.AutoConnect=false for the network represented by |service_path|.
void DisableAutoconnectForWiFiNetwork(const std::string& service_path);
// Requests and if possible connects to the 'best' available network, see // Requests and if possible connects to the 'best' available network, see
// CheckBestConnection(). // CheckBestConnection().
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment