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 */