From 4e409d6626737f0e668d86dd233ed105fd2f44fa Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 17 Jul 2017 15:14:02 -0400 Subject: libgdm: add api for getting at ChoiceList interface This provides gnome-shell with a way to use the new interface. https://bugzilla.gnome.org/show_bug.cgi?id=788851 --- libgdm/gdm-client.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++- libgdm/gdm-client.h | 4 + 2 files changed, 218 insertions(+), 2 deletions(-) (limited to 'libgdm') diff --git a/libgdm/gdm-client.c b/libgdm/gdm-client.c index 1f428915..6fd55bd0 100644 --- a/libgdm/gdm-client.c +++ b/libgdm/gdm-client.c @@ -41,7 +41,10 @@ struct GdmClientPrivate { GdmManager *manager; + GdmUserVerifier *user_verifier; + GHashTable *user_verifier_extensions; + GdmGreeter *greeter; GdmRemoteGreeter *remote_greeter; GdmChooser *chooser; @@ -49,6 +52,7 @@ struct GdmClientPrivate char *address; GList *pending_opens; + char **enabled_extensions; }; static void gdm_client_class_init (GdmClientClass *klass); @@ -142,12 +146,128 @@ get_manager (GdmClient *client, result); } +static void +complete_user_verifier_proxy_operation (GdmClient *client, + GSimpleAsyncResult *operation_result) +{ + g_simple_async_result_complete_in_idle (operation_result); + g_object_unref (operation_result); +} + +static void +maybe_complete_user_verifier_proxy_operation (GdmClient *client, + GSimpleAsyncResult *operation_result) +{ + GHashTableIter iter; + gpointer key, value; + + if (client->priv->user_verifier_extensions != NULL) { + g_hash_table_iter_init (&iter, client->priv->user_verifier_extensions); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (value == NULL) + return; + } + } + + complete_user_verifier_proxy_operation (client, operation_result); +} + +static void +on_user_verifier_choice_list_proxy_created (GObject *source, + GAsyncResult *result, + GSimpleAsyncResult *operation_result) +{ + GdmClient *client; + GdmUserVerifierChoiceList *choice_list; + GError *error = NULL; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result))); + + choice_list = gdm_user_verifier_choice_list_proxy_new_finish (result, &error); + + if (choice_list == NULL) { + g_debug ("Couldn't create UserVerifier ChoiceList proxy: %s", error->message); + g_clear_error (&error); + g_hash_table_remove (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name); + } else { + g_hash_table_replace (client->priv->user_verifier_extensions, gdm_user_verifier_choice_list_interface_info ()->name, choice_list); + } + + maybe_complete_user_verifier_proxy_operation (client, operation_result); +} + +static void +on_user_verifier_extensions_enabled (GdmUserVerifier *user_verifier, + GAsyncResult *result, + GSimpleAsyncResult *operation_result) +{ + GdmClient *client; + GCancellable *cancellable; + GDBusConnection *connection; + GError *error = NULL; + size_t i; + + client = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result))); + cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable"); + + gdm_user_verifier_call_enable_extensions_finish (user_verifier, result, &error); + + if (error != NULL) { + g_debug ("Couldn't enable user verifier extensions: %s", + error->message); + g_clear_error (&error); + complete_user_verifier_proxy_operation (client, operation_result); + return; + } + + connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (user_verifier)); + + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + g_debug ("Enabled extensions[%lu] = %s", i, client->priv->enabled_extensions[i]); + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], NULL); + gdm_user_verifier_choice_list_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_choice_list_proxy_created, + operation_result); + } else { + g_debug ("User verifier extension %s is unsupported", client->priv->enabled_extensions[i]); + g_hash_table_remove (client->priv->user_verifier_extensions, + client->priv->enabled_extensions[i]); + } + } + + if (g_hash_table_size (client->priv->user_verifier_extensions) == 0) { + g_debug ("No supported user verifier extensions"); + complete_user_verifier_proxy_operation (client, operation_result); + } + +} + +static void +free_interface_skeleton (GDBusInterfaceSkeleton *interface) +{ + if (interface == NULL) + return; + + g_object_unref (interface); +} + static void on_user_verifier_proxy_created (GObject *source, GAsyncResult *result, GSimpleAsyncResult *operation_result) { + GdmClient *self; GdmUserVerifier *user_verifier; + GCancellable *cancellable = NULL; GError *error = NULL; user_verifier = gdm_user_verifier_proxy_new_finish (result, &error); @@ -164,8 +284,29 @@ on_user_verifier_proxy_created (GObject *source, user_verifier, (GDestroyNotify) g_object_unref); - g_simple_async_result_complete_in_idle (operation_result); - g_object_unref (operation_result); + + self = GDM_CLIENT (g_async_result_get_source_object (G_ASYNC_RESULT (operation_result))); + if (self->priv->enabled_extensions == NULL) { + g_debug ("no enabled extensions"); + g_simple_async_result_complete_in_idle (operation_result); + g_object_unref (operation_result); + return; + } + + self->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + cancellable = g_object_get_data (G_OBJECT (operation_result), "cancellable"); + gdm_user_verifier_call_enable_extensions (user_verifier, + (const char * const *) + self->priv->enabled_extensions, + cancellable, + (GAsyncReadyCallback) + on_user_verifier_extensions_enabled, + operation_result); + } static void @@ -688,6 +829,39 @@ gdm_client_get_user_verifier_sync (GdmClient *client, (GWeakNotify) g_clear_object, &client->priv->connection); + + if (client->priv->enabled_extensions != NULL) { + gboolean res; + + client->priv->user_verifier_extensions = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + (GDestroyNotify) + free_interface_skeleton); + res = gdm_user_verifier_call_enable_extensions_sync (client->priv->user_verifier, + (const char * const *) + client->priv->enabled_extensions, + cancellable, + NULL); + + if (res) { + size_t i; + for (i = 0; client->priv->enabled_extensions[i] != NULL; i++) { + if (strcmp (client->priv->enabled_extensions[i], + gdm_user_verifier_choice_list_interface_info ()->name) == 0) { + GdmUserVerifierChoiceList *choice_list_interface; + choice_list_interface = gdm_user_verifier_choice_list_proxy_new_sync (client->priv->connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + SESSION_DBUS_PATH, + cancellable, + NULL); + if (choice_list_interface != NULL) + g_hash_table_insert (client->priv->user_verifier_extensions, client->priv->enabled_extensions[i], choice_list_interface); + } + } + } + } } return client->priv->user_verifier; @@ -815,6 +989,26 @@ gdm_client_get_user_verifier_finish (GdmClient *client, return g_object_ref (user_verifier); } +/** + * gdm_client_get_user_verifier_choice_list: + * @client: a #GdmClient + * + * Gets a #GdmUserVerifierChoiceList object that can be used to + * verify a user's local account. + * + * Returns: (transfer none): #GdmUserVerifierChoiceList or %NULL if user + * verifier isn't yet fetched, or daemon doesn't support choice lists + */ +GdmUserVerifierChoiceList * +gdm_client_get_user_verifier_choice_list (GdmClient *client) +{ + if (client->priv->user_verifier_extensions == NULL) + return NULL; + + return g_hash_table_lookup (client->priv->user_verifier_extensions, + gdm_user_verifier_choice_list_interface_info ()->name); +} + static void on_timed_login_details_got (GdmGreeter *greeter, GAsyncResult *result) @@ -1483,6 +1677,7 @@ gdm_client_finalize (GObject *object) g_clear_object (&client->priv->manager); g_clear_object (&client->priv->connection); + g_strfreev (client->priv->enabled_extensions); g_free (client->priv->address); G_OBJECT_CLASS (gdm_client_parent_class)->finalize (object); @@ -1501,3 +1696,20 @@ gdm_client_new (void) return GDM_CLIENT (client_object); } + + +/** + * gdm_client_set_enabled_extensions: + * @client: a #GdmClient + * @extensions: (array zero-terminated=1) (element-type utf8): a list of extensions + * + * Enables GDM's pam extensions. Currently, only + * org.gnome.DisplayManager.UserVerifier.ChoiceList is supported. + */ +void +gdm_client_set_enabled_extensions (GdmClient *client, + const char * const *extensions) +{ + client->priv->enabled_extensions = g_strdupv ((char **) extensions); + +} diff --git a/libgdm/gdm-client.h b/libgdm/gdm-client.h index cbe2b389..1ae3d39e 100644 --- a/libgdm/gdm-client.h +++ b/libgdm/gdm-client.h @@ -58,6 +58,8 @@ GType gdm_client_get_type (void); GQuark gdm_client_error_quark (void); GdmClient *gdm_client_new (void); +void gdm_client_set_enabled_extensions (GdmClient *client, + const char * const * extensions); void gdm_client_open_reauthentication_channel (GdmClient *client, const char *username, @@ -85,6 +87,8 @@ GdmUserVerifier *gdm_client_get_user_verifier_sync (GdmClient *client, GCancellable *cancellable, GError **error); +GdmUserVerifierChoiceList *gdm_client_get_user_verifier_choice_list (GdmClient *client); + void gdm_client_get_greeter (GdmClient *client, GCancellable *cancellable, GAsyncReadyCallback callback, -- cgit v1.2.1