Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Unified Diff: chromeos/network/onc/onc_utils.cc

Issue 2442313003: Move some proxy config code out of src/chrome (Closed)
Patch Set: Fix DEPS Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromeos/network/onc/onc_utils.h ('k') | chromeos/network/proxy/proxy_config_handler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromeos/network/onc/onc_utils.cc
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc
index 6abcd759799bd24e85838797ab1e251dd07aa81d..fc8f0db6b5622b60e613fb640ab7f1d7480ae27f 100644
--- a/chromeos/network/onc/onc_utils.cc
+++ b/chromeos/network/onc/onc_utils.cc
@@ -9,6 +9,7 @@
#include "base/base64.h"
#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -16,13 +17,26 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
+#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_mapper.h"
+#include "chromeos/network/onc/onc_normalizer.h"
#include "chromeos/network/onc/onc_signature.h"
+#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/onc/onc_validator.h"
#include "components/device_event_log/device_event_log.h"
+#include "components/onc/onc_pref_names.h"
+#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
#include "crypto/encryptor.h"
#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
@@ -32,6 +46,8 @@
#include "net/proxy/proxy_bypass_rules.h"
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_server.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "url/gurl.h"
#include "url/url_constants.h"
using namespace ::onc;
@@ -44,6 +60,31 @@ namespace {
const char kUnableToDecrypt[] = "Unable to decrypt encrypted ONC";
const char kUnableToDecode[] = "Unable to decode encrypted ONC";
+// This class defines which string placeholders of ONC are replaced by which
+// user attribute.
+class UserStringSubstitution : public chromeos::onc::StringSubstitution {
+ public:
+ explicit UserStringSubstitution(const user_manager::User* user)
+ : user_(user) {}
+ ~UserStringSubstitution() override {}
+
+ bool GetSubstitute(const std::string& placeholder,
+ std::string* substitute) const override {
+ if (placeholder == ::onc::substitutes::kLoginIDField)
+ *substitute = user_->GetAccountName(false);
+ else if (placeholder == ::onc::substitutes::kEmailField)
+ *substitute = user_->email();
+ else
+ return false;
+ return true;
+ }
+
+ private:
+ const user_manager::User* user_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution);
+};
+
} // namespace
const char kEmptyUnencryptedConfiguration[] =
@@ -992,5 +1033,294 @@ std::unique_ptr<base::DictionaryValue> ConvertProxyConfigToOncProxySettings(
return proxy_settings;
}
+namespace {
+
+const base::DictionaryValue* GetNetworkConfigByGUID(
+ const base::ListValue& network_configs,
+ const std::string& guid) {
+ for (base::ListValue::const_iterator it = network_configs.begin();
+ it != network_configs.end(); ++it) {
+ const base::DictionaryValue* network = NULL;
+ (*it)->GetAsDictionary(&network);
+ DCHECK(network);
+
+ std::string current_guid;
+ network->GetStringWithoutPathExpansion(::onc::network_config::kGUID,
+ &current_guid);
+ if (current_guid == guid)
+ return network;
+ }
+ return NULL;
+}
+
+const base::DictionaryValue* GetNetworkConfigForEthernetWithoutEAP(
+ const base::ListValue& network_configs) {
+ VLOG(2) << "Search for ethernet policy without EAP.";
+ for (base::ListValue::const_iterator it = network_configs.begin();
+ it != network_configs.end(); ++it) {
+ const base::DictionaryValue* network = NULL;
+ (*it)->GetAsDictionary(&network);
+ DCHECK(network);
+
+ std::string type;
+ network->GetStringWithoutPathExpansion(::onc::network_config::kType, &type);
+ if (type != ::onc::network_type::kEthernet)
+ continue;
+
+ const base::DictionaryValue* ethernet = NULL;
+ network->GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet,
+ &ethernet);
+
+ std::string auth;
+ ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication,
+ &auth);
+ if (auth == ::onc::ethernet::kAuthenticationNone)
+ return network;
+ }
+ return NULL;
+}
+
+const base::DictionaryValue* GetNetworkConfigForNetworkFromOnc(
+ const base::ListValue& network_configs,
+ const NetworkState& network) {
+ // In all cases except Ethernet, we use the GUID of |network|.
+ if (!network.Matches(NetworkTypePattern::Ethernet()))
+ return GetNetworkConfigByGUID(network_configs, network.guid());
+
+ // Ethernet is always shared and thus cannot store a GUID per user. Thus we
+ // search for any Ethernet policy intead of a matching GUID.
+ // EthernetEAP service contains only the EAP parameters and stores the GUID of
+ // the respective ONC policy. The EthernetEAP service itself is however never
+ // in state "connected". An EthernetEAP policy must be applied, if an Ethernet
+ // service is connected using the EAP parameters.
+ const NetworkState* ethernet_eap = NULL;
+ if (NetworkHandler::IsInitialized()) {
+ ethernet_eap =
+ NetworkHandler::Get()->network_state_handler()->GetEAPForEthernet(
+ network.path());
+ }
+
+ // The GUID associated with the EthernetEAP service refers to the ONC policy
+ // with "Authentication: 8021X".
+ if (ethernet_eap)
+ return GetNetworkConfigByGUID(network_configs, ethernet_eap->guid());
+
+ // Otherwise, EAP is not used and instead the Ethernet policy with
+ // "Authentication: None" applies.
+ return GetNetworkConfigForEthernetWithoutEAP(network_configs);
+}
+
+const base::DictionaryValue* GetPolicyForNetworkFromPref(
+ const PrefService* pref_service,
+ const char* pref_name,
+ const NetworkState& network) {
+ if (!pref_service) {
+ VLOG(2) << "No pref service";
+ return NULL;
+ }
+
+ const PrefService::Preference* preference =
+ pref_service->FindPreference(pref_name);
+ if (!preference) {
+ VLOG(2) << "No preference " << pref_name;
+ // The preference may not exist in tests.
+ return NULL;
+ }
+
+ // User prefs are not stored in this Preference yet but only the policy.
+ //
+ // The policy server incorrectly configures the OpenNetworkConfiguration user
+ // policy as Recommended. To work around that, we handle the Recommended and
+ // the Mandatory value in the same way.
+ // TODO(pneubeck): Remove this workaround, once the server is fixed. See
+ // http://crbug.com/280553 .
+ if (preference->IsDefaultValue()) {
+ VLOG(2) << "Preference has no recommended or mandatory value.";
+ // No policy set.
+ return NULL;
+ }
+ VLOG(2) << "Preference with policy found.";
+ const base::Value* onc_policy_value = preference->GetValue();
+ DCHECK(onc_policy_value);
+
+ const base::ListValue* onc_policy = NULL;
+ onc_policy_value->GetAsList(&onc_policy);
+ DCHECK(onc_policy);
+
+ return GetNetworkConfigForNetworkFromOnc(*onc_policy, network);
+}
+
+} // namespace
+
+void ExpandStringPlaceholdersInNetworksForUser(
+ const user_manager::User* user,
+ base::ListValue* network_configs) {
+ if (!user) {
+ // In tests no user may be logged in. It's not harmful if we just don't
+ // expand the strings.
+ return;
+ }
+ UserStringSubstitution substitution(user);
+ chromeos::onc::ExpandStringsInNetworks(substitution, network_configs);
+}
+
+void ImportNetworksForUser(const user_manager::User* user,
+ const base::ListValue& network_configs,
+ std::string* error) {
+ error->clear();
+
+ std::unique_ptr<base::ListValue> expanded_networks(
+ network_configs.DeepCopy());
+ ExpandStringPlaceholdersInNetworksForUser(user, expanded_networks.get());
+
+ const NetworkProfile* profile =
+ NetworkHandler::Get()->network_profile_handler()->GetProfileForUserhash(
+ user->username_hash());
+ if (!profile) {
+ *error = "User profile doesn't exist.";
+ return;
+ }
+
+ bool ethernet_not_found = false;
+ for (base::ListValue::const_iterator it = expanded_networks->begin();
+ it != expanded_networks->end(); ++it) {
+ const base::DictionaryValue* network = NULL;
+ (*it)->GetAsDictionary(&network);
+ DCHECK(network);
+
+ // Remove irrelevant fields.
+ onc::Normalizer normalizer(true /* remove recommended fields */);
+ std::unique_ptr<base::DictionaryValue> normalized_network =
+ normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature,
+ *network);
+
+ // TODO(pneubeck): Use ONC and ManagedNetworkConfigurationHandler instead.
+ // crbug.com/457936
+ std::unique_ptr<base::DictionaryValue> shill_dict =
+ onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature,
+ *normalized_network);
+
+ std::unique_ptr<NetworkUIData> ui_data(
+ NetworkUIData::CreateFromONC(::onc::ONC_SOURCE_USER_IMPORT));
+ base::DictionaryValue ui_data_dict;
+ ui_data->FillDictionary(&ui_data_dict);
+ std::string ui_data_json;
+ base::JSONWriter::Write(ui_data_dict, &ui_data_json);
+ shill_dict->SetStringWithoutPathExpansion(shill::kUIDataProperty,
+ ui_data_json);
+
+ shill_dict->SetStringWithoutPathExpansion(shill::kProfileProperty,
+ profile->path);
+
+ std::string type;
+ shill_dict->GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
+ NetworkConfigurationHandler* config_handler =
+ NetworkHandler::Get()->network_configuration_handler();
+ if (NetworkTypePattern::Ethernet().MatchesType(type)) {
+ // Ethernet has to be configured using an existing Ethernet service.
+ const NetworkState* ethernet =
+ NetworkHandler::Get()->network_state_handler()->FirstNetworkByType(
+ NetworkTypePattern::Ethernet());
+ if (ethernet) {
+ config_handler->SetShillProperties(
+ ethernet->path(), *shill_dict,
+ NetworkConfigurationObserver::SOURCE_USER_ACTION, base::Closure(),
+ network_handler::ErrorCallback());
+ } else {
+ ethernet_not_found = true;
+ }
+
+ } else {
+ config_handler->CreateShillConfiguration(
+ *shill_dict, NetworkConfigurationObserver::SOURCE_USER_ACTION,
+ network_handler::ServiceResultCallback(),
+ network_handler::ErrorCallback());
+ }
+ }
+
+ if (ethernet_not_found)
+ *error = "No Ethernet available to configure.";
+}
+
+const base::DictionaryValue* FindPolicyForActiveUser(
+ const std::string& guid,
+ ::onc::ONCSource* onc_source) {
+ const user_manager::User* user =
+ user_manager::UserManager::Get()->GetActiveUser();
+ std::string username_hash = user ? user->username_hash() : std::string();
+ return NetworkHandler::Get()
+ ->managed_network_configuration_handler()
+ ->FindPolicyByGUID(username_hash, guid, onc_source);
+}
+
+namespace {
+
+const base::DictionaryValue* GetGlobalConfigFromPolicy(bool for_active_user) {
+ std::string username_hash;
+ if (for_active_user) {
+ const user_manager::User* user =
+ user_manager::UserManager::Get()->GetActiveUser();
+ if (!user) {
+ LOG(ERROR) << "No user logged in yet.";
+ return NULL;
+ }
+ username_hash = user->username_hash();
+ }
+ return NetworkHandler::Get()
+ ->managed_network_configuration_handler()
+ ->GetGlobalConfigFromPolicy(username_hash);
+}
+
+} // namespace
+
+bool PolicyAllowsOnlyPolicyNetworksToAutoconnect(bool for_active_user) {
+ const base::DictionaryValue* global_config =
+ GetGlobalConfigFromPolicy(for_active_user);
+ if (!global_config)
+ return false; // By default, all networks are allowed to autoconnect.
+
+ bool only_policy_autoconnect = false;
+ global_config->GetBooleanWithoutPathExpansion(
+ ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
+ &only_policy_autoconnect);
+ return only_policy_autoconnect;
+}
+
+const base::DictionaryValue* GetPolicyForNetwork(
+ const PrefService* profile_prefs,
+ const PrefService* local_state_prefs,
+ const NetworkState& network,
+ ::onc::ONCSource* onc_source) {
+ VLOG(2) << "GetPolicyForNetwork: " << network.path();
+ *onc_source = ::onc::ONC_SOURCE_NONE;
+
+ const base::DictionaryValue* network_policy = GetPolicyForNetworkFromPref(
+ profile_prefs, ::onc::prefs::kOpenNetworkConfiguration, network);
+ if (network_policy) {
+ VLOG(1) << "Network " << network.path() << " is managed by user policy.";
+ *onc_source = ::onc::ONC_SOURCE_USER_POLICY;
+ return network_policy;
+ }
+ network_policy = GetPolicyForNetworkFromPref(
+ local_state_prefs, ::onc::prefs::kDeviceOpenNetworkConfiguration,
+ network);
+ if (network_policy) {
+ VLOG(1) << "Network " << network.path() << " is managed by device policy.";
+ *onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
+ return network_policy;
+ }
+ VLOG(2) << "Network " << network.path() << " is unmanaged.";
+ return NULL;
+}
+
+bool HasPolicyForNetwork(const PrefService* profile_prefs,
+ const PrefService* local_state_prefs,
+ const NetworkState& network) {
+ ::onc::ONCSource ignored_onc_source;
+ const base::DictionaryValue* policy = onc::GetPolicyForNetwork(
+ profile_prefs, local_state_prefs, network, &ignored_onc_source);
+ return policy != NULL;
+}
+
} // namespace onc
} // namespace chromeos
« no previous file with comments | « chromeos/network/onc/onc_utils.h ('k') | chromeos/network/proxy/proxy_config_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698