diff --git a/introspection/nm-secret-agent.xml b/introspection/nm-secret-agent.xml index 655b2b72f2..8a651dd66c 100644 --- a/introspection/nm-secret-agent.xml +++ b/introspection/nm-secret-agent.xml @@ -137,8 +137,8 @@ - Nested settings maps containing the entire connection - (including secrets), for which the agent should delete the + Nested settings maps containing the connection properties + (sans secrets), for which the agent should delete the secrets from backing storage. diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c index c3a303bb46..d8ac0493ff 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/settings/nm-agent-manager.c @@ -411,12 +411,12 @@ request_new_get (NMConnection *connection, } static Request * -request_new_save (NMConnection *connection, - gboolean filter_by_uid, - gulong uid_filter, - RequestCompleteFunc complete_callback, - gpointer complete_callback_data, - RequestNextFunc next_callback) +request_new_other (NMConnection *connection, + gboolean filter_by_uid, + gulong uid_filter, + RequestCompleteFunc complete_callback, + gpointer complete_callback_data, + RequestNextFunc next_callback) { Request *req; @@ -600,6 +600,17 @@ next_generic (Request *req, const char *detail) return success; } +static gboolean +start_generic (gpointer user_data) +{ + Request *req = user_data; + + req->idle_id = 0; + req->next_callback (req); + return FALSE; +} + + /*************************************************************/ static void @@ -881,16 +892,6 @@ save_complete_cb (Request *req, g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->reqid)); } -static gboolean -save_start (gpointer user_data) -{ - Request *req = user_data; - - req->idle_id = 0; - req->next_callback (req); - return FALSE; -} - guint32 nm_agent_manager_save_secrets (NMAgentManager *self, NMConnection *connection, @@ -908,17 +909,111 @@ nm_agent_manager_save_secrets (NMAgentManager *self, "Saving secrets for connection %s", nm_connection_get_path (connection)); - req = request_new_save (connection, - filter_by_uid, - uid_filter, - save_complete_cb, - self, - save_next_cb); + req = request_new_other (connection, + filter_by_uid, + uid_filter, + save_complete_cb, + self, + save_next_cb); g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req); /* Kick off the request */ request_add_agents (self, req); - req->idle_id = g_idle_add (save_start, req); + req->idle_id = g_idle_add (start_generic, req); + + return req->reqid; +} + +/*************************************************************/ + +static void +delete_done_cb (NMSecretAgent *agent, + gconstpointer call_id, + GHashTable *secrets, + GError *error, + gpointer user_data) +{ + Request *req = user_data; + + g_return_if_fail (call_id == req->current_call_id); + + req->current = NULL; + req->current_call_id = NULL; + + if (error) { + nm_log_dbg (LOGD_AGENTS, "(%s) agent failed delete secrets request %p/%s: (%d) %s", + nm_secret_agent_get_description (agent), + req, req->setting_name, + error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + } else { + nm_log_dbg (LOGD_AGENTS, "(%s) agent deleted secrets for request %p/%s", + nm_secret_agent_get_description (agent), + req, req->setting_name); + } + + /* Tell the next agent to delete secrets */ + req->next_callback (req); +} + +static void +delete_next_cb (Request *req) +{ + if (!next_generic (req, "deleting")) + return; + + req->current_call_id = nm_secret_agent_delete_secrets (NM_SECRET_AGENT (req->current), + req->connection, + delete_done_cb, + req); + if (req->current_call_id == NULL) { + /* Shouldn't hit this, but handle it anyway */ + g_warn_if_fail (req->current_call_id != NULL); + req->current = NULL; + req->next_callback (req); + } +} + +static void +delete_complete_cb (Request *req, + GHashTable *secrets, + GError *error, + gpointer user_data) +{ + NMAgentManager *self = NM_AGENT_MANAGER (user_data); + NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self); + + g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->reqid)); +} + +guint32 +nm_agent_manager_delete_secrets (NMAgentManager *self, + NMConnection *connection, + gboolean filter_by_uid, + gulong uid_filter) +{ + NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self); + Request *req; + + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (connection != NULL, 0); + g_return_val_if_fail (NM_IS_CONNECTION (connection), 0); + + nm_log_dbg (LOGD_SETTINGS, + "Deleting secrets for connection %s", + nm_connection_get_path (connection)); + + req = request_new_other (connection, + filter_by_uid, + uid_filter, + delete_complete_cb, + self, + delete_next_cb); + g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req); + + /* Kick off the request */ + request_add_agents (self, req); + req->idle_id = g_idle_add (start_generic, req); return req->reqid; } diff --git a/src/settings/nm-agent-manager.h b/src/settings/nm-agent-manager.h index 9b028aa956..2c34b4f099 100644 --- a/src/settings/nm-agent-manager.h +++ b/src/settings/nm-agent-manager.h @@ -74,4 +74,9 @@ guint32 nm_agent_manager_save_secrets (NMAgentManager *manager, gboolean filter_by_uid, gulong uid_filter); +guint32 nm_agent_manager_delete_secrets (NMAgentManager *manager, + NMConnection *connection, + gboolean filter_by_uid, + gulong uid_filter); + #endif /* NM_AGENT_MANAGER_H */ diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index f63b637997..1a995f9715 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -234,9 +234,9 @@ nm_secret_agent_cancel_secrets (NMSecretAgent *self, gconstpointer call) /*************************************************************/ static void -save_callback (DBusGProxy *proxy, - DBusGProxyCall *call, - void *user_data) +agent_save_delete_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + void *user_data) { Request *r = user_data; NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent); @@ -250,38 +250,71 @@ save_callback (DBusGProxy *proxy, g_hash_table_remove (priv->requests, call); } +static gpointer +agent_new_save_delete (NMSecretAgent *self, + NMConnection *connection, + NMSettingHashFlags hash_flags, + const char *method, + NMSecretAgentCallback callback, + gpointer callback_data) +{ + NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); + GHashTable *hash; + Request *r; + const char *cpath = nm_connection_get_path (connection); + + hash = nm_connection_to_hash (connection, hash_flags); + + r = request_new (self, cpath, NULL, callback, callback_data); + r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, + method, + agent_save_delete_cb, + r, + NULL, + 10000, /* 10 seconds */ + DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, + DBUS_TYPE_G_OBJECT_PATH, cpath, + G_TYPE_INVALID); + g_hash_table_insert (priv->requests, r->call, r); + + g_hash_table_destroy (hash); + return r->call; +} + gconstpointer nm_secret_agent_save_secrets (NMSecretAgent *self, NMConnection *connection, NMSecretAgentCallback callback, gpointer callback_data) { - NMSecretAgentPrivate *priv; - Request *r; - GHashTable *hash; - g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); - priv = NM_SECRET_AGENT_GET_PRIVATE (self); - /* Caller should have ensured that only agent-owned secrets exist in 'connection' */ - hash = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL); + return agent_new_save_delete (self, + connection, + NM_SETTING_HASH_FLAG_ALL, + "SaveSecrets", + callback, + callback_data); +} - r = request_new (self, nm_connection_get_path (connection), NULL, callback, callback_data); - r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy, - "SaveSecrets", - save_callback, - r, - NULL, - 10000, /* 10 seconds */ - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash, - DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection), - G_TYPE_INVALID); - g_hash_table_insert (priv->requests, r->call, r); +gconstpointer +nm_secret_agent_delete_secrets (NMSecretAgent *self, + NMConnection *connection, + NMSecretAgentCallback callback, + gpointer callback_data) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); - g_hash_table_destroy (hash); - return r->call; + /* No secrets sent; agents must be smart enough to track secrets using the UUID or something */ + return agent_new_save_delete (self, + connection, + NM_SETTING_HASH_FLAG_NO_SECRETS, + "DeleteSecrets", + callback, + callback_data); } /*************************************************************/ diff --git a/src/settings/nm-secret-agent.h b/src/settings/nm-secret-agent.h index 6387d1760c..676a370b66 100644 --- a/src/settings/nm-secret-agent.h +++ b/src/settings/nm-secret-agent.h @@ -83,4 +83,9 @@ gconstpointer nm_secret_agent_save_secrets (NMSecretAgent *agent, NMSecretAgentCallback callback, gpointer callback_data); +gconstpointer nm_secret_agent_delete_secrets (NMSecretAgent *agent, + NMConnection *connection, + NMSecretAgentCallback callback, + gpointer callback_data); + #endif /* NM_SECRET_AGENT_H */ diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index a0cbbab21d..f7c9d6c0a1 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -326,8 +326,18 @@ do_delete (NMSettingsConnection *connection, NMSettingsConnectionDeleteFunc callback, gpointer user_data) { + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection); + NMConnection *for_agents; + g_object_ref (connection); set_visible (connection, FALSE); + + /* Tell agents to remove secrets for this connection */ + for_agents = nm_connection_duplicate (NM_CONNECTION (connection)); + nm_connection_clear_secrets (for_agents); + nm_agent_manager_delete_secrets (priv->agent_mgr, for_agents, FALSE, 0); + + /* Signal the connection is removed and deleted */ g_signal_emit (connection, signals[REMOVED], 0); callback (connection, NULL, user_data); g_object_unref (connection);