agent: add CancelGetSecrets D-Bus API

Allows NM to signal to an agent that an in-progress secrets
request is no longer needed.  This could happen if the device
for which the request was started was removed, disabled, or the
network being connected to changed, or whatever.
This commit is contained in:
Dan Williams 2011-01-18 13:19:29 -06:00
parent 7fa1a62cd3
commit a2f36e8bd4
4 changed files with 155 additions and 55 deletions

View file

@ -59,6 +59,27 @@
</arg>
</method>
<method name="CancelGetSecrets">
<tp:docstring>
Cancel a pending GetSecrets request for secrets of the given
connection. Any matching request should be canceled.
</tp:docstring>
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_secret_agent_cancel_get_secrets"/>
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="connection_path" type="o" direction="in">
<tp:docstring>
Object path of the connection for which, if secrets are being
requested, the request should be canceled.
</tp:docstring>
</arg>
<arg name="setting_name" type="s" direction="in">
<tp:docstring>
Setting name for which secrets for this connection were
originally being requested.
</tp:docstring>
</arg>
</method>
<method name="SaveSecrets">
<tp:docstring>
Save given secrets to backing storage.

View file

@ -336,7 +336,7 @@ struct _Request {
/* Current agent being asked for secrets */
NMSecretAgent *current;
gpointer current_call_id;
gconstpointer current_call_id;
/* Stores the sorted list of NMSecretAgents which will be
* asked for secrets.
@ -462,25 +462,21 @@ merge_secrets (GHashTable *src, GHashTable *dest)
}
static void
request_secrets_done_cb (DBusGProxy *proxy,
DBusGProxyCall *call_id,
void *user_data)
request_secrets_done_cb (NMSecretAgent *agent,
gconstpointer call_id,
GHashTable *secrets,
GError *error,
gpointer user_data)
{
Request *req = user_data;
GError *error = NULL;
GHashTable *secrets = NULL;
GHashTable *setting_secrets;
NMSecretAgent *agent = NM_SECRET_AGENT (req->current);
GHashTable *setting_secrets, *merged;
if (call_id != req->current_call_id)
return;
g_return_if_fail (call_id == req->current_call_id);
req->current = NULL;
req->current_call_id = NULL;
if (!dbus_g_proxy_end_call (proxy, call_id, &error,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets,
G_TYPE_INVALID)) {
if (error) {
nm_log_dbg (LOGD_AGENTS, "(%s) agent failed secrets request %p/%s: (%d) %s",
nm_secret_agent_get_description (agent),
req, req->setting_name,
@ -498,7 +494,6 @@ request_secrets_done_cb (DBusGProxy *proxy,
nm_log_dbg (LOGD_AGENTS, "(%s) agent returned no secrets for request %p/%s",
nm_secret_agent_get_description (agent),
req, req->setting_name);
g_hash_table_destroy (secrets);
/* Try the next agent */
request_next (req);
@ -513,8 +508,6 @@ request_secrets_done_cb (DBusGProxy *proxy,
* with the ones from the secret agent.
*/
if (req->settings_secrets) {
GHashTable *merged;
merged = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_unref);
/* Copy agent secrets first, then overwrite with settings secrets */
@ -525,8 +518,6 @@ request_secrets_done_cb (DBusGProxy *proxy,
g_hash_table_destroy (merged);
} else
req->complete_callback (req, secrets, NULL, req->complete_callback_data);
g_hash_table_destroy (secrets);
}
static void

View file

@ -45,10 +45,49 @@ typedef struct {
NMDBusManager *dbus_mgr;
DBusGProxy *proxy;
GHashTable *requests;
} NMSecretAgentPrivate;
/*************************************************************/
typedef struct {
NMSecretAgent *agent;
DBusGProxyCall *call;
char *path;
char *setting_name;
NMSecretAgentCallback callback;
gpointer callback_data;
} Request;
static Request *
request_new (NMSecretAgent *agent,
const char *path,
const char *setting_name,
NMSecretAgentCallback callback,
gpointer callback_data)
{
Request *r;
r = g_slice_new0 (Request);
r->agent = agent;
r->path = g_strdup (path);
r->setting_name = g_strdup (setting_name);
r->callback = callback;
r->callback_data = callback_data;
return r;
}
static void
request_free (Request *r)
{
g_free (r->path);
g_free (r->setting_name);
g_slice_free (Request, r);
}
/*************************************************************/
const char *
nm_secret_agent_get_description (NMSecretAgent *agent)
{
@ -106,19 +145,41 @@ nm_secret_agent_get_hash (NMSecretAgent *agent)
/*************************************************************/
gpointer
static void
secrets_callback (DBusGProxy *proxy,
DBusGProxyCall *call,
void *user_data)
{
Request *r = user_data;
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (r->agent);
GError *error = NULL;
GHashTable *secrets = NULL;
g_return_if_fail (call == r->call);
dbus_g_proxy_end_call (proxy, call, &error,
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &secrets,
G_TYPE_INVALID);
r->callback (r->agent, r, secrets, error, r->callback_data);
if (secrets)
g_hash_table_unref (secrets);
g_clear_error (&error);
g_hash_table_remove (priv->requests, call);
}
gconstpointer
nm_secret_agent_get_secrets (NMSecretAgent *self,
NMConnection *connection,
const char *setting_name,
const char *hint,
gboolean request_new,
DBusGProxyCallNotify done_callback,
gpointer done_callback_data)
gboolean get_new,
NMSecretAgentCallback callback,
gpointer callback_data)
{
NMSecretAgentPrivate *priv;
DBusGProxyCall *call;
GHashTable *hash;
const char *hints[2] = { hint, NULL };
Request *r;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (connection != NULL, NULL);
@ -127,29 +188,46 @@ nm_secret_agent_get_secrets (NMSecretAgent *self,
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
hash = nm_connection_to_hash (connection);
call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
"GetSecrets",
done_callback,
done_callback_data,
NULL,
120000, /* 120 seconds */
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
G_TYPE_STRING, setting_name,
G_TYPE_STRV, hints,
G_TYPE_BOOLEAN, request_new,
G_TYPE_INVALID);
g_hash_table_destroy (hash);
return call;
r = request_new (self, nm_connection_get_path (connection), setting_name, callback, callback_data);
r->call = dbus_g_proxy_begin_call_with_timeout (priv->proxy,
"GetSecrets",
secrets_callback,
r,
NULL,
120000, /* 120 seconds */
DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, hash,
DBUS_TYPE_G_OBJECT_PATH, nm_connection_get_path (connection),
G_TYPE_STRING, setting_name,
G_TYPE_STRV, hints,
G_TYPE_BOOLEAN, get_new,
G_TYPE_INVALID);
g_hash_table_insert (priv->requests, r->call, r);
g_hash_table_destroy (hash);
return r->call;
}
void
nm_secret_agent_cancel_secrets (NMSecretAgent *self, gpointer call_id)
nm_secret_agent_cancel_secrets (NMSecretAgent *self, gconstpointer call)
{
g_return_if_fail (self != NULL);
NMSecretAgentPrivate *priv;
Request *r;
dbus_g_proxy_cancel_call (NM_SECRET_AGENT_GET_PRIVATE (self)->proxy, call_id);
g_return_if_fail (self != NULL);
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
r = g_hash_table_lookup (priv->requests, call);
g_return_if_fail (r != NULL);
dbus_g_proxy_cancel_call (NM_SECRET_AGENT_GET_PRIVATE (self)->proxy, (gpointer) call);
dbus_g_proxy_call_no_reply (priv->proxy,
"CancelGetSecrets",
G_TYPE_STRING, r->path,
G_TYPE_STRING, r->setting_name,
G_TYPE_INVALID);
g_hash_table_remove (priv->requests, call);
}
/*************************************************************/
@ -162,15 +240,14 @@ nm_secret_agent_new (NMDBusManager *dbus_mgr,
{
NMSecretAgent *self;
NMSecretAgentPrivate *priv;
DBusGConnection *bus;
char *hash_str;
g_return_val_if_fail (owner != NULL, NULL);
g_return_val_if_fail (identifier != NULL, NULL);
self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL);
if (self) {
DBusGConnection *bus;
char *hash_str;
priv = NM_SECRET_AGENT_GET_PRIVATE (self);
priv->owner = g_strdup (owner);
@ -196,6 +273,10 @@ nm_secret_agent_new (NMDBusManager *dbus_mgr,
static void
nm_secret_agent_init (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
priv->requests = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) request_free);
}
static void
@ -203,16 +284,17 @@ dispose (GObject *object)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (object);
if (priv->disposed)
return;
priv->disposed = TRUE;
if (!priv->disposed) {
priv->disposed = TRUE;
g_free (priv->description);
g_free (priv->owner);
g_free (priv->identifier);
g_free (priv->description);
g_free (priv->owner);
g_free (priv->identifier);
g_object_unref (priv->proxy);
g_object_unref (priv->dbus_mgr);
g_hash_table_destroy (priv->requests);
g_object_unref (priv->proxy);
g_object_unref (priv->dbus_mgr);
}
G_OBJECT_CLASS (nm_secret_agent_parent_class)->dispose (object);
}

View file

@ -61,15 +61,21 @@ uid_t nm_secret_agent_get_owner_uid (NMSecretAgent *agent);
guint32 nm_secret_agent_get_hash (NMSecretAgent *agent);
gpointer nm_secret_agent_get_secrets (NMSecretAgent *agent,
typedef void (*NMSecretAgentCallback) (NMSecretAgent *agent,
gconstpointer call,
GHashTable *secrets,
GError *error,
gpointer user_data);
gconstpointer nm_secret_agent_get_secrets (NMSecretAgent *agent,
NMConnection *connection,
const char *setting_name,
const char *hint,
gboolean request_new,
DBusGProxyCallNotify done_callback,
gpointer done_callback_data);
NMSecretAgentCallback callback,
gpointer callback_data);
void nm_secret_agent_cancel_secrets (NMSecretAgent *agent,
gpointer call_id);
gconstpointer call_id);
#endif /* NM_SECRET_AGENT_H */