settings: refactor call_id type of async functions for NMAgentManager, NMSettingsConnection and NMActRequest

Instead of having the call_id of type guint32, make it an (opaque)
pointer type.

This has the advantage of strong typing and avoids the possiblity
of reusing an invalid integer (or overflow of the call-id counter).

OTOH, it has the disadvantage, that after a call_id is disposed,
it might be reused for future invocations (because malloc might
reuse the memory).

In fact, it is always an error to use a call_id that is already
completed. This commit also adds assertions to the cancel() calls
that the provided call_id is a pending call. Hence, such a bug
will be uncovered by assertions (that only might not tigger in
certain unlikely cases where a call-id got reused).

Note that for NMAgentManager, save_secrets() and delete_secrets()
both returned a call_id. But they didn't also provide a callback when
the operation completes. So the user trying to cancel such a call,
cannot know whether the operation is still in process and he cannot
avoid triggering an assertion.
Fix that by not returning a call-id for these operations. No caller
cared about it anyway.

For NMSettingsConnection, also track the internally scheduled requests
for so that we can cancel them on dispose.
This commit is contained in:
Thomas Haller 2015-09-02 22:43:04 +02:00
parent 40eda71dc6
commit 21fd5fa0ab
11 changed files with 202 additions and 163 deletions

View file

@ -480,7 +480,7 @@ supplicant_interface_release (NMDeviceEthernet *self)
static void
wired_secrets_cb (NMActRequest *req,
guint32 call_id,
NMActRequestGetSecretsCallId call_id,
NMConnection *connection,
GError *error,
gpointer user_data)

View file

@ -1674,7 +1674,7 @@ cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
static void
wifi_secrets_cb (NMActRequest *req,
guint32 call_id,
NMActRequestGetSecretsCallId call_id,
NMConnection *connection,
GError *error,
gpointer user_data)

View file

@ -73,7 +73,7 @@ typedef struct {
NMActRequest *act_request;
guint32 secrets_tries;
guint32 secrets_id;
NMActRequestGetSecretsCallId secrets_id;
guint32 mm_ip_timeout;
@ -724,13 +724,13 @@ cancel_get_secrets (NMModem *self)
if (priv->secrets_id) {
nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
}
}
static void
modem_secrets_cb (NMActRequest *req,
guint32 call_id,
NMActRequestGetSecretsCallId call_id,
NMConnection *connection,
GError *error,
gpointer user_data)
@ -740,7 +740,7 @@ modem_secrets_cb (NMActRequest *req,
g_return_if_fail (call_id == priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
if (error)
nm_log_warn (LOGD_MB, "(%s): %s", nm_modem_get_uid (self), error->message);

View file

@ -75,16 +75,18 @@ nm_act_request_get_connection (NMActRequest *req)
/*******************************************************************/
typedef struct {
struct _NMActRequestGetSecretsCallId {
NMActRequest *self;
guint32 call_id;
NMSettingsConnectionCallId call_id_s;
NMActRequestSecretsFunc callback;
gpointer callback_data;
} GetSecretsInfo;
};
typedef struct _NMActRequestGetSecretsCallId GetSecretsInfo;
static void
get_secrets_cb (NMSettingsConnection *connection,
guint32 call_id,
NMSettingsConnectionCallId call_id_s,
const char *agent_username,
const char *setting_name,
GError *error,
@ -93,14 +95,14 @@ get_secrets_cb (NMSettingsConnection *connection,
GetSecretsInfo *info = user_data;
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (info->self);
g_return_if_fail (info->call_id == call_id);
g_return_if_fail (info->call_id_s == call_id_s);
priv->secrets_calls = g_slist_remove (priv->secrets_calls, info);
info->callback (info->self, call_id, NM_CONNECTION (connection), error, info->callback_data);
info->callback (info->self, info, NM_CONNECTION (connection), error, info->callback_data);
g_free (info);
}
guint32
NMActRequestGetSecretsCallId
nm_act_request_get_secrets (NMActRequest *self,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
@ -110,7 +112,7 @@ nm_act_request_get_secrets (NMActRequest *self,
{
NMActRequestPrivate *priv;
GetSecretsInfo *info;
guint32 call_id;
NMSettingsConnectionCallId call_id_s;
NMConnection *connection;
const char *hints[2] = { hint, NULL };
@ -128,25 +130,25 @@ nm_act_request_get_secrets (NMActRequest *self,
flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED;
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
call_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection),
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)),
setting_name,
flags,
hints,
get_secrets_cb,
info,
NULL);
if (call_id > 0) {
info->call_id = call_id;
call_id_s = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection),
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)),
setting_name,
flags,
hints,
get_secrets_cb,
info,
NULL);
if (call_id_s) {
info->call_id_s = call_id_s;
priv->secrets_calls = g_slist_append (priv->secrets_calls, info);
} else
g_free (info);
return call_id;
return info;
}
void
nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id)
nm_act_request_cancel_secrets (NMActRequest *self, NMActRequestGetSecretsCallId call_id)
{
NMActRequestPrivate *priv;
NMConnection *connection;
@ -154,24 +156,25 @@ nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id)
g_return_if_fail (self);
g_return_if_fail (NM_IS_ACT_REQUEST (self));
g_return_if_fail (call_id > 0);
g_return_if_fail (call_id);
priv = NM_ACT_REQUEST_GET_PRIVATE (self);
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) {
GetSecretsInfo *info = iter->data;
/* Remove the matching info */
if (info->call_id == call_id) {
if (info == call_id) {
priv->secrets_calls = g_slist_remove_link (priv->secrets_calls, iter);
g_slist_free (iter);
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), call_id);
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id_s);
g_free (info);
break;
return;
}
}
g_return_if_reached ();
}
/********************************************************************/
@ -444,7 +447,7 @@ dispose (GObject *object)
for (iter = priv->secrets_calls; connection && iter; iter = g_slist_next (iter)) {
GetSecretsInfo *info = iter->data;
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id);
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id_s);
g_free (info);
}
g_slist_free (priv->secrets_calls);

View file

@ -33,6 +33,9 @@
#define NM_IS_ACT_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ACT_REQUEST))
#define NM_ACT_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ACT_REQUEST, NMActRequestClass))
struct _NMActRequestGetSecretsCallId;
typedef struct _NMActRequestGetSecretsCallId *NMActRequestGetSecretsCallId;
struct _NMActRequest {
NMActiveConnection parent;
};
@ -62,19 +65,19 @@ void nm_act_request_add_share_rule (NMActRequest *req,
/* Secrets handling */
typedef void (*NMActRequestSecretsFunc) (NMActRequest *req,
guint32 call_id,
NMActRequestGetSecretsCallId call_id,
NMConnection *connection,
GError *error,
gpointer user_data);
guint32 nm_act_request_get_secrets (NMActRequest *req,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char *hint,
NMActRequestSecretsFunc callback,
gpointer callback_data);
NMActRequestGetSecretsCallId nm_act_request_get_secrets (NMActRequest *req,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char *hint,
NMActRequestSecretsFunc callback,
gpointer callback_data);
void nm_act_request_cancel_secrets (NMActRequest *req, guint32 call_id);
void nm_act_request_cancel_secrets (NMActRequest *req, NMActRequestGetSecretsCallId call_id);
#endif /* __NETWORKMANAGER_ACTIVATION_REQUEST_H__ */

View file

@ -63,7 +63,7 @@ typedef struct {
NMActRequest *act_req;
GDBusMethodInvocation *pending_secrets_context;
guint32 secrets_id;
NMActRequestGetSecretsCallId secrets_id;
const char *secrets_setting_name;
guint32 ppp_watch_id;
@ -243,7 +243,7 @@ cancel_get_secrets (NMPPPManager *self)
if (priv->secrets_id) {
nm_act_request_cancel_secrets (priv->act_req, priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
}
priv->secrets_setting_name = NULL;
}
@ -309,7 +309,7 @@ extract_details_from_connection (NMConnection *connection,
static void
ppp_secrets_cb (NMActRequest *req,
guint32 call_id,
NMActRequestGetSecretsCallId call_id,
NMConnection *connection,
GError *error,
gpointer user_data)
@ -348,7 +348,7 @@ ppp_secrets_cb (NMActRequest *req,
out:
priv->pending_secrets_context = NULL;
priv->secrets_id = 0;
priv->secrets_id = NULL;
priv->secrets_setting_name = NULL;
}

View file

@ -124,7 +124,7 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _Request Request;
typedef struct _NMAgentManagerCallId Request;
static void request_add_agent (Request *req, NMSecretAgent *agent);
@ -160,7 +160,7 @@ remove_agent (NMAgentManager *self, const char *owner)
/* Remove this agent from any in-progress secrets requests */
g_hash_table_iter_init (&iter, priv->requests);
while (g_hash_table_iter_next (&iter, NULL, &data))
while (g_hash_table_iter_next (&iter, &data, NULL))
request_remove_agent ((Request *) data, agent, &pending_reqs);
/* We cannot call request_next_agent() from from within hash iterating loop,
@ -290,7 +290,7 @@ agent_register_permissions_done (NMAuthChain *chain,
/* Add this agent to any in-progress secrets requests */
g_hash_table_iter_init (&iter, priv->requests);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &req))
while (g_hash_table_iter_next (&iter, (gpointer) &req, NULL))
request_add_agent (req, agent);
}
@ -435,12 +435,11 @@ done:
/*************************************************************/
struct _Request {
struct _NMAgentManagerCallId {
NMAgentManager *self;
RequestType request_type;
guint32 reqid;
char *detail;
NMAuthSubject *subject;
@ -485,8 +484,6 @@ struct _Request {
};
};
static guint32 next_req_id = 1;
static Request *
request_new (NMAgentManager *self,
RequestType request_type,
@ -498,7 +495,6 @@ request_new (NMAgentManager *self,
req = g_slice_new0 (Request);
req->self = g_object_ref (self);
req->request_type = request_type;
req->reqid = next_req_id++;
req->detail = g_strdup (detail);
req->subject = g_object_ref (subject);
return req;
@ -569,7 +565,7 @@ req_complete (Request *req,
switch (req->request_type) {
case REQUEST_TYPE_CON_GET:
req->con.get.callback (self,
req->reqid,
req,
agent_dbus_owner,
agent_username,
req->con.current_has_modify,
@ -589,7 +585,7 @@ req_complete (Request *req,
g_return_if_reached ();
}
g_hash_table_remove (priv->requests, GUINT_TO_POINTER (req->reqid));
g_hash_table_remove (priv->requests, req);
}
static void
@ -1137,7 +1133,7 @@ _con_get_try_complete_early (Request *req)
return FALSE;
}
guint32
NMAgentManagerCallId
nm_agent_manager_get_secrets (NMAgentManager *self,
NMConnection *connection,
NMAuthSubject *subject,
@ -1184,24 +1180,26 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
req->con.get.other_data2 = other_data2;
req->con.get.other_data3 = other_data3;
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
g_hash_table_add (priv->requests, req);
/* Kick off the request */
if (!(req->con.get.flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM))
request_add_agents (self, req);
req->idle_id = g_idle_add (request_start, req);
return req->reqid;
return req;
}
void
nm_agent_manager_cancel_secrets (NMAgentManager *self,
guint32 request_id)
NMAgentManagerCallId request_id)
{
g_return_if_fail (self != NULL);
g_return_if_fail (request_id > 0);
g_return_if_fail (request_id);
g_return_if_fail (request_id->request_type == REQUEST_TYPE_CON_GET);
g_hash_table_remove (NM_AGENT_MANAGER_GET_PRIVATE (self)->requests,
GUINT_TO_POINTER (request_id));
if (!g_hash_table_remove (NM_AGENT_MANAGER_GET_PRIVATE (self)->requests,
request_id))
g_return_if_reached ();
}
/*************************************************************/
@ -1260,7 +1258,7 @@ _con_save_request_start (Request *req)
}
}
guint32
void
nm_agent_manager_save_secrets (NMAgentManager *self,
NMConnection *connection,
NMAuthSubject *subject)
@ -1268,8 +1266,8 @@ nm_agent_manager_save_secrets (NMAgentManager *self,
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
Request *req;
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (NM_IS_CONNECTION (connection), 0);
g_return_if_fail (self);
g_return_if_fail (NM_IS_CONNECTION (connection));
nm_log_dbg (LOGD_SETTINGS,
"Saving secrets for connection %s (%s)",
@ -1281,12 +1279,11 @@ nm_agent_manager_save_secrets (NMAgentManager *self,
nm_connection_get_id (connection),
subject);
req->con.connection = g_object_ref (connection);
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
g_hash_table_add (priv->requests, req);
/* Kick off the request */
request_add_agents (self, req);
req->idle_id = g_idle_add (request_start, req);
return req->reqid;
}
/*************************************************************/
@ -1342,7 +1339,7 @@ _con_del_request_start (Request *req)
}
}
guint32
void
nm_agent_manager_delete_secrets (NMAgentManager *self,
NMConnection *connection)
{
@ -1350,8 +1347,8 @@ nm_agent_manager_delete_secrets (NMAgentManager *self,
NMAuthSubject *subject;
Request *req;
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (NM_IS_CONNECTION (connection), 0);
g_return_if_fail (self != NULL);
g_return_if_fail (NM_IS_CONNECTION (connection));
nm_log_dbg (LOGD_SETTINGS,
"Deleting secrets for connection %s (%s)",
@ -1365,12 +1362,11 @@ nm_agent_manager_delete_secrets (NMAgentManager *self,
subject);
req->con.connection = g_object_ref (connection);
g_object_unref (subject);
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
g_hash_table_add (priv->requests, req);
/* Kick off the request */
request_add_agents (self, req);
req->idle_id = g_idle_add (request_start, req);
return req->reqid;
}
/*************************************************************/
@ -1493,8 +1489,8 @@ nm_agent_manager_init (NMAgentManager *self)
priv->agents = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
priv->requests = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify) request_free);
(GDestroyNotify) request_free,
NULL);
}
static void

View file

@ -33,6 +33,9 @@
#define NM_IS_AGENT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_AGENT_MANAGER))
#define NM_AGENT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_AGENT_MANAGER, NMAgentManagerClass))
struct _NMAgentManagerCallId;
typedef struct _NMAgentManagerCallId *NMAgentManagerCallId;
struct _NMAgentManager {
NMExportedObject parent;
};
@ -50,7 +53,7 @@ NMAgentManager *nm_agent_manager_get (void);
/* If no agent fulfilled the secrets request, agent_dbus_owner will be NULL */
typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager,
guint32 call_id,
NMAgentManagerCallId call_id,
const char *agent_dbus_owner,
const char *agent_uname,
gboolean agent_has_modify,
@ -62,27 +65,27 @@ typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager,
gpointer other_data2,
gpointer other_data3);
guint32 nm_agent_manager_get_secrets (NMAgentManager *manager,
NMConnection *connection,
NMAuthSubject *subject,
GVariant *existing_secrets,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char **hints,
NMAgentSecretsResultFunc callback,
gpointer callback_data,
gpointer other_data2,
gpointer other_data3);
NMAgentManagerCallId nm_agent_manager_get_secrets (NMAgentManager *manager,
NMConnection *connection,
NMAuthSubject *subject,
GVariant *existing_secrets,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char **hints,
NMAgentSecretsResultFunc callback,
gpointer callback_data,
gpointer other_data2,
gpointer other_data3);
void nm_agent_manager_cancel_secrets (NMAgentManager *manager,
guint32 request_id);
NMAgentManagerCallId request_id);
guint32 nm_agent_manager_save_secrets (NMAgentManager *manager,
NMConnection *connection,
NMAuthSubject *subject);
void nm_agent_manager_save_secrets (NMAgentManager *manager,
NMConnection *connection,
NMAuthSubject *subject);
guint32 nm_agent_manager_delete_secrets (NMAgentManager *manager,
NMConnection *connection);
void nm_agent_manager_delete_secrets (NMAgentManager *manager,
NMConnection *connection);
NMSecretAgent *nm_agent_manager_get_agent_by_user (NMAgentManager *manager,
const char *username);

View file

@ -72,6 +72,18 @@ G_DEFINE_TYPE_WITH_CODE (NMSettingsConnection, nm_settings_connection, NM_TYPE_E
NM_TYPE_SETTINGS_CONNECTION, \
NMSettingsConnectionPrivate))
static inline NMAgentManagerCallId
NM_AGENT_MANAGER_CALL_ID (NMSettingsConnectionCallId call_id)
{
return (NMAgentManagerCallId) call_id;
}
static inline NMSettingsConnectionCallId
NM_SETTINGS_CONNECTION_CALL_ID (NMAgentManagerCallId call_id_a)
{
return (NMSettingsConnectionCallId) call_id_a;
}
enum {
PROP_0 = 0,
PROP_VISIBLE,
@ -103,7 +115,9 @@ typedef struct {
GSList *pending_auths; /* List of pending authentication requests */
gboolean visible; /* Is this connection is visible by some session? */
GSList *reqs; /* in-progress secrets requests */
GSList *reqs_int; /* in-progress internal secrets requests */
GSList *reqs_ext; /* in-progress external secrets requests (D-Bus) */
/* Caches secrets from on-disk connections; were they not cached any
* call to nm_connection_clear_secrets() wipes them out and we'd have
@ -794,7 +808,7 @@ new_secrets_commit_cb (NMSettingsConnection *self,
static void
agent_secrets_done_cb (NMAgentManager *manager,
guint32 call_id,
NMAgentManagerCallId call_id_a,
const char *agent_dbus_owner,
const char *agent_username,
gboolean agent_has_modify,
@ -806,6 +820,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
gpointer other_data2,
gpointer other_data3)
{
NMSettingsConnectionCallId call_id = NM_SETTINGS_CONNECTION_CALL_ID (call_id_a);
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data);
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMSettingsConnectionSecretsFunc callback = other_data2;
@ -815,8 +830,10 @@ agent_secrets_done_cb (NMAgentManager *manager,
gboolean agent_had_system = FALSE;
ForEachSecretFlags cmp_flags = { NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_SECRET_FLAG_NONE };
priv->reqs_int = g_slist_remove (priv->reqs_int, call_id_a);
if (error) {
_LOGD ("(%s:%u) secrets request error: (%d) %s",
_LOGD ("(%s:%p) secrets request error: (%d) %s",
setting_name,
call_id,
error->code,
@ -837,7 +854,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
g_assert (secrets);
if (agent_dbus_owner) {
_LOGD ("(%s:%u) secrets returned from agent %s",
_LOGD ("(%s:%p) secrets returned from agent %s",
setting_name,
call_id,
agent_dbus_owner);
@ -854,7 +871,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
/* No user interaction was allowed when requesting secrets; the
* agent is being bad. Remove system-owned secrets.
*/
_LOGD ("(%s:%u) interaction forbidden but agent %s returned system secrets",
_LOGD ("(%s:%p) interaction forbidden but agent %s returned system secrets",
setting_name,
call_id,
agent_dbus_owner);
@ -864,7 +881,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
/* Agent didn't successfully authenticate; clear system-owned secrets
* from the secrets the agent returned.
*/
_LOGD ("(%s:%u) agent failed to authenticate but provided system secrets",
_LOGD ("(%s:%p) agent failed to authenticate but provided system secrets",
setting_name,
call_id);
@ -872,12 +889,12 @@ agent_secrets_done_cb (NMAgentManager *manager,
}
}
} else {
_LOGD ("(%s:%u) existing secrets returned",
_LOGD ("(%s:%p) existing secrets returned",
setting_name,
call_id);
}
_LOGD ("(%s:%u) secrets request completed",
_LOGD ("(%s:%p) secrets request completed",
setting_name,
call_id);
@ -914,19 +931,19 @@ agent_secrets_done_cb (NMAgentManager *manager,
* nothing has changed, since agent-owned secrets don't get saved here.
*/
if (agent_had_system) {
_LOGD ("(%s:%u) saving new secrets to backing storage",
_LOGD ("(%s:%p) saving new secrets to backing storage",
setting_name,
call_id);
nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, new_secrets_commit_cb, NULL);
} else {
_LOGD ("(%s:%u) new agent secrets processed",
_LOGD ("(%s:%p) new agent secrets processed",
setting_name,
call_id);
}
} else {
_LOGD ("(%s:%u) failed to update with agent secrets: (%d) %s",
_LOGD ("(%s:%p) failed to update with agent secrets: (%d) %s",
setting_name,
call_id,
local ? local->code : -1,
@ -934,7 +951,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
}
g_variant_unref (filtered_secrets);
} else {
_LOGD ("(%s:%u) failed to update with existing secrets: (%d) %s",
_LOGD ("(%s:%p) failed to update with existing secrets: (%d) %s",
setting_name,
call_id,
local ? local->code : -1,
@ -963,7 +980,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
*
* Returns: a call ID which may be used to cancel the ongoing secrets request
**/
guint32
NMSettingsConnectionCallId
nm_settings_connection_get_secrets (NMSettingsConnection *self,
NMAuthSubject *subject,
const char *setting_name,
@ -975,7 +992,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
GVariant *existing_secrets;
guint32 call_id = 0;
NMAgentManagerCallId call_id_a;
gs_free char *joined_hints = NULL;
/* Use priv->secrets to work around the fact that nm_connection_clear_secrets()
@ -985,7 +1002,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"%s.%d - Internal error; secrets cache invalid.",
__FILE__, __LINE__);
return 0;
return NULL;
}
/* Make sure the request actually requests something we can return */
@ -993,46 +1010,50 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
"%s.%d - Connection didn't have requested setting '%s'.",
__FILE__, __LINE__, setting_name);
return 0;
return NULL;
}
existing_secrets = nm_connection_to_dbus (priv->system_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS);
if (existing_secrets)
g_variant_ref_sink (existing_secrets);
call_id = nm_agent_manager_get_secrets (priv->agent_mgr,
NM_CONNECTION (self),
subject,
existing_secrets,
setting_name,
flags,
hints,
agent_secrets_done_cb,
self,
callback,
callback_data);
call_id_a = nm_agent_manager_get_secrets (priv->agent_mgr,
NM_CONNECTION (self),
subject,
existing_secrets,
setting_name,
flags,
hints,
agent_secrets_done_cb,
self,
callback,
callback_data);
if (existing_secrets)
g_variant_unref (existing_secrets);
_LOGD ("(%s:%u) secrets requested flags 0x%X hints '%s'",
_LOGD ("(%s:%p) secrets requested flags 0x%X hints '%s'",
setting_name,
call_id,
call_id_a,
flags,
(hints && hints[0]) ? (joined_hints = g_strjoinv (",", (char **) hints)) : "(none)");
return call_id;
priv->reqs_int = g_slist_append (priv->reqs_int, call_id_a);
return NM_SETTINGS_CONNECTION_CALL_ID (call_id_a);
}
void
nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
guint32 call_id)
NMSettingsConnectionCallId call_id)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
_LOGD ("(%u) secrets canceled",
call_id);
if (!g_slist_find (priv->reqs_int, call_id))
g_return_if_reached ();
priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id));
nm_agent_manager_cancel_secrets (priv->agent_mgr, call_id);
_LOGD ("(%p) secrets canceled", call_id);
priv->reqs_int = g_slist_remove (priv->reqs_int, call_id);
nm_agent_manager_cancel_secrets (priv->agent_mgr, NM_AGENT_MANAGER_CALL_ID (call_id));
}
/**** User authorization **************************************/
@ -1606,7 +1627,7 @@ impl_settings_connection_delete (NMSettingsConnection *self,
{
NMAuthSubject *subject = NULL;
GError *error = NULL;
if (!check_writable (NM_CONNECTION (self), &error))
goto out_err;
@ -1627,7 +1648,7 @@ out_err:
static void
dbus_get_agent_secrets_cb (NMSettingsConnection *self,
guint32 call_id,
NMSettingsConnectionCallId call_id,
const char *agent_username,
const char *setting_name,
GError *error,
@ -1637,7 +1658,7 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self,
GDBusMethodInvocation *context = user_data;
GVariant *dict;
priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id));
priv->reqs_ext = g_slist_remove (priv->reqs_ext, call_id);
if (error)
g_dbus_method_invocation_return_gerror (context, error);
@ -1655,7 +1676,7 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self,
}
static void
dbus_get_secrets_auth_cb (NMSettingsConnection *self,
dbus_get_secrets_auth_cb (NMSettingsConnection *self,
GDBusMethodInvocation *context,
NMAuthSubject *subject,
GError *error,
@ -1663,22 +1684,22 @@ dbus_get_secrets_auth_cb (NMSettingsConnection *self,
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
char *setting_name = user_data;
guint32 call_id = 0;
NMSettingsConnectionCallId call_id;
GError *local = NULL;
if (!error) {
call_id = nm_settings_connection_get_secrets (self,
subject,
setting_name,
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED
| NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS,
NULL,
dbus_get_agent_secrets_cb,
context,
&local);
if (call_id > 0) {
subject,
setting_name,
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED
| NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS,
NULL,
dbus_get_agent_secrets_cb,
context,
&local);
if (call_id) {
/* track the request and wait for the callback */
priv->reqs = g_slist_append (priv->reqs, GUINT_TO_POINTER (call_id));
priv->reqs_ext = g_slist_append (priv->reqs_ext, call_id);
}
}
@ -2334,15 +2355,31 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_settings_connection_parent_class)->constructed (object);
}
static void
_cancel_all (NMAgentManager *agent_mgr, GSList **preqs)
{
while (*preqs) {
NMAgentManagerCallId call_id_a = (*preqs)->data;
*preqs = g_slist_delete_link (*preqs, *preqs);
nm_agent_manager_cancel_secrets (agent_mgr, call_id_a);
}
}
static void
dispose (GObject *object)
{
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object);
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
GSList *iter;
_LOGD ("disposing");
/* Cancel in-progress secrets requests */
if (priv->agent_mgr) {
_cancel_all (priv->agent_mgr, &priv->reqs_ext);
_cancel_all (priv->agent_mgr, &priv->reqs_int);
}
if (priv->updated_idle_id) {
g_source_remove (priv->updated_idle_id);
priv->updated_idle_id = 0;
@ -2363,12 +2400,6 @@ dispose (GObject *object)
g_slist_free_full (priv->pending_auths, (GDestroyNotify) nm_auth_chain_unref);
priv->pending_auths = NULL;
/* Cancel in-progress secrets requests */
for (iter = priv->reqs; iter; iter = g_slist_next (iter))
nm_agent_manager_cancel_secrets (priv->agent_mgr, GPOINTER_TO_UINT (iter->data));
g_slist_free (priv->reqs);
priv->reqs = NULL;
g_clear_pointer (&priv->seen_bssids, (GDestroyNotify) g_hash_table_destroy);
set_visible (self, FALSE);

View file

@ -85,6 +85,9 @@ typedef enum { /*< skip >*/
NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED = (1LL << 1),
} NMSettingsConnectionCommitReason;
struct _NMSettingsConnectionCallId;
typedef struct _NMSettingsConnectionCallId *NMSettingsConnectionCallId;
typedef struct _NMSettingsConnectionClass NMSettingsConnectionClass;
typedef void (*NMSettingsConnectionCommitFunc) (NMSettingsConnection *self,
@ -144,23 +147,23 @@ void nm_settings_connection_delete (NMSettingsConnection *self,
gpointer user_data);
typedef void (*NMSettingsConnectionSecretsFunc) (NMSettingsConnection *self,
guint32 call_id,
NMSettingsConnectionCallId call_id,
const char *agent_username,
const char *setting_name,
GError *error,
gpointer user_data);
guint32 nm_settings_connection_get_secrets (NMSettingsConnection *self,
NMAuthSubject *subject,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char **hints,
NMSettingsConnectionSecretsFunc callback,
gpointer callback_data,
GError **error);
NMSettingsConnectionCallId nm_settings_connection_get_secrets (NMSettingsConnection *self,
NMAuthSubject *subject,
const char *setting_name,
NMSecretAgentGetSecretsFlags flags,
const char **hints,
NMSettingsConnectionSecretsFunc callback,
gpointer callback_data,
GError **error);
void nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
guint32 call_id);
NMSettingsConnectionCallId call_id);
gboolean nm_settings_connection_is_visible (NMSettingsConnection *self);

View file

@ -80,7 +80,7 @@ typedef struct {
gboolean service_can_persist;
gboolean connection_can_persist;
guint32 secrets_id;
NMSettingsConnectionCallId secrets_id;
SecretsReq secrets_idx;
char *username;
@ -334,7 +334,7 @@ _set_vpn_state (NMVpnConnection *connection,
/* Clear any in-progress secrets request */
if (priv->secrets_id) {
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
}
dispatcher_cleanup (connection);
@ -2009,7 +2009,7 @@ plugin_new_secrets_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_da
static void
get_secrets_cb (NMSettingsConnection *connection,
guint32 call_id,
NMSettingsConnectionCallId call_id,
const char *agent_username,
const char *setting_name,
GError *error,
@ -2022,7 +2022,7 @@ get_secrets_cb (NMSettingsConnection *connection,
g_return_if_fail (NM_CONNECTION (connection) == priv->connection);
g_return_if_fail (call_id == priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
if (error && priv->secrets_idx >= SECRETS_REQ_NEW) {
nm_log_err (LOGD_VPN, "Failed to request VPN secrets #%d: (%d) %s",
@ -2227,7 +2227,7 @@ dispose (GObject *object)
if (priv->secrets_id) {
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection),
priv->secrets_id);
priv->secrets_id = 0;
priv->secrets_id = NULL;
}
if (priv->cancellable) {