summaryrefslogtreecommitdiffstats
path: root/net/websockets
diff options
context:
space:
mode:
authorricea <ricea@chromium.org>2015-02-02 05:35:13 -0800
committerCommit bot <commit-bot@chromium.org>2015-02-02 13:37:21 +0000
commit23c3f94ffbf774f240fbc52c08760b0e3d90964b (patch)
tree8a11af221d635d6a6402bb63770f8210d2508c14 /net/websockets
parentac1aaf963cfedf830afce10e2bfe1a9504bd49d3 (diff)
downloadchromium_src-23c3f94ffbf774f240fbc52c08760b0e3d90964b.zip
chromium_src-23c3f94ffbf774f240fbc52c08760b0e3d90964b.tar.gz
chromium_src-23c3f94ffbf774f240fbc52c08760b0e3d90964b.tar.bz2
Avoid WebSocket upgrade on network error.
In the event of network error, the WebSocket server response is not validated. However, some network errors are ignored higher up in the stack. For example, in HttpNetworkTransaction::DoReadHeadersComplete at http_network_transaction.cc:988, ERR_CONNECTION_CLOSED is converted to OK. To avoid this whole class of bugs, do not keep status code 101 (Switching Protocols) if there was a network error. It is changed to 503. The response headers that are displayed in devtools are copied before the change, so they will still retain the original status code. BUG=408061 TEST=net_unittests Review URL: https://codereview.chromium.org/889783002 Cr-Commit-Position: refs/heads/master@{#314136}
Diffstat (limited to 'net/websockets')
-rw-r--r--net/websockets/websocket_basic_handshake_stream.cc12
-rw-r--r--net/websockets/websocket_end_to_end_test.cc13
-rw-r--r--net/websockets/websocket_stream_test.cc24
3 files changed, 49 insertions, 0 deletions
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index c0f20c7..7d99311 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -50,6 +50,8 @@ namespace net {
namespace {
+const char kConnectionErrorStatusLine[] = "HTTP/1.1 503 Connection Error";
+
// TODO(yhirano): Remove these functions once http://crbug.com/399535 is fixed.
NOINLINE void RunCallbackWithOk(const CompletionCallback& callback,
int result) {
@@ -654,6 +656,16 @@ int WebSocketBasicHandshakeStream::ValidateResponse(int rv,
set_failure_message(std::string("Error during WebSocket handshake: ") +
ErrorToString(rv));
OnFinishOpeningHandshake();
+ // Some error codes (for example ERR_CONNECTION_CLOSED) get changed to OK at
+ // higher levels. To prevent an unvalidated connection getting erroneously
+ // upgraded, don't pass through the status code unchanged if it is
+ // HTTP_SWITCHING_PROTOCOLS.
+ if (http_response_info_->headers &&
+ http_response_info_->headers->response_code() ==
+ HTTP_SWITCHING_PROTOCOLS) {
+ http_response_info_->headers->ReplaceStatusLine(
+ kConnectionErrorStatusLine);
+ }
return rv;
}
}
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 0b5944f..4aa2f1c 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -365,6 +365,19 @@ TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(HttpsProxyUsed)) {
EXPECT_TRUE(info.proxy_info.is_http());
}
+// This is a regression test for crbug.com/408061 Crash in
+// net::WebSocketBasicHandshakeStream::Upgrade.
+TEST_F(WebSocketEndToEndTest, DISABLED_ON_ANDROID(TruncatedResponse)) {
+ SpawnedTestServer ws_server(SpawnedTestServer::TYPE_WS,
+ SpawnedTestServer::kLocalhost,
+ GetWebSocketTestDataDirectory());
+ ASSERT_TRUE(ws_server.Start());
+ InitialiseContext();
+
+ GURL ws_url = ws_server.GetURL("truncated-headers");
+ EXPECT_FALSE(ConnectAndWait(ws_url));
+}
+
} // namespace
} // namespace net
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index 0fdc34b..713af37 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -1388,5 +1388,29 @@ TEST_F(WebSocketStreamCreateUMATest, Failed) {
EXPECT_EQ(0, samples->GetCount(FAILED));
}
+TEST_F(WebSocketStreamCreateTest, HandleErrConnectionClosed) {
+ static const char kTruncatedResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "Cache-Control: no-sto";
+
+ std::string request =
+ WebSocketStandardRequest("/", "localhost", "http://localhost", "");
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, 1, kTruncatedResponse),
+ MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED, 2),
+ };
+ MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, request.c_str())};
+ scoped_ptr<DeterministicSocketData> socket_data(
+ BuildSocketData(reads, writes));
+ socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
+ "http://localhost", socket_data.Pass());
+ RunUntilIdle();
+ EXPECT_TRUE(has_failed());
+}
+
} // namespace
} // namespace net