Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2012 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 #include "chrome/browser/net/ssl_config_service_manager.h"
      5 
      6 #include <algorithm>
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/bind.h"
     12 #include "base/prefs/pref_change_registrar.h"
     13 #include "base/prefs/pref_member.h"
     14 #include "base/prefs/pref_registry_simple.h"
     15 #include "base/prefs/pref_service.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/content_settings/content_settings_utils.h"
     18 #include "chrome/common/content_settings.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "content/public/browser/browser_thread.h"
     21 #include "net/ssl/ssl_cipher_suite_names.h"
     22 #include "net/ssl/ssl_config_service.h"
     23 
     24 using content::BrowserThread;
     25 
     26 namespace {
     27 
     28 // Converts a ListValue of StringValues into a vector of strings. Any Values
     29 // which cannot be converted will be skipped.
     30 std::vector<std::string> ListValueToStringVector(const base::ListValue* value) {
     31   std::vector<std::string> results;
     32   results.reserve(value->GetSize());
     33   std::string s;
     34   for (base::ListValue::const_iterator it = value->begin(); it != value->end();
     35        ++it) {
     36     if (!(*it)->GetAsString(&s))
     37       continue;
     38     results.push_back(s);
     39   }
     40   return results;
     41 }
     42 
     43 // Parses a vector of cipher suite strings, returning a sorted vector
     44 // containing the underlying SSL/TLS cipher suites. Unrecognized/invalid
     45 // cipher suites will be ignored.
     46 std::vector<uint16> ParseCipherSuites(
     47     const std::vector<std::string>& cipher_strings) {
     48   std::vector<uint16> cipher_suites;
     49   cipher_suites.reserve(cipher_strings.size());
     50 
     51   for (std::vector<std::string>::const_iterator it = cipher_strings.begin();
     52        it != cipher_strings.end(); ++it) {
     53     uint16 cipher_suite = 0;
     54     if (!net::ParseSSLCipherString(*it, &cipher_suite)) {
     55       LOG(ERROR) << "Ignoring unrecognized or unparsable cipher suite: "
     56                  << *it;
     57       continue;
     58     }
     59     cipher_suites.push_back(cipher_suite);
     60   }
     61   std::sort(cipher_suites.begin(), cipher_suites.end());
     62   return cipher_suites;
     63 }
     64 
     65 // Returns the string representation of an SSL protocol version. Returns an
     66 // empty string on error.
     67 std::string SSLProtocolVersionToString(uint16 version) {
     68   switch (version) {
     69     case net::SSL_PROTOCOL_VERSION_SSL3:
     70       return "ssl3";
     71     case net::SSL_PROTOCOL_VERSION_TLS1:
     72       return "tls1";
     73     case net::SSL_PROTOCOL_VERSION_TLS1_1:
     74       return "tls1.1";
     75     case net::SSL_PROTOCOL_VERSION_TLS1_2:
     76       return "tls1.2";
     77     default:
     78       NOTREACHED();
     79       return std::string();
     80   }
     81 }
     82 
     83 // Returns the SSL protocol version (as a uint16) represented by a string.
     84 // Returns 0 if the string is invalid.
     85 uint16 SSLProtocolVersionFromString(const std::string& version_str) {
     86   uint16 version = 0;  // Invalid.
     87   if (version_str == "ssl3") {
     88     version = net::SSL_PROTOCOL_VERSION_SSL3;
     89   } else if (version_str == "tls1") {
     90     version = net::SSL_PROTOCOL_VERSION_TLS1;
     91   } else if (version_str == "tls1.1") {
     92     version = net::SSL_PROTOCOL_VERSION_TLS1_1;
     93   } else if (version_str == "tls1.2") {
     94     version = net::SSL_PROTOCOL_VERSION_TLS1_2;
     95   }
     96   return version;
     97 }
     98 
     99 }  // namespace
    100 
    101 ////////////////////////////////////////////////////////////////////////////////
    102 //  SSLConfigServicePref
    103 
    104 // An SSLConfigService which stores a cached version of the current SSLConfig
    105 // prefs, which are updated by SSLConfigServiceManagerPref when the prefs
    106 // change.
    107 class SSLConfigServicePref : public net::SSLConfigService {
    108  public:
    109   SSLConfigServicePref() {}
    110 
    111   // Store SSL config settings in |config|. Must only be called from IO thread.
    112   virtual void GetSSLConfig(net::SSLConfig* config) OVERRIDE;
    113 
    114  private:
    115   // Allow the pref watcher to update our internal state.
    116   friend class SSLConfigServiceManagerPref;
    117 
    118   virtual ~SSLConfigServicePref() {}
    119 
    120   // This method is posted to the IO thread from the browser thread to carry the
    121   // new config information.
    122   void SetNewSSLConfig(const net::SSLConfig& new_config);
    123 
    124   // Cached value of prefs, should only be accessed from IO thread.
    125   net::SSLConfig cached_config_;
    126 
    127   DISALLOW_COPY_AND_ASSIGN(SSLConfigServicePref);
    128 };
    129 
    130 void SSLConfigServicePref::GetSSLConfig(net::SSLConfig* config) {
    131   *config = cached_config_;
    132 }
    133 
    134 void SSLConfigServicePref::SetNewSSLConfig(
    135     const net::SSLConfig& new_config) {
    136   net::SSLConfig orig_config = cached_config_;
    137   cached_config_ = new_config;
    138   ProcessConfigUpdate(orig_config, new_config);
    139 }
    140 
    141 ////////////////////////////////////////////////////////////////////////////////
    142 //  SSLConfigServiceManagerPref
    143 
    144 // The manager for holding and updating an SSLConfigServicePref instance.
    145 class SSLConfigServiceManagerPref
    146     : public SSLConfigServiceManager {
    147  public:
    148   explicit SSLConfigServiceManagerPref(PrefService* local_state);
    149   virtual ~SSLConfigServiceManagerPref() {}
    150 
    151   // Register local_state SSL preferences.
    152   static void RegisterPrefs(PrefRegistrySimple* registry);
    153 
    154   virtual net::SSLConfigService* Get() OVERRIDE;
    155 
    156  private:
    157   // Callback for preference changes.  This will post the changes to the IO
    158   // thread with SetNewSSLConfig.
    159   void OnPreferenceChanged(PrefService* prefs,
    160                            const std::string& pref_name);
    161 
    162   // Store SSL config settings in |config|, directly from the preferences. Must
    163   // only be called from UI thread.
    164   void GetSSLConfigFromPrefs(net::SSLConfig* config);
    165 
    166   // Processes changes to the disabled cipher suites preference, updating the
    167   // cached list of parsed SSL/TLS cipher suites that are disabled.
    168   void OnDisabledCipherSuitesChange(PrefService* local_state);
    169 
    170   PrefChangeRegistrar local_state_change_registrar_;
    171 
    172   // The local_state prefs (should only be accessed from UI thread)
    173   BooleanPrefMember rev_checking_enabled_;
    174   BooleanPrefMember rev_checking_required_local_anchors_;
    175   StringPrefMember ssl_version_min_;
    176   StringPrefMember ssl_version_max_;
    177   BooleanPrefMember ssl_record_splitting_disabled_;
    178 
    179   // The cached list of disabled SSL cipher suites.
    180   std::vector<uint16> disabled_cipher_suites_;
    181 
    182   scoped_refptr<SSLConfigServicePref> ssl_config_service_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(SSLConfigServiceManagerPref);
    185 };
    186 
    187 SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
    188     PrefService* local_state)
    189     : ssl_config_service_(new SSLConfigServicePref()) {
    190   DCHECK(local_state);
    191 
    192   PrefChangeRegistrar::NamedChangeCallback local_state_callback = base::Bind(
    193       &SSLConfigServiceManagerPref::OnPreferenceChanged,
    194       base::Unretained(this),
    195       local_state);
    196 
    197   rev_checking_enabled_.Init(
    198       prefs::kCertRevocationCheckingEnabled, local_state, local_state_callback);
    199   rev_checking_required_local_anchors_.Init(
    200       prefs::kCertRevocationCheckingRequiredLocalAnchors,
    201       local_state,
    202       local_state_callback);
    203   ssl_version_min_.Init(
    204       prefs::kSSLVersionMin, local_state, local_state_callback);
    205   ssl_version_max_.Init(
    206       prefs::kSSLVersionMax, local_state, local_state_callback);
    207   ssl_record_splitting_disabled_.Init(
    208       prefs::kDisableSSLRecordSplitting, local_state, local_state_callback);
    209 
    210   local_state_change_registrar_.Init(local_state);
    211   local_state_change_registrar_.Add(
    212       prefs::kCipherSuiteBlacklist, local_state_callback);
    213 
    214   OnDisabledCipherSuitesChange(local_state);
    215 
    216   // Initialize from UI thread.  This is okay as there shouldn't be anything on
    217   // the IO thread trying to access it yet.
    218   GetSSLConfigFromPrefs(&ssl_config_service_->cached_config_);
    219 }
    220 
    221 // static
    222 void SSLConfigServiceManagerPref::RegisterPrefs(PrefRegistrySimple* registry) {
    223   net::SSLConfig default_config;
    224   registry->RegisterBooleanPref(prefs::kCertRevocationCheckingEnabled,
    225                                 default_config.rev_checking_enabled);
    226   registry->RegisterBooleanPref(
    227       prefs::kCertRevocationCheckingRequiredLocalAnchors,
    228       default_config.rev_checking_required_local_anchors);
    229   std::string version_min_str =
    230       SSLProtocolVersionToString(default_config.version_min);
    231   std::string version_max_str =
    232       SSLProtocolVersionToString(default_config.version_max);
    233   registry->RegisterStringPref(prefs::kSSLVersionMin, version_min_str);
    234   registry->RegisterStringPref(prefs::kSSLVersionMax, version_max_str);
    235   registry->RegisterBooleanPref(prefs::kDisableSSLRecordSplitting,
    236                                 !default_config.false_start_enabled);
    237   registry->RegisterListPref(prefs::kCipherSuiteBlacklist);
    238 }
    239 
    240 net::SSLConfigService* SSLConfigServiceManagerPref::Get() {
    241   return ssl_config_service_.get();
    242 }
    243 
    244 void SSLConfigServiceManagerPref::OnPreferenceChanged(
    245     PrefService* prefs,
    246     const std::string& pref_name_in) {
    247   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    248   DCHECK(prefs);
    249   if (pref_name_in == prefs::kCipherSuiteBlacklist)
    250     OnDisabledCipherSuitesChange(prefs);
    251 
    252   net::SSLConfig new_config;
    253   GetSSLConfigFromPrefs(&new_config);
    254 
    255   // Post a task to |io_loop| with the new configuration, so it can
    256   // update |cached_config_|.
    257   BrowserThread::PostTask(
    258       BrowserThread::IO,
    259       FROM_HERE,
    260       base::Bind(
    261           &SSLConfigServicePref::SetNewSSLConfig,
    262           ssl_config_service_.get(),
    263           new_config));
    264 }
    265 
    266 void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs(
    267     net::SSLConfig* config) {
    268   // rev_checking_enabled was formerly a user-settable preference, but now
    269   // it is managed-only.
    270   if (rev_checking_enabled_.IsManaged())
    271     config->rev_checking_enabled = rev_checking_enabled_.GetValue();
    272   else
    273     config->rev_checking_enabled = false;
    274   config->rev_checking_required_local_anchors =
    275       rev_checking_required_local_anchors_.GetValue();
    276   std::string version_min_str = ssl_version_min_.GetValue();
    277   std::string version_max_str = ssl_version_max_.GetValue();
    278   config->version_min = net::kDefaultSSLVersionMin;
    279   config->version_max = net::kDefaultSSLVersionMax;
    280   uint16 version_min = SSLProtocolVersionFromString(version_min_str);
    281   uint16 version_max = SSLProtocolVersionFromString(version_max_str);
    282   if (version_min) {
    283     // TODO(wtc): get the minimum SSL protocol version supported by the
    284     // SSLClientSocket class. Right now it happens to be the same as the
    285     // default minimum SSL protocol version because we enable all supported
    286     // versions by default.
    287     uint16 supported_version_min = config->version_min;
    288     config->version_min = std::max(supported_version_min, version_min);
    289   }
    290   if (version_max) {
    291     // TODO(wtc): get the maximum SSL protocol version supported by the
    292     // SSLClientSocket class.
    293     uint16 supported_version_max = config->version_max;
    294     config->version_max = std::min(supported_version_max, version_max);
    295   }
    296   config->disabled_cipher_suites = disabled_cipher_suites_;
    297   // disabling False Start also happens to disable record splitting.
    298   config->false_start_enabled = !ssl_record_splitting_disabled_.GetValue();
    299 }
    300 
    301 void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
    302     PrefService* local_state) {
    303   const base::ListValue* value =
    304       local_state->GetList(prefs::kCipherSuiteBlacklist);
    305   disabled_cipher_suites_ = ParseCipherSuites(ListValueToStringVector(value));
    306 }
    307 
    308 ////////////////////////////////////////////////////////////////////////////////
    309 //  SSLConfigServiceManager
    310 
    311 // static
    312 SSLConfigServiceManager* SSLConfigServiceManager::CreateDefaultManager(
    313     PrefService* local_state) {
    314   return new SSLConfigServiceManagerPref(local_state);
    315 }
    316 
    317 // static
    318 void SSLConfigServiceManager::RegisterPrefs(PrefRegistrySimple* registry) {
    319   SSLConfigServiceManagerPref::RegisterPrefs(registry);
    320 }
    321