[Spice-devel] [PATCH spice 1/3] spice-server: Add the ability to filter agent messages

Hans de Goede hdegoede at redhat.com
Thu Mar 24 09:39:46 PDT 2011


---
 server/Makefile.am        |    2 +
 server/agent-msg-filter.c |   85 +++++++++++++++++++++++++++++++++++++++++++++
 server/agent-msg-filter.h |   45 ++++++++++++++++++++++++
 server/reds.c             |   32 ++++++++++++++++-
 4 files changed, 162 insertions(+), 2 deletions(-)
 create mode 100644 server/agent-msg-filter.c
 create mode 100644 server/agent-msg-filter.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 7ab8c3d..37ff183 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -95,6 +95,8 @@ SMARTCARD_SRCS =
 endif
 
 libspice_server_la_SOURCES =			\
+	agent-msg-filter.c			\
+	agent-msg-filter.h			\
 	demarshallers.h				\
 	glz_encoder.c				\
 	glz_encoder_config.h			\
diff --git a/server/agent-msg-filter.c b/server/agent-msg-filter.c
new file mode 100644
index 0000000..3867d11
--- /dev/null
+++ b/server/agent-msg-filter.c
@@ -0,0 +1,85 @@
+/*
+   Copyright (C) 2011 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+   Red Hat Authors:
+        hdegoede at redhat.com
+*/
+
+#include <string.h>
+#include "red_common.h"
+#include "agent-msg-filter.h"
+
+void agent_msg_filter_init(struct AgentMsgFilter *filter, int copy_paste)
+{
+    memset(filter, 0, sizeof(*filter));
+    filter->copy_paste_enabled = copy_paste;
+}
+
+int agent_msg_filter_process_data(struct AgentMsgFilter *filter,
+                                  uint8_t *data, uint32_t len)
+{
+    struct VDAgentMessage msg_header;
+
+    if (len > VD_AGENT_MAX_DATA_SIZE) {
+        red_printf("invalid agent message: too large");
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+
+    /* Are we expecting more data from a previous message? */
+    if (filter->msg_data_to_read) {
+data_to_read:
+        if (len > filter->msg_data_to_read) {
+            red_printf("invalid agent message: data exceeds size from header");
+            return AGENT_MSG_FILTER_PROTO_ERROR;
+        }
+        filter->msg_data_to_read -= len;
+        return filter->result;
+    }
+
+    if (len < sizeof(msg_header)) {
+        red_printf("invalid agent message: incomplete header");
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+    memcpy(&msg_header, data, sizeof(msg_header));
+    len -= sizeof(msg_header);
+
+    if (msg_header.protocol != VD_AGENT_PROTOCOL) {
+        red_printf("invalid agent protocol: %u", msg_header.protocol);
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+
+    switch (msg_header.type) {
+    case VD_AGENT_CLIPBOARD:
+    case VD_AGENT_CLIPBOARD_GRAB:
+    case VD_AGENT_CLIPBOARD_REQUEST:
+    case VD_AGENT_CLIPBOARD_RELEASE:
+        if (filter->copy_paste_enabled) {
+            filter->result = AGENT_MSG_FILTER_OK;
+        } else {
+            filter->result = AGENT_MSG_FILTER_DISCARD;
+        }
+        break;
+    default:
+        filter->result = AGENT_MSG_FILTER_OK;
+    }
+
+    filter->msg_data_to_read = msg_header.size;
+    if (filter->msg_data_to_read) {
+        goto data_to_read;
+    }
+
+    return filter->result;
+}
diff --git a/server/agent-msg-filter.h b/server/agent-msg-filter.h
new file mode 100644
index 0000000..99dbb8c
--- /dev/null
+++ b/server/agent-msg-filter.h
@@ -0,0 +1,45 @@
+/*
+   Copyright (C) 2011 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+
+   Red Hat Authors:
+        hdegoede at redhat.com
+*/
+
+#ifndef _H_AGENT_MSG_FILTER
+#define _H_AGENT_MSG_FILTER
+
+#include <spice/vd_agent.h>
+
+/* Possible return values for agent_msg_filter_process_data */
+enum {
+    AGENT_MSG_FILTER_OK,
+    AGENT_MSG_FILTER_DISCARD,
+    AGENT_MSG_FILTER_PROTO_ERROR,
+    AGENT_MSG_FILTER_END
+};
+
+typedef struct AgentMsgFilter {
+    struct VDAgentMessage msg_header;
+    int msg_data_to_read;
+    int result;
+    int copy_paste_enabled;
+} AgentMsgFilter;
+
+void agent_msg_filter_init(struct AgentMsgFilter *filter, int copy_paste);
+int agent_msg_filter_process_data(struct AgentMsgFilter *filter,
+                                  uint8_t *data, uint32_t len);
+
+#endif
diff --git a/server/reds.c b/server/reds.c
index c1873ef..4663a85 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -49,6 +49,7 @@
 #include "reds.h"
 #include <spice/protocol.h>
 #include <spice/vd_agent.h>
+#include "agent-msg-filter.h"
 
 #include "inputs_channel.h"
 #include "main_channel.h"
@@ -158,6 +159,7 @@ typedef struct VDIPortState {
     Ring external_bufs;
     Ring internal_bufs;
     Ring write_queue;
+    AgentMsgFilter write_filter;
 
     Ring read_bufs;
     uint32_t read_state;
@@ -165,6 +167,7 @@ typedef struct VDIPortState {
     uint8_t *recive_pos;
     uint32_t recive_len;
     VDIReadBuf *current_read_buf;
+    AgentMsgFilter read_filter;
 
     VDIChunkHeader vdi_chunk_header;
 
@@ -806,9 +809,24 @@ void vdi_read_buf_release(uint8_t *data, void *opaque)
 static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
 {
     VDIPortState *state = &reds->agent_state;
+    int res;
 
     switch (port) {
     case VDP_CLIENT_PORT: {
+        res = agent_msg_filter_process_data(&state->read_filter,
+                                            buf->data, buf->len);
+        switch (res) {
+        case AGENT_MSG_FILTER_OK:
+            break;
+        case AGENT_MSG_FILTER_DISCARD:
+            ring_add(&state->read_bufs, &buf->link);
+            return;
+        case AGENT_MSG_FILTER_PROTO_ERROR:
+            ring_add(&state->read_bufs, &buf->link);
+            reds_agent_remove();
+            return;
+        }
+
         if (reds->agent_state.connected) {
             main_channel_push_agent_data(reds->main_channel, buf->data, buf->len,
                                          vdi_read_buf_release, buf);
@@ -994,6 +1012,7 @@ void reds_on_main_agent_data(void *message, size_t size)
 {
     RingItem *ring_item;
     VDAgentExtBuf *buf;
+    int res;
 
     if (!reds->agent_state.num_client_tokens) {
         red_printf("token violation");
@@ -1013,8 +1032,15 @@ void reds_on_main_agent_data(void *message, size_t size)
         return;
     }
 
-    if (size > SPICE_AGENT_MAX_DATA_SIZE) {
-        red_printf("invalid agent message");
+    res = agent_msg_filter_process_data(&reds->agent_state.write_filter,
+                                        message, size);
+    switch (res) {
+    case AGENT_MSG_FILTER_OK:
+        break;
+    case AGENT_MSG_FILTER_DISCARD:
+        add_token();
+        return;
+    case AGENT_MSG_FILTER_PROTO_ERROR:
         reds_disconnect();
         return;
     }
@@ -3384,6 +3410,8 @@ static void init_vd_agent_resources()
     ring_init(&state->internal_bufs);
     ring_init(&state->write_queue);
     ring_init(&state->read_bufs);
+    agent_msg_filter_init(&state->write_filter, TRUE);
+    agent_msg_filter_init(&state->read_filter, TRUE);
 
     state->read_state = VDI_PORT_READ_STATE_READ_HADER;
     state->recive_pos = (uint8_t *)&state->vdi_chunk_header;
-- 
1.7.3.2



More information about the Spice-devel mailing list