Merge branch '1804-gdbus-require-same-user' into 'master'

Resolve "Add G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag"

Closes #1804

See merge request GNOME/glib!1814
This commit is contained in:
Simon McVittie 2021-02-12 16:38:01 +00:00
commit 600c873b3e
8 changed files with 68 additions and 62 deletions

View File

@ -924,6 +924,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
GDBusAuthObserver *observer, GDBusAuthObserver *observer,
const gchar *guid, const gchar *guid,
gboolean allow_anonymous, gboolean allow_anonymous,
gboolean require_same_user,
GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags offered_capabilities,
GDBusCapabilityFlags *out_negotiated_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities,
GCredentials **out_received_credentials, GCredentials **out_received_credentials,
@ -941,6 +942,7 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
gchar *s; gchar *s;
GDBusCapabilityFlags negotiated_capabilities; GDBusCapabilityFlags negotiated_capabilities;
GCredentials *credentials; GCredentials *credentials;
GCredentials *own_credentials = NULL;
debug_print ("SERVER: initiating"); debug_print ("SERVER: initiating");
@ -1039,6 +1041,8 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
debug_print ("SERVER: didn't receive any credentials"); debug_print ("SERVER: didn't receive any credentials");
} }
own_credentials = g_credentials_new ();
state = SERVER_STATE_WAITING_FOR_AUTH; state = SERVER_STATE_WAITING_FOR_AUTH;
while (TRUE) while (TRUE)
{ {
@ -1155,10 +1159,21 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
switch (_g_dbus_auth_mechanism_server_get_state (mech)) switch (_g_dbus_auth_mechanism_server_get_state (mech))
{ {
case G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED: case G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED:
if (observer != NULL && if (require_same_user &&
!g_dbus_auth_observer_authorize_authenticated_peer (observer, (credentials == NULL ||
auth->priv->stream, !g_credentials_is_same_user (credentials, own_credentials, NULL)))
credentials)) {
/* disconnect */
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("User IDs must be the same for peer and server"));
goto out;
}
else if (observer != NULL &&
!g_dbus_auth_observer_authorize_authenticated_peer (observer,
auth->priv->stream,
credentials))
{ {
/* disconnect */ /* disconnect */
g_set_error_literal (error, g_set_error_literal (error,
@ -1348,12 +1363,10 @@ _g_dbus_auth_run_server (GDBusAuth *auth,
"Not implemented (server)"); "Not implemented (server)");
out: out:
if (mech != NULL) g_clear_object (&mech);
g_object_unref (mech); g_clear_object (&dis);
if (dis != NULL) g_clear_object (&dos);
g_object_unref (dis); g_clear_object (&own_credentials);
if (dos != NULL)
g_object_unref (dos);
/* ensure return value is FALSE if error is set */ /* ensure return value is FALSE if error is set */
if (error != NULL && *error != NULL) if (error != NULL && *error != NULL)

View File

@ -67,6 +67,7 @@ gboolean _g_dbus_auth_run_server (GDBusAuth *auth,
GDBusAuthObserver *observer, GDBusAuthObserver *observer,
const gchar *guid, const gchar *guid,
gboolean allow_anonymous, gboolean allow_anonymous,
gboolean require_same_user,
GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags offered_capabilities,
GDBusCapabilityFlags *out_negotiated_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities,
GCredentials **out_received_credentials, GCredentials **out_received_credentials,

View File

@ -70,7 +70,9 @@
* connections from any successfully authenticated user (but not from * connections from any successfully authenticated user (but not from
* anonymous connections using the `ANONYMOUS` mechanism). If you only * anonymous connections using the `ANONYMOUS` mechanism). If you only
* want to allow D-Bus connections from processes owned by the same uid * want to allow D-Bus connections from processes owned by the same uid
* as the server, you would use a signal handler like the following: * as the server, since GLib 2.68, you should use the
* %G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag. Its equivalent
* to the following signal handler:
* *
* |[<!-- language="C" --> * |[<!-- language="C" -->
* static gboolean * static gboolean

View File

@ -125,7 +125,8 @@
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | \ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER | \
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | \ G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION | \
G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING | \
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
/** /**
* SECTION:gdbusconnection * SECTION:gdbusconnection
@ -2518,7 +2519,8 @@ initable_init (GInitable *initable,
g_assert (connection->stream == NULL); g_assert (connection->stream == NULL);
if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) || if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)) (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) ||
(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER))
{ {
g_set_error_literal (&connection->initialization_error, g_set_error_literal (&connection->initialization_error,
G_IO_ERROR, G_IO_ERROR,
@ -2553,6 +2555,7 @@ initable_init (GInitable *initable,
connection->authentication_observer, connection->authentication_observer,
connection->guid, connection->guid,
(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS), (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS),
(connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER),
get_offered_capabilities_max (connection), get_offered_capabilities_max (connection),
&connection->capabilities, &connection->capabilities,
&connection->credentials, &connection->credentials,
@ -2838,8 +2841,9 @@ g_dbus_connection_new_sync (GIOStream *stream,
* This constructor can only be used to initiate client-side * This constructor can only be used to initiate client-side
* connections - use g_dbus_connection_new() if you need to act as the * connections - use g_dbus_connection_new() if you need to act as the
* server. In particular, @flags cannot contain the * server. In particular, @flags cannot contain the
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags. * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags.
* *
* When the operation is finished, @callback will be invoked. You can * When the operation is finished, @callback will be invoked. You can
* then call g_dbus_connection_new_for_address_finish() to get the result of * then call g_dbus_connection_new_for_address_finish() to get the result of
@ -2929,8 +2933,9 @@ g_dbus_connection_new_for_address_finish (GAsyncResult *res,
* This constructor can only be used to initiate client-side * This constructor can only be used to initiate client-side
* connections - use g_dbus_connection_new_sync() if you need to act * connections - use g_dbus_connection_new_sync() if you need to act
* as the server. In particular, @flags cannot contain the * as the server. In particular, @flags cannot contain the
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER or * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS flags. * %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS or
* %G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flags.
* *
* This is a synchronous failable constructor. See * This is a synchronous failable constructor. See
* g_dbus_connection_new_for_address() for the asynchronous version. * g_dbus_connection_new_for_address() for the asynchronous version.

View File

@ -1538,34 +1538,6 @@ on_new_connection (GDBusServer *server,
return TRUE; return TRUE;
} }
static gboolean
on_authorize_authenticated_peer (GDBusAuthObserver *observer,
GIOStream *stream,
GCredentials *credentials,
gpointer user_data)
{
gboolean authorized = FALSE;
if (credentials != NULL)
{
GCredentials *own_credentials;
own_credentials = g_credentials_new ();
authorized = g_credentials_is_same_user (credentials, own_credentials, NULL);
g_object_unref (own_credentials);
}
#ifdef G_OS_WIN32
else
{
/* We allow ANONYMOUS authentication on Windows for now, in
* combination with the nonce-tcp transport. */
authorized = TRUE;
}
#endif
return authorized;
}
static void static void
g_dbus_daemon_finalize (GObject *object) g_dbus_daemon_finalize (GObject *object)
{ {
@ -1615,7 +1587,6 @@ initable_init (GInitable *initable,
GError **error) GError **error)
{ {
GDBusDaemon *daemon = G_DBUS_DAEMON (initable); GDBusDaemon *daemon = G_DBUS_DAEMON (initable);
GDBusAuthObserver *observer;
GDBusServerFlags flags; GDBusServerFlags flags;
flags = G_DBUS_SERVER_FLAGS_NONE; flags = G_DBUS_SERVER_FLAGS_NONE;
@ -1629,24 +1600,23 @@ initable_init (GInitable *initable,
daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL); daemon->tmpdir = g_dir_make_tmp ("gdbus-daemon-XXXXXX", NULL);
daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir); daemon->address = g_strdup_printf ("unix:tmpdir=%s", daemon->tmpdir);
} }
flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
#else #else
/* Dont require authentication on Windows as that hasnt been
* implemented yet. */
daemon->address = g_strdup ("nonce-tcp:"); daemon->address = g_strdup ("nonce-tcp:");
flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
#endif #endif
} }
observer = g_dbus_auth_observer_new ();
daemon->server = g_dbus_server_new_sync (daemon->address, daemon->server = g_dbus_server_new_sync (daemon->address,
flags, flags,
daemon->guid, daemon->guid,
observer, NULL,
cancellable, cancellable,
error); error);
if (daemon->server == NULL) if (daemon->server == NULL)
{ return FALSE;
g_object_unref (observer);
return FALSE;
}
g_dbus_server_start (daemon->server); g_dbus_server_start (daemon->server);
@ -1654,12 +1624,6 @@ initable_init (GInitable *initable,
g_signal_connect (daemon->server, "new-connection", g_signal_connect (daemon->server, "new-connection",
G_CALLBACK (on_new_connection), G_CALLBACK (on_new_connection),
daemon); daemon);
g_signal_connect (observer,
"authorize-authenticated-peer",
G_CALLBACK (on_authorize_authenticated_peer),
daemon);
g_object_unref (observer);
return TRUE; return TRUE;
} }

View File

@ -59,7 +59,8 @@
#define G_DBUS_SERVER_FLAGS_ALL \ #define G_DBUS_SERVER_FLAGS_ALL \
(G_DBUS_SERVER_FLAGS_RUN_IN_THREAD | \ (G_DBUS_SERVER_FLAGS_RUN_IN_THREAD | \
G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS | \
G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
/** /**
* SECTION:gdbusserver * SECTION:gdbusserver
@ -81,7 +82,9 @@
* Note that a minimal #GDBusServer will accept connections from any * Note that a minimal #GDBusServer will accept connections from any
* peer. In many use-cases it will be necessary to add a #GDBusAuthObserver * peer. In many use-cases it will be necessary to add a #GDBusAuthObserver
* that only accepts connections that have successfully authenticated * that only accepts connections that have successfully authenticated
* as the same user that is running the #GDBusServer. * as the same user that is running the #GDBusServer. Since GLib 2.68 this can
* be achieved more simply by passing the
* %G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER flag to the server.
*/ */
/** /**
@ -1037,6 +1040,8 @@ on_run (GSocketService *service,
G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING; G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING;
if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS) if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS)
connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
if (server->flags & G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER)
connection_flags |= G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection), connection = g_dbus_connection_new_sync (G_IO_STREAM (socket_connection),
server->guid, server->guid,

View File

@ -1206,6 +1206,8 @@ typedef enum
* message bus. This means that the Hello() method will be invoked as part of the connection setup. * message bus. This means that the Hello() method will be invoked as part of the connection setup.
* @G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING: If set, processing of D-Bus messages is * @G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING: If set, processing of D-Bus messages is
* delayed until g_dbus_connection_start_message_processing() is called. * 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)
* *
* Flags used when creating a new #GDBusConnection. * Flags used when creating a new #GDBusConnection.
* *
@ -1217,7 +1219,8 @@ typedef enum {
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER = (1<<1), G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER = (1<<1),
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<2), G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<2),
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION = (1<<3), G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION = (1<<3),
G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING = (1<<4) G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING = (1<<4),
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER = (1<<5)
} GDBusConnectionFlags; } GDBusConnectionFlags;
/** /**
@ -1368,6 +1371,8 @@ typedef enum
* details). * details).
* @G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS: Allow the anonymous * @G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS: Allow the anonymous
* authentication method. * authentication method.
* @G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER: Require the UID of the
* peer to be the same as the UID of the server when authenticating. (Since: 2.68)
* *
* Flags used when creating a #GDBusServer. * Flags used when creating a #GDBusServer.
* *
@ -1377,7 +1382,8 @@ typedef enum
{ {
G_DBUS_SERVER_FLAGS_NONE = 0, G_DBUS_SERVER_FLAGS_NONE = 0,
G_DBUS_SERVER_FLAGS_RUN_IN_THREAD = (1<<0), G_DBUS_SERVER_FLAGS_RUN_IN_THREAD = (1<<0),
G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<1) G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS = (1<<1),
G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER = (1<<2)
} GDBusServerFlags; } GDBusServerFlags;
/** /**

View File

@ -37,6 +37,7 @@ typedef enum
INTEROP_FLAGS_TCP = (1 << 3), INTEROP_FLAGS_TCP = (1 << 3),
INTEROP_FLAGS_LIBDBUS = (1 << 4), INTEROP_FLAGS_LIBDBUS = (1 << 4),
INTEROP_FLAGS_ABSTRACT = (1 << 5), INTEROP_FLAGS_ABSTRACT = (1 << 5),
INTEROP_FLAGS_REQUIRE_SAME_USER = (1 << 6),
INTEROP_FLAGS_NONE = 0 INTEROP_FLAGS_NONE = 0
} InteropFlags; } InteropFlags;
@ -325,6 +326,8 @@ do_test_server_auth (InteropFlags flags)
if (flags & INTEROP_FLAGS_ANONYMOUS) if (flags & INTEROP_FLAGS_ANONYMOUS)
server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS;
if (flags & INTEROP_FLAGS_REQUIRE_SAME_USER)
server_flags |= G_DBUS_SERVER_FLAGS_AUTHENTICATION_REQUIRE_SAME_USER;
observer = g_dbus_auth_observer_new (); observer = g_dbus_auth_observer_new ();
@ -513,6 +516,12 @@ test_server_auth_external (void)
do_test_server_auth (INTEROP_FLAGS_EXTERNAL); do_test_server_auth (INTEROP_FLAGS_EXTERNAL);
} }
static void
test_server_auth_external_require_same_user (void)
{
do_test_server_auth (INTEROP_FLAGS_EXTERNAL | INTEROP_FLAGS_REQUIRE_SAME_USER);
}
static void static void
test_server_auth_sha1 (void) test_server_auth_sha1 (void)
{ {
@ -537,6 +546,7 @@ main (int argc,
g_test_add_func ("/gdbus/server-auth/anonymous", test_server_auth_anonymous); g_test_add_func ("/gdbus/server-auth/anonymous", test_server_auth_anonymous);
g_test_add_func ("/gdbus/server-auth/anonymous/tcp", test_server_auth_anonymous_tcp); g_test_add_func ("/gdbus/server-auth/anonymous/tcp", test_server_auth_anonymous_tcp);
g_test_add_func ("/gdbus/server-auth/external", test_server_auth_external); g_test_add_func ("/gdbus/server-auth/external", test_server_auth_external);
g_test_add_func ("/gdbus/server-auth/external/require-same-user", test_server_auth_external_require_same_user);
g_test_add_func ("/gdbus/server-auth/sha1", test_server_auth_sha1); g_test_add_func ("/gdbus/server-auth/sha1", test_server_auth_sha1);
g_test_add_func ("/gdbus/server-auth/sha1/tcp", test_server_auth_sha1_tcp); g_test_add_func ("/gdbus/server-auth/sha1/tcp", test_server_auth_sha1_tcp);