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=""/>
|
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
|
||||||
<arg name="connection" type="a{sa{sv}}" direction="in" tp:type="String_String_Variant_Map_Map">
|
<arg name="connection" type="a{sa{sv}}" direction="in" tp:type="String_String_Variant_Map_Map">
|
||||||
<tp:docstring>
|
<tp:docstring>
|
||||||
Nested settings maps containing the entire connection
|
Nested settings maps containing the connection properties
|
||||||
(including secrets), for which the agent should delete the
|
(sans secrets), for which the agent should delete the
|
||||||
secrets from backing storage.
|
secrets from backing storage.
|
||||||
</tp:docstring>
|
</tp:docstring>
|
||||||
</arg>
|
</arg>
|
||||||
|
@@ -411,12 +411,12 @@ request_new_get (NMConnection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Request *
|
static Request *
|
||||||
request_new_save (NMConnection *connection,
|
request_new_other (NMConnection *connection,
|
||||||
gboolean filter_by_uid,
|
gboolean filter_by_uid,
|
||||||
gulong uid_filter,
|
gulong uid_filter,
|
||||||
RequestCompleteFunc complete_callback,
|
RequestCompleteFunc complete_callback,
|
||||||
gpointer complete_callback_data,
|
gpointer complete_callback_data,
|
||||||
RequestNextFunc next_callback)
|
RequestNextFunc next_callback)
|
||||||
{
|
{
|
||||||
Request *req;
|
Request *req;
|
||||||
|
|
||||||
@@ -600,6 +600,17 @@ next_generic (Request *req, const char *detail)
|
|||||||
return success;
|
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
|
static void
|
||||||
@@ -881,16 +892,6 @@ save_complete_cb (Request *req,
|
|||||||
g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->reqid));
|
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
|
guint32
|
||||||
nm_agent_manager_save_secrets (NMAgentManager *self,
|
nm_agent_manager_save_secrets (NMAgentManager *self,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
@@ -908,17 +909,111 @@ nm_agent_manager_save_secrets (NMAgentManager *self,
|
|||||||
"Saving secrets for connection %s",
|
"Saving secrets for connection %s",
|
||||||
nm_connection_get_path (connection));
|
nm_connection_get_path (connection));
|
||||||
|
|
||||||
req = request_new_save (connection,
|
req = request_new_other (connection,
|
||||||
filter_by_uid,
|
filter_by_uid,
|
||||||
uid_filter,
|
uid_filter,
|
||||||
save_complete_cb,
|
save_complete_cb,
|
||||||
self,
|
self,
|
||||||
save_next_cb);
|
save_next_cb);
|
||||||
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
|
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
|
||||||
|
|
||||||
/* Kick off the request */
|
/* Kick off the request */
|
||||||
request_add_agents (self, req);
|
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;
|
return req->reqid;
|
||||||
}
|
}
|
||||||
|
@@ -74,4 +74,9 @@ guint32 nm_agent_manager_save_secrets (NMAgentManager *manager,
|
|||||||
gboolean filter_by_uid,
|
gboolean filter_by_uid,
|
||||||
gulong uid_filter);
|
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 */
|
#endif /* NM_AGENT_MANAGER_H */
|
||||||
|
@@ -234,9 +234,9 @@ nm_secret_agent_cancel_secrets (NMSecretAgent *self, gconstpointer call)
|
|||||||
/*************************************************************/
|
/*************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
save_callback (DBusGProxy *proxy,
|
agent_save_delete_cb (DBusGProxy *proxy,
|
||||||
DBusGProxyCall *call,
|
DBusGProxyCall *call,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
Request *r = user_data;
|
Request *r = user_data;
|
||||||
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent);
|
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent);
|
||||||
@@ -250,38 +250,71 @@ save_callback (DBusGProxy *proxy,
|
|||||||
g_hash_table_remove (priv->requests, call);
|
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
|
gconstpointer
|
||||||
nm_secret_agent_save_secrets (NMSecretAgent *self,
|
nm_secret_agent_save_secrets (NMSecretAgent *self,
|
||||||
NMConnection *connection,
|
NMConnection *connection,
|
||||||
NMSecretAgentCallback callback,
|
NMSecretAgentCallback callback,
|
||||||
gpointer callback_data)
|
gpointer callback_data)
|
||||||
{
|
{
|
||||||
NMSecretAgentPrivate *priv;
|
|
||||||
Request *r;
|
|
||||||
GHashTable *hash;
|
|
||||||
|
|
||||||
g_return_val_if_fail (self != NULL, NULL);
|
g_return_val_if_fail (self != NULL, NULL);
|
||||||
g_return_val_if_fail (connection != 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' */
|
/* 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);
|
gconstpointer
|
||||||
r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
|
nm_secret_agent_delete_secrets (NMSecretAgent *self,
|
||||||
"SaveSecrets",
|
NMConnection *connection,
|
||||||
save_callback,
|
NMSecretAgentCallback callback,
|
||||||
r,
|
gpointer callback_data)
|
||||||
NULL,
|
{
|
||||||
10000, /* 10 seconds */
|
g_return_val_if_fail (self != NULL, NULL);
|
||||||
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
|
g_return_val_if_fail (connection != NULL, NULL);
|
||||||
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
|
|
||||||
G_TYPE_INVALID);
|
|
||||||
g_hash_table_insert (priv->requests, r->call, r);
|
|
||||||
|
|
||||||
g_hash_table_destroy (hash);
|
/* No secrets sent; agents must be smart enough to track secrets using the UUID or something */
|
||||||
return r->call;
|
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,
|
NMSecretAgentCallback callback,
|
||||||
gpointer callback_data);
|
gpointer callback_data);
|
||||||
|
|
||||||
|
gconstpointer nm_secret_agent_delete_secrets (NMSecretAgent *agent,
|
||||||
|
NMConnection *connection,
|
||||||
|
NMSecretAgentCallback callback,
|
||||||
|
gpointer callback_data);
|
||||||
|
|
||||||
#endif /* NM_SECRET_AGENT_H */
|
#endif /* NM_SECRET_AGENT_H */
|
||||||
|
@@ -326,8 +326,18 @@ do_delete (NMSettingsConnection *connection,
|
|||||||
NMSettingsConnectionDeleteFunc callback,
|
NMSettingsConnectionDeleteFunc callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (connection);
|
||||||
|
NMConnection *for_agents;
|
||||||
|
|
||||||
g_object_ref (connection);
|
g_object_ref (connection);
|
||||||
set_visible (connection, FALSE);
|
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);
|
g_signal_emit (connection, signals[REMOVED], 0);
|
||||||
callback (connection, NULL, user_data);
|
callback (connection, NULL, user_data);
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
|
Reference in New Issue
Block a user