summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/http/http_network_transaction.cc21
-rw-r--r--net/socket/ssl_client_socket_nss.cc43
-rw-r--r--net/url_request/url_request_unittest.cc28
3 files changed, 54 insertions, 38 deletions
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 0e278eb..0a2c8c4 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1306,6 +1306,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
uint16 version_max = server_ssl_config_.version_max;
switch (error) {
+ case ERR_CONNECTION_CLOSED:
case ERR_SSL_PROTOCOL_ERROR:
case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
if (version_max >= SSL_PROTOCOL_VERSION_TLS1 &&
@@ -1329,6 +1330,26 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
should_fallback = true;
}
break;
+ case ERR_CONNECTION_RESET:
+ if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
+ version_max > server_ssl_config_.version_min) {
+ // Some network devices that inspect application-layer packets seem to
+ // inject TCP reset packets to break the connections when they see TLS
+ // 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
+ //
+ // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
+ // 1.2. We don't lose much in this fallback because the explicit IV for
+ // CBC mode in TLS 1.1 is approximated by record splitting in TLS
+ // 1.0. The fallback will be more painful for TLS 1.2 when we have GCM
+ // support.
+ //
+ // ERR_CONNECTION_RESET is a common network error, so we don't want it
+ // to trigger a version fallback in general, especially the TLS 1.0 ->
+ // SSL 3.0 fallback, which would drop TLS extensions.
+ version_max--;
+ should_fallback = true;
+ }
+ break;
case ERR_SSL_BAD_RECORD_MAC_ALERT:
if (version_max >= SSL_PROTOCOL_VERSION_TLS1_1 &&
version_max > server_ssl_config_.version_min) {
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index deece93..6eca964 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -474,18 +474,6 @@ int MapNSSClientError(PRErrorCode err) {
}
}
-// Map NSS error code from the first SSL handshake to network error code.
-int MapNSSClientHandshakeError(PRErrorCode err) {
- switch (err) {
- // If the server closed on us, it is a protocol error.
- // Some TLS-intolerant servers do this when we request TLS.
- case PR_END_OF_FILE_ERROR:
- return ERR_SSL_PROTOCOL_ERROR;
- default:
- return MapNSSClientError(err);
- }
-}
-
} // namespace
// SSLClientSocketNSS::Core provides a thread-safe, ref-counted core that is
@@ -720,7 +708,7 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
// Handles an NSS error generated while handshaking or performing IO.
// Returns a network error code mapped from the original NSS error.
- int HandleNSSError(PRErrorCode error, bool handshake_error);
+ int HandleNSSError(PRErrorCode error);
int DoHandshakeLoop(int last_io_result);
int DoReadLoop(int result);
@@ -1683,12 +1671,10 @@ void SSLClientSocketNSS::Core::HandshakeSucceeded() {
nss_handshake_state_));
}
-int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error,
- bool handshake_error) {
+int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error) {
DCHECK(OnNSSTaskRunner());
- int net_error = handshake_error ? MapNSSClientHandshakeError(nss_error) :
- MapNSSClientError(nss_error);
+ int net_error = MapNSSClientError(nss_error);
#if defined(OS_WIN)
// On Windows, a handle to the HCRYPTPROV is cached in the X509Certificate
@@ -1846,24 +1832,7 @@ int SSLClientSocketNSS::Core::DoHandshake() {
}
} else {
PRErrorCode prerr = PR_GetError();
- net_error = HandleNSSError(prerr, true);
-
- // Some network devices that inspect application-layer packets seem to
- // inject TCP reset packets to break the connections when they see
- // TLS 1.1 in ClientHello or ServerHello. See http://crbug.com/130293.
- //
- // Only allow ERR_CONNECTION_RESET to trigger a fallback from TLS 1.1 or
- // 1.2. We don't lose much in this fallback because the explicit IV for CBC
- // mode in TLS 1.1 is approximated by record splitting in TLS 1.0. The
- // fallback will be more painful for TLS 1.2 when we have GCM support.
- //
- // ERR_CONNECTION_RESET is a common network error, so we don't want it
- // to trigger a version fallback in general, especially the TLS 1.0 ->
- // SSL 3.0 fallback, which would drop TLS extensions.
- if (prerr == PR_CONNECT_RESET_ERROR &&
- ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1) {
- net_error = ERR_SSL_PROTOCOL_ERROR;
- }
+ net_error = HandleNSSError(prerr);
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
@@ -1990,7 +1959,7 @@ int SSLClientSocketNSS::Core::DoPayloadRead() {
// If *next_result == 0, then that indicates EOF, and no special error
// handling is needed.
pending_read_nss_error_ = PR_GetError();
- *next_result = HandleNSSError(pending_read_nss_error_, false);
+ *next_result = HandleNSSError(pending_read_nss_error_);
if (rv > 0 && *next_result == ERR_IO_PENDING) {
// If at least some data was read from PR_Read(), do not treat
// insufficient data as an error to return in the next call to
@@ -2052,7 +2021,7 @@ int SSLClientSocketNSS::Core::DoPayloadWrite() {
if (prerr == PR_WOULD_BLOCK_ERROR)
return ERR_IO_PENDING;
- rv = HandleNSSError(prerr, false);
+ rv = HandleNSSError(prerr);
PostOrRunCallback(
FROM_HERE,
base::Bind(&AddLogEventWithCallback, weak_net_log_,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index c770041..d139888 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -7046,7 +7046,8 @@ TEST_F(HTTPSFallbackTest, TLSv1FallbackReset) {
}
#endif // !OS_ANDROID
-// Tests that we don't fallback with servers that implement TLS_FALLBACK_SCSV.
+// Tests that we don't fallback on handshake failure with servers that implement
+// TLS_FALLBACK_SCSV. Also ensure that the original error code is reported.
#if defined(USE_OPENSSL)
TEST_F(HTTPSFallbackTest, DISABLED_FallbackSCSV) {
#else
@@ -7071,6 +7072,31 @@ TEST_F(HTTPSFallbackTest, FallbackSCSV) {
ExpectFailure(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
}
+// Tests that we don't fallback on connection closed with servers that implement
+// TLS_FALLBACK_SCSV. Also ensure that the original error code is reported.
+#if defined(USE_OPENSSL)
+TEST_F(HTTPSFallbackTest, DISABLED_FallbackSCSVClosed) {
+#else
+TEST_F(HTTPSFallbackTest, FallbackSCSVClosed) {
+#endif
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_OK);
+ // Configure HTTPS server to be intolerant of TLS >= 1.0 in order to trigger
+ // a version fallback.
+ ssl_options.tls_intolerant =
+ SpawnedTestServer::SSLOptions::TLS_INTOLERANT_ALL;
+ ssl_options.tls_intolerance_type =
+ SpawnedTestServer::SSLOptions::TLS_INTOLERANCE_CLOSE;
+ // Have the server process TLS_FALLBACK_SCSV so that version fallback
+ // connections are rejected.
+ ssl_options.fallback_scsv_enabled = true;
+
+ ASSERT_NO_FATAL_FAILURE(DoFallbackTest(ssl_options));
+
+ // The original error should be replayed on rejected fallback.
+ ExpectFailure(ERR_CONNECTION_CLOSED);
+}
+
// Tests that the SSLv3 fallback triggers on alert.
TEST_F(HTTPSFallbackTest, SSLv3Fallback) {
SpawnedTestServer::SSLOptions ssl_options(