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 |