diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2015-06-15 18:21:13 +0200 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2015-06-15 18:22:12 +0200 |
commit | 7f4aa780b9e074d8460d0cc50d9ce3e6aaf8a668 (patch) | |
tree | cd559b5335f8d0af6742a2ba41b157f09a767cb5 /src | |
parent | f77dd55b39486960fcf9259ebb5d869c93a1f19d (diff) |
channel: check too long password
Make sure that the password length is under the maximum lenght. If not
report it as an authentication failure with an adapted message.
Diffstat (limited to 'src')
-rw-r--r-- | src/spice-channel.c | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/src/spice-channel.c b/src/spice-channel.c index 0585a01..c67e0aa 100644 --- a/src/spice-channel.c +++ b/src/spice-channel.c @@ -1011,7 +1011,34 @@ static int spice_channel_read(SpiceChannel *channel, void *data, size_t length) } /* coroutine context */ -static void spice_channel_send_spice_ticket(SpiceChannel *channel) +static void spice_channel_failed_authentication(SpiceChannel *channel, + gboolean invalidPassword) +{ + SpiceChannelPrivate *c = channel->priv; + + if (c->auth_needs_username_and_password) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME, + _("Authentication failed: password and username are required")); + else if (invalidPassword) + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + _("Authentication failed: password is too long")); + else + g_set_error_literal(&c->error, + SPICE_CLIENT_ERROR, + SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, + _("Authentication failed: password is required")); + + c->event = SPICE_CHANNEL_ERROR_AUTH; + + c->has_error = TRUE; /* force disconnect */ +} + +/* coroutine context */ +static SpiceChannelEvent spice_channel_send_spice_ticket(SpiceChannel *channel) { SpiceChannelPrivate *c = channel->priv; EVP_PKEY *pubkey; @@ -1021,13 +1048,14 @@ static void spice_channel_send_spice_ticket(SpiceChannel *channel) char *password; uint8_t *encrypted; int rc; + SpiceChannelEvent ret = SPICE_CHANNEL_ERROR_LINK; bioKey = BIO_new(BIO_s_mem()); - g_return_if_fail(bioKey != NULL); + g_return_val_if_fail(bioKey != NULL, ret); BIO_write(bioKey, c->peer_msg->pub_key, SPICE_TICKET_PUBKEY_BYTES); pubkey = d2i_PUBKEY_bio(bioKey, NULL); - g_return_if_fail(pubkey != NULL); + g_return_val_if_fail(pubkey != NULL, ret); rsa = pubkey->pkey.rsa; nRSASize = RSA_size(rsa); @@ -1040,36 +1068,24 @@ static void spice_channel_send_spice_ticket(SpiceChannel *channel) g_object_get(c->session, "password", &password, NULL); if (password == NULL) password = g_strdup(""); + if (strlen(password) > SPICE_MAX_PASSWORD_LENGTH) { + spice_channel_failed_authentication(channel, TRUE); + ret = SPICE_CHANNEL_ERROR_AUTH; + goto cleanup; + } rc = RSA_public_encrypt(strlen(password) + 1, (uint8_t*)password, encrypted, rsa, RSA_PKCS1_OAEP_PADDING); g_warn_if_fail(rc > 0); spice_channel_write(channel, encrypted, nRSASize); + ret = SPICE_CHANNEL_NONE; + +cleanup: memset(encrypted, 0, nRSASize); EVP_PKEY_free(pubkey); BIO_free(bioKey); g_free(password); -} - -/* coroutine context */ -static void spice_channel_failed_authentication(SpiceChannel *channel) -{ - SpiceChannelPrivate *c = channel->priv; - - if (c->auth_needs_username_and_password) - g_set_error_literal(&c->error, - SPICE_CLIENT_ERROR, - SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME, - _("Authentication failed: password and username are required")); - else - g_set_error_literal(&c->error, - SPICE_CLIENT_ERROR, - SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD, - _("Authentication failed: password is required")); - - c->event = SPICE_CHANNEL_ERROR_AUTH; - - c->has_error = TRUE; /* force disconnect */ + return ret; } /* coroutine context */ @@ -1089,7 +1105,7 @@ static gboolean spice_channel_recv_auth(SpiceChannel *channel) if (link_res != SPICE_LINK_ERR_OK) { CHANNEL_DEBUG(channel, "link result: reply %d", link_res); - spice_channel_failed_authentication(channel); + spice_channel_failed_authentication(channel, FALSE); return FALSE; } @@ -1663,7 +1679,7 @@ error: if (saslconn) sasl_dispose(&saslconn); - spice_channel_failed_authentication(channel); + spice_channel_failed_authentication(channel, FALSE); ret = FALSE; cleanup: @@ -1682,6 +1698,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel) SpiceChannelPrivate *c; int rc, num_caps, i; uint32_t *caps; + SpiceChannelEvent event = SPICE_CHANNEL_ERROR_LINK; g_return_val_if_fail(channel != NULL, FALSE); g_return_val_if_fail(channel->priv != NULL, FALSE); @@ -1734,7 +1751,8 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel) if (!spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION)) { CHANNEL_DEBUG(channel, "Server supports spice ticket auth only"); - spice_channel_send_spice_ticket(channel); + if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) + goto error; } else { SpiceLinkAuthMechanism auth = { 0, }; @@ -1750,7 +1768,8 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel) if (spice_channel_test_common_capability(channel, SPICE_COMMON_CAP_AUTH_SPICE)) { auth.auth_mechanism = SPICE_COMMON_CAP_AUTH_SPICE; spice_channel_write(channel, &auth, sizeof(auth)); - spice_channel_send_spice_ticket(channel); + if ((event = spice_channel_send_spice_ticket(channel)) != SPICE_CHANNEL_NONE) + goto error; } else { g_warning("No compatible AUTH mechanism"); goto error; @@ -1763,7 +1782,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel) error: c->has_error = TRUE; - c->event = SPICE_CHANNEL_ERROR_LINK; + c->event = event; return FALSE; } |