From 51bc2c02242ead7659c417cfa2336a231ac4ea24 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 6 Dec 2019 11:48:04 +0100 Subject: [PATCH] libnm: track permissions in NMClient as an array of well known permissions On D-Bus, the permission names are just the PolicyKit action names, like "org.freedesktop.NetworkManager.wifi.scan". But NMClient already ignores all strings that it doesn't know at compile time and only keeps track of well known permission. And neither does the API nm_client_get_permissions_result() allow to expose permissions unknown to libnm. Maybe the API of NMClient should be more generic and allow exposing any permissions announced by NetworkManager. As it is however, it's not necessary to track the permissions in a hash table. An array with fixed indices is sufficient. --- libnm/nm-client.c | 80 ++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 42cba4095d..b10456e274 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -278,7 +278,7 @@ typedef struct { NMLDBusObject *dbobj_settings; NMLDBusObject *dbobj_dns_manager; - GHashTable *permissions; + guint8 *permissions; GCancellable *permissions_cancellable; char *name_owner; @@ -3311,27 +3311,35 @@ _dbus_nm_vpn_connection_state_changed_cb (GDBusConnection *connection, static void _emit_permissions_changed (NMClient *self, - GHashTable *permissions, - gboolean force_unknown) + const guint8 *old_permissions, + const guint8 *permissions) { - GHashTableIter iter; - gpointer key; - gpointer value; + int i; - if (!permissions) - return; if (self->obj_base.is_disposing) return; - g_hash_table_iter_init (&iter, permissions); - while (g_hash_table_iter_next (&iter, &key, &value)) { + if (old_permissions == permissions) + return; + + for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) { + NMClientPermission perm = nm_auth_permission_sorted[i]; + NMClientPermissionResult perm_result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; + NMClientPermissionResult perm_result_old = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; + + if (permissions) + perm_result = permissions[perm - 1]; + if (old_permissions) + perm_result_old = old_permissions[perm - 1]; + + if (perm_result == perm_result_old) + continue; + g_signal_emit (self, signals[PERMISSION_CHANGED], 0, - GPOINTER_TO_UINT (key), - force_unknown - ? (guint) NM_CLIENT_PERMISSION_NONE - : GPOINTER_TO_UINT (value)); + (guint) perm, + (guint) perm_result); } } @@ -3344,10 +3352,11 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe NMClientPrivate *priv; gs_unref_variant GVariant *ret = NULL; nm_auto_free_variant_iter GVariantIter *v_permissions = NULL; - gs_unref_hashtable GHashTable *old_permissions = NULL; + gs_free guint8 *old_permissions = NULL; gs_free_error GError *error = NULL; const char *pkey; const char *pvalue; + int i; ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error); if ( !ret @@ -3366,9 +3375,10 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe NML_NMCLIENT_LOG_T (self, "GetPermissions call finished with success"); - /* get list of old permissions for change notification */ old_permissions = g_steal_pointer (&priv->permissions); - priv->permissions = g_hash_table_new (nm_direct_hash, NULL); + priv->permissions = g_new (guint8, G_N_ELEMENTS (nm_auth_permission_sorted)); + for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) + priv->permissions[i] = NM_CLIENT_PERMISSION_NONE; g_variant_get (ret, "(a{ss})", &v_permissions); while (g_variant_iter_next (v_permissions, "{&s&s}", &pkey, &pvalue)) { @@ -3380,19 +3390,11 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe continue; perm_result = nm_client_permission_result_from_string (pvalue); - - g_hash_table_insert (priv->permissions, - GUINT_TO_POINTER (perm), - GUINT_TO_POINTER (perm_result)); - if (old_permissions) { - g_hash_table_remove (old_permissions, - GUINT_TO_POINTER (perm)); - } + priv->permissions[perm - 1] = perm_result; } dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context); - _emit_permissions_changed (self, priv->permissions, FALSE); - _emit_permissions_changed (self, old_permissions, TRUE); + _emit_permissions_changed (self, old_permissions, priv->permissions); } static void @@ -4271,18 +4273,18 @@ NMClientPermissionResult nm_client_get_permission_result (NMClient *client, NMClientPermission permission) { NMClientPrivate *priv; - gpointer result; + NMClientPermissionResult result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN; g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN); - priv = NM_CLIENT_GET_PRIVATE (client); - if ( !priv->permissions - || !g_hash_table_lookup_extended (priv->permissions, - GUINT_TO_POINTER (permission), - NULL, - &result)) - return NM_CLIENT_PERMISSION_RESULT_UNKNOWN; - return GPOINTER_TO_UINT (result); + if ( permission > NM_CLIENT_PERMISSION_NONE + && permission <= NM_CLIENT_PERMISSION_LAST) { + priv = NM_CLIENT_GET_PRIVATE (client); + if (priv->permissions) + result = priv->permissions[permission - 1]; + } + + return result; } /** @@ -6553,9 +6555,9 @@ _init_release_all (NMClient *self) &priv->dbsid_nm_check_permissions); if (priv->permissions) { - gs_unref_hashtable GHashTable *old_permissions = g_steal_pointer (&priv->permissions); + gs_free guint8 *old_permissions = g_steal_pointer (&priv->permissions); - _emit_permissions_changed (self, old_permissions, TRUE); + _emit_permissions_changed (self, old_permissions, NULL); } nm_assert (c_list_is_empty (&priv->obj_changed_lst_head)); @@ -7372,7 +7374,7 @@ dispose (GObject *object) nm_clear_pointer (&priv->dbus_context, g_main_context_unref); nm_clear_pointer (&priv->main_context, g_main_context_unref); - nm_clear_pointer (&priv->permissions, g_hash_table_unref); + nm_clear_g_free (&priv->permissions); g_clear_object (&priv->dbus_connection);