summaryrefslogtreecommitdiffstats
path: root/server/reds.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2011-02-22 13:54:09 +0100
committerAlon Levy <alevy@redhat.com>2011-07-21 15:09:27 +0300
commit6101cb805ac1fc524f74a311e6cafafc0abc1982 (patch)
treede1652d42a2b0e87535955fa57e2b3bce55cb1a4 /server/reds.c
parentbb6747b3d5ca52810eb0c9e12286262491e34559 (diff)
downloadspice-6101cb805ac1fc524f74a311e6cafafc0abc1982.tar.gz
spice-6101cb805ac1fc524f74a311e6cafafc0abc1982.tar.xz
spice-6101cb805ac1fc524f74a311e6cafafc0abc1982.zip
server: add auth mechanism selection
https://bugs.freedesktop.org/show_bug.cgi?id=34795
Diffstat (limited to 'server/reds.c')
-rw-r--r--server/reds.c68
1 files changed, 64 insertions, 4 deletions
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 = &caps;
}
+ 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)