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"
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"
27 using content::BrowserThread
;
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());
37 for (base::ListValue::const_iterator it
= value
->begin(); it
!= value
->end();
39 if (!(*it
)->GetAsString(&s
))
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());
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: "
62 cipher_suites
.push_back(cipher_suite
);
64 std::sort(cipher_suites
.begin(), cipher_suites
.end());
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
;
84 ////////////////////////////////////////////////////////////////////////////////
85 // SSLConfigServicePref
87 // An SSLConfigService which stores a cached version of the current SSLConfig
88 // prefs, which are updated by SSLConfigServiceManagerPref when the prefs
90 class SSLConfigServicePref
: public net::SSLConfigService
{
92 SSLConfigServicePref() {}
94 // Store SSL config settings in |config|. Must only be called from IO thread.
95 void GetSSLConfig(net::SSLConfig
* config
) override
;
98 // Allow the pref watcher to update our internal state.
99 friend class SSLConfigServiceManagerPref
;
101 ~SSLConfigServicePref() override
{}
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
);
107 // Cached value of prefs, should only be accessed from IO thread.
108 net::SSLConfig cached_config_
;
110 DISALLOW_COPY_AND_ASSIGN(SSLConfigServicePref
);
113 void SSLConfigServicePref::GetSSLConfig(net::SSLConfig
* config
) {
114 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
115 *config
= cached_config_
;
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
);
125 ////////////////////////////////////////////////////////////////////////////////
126 // SSLConfigServiceManagerPref
128 // The manager for holding and updating an SSLConfigServicePref instance.
129 class SSLConfigServiceManagerPref
130 : public SSLConfigServiceManager
{
132 explicit SSLConfigServiceManagerPref(PrefService
* local_state
);
133 ~SSLConfigServiceManagerPref() override
{}
135 // Register local_state SSL preferences.
136 static void RegisterPrefs(PrefRegistrySimple
* registry
);
138 net::SSLConfigService
* Get() override
;
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
);
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
);
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
);
154 PrefChangeRegistrar local_state_change_registrar_
;
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_
;
164 // The cached list of disabled SSL cipher suites.
165 std::vector
<uint16
> disabled_cipher_suites_
;
167 scoped_refptr
<SSLConfigServicePref
> ssl_config_service_
;
169 DISALLOW_COPY_AND_ASSIGN(SSLConfigServiceManagerPref
);
172 SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
173 PrefService
* local_state
)
174 : ssl_config_service_(new SSLConfigServicePref()) {
177 PrefChangeRegistrar::NamedChangeCallback local_state_callback
= base::Bind(
178 &SSLConfigServiceManagerPref::OnPreferenceChanged
,
179 base::Unretained(this),
182 rev_checking_enabled_
.Init(
183 prefs::kCertRevocationCheckingEnabled
, local_state
, local_state_callback
);
184 rev_checking_required_local_anchors_
.Init(
185 prefs::kCertRevocationCheckingRequiredLocalAnchors
,
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
);
197 local_state_change_registrar_
.Init(local_state
);
198 local_state_change_registrar_
.Add(
199 prefs::kCipherSuiteBlacklist
, local_state_callback
);
201 OnDisabledCipherSuitesChange(local_state
);
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_
);
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
);
224 net::SSLConfigService
* SSLConfigServiceManagerPref::Get() {
225 return ssl_config_service_
.get();
228 void SSLConfigServiceManagerPref::OnPreferenceChanged(
230 const std::string
& pref_name_in
) {
231 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
233 if (pref_name_in
== prefs::kCipherSuiteBlacklist
)
234 OnDisabledCipherSuitesChange(prefs
);
236 net::SSLConfig new_config
;
237 GetSSLConfigFromPrefs(&new_config
);
239 // Post a task to |io_loop| with the new configuration, so it can
240 // update |cached_config_|.
241 BrowserThread::PostTask(
245 &SSLConfigServicePref::SetNewSSLConfig
,
246 ssl_config_service_
.get(),
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();
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
);
271 config
->version_min
= version_min
;
274 uint16 supported_version_max
= config
->version_max
;
275 config
->version_max
= std::min(supported_version_max
, version_max
);
277 if (version_fallback_min
) {
278 config
->version_fallback_min
= version_fallback_min
;
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();
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
));
292 ////////////////////////////////////////////////////////////////////////////////
293 // SSLConfigServiceManager
296 SSLConfigServiceManager
* SSLConfigServiceManager::CreateDefaultManager(
297 PrefService
* local_state
) {
298 return new SSLConfigServiceManagerPref(local_state
);
302 void SSLConfigServiceManager::RegisterPrefs(PrefRegistrySimple
* registry
) {
303 SSLConfigServiceManagerPref::RegisterPrefs(registry
);