Bug 711886. Fail Websocket if server replies with non-matching subprotocol r=mcmanus

This commit is contained in:
Jason Duell 2016-05-11 08:50:13 -07:00
parent aa7218be51
commit d3772280b8
5 changed files with 40 additions and 6 deletions

View File

@ -28,6 +28,9 @@ def web_socket_do_extra_handshake(request):
time.sleep(13)
elif request.ws_protocol == "test-41b":
request.sts = "max-age=100"
elif request.ws_protocol == "test-49":
# subprotocols are compared case-sensitively, so this should fail
request.ws_protocol = "teST-49"
else:
pass

View File

@ -21,6 +21,7 @@ var tests = [
test47, // Make sure onerror/onclose aren't called during close()
test48, // see bug 1227136 - client calls close() from onopen() and waits
// until WebSocketChannel::mSocketIn is nulled out on socket thread
test49, // Test that we fail if subprotocol returned from server doesn't match
];
function testWebSocket() {

View File

@ -1242,3 +1242,29 @@ function test48() {
SpecialPowers.clearUserPref(pref_close);
});
}
function test49()
{
return new Promise(function(resolve, reject) {
var ws = CreateTestWS("ws://mochi.test:8888/tests/dom/base/test/file_websocket", "test-49");
var gotError = 0;
ok(ws.readyState == 0, "create bad readyState in test-49!");
ws.onopen = function()
{
ok(false, "Connection must fail in test-49")
}
ws.onerror = function(e)
{
gotError = 1
}
ws.onclose = function(e)
{
ok(gotError, "Should get error in test-49!");
resolve();
}
});
}

View File

@ -8,6 +8,7 @@ var tests = [
test44, // Test sending/receving binary ArrayBuffer
test46, // Test that we don't dispatch incoming msgs once in CLOSING state
test47, // Make sure onerror/onclose aren't called during close()
test49, // Test that we fail if subprotocol returned from server doesn't match
];
doTest();

View File

@ -3645,9 +3645,10 @@ WebSocketChannel::OnStartRequest(nsIRequest *aRequest,
return NS_ERROR_ILLEGAL_VALUE;
}
// If we sent a sub protocol header, verify the response matches
// If it does not, set mProtocol to "" so the protocol attribute
// of the WebSocket JS object reflects that
// If we sent a sub protocol header, verify the response matches.
// If response contains protocol that was not in request, fail.
// If response contained no protocol header, set to "" so the protocol
// attribute of the WebSocket JS object reflects that
if (!mProtocol.IsEmpty()) {
nsAutoCString respProtocol;
rv = mHttpChannel->GetResponseHeader(
@ -3657,7 +3658,7 @@ WebSocketChannel::OnStartRequest(nsIRequest *aRequest,
rv = NS_ERROR_ILLEGAL_VALUE;
val = mProtocol.BeginWriting();
while ((token = nsCRT::strtok(val, ", \t", &val))) {
if (PL_strcasecmp(token, respProtocol.get()) == 0) {
if (PL_strcmp(token, respProtocol.get()) == 0) {
rv = NS_OK;
break;
}
@ -3669,9 +3670,11 @@ WebSocketChannel::OnStartRequest(nsIRequest *aRequest,
mProtocol = respProtocol;
} else {
LOG(("WebsocketChannel::OnStartRequest: "
"subprotocol [%s] not found - %s returned",
mProtocol.get(), respProtocol.get()));
"Server replied with non-matching subprotocol [%s]: aborting",
respProtocol.get()));
mProtocol.Truncate();
AbortSession(NS_ERROR_ILLEGAL_VALUE);
return NS_ERROR_ILLEGAL_VALUE;
}
} else {
LOG(("WebsocketChannel::OnStartRequest "