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);