ssl_config_service_manager_pref.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/public/pref_change_registrar.h" 13#include "base/prefs/public/pref_observer.h" 14#include "chrome/browser/api/prefs/pref_member.h" 15#include "chrome/browser/content_settings/content_settings_utils.h" 16#include "chrome/browser/prefs/pref_service.h" 17#include "chrome/common/chrome_notification_types.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/base/ssl_cipher_suite_names.h" 22#include "net/base/ssl_config_service.h" 23 24using content::BrowserThread; 25 26namespace { 27 28// Converts a ListValue of StringValues into a vector of strings. Any Values 29// which cannot be converted will be skipped. 30std::vector<std::string> ListValueToStringVector(const ListValue* value) { 31 std::vector<std::string> results; 32 results.reserve(value->GetSize()); 33 std::string s; 34 for (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. 46std::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. 67std::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. 85uint16 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. 107class 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); 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 130void SSLConfigServicePref::GetSSLConfig(net::SSLConfig* config) { 131 *config = cached_config_; 132} 133 134void 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. 145class SSLConfigServiceManagerPref 146 : public SSLConfigServiceManager, 147 public PrefObserver { 148 public: 149 SSLConfigServiceManagerPref(PrefService* local_state, 150 PrefService* user_prefs); 151 virtual ~SSLConfigServiceManagerPref() {} 152 153 // Register local_state SSL preferences. 154 static void RegisterPrefs(PrefService* local_state); 155 156 virtual net::SSLConfigService* Get(); 157 158 private: 159 // Callback for preference changes. This will post the changes to the IO 160 // thread with SetNewSSLConfig. 161 virtual void OnPreferenceChanged(PrefServiceBase* service, 162 const std::string& pref_name) OVERRIDE; 163 164 // Store SSL config settings in |config|, directly from the preferences. Must 165 // only be called from UI thread. 166 void GetSSLConfigFromPrefs(net::SSLConfig* config); 167 168 // Processes changes to the disabled cipher suites preference, updating the 169 // cached list of parsed SSL/TLS cipher suites that are disabled. 170 void OnDisabledCipherSuitesChange(PrefServiceBase* local_state); 171 172 // Processes changes to the default cookie settings. 173 void OnDefaultContentSettingsChange(PrefServiceBase* user_prefs); 174 175 PrefChangeRegistrar local_state_change_registrar_; 176 PrefChangeRegistrar user_prefs_change_registrar_; 177 178 // The local_state prefs (should only be accessed from UI thread) 179 BooleanPrefMember rev_checking_enabled_; 180 StringPrefMember ssl_version_min_; 181 StringPrefMember ssl_version_max_; 182 BooleanPrefMember channel_id_enabled_; 183 BooleanPrefMember ssl_record_splitting_disabled_; 184 185 // The cached list of disabled SSL cipher suites. 186 std::vector<uint16> disabled_cipher_suites_; 187 188 // The user_prefs prefs (should only be accessed from UI thread). 189 // |have_user_prefs_| will be false if no user_prefs are associated with this 190 // instance. 191 bool have_user_prefs_; 192 BooleanPrefMember block_third_party_cookies_; 193 194 // Cached value of if cookies are disabled by default. 195 bool cookies_disabled_; 196 197 scoped_refptr<SSLConfigServicePref> ssl_config_service_; 198 199 DISALLOW_COPY_AND_ASSIGN(SSLConfigServiceManagerPref); 200}; 201 202SSLConfigServiceManagerPref::SSLConfigServiceManagerPref( 203 PrefService* local_state, PrefService* user_prefs) 204 : have_user_prefs_(!!user_prefs), 205 ssl_config_service_(new SSLConfigServicePref()) { 206 DCHECK(local_state); 207 208 rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled, 209 local_state, this); 210 ssl_version_min_.Init(prefs::kSSLVersionMin, local_state, this); 211 ssl_version_max_.Init(prefs::kSSLVersionMax, local_state, this); 212 channel_id_enabled_.Init(prefs::kEnableOriginBoundCerts, local_state, this); 213 ssl_record_splitting_disabled_.Init(prefs::kDisableSSLRecordSplitting, 214 local_state, this); 215 local_state_change_registrar_.Init(local_state); 216 local_state_change_registrar_.Add(prefs::kCipherSuiteBlacklist, this); 217 218 OnDisabledCipherSuitesChange(local_state); 219 220 if (user_prefs) { 221 block_third_party_cookies_.Init(prefs::kBlockThirdPartyCookies, user_prefs, 222 this); 223 user_prefs_change_registrar_.Init(user_prefs); 224 user_prefs_change_registrar_.Add(prefs::kDefaultContentSettings, this); 225 226 OnDefaultContentSettingsChange(user_prefs); 227 } 228 229 // Initialize from UI thread. This is okay as there shouldn't be anything on 230 // the IO thread trying to access it yet. 231 GetSSLConfigFromPrefs(&ssl_config_service_->cached_config_); 232} 233 234// static 235void SSLConfigServiceManagerPref::RegisterPrefs(PrefService* local_state) { 236 net::SSLConfig default_config; 237 local_state->RegisterBooleanPref(prefs::kCertRevocationCheckingEnabled, 238 default_config.rev_checking_enabled); 239 std::string version_min_str = 240 SSLProtocolVersionToString(default_config.version_min); 241 std::string version_max_str = 242 SSLProtocolVersionToString(default_config.version_max); 243 local_state->RegisterStringPref(prefs::kSSLVersionMin, version_min_str); 244 local_state->RegisterStringPref(prefs::kSSLVersionMax, version_max_str); 245 local_state->RegisterBooleanPref(prefs::kEnableOriginBoundCerts, 246 default_config.channel_id_enabled); 247 local_state->RegisterBooleanPref(prefs::kDisableSSLRecordSplitting, 248 !default_config.false_start_enabled); 249 local_state->RegisterListPref(prefs::kCipherSuiteBlacklist); 250} 251 252net::SSLConfigService* SSLConfigServiceManagerPref::Get() { 253 return ssl_config_service_; 254} 255 256void SSLConfigServiceManagerPref::OnPreferenceChanged( 257 PrefServiceBase* prefs, 258 const std::string& pref_name_in) { 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 260 DCHECK(prefs); 261 if (pref_name_in == prefs::kCipherSuiteBlacklist) 262 OnDisabledCipherSuitesChange(prefs); 263 else if (pref_name_in == prefs::kDefaultContentSettings) 264 OnDefaultContentSettingsChange(prefs); 265 266 net::SSLConfig new_config; 267 GetSSLConfigFromPrefs(&new_config); 268 269 // Post a task to |io_loop| with the new configuration, so it can 270 // update |cached_config_|. 271 BrowserThread::PostTask( 272 BrowserThread::IO, 273 FROM_HERE, 274 base::Bind( 275 &SSLConfigServicePref::SetNewSSLConfig, 276 ssl_config_service_.get(), 277 new_config)); 278} 279 280void SSLConfigServiceManagerPref::GetSSLConfigFromPrefs( 281 net::SSLConfig* config) { 282 config->rev_checking_enabled = rev_checking_enabled_.GetValue(); 283 std::string version_min_str = ssl_version_min_.GetValue(); 284 std::string version_max_str = ssl_version_max_.GetValue(); 285 config->version_min = net::SSLConfigService::default_version_min(); 286 config->version_max = net::SSLConfigService::default_version_max(); 287 uint16 version_min = SSLProtocolVersionFromString(version_min_str); 288 uint16 version_max = SSLProtocolVersionFromString(version_max_str); 289 if (version_min) { 290 // TODO(wtc): get the minimum SSL protocol version supported by the 291 // SSLClientSocket class. Right now it happens to be the same as the 292 // default minimum SSL protocol version because we enable all supported 293 // versions by default. 294 uint16 supported_version_min = config->version_min; 295 config->version_min = std::max(supported_version_min, version_min); 296 } 297 if (version_max) { 298 // TODO(wtc): get the maximum SSL protocol version supported by the 299 // SSLClientSocket class. 300 uint16 supported_version_max = config->version_max; 301 config->version_max = std::min(supported_version_max, version_max); 302 } 303 config->disabled_cipher_suites = disabled_cipher_suites_; 304 config->channel_id_enabled = channel_id_enabled_.GetValue(); 305 if (have_user_prefs_ && 306 (cookies_disabled_ || block_third_party_cookies_.GetValue())) 307 config->channel_id_enabled = false; 308 // disabling False Start also happens to disable record splitting. 309 config->false_start_enabled = !ssl_record_splitting_disabled_.GetValue(); 310 SSLConfigServicePref::SetSSLConfigFlags(config); 311} 312 313void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange( 314 PrefServiceBase* local_state) { 315 const ListValue* value = local_state->GetList(prefs::kCipherSuiteBlacklist); 316 disabled_cipher_suites_ = ParseCipherSuites(ListValueToStringVector(value)); 317} 318 319void SSLConfigServiceManagerPref::OnDefaultContentSettingsChange( 320 PrefServiceBase* user_prefs) { 321 const DictionaryValue* value = user_prefs->GetDictionary( 322 prefs::kDefaultContentSettings); 323 int default_cookie_settings = -1; 324 cookies_disabled_ = ( 325 value && 326 value->GetInteger( 327 content_settings::GetTypeName(CONTENT_SETTINGS_TYPE_COOKIES), 328 &default_cookie_settings) && 329 default_cookie_settings == CONTENT_SETTING_BLOCK); 330} 331 332//////////////////////////////////////////////////////////////////////////////// 333// SSLConfigServiceManager 334 335// static 336SSLConfigServiceManager* SSLConfigServiceManager::CreateDefaultManager( 337 PrefService* local_state, PrefService* user_prefs) { 338 return new SSLConfigServiceManagerPref(local_state, user_prefs); 339} 340 341// static 342void SSLConfigServiceManager::RegisterPrefs(PrefService* prefs) { 343 SSLConfigServiceManagerPref::RegisterPrefs(prefs); 344} 345