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