[Spice-devel,v2] Report invalid password as a special auth error

Submitted by Cedric Bosdonnat on May 27, 2015, 2:05 p.m.

Details

Message ID 1432735516-23081-1-git-send-email-cbosdonnat@suse.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Cedric Bosdonnat May 27, 2015, 2:05 p.m.
Provide a special authentication error message for too long passwords.
Also check for too long passwords before sending them over the wire.
---

 Diff to v1:
   * Added a check in spice_channel_send_spice_ticket
   * moved spice_channel_failed_authentication before spice_channel_send_spice_ticket
     in order to reuse it there.

 gtk/spice-channel.c | 64 +++++++++++++++++++++++++++++++++--------------------
 gtk/spice-client.h  |  2 ++
 2 files changed, 42 insertions(+), 24 deletions(-)

Patch hide | download patch | download mbox

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 4e7d8b7..c4a18f5 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1010,6 +1010,33 @@  static int spice_channel_read(SpiceChannel *channel, void *data, size_t length)
 }
 
 /* coroutine context */
+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_INVALID_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 void spice_channel_send_spice_ticket(SpiceChannel *channel)
 {
     SpiceChannelPrivate *c = channel->priv;
@@ -1039,11 +1066,17 @@  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);
+        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);
+
+cleanup:
     memset(encrypted, 0, nRSASize);
     EVP_PKEY_free(pubkey);
     BIO_free(bioKey);
@@ -1051,27 +1084,6 @@  static void spice_channel_send_spice_ticket(SpiceChannel *channel)
 }
 
 /* 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 */
-}
-
-/* coroutine context */
 static gboolean spice_channel_recv_auth(SpiceChannel *channel)
 {
     SpiceChannelPrivate *c = channel->priv;
@@ -1086,9 +1098,13 @@  static gboolean spice_channel_recv_auth(SpiceChannel *channel)
         return FALSE;
     }
 
-    if (link_res != SPICE_LINK_ERR_OK) {
+    if (link_res == SPICE_LINK_ERR_INVALID_PASSWORD) {
+        CHANNEL_DEBUG(channel, "link result: invalid password");
+        spice_channel_failed_authentication(channel, TRUE);
+        return FALSE;
+    } 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:
diff --git a/gtk/spice-client.h b/gtk/spice-client.h
index c2474d1..58d1f76 100644
--- a/gtk/spice-client.h
+++ b/gtk/spice-client.h
@@ -60,6 +60,7 @@  G_BEGIN_DECLS
  * @SPICE_CLIENT_USB_DEVICE_LOST: usb device disconnected (fatal IO error)
  * @SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD: password is required
  * @SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME: password and username are required
+ * @SPICE_CLIENT_ERROR_AUTH_INVALID_PASSWORD: password is too long
  *
  * Error codes returned by spice-client API.
  */
@@ -70,6 +71,7 @@  typedef enum
     SPICE_CLIENT_USB_DEVICE_LOST,
     SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD,
     SPICE_CLIENT_ERROR_AUTH_NEEDS_PASSWORD_AND_USERNAME,
+    SPICE_CLIENT_ERROR_AUTH_INVALID_PASSWORD,
 } SpiceClientError;
 
 GQuark spice_client_error_quark(void);

Comments

Hey,

On Wed, May 27, 2015 at 04:05:16PM +0200, C├ędric Bosdonnat wrote:
> Provide a special authentication error message for too long passwords.
> Also check for too long passwords before sending them over the wire.
> ---
> 
>  Diff to v1:
>    * Added a check in spice_channel_send_spice_ticket
>    * moved spice_channel_failed_authentication before spice_channel_send_spice_ticket
>      in order to reuse it there.
> 
>  gtk/spice-channel.c | 64 +++++++++++++++++++++++++++++++++--------------------
>  gtk/spice-client.h  |  2 ++
>  2 files changed, 42 insertions(+), 24 deletions(-)
> 
> diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
> index 4e7d8b7..c4a18f5 100644
> --- a/gtk/spice-channel.c
> +++ b/gtk/spice-channel.c
> @@ -1010,6 +1010,33 @@ static int spice_channel_read(SpiceChannel *channel, void *data, size_t length)
>  }
>  
>  /* coroutine context */
> +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_INVALID_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 void spice_channel_send_spice_ticket(SpiceChannel *channel)
>  {
>      SpiceChannelPrivate *c = channel->priv;
> @@ -1039,11 +1066,17 @@ 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);
> +        goto cleanup;
> +    }


My feeling is that spice_channel_send_spice_ticket() should return
TRUE/FALSE to indicate whether it failed or not, so that
spice_channel_recv_link_msg() can then decide to jump to its error:
label.

Christophe