Home | History | Annotate | Download | only in net
      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