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 |