From a2f36e8bd4afd52c3fa3831b7f843633fc08f8fa Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 18 Jan 2011 13:19:29 -0600 Subject: [PATCH] agent: add CancelGetSecrets D-Bus API Allows NM to signal to an agent that an in-progress secrets request is no longer needed. This could happen if the device for which the request was started was removed, disabled, or the network being connected to changed, or whatever. --- introspection/nm-secret-agent.xml | 21 +++++ src/nm-agent-manager.c | 27 ++---- src/nm-secret-agent.c | 148 +++++++++++++++++++++++------- src/nm-secret-agent.h | 14 ++- 4 files changed, 155 insertions(+), 55 deletions(-) diff --git a/introspection/nm-secret-agent.xml b/introspection/nm-secret-agent.xml index ec1ac687bd..9ac6950faf 100644 --- a/introspection/nm-secret-agent.xml +++ b/introspection/nm-secret-agent.xml @@ -59,6 +59,27 @@ + + + Cancel a pending GetSecrets request for secrets of the given + connection. Any matching request should be canceled. + + + + + + Object path of the connection for which, if secrets are being + requested, the request should be canceled. + + + + + Setting name for which secrets for this connection were + originally being requested. + + + + Save given secrets to backing storage. diff --git a/src/nm-agent-manager.c b/src/nm-agent-manager.c index 3b62621100..ddefc877b8 100644 --- a/src/nm-agent-manager.c +++ b/src/nm-agent-manager.c @@ -336,7 +336,7 @@ struct _Request { /* Current agent being asked for secrets */ NMSecretAgent *current; - gpointer current_call_id; + gconstpointer current_call_id; /* Stores the sorted list of NMSecretAgents which will be * asked for secrets. @@ -462,25 +462,21 @@ merge_secrets (GHashTable *src, GHashTable *dest) } static void -request_secrets_done_cb (DBusGProxy *proxy, - DBusGProxyCall *call_id, - void *user_data) +request_secrets_done_cb (NMSecretAgent *agent, + gconstpointer call_id, + GHashTable *secrets, + GError *error, + gpointer user_data) { Request *req = user_data; - GError *error = NULL; - GHashTable *secrets = NULL; - GHashTable *setting_secrets; - NMSecretAgent *agent = NM_SECRET_AGENT (req->current); + GHashTable *setting_secrets, *merged; - if (call_id != req->current_call_id) - return; + g_return_if_fail (call_id == req->current_call_id); req->current = NULL; req->current_call_id = NULL; - if (!dbus_g_proxy_end_call (proxy, call_id, &error, - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets, - G_TYPE_INVALID)) { + if (error) { nm_log_dbg (LOGD_AGENTS, "(%s) agent failed secrets request %p/%s: (%d) %s", nm_secret_agent_get_description (agent), req, req->setting_name, @@ -498,7 +494,6 @@ request_secrets_done_cb (DBusGProxy *proxy, nm_log_dbg (LOGD_AGENTS, "(%s) agent returned no secrets for request %p/%s", nm_secret_agent_get_description (agent), req, req->setting_name); - g_hash_table_destroy (secrets); /* Try the next agent */ request_next (req); @@ -513,8 +508,6 @@ request_secrets_done_cb (DBusGProxy *proxy, * with the ones from the secret agent. */ if (req->settings_secrets) { - GHashTable *merged; - merged = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_unref); /* Copy agent secrets first, then overwrite with settings secrets */ @@ -525,8 +518,6 @@ request_secrets_done_cb (DBusGProxy *proxy, g_hash_table_destroy (merged); } else req->complete_callback (req, secrets, NULL, req->complete_callback_data); - - g_hash_table_destroy (secrets); } static void diff --git a/src/nm-secret-agent.c b/src/nm-secret-agent.c index 7951c50659..e1755d26a6 100644 --- a/src/nm-secret-agent.c +++ b/src/nm-secret-agent.c @@ -45,10 +45,49 @@ typedef struct { NMDBusManager *dbus_mgr; DBusGProxy *proxy; + + GHashTable *requests; } NMSecretAgentPrivate; /*************************************************************/ +typedef struct { + NMSecretAgent *agent; + DBusGProxyCall *call; + char *path; + char *setting_name; + NMSecretAgentCallback callback; + gpointer callback_data; +} Request; + +static Request * +request_new (NMSecretAgent *agent, + const char *path, + const char *setting_name, + NMSecretAgentCallback callback, + gpointer callback_data) +{ + Request *r; + + r = g_slice_new0 (Request); + r->agent = agent; + r->path = g_strdup (path); + r->setting_name = g_strdup (setting_name); + r->callback = callback; + r->callback_data = callback_data; + return r; +} + +static void +request_free (Request *r) +{ + g_free (r->path); + g_free (r->setting_name); + g_slice_free (Request, r); +} + +/*************************************************************/ + const char * nm_secret_agent_get_description (NMSecretAgent *agent) { @@ -106,19 +145,41 @@ nm_secret_agent_get_hash (NMSecretAgent *agent) /*************************************************************/ -gpointer +static void +secrets_callback (DBusGProxy *proxy, + DBusGProxyCall *call, + void *user_data) +{ + Request *r = user_data; + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent); + GError *error = NULL; + GHashTable *secrets = NULL; + + g_return_if_fail (call == r->call); + + dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets, + G_TYPE_INVALID); + r->callback (r->agent, r, secrets, error, r->callback_data); + if (secrets) + g_hash_table_unref (secrets); + g_clear_error (&error); + g_hash_table_remove (priv->requests, call); +} + +gconstpointer nm_secret_agent_get_secrets (NMSecretAgent *self, NMConnection *connection, const char *setting_name, const char *hint, - gboolean request_new, - DBusGProxyCallNotify done_callback, - gpointer done_callback_data) + gboolean get_new, + NMSecretAgentCallback callback, + gpointer callback_data) { NMSecretAgentPrivate *priv; - DBusGProxyCall *call; GHashTable *hash; const char *hints[2] = { hint, NULL }; + Request *r; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); @@ -127,29 +188,46 @@ nm_secret_agent_get_secrets (NMSecretAgent *self, priv = NM_SECRET_AGENT_GET_PRIVATE (self); hash = nm_connection_to_hash (connection); - call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, - "GetSecrets", - done_callback, - done_callback_data, - NULL, - 120000, /* 120 seconds */ - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, - DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection), - G_TYPE_STRING, setting_name, - G_TYPE_STRV, hints, - G_TYPE_BOOLEAN, request_new, - G_TYPE_INVALID); - g_hash_table_destroy (hash); - return call; + r = request_new (self, nm_connection_get_path (connection), setting_name, callback, callback_data); + r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, + "GetSecrets", + secrets_callback, + r, + NULL, + 120000, /* 120 seconds */ + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, + DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection), + G_TYPE_STRING, setting_name, + G_TYPE_STRV, hints, + G_TYPE_BOOLEAN, get_new, + G_TYPE_INVALID); + g_hash_table_insert (priv->requests, r->call, r); + + g_hash_table_destroy (hash); + return r->call; } void -nm_secret_agent_cancel_secrets (NMSecretAgent *self, gpointer call_id) +nm_secret_agent_cancel_secrets (NMSecretAgent *self, gconstpointer call) { - g_return_if_fail (self != NULL); + NMSecretAgentPrivate *priv; + Request *r; - dbus_g_proxy_cancel_call (NM_SECRET_AGENT_GET_PRIVATE (self)->proxy, call_id); + g_return_if_fail (self != NULL); + priv = NM_SECRET_AGENT_GET_PRIVATE (self); + + r = g_hash_table_lookup (priv->requests, call); + g_return_if_fail (r != NULL); + + dbus_g_proxy_cancel_call (NM_SECRET_AGENT_GET_PRIVATE (self)->proxy, (gpointer) call); + + dbus_g_proxy_call_no_reply (priv->proxy, + "CancelGetSecrets", + G_TYPE_STRING, r->path, + G_TYPE_STRING, r->setting_name, + G_TYPE_INVALID); + g_hash_table_remove (priv->requests, call); } /*************************************************************/ @@ -162,15 +240,14 @@ nm_secret_agent_new (NMDBusManager *dbus_mgr, { NMSecretAgent *self; NMSecretAgentPrivate *priv; + DBusGConnection *bus; + char *hash_str; g_return_val_if_fail (owner != NULL, NULL); g_return_val_if_fail (identifier != NULL, NULL); self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL); if (self) { - DBusGConnection *bus; - char *hash_str; - priv = NM_SECRET_AGENT_GET_PRIVATE (self); priv->owner = g_strdup (owner); @@ -196,6 +273,10 @@ nm_secret_agent_new (NMDBusManager *dbus_mgr, static void nm_secret_agent_init (NMSecretAgent *self) { + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + + priv->requests = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) request_free); } static void @@ -203,16 +284,17 @@ dispose (GObject *object) { NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object); - if (priv->disposed) - return; - priv->disposed = TRUE; + if (!priv->disposed) { + priv->disposed = TRUE; - g_free (priv->description); - g_free (priv->owner); - g_free (priv->identifier); + g_free (priv->description); + g_free (priv->owner); + g_free (priv->identifier); - g_object_unref (priv->proxy); - g_object_unref (priv->dbus_mgr); + g_hash_table_destroy (priv->requests); + g_object_unref (priv->proxy); + g_object_unref (priv->dbus_mgr); + } G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object); } diff --git a/src/nm-secret-agent.h b/src/nm-secret-agent.h index 3aebf27f98..7241ecb920 100644 --- a/src/nm-secret-agent.h +++ b/src/nm-secret-agent.h @@ -61,15 +61,21 @@ uid_t nm_secret_agent_get_owner_uid (NMSecretAgent *agent); guint32 nm_secret_agent_get_hash (NMSecretAgent *agent); -gpointer nm_secret_agent_get_secrets (NMSecretAgent *agent, +typedef void (*NMSecretAgentCallback) (NMSecretAgent *agent, + gconstpointer call, + GHashTable *secrets, + GError *error, + gpointer user_data); + +gconstpointer nm_secret_agent_get_secrets (NMSecretAgent *agent, NMConnection *connection, const char *setting_name, const char *hint, gboolean request_new, - DBusGProxyCallNotify done_callback, - gpointer done_callback_data); + NMSecretAgentCallback callback, + gpointer callback_data); void nm_secret_agent_cancel_secrets (NMSecretAgent *agent, - gpointer call_id); + gconstpointer call_id); #endif /* NM_SECRET_AGENT_H */