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