[WebSocket]Browser must fail connection if Sec-WebSocket-Protocol mismatched.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2012 04:22:12 +0000 (04:22 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 29 Mar 2012 04:22:12 +0000 (04:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=82307

Patch by Li Yin <li.yin@intel.com> on 2012-03-28
Reviewed by Kent Tamura.

Source/WebCore:

From RFC6455: http://tools.ietf.org/html/rfc6455#section-4.1
If the WebSocket openhanding respond included the mismatched
Sec-WebSocket-Protocol header field, the client must fail the WebSocket Connection.

Test: http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html

* Modules/websockets/WebSocketHandshake.cpp:
(WebCore::WebSocketHandshake::checkResponseHeaders):

LayoutTests:

From RFC6455: http://tools.ietf.org/html/rfc6455#section-4.1
If the response includes a |Sec-WebSocket-Protocol| header field
and this header field indicates the use of a subprotocol that was
not present in the client's handshake (the server has indicated a
subprotocol not requested by the client), the client MUST _Fail
the WebSocket Connection_.

* http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header-expected.txt: Added.
* http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html: Added.
* http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header_wsh.py: Added.
(web_socket_do_extra_handshake):
(web_socket_transfer_data):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@112499 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html [new file with mode: 0644]
LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header_wsh.py [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/websockets/WebSocket.cpp
Source/WebCore/Modules/websockets/WebSocket.h
Source/WebCore/Modules/websockets/WebSocketHandshake.cpp

index 34b4bc3..1380cc6 100644 (file)
@@ -1,3 +1,23 @@
+2012-03-28  Li Yin  <li.yin@intel.com>
+
+        [WebSocket]Browser must fail connection if Sec-WebSocket-Protocol mismatched.
+        https://bugs.webkit.org/show_bug.cgi?id=82307
+
+        Reviewed by Kent Tamura.
+
+        From RFC6455: http://tools.ietf.org/html/rfc6455#section-4.1
+        If the response includes a |Sec-WebSocket-Protocol| header field
+        and this header field indicates the use of a subprotocol that was
+        not present in the client's handshake (the server has indicated a
+        subprotocol not requested by the client), the client MUST _Fail
+        the WebSocket Connection_.
+
+        * http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header-expected.txt: Added.
+        * http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html: Added.
+        * http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header_wsh.py: Added.
+        (web_socket_do_extra_handshake):
+        (web_socket_transfer_data):
+
 2012-03-28  David Grogan  <dgrogan@chromium.org>
 
         IndexedDB: don't expose IDBDatabaseError to script
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header-expected.txt b/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header-expected.txt
new file mode 100644 (file)
index 0000000..f337134
--- /dev/null
@@ -0,0 +1,14 @@
+CONSOLE MESSAGE: Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
+CONSOLE MESSAGE: Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
+CONSOLE MESSAGE: Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch
+Test whether WebSocket handshake fails if the server sends mismatched Sec-WebSocket-Protocol header.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS closeEvent.wasClean is false
+PASS closeEvent.wasClean is false
+PASS closeEvent.wasClean is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html b/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html
new file mode 100644 (file)
index 0000000..d65969a
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src="../../../../js-test-resources/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+description("Test whether WebSocket handshake fails if the server sends mismatched Sec-WebSocket-Protocol header.");
+
+window.jsTestIsAsync = true;
+if (window.layoutTestController)
+    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
+
+var url = "ws://localhost:8880/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header";
+var closeEvent;
+var ws;
+var protocolCase = ["", "MatchProtocol", ["MatchProtocol1", "MatchProtocol2"]];
+
+function doTest(index)
+{
+    if (protocolCase[index] === "")
+        ws = new WebSocket(url);
+    else
+        ws = new WebSocket(url, protocolCase[index]);
+
+    ws.onopen = function()
+    {
+        testFailed("Connection established.");
+        ws.close();
+    };
+
+    ws.onclose = function(event)
+    {
+        closeEvent = event;
+        shouldBeFalse("closeEvent.wasClean");
+        if (index === protocolCase.length - 1) {
+            finishJSTest();
+            return;
+        }
+        doTest(index + 1);        
+    };
+}
+
+doTest(0);
+
+</script>
+<script src="../../../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header_wsh.py b/LayoutTests/http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header_wsh.py
new file mode 100644 (file)
index 0000000..d35c57b
--- /dev/null
@@ -0,0 +1,17 @@
+from mod_pywebsocket import handshake
+from mod_pywebsocket.handshake.hybi import compute_accept
+
+
+def web_socket_do_extra_handshake(request):
+    msg = 'HTTP/1.1 101 Switching Protocols\r\n'
+    msg += 'Upgrade: websocket\r\n'
+    msg += 'Connection: Upgrade\r\n'
+    msg += 'Sec-WebSocket-Accept: %s\r\n' % compute_accept(request.headers_in['Sec-WebSocket-Key'])[0]
+    msg += 'Sec-WebSocket-Protocol: MismatchProtocol\r\n' 
+    msg += '\r\n'
+    request.connection.write(msg)
+    raise handshake.AbortedByUserException('Abort the connection') # Prevents pywebsocket from sending its own handshake message.
+
+
+def web_socket_transfer_data(request):
+    pass
index 5b2eaab..1475a4a 100644 (file)
@@ -1,3 +1,19 @@
+2012-03-28  Li Yin  <li.yin@intel.com>
+
+        [WebSocket]Browser must fail connection if Sec-WebSocket-Protocol mismatched.
+        https://bugs.webkit.org/show_bug.cgi?id=82307
+
+        Reviewed by Kent Tamura.
+
+        From RFC6455: http://tools.ietf.org/html/rfc6455#section-4.1
+        If the WebSocket openhanding respond included the mismatched
+        Sec-WebSocket-Protocol header field, the client must fail the WebSocket Connection.
+
+        Test: http/tests/websocket/tests/hybi/handshake-fail-by-mismatch-protocol-header.html
+
+        * Modules/websockets/WebSocketHandshake.cpp:
+        (WebCore::WebSocketHandshake::checkResponseHeaders):
+
 2012-03-28  Jessie Berlin  <jberlin@apple.com>
 
         Fix Windows build after r112482.
index 78183f1..3f383e7 100644 (file)
@@ -147,6 +147,11 @@ bool WebSocket::isAvailable()
     return webSocketsAvailable;
 }
 
+const char* WebSocket::subProtocolSeperator()
+{
+    return ", ";
+}
+
 WebSocket::WebSocket(ScriptExecutionContext* context)
     : ActiveDOMObject(context, this)
     , m_state(CONNECTING)
@@ -267,7 +272,7 @@ void WebSocket::connect(const String& url, const Vector<String>& protocols, Exce
         }
 
         if (!protocols.isEmpty())
-            protocolString = joinStrings(protocols, ", ");
+            protocolString = joinStrings(protocols, subProtocolSeperator());
     }
 
     m_channel->connect(m_url, protocolString);
index 1e44245..f25c55c 100644 (file)
@@ -53,6 +53,7 @@ class WebSocket : public RefCounted<WebSocket>, public EventTarget, public Activ
 public:
     static void setIsAvailable(bool);
     static bool isAvailable();
+    static const char* subProtocolSeperator();
     static PassRefPtr<WebSocket> create(ScriptExecutionContext*);
     virtual ~WebSocket();
 
index 17c59e1..4f32d6c 100644 (file)
@@ -34,6 +34,7 @@
 #if ENABLE(WEB_SOCKETS)
 
 #include "WebSocketHandshake.h"
+#include "WebSocket.h"
 
 #include "Base64.h"
 #include "Cookie.h"
@@ -727,6 +728,18 @@ bool WebSocketHandshake::checkResponseHeaders()
             m_failureReason = "Error during WebSocket handshake: Sec-WebSocket-Accept mismatch";
             return false;
         }
+        if (!serverWebSocketProtocol.isNull()) {
+            if (m_clientProtocol.isEmpty()) {
+                m_failureReason = "Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch";
+                return false;
+            }
+            Vector<String> result;
+            m_clientProtocol.split(String(WebSocket::subProtocolSeperator()), result);
+            if (!result.contains(serverWebSocketProtocol)) {
+                m_failureReason = "Error during WebSocket handshake: Sec-WebSocket-Protocol mismatch";
+                return false;
+            }
+        }
     }
     return true;
 }