onc_utils.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/chromeos/net/onc_utils.h" 6 7#include "base/bind_helpers.h" 8#include "base/json/json_writer.h" 9#include "base/logging.h" 10#include "base/values.h" 11#include "chrome/browser/chromeos/login/user.h" 12#include "chrome/browser/chromeos/login/user_manager.h" 13#include "chrome/browser/chromeos/ui_proxy_config.h" 14#include "chrome/browser/prefs/proxy_config_dictionary.h" 15#include "chromeos/network/managed_network_configuration_handler.h" 16#include "chromeos/network/network_configuration_handler.h" 17#include "chromeos/network/network_handler.h" 18#include "chromeos/network/network_profile.h" 19#include "chromeos/network/network_profile_handler.h" 20#include "chromeos/network/network_ui_data.h" 21#include "chromeos/network/onc/onc_normalizer.h" 22#include "chromeos/network/onc/onc_signature.h" 23#include "chromeos/network/onc/onc_translator.h" 24#include "chromeos/network/onc/onc_utils.h" 25#include "net/base/host_port_pair.h" 26#include "net/proxy/proxy_bypass_rules.h" 27#include "net/proxy/proxy_server.h" 28#include "third_party/cros_system_api/dbus/service_constants.h" 29#include "url/gurl.h" 30 31namespace chromeos { 32namespace onc { 33 34namespace { 35 36net::ProxyServer ConvertOncProxyLocationToHostPort( 37 net::ProxyServer::Scheme default_proxy_scheme, 38 const base::DictionaryValue& onc_proxy_location) { 39 std::string host; 40 onc_proxy_location.GetStringWithoutPathExpansion(onc::proxy::kHost, &host); 41 // Parse |host| according to the format [<scheme>"://"]<server>[":"<port>]. 42 net::ProxyServer proxy_server = 43 net::ProxyServer::FromURI(host, default_proxy_scheme); 44 int port = 0; 45 onc_proxy_location.GetIntegerWithoutPathExpansion(onc::proxy::kPort, &port); 46 47 // Replace the port parsed from |host| by the provided |port|. 48 return net::ProxyServer( 49 proxy_server.scheme(), 50 net::HostPortPair(proxy_server.host_port_pair().host(), 51 static_cast<uint16>(port))); 52} 53 54void AppendProxyServerForScheme( 55 const base::DictionaryValue& onc_manual, 56 const std::string& onc_scheme, 57 std::string* spec) { 58 const base::DictionaryValue* onc_proxy_location = NULL; 59 if (!onc_manual.GetDictionaryWithoutPathExpansion(onc_scheme, 60 &onc_proxy_location)) { 61 return; 62 } 63 64 net::ProxyServer::Scheme default_proxy_scheme = net::ProxyServer::SCHEME_HTTP; 65 std::string url_scheme; 66 if (onc_scheme == proxy::kFtp) { 67 url_scheme = "ftp"; 68 } else if (onc_scheme == proxy::kHttp) { 69 url_scheme = "http"; 70 } else if (onc_scheme == proxy::kHttps) { 71 url_scheme = "https"; 72 } else if (onc_scheme == proxy::kSocks) { 73 default_proxy_scheme = net::ProxyServer::SCHEME_SOCKS4; 74 url_scheme = "socks"; 75 } else { 76 NOTREACHED(); 77 } 78 79 net::ProxyServer proxy_server = ConvertOncProxyLocationToHostPort( 80 default_proxy_scheme, *onc_proxy_location); 81 82 UIProxyConfig::EncodeAndAppendProxyServer(url_scheme, proxy_server, spec); 83} 84 85net::ProxyBypassRules ConvertOncExcludeDomainsToBypassRules( 86 const base::ListValue& onc_exclude_domains) { 87 net::ProxyBypassRules rules; 88 for (base::ListValue::const_iterator it = onc_exclude_domains.begin(); 89 it != onc_exclude_domains.end(); ++it) { 90 std::string rule; 91 (*it)->GetAsString(&rule); 92 rules.AddRuleFromString(rule); 93 } 94 return rules; 95} 96 97} // namespace 98 99scoped_ptr<base::DictionaryValue> ConvertOncProxySettingsToProxyConfig( 100 const base::DictionaryValue& onc_proxy_settings) { 101 std::string type; 102 onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kType, &type); 103 scoped_ptr<DictionaryValue> proxy_dict; 104 105 if (type == proxy::kDirect) { 106 proxy_dict.reset(ProxyConfigDictionary::CreateDirect()); 107 } else if (type == proxy::kWPAD) { 108 proxy_dict.reset(ProxyConfigDictionary::CreateAutoDetect()); 109 } else if (type == proxy::kPAC) { 110 std::string pac_url; 111 onc_proxy_settings.GetStringWithoutPathExpansion(proxy::kPAC, &pac_url); 112 GURL url(pac_url); 113 DCHECK(url.is_valid()) 114 << "PAC field is invalid for this ProxySettings.Type"; 115 proxy_dict.reset(ProxyConfigDictionary::CreatePacScript(url.spec(), 116 false)); 117 } else if (type == proxy::kManual) { 118 const base::DictionaryValue* manual_dict = NULL; 119 onc_proxy_settings.GetDictionaryWithoutPathExpansion(proxy::kManual, 120 &manual_dict); 121 std::string manual_spec; 122 AppendProxyServerForScheme(*manual_dict, proxy::kFtp, &manual_spec); 123 AppendProxyServerForScheme(*manual_dict, proxy::kHttp, &manual_spec); 124 AppendProxyServerForScheme(*manual_dict, proxy::kSocks, &manual_spec); 125 AppendProxyServerForScheme(*manual_dict, proxy::kHttps, &manual_spec); 126 127 const base::ListValue* exclude_domains = NULL; 128 net::ProxyBypassRules bypass_rules; 129 if (onc_proxy_settings.GetListWithoutPathExpansion(proxy::kExcludeDomains, 130 &exclude_domains)) { 131 bypass_rules.AssignFrom( 132 ConvertOncExcludeDomainsToBypassRules(*exclude_domains)); 133 } 134 proxy_dict.reset(ProxyConfigDictionary::CreateFixedServers( 135 manual_spec, bypass_rules.ToString())); 136 } else { 137 NOTREACHED(); 138 } 139 return proxy_dict.Pass(); 140} 141 142namespace { 143 144// This class defines which string placeholders of ONC are replaced by which 145// user attribute. 146class UserStringSubstitution : public chromeos::onc::StringSubstitution { 147 public: 148 explicit UserStringSubstitution(const chromeos::User* user) : user_(user) {} 149 virtual ~UserStringSubstitution() {} 150 151 virtual bool GetSubstitute(const std::string& placeholder, 152 std::string* substitute) const OVERRIDE { 153 if (placeholder == chromeos::onc::substitutes::kLoginIDField) 154 *substitute = user_->GetAccountName(false); 155 else if (placeholder == chromeos::onc::substitutes::kEmailField) 156 *substitute = user_->email(); 157 else 158 return false; 159 return true; 160 } 161 162 private: 163 const chromeos::User* user_; 164 165 DISALLOW_COPY_AND_ASSIGN(UserStringSubstitution); 166}; 167 168} // namespace 169 170void ExpandStringPlaceholdersInNetworksForUser( 171 const chromeos::User* user, 172 base::ListValue* network_configs) { 173 if (!user) { 174 // In tests no user may be logged in. It's not harmful if we just don't 175 // expand the strings. 176 return; 177 } 178 UserStringSubstitution substitution(user); 179 chromeos::onc::ExpandStringsInNetworks(substitution, network_configs); 180} 181 182void ImportNetworksForUser(const chromeos::User* user, 183 const base::ListValue& network_configs, 184 std::string* error) { 185 error->clear(); 186 187 scoped_ptr<base::ListValue> expanded_networks(network_configs.DeepCopy()); 188 ExpandStringPlaceholdersInNetworksForUser(user, expanded_networks.get()); 189 190 const NetworkProfile* profile = 191 NetworkHandler::Get()->network_profile_handler()->GetProfileForUserhash( 192 user->username_hash()); 193 if (!profile) { 194 *error = "User profile doesn't exist."; 195 return; 196 } 197 198 for (base::ListValue::const_iterator it = expanded_networks->begin(); 199 it != expanded_networks->end(); 200 ++it) { 201 const base::DictionaryValue* network = NULL; 202 (*it)->GetAsDictionary(&network); 203 DCHECK(network); 204 205 // Remove irrelevant fields. 206 onc::Normalizer normalizer(true /* remove recommended fields */); 207 scoped_ptr<base::DictionaryValue> normalized_network = 208 normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature, 209 *network); 210 211 scoped_ptr<base::DictionaryValue> shill_dict = 212 onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature, 213 *normalized_network); 214 215 scoped_ptr<NetworkUIData> ui_data = NetworkUIData::CreateFromONC( 216 onc::ONC_SOURCE_USER_IMPORT, *normalized_network); 217 base::DictionaryValue ui_data_dict; 218 ui_data->FillDictionary(&ui_data_dict); 219 std::string ui_data_json; 220 base::JSONWriter::Write(&ui_data_dict, &ui_data_json); 221 shill_dict->SetStringWithoutPathExpansion(flimflam::kUIDataProperty, 222 ui_data_json); 223 224 shill_dict->SetStringWithoutPathExpansion(flimflam::kProfileProperty, 225 profile->path); 226 227 NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration( 228 *shill_dict, 229 network_handler::StringResultCallback(), 230 network_handler::ErrorCallback()); 231 } 232} 233 234const base::DictionaryValue* FindPolicyForActiveUser( 235 const std::string& guid, 236 onc::ONCSource* onc_source) { 237 const User* user = UserManager::Get()->GetActiveUser(); 238 std::string username_hash = user ? user->username_hash() : std::string(); 239 return NetworkHandler::Get()->managed_network_configuration_handler()-> 240 FindPolicyByGUID(username_hash, guid, onc_source); 241} 242 243} // namespace onc 244} // namespace chromeos 245