[libsoup/websockets-fixes-2.64: 8/19] WebSockets: client must fail when receiving a masked frame from server




commit 99f327f51ebeec4e2bdcc42670239027ef717b51
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]