settings: implement deleting secrets from agents when connection is deleted

This commit is contained in:
Dan Williams
2011-01-31 23:33:46 -06:00
parent 393bcf8d12
commit 570c0eb2df
6 changed files with 196 additions and 48 deletions

View File

@@ -137,8 +137,8 @@
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection" type="a{sa{sv}}" direction="in" tp:type="String_String_Variant_Map_Map">
<tp:docstring>
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.
</tp:docstring>
</arg>

View File

@@ -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;
}

View File

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

View File

@@ -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);
}
/*************************************************************/

View File

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

View File

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