| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/net/proxy_policy_handler.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/prefs/pref_value_map.h" | |
| 9 #include "base/strings/string_number_conversions.h" | |
| 10 #include "base/values.h" | |
| 11 #include "chrome/common/pref_names.h" | |
| 12 #include "components/policy/core/browser/configuration_policy_handler.h" | |
| 13 #include "components/policy/core/browser/policy_error_map.h" | |
| 14 #include "components/policy/core/common/policy_map.h" | |
| 15 #include "components/proxy_config/proxy_config_dictionary.h" | |
| 16 #include "components/proxy_config/proxy_config_pref_names.h" | |
| 17 #include "grit/components_strings.h" | |
| 18 #include "policy/policy_constants.h" | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 // This is used to check whether for a given ProxyMode value, the ProxyPacUrl, | |
| 23 // the ProxyBypassList and the ProxyServer policies are allowed to be specified. | |
| 24 // |error_message_id| is the message id of the localized error message to show | |
| 25 // when the policies are not specified as allowed. Each value of ProxyMode | |
| 26 // has a ProxyModeValidationEntry in the |kProxyModeValidationMap| below. | |
| 27 struct ProxyModeValidationEntry { | |
| 28 const char* mode_value; | |
| 29 bool pac_url_allowed; | |
| 30 bool bypass_list_allowed; | |
| 31 bool server_allowed; | |
| 32 int error_message_id; | |
| 33 }; | |
| 34 | |
| 35 // List of entries determining which proxy policies can be specified, depending | |
| 36 // on the ProxyMode. | |
| 37 const ProxyModeValidationEntry kProxyModeValidationMap[] = { | |
| 38 { ProxyPrefs::kDirectProxyModeName, | |
| 39 false, false, false, IDS_POLICY_PROXY_MODE_DISABLED_ERROR }, | |
| 40 { ProxyPrefs::kAutoDetectProxyModeName, | |
| 41 false, false, false, IDS_POLICY_PROXY_MODE_AUTO_DETECT_ERROR }, | |
| 42 { ProxyPrefs::kPacScriptProxyModeName, | |
| 43 true, false, false, IDS_POLICY_PROXY_MODE_PAC_URL_ERROR }, | |
| 44 { ProxyPrefs::kFixedServersProxyModeName, | |
| 45 false, true, true, IDS_POLICY_PROXY_MODE_FIXED_SERVERS_ERROR }, | |
| 46 { ProxyPrefs::kSystemProxyModeName, | |
| 47 false, false, false, IDS_POLICY_PROXY_MODE_SYSTEM_ERROR }, | |
| 48 }; | |
| 49 | |
| 50 } // namespace | |
| 51 | |
| 52 namespace policy { | |
| 53 | |
| 54 // The proxy policies have the peculiarity that they are loaded from individual | |
| 55 // policies, but the providers then expose them through a unified | |
| 56 // DictionaryValue. Once Dictionary policies are fully supported, the individual | |
| 57 // proxy policies will be deprecated. http://crbug.com/108996 | |
| 58 | |
| 59 ProxyPolicyHandler::ProxyPolicyHandler() {} | |
| 60 | |
| 61 ProxyPolicyHandler::~ProxyPolicyHandler() { | |
| 62 } | |
| 63 | |
| 64 bool ProxyPolicyHandler::CheckPolicySettings(const PolicyMap& policies, | |
| 65 PolicyErrorMap* errors) { | |
| 66 const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); | |
| 67 const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); | |
| 68 const base::Value* server_mode = | |
| 69 GetProxyPolicyValue(policies, key::kProxyServerMode); | |
| 70 const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); | |
| 71 const base::Value* bypass_list = | |
| 72 GetProxyPolicyValue(policies, key::kProxyBypassList); | |
| 73 | |
| 74 if ((server || pac_url || bypass_list) && !(mode || server_mode)) { | |
| 75 errors->AddError(key::kProxySettings, | |
| 76 key::kProxyMode, | |
| 77 IDS_POLICY_NOT_SPECIFIED_ERROR); | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 std::string mode_value; | |
| 82 if (!CheckProxyModeAndServerMode(policies, errors, &mode_value)) | |
| 83 return false; | |
| 84 | |
| 85 // If neither ProxyMode nor ProxyServerMode are specified, mode_value will be | |
| 86 // empty and the proxy shouldn't be configured at all. | |
| 87 if (mode_value.empty()) | |
| 88 return true; | |
| 89 | |
| 90 bool is_valid_mode = false; | |
| 91 for (size_t i = 0; i != arraysize(kProxyModeValidationMap); ++i) { | |
| 92 const ProxyModeValidationEntry& entry = kProxyModeValidationMap[i]; | |
| 93 if (entry.mode_value != mode_value) | |
| 94 continue; | |
| 95 | |
| 96 is_valid_mode = true; | |
| 97 | |
| 98 if (!entry.pac_url_allowed && pac_url) { | |
| 99 errors->AddError(key::kProxySettings, | |
| 100 key::kProxyPacUrl, | |
| 101 entry.error_message_id); | |
| 102 } | |
| 103 if (!entry.bypass_list_allowed && bypass_list) { | |
| 104 errors->AddError(key::kProxySettings, | |
| 105 key::kProxyBypassList, | |
| 106 entry.error_message_id); | |
| 107 } | |
| 108 if (!entry.server_allowed && server) { | |
| 109 errors->AddError(key::kProxySettings, | |
| 110 key::kProxyServer, | |
| 111 entry.error_message_id); | |
| 112 } | |
| 113 | |
| 114 if ((!entry.pac_url_allowed && pac_url) || | |
| 115 (!entry.bypass_list_allowed && bypass_list) || | |
| 116 (!entry.server_allowed && server)) { | |
| 117 return false; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 if (!is_valid_mode) { | |
| 122 errors->AddError(key::kProxySettings, | |
| 123 mode ? key::kProxyMode : key::kProxyServerMode, | |
| 124 IDS_POLICY_OUT_OF_RANGE_ERROR, | |
| 125 mode_value); | |
| 126 return false; | |
| 127 } | |
| 128 return true; | |
| 129 } | |
| 130 | |
| 131 void ProxyPolicyHandler::ApplyPolicySettings(const PolicyMap& policies, | |
| 132 PrefValueMap* prefs) { | |
| 133 const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); | |
| 134 const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); | |
| 135 const base::Value* server_mode = | |
| 136 GetProxyPolicyValue(policies, key::kProxyServerMode); | |
| 137 const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); | |
| 138 const base::Value* bypass_list = | |
| 139 GetProxyPolicyValue(policies, key::kProxyBypassList); | |
| 140 | |
| 141 ProxyPrefs::ProxyMode proxy_mode; | |
| 142 if (mode) { | |
| 143 std::string string_mode; | |
| 144 CHECK(mode->GetAsString(&string_mode)); | |
| 145 CHECK(ProxyPrefs::StringToProxyMode(string_mode, &proxy_mode)); | |
| 146 } else if (server_mode) { | |
| 147 int int_mode = 0; | |
| 148 CHECK(server_mode->GetAsInteger(&int_mode)); | |
| 149 | |
| 150 switch (int_mode) { | |
| 151 case PROXY_SERVER_MODE: | |
| 152 proxy_mode = ProxyPrefs::MODE_DIRECT; | |
| 153 break; | |
| 154 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE: | |
| 155 proxy_mode = ProxyPrefs::MODE_AUTO_DETECT; | |
| 156 break; | |
| 157 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE: | |
| 158 proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS; | |
| 159 if (pac_url) | |
| 160 proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT; | |
| 161 break; | |
| 162 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE: | |
| 163 proxy_mode = ProxyPrefs::MODE_SYSTEM; | |
| 164 break; | |
| 165 default: | |
| 166 proxy_mode = ProxyPrefs::MODE_DIRECT; | |
| 167 NOTREACHED(); | |
| 168 } | |
| 169 } else { | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 switch (proxy_mode) { | |
| 174 case ProxyPrefs::MODE_DIRECT: | |
| 175 prefs->SetValue(proxy_config::prefs::kProxy, | |
| 176 make_scoped_ptr(ProxyConfigDictionary::CreateDirect())); | |
| 177 break; | |
| 178 case ProxyPrefs::MODE_AUTO_DETECT: | |
| 179 prefs->SetValue( | |
| 180 proxy_config::prefs::kProxy, | |
| 181 make_scoped_ptr(ProxyConfigDictionary::CreateAutoDetect())); | |
| 182 break; | |
| 183 case ProxyPrefs::MODE_PAC_SCRIPT: { | |
| 184 std::string pac_url_string; | |
| 185 if (pac_url && pac_url->GetAsString(&pac_url_string)) { | |
| 186 prefs->SetValue(proxy_config::prefs::kProxy, | |
| 187 make_scoped_ptr(ProxyConfigDictionary::CreatePacScript( | |
| 188 pac_url_string, false))); | |
| 189 } else { | |
| 190 NOTREACHED(); | |
| 191 } | |
| 192 break; | |
| 193 } | |
| 194 case ProxyPrefs::MODE_FIXED_SERVERS: { | |
| 195 std::string proxy_server; | |
| 196 std::string bypass_list_string; | |
| 197 if (server->GetAsString(&proxy_server)) { | |
| 198 if (bypass_list) | |
| 199 bypass_list->GetAsString(&bypass_list_string); | |
| 200 prefs->SetValue( | |
| 201 proxy_config::prefs::kProxy, | |
| 202 make_scoped_ptr(ProxyConfigDictionary::CreateFixedServers( | |
| 203 proxy_server, bypass_list_string))); | |
| 204 } | |
| 205 break; | |
| 206 } | |
| 207 case ProxyPrefs::MODE_SYSTEM: | |
| 208 prefs->SetValue(proxy_config::prefs::kProxy, | |
| 209 make_scoped_ptr(ProxyConfigDictionary::CreateSystem())); | |
| 210 break; | |
| 211 case ProxyPrefs::kModeCount: | |
| 212 NOTREACHED(); | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 const base::Value* ProxyPolicyHandler::GetProxyPolicyValue( | |
| 217 const PolicyMap& policies, const char* policy_name) { | |
| 218 // See note on the ProxyPolicyHandler implementation above. | |
| 219 const base::Value* value = policies.GetValue(key::kProxySettings); | |
| 220 const base::DictionaryValue* settings; | |
| 221 if (!value || !value->GetAsDictionary(&settings)) | |
| 222 return NULL; | |
| 223 | |
| 224 const base::Value* policy_value = NULL; | |
| 225 std::string tmp; | |
| 226 if (!settings->Get(policy_name, &policy_value) || | |
| 227 policy_value->IsType(base::Value::TYPE_NULL) || | |
| 228 (policy_value->IsType(base::Value::TYPE_STRING) && | |
| 229 policy_value->GetAsString(&tmp) && | |
| 230 tmp.empty())) { | |
| 231 return NULL; | |
| 232 } | |
| 233 return policy_value; | |
| 234 } | |
| 235 | |
| 236 bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap& policies, | |
| 237 PolicyErrorMap* errors, | |
| 238 std::string* mode_value) { | |
| 239 const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); | |
| 240 const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); | |
| 241 const base::Value* server_mode = | |
| 242 GetProxyPolicyValue(policies, key::kProxyServerMode); | |
| 243 const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); | |
| 244 | |
| 245 // If there's a server mode, convert it into a mode. | |
| 246 // When both are specified, the mode takes precedence. | |
| 247 if (mode) { | |
| 248 if (server_mode) { | |
| 249 errors->AddError(key::kProxySettings, | |
| 250 key::kProxyServerMode, | |
| 251 IDS_POLICY_OVERRIDDEN, | |
| 252 key::kProxyMode); | |
| 253 } | |
| 254 if (!mode->GetAsString(mode_value)) { | |
| 255 errors->AddError(key::kProxySettings, | |
| 256 key::kProxyMode, | |
| 257 IDS_POLICY_TYPE_ERROR, | |
| 258 ValueTypeToString(base::Value::TYPE_BOOLEAN)); | |
| 259 return false; | |
| 260 } | |
| 261 | |
| 262 ProxyPrefs::ProxyMode mode; | |
| 263 if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) { | |
| 264 errors->AddError(key::kProxySettings, | |
| 265 key::kProxyMode, | |
| 266 IDS_POLICY_INVALID_PROXY_MODE_ERROR); | |
| 267 return false; | |
| 268 } | |
| 269 | |
| 270 if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) { | |
| 271 errors->AddError(key::kProxySettings, | |
| 272 key::kProxyPacUrl, | |
| 273 IDS_POLICY_NOT_SPECIFIED_ERROR); | |
| 274 return false; | |
| 275 } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) { | |
| 276 errors->AddError(key::kProxySettings, | |
| 277 key::kProxyServer, | |
| 278 IDS_POLICY_NOT_SPECIFIED_ERROR); | |
| 279 return false; | |
| 280 } | |
| 281 } else if (server_mode) { | |
| 282 int server_mode_value; | |
| 283 if (!server_mode->GetAsInteger(&server_mode_value)) { | |
| 284 errors->AddError(key::kProxySettings, | |
| 285 key::kProxyServerMode, | |
| 286 IDS_POLICY_TYPE_ERROR, | |
| 287 ValueTypeToString(base::Value::TYPE_INTEGER)); | |
| 288 return false; | |
| 289 } | |
| 290 | |
| 291 switch (server_mode_value) { | |
| 292 case PROXY_SERVER_MODE: | |
| 293 *mode_value = ProxyPrefs::kDirectProxyModeName; | |
| 294 break; | |
| 295 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE: | |
| 296 *mode_value = ProxyPrefs::kAutoDetectProxyModeName; | |
| 297 break; | |
| 298 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE: | |
| 299 if (server && pac_url) { | |
| 300 int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR; | |
| 301 errors->AddError(key::kProxySettings, | |
| 302 key::kProxyServer, | |
| 303 message_id); | |
| 304 errors->AddError(key::kProxySettings, | |
| 305 key::kProxyPacUrl, | |
| 306 message_id); | |
| 307 return false; | |
| 308 } | |
| 309 if (!server && !pac_url) { | |
| 310 int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR; | |
| 311 errors->AddError(key::kProxySettings, | |
| 312 key::kProxyServer, | |
| 313 message_id); | |
| 314 errors->AddError(key::kProxySettings, | |
| 315 key::kProxyPacUrl, | |
| 316 message_id); | |
| 317 return false; | |
| 318 } | |
| 319 if (pac_url) | |
| 320 *mode_value = ProxyPrefs::kPacScriptProxyModeName; | |
| 321 else | |
| 322 *mode_value = ProxyPrefs::kFixedServersProxyModeName; | |
| 323 break; | |
| 324 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE: | |
| 325 *mode_value = ProxyPrefs::kSystemProxyModeName; | |
| 326 break; | |
| 327 default: | |
| 328 errors->AddError(key::kProxySettings, | |
| 329 key::kProxyServerMode, | |
| 330 IDS_POLICY_OUT_OF_RANGE_ERROR, | |
| 331 base::IntToString(server_mode_value)); | |
| 332 return false; | |
| 333 } | |
| 334 } | |
| 335 return true; | |
| 336 } | |
| 337 | |
| 338 } // namespace policy | |
| OLD | NEW |