[glib/wip/smcv/gdbus-sasl: 2/5] GDBusServer: If no initial response for EXTERNAL, send a challenge




commit a7d2e727eefcf883bb463ad559f5632e8e448757
Author: Giuseppe Scrivano <giuseppe scrivano org>
Date:   Mon Sep 14 16:28:10 2020 +0200

    GDBusServer: If no initial response for EXTERNAL, send a challenge
    
    Sending an "initial response" along with the AUTH command is meant
    to be an optional optimization, and clients are allowed to omit it.
    We must reply with our initial challenge, which in the case of EXTERNAL
    is an empty string: the client responds to that with the authorization
    identity.
    
    If we do not reply to the AUTH command, then the client will wait
    forever for our reply, while we wait forever for the reply that we
    expect the client to send, resulting in deadlock.
    
    D-Bus does not have a way to distinguish between an empty initial
    response and the absence of an initial response, so clients that want
    to use an empty authorization identity, such as systed's sd-bus,
    cannot use the initial-response optimization and will fail to connect
    to a GDBusServer that does not have this change.
    
    [Originally part of a larger commit; commit message added by smcv.]
    
    Signed-off-by: Simon McVittie <smcv collabora com>

 gio/gdbusauthmechanismexternal.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
---
diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c
index 617fe1d0e5..ddd06cbd5e 100644
--- a/gio/gdbusauthmechanismexternal.c
+++ b/gio/gdbusauthmechanismexternal.c
@@ -40,6 +40,7 @@ struct _GDBusAuthMechanismExternalPrivate
   gboolean is_client;
   gboolean is_server;
   GDBusAuthMechanismState state;
+  gboolean empty_data_sent;
 };
 
 static gint                     mechanism_get_priority              (void);
@@ -253,7 +254,9 @@ mechanism_server_initiate (GDBusAuthMechanism   *mechanism,
     }
   else
     {
-      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
+      /* The initial-response optimization was not used, so we need to
+       * send an empty challenge to prompt the client to respond. */
+      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
     }
 }
 
@@ -288,12 +291,22 @@ mechanism_server_data_send (GDBusAuthMechanism   *mechanism,
 
   g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
   g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
-  g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND, NULL);
 
-  /* can never end up here because we are never in the HAVE_DATA_TO_SEND state */
-  g_assert_not_reached ();
+  if (out_data_len)
+    *out_data_len = 0;
 
-  return NULL;
+  if (m->priv->empty_data_sent)
+    {
+      /* We have already sent an empty data response.
+         Reject the connection.  */
+      m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
+      return NULL;
+    }
+
+  m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
+  m->priv->empty_data_sent = TRUE;
+
+  return g_strdup ("");
 }
 
 static gchar *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]