[Spice-devel] [PATCH v4] Check too long password
Christophe Fergeau
cfergeau at redhat.com
Thu Jun 4 02:19:47 PDT 2015
On Wed, Jun 03, 2015 at 04:22:35PM +0200, Cédric Bosdonnat wrote:
> Make sure that the password lenght is under the maximum lenght. If not
> report it as an authentication failure with an adapted message.
> ---
> Diff to v3:
>
> * Removed the checks on the server side and the corresponding code here
> * Removed the new error code to reuse SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD.
> * spice_channel_send_spice_ticket returns SpiceChannelEvent instead of a gboolean:
> this helps properly propagating the kind of error to the client.
>
> gtk/spice-channel.c | 80 ++++++++++++++++++++++++++++++++++-------------------
> 1 file changed, 51 insertions(+), 29 deletions(-)
>
> diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
> index 4e7d8b7..d01b147 100644
> --- a/gtk/spice-channel.c
> +++ b/gtk/spice-channel.c
> @@ -1010,7 +1010,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;
> @@ -1020,13 +1047,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);
> @@ -1039,36 +1067,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 */
> @@ -1088,7 +1104,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;
> }
>
> @@ -1662,7 +1678,7 @@ error:
> if (saslconn)
> sasl_dispose(&saslconn);
>
> - spice_channel_failed_authentication(channel);
> + spice_channel_failed_authentication(channel, FALSE);
> ret = FALSE;
>
> cleanup:
> @@ -1681,6 +1697,7 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
> SpiceChannelPrivate *c;
> int rc, num_caps, i;
> uint32_t *caps;
> + SpiceChannelEvent event = SPICE_CHANNEL_NONE;
I would set this to SPICE_CHANNEL_ERROR_LINK...
>
> g_return_val_if_fail(channel != NULL, FALSE);
> g_return_val_if_fail(channel->priv != NULL, FALSE);
> @@ -1733,7 +1750,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, };
>
> @@ -1749,7 +1767,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;
> @@ -1762,7 +1781,10 @@ static gboolean spice_channel_recv_link_msg(SpiceChannel *channel)
>
> error:
> c->has_error = TRUE;
> - c->event = SPICE_CHANNEL_ERROR_LINK;
> + if (event == SPICE_CHANNEL_NONE)
> + c->event = SPICE_CHANNEL_ERROR_LINK;
> + else
> + c->event = event;
... and just do c->event = event; here (with a g_warn_if_fail(event !=
SPICE_CHANNEL_NONE); if you want to be paranoid).
Looks good to me otherwise, ACK.
Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20150604/94115f01/attachment-0001.sig>
More information about the Spice-devel
mailing list