[Spice-devel] [PATCH spice 1/3] spice-server: Add the ability to filter agent messages
Alon Levy
alevy at redhat.com
Fri Mar 25 06:52:40 PDT 2011
On Thu, Mar 24, 2011 at 05:39:46PM +0100, Hans de Goede wrote:
> ---
> 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));
You are explicitly relying on AGENT_MSG_FILTER_OK == 0, would be nice
to set filter->Result = AGENT_MSG_FILTER_OK explicitly.
> + 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)) {
Is it impossible to get a partial write that is smaller then the size
of the header? This also applies for a read with multiple messages
ending with a partial 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
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list