summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-26 16:22:17 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-26 16:22:17 +0000
commit80c75f6850ba88b4a2305663c63069fec9d7580a (patch)
treee9aef636347e0f10a7ff7356cb759976c665f073 /net
parent0969d1b4edbc89ee74421a20b2fb4f78b7e43448 (diff)
downloadchromium_src-80c75f6850ba88b4a2305663c63069fec9d7580a.zip
chromium_src-80c75f6850ba88b4a2305663c63069fec9d7580a.tar.gz
chromium_src-80c75f6850ba88b4a2305663c63069fec9d7580a.tar.bz2
Use TLS 1.1.
Enable SSL 3.0 ~ TLS 1.1 by default. If the SSLClientSocket class does not support TLS 1.1, enable SSL 3.0 ~ TLS 1.0 by default. TLS intolerant servers are handled by falling back to the next lower protocol version at a time, rather than falling back to SSL 3.0 directly. In the SSLConfig structure, replace the ssl3_enabled and tls1_enabled members by version_min and version_max to allow multiple, contiguous protocol versions to be enabled, and rename the ssl3_fallback member to version_fallback. The preferences prefs::kSSL3Enabled and prefs::kTLS1Enabled are not yet removed. Generalize prefs::kTLS1Enabled to mean enabling or disabling all TLS versions. R=agl@chromium.org,rsleevi@chromium.org BUG=126340 TEST=net_unittests --gtest_filter=HTTPSRequestTest.TLSv1Fallback Review URL: https://chromiumcodereview.appspot.com/10377022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139204 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/ssl_config_service.cc44
-rw-r--r--net/base/ssl_config_service.h38
-rw-r--r--net/base/ssl_config_service_unittest.cc12
-rw-r--r--net/base/ssl_connection_status_flags.h6
-rw-r--r--net/http/http_network_transaction.cc46
-rw-r--r--net/http/http_network_transaction_spdy2_unittest.cc41
-rw-r--r--net/http/http_network_transaction_spdy3_unittest.cc41
-rw-r--r--net/http/http_stream_factory_impl_job.cc26
-rw-r--r--net/socket/client_socket_factory.cc10
-rw-r--r--net/socket/client_socket_pool_manager.cc34
-rw-r--r--net/socket/ssl_client_socket_mac.cc16
-rw-r--r--net/socket/ssl_client_socket_nss.cc26
-rw-r--r--net/socket/ssl_client_socket_openssl.cc26
-rw-r--r--net/socket/ssl_client_socket_win.cc17
-rw-r--r--net/socket/ssl_server_socket_nss.cc19
-rw-r--r--net/socket/ssl_server_socket_unittest.cc4
-rw-r--r--net/url_request/url_request_unittest.cc40
17 files changed, 348 insertions, 98 deletions
diff --git a/net/base/ssl_config_service.cc b/net/base/ssl_config_service.cc
index 602bb21..3a79540 100644
--- a/net/base/ssl_config_service.cc
+++ b/net/base/ssl_config_service.cc
@@ -10,22 +10,39 @@
#include "net/base/crl_set.h"
#include "net/base/ssl_config_service_defaults.h"
+#if defined(USE_OPENSSL)
+#include <openssl/ssl.h>
+#endif
+
namespace net {
+static uint16 g_default_version_min = SSL_PROTOCOL_VERSION_SSL3;
+
+static uint16 g_default_version_max =
+#if defined(USE_OPENSSL)
+#if defined(SSL_OP_NO_TLSv1_1)
+ SSL_PROTOCOL_VERSION_TLS1_1;
+#else
+ SSL_PROTOCOL_VERSION_TLS1;
+#endif
+#else
+ SSL_PROTOCOL_VERSION_TLS1_1;
+#endif
+
SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
SSLConfig::CertAndStatus::~CertAndStatus() {}
SSLConfig::SSLConfig()
: rev_checking_enabled(false),
- ssl3_enabled(true),
- tls1_enabled(true),
+ version_min(g_default_version_min),
+ version_max(g_default_version_max),
cached_info_enabled(false),
domain_bound_certs_enabled(false),
false_start_enabled(true),
send_client_cert(false),
verify_ev_cert(false),
- ssl3_fallback(false),
+ version_fallback(false),
cert_io_enabled(true) {
}
@@ -102,6 +119,21 @@ bool SSLConfigService::cached_info_enabled() {
}
// static
+uint16 SSLConfigService::default_version_min() {
+ return g_default_version_min;
+}
+
+// static
+void SSLConfigService::SetDefaultVersionMax(uint16 version_max) {
+ g_default_version_max = version_max;
+}
+
+// static
+uint16 SSLConfigService::default_version_max() {
+ return g_default_version_max;
+}
+
+// static
void SSLConfigService::EnableDomainBoundCertsTrial() {
g_domain_bound_certs_trial = true;
}
@@ -128,8 +160,8 @@ void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
const SSLConfig& new_config) {
bool config_changed =
(orig_config.rev_checking_enabled != new_config.rev_checking_enabled) ||
- (orig_config.ssl3_enabled != new_config.ssl3_enabled) ||
- (orig_config.tls1_enabled != new_config.tls1_enabled) ||
+ (orig_config.version_min != new_config.version_min) ||
+ (orig_config.version_max != new_config.version_max) ||
(orig_config.disabled_cipher_suites !=
new_config.disabled_cipher_suites) ||
(orig_config.domain_bound_certs_enabled !=
@@ -148,7 +180,7 @@ bool SSLConfigService::IsSNIAvailable(SSLConfigService* service) {
SSLConfig ssl_config;
service->GetSSLConfig(&ssl_config);
- return ssl_config.tls1_enabled;
+ return ssl_config.version_max >= SSL_PROTOCOL_VERSION_TLS1;
}
} // namespace net
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index f977370..37f66d2 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -19,10 +19,24 @@
namespace net {
+// Various TLS/SSL ProtocolVersion values encoded as uint16
+// struct {
+// uint8 major;
+// uint8 minor;
+// } ProtocolVersion;
+// The most significant byte is |major|, and the least significant byte
+// is |minor|.
+enum {
+ SSL_PROTOCOL_VERSION_SSL3 = 0x0300,
+ SSL_PROTOCOL_VERSION_TLS1 = 0x0301,
+ SSL_PROTOCOL_VERSION_TLS1_1 = 0x0302,
+ SSL_PROTOCOL_VERSION_TLS1_2 = 0x0303,
+};
+
// A collection of SSL-related configuration settings.
struct NET_EXPORT SSLConfig {
// Default to revocation checking.
- // Default to SSL 3.0 on and TLS 1.0 on.
+ // Default to SSL 3.0 ~ default_version_max() on.
SSLConfig();
~SSLConfig();
@@ -43,9 +57,13 @@ struct NET_EXPORT SSLConfig {
// cached revocation information will be considered.
bool rev_checking_enabled;
- // SSL 2.0 is not supported.
- bool ssl3_enabled; // True if SSL 3.0 is enabled.
- bool tls1_enabled; // True if TLS 1.0 is enabled.
+ // The minimum and maximum protocol versions that are enabled.
+ // SSL 3.0 is 0x0300, TLS 1.0 is 0x0301, TLS 1.1 is 0x0302, and so on.
+ // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.)
+ // SSL 2.0 is not supported. If version_max < version_min, it means no
+ // protocol versions are enabled.
+ uint16 version_min;
+ uint16 version_max;
// Presorted list of cipher suites which should be explicitly prevented from
// being used in addition to those disabled by the net built-in policy.
@@ -96,8 +114,9 @@ struct NET_EXPORT SSLConfig {
bool verify_ev_cert; // True if we should verify the certificate for EV.
- bool ssl3_fallback; // True if we are falling back to SSL 3.0 (one still
- // needs to clear tls1_enabled).
+ bool version_fallback; // True if we are falling back to an older protocol
+ // version (one still needs to decrement
+ // version_max).
// If cert_io_enabled is false, then certificate verification will not
// result in additional HTTP requests. (For example: to fetch missing
@@ -154,6 +173,13 @@ class NET_EXPORT SSLConfigService
static void EnableCachedInfo();
static bool cached_info_enabled();
+ // Gets the default minimum protocol version.
+ static uint16 default_version_min();
+
+ // Sets and gets the default maximum protocol version.
+ static void SetDefaultVersionMax(uint16 version_max);
+ static uint16 default_version_max();
+
// Force domain bound cert support to be enabled.
static void EnableDomainBoundCertsTrial();
diff --git a/net/base/ssl_config_service_unittest.cc b/net/base/ssl_config_service_unittest.cc
index 2ac2a9b..7c28b61 100644
--- a/net/base/ssl_config_service_unittest.cc
+++ b/net/base/ssl_config_service_unittest.cc
@@ -50,8 +50,8 @@ class MockSSLConfigServiceObserver : public SSLConfigService::Observer {
TEST(SSLConfigServiceTest, NoChangesWontNotifyObservers) {
SSLConfig initial_config;
initial_config.rev_checking_enabled = true;
- initial_config.ssl3_enabled = true;
- initial_config.tls1_enabled = true;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
scoped_refptr<MockSSLConfigService> mock_service(
new MockSSLConfigService(initial_config));
@@ -67,8 +67,8 @@ TEST(SSLConfigServiceTest, NoChangesWontNotifyObservers) {
TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
SSLConfig initial_config;
initial_config.rev_checking_enabled = true;
- initial_config.ssl3_enabled = true;
- initial_config.tls1_enabled = true;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
scoped_refptr<MockSSLConfigService> mock_service(
new MockSSLConfigService(initial_config));
@@ -80,11 +80,11 @@ TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) {
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
- initial_config.ssl3_enabled = false;
+ initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
- initial_config.tls1_enabled = false;
+ initial_config.version_max = SSL_PROTOCOL_VERSION_SSL3;
EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
mock_service->SetSSLConfig(initial_config);
diff --git a/net/base/ssl_connection_status_flags.h b/net/base/ssl_connection_status_flags.h
index 9596f00..bf349ce 100644
--- a/net/base/ssl_connection_status_flags.h
+++ b/net/base/ssl_connection_status_flags.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -18,8 +18,8 @@ enum {
SSL_CONNECTION_COMPRESSION_SHIFT = 16,
SSL_CONNECTION_COMPRESSION_MASK = 3,
- // We fell back to SSLv3 for this connection.
- SSL_CONNECTION_SSL3_FALLBACK = 1 << 18,
+ // We fell back to an older protocol version for this connection.
+ SSL_CONNECTION_VERSION_FALLBACK = 1 << 18,
// The server doesn't support the renegotiation_info extension. If this bit
// is not set then either the extension isn't supported, or we don't have any
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 7b52766..8f94732 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1162,16 +1162,39 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
switch (error) {
case ERR_SSL_PROTOCOL_ERROR:
case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
+ if (server_ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
+ server_ssl_config_.version_max > server_ssl_config_.version_min) {
+ // This could be a TLS-intolerant server or a server that chose a
+ // cipher suite defined only for higher protocol versions (such as
+ // an SSL 3.0 server that chose a TLS-only cipher suite). Fall
+ // back to the next lower version and retry.
+ // NOTE: if the SSLClientSocket class doesn't support TLS 1.1,
+ // specifying TLS 1.1 in version_max will result in a TLS 1.0
+ // handshake, so falling back from TLS 1.1 to TLS 1.0 will simply
+ // repeat the TLS 1.0 handshake. To avoid this problem, the default
+ // version_max should match the maximum protocol version supported
+ // by the SSLClientSocket class.
+ LOG(WARNING) << "Falling back one version because host is "
+ "TLS intolerant: " << GetHostAndPort(request_->url)
+ << " error: " << error;
+ server_ssl_config_.version_max--;
+ server_ssl_config_.version_fallback = true;
+ ResetConnectionAndRequestForResend();
+ error = OK;
+ }
+ break;
case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
case ERR_SSL_BAD_RECORD_MAC_ALERT:
- if (server_ssl_config_.tls1_enabled) {
- // This could be a TLS-intolerant server, an SSL 3.0 server that
- // chose a TLS-only cipher suite or a server with buggy DEFLATE
- // support. Turn off TLS 1.0, DEFLATE support and retry.
- LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: "
- << GetHostAndPort(request_->url);
- server_ssl_config_.tls1_enabled = false;
- server_ssl_config_.ssl3_fallback = true;
+ if (server_ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
+ server_ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3) {
+ // This could be a server with buggy DEFLATE support. Turn off TLS,
+ // DEFLATE support and retry.
+ // TODO(wtc): turn off DEFLATE support only. Do not tie it to TLS.
+ LOG(WARNING) << "Falling back to SSLv3 because host has buggy TLS "
+ "compression support: "
+ << GetHostAndPort(request_->url) << " error: " << error;
+ server_ssl_config_.version_max = SSL_PROTOCOL_VERSION_SSL3;
+ server_ssl_config_.version_fallback = true;
ResetConnectionAndRequestForResend();
error = OK;
}
@@ -1188,10 +1211,9 @@ int HttpNetworkTransaction::HandleIOError(int error) {
// SSL errors may happen at any time during the stream and indicate issues
// with the underlying connection. Because the peer may request
// renegotiation at any time, check and handle any possible SSL handshake
- // related errors. In addition to renegotiation, TLS False/Snap Start may
- // cause SSL handshake errors to be delayed until the first or second Write
- // (Snap Start) or the first Read (False & Snap Start) on the underlying
- // connection.
+ // related errors. In addition to renegotiation, TLS False Start may cause
+ // SSL handshake errors (specifically servers with buggy DEFLATE support)
+ // to be delayed until the first Read on the underlying connection.
error = HandleSSLHandshakeError(error);
switch (error) {
diff --git a/net/http/http_network_transaction_spdy2_unittest.cc b/net/http/http_network_transaction_spdy2_unittest.cc
index 27470e0..fdb18b0 100644
--- a/net/http/http_network_transaction_spdy2_unittest.cc
+++ b/net/http/http_network_transaction_spdy2_unittest.cc
@@ -9101,8 +9101,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
// [ssl_]data3 contains the data for the third SSL handshake. When a
// connection to a server fails during an SSL handshake,
- // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
- // connection was attempted with TLSv1. This is transparent to the caller
+ // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
+ // connection was attempted with TLSv1.1. This is transparent to the caller
// of the HttpNetworkTransaction. Because this test failure is due to
// requiring a client certificate, this fallback handshake should also
// fail.
@@ -9112,6 +9112,19 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+ // [ssl_]data4 contains the data for the fourth SSL handshake. When a
+ // connection to a server fails during an SSL handshake,
+ // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
+ // connection was attempted with TLSv1. This is transparent to the caller
+ // of the HttpNetworkTransaction. Because this test failure is due to
+ // requiring a client certificate, this fallback handshake should also
+ // fail.
+ SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data4.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data4);
+ net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data4);
+
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
@@ -9140,8 +9153,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
ASSERT_EQ(NULL, client_cert.get());
// Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
+ // then consume ssl_data3 and ssl_data4, both of which should also fail.
+ // The result code is checked against what ssl_data4 should return.
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
@@ -9208,8 +9221,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
session_deps.socket_factory.AddSocketDataProvider(&data2);
// As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
- // the data for the SSL handshake once the TLSv1 connection falls back to
- // SSLv3. It has the same behaviour as [ssl_]data2.
+ // the data for the SSL handshake once the TLSv1.1 connection falls back to
+ // TLSv1. It has the same behaviour as [ssl_]data2.
SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
ssl_data3.cert_request_info = cert_request.get();
session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
@@ -9217,6 +9230,15 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+ // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
+ // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
+ SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
+ ssl_data4.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data4);
+ net::StaticSocketDataProvider data4(
+ data2_reads, arraysize(data2_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data4);
+
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
@@ -9246,8 +9268,8 @@ TEST_F(HttpNetworkTransactionSpdy2Test,
// Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
+ // then consume ssl_data3 and ssl_data4, both of which should also fail.
+ // The result code is checked against what ssl_data4 should return.
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
@@ -9290,11 +9312,14 @@ TEST_F(HttpNetworkTransactionSpdy2Test, ClientAuthCertCache_Proxy_Fail) {
net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data2);
+ // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
+#if 0
SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data3.cert_request_info = cert_request.get();
session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+#endif
net::HttpRequestInfo requests[2];
requests[0].url = GURL("https://www.example.com/");
diff --git a/net/http/http_network_transaction_spdy3_unittest.cc b/net/http/http_network_transaction_spdy3_unittest.cc
index 6f7468d..81051b2 100644
--- a/net/http/http_network_transaction_spdy3_unittest.cc
+++ b/net/http/http_network_transaction_spdy3_unittest.cc
@@ -9100,8 +9100,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test,
// [ssl_]data3 contains the data for the third SSL handshake. When a
// connection to a server fails during an SSL handshake,
- // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
- // connection was attempted with TLSv1. This is transparent to the caller
+ // HttpNetworkTransaction will attempt to fallback to TLSv1 if the previous
+ // connection was attempted with TLSv1.1. This is transparent to the caller
// of the HttpNetworkTransaction. Because this test failure is due to
// requiring a client certificate, this fallback handshake should also
// fail.
@@ -9111,6 +9111,19 @@ TEST_F(HttpNetworkTransactionSpdy3Test,
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+ // [ssl_]data4 contains the data for the fourth SSL handshake. When a
+ // connection to a server fails during an SSL handshake,
+ // HttpNetworkTransaction will attempt to fallback to SSLv3 if the previous
+ // connection was attempted with TLSv1. This is transparent to the caller
+ // of the HttpNetworkTransaction. Because this test failure is due to
+ // requiring a client certificate, this fallback handshake should also
+ // fail.
+ SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
+ ssl_data4.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data4);
+ net::StaticSocketDataProvider data4(NULL, 0, NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data4);
+
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
@@ -9139,8 +9152,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test,
ASSERT_EQ(NULL, client_cert.get());
// Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
+ // then consume ssl_data3 and ssl_data4, both of which should also fail.
+ // The result code is checked against what ssl_data4 should return.
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
@@ -9206,8 +9219,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test, ClientAuthCertCache_Direct_FalseStart) {
session_deps.socket_factory.AddSocketDataProvider(&data2);
// As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
- // the data for the SSL handshake once the TLSv1 connection falls back to
- // SSLv3. It has the same behaviour as [ssl_]data2.
+ // the data for the SSL handshake once the TLSv1.1 connection falls back to
+ // TLSv1. It has the same behaviour as [ssl_]data2.
SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
ssl_data3.cert_request_info = cert_request.get();
session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
@@ -9215,6 +9228,15 @@ TEST_F(HttpNetworkTransactionSpdy3Test, ClientAuthCertCache_Direct_FalseStart) {
data2_reads, arraysize(data2_reads), NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+ // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection
+ // falls back to SSLv3. It has the same behaviour as [ssl_]data2.
+ SSLSocketDataProvider ssl_data4(ASYNC, net::OK);
+ ssl_data4.cert_request_info = cert_request.get();
+ session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data4);
+ net::StaticSocketDataProvider data4(
+ data2_reads, arraysize(data2_reads), NULL, 0);
+ session_deps.socket_factory.AddSocketDataProvider(&data4);
+
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
@@ -9244,8 +9266,8 @@ TEST_F(HttpNetworkTransactionSpdy3Test, ClientAuthCertCache_Direct_FalseStart) {
// Restart the handshake. This will consume ssl_data2, which fails, and
- // then consume ssl_data3, which should also fail. The result code is
- // checked against what ssl_data3 should return.
+ // then consume ssl_data3 and ssl_data4, both of which should also fail.
+ // The result code is checked against what ssl_data4 should return.
rv = callback.WaitForResult();
ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
@@ -9288,11 +9310,14 @@ TEST_F(HttpNetworkTransactionSpdy3Test, ClientAuthCertCache_Proxy_Fail) {
net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data2);
+ // TODO(wtc): find out why this unit test doesn't need [ssl_]data3.
+#if 0
SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
ssl_data3.cert_request_info = cert_request.get();
session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
session_deps.socket_factory.AddSocketDataProvider(&data3);
+#endif
net::HttpRequestInfo requests[2];
requests[0].url = GURL("https://www.example.com/");
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 7a2aa87..15cba9d 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -1071,8 +1071,30 @@ void HttpStreamFactoryImpl::Job::InitSSLConfig(
ssl_config->false_start_enabled = false;
}
- UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLv3Fallback",
- static_cast<int>(ssl_config->ssl3_fallback), 2);
+ enum {
+ FALLBACK_NONE = 0, // SSL version fallback did not occur.
+ FALLBACK_SSL3 = 1, // Fell back to SSL 3.0.
+ FALLBACK_TLS1 = 2, // Fell back to TLS 1.0.
+ FALLBACK_TLS1_1 = 3, // Fell back to TLS 1.1.
+ FALLBACK_MAX
+ };
+
+ int fallback = FALLBACK_NONE;
+ if (ssl_config->version_fallback) {
+ switch (ssl_config->version_max) {
+ case SSL_PROTOCOL_VERSION_SSL3:
+ fallback = FALLBACK_SSL3;
+ break;
+ case SSL_PROTOCOL_VERSION_TLS1:
+ fallback = FALLBACK_TLS1;
+ break;
+ case SSL_PROTOCOL_VERSION_TLS1_1:
+ fallback = FALLBACK_TLS1_1;
+ break;
+ }
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLVersionFallback",
+ fallback, FALLBACK_MAX);
if (request_info_.load_flags & LOAD_VERIFY_EV_CERT)
ssl_config->verify_ev_cert = true;
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index 60daef4..42f6d4f 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -134,6 +134,14 @@ ClientSocketFactory* ClientSocketFactory::GetDefaultFactory() {
// static
void ClientSocketFactory::UseSystemSSL() {
g_use_system_ssl = true;
+
+#if defined(OS_WIN)
+ // Reflect the capability of SSLClientSocketWin.
+ SSLConfigService::SetDefaultVersionMax(SSL_PROTOCOL_VERSION_TLS1);
+#elif defined(OS_MACOSX)
+ // Reflect the capability of SSLClientSocketMac.
+ SSLConfigService::SetDefaultVersionMax(SSL_PROTOCOL_VERSION_TLS1);
+#endif
}
} // namespace net
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 20b02f4..70f1edb 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -112,11 +112,35 @@ int InitSocketPoolHelper(const GURL& request_url,
std::string connection_group = origin_host_port.ToString();
DCHECK(!connection_group.empty());
if (using_ssl) {
- std::string prefix;
- if (ssl_config_for_origin.tls1_enabled) {
- prefix = "ssl/";
- } else {
- prefix = "sslv3/";
+ // All connections in a group should use the same SSLConfig settings.
+ // Encode version_max in the connection group's name, unless it's the
+ // default version_max. (We want the common case to use the shortest
+ // encoding). A version_max of TLS 1.1 is encoded as "ssl(max:3.2)/"
+ // rather than "tlsv1.1/" because the actual protocol version, which
+ // is selected by the server, may not be TLS 1.1. Do not encode
+ // version_min in the connection group's name because version_min
+ // should be the same for all connections, whereas version_max may
+ // change for version fallbacks.
+ std::string prefix = "ssl/";
+ if (ssl_config_for_origin.version_max !=
+ SSLConfigService::default_version_max()) {
+ switch (ssl_config_for_origin.version_max) {
+ case SSL_PROTOCOL_VERSION_TLS1_2:
+ prefix = "ssl(max:3.3)/";
+ break;
+ case SSL_PROTOCOL_VERSION_TLS1_1:
+ prefix = "ssl(max:3.2)/";
+ break;
+ case SSL_PROTOCOL_VERSION_TLS1:
+ prefix = "ssl(max:3.1)/";
+ break;
+ case SSL_PROTOCOL_VERSION_SSL3:
+ prefix = "sslv3/";
+ break;
+ default:
+ CHECK(false);
+ break;
+ }
}
connection_group = prefix + connection_group;
}
diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc
index f84f3fb..862ef52 100644
--- a/net/socket/ssl_client_socket_mac.cc
+++ b/net/socket/ssl_client_socket_mac.cc
@@ -738,8 +738,8 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) {
SSL_CONNECTION_CIPHERSUITE_SHIFT;
}
- if (ssl_config_.ssl3_fallback)
- ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
+ if (ssl_config_.version_fallback)
+ ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
}
void SSLClientSocketMac::GetSSLCertRequestInfo(
@@ -812,15 +812,23 @@ int SSLClientSocketMac::InitializeSSLContext() {
if (status)
return NetErrorFromOSStatus(status);
+ // If ssl_config_.version_max > SSL_PROTOCOL_VERSION_TLS1, it means the
+ // SSLConfigService::SetDefaultVersionMax(SSL_PROTOCOL_VERSION_TLS1) call
+ // in ClientSocketFactory::UseSystemSSL() is not effective.
+ DCHECK_LE(ssl_config_.version_max, SSL_PROTOCOL_VERSION_TLS1);
+
+ bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
status = SSLSetProtocolVersionEnabled(ssl_context_,
kSSLProtocol3,
- ssl_config_.ssl3_enabled);
+ ssl3_enabled);
if (status)
return NetErrorFromOSStatus(status);
+ bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
status = SSLSetProtocolVersionEnabled(ssl_context_,
kTLSProtocol1,
- ssl_config_.tls1_enabled);
+ tls1_enabled);
if (status)
return NetErrorFromOSStatus(status);
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index ed99bbf..d45b429 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -864,16 +864,13 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, ssl_config_.ssl3_enabled);
+ SSLVersionRange version_range;
+ version_range.min = ssl_config_.version_min;
+ version_range.max = ssl_config_.version_max;
+ rv = SSL_VersionRangeSet(nss_fd_, &version_range);
if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
- return ERR_UNEXPECTED;
+ LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
+ return ERR_NO_SSL_VERSIONS_ENABLED;
}
for (std::vector<uint16>::const_iterator it =
@@ -900,7 +897,8 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// is advertised. Thus, if TLS is disabled (probably because we are doing
// SSLv3 fallback), we disable DEFLATE also.
// See http://crbug.com/31628
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE, ssl_config_.tls1_enabled);
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_DEFLATE,
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
if (rv != SECSuccess)
LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_DEFLATE");
#endif
@@ -1135,8 +1133,8 @@ void SSLClientSocketNSS::UpdateConnectionStatus() {
}
#endif
- if (ssl_config_.ssl3_fallback)
- ssl_connection_status_ |= SSL_CONNECTION_SSL3_FALLBACK;
+ if (ssl_config_.version_fallback)
+ ssl_connection_status_ |= SSL_CONNECTION_VERSION_FALLBACK;
}
void SSLClientSocketNSS::DoReadCallback(int rv) {
@@ -1759,7 +1757,9 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
IsCertStatusMinorError(cert_status))) &&
server_cert_verify_result_->is_issued_by_known_root &&
transport_security_state_) {
- bool sni_available = ssl_config_.tls1_enabled || ssl_config_.ssl3_fallback;
+ bool sni_available =
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1 ||
+ ssl_config_.version_fallback;
const std::string& host = host_and_port_.host();
TransportSecurityState::DomainState domain_state;
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index 55f9fbf..ba52ec0 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -467,13 +467,29 @@ bool SSLClientSocketOpenSSL::Init() {
// set everything we care about to an absolute value.
SslSetClearMask options;
options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
- options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl_config_.ssl3_enabled);
- options.ConfigureFlag(SSL_OP_NO_TLSv1, !ssl_config_.tls1_enabled);
+ bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
+ options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);
+ bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
+ options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);
+#if defined(SSL_OP_NO_TLSv1_1)
+ bool tls1_1_enabled =
+ (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 &&
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);
+ options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);
+#endif
+#if defined(SSL_OP_NO_TLSv1_2)
+ bool tls1_2_enabled =
+ (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 &&
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);
+ options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);
+#endif
#if defined(SSL_OP_NO_COMPRESSION)
// If TLS was disabled also disable compression, to provide maximum site
// compatibility in the case of protocol fallback. See http://crbug.com/31628
- options.ConfigureFlag(SSL_OP_NO_COMPRESSION, !ssl_config_.tls1_enabled);
+ options.ConfigureFlag(SSL_OP_NO_COMPRESSION,
+ ssl_config_.version_max < SSL_PROTOCOL_VERSION_TLS1);
#endif
// TODO(joth): Set this conditionally, see http://crbug.com/55410
@@ -601,8 +617,8 @@ void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
implicit_cast<int>(peer_supports_renego_ext), 2);
- if (ssl_config_.ssl3_fallback)
- ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
+ if (ssl_config_.version_fallback)
+ ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
DVLOG(3) << "Encoded connection status: cipher suite = "
<< SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc
index 1442ad6..8728532 100644
--- a/net/socket/ssl_client_socket_win.cc
+++ b/net/socket/ssl_client_socket_win.cc
@@ -116,6 +116,7 @@ static int MapSecurityError(SECURITY_STATUS err) {
// A bitmask consisting of these bit flags encodes which versions of the SSL
// protocol (SSL 3.0 and TLS 1.0) are enabled.
+// TODO(wtc): support TLS 1.1 and TLS 1.2 on Windows Vista and later.
enum {
SSL3 = 1 << 0,
TLS1 = 1 << 1,
@@ -423,6 +424,8 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
// dwExchStrength and dwHashStrength. dwExchStrength needs to be
// normalized.
ssl_info->security_bits = connection_info.dwCipherStrength;
+ // TODO(wtc): connection_info.dwProtocol is the negotiated version.
+ // Save it in ssl_info->connection_status.
}
// SecPkgContext_CipherInfo comes from CNG and is available on Vista or
// later only. On XP, the next QueryContextAttributes call fails with
@@ -442,8 +445,8 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
// any field related to the compression method.
}
- if (ssl_config_.ssl3_fallback)
- ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
+ if (ssl_config_.version_fallback)
+ ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
}
void SSLClientSocketWin::GetSSLCertRequestInfo(
@@ -585,11 +588,17 @@ int SSLClientSocketWin::Connect(const CompletionCallback& callback) {
}
int SSLClientSocketWin::InitializeSSLContext() {
+ // If ssl_config_.version_max > SSL_PROTOCOL_VERSION_TLS1, it means the
+ // SSLConfigService::SetDefaultVersionMax(SSL_PROTOCOL_VERSION_TLS1) call
+ // in ClientSocketFactory::UseSystemSSL() is not effective.
+ DCHECK_LE(ssl_config_.version_max, SSL_PROTOCOL_VERSION_TLS1);
int ssl_version_mask = 0;
- if (ssl_config_.ssl3_enabled)
+ if (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3)
ssl_version_mask |= SSL3;
- if (ssl_config_.tls1_enabled)
+ if (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
+ ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1) {
ssl_version_mask |= TLS1;
+ }
// If we pass 0 to GetCredHandle, we will let Schannel select the protocols,
// rather than enabling no protocols. So we have to fail here.
if (ssl_version_mask == 0)
diff --git a/net/socket/ssl_server_socket_nss.cc b/net/socket/ssl_server_socket_nss.cc
index 9ba0aaa..76d5559 100644
--- a/net/socket/ssl_server_socket_nss.cc
+++ b/net/socket/ssl_server_socket_nss.cc
@@ -68,8 +68,8 @@ SSLServerSocketNSS::SSLServerSocketNSS(
next_handshake_state_(STATE_NONE),
completed_handshake_(false) {
ssl_config_.false_start_enabled = false;
- ssl_config_.ssl3_enabled = true;
- ssl_config_.tls1_enabled = true;
+ ssl_config_.version_min = SSL_PROTOCOL_VERSION_SSL3;
+ ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
// TODO(hclam): Need a better way to clone a key.
std::vector<uint8> key_bytes;
@@ -284,16 +284,13 @@ int SSLServerSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, PR_TRUE);
+ SSLVersionRange version_range;
+ version_range.min = ssl_config_.version_min;
+ version_range.max = ssl_config_.version_max;
+ rv = SSL_VersionRangeSet(nss_fd_, &version_range);
if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
- return ERR_UNEXPECTED;
- }
-
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
- return ERR_UNEXPECTED;
+ LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
+ return ERR_NO_SSL_VERSIONS_ENABLED;
}
for (std::vector<uint16>::const_iterator it =
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index 53af569..806a598 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -326,8 +326,8 @@ class SSLServerSocketTest : public PlatformTest {
ssl_config.cached_info_enabled = false;
ssl_config.false_start_enabled = false;
ssl_config.domain_bound_certs_enabled = false;
- ssl_config.ssl3_enabled = true;
- ssl_config.tls1_enabled = true;
+ ssl_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
+ ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
// Certificate provided by the host doesn't need authority.
net::SSLConfig::CertAndStatus cert_and_status;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index aae4b4e..e6b7658 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -1751,9 +1751,45 @@ TEST_F(HTTPSRequestTest, SSLv3Fallback) {
EXPECT_EQ(1, d.response_started_count());
EXPECT_NE(0, d.bytes_received());
- EXPECT_EQ(SSL_CONNECTION_VERSION_SSL3,
+ EXPECT_EQ(static_cast<int>(SSL_CONNECTION_VERSION_SSL3),
SSLConnectionStatusToVersion(r.ssl_info().connection_status));
- EXPECT_TRUE(r.ssl_info().connection_status & SSL_CONNECTION_SSL3_FALLBACK);
+ EXPECT_TRUE(r.ssl_info().connection_status & SSL_CONNECTION_VERSION_FALLBACK);
+}
+
+// Tests TLSv1.1 -> TLSv1 fallback. Verifies that we don't fall back more
+// than necessary.
+TEST_F(HTTPSRequestTest, TLSv1Fallback) {
+ uint16 default_version_max = SSLConfigService::default_version_max();
+ // The OpenSSL library in use may not support TLS 1.1.
+#if !defined(USE_OPENSSL)
+ EXPECT_GT(default_version_max, SSL_PROTOCOL_VERSION_TLS1);
+#endif
+ if (default_version_max <= SSL_PROTOCOL_VERSION_TLS1)
+ return;
+
+ TestServer::HTTPSOptions https_options(
+ TestServer::HTTPSOptions::CERT_OK);
+ https_options.tls_intolerant =
+ TestServer::HTTPSOptions::TLS_INTOLERANT_TLS1_1;
+ TestServer test_server(https_options,
+ FilePath(FILE_PATH_LITERAL("net/data/ssl")));
+ ASSERT_TRUE(test_server.Start());
+
+ TestDelegate d;
+ TestURLRequestContext context(true);
+ context.Init();
+ d.set_allow_certificate_errors(true);
+ URLRequest r(test_server.GetURL(""), &d);
+ r.set_context(&context);
+ r.Start();
+
+ MessageLoop::current()->Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ EXPECT_NE(0, d.bytes_received());
+ EXPECT_EQ(static_cast<int>(SSL_CONNECTION_VERSION_TLS1),
+ SSLConnectionStatusToVersion(r.ssl_info().connection_status));
+ EXPECT_TRUE(r.ssl_info().connection_status & SSL_CONNECTION_VERSION_FALLBACK);
}
// This tests that a load of www.google.com with a certificate error sets