[libsoup/websockets-fixes-2.66: 8/19] WebSockets: client must fail when receiving a masked frame from server
- From: Claudio Saavedra <csaavedra src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup/websockets-fixes-2.66: 8/19] WebSockets: client must fail when receiving a masked frame from server
- Date: Fri, 11 Dec 2020 14:41:14 +0000 (UTC)
commit 912b4e4271f362c45509c2e880ed50552d89895e
Author: Carlos Garcia Campos <cgarcia igalia com>
Date: Mon Jun 24 15:00:14 2019 +0200
WebSockets: client must fail when receiving a masked frame from server
RFC 6455:
A server MUST NOT mask any frames that it sends to the client. A client
MUST close a connection if it detects a masked frame.
libsoup/soup-websocket-connection.c | 9 +++++++
tests/websocket-test.c | 47 +++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+)
---
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c
index 963d539d..a41f05cd 100644
--- a/libsoup/soup-websocket-connection.c
+++ b/libsoup/soup-websocket-connection.c
@@ -912,6 +912,15 @@ process_frame (SoupWebsocketConnection *self)
opcode = header[0] & 0x0f;
masked = ((header[1] & 0x80) != 0);
+ if (self->pv->connection_type == SOUP_WEBSOCKET_CONNECTION_CLIENT && masked) {
+ /* A server MUST NOT mask any frames that it sends to the client.
+ * A client MUST close a connection if it detects a masked frame.
+ */
+ g_debug ("A server must not mask any frames that it sends to the client.");
+ protocol_error_and_close (self);
+ return FALSE;
+ }
+
/* We do not support extensions, reserved bits must be 0 */
if (header[0] & 0x70) {
protocol_error_and_close (self);
diff --git a/tests/websocket-test.c b/tests/websocket-test.c
index 1f2781af..59cbba39 100644
--- a/tests/websocket-test.c
+++ b/tests/websocket-test.c
@@ -985,6 +985,48 @@ test_receive_invalid_encode_length_64 (Test *test,
WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
}
+static gpointer
+send_masked_frame_server_thread (gpointer user_data)
+{
+ Test *test = user_data;
+ const char frame[] = "\x82\x8e\x9a";
+ gsize written;
+ GError *error = NULL;
+
+ g_output_stream_write_all (g_io_stream_get_output_stream (test->raw_server),
+ frame, sizeof (frame), &written, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpuint (written, ==, sizeof (frame));
+
+ g_io_stream_close (test->raw_server, NULL, &error);
+ g_assert_no_error (error);
+
+ return NULL;
+}
+
+static void
+test_client_receive_masked_frame (Test *test,
+ gconstpointer data)
+{
+ GThread *thread;
+ GBytes *received = NULL;
+ GError *error = NULL;
+
+ g_signal_connect (test->client, "error", G_CALLBACK (on_error_copy), &error);
+ g_signal_connect (test->client, "message", G_CALLBACK (on_binary_message), &received);
+
+ thread = g_thread_new ("send-masked-frame-thread", send_masked_frame_server_thread, test);
+
+ WAIT_UNTIL (error != NULL || received != NULL);
+ g_assert_error (error, SOUP_WEBSOCKET_ERROR, SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR);
+ g_clear_error (&error);
+ g_assert_null (received);
+
+ g_thread_join (thread);
+
+ WAIT_UNTIL (soup_websocket_connection_get_state (test->client) == SOUP_WEBSOCKET_STATE_CLOSED);
+}
+
static void
test_client_context_got_server_connection (SoupServer *server,
SoupWebsocketConnection *connection,
@@ -1167,6 +1209,11 @@ main (int argc,
test_receive_invalid_encode_length_64,
teardown_direct_connection);
+ g_test_add ("/websocket/direct/client-receive-masked-frame", Test, NULL,
+ setup_half_direct_connection,
+ test_client_receive_masked_frame,
+ teardown_direct_connection);
+
if (g_test_slow ()) {
g_test_add ("/websocket/direct/close-after-timeout", Test, NULL,
setup_half_direct_connection,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]