diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-03-24 16:29:25 +0100 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2011-03-24 17:28:21 +0100 |
commit | c2db6d1066bcb73c5ddf9e38c4ef30545706eae9 (patch) | |
tree | a8941330bc01f58443c0afbd08a15aa295171291 | |
parent | 66dde82fee3c4eb5262d582aeb77935efd40def0 (diff) | |
download | spice-c2db6d1066bcb73c5ddf9e38c4ef30545706eae9.tar.gz spice-c2db6d1066bcb73c5ddf9e38c4ef30545706eae9.tar.xz spice-c2db6d1066bcb73c5ddf9e38c4ef30545706eae9.zip |
spice-server: Add the ability to filter agent messages
-rw-r--r-- | server/Makefile.am | 2 | ||||
-rw-r--r-- | server/agent-msg-filter.c | 85 | ||||
-rw-r--r-- | server/agent-msg-filter.h | 45 | ||||
-rw-r--r-- | server/reds.c | 32 |
4 files changed, 162 insertions, 2 deletions
diff --git a/server/Makefile.am b/server/Makefile.am index 7ab8c3dd..37ff1830 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 00000000..3867d11e --- /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@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 00000000..99dbb8c5 --- /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@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 c1873efb..4663a852 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; |