summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2022-07-24 22:55:08 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2022-07-24 22:55:08 +0000
commit196e3605aa774c0b3082857a6e7fe23808c35cd1 (patch)
tree18478b83e60474c752ad6d90da64b87f6bc8c536
parent101be84d2f6b1f2b41300e6abd444b756b6d71a5 (diff)
parent32b226d1b1e23e7f45d874c0147b9d3ab89e2747 (diff)
downloadglib-196e3605aa774c0b3082857a6e7fe23808c35cd1.tar.gz
Merge branch 'wip/smcv/gdbus-cross-namespace' into 'main'
GDBus: Use namespace-friendly protocol for Linux message buses, and optionally other connections See merge request GNOME/glib!2832
-rw-r--r--gio/gdbusauth.c7
-rw-r--r--gio/gdbusauth.h1
-rw-r--r--gio/gdbusauthmechanism.c6
-rw-r--r--gio/gdbusauthmechanism.h2
-rw-r--r--gio/gdbusauthmechanismanon.c2
-rw-r--r--gio/gdbusauthmechanismexternal.c58
-rw-r--r--gio/gdbusauthmechanismsha1.c2
-rw-r--r--gio/gdbusconnection.c4
-rw-r--r--gio/gioenums.h9
-rw-r--r--gio/tests/gdbus-connection.c3
10 files changed, 70 insertions, 24 deletions
diff --git a/gio/gdbusauth.c b/gio/gdbusauth.c
index 89cbbf67c..671036805 100644
--- a/gio/gdbusauth.c
+++ b/gio/gdbusauth.c
@@ -417,6 +417,7 @@ hexdecode (const gchar *str,
static GDBusAuthMechanism *
client_choose_mech_and_send_initial_response (GDBusAuth *auth,
GCredentials *credentials_that_were_sent,
+ GDBusConnectionFlags conn_flags,
const gchar* const *supported_auth_mechs,
GPtrArray *attempted_auth_mechs,
GDataOutputStream *dos,
@@ -507,6 +508,7 @@ client_choose_mech_and_send_initial_response (GDBusAuth *auth,
initial_response_len = 0;
initial_response = _g_dbus_auth_mechanism_client_initiate (mech,
+ conn_flags,
&initial_response_len);
#if 0
g_printerr ("using auth mechanism with name '%s' of type '%s' with initial response '%s'\n",
@@ -556,6 +558,7 @@ typedef enum
gchar *
_g_dbus_auth_run_client (GDBusAuth *auth,
GDBusAuthObserver *observer,
+ GDBusConnectionFlags conn_flags,
GDBusCapabilityFlags offered_capabilities,
GDBusCapabilityFlags *out_negotiated_capabilities,
GCancellable *cancellable,
@@ -574,6 +577,9 @@ _g_dbus_auth_run_client (GDBusAuth *auth,
ClientState state;
GDBusCapabilityFlags negotiated_capabilities;
+ g_return_val_if_fail ((conn_flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT), NULL);
+ g_return_val_if_fail (!(conn_flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER), NULL);
+
debug_print ("CLIENT: initiating");
_g_dbus_auth_add_mechs (auth, observer);
@@ -667,6 +673,7 @@ _g_dbus_auth_run_client (GDBusAuth *auth,
g_free (line);
mech = client_choose_mech_and_send_initial_response (auth,
credentials,
+ conn_flags,
(const gchar* const *) supported_auth_mechs,
attempted_auth_mechs,
dos,
diff --git a/gio/gdbusauth.h b/gio/gdbusauth.h
index 30140fb98..8fa89444a 100644
--- a/gio/gdbusauth.h
+++ b/gio/gdbusauth.h
@@ -78,6 +78,7 @@ gboolean _g_dbus_auth_run_server (GDBusAuth *auth,
gchar *_g_dbus_auth_run_client (GDBusAuth *auth,
GDBusAuthObserver *observer,
+ GDBusConnectionFlags conn_flags,
GDBusCapabilityFlags offered_capabilities,
GDBusCapabilityFlags *out_negotiated_capabilities,
GCancellable *cancellable,
diff --git a/gio/gdbusauthmechanism.c b/gio/gdbusauthmechanism.c
index 38d7210e5..6e494dbd9 100644
--- a/gio/gdbusauthmechanism.c
+++ b/gio/gdbusauthmechanism.c
@@ -301,11 +301,13 @@ _g_dbus_auth_mechanism_client_get_state (GDBusAuthMechanism *mechanism)
}
gchar *
-_g_dbus_auth_mechanism_client_initiate (GDBusAuthMechanism *mechanism,
- gsize *out_initial_response_len)
+_g_dbus_auth_mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
+ gsize *out_initial_response_len)
{
g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM (mechanism), NULL);
return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_initiate (mechanism,
+ conn_flags,
out_initial_response_len);
}
diff --git a/gio/gdbusauthmechanism.h b/gio/gdbusauthmechanism.h
index bc4afe74d..f0edd19a3 100644
--- a/gio/gdbusauthmechanism.h
+++ b/gio/gdbusauthmechanism.h
@@ -93,6 +93,7 @@ struct _GDBusAuthMechanismClass
/* functions for client-side authentication */
GDBusAuthMechanismState (*client_get_state) (GDBusAuthMechanism *mechanism);
gchar *(*client_initiate) (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len);
void (*client_data_receive) (GDBusAuthMechanism *mechanism,
const gchar *data,
@@ -140,6 +141,7 @@ void _g_dbus_auth_mechanism_server_shutdown (GDBus
GDBusAuthMechanismState _g_dbus_auth_mechanism_client_get_state (GDBusAuthMechanism *mechanism);
gchar *_g_dbus_auth_mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len);
void _g_dbus_auth_mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
const gchar *data,
diff --git a/gio/gdbusauthmechanismanon.c b/gio/gdbusauthmechanismanon.c
index 903907f86..5f59d4a61 100644
--- a/gio/gdbusauthmechanismanon.c
+++ b/gio/gdbusauthmechanismanon.c
@@ -60,6 +60,7 @@ static gchar *mechanism_server_get_reject_reason (GDBusAuthMe
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len);
static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
const gchar *data,
@@ -261,6 +262,7 @@ mechanism_client_get_state (GDBusAuthMechanism *mechanism)
static gchar *
mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len)
{
GDBusAuthMechanismAnon *m = G_DBUS_AUTH_MECHANISM_ANON (mechanism);
diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c
index a465862d1..6fe8b1bed 100644
--- a/gio/gdbusauthmechanismexternal.c
+++ b/gio/gdbusauthmechanismexternal.c
@@ -68,6 +68,7 @@ static gchar *mechanism_server_get_reject_reason (GDBusAuthMe
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len);
static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
const gchar *data,
@@ -360,38 +361,51 @@ mechanism_client_get_state (GDBusAuthMechanism *mechanism)
static gchar *
mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len)
{
GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
gchar *initial_response = NULL;
-#if defined(G_OS_UNIX)
- GCredentials *credentials;
-#endif
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);
m->priv->is_client = TRUE;
- m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
+ m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA;
*out_initial_response_len = 0;
- /* return the uid */
+ if (conn_flags & G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE)
+ {
+ /* If backwards-compatibility with GDBus servers < 2.73.3 is not a
+ * concern, we do not send an initial response, because there is
+ * no way to express an empty authorization identity this way.
+ * Instead, we'll reply to the server's first (empty) challenge
+ * with an empty authorization identity in our first response. */
+ g_debug ("Using cross-namespace EXTERNAL authentication (this will deadlock if server is GDBus < 2.73.3)");
+ }
+ else
+ {
+ /* Send the Unix uid or Windows SID as an initial response.
+ * This is the only thing that is interoperable with GDBus 2.73.3
+ * servers. */
#if defined(G_OS_UNIX)
- credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
- g_assert (credentials != NULL);
+ GCredentials *credentials;
+
+ credentials = _g_dbus_auth_mechanism_get_credentials (mechanism);
+ g_assert (credentials != NULL);
- initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) g_credentials_get_unix_user (credentials, NULL));
+ initial_response = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) g_credentials_get_unix_user (credentials, NULL));
#elif defined(G_OS_WIN32)
- initial_response = _g_win32_current_process_sid_string (NULL);
+ initial_response = _g_win32_current_process_sid_string (NULL);
#else
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wcpp"
-#warning Dont know how to send credentials on this OS. The EXTERNAL D-Bus authentication mechanism will not work.
-#pragma GCC diagnostic pop
-#endif
+ /* GDBus < 2.73.3 servers can't have worked on this platform anyway,
+ * so it isn't a regression to behave as though
+ * G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE had been set. */
+ g_debug ("Unknown platform, cannot use initial response in EXTERNAL");
#endif
+ }
+
if (initial_response)
{
m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED;
@@ -411,8 +425,9 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
g_return_if_fail (m->priv->is_client && !m->priv->is_server);
g_return_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA);
- /* can never end up here because we are never in the WAITING_FOR_DATA state */
- g_assert_not_reached ();
+ /* The server sent us a challenge, which should normally
+ * be empty. We respond with our authorization identity. */
+ m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND;
}
static gchar *
@@ -425,10 +440,11 @@ mechanism_client_data_send (GDBusAuthMechanism *mechanism,
g_return_val_if_fail (m->priv->is_client && !m->priv->is_server, 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 ();
-
- return NULL;
+ /* We respond to the server's challenge by sending our
+ * authorization identity, which is the empty string, meaning
+ * whoever the out-of-band credentials say we are. */
+ *out_data_len = 0;
+ return g_strdup ("");
}
static void
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index a11c9f38d..fb6488a2a 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -119,6 +119,7 @@ static gchar *mechanism_server_get_reject_reason (GDBusAuthMe
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len);
static void mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
const gchar *data,
@@ -1160,6 +1161,7 @@ mechanism_client_get_state (GDBusAuthMechanism *mechanism)
static gchar *
mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
gsize *out_initial_response_len)
{
GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index f0d50f7d8..663cd95ab 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -2569,6 +2569,7 @@ initable_init (GInitable *initable,
connection->auth = _g_dbus_auth_new (connection->stream);
connection->guid = _g_dbus_auth_run_client (connection->auth,
connection->authentication_observer,
+ connection->flags,
get_offered_capabilities_max (connection),
&connection->capabilities,
cancellable,
@@ -7368,6 +7369,9 @@ get_uninitialized_connection (GBusType bus_type,
ret = g_object_new (G_TYPE_DBUS_CONNECTION,
"address", address,
"flags", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+#ifdef __linux__
+ G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE |
+#endif
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
"exit-on-close", TRUE,
NULL);
diff --git a/gio/gioenums.h b/gio/gioenums.h
index fb5944996..3ba1d5b75 100644
--- a/gio/gioenums.h
+++ b/gio/gioenums.h
@@ -1216,6 +1216,12 @@ typedef enum
* delayed until g_dbus_connection_start_message_processing() is called.
* @G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER: When authenticating
* as a server, require the UID of the peer to be the same as the UID of the server. (Since: 2.68)
+ * @G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE: When authenticating, try to use
+ * protocols that work across a Linux user namespace boundary, even if this
+ * reduces interoperability with older D-Bus implementations. This currently
+ * affects client-side `EXTERNAL` authentication, for which this flag makes
+ * connections to a server in another user namespace succeed, but causes
+ * a deadlock when connecting to a GDBus server older than 2.73.3. Since: 2.74
*
* Flags used when creating a new #GDBusConnection.
*
@@ -1228,7 +1234,8 @@ typedef enum {
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<2),
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION = (1<<3),
G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING = (1<<4),
- G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_AVAILABLE_ENUMERATOR_IN_2_68 = (1<<5)
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER GLIB_AVAILABLE_ENUMERATOR_IN_2_68 = (1<<5),
+ G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE GLIB_AVAILABLE_ENUMERATOR_IN_2_74 = (1<<6)
} GDBusConnectionFlags;
/**
diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c
index 61ca5c4b7..d04dd0446 100644
--- a/gio/tests/gdbus-connection.c
+++ b/gio/tests/gdbus-connection.c
@@ -1234,6 +1234,9 @@ test_connection_basic (void)
flags == G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
connection_flags = g_dbus_connection_get_flags (connection);
+ /* Ignore G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE, it's an
+ * implementation detail whether we set it */
+ connection_flags &= ~G_DBUS_CONNECTION_FLAGS_CROSS_NAMESPACE;
g_assert_cmpint (connection_flags, ==,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION);