diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2022-07-24 22:55:08 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2022-07-24 22:55:08 +0000 |
commit | 196e3605aa774c0b3082857a6e7fe23808c35cd1 (patch) | |
tree | 18478b83e60474c752ad6d90da64b87f6bc8c536 | |
parent | 101be84d2f6b1f2b41300e6abd444b756b6d71a5 (diff) | |
parent | 32b226d1b1e23e7f45d874c0147b9d3ab89e2747 (diff) | |
download | glib-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.c | 7 | ||||
-rw-r--r-- | gio/gdbusauth.h | 1 | ||||
-rw-r--r-- | gio/gdbusauthmechanism.c | 6 | ||||
-rw-r--r-- | gio/gdbusauthmechanism.h | 2 | ||||
-rw-r--r-- | gio/gdbusauthmechanismanon.c | 2 | ||||
-rw-r--r-- | gio/gdbusauthmechanismexternal.c | 58 | ||||
-rw-r--r-- | gio/gdbusauthmechanismsha1.c | 2 | ||||
-rw-r--r-- | gio/gdbusconnection.c | 4 | ||||
-rw-r--r-- | gio/gioenums.h | 9 | ||||
-rw-r--r-- | gio/tests/gdbus-connection.c | 3 |
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); |