spice auth过程分析

1、客户端选择认证方法

Client authentication method selection

抓包分析

{

Authentication selected by client: Spice (1)

}

代码分析

spice_channel_send_link(channel);

if (!spice_channel_recv_link_hdr(channel) ||

!spice_channel_recv_link_msg(channel) ||

!spice_channel_recv_auth(channel))

goto cleanup;

while (spice_channel_iterate(channel));

if (!spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION)) {

CHANNEL_DEBUG(channel, "Server supports spice ticket auth only");

if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE)

goto error;

} else {

SpiceLinkAuthMechanism auth = { 0, };

if (spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_AUTH_SPICE)) {

auth.auth_mechanism = GUINT32_TO_LE(SPICE_COMMON_CAP_AUTH_SPICE); //发送spice认证方式

spice_channel_write(channel, &auth, sizeof(auth));

if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) //发送client ticket

goto error;

} else {

g_warning("No compatible AUTH mechanism");

goto error;

}

}

2、Client ticket

抓包分析

{

Ticket - client: 542...

}

代码分析

if (!spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION)) {

CHANNEL_DEBUG(channel, "Server supports spice ticket auth only");

if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE)

goto error;

} else {

SpiceLinkAuthMechanism auth = { 0, };

if (spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_AUTH_SPICE)) {

auth.auth_mechanism = GUINT32_TO_LE(SPICE_COMMON_CAP_AUTH_SPICE); //发送spice认证方式

spice_channel_write(channel, &auth, sizeof(auth));

if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) //发送client ticket

goto error;

} else {

g_warning("No compatible AUTH mechanism");

goto error;

}

}

3、Server ticket

抓包分析

{

Link result: OK (0)

}

代码分析

static void reds_handle_read_link_done(void *opaque)

{

auto link = static_cast<RedLinkInfo *>(opaque);

RedsState *reds = link->reds;

SpiceLinkMess *link_mess = link->link_mess;

uint32_t num_caps;

uint32_t *caps;

int auth_selection;

unsigned int i;

link_mess->caps_offset = GUINT32_FROM_LE(link_mess->caps_offset);

link_mess->connection_id = GUINT32_FROM_LE(link_mess->connection_id);

link_mess->num_channel_caps = GUINT32_FROM_LE(link_mess->num_channel_caps);

link_mess->num_common_caps = GUINT32_FROM_LE(link_mess->num_common_caps);

/* Prevent DoS. Currently we defined only 13 capabilities,

* I expect 1024 to be valid for quite a lot time */

if (link_mess->num_channel_caps > 1024 || link_mess->num_common_caps > 1024) {

reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA);

reds_link_free(link);

return;

}

num_caps = link_mess->num_common_caps + link_mess->num_channel_caps;

caps = reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(link_mess) +link_mess->caps_offset);

if (num_caps && (num_caps * sizeof(uint32_t) + link_mess->caps_offset > link->link_header.size || link_mess->caps_offset < sizeof(*link_mess))) {

reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA);

reds_link_free(link);

return;

}

for(i = 0; i < num_caps;i++)

caps[i] = GUINT32_FROM_LE(caps[i]);

auth_selection = red_link_info_test_capability(link,SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);

if (!reds_security_check(link)) {

if (red_stream_is_ssl(link->stream)) {

spice_warning("spice channels %d should not be encrypted", link_mess->channel_type);

reds_send_link_error(link, SPICE_LINK_ERR_NEED_UNSECURED);

} else {

spice_warning("spice channels %d should be encrypted", link_mess->channel_type);

reds_send_link_error(link, SPICE_LINK_ERR_NEED_SECURED);

}

reds_link_free(link);

return;

}

if (!reds_send_link_ack(reds, link)) {

reds_link_free(link);

return;

}

if (!auth_selection) {

if (reds->config->sasl_enabled && !link->skip_auth) {

spice_warning("SASL enabled, but peer supports only spice authentication");

reds_send_link_error(link, SPICE_LINK_ERR_VERSION_MISMATCH);

return;

}

spice_warning("Peer doesn't support AUTH selection");

reds_get_spice_ticket(link);

} else {

red_stream_async_read(link->stream, reinterpret_cast<uint8_t *>(&link->auth_mechanism),

sizeof(SpiceLinkAuthMechanism), reds_handle_auth_mechanism, link);

}

}

发送ticket数据包

static void reds_handle_auth_mechanism(void *opaque)

{

auto link = static_cast<RedLinkInfo *>(opaque);

RedsState *reds = link->reds;

spice_debug("Auth method: %d", link->auth_mechanism.auth_mechanism);

link->auth_mechanism.auth_mechanism = GUINT32_FROM_LE(link->auth_mechanism.auth_mechanism);

if (link->auth_mechanism.auth_mechanism == SPICE_COMMON_CAP_AUTH_SPICE&& !reds->config->sasl_enabled) {

reds_get_spice_ticket(link);

#if HAVE_SASL

} else if (link->auth_mechanism.auth_mechanism == SPICE_COMMON_CAP_AUTH_SASL) {

spice_debug("Starting SASL");

reds_start_auth_sasl(link);

#endif

} else {

spice_warning("Unknown auth method, disconnecting");

if (reds->config->sasl_enabled) {

spice_warning("Your client doesn't handle SASL?");

}

reds_send_link_error(link, SPICE_LINK_ERR_INVALID_DATA);

reds_link_free(link);

}

}

猜你喜欢

转载自blog.csdn.net/cai742925624/article/details/128735678