Submitted By: Douglas R. Reno Date: 2019-12-09 Initial Package Version: 1.5.21 Upstream Status: Applied Origin: Upstream / Self Description: Fixes a security problem with chinese and taiwanese keyboard layouts that could allow another person on the machine to read the keystrokes from another user in a GNOME or KDE Plasma session. Also adapts to glib-2.62.3 and above, fixing a regression with GDBus authentication. The security problem is identified as CVE-2019-14822. diff -Naurp ibus-1.5.21.orig/bus/server.c ibus-1.5.21/bus/server.c --- ibus-1.5.21.orig/bus/server.c 2019-08-23 06:08:34.000000000 -0500 +++ ibus-1.5.21/bus/server.c 2019-10-16 16:50:39.882092214 -0500 @@ -70,16 +70,63 @@ _restart_server (void) } /** + * bus_allow_mechanism_cb: + * @observer: A GDBusAuthObserver + * @mechanism: The name of the mechanism. + * @user_data: always %NULL + * + * Check if @mechanism can be used to authenticate the other peer. + * Returns: %TRUE if the peer's mechanism is allowed. + */ +static gboolean +bus_allow_mechanism_cb(GDBusAuthObserver *observer, + const gchar *mechanism, + G_GNUC_UNUSED gpointer user_data) +{ + if (g_strcmp0 (mechanism, "EXTERNAL") == 0) + return TRUE; + return FALSE; +} + +/** + * bus_authorize_authenticated_peer_cb: + * @observer: A GDBusAuthObserver + * @stream: A GIOStream + * @credentials: A GCredentials + * @user_data: always %NULL. + * + * Check is a peer who has already authenticated should be authorized. + * Returns: %TRUE if the peer's credential is authorized. + */ +static gboolean +bus_authorize_authenticated_peer_cb (GDBusAuthObserver *observer, + GIOStream *stream, + GCredentials *credentials, + G_GNUC_UNUSED gpointer user_data) +{ + gboolean authorized = FALSE; + if (credentials) { + GCredentials *own_credentials = g_credentials_new (); + if (g_credentials_is_same_user (credentials, own_credentials, NULL)) + authorized = TRUE; + g_object_unref (own_credentials); + } + return authorized; +} + +/** * bus_new_connection_cb: - * @user_data: always NULL. - * @returns: TRUE when the function can handle the connection. + * @observer: A GDBusAuthObserver + * @dbus_connection: A GDbusConnection + * @user_data: always %NULL. * * Handle incoming connections. + * Returns: %TRUE when the function can handle the connection. */ static gboolean -bus_new_connection_cb (GDBusServer *server, - GDBusConnection *dbus_connection, - gpointer user_data) +bus_new_connection_cb (GDBusServer *server, + GDBusConnection *dbus_connection, + G_GNUC_UNUSED gpointer user_data) { BusConnection *connection = bus_connection_new (dbus_connection); bus_dbus_impl_new_connection (dbus, connection); @@ -94,9 +141,9 @@ bus_new_connection_cb (GDBusServer * } static void -_server_connect_start_portal_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) +_server_connect_start_portal_cb (GObject *source_object, + GAsyncResult *res, + G_GNUC_UNUSED gpointer user_data) { GVariant *result; GError *error = NULL; @@ -113,9 +160,9 @@ _server_connect_start_portal_cb (GObject } static void -bus_acquired_handler (GDBusConnection *connection, - const gchar *name, - gpointer user_data) +bus_acquired_handler (GDBusConnection *connection, + const gchar *name, + G_GNUC_UNUSED gpointer user_data) { g_dbus_connection_call (connection, IBUS_SERVICE_PORTAL, @@ -136,14 +183,17 @@ void bus_server_init (void) { GError *error = NULL; + GDBusServerFlags flags = G_DBUS_SERVER_FLAGS_NONE; + gchar *guid; + GDBusAuthObserver *observer; dbus = bus_dbus_impl_get_default (); ibus = bus_ibus_impl_get_default (); bus_dbus_impl_register_object (dbus, (IBusService *)ibus); /* init server */ - GDBusServerFlags flags = G_DBUS_SERVER_FLAGS_AUTHENTICATION_ALLOW_ANONYMOUS; - gchar *guid = g_dbus_generate_guid (); + guid = g_dbus_generate_guid (); + observer = g_dbus_auth_observer_new (); if (!g_str_has_prefix (g_address, "unix:tmpdir=") && !g_str_has_prefix (g_address, "unix:path=")) { g_error ("Your socket address does not have the format unix:tmpdir=$DIR " @@ -152,7 +202,7 @@ bus_server_init (void) server = g_dbus_server_new_sync ( g_address, /* the place where the socket file lives, e.g. /tmp, abstract namespace, etc. */ flags, guid, - NULL /* observer */, + observer, NULL /* cancellable */, &error); if (server == NULL) { @@ -162,7 +212,13 @@ bus_server_init (void) } g_free (guid); - g_signal_connect (server, "new-connection", G_CALLBACK (bus_new_connection_cb), NULL); + g_signal_connect (observer, "allow-mechanism", + G_CALLBACK (bus_allow_mechanism_cb), NULL); + g_signal_connect (observer, "authorize-authenticated-peer", + G_CALLBACK (bus_authorize_authenticated_peer_cb), NULL); + g_object_unref (observer); + g_signal_connect (server, "new-connection", + G_CALLBACK (bus_new_connection_cb), NULL); g_dbus_server_start (server);