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/browser/prefs/proxy_config_dictionary.h" 12 #include "chrome/browser/prefs/proxy_prefs.h" 13 #include "chrome/common/pref_names.h" 14 #include "components/policy/core/browser/configuration_policy_handler.h" 15 #include "components/policy/core/browser/policy_error_map.h" 16 #include "components/policy/core/common/policy_map.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(prefs::kProxy, ProxyConfigDictionary::CreateDirect()); 176 break; 177 case ProxyPrefs::MODE_AUTO_DETECT: 178 prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateAutoDetect()); 179 break; 180 case ProxyPrefs::MODE_PAC_SCRIPT: { 181 std::string pac_url_string; 182 if (pac_url && pac_url->GetAsString(&pac_url_string)) { 183 prefs->SetValue( 184 prefs::kProxy, 185 ProxyConfigDictionary::CreatePacScript(pac_url_string, false)); 186 } else { 187 NOTREACHED(); 188 } 189 break; 190 } 191 case ProxyPrefs::MODE_FIXED_SERVERS: { 192 std::string proxy_server; 193 std::string bypass_list_string; 194 if (server->GetAsString(&proxy_server)) { 195 if (bypass_list) 196 bypass_list->GetAsString(&bypass_list_string); 197 prefs->SetValue(prefs::kProxy, 198 ProxyConfigDictionary::CreateFixedServers( 199 proxy_server, bypass_list_string)); 200 } 201 break; 202 } 203 case ProxyPrefs::MODE_SYSTEM: 204 prefs->SetValue(prefs::kProxy, ProxyConfigDictionary::CreateSystem()); 205 break; 206 case ProxyPrefs::kModeCount: 207 NOTREACHED(); 208 } 209 } 210 211 const base::Value* ProxyPolicyHandler::GetProxyPolicyValue( 212 const PolicyMap& policies, const char* policy_name) { 213 // See note on the ProxyPolicyHandler implementation above. 214 const base::Value* value = policies.GetValue(key::kProxySettings); 215 const base::DictionaryValue* settings; 216 if (!value || !value->GetAsDictionary(&settings)) 217 return NULL; 218 219 const base::Value* policy_value = NULL; 220 std::string tmp; 221 if (!settings->Get(policy_name, &policy_value) || 222 policy_value->IsType(base::Value::TYPE_NULL) || 223 (policy_value->IsType(base::Value::TYPE_STRING) && 224 policy_value->GetAsString(&tmp) && 225 tmp.empty())) { 226 return NULL; 227 } 228 return policy_value; 229 } 230 231 bool ProxyPolicyHandler::CheckProxyModeAndServerMode(const PolicyMap& policies, 232 PolicyErrorMap* errors, 233 std::string* mode_value) { 234 const base::Value* mode = GetProxyPolicyValue(policies, key::kProxyMode); 235 const base::Value* server = GetProxyPolicyValue(policies, key::kProxyServer); 236 const base::Value* server_mode = 237 GetProxyPolicyValue(policies, key::kProxyServerMode); 238 const base::Value* pac_url = GetProxyPolicyValue(policies, key::kProxyPacUrl); 239 240 // If there's a server mode, convert it into a mode. 241 // When both are specified, the mode takes precedence. 242 if (mode) { 243 if (server_mode) { 244 errors->AddError(key::kProxySettings, 245 key::kProxyServerMode, 246 IDS_POLICY_OVERRIDDEN, 247 key::kProxyMode); 248 } 249 if (!mode->GetAsString(mode_value)) { 250 errors->AddError(key::kProxySettings, 251 key::kProxyMode, 252 IDS_POLICY_TYPE_ERROR, 253 ValueTypeToString(base::Value::TYPE_BOOLEAN)); 254 return false; 255 } 256 257 ProxyPrefs::ProxyMode mode; 258 if (!ProxyPrefs::StringToProxyMode(*mode_value, &mode)) { 259 errors->AddError(key::kProxySettings, 260 key::kProxyMode, 261 IDS_POLICY_INVALID_PROXY_MODE_ERROR); 262 return false; 263 } 264 265 if (mode == ProxyPrefs::MODE_PAC_SCRIPT && !pac_url) { 266 errors->AddError(key::kProxySettings, 267 key::kProxyPacUrl, 268 IDS_POLICY_NOT_SPECIFIED_ERROR); 269 return false; 270 } else if (mode == ProxyPrefs::MODE_FIXED_SERVERS && !server) { 271 errors->AddError(key::kProxySettings, 272 key::kProxyServer, 273 IDS_POLICY_NOT_SPECIFIED_ERROR); 274 return false; 275 } 276 } else if (server_mode) { 277 int server_mode_value; 278 if (!server_mode->GetAsInteger(&server_mode_value)) { 279 errors->AddError(key::kProxySettings, 280 key::kProxyServerMode, 281 IDS_POLICY_TYPE_ERROR, 282 ValueTypeToString(base::Value::TYPE_INTEGER)); 283 return false; 284 } 285 286 switch (server_mode_value) { 287 case PROXY_SERVER_MODE: 288 *mode_value = ProxyPrefs::kDirectProxyModeName; 289 break; 290 case PROXY_AUTO_DETECT_PROXY_SERVER_MODE: 291 *mode_value = ProxyPrefs::kAutoDetectProxyModeName; 292 break; 293 case PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE: 294 if (server && pac_url) { 295 int message_id = IDS_POLICY_PROXY_BOTH_SPECIFIED_ERROR; 296 errors->AddError(key::kProxySettings, 297 key::kProxyServer, 298 message_id); 299 errors->AddError(key::kProxySettings, 300 key::kProxyPacUrl, 301 message_id); 302 return false; 303 } 304 if (!server && !pac_url) { 305 int message_id = IDS_POLICY_PROXY_NEITHER_SPECIFIED_ERROR; 306 errors->AddError(key::kProxySettings, 307 key::kProxyServer, 308 message_id); 309 errors->AddError(key::kProxySettings, 310 key::kProxyPacUrl, 311 message_id); 312 return false; 313 } 314 if (pac_url) 315 *mode_value = ProxyPrefs::kPacScriptProxyModeName; 316 else 317 *mode_value = ProxyPrefs::kFixedServersProxyModeName; 318 break; 319 case PROXY_USE_SYSTEM_PROXY_SERVER_MODE: 320 *mode_value = ProxyPrefs::kSystemProxyModeName; 321 break; 322 default: 323 errors->AddError(key::kProxySettings, 324 key::kProxyServerMode, 325 IDS_POLICY_OUT_OF_RANGE_ERROR, 326 base::IntToString(server_mode_value)); 327 return false; 328 } 329 } 330 return true; 331 } 332 333 } // namespace policy 334