settings: implement deleting secrets from agents when connection is deleted
This commit is contained in:
@@ -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>
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user