[Spice-devel] [PATCH spice-server v2 6/7] test-smartcard: Add test for Smartcard device
Victor Toso
victortoso at redhat.com
Wed Oct 9 09:12:45 UTC 2019
On Tue, Oct 08, 2019 at 06:39:23PM +0100, Frediano Ziglio wrote:
> Create Smardcard device.
> Connect to it and test some messages are parsed and processed
> as expected.
>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
Acked-by: Victor Toso <victortoso at redhat.com>
(and keeping ack of 5/7)
> --
> Changes since v1:
> - add more comments
> - limit time the test executes
> ---
> server/tests/.gitignore | 1 +
> server/tests/Makefile.am | 4 +
> server/tests/meson.build | 4 +
> server/tests/test-smartcard.c | 211 ++++++++++++++++++++++++++++++++++
> 4 files changed, 220 insertions(+)
> create mode 100644 server/tests/test-smartcard.c
>
> diff --git a/server/tests/.gitignore b/server/tests/.gitignore
> index 36e978d4f..56cc7eb9a 100644
> --- a/server/tests/.gitignore
> +++ b/server/tests/.gitignore
> @@ -29,5 +29,6 @@ test-leaks
> test-sasl
> test-record
> test-websocket
> +test-smartcard
> /test-*.log
> /test-*.trs
> diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am
> index 982508510..dd285c24e 100644
> --- a/server/tests/Makefile.am
> +++ b/server/tests/Makefile.am
> @@ -68,6 +68,10 @@ check_PROGRAMS = \
> test-record \
> $(NULL)
>
> +if HAVE_SMARTCARD
> +check_PROGRAMS += test-smartcard
> +endif
> +
> if !OS_WIN32
> check_PROGRAMS += \
> test-stream \
> diff --git a/server/tests/meson.build b/server/tests/meson.build
> index 33472f14e..95ade60fa 100644
> --- a/server/tests/meson.build
> +++ b/server/tests/meson.build
> @@ -65,6 +65,10 @@ if spice_server_has_sasl
> tests += [['test-sasl', true]]
> endif
>
> +if spice_server_has_smartcard == true
> + tests += [['test-smartcard', true]]
> +endif
> +
> if host_machine.system() != 'windows'
> tests += [
> ['test-stream', true],
> diff --git a/server/tests/test-smartcard.c b/server/tests/test-smartcard.c
> new file mode 100644
> index 000000000..aac2e7941
> --- /dev/null
> +++ b/server/tests/test-smartcard.c
> @@ -0,0 +1,211 @@
> +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
> +/*
> + Copyright (C) 2019 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/>.
> +*/
> +/**
> + * Test Smartcard device and channel
> + */
> +
> +#include <config.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +#include <stdbool.h>
> +#include <unistd.h>
> +
> +#include <spice/protocol.h>
> +#include <spice/stream-device.h>
> +
> +#include "test-display-base.h"
> +#include "test-glib-compat.h"
> +#include "reds.h"
> +#include "vmc-emu.h"
> +#include "red-client.h"
> +#include "net-utils.h"
> +#include "win-alarm.h"
> +
> +static SpiceCoreInterface *core;
> +static Test *test;
> +static VmcEmu *vmc;
> +typedef int TestFixture;
> +
> +static void test_smartcard_setup(TestFixture *fixture, gconstpointer user_data)
> +{
> + g_assert_null(core);
> + g_assert_null(test);
> + g_assert_null(vmc);
> + core = basic_event_loop_init();
> + g_assert_nonnull(core);
> + test = test_new(core);
> + g_assert_nonnull(test);
> + vmc = vmc_emu_new("smartcard", NULL);
> + g_assert_nonnull(vmc);
> +}
> +
> +static void test_smartcard_teardown(TestFixture *fixture, gconstpointer user_data)
> +{
> + g_assert_nonnull(core);
> + g_assert_nonnull(test);
> + g_assert_nonnull(vmc);
> +
> + vmc_emu_destroy(vmc);
> + vmc = NULL;
> + test_destroy(test);
> + test = NULL;
> + basic_event_loop_destroy();
> + core = NULL;
> +}
> +
> +static RedStream *create_dummy_stream(SpiceServer *server, int *p_socket)
> +{
> + int sv[2];
> + g_assert_cmpint(socketpair(AF_LOCAL, SOCK_STREAM, 0, sv), ==, 0);
> + if (p_socket) {
> + *p_socket = sv[1];
> + }
> + red_socket_set_non_blocking(sv[0], true);
> + red_socket_set_non_blocking(sv[1], true);
> +
> + RedStream * stream = red_stream_new(server, sv[0]);
> + g_assert_nonnull(stream);
> +
> + return stream;
> +}
> +
> +static void send_ack_sync(int socket, uint32_t generation)
> +{
> + struct {
> + uint16_t dummy;
> + uint16_t type;
> + uint32_t len;
> + uint32_t generation;
> + } msg;
> + SPICE_VERIFY(sizeof(msg) == 12);
> + msg.type = GUINT16_TO_LE(SPICE_MSGC_ACK_SYNC);
> + msg.len = GUINT32_TO_LE(sizeof(generation));
> + msg.generation = GUINT32_TO_LE(generation);
> +
> + g_assert_cmpint(socket_write(socket, &msg.type, 10), ==, 10);
> +}
> +
> +static void send_data(int socket, uint32_t type)
> +{
> + struct {
> + uint16_t dummy;
> + uint16_t type;
> + uint32_t len;
> + VSCMsgHeader vheader;
> + char data[6];
> + } msg;
> + SPICE_VERIFY(sizeof(msg) == 8+12+8);
> + msg.type = GUINT16_TO_LE(SPICE_MSGC_SMARTCARD_DATA);
> + msg.len = GUINT32_TO_LE(sizeof(VSCMsgHeader)+6);
> + msg.vheader.type = GUINT32_TO_LE(type);
> + msg.vheader.reader_id = 0;
> + msg.vheader.length = GUINT32_TO_LE(6);
> + strcpy(msg.data, "hello");
> +
> + g_assert_cmpint(socket_write(socket, &msg.type, sizeof(msg)-4), ==, sizeof(msg)-4);
> +}
> +
> +static void check_data(void *opaque)
> +{
> + static const char expected_buf[] =
> + // forwarded ReaderAdd message, note that payload is stripped
> + "\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00"
> + // forwarded APDU message
> + "\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x06\x68\x65\x6c\x6c\x6f\x00";
> + const size_t expected_buf_len = sizeof(expected_buf) - 1;
> + g_assert_cmpint(vmc->write_pos, ==, expected_buf_len);
> + g_assert_true(memcmp(vmc->write_buf, expected_buf, expected_buf_len) == 0);
> + basic_event_loop_quit();
> +}
> +
> +static void test_smartcard(TestFixture *fixture, gconstpointer user_data)
> +{
> + SpiceServer *const server = test->server;
> + uint8_t *p = vmc->message;
> +
> + spice_server_add_interface(server, &vmc->instance.base);
> +
> + // add VSC_Init message
> + memcpy(p, "\x00\x00\x00\x01\x0a\x0b\x0c\x0d\x00\x00\x00\x00", 12);
> + p += 12;
> + vmc_emu_add_read_till(vmc, p);
> +
> + // find Smartcard channel to connect to
> + RedChannel *channel = reds_find_channel(server, SPICE_CHANNEL_SMARTCARD, 0);
> + g_assert_nonnull(channel);
> +
> + // create dummy RedClient and MainChannelClient
> + RedChannelCapabilities caps;
> + memset(&caps, 0, sizeof(caps));
> + uint32_t common_caps = 1 << SPICE_COMMON_CAP_MINI_HEADER;
> + caps.num_common_caps = 1;
> + caps.common_caps = spice_memdup(&common_caps, sizeof(common_caps));
> +
> + RedClient *client = red_client_new(server, FALSE);
> + g_assert_nonnull(client);
> +
> + MainChannel *main_channel = main_channel_new(server);
> + g_assert_nonnull(main_channel);
> +
> + MainChannelClient *mcc;
> + mcc = main_channel_link(main_channel, client, create_dummy_stream(server, NULL),
> + 0, FALSE, &caps);
> + g_assert_nonnull(mcc);
> + red_client_set_main(client, mcc);
> +
> + // create our testing RedChannelClient
> + int client_socket;
> + red_channel_connect(channel, client, create_dummy_stream(server, &client_socket),
> + FALSE, &caps);
> + red_channel_capabilities_reset(&caps);
> +
> + // push data to device
> + spice_server_char_device_wakeup(&vmc->instance);
> +
> + // push data into channel
> + send_ack_sync(client_socket, 1);
> + send_data(client_socket, VSC_ReaderAdd);
> + send_data(client_socket, VSC_APDU);
> +
> + // check data are processed after a short time
> + SpiceTimer *watch_timer;
> + watch_timer = core->timer_add(check_data, core);
> + core->timer_start(watch_timer, 100);
> +
> + // start all test
> + alarm(10);
> + basic_event_loop_mainloop();
> + alarm(0);
> +
> + // cleanup
> + core->timer_remove(watch_timer);
> + red_client_destroy(client);
> + g_object_unref(main_channel);
> + g_object_unref(channel);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> + g_test_init(&argc, &argv, NULL);
> +
> + g_test_add("/server/smartcard", TestFixture, NULL, test_smartcard_setup,
> + test_smartcard, test_smartcard_teardown);
> +
> + return g_test_run();
> +}
> --
> 2.21.0
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20191009/06d98699/attachment-0001.sig>
More information about the Spice-devel
mailing list