From 6101cb805ac1fc524f74a311e6cafafc0abc1982 Mon Sep 17 00:00:00 2001 From: Marc-AndrĂ© Lureau Date: Tue, 22 Feb 2011 13:54:09 +0100 Subject: server: add auth mechanism selection https://bugs.freedesktop.org/show_bug.cgi?id=34795 --- server/reds.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 4 deletions(-) (limited to 'server/reds.c') diff --git a/server/reds.c b/server/reds.c index 999adfe6..1cc2e157 100644 --- a/server/reds.c +++ b/server/reds.c @@ -319,6 +319,7 @@ typedef struct RedLinkInfo { SpiceLinkMess *link_mess; int mess_pos; TicketInfo tiTicketing; + SpiceLinkAuthMechanism auth_mechanism; } RedLinkInfo; typedef struct VDIPortBuf VDIPortBuf; @@ -1881,6 +1882,28 @@ static int sync_write(RedsStream *stream, const void *in_buf, size_t n) return TRUE; } +static void reds_channel_set_common_caps(Channel *channel, int cap, int active) +{ + int nbefore, n; + + nbefore = channel->num_common_caps; + n = cap / 32; + channel->num_common_caps = MAX(channel->num_common_caps, n + 1); + channel->common_caps = spice_renew(uint32_t, channel->common_caps, channel->num_common_caps); + memset(channel->common_caps + nbefore, 0, + (channel->num_common_caps - nbefore) * sizeof(uint32_t)); + if (active) + channel->common_caps[n] |= (1 << cap); + else + channel->common_caps[n] &= ~(1 << cap); +} + +void reds_channel_init_auth_caps(Channel *channel) +{ + reds_channel_set_common_caps(channel, SPICE_COMMON_CAP_AUTH_SPICE, TRUE); + reds_channel_set_common_caps(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION, TRUE); +} + void reds_channel_dispose(Channel *channel) { free(channel->caps); @@ -1914,6 +1937,8 @@ static int reds_send_link_ack(RedLinkInfo *link) channel = ∩︀ } + reds_channel_init_auth_caps(channel); /* make sure common caps are set */ + ack.num_common_caps = channel->num_common_caps; ack.num_channel_caps = channel->num_caps; header.size += (ack.num_common_caps + ack.num_channel_caps) * sizeof(uint32_t); @@ -2655,6 +2680,31 @@ static void async_read_handler(int fd, int event, void *data) } } +static void reds_get_spice_ticket(RedLinkInfo *link) +{ + AsyncRead *obj = &link->asyc_read; + + obj->now = (uint8_t *)&link->tiTicketing.encrypted_ticket.encrypted_data; + obj->end = obj->now + link->tiTicketing.rsa_size; + obj->done = reds_handle_ticket; + async_read_handler(0, 0, &link->asyc_read); +} + +static void reds_handle_auth_mechanism(void *opaque) +{ + RedLinkInfo *link = (RedLinkInfo *)opaque; + + red_printf("Auth method: %d", link->auth_mechanism.auth_mechanism); + + if (link->auth_mechanism.auth_mechanism == SPICE_COMMON_CAP_AUTH_SPICE) { + reds_get_spice_ticket(link); + } else { + red_printf("Unknown auth method, disconnecting"); + reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA); + reds_link_free(link); + } +} + static int reds_security_check(RedLinkInfo *link) { ChannelSecurityOptions *security_option = find_channel_security(link->link_mess->channel_type); @@ -2669,6 +2719,8 @@ static void reds_handle_read_link_done(void *opaque) SpiceLinkMess *link_mess = link->link_mess; AsyncRead *obj = &link->asyc_read; uint32_t num_caps = link_mess->num_common_caps + link_mess->num_channel_caps; + uint32_t *caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset); + int auth_selection; if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset > link->link_header.size || @@ -2678,6 +2730,9 @@ static void reds_handle_read_link_done(void *opaque) return; } + auth_selection = link_mess->num_common_caps > 0 && + (caps[0] & (1 << SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION));; + if (!reds_security_check(link)) { if (link->stream->ssl) { red_printf("spice channels %d should not be encrypted", link_mess->channel_type); @@ -2695,10 +2750,15 @@ static void reds_handle_read_link_done(void *opaque) return; } - obj->now = (uint8_t *)&link->tiTicketing.encrypted_ticket.encrypted_data; - obj->end = obj->now + link->tiTicketing.rsa_size; - obj->done = reds_handle_ticket; - async_read_handler(0, 0, &link->asyc_read); + if (!auth_selection) { + red_printf("Peer doesn't support AUTH selection"); + reds_get_spice_ticket(link); + } else { + obj->now = (uint8_t *)&link->auth_mechanism; + obj->end = obj->now + sizeof(SpiceLinkAuthMechanism); + obj->done = reds_handle_auth_mechanism; + async_read_handler(0, 0, &link->asyc_read); + } } static void reds_handle_link_error(void *opaque, int err) -- cgit