• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/component_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 
ProxyPolicyHandler()59 ProxyPolicyHandler::ProxyPolicyHandler() {}
60 
~ProxyPolicyHandler()61 ProxyPolicyHandler::~ProxyPolicyHandler() {
62 }
63 
CheckPolicySettings(const PolicyMap & policies,PolicyErrorMap * errors)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 
ApplyPolicySettings(const PolicyMap & policies,PrefValueMap * prefs)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 
GetProxyPolicyValue(const PolicyMap & policies,const char * policy_name)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 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(Value::TYPE_NULL) ||
223       (policy_value->IsType(Value::TYPE_STRING) &&
224        policy_value->GetAsString(&tmp) &&
225        tmp.empty())) {
226     return NULL;
227   }
228   return policy_value;
229 }
230 
CheckProxyModeAndServerMode(const PolicyMap & policies,PolicyErrorMap * errors,std::string * mode_value)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(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(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