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