From 2a2fd1216b15efc6ef15ba4e49c0aa7b5969e6d7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 27 Apr 2015 14:54:32 -0400 Subject: [PATCH] settings: rework NMSecretAgent disconnection detection Have NMSecretAgent emit "disconnected" when it detects that it has been disconnected, rather than having both the agent and the agent manager monitor it separately. --- src/settings/nm-agent-manager.c | 42 +++++++--------------- src/settings/nm-secret-agent.c | 64 ++++++++++++++++++++++++++------- src/settings/nm-secret-agent.h | 4 +++ 3 files changed, 69 insertions(+), 41 deletions(-) diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index 0293d783d..eb0073be0 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -50,7 +50,6 @@ G_DEFINE_TYPE (NMAgentManager, nm_agent_manager, NM_TYPE_EXPORTED_OBJECT) NMAgentManagerPrivate)) typedef struct { - NMDBusManager *dbus_mgr; NMAuthManager *auth_mgr; /* Auth chains for checking agent permissions */ @@ -263,6 +262,14 @@ find_agent_by_identifier_and_uid (NMAgentManager *self, return NULL; } +static void +agent_disconnected_cb (NMSecretAgent *agent, gpointer user_data) +{ + /* The agent quit, so remove it and let interested clients know */ + remove_agent (NM_AGENT_MANAGER (user_data), + nm_secret_agent_get_dbus_owner (agent)); +} + static void impl_agent_manager_register_with_capabilities (NMAgentManager *self, const char *identifier, @@ -305,6 +312,8 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self, "Failed to initialize the agent"); goto done; } + g_signal_connect (agent, NM_SECRET_AGENT_DISCONNECTED, + G_CALLBACK (agent_disconnected_cb), self); nm_log_dbg (LOGD_AGENTS, "(%s) requesting permissions", nm_secret_agent_get_description (agent)); @@ -343,11 +352,10 @@ static void impl_agent_manager_unregister (NMAgentManager *self, DBusGMethodInvocation *context) { - NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self); GError *error = NULL; char *sender = NULL; - if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, + if (!nm_dbus_manager_get_caller_info (nm_dbus_manager_get (), context, &sender, NULL, @@ -1450,19 +1458,6 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager, /*************************************************************/ -static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - if (old_owner) { - /* The agent quit, so remove it and let interested clients know */ - remove_agent (NM_AGENT_MANAGER (user_data), old_owner); - } -} - static void agent_permissions_changed_done (NMAuthChain *chain, GError *error, @@ -1550,16 +1545,10 @@ constructed (GObject *object) G_OBJECT_CLASS (nm_agent_manager_parent_class)->constructed (object); - priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ()); priv->auth_mgr = g_object_ref (nm_auth_manager_get ()); nm_exported_object_export (NM_EXPORTED_OBJECT (object)); - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - object); - g_signal_connect (priv->auth_mgr, NM_AUTH_MANAGER_SIGNAL_CHANGED, G_CALLBACK (authority_changed_cb), @@ -1589,13 +1578,8 @@ dispose (GObject *object) object); g_clear_object (&priv->auth_mgr); } - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, - G_CALLBACK (name_owner_changed_cb), - object); - nm_exported_object_unexport (NM_EXPORTED_OBJECT (object)); - g_clear_object (&priv->dbus_mgr); - } + + nm_exported_object_unexport (NM_EXPORTED_OBJECT (object)); G_OBJECT_CLASS (nm_agent_manager_parent_class)->dispose (object); } diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index be21f16a7..e1355a76c 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -47,17 +47,24 @@ typedef struct { NMAuthSubject *subject; char *identifier; char *owner_username; + char *dbus_owner; NMSecretAgentCapabilities capabilities; guint32 hash; GSList *permissions; DBusGProxy *proxy; - guint proxy_destroy_id; GHashTable *requests; } NMSecretAgentPrivate; +enum { + DISCONNECTED, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + /*************************************************************/ typedef struct { @@ -107,7 +114,7 @@ nm_secret_agent_get_description (NMSecretAgent *agent) priv = NM_SECRET_AGENT_GET_PRIVATE (agent); if (!priv->description) { priv->description = g_strdup_printf ("%s/%s/%lu", - nm_auth_subject_get_unix_process_dbus_sender (priv->subject), + priv->dbus_owner, priv->identifier, nm_auth_subject_get_unix_process_uid (priv->subject)); } @@ -120,7 +127,7 @@ nm_secret_agent_get_dbus_owner (NMSecretAgent *agent) { g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL); - return nm_auth_subject_get_unix_process_dbus_sender (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject); + return NM_SECRET_AGENT_GET_PRIVATE (agent)->dbus_owner; } const char * @@ -450,15 +457,35 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self, callback_data); } +static void proxy_cleanup (NMSecretAgent *self); + +static void +name_owner_changed_cb (NMDBusManager *dbus_mgr, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMSecretAgent *self = NM_SECRET_AGENT (user_data); + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + + if (!new_owner && !g_strcmp0 (old_owner, priv->dbus_owner)) + proxy_cleanup (self); +} + static void proxy_cleanup (NMSecretAgent *self) { NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); if (priv->proxy) { - g_signal_handler_disconnect (priv->proxy, priv->proxy_destroy_id); - priv->proxy_destroy_id = 0; + g_signal_handlers_disconnect_by_func (priv->proxy, proxy_cleanup, self); g_clear_object (&priv->proxy); + + g_signal_handlers_disconnect_by_func (nm_dbus_manager_get (), name_owner_changed_cb, self); + g_clear_pointer (&priv->dbus_owner, g_free); + + g_signal_emit (self, signals[DISCONNECTED], 0); } } @@ -472,7 +499,7 @@ nm_secret_agent_new (DBusGMethodInvocation *context, { NMSecretAgent *self; NMSecretAgentPrivate *priv; - char *hash_str, *username; + char *hash_str; struct passwd *pw; g_return_val_if_fail (context != NULL, NULL); @@ -483,13 +510,13 @@ nm_secret_agent_new (DBusGMethodInvocation *context, pw = getpwuid (nm_auth_subject_get_unix_process_uid (subject)); g_return_val_if_fail (pw != NULL, NULL); g_return_val_if_fail (pw->pw_name[0] != '\0', NULL); - username = g_strdup (pw->pw_name); self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL); priv = NM_SECRET_AGENT_GET_PRIVATE (self); priv->identifier = g_strdup (identifier); - priv->owner_username = g_strdup (username); + priv->owner_username = g_strdup (pw->pw_name); + priv->dbus_owner = g_strdup (nm_auth_subject_get_unix_process_dbus_sender (subject)); priv->capabilities = capabilities; priv->subject = g_object_ref (subject); @@ -499,14 +526,17 @@ nm_secret_agent_new (DBusGMethodInvocation *context, priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (), context, - nm_auth_subject_get_unix_process_dbus_sender (subject), + priv->dbus_owner, NM_DBUS_PATH_SECRET_AGENT, NM_DBUS_INTERFACE_SECRET_AGENT); g_assert (priv->proxy); - priv->proxy_destroy_id = g_signal_connect_swapped (priv->proxy, "destroy", - G_CALLBACK (proxy_cleanup), self); + g_signal_connect_swapped (priv->proxy, "destroy", + G_CALLBACK (proxy_cleanup), self); + g_signal_connect (nm_dbus_manager_get (), + NM_DBUS_MANAGER_NAME_OWNER_CHANGED, + G_CALLBACK (name_owner_changed_cb), + self); - g_free (username); return self; } @@ -555,5 +585,15 @@ nm_secret_agent_class_init (NMSecretAgentClass *config_class) /* virtual methods */ object_class->dispose = dispose; object_class->finalize = finalize; + + /* signals */ + signals[DISCONNECTED] = + g_signal_new (NM_SECRET_AGENT_DISCONNECTED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSecretAgentClass, disconnected), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } diff --git a/src/settings/nm-secret-agent.h b/src/settings/nm-secret-agent.h index ed49f9357..d8712c59e 100644 --- a/src/settings/nm-secret-agent.h +++ b/src/settings/nm-secret-agent.h @@ -33,12 +33,16 @@ #define NM_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT)) #define NM_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentClass)) +#define NM_SECRET_AGENT_DISCONNECTED "disconnected" + struct _NMSecretAgent { GObject parent; }; typedef struct { GObjectClass parent; + + void (*disconnected) (NMSecretAgent *self); } NMSecretAgentClass; GType nm_secret_agent_get_type (void);