[Spice-devel] [PATCH 12/13] server: add auth mechanism selection

Marc-André Lureau marcandre.lureau at redhat.com
Tue Feb 22 08:09:06 PST 2011


---
 server/reds.c |   68 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index d7ac6d8..0a26e79 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -239,6 +239,7 @@ typedef struct RedLinkInfo {
     SpiceLinkMess *link_mess;
     int mess_pos;
     TicketInfo tiTicketing;
+    SpiceLinkAuthMechanism auth_mechanism;
 } RedLinkInfo;
 
 typedef struct VDIPortBuf VDIPortBuf;
@@ -1347,6 +1348,28 @@ static int sync_write(RedsStream *peer, 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);
@@ -1379,6 +1402,8 @@ static int reds_send_link_ack(RedLinkInfo *link)
     if (!channel)
         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);
@@ -1688,6 +1713,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);
@@ -1702,6 +1752,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 ||
@@ -1711,6 +1763,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);
@@ -1728,10 +1783,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)
-- 
1.7.4



More information about the Spice-devel mailing list