Due to ticket expiration, it is possible that the streaming channels for the client are created after the ticket expires. Currently, streaming channels are created dynamically when the guest starts streaming to the server, which can happen at any time (for instance if you decide to start the graphic server manually). If the ticket has expired before the streaming channel is created, authentication will fail and the client will not be able to connect. To avoid this, create the channels when the first main channel connection is made. This ensures that client will connect to all streaming channels. This could be considered a temporary solution. There may be other situations where it would be useful to connect new channels after the ticket has expired, but enabling this behavior would require protocol changes and a careful analysis of security implications. Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/char-device.h | 1 + server/reds-private.h | 1 + server/reds.c | 21 +++++++++++++++++++++ server/stream-device.c | 11 +++++++++++ 4 files changed, 34 insertions(+) Changes since v2: - improve commit message; - add comment in code. Changes since v1: - improve commit message. diff --git a/server/char-device.h b/server/char-device.h index 54a1ef93..a9634383 100644 --- a/server/char-device.h +++ b/server/char-device.h @@ -237,6 +237,7 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds, void spicevmc_device_disconnect(RedsState *reds, SpiceCharDeviceInstance *char_device); RedCharDevice *stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin); +void stream_device_create_channel(RedCharDevice *dev); SpiceCharDeviceInterface *spice_char_device_get_interface(SpiceCharDeviceInstance *instance); diff --git a/server/reds-private.h b/server/reds-private.h index adc48ba5..920edc5c 100644 --- a/server/reds-private.h +++ b/server/reds-private.h @@ -117,6 +117,7 @@ struct RedsState { RedStatFile *stat_file; #endif int allow_multiple_clients; + bool late_initialization_done; /* Intermediate state for on going monitors config message from a single * client, being passed to the guest */ diff --git a/server/reds.c b/server/reds.c index a31ed4e9..4705557c 100644 --- a/server/reds.c +++ b/server/reds.c @@ -1733,6 +1733,25 @@ static RedClient *reds_get_client(RedsState *reds) return reds->clients->data; } +/* Performs late initializations steps. + * This should be called when a client connects */ +static void reds_late_initialization(RedsState *reds) +{ + RedCharDevice *dev; + + // do only once + if (reds->late_initialization_done) { + return; + } + + // create stream channels for streaming devices, stream_device_create_channel ignores devices + // which are not streaming devices + GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) { + stream_device_create_channel(dev); + } + reds->late_initialization_done = true; +} + static void red_channel_capabilities_init_from_link_message(RedChannelCapabilities *caps, const SpiceLinkMess *link_mess) @@ -1768,6 +1787,8 @@ static void reds_handle_main_link(RedsState *reds, RedLinkInfo *link) spice_debug("trace"); spice_assert(reds->main_channel); + reds_late_initialization(reds); + link_mess = link->link_mess; if (!reds->allow_multiple_clients) { reds_disconnect(reds); diff --git a/server/stream-device.c b/server/stream-device.c index bb7c9eff..8c64a15e 100644 --- a/server/stream-device.c +++ b/server/stream-device.c @@ -32,6 +32,8 @@ (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_STREAM_DEVICE, StreamDevice)) #define STREAM_DEVICE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_STREAM_DEVICE, StreamDeviceClass)) +#define IS_STREAM_DEVICE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_STREAM_DEVICE)) #define STREAM_DEVICE_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_DEVICE, StreamDeviceClass)) @@ -70,6 +72,7 @@ static StreamDevice *stream_device_new(SpiceCharDeviceInstance *sin, RedsState * G_DEFINE_TYPE(StreamDevice, stream_device, RED_TYPE_CHAR_DEVICE) static void char_device_set_state(RedCharDevice *char_dev, int state); +static void allocate_channels(StreamDevice *dev); typedef bool StreamMsgHandler(StreamDevice *dev, SpiceCharDeviceInstance *sin) SPICE_GNUC_WARN_UNUSED_RESULT; @@ -520,6 +523,14 @@ stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *sin) return RED_CHAR_DEVICE(dev); } +void +stream_device_create_channel(RedCharDevice *char_dev) +{ + if (IS_STREAM_DEVICE(char_dev)) { + allocate_channels(STREAM_DEVICE(char_dev)); + } +} + static void stream_device_dispose(GObject *object) { -- 2.14.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel