core: merge branch 'th/secret-requests-bgo754508'

https://bugzilla.gnome.org/show_bug.cgi?id=754508
This commit is contained in:
Thomas Haller
2015-09-18 14:28:08 +02:00
15 changed files with 806 additions and 752 deletions

View File

@@ -1540,6 +1540,12 @@ nm_match_spec_join (GSList *specs)
return g_string_free (str, FALSE); return g_string_free (str, FALSE);
} }
/**
* nm_utils_get_shared_wifi_permission:
* @connection: the NMConnection to lookup the permission.
*
* Returns: a static string of the wifi-permission (if any) or %NULL.
*/
const char * const char *
nm_utils_get_shared_wifi_permission (NMConnection *connection) nm_utils_get_shared_wifi_permission (NMConnection *connection)
{ {

View File

@@ -480,7 +480,7 @@ supplicant_interface_release (NMDeviceEthernet *self)
static void static void
wired_secrets_cb (NMActRequest *req, wired_secrets_cb (NMActRequest *req,
guint32 call_id, NMActRequestGetSecretsCallId call_id,
NMConnection *connection, NMConnection *connection,
GError *error, GError *error,
gpointer user_data) gpointer user_data)
@@ -488,7 +488,9 @@ wired_secrets_cb (NMActRequest *req,
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
NMDevice *dev = NM_DEVICE (self); NMDevice *dev = NM_DEVICE (self);
g_return_if_fail (req == nm_device_get_act_request (dev)); if (req != nm_device_get_act_request (dev))
return;
g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
g_return_if_fail (nm_act_request_get_connection (req) == connection); g_return_if_fail (nm_act_request_get_connection (req) == connection);

View File

@@ -1674,7 +1674,7 @@ cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
static void static void
wifi_secrets_cb (NMActRequest *req, wifi_secrets_cb (NMActRequest *req,
guint32 call_id, NMActRequestGetSecretsCallId call_id,
NMConnection *connection, NMConnection *connection,
GError *error, GError *error,
gpointer user_data) gpointer user_data)
@@ -1682,7 +1682,9 @@ wifi_secrets_cb (NMActRequest *req,
NMDevice *device = NM_DEVICE (user_data); NMDevice *device = NM_DEVICE (user_data);
NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifi *self = NM_DEVICE_WIFI (device);
g_return_if_fail (req == nm_device_get_act_request (device)); if (req != nm_device_get_act_request (device))
return;
g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
g_return_if_fail (nm_act_request_get_connection (req) == connection); g_return_if_fail (nm_act_request_get_connection (req) == connection);

View File

@@ -73,7 +73,7 @@ typedef struct {
NMActRequest *act_request; NMActRequest *act_request;
guint32 secrets_tries; guint32 secrets_tries;
guint32 secrets_id; NMActRequestGetSecretsCallId secrets_id;
guint32 mm_ip_timeout; guint32 mm_ip_timeout;
@@ -722,15 +722,12 @@ cancel_get_secrets (NMModem *self)
{ {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
if (priv->secrets_id) { nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id);
nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id);
priv->secrets_id = 0;
}
} }
static void static void
modem_secrets_cb (NMActRequest *req, modem_secrets_cb (NMActRequest *req,
guint32 call_id, NMActRequestGetSecretsCallId call_id,
NMConnection *connection, NMConnection *connection,
GError *error, GError *error,
gpointer user_data) gpointer user_data)
@@ -740,7 +737,10 @@ modem_secrets_cb (NMActRequest *req,
g_return_if_fail (call_id == priv->secrets_id); g_return_if_fail (call_id == priv->secrets_id);
priv->secrets_id = 0; priv->secrets_id = NULL;
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
if (error) if (error)
nm_log_warn (LOGD_MB, "(%s): %s", nm_modem_get_uid (self), error->message); nm_log_warn (LOGD_MB, "(%s): %s", nm_modem_get_uid (self), error->message);
@@ -748,7 +748,7 @@ modem_secrets_cb (NMActRequest *req,
g_signal_emit (self, signals[AUTH_RESULT], 0, error); g_signal_emit (self, signals[AUTH_RESULT], 0, error);
} }
gboolean void
nm_modem_get_secrets (NMModem *self, nm_modem_get_secrets (NMModem *self,
const char *setting_name, const char *setting_name,
gboolean request_new, gboolean request_new,
@@ -767,10 +767,8 @@ nm_modem_get_secrets (NMModem *self,
hint, hint,
modem_secrets_cb, modem_secrets_cb,
self); self);
if (priv->secrets_id) g_return_if_fail (priv->secrets_id);
g_signal_emit (self, signals[AUTH_REQUESTED], 0); g_signal_emit (self, signals[AUTH_REQUESTED], 0);
return !!(priv->secrets_id);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -790,8 +788,7 @@ nm_modem_act_stage1_prepare (NMModem *self,
NMDeviceStateReason *reason) NMDeviceStateReason *reason)
{ {
NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
NMActStageReturn ret; gs_unref_ptrarray GPtrArray *hints = NULL;
GPtrArray *hints = NULL;
const char *setting_name = NULL; const char *setting_name = NULL;
NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION;
NMConnection *connection; NMConnection *connection;
@@ -820,18 +817,9 @@ nm_modem_act_stage1_prepare (NMModem *self,
hints ? g_ptr_array_index (hints, 0) : NULL, hints ? g_ptr_array_index (hints, 0) : NULL,
modem_secrets_cb, modem_secrets_cb,
self); self);
if (priv->secrets_id) { g_return_val_if_fail (priv->secrets_id, NM_ACT_STAGE_RETURN_FAILURE);
g_signal_emit (self, signals[AUTH_REQUESTED], 0); g_signal_emit (self, signals[AUTH_REQUESTED], 0);
ret = NM_ACT_STAGE_RETURN_POSTPONE; return NM_ACT_STAGE_RETURN_POSTPONE;
} else {
*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
ret = NM_ACT_STAGE_RETURN_FAILURE;
}
if (hints)
g_ptr_array_free (hints, TRUE);
return ret;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@@ -218,10 +218,10 @@ NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem,
void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config);
gboolean nm_modem_get_secrets (NMModem *modem, void nm_modem_get_secrets (NMModem *modem,
const char *setting_name, const char *setting_name,
gboolean request_new, gboolean request_new,
const char *hint); const char *hint);
void nm_modem_deactivate (NMModem *modem, NMDevice *device); void nm_modem_deactivate (NMModem *modem, NMDevice *device);

View File

@@ -75,16 +75,18 @@ nm_act_request_get_connection (NMActRequest *req)
/*******************************************************************/ /*******************************************************************/
typedef struct { struct _NMActRequestGetSecretsCallId {
NMActRequest *self; NMActRequest *self;
guint32 call_id; NMSettingsConnectionCallId call_id_s;
NMActRequestSecretsFunc callback; NMActRequestSecretsFunc callback;
gpointer callback_data; gpointer callback_data;
} GetSecretsInfo; };
typedef struct _NMActRequestGetSecretsCallId GetSecretsInfo;
static void static void
get_secrets_cb (NMSettingsConnection *connection, get_secrets_cb (NMSettingsConnection *connection,
guint32 call_id, NMSettingsConnectionCallId call_id_s,
const char *agent_username, const char *agent_username,
const char *setting_name, const char *setting_name,
GError *error, GError *error,
@@ -93,14 +95,36 @@ get_secrets_cb (NMSettingsConnection *connection,
GetSecretsInfo *info = user_data; GetSecretsInfo *info = user_data;
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (info->self); 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);
g_return_if_fail (g_slist_find (priv->secrets_calls, info));
priv->secrets_calls = g_slist_remove (priv->secrets_calls, info); priv->secrets_calls = g_slist_remove (priv->secrets_calls, info);
info->callback (info->self, call_id, NM_CONNECTION (connection), error, info->callback_data); if (info->callback)
info->callback (info->self, info, NM_CONNECTION (connection), error, info->callback_data);
g_free (info); g_free (info);
} }
guint32 /**
* nm_act_request_get_secrets:
* @self:
* @setting_name:
* @flags:
* @hint:
* @callback:
* @callback_data:
*
* Asnychronously starts the request for secrets. This function cannot
* fail.
*
* The return call-id can be used to cancel the request. You are
* only allowed to cancel a still pending operation (once).
* The callback will always be invoked once, even for canceling
* or disposing of NMActRequest.
*
* Returns: a call-id.
*/
NMActRequestGetSecretsCallId
nm_act_request_get_secrets (NMActRequest *self, nm_act_request_get_secrets (NMActRequest *self,
const char *setting_name, const char *setting_name,
NMSecretAgentGetSecretsFlags flags, NMSecretAgentGetSecretsFlags flags,
@@ -110,7 +134,7 @@ nm_act_request_get_secrets (NMActRequest *self,
{ {
NMActRequestPrivate *priv; NMActRequestPrivate *priv;
GetSecretsInfo *info; GetSecretsInfo *info;
guint32 call_id; NMSettingsConnectionCallId call_id_s;
NMConnection *connection; NMConnection *connection;
const char *hints[2] = { hint, NULL }; const char *hints[2] = { hint, NULL };
@@ -128,50 +152,40 @@ nm_act_request_get_secrets (NMActRequest *self,
flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED; flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED;
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self)); connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
call_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection), call_id_s = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection),
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)), nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)),
setting_name, setting_name,
flags, flags,
hints, hints,
get_secrets_cb, get_secrets_cb,
info, info,
NULL); NULL);
if (call_id > 0) { if (call_id_s) {
info->call_id = call_id; info->call_id_s = call_id_s;
priv->secrets_calls = g_slist_append (priv->secrets_calls, info); priv->secrets_calls = g_slist_append (priv->secrets_calls, info);
} else } else
g_free (info); g_free (info);
return call_id; return info;
} }
void void
nm_act_request_cancel_secrets (NMActRequest *self, guint32 call_id) nm_act_request_cancel_secrets (NMActRequest *self, NMActRequestGetSecretsCallId call_id)
{ {
NMActRequestPrivate *priv; NMActRequestPrivate *priv;
NMConnection *connection; NMConnection *connection;
GSList *iter;
g_return_if_fail (self); g_return_if_fail (self);
g_return_if_fail (NM_IS_ACT_REQUEST (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); priv = NM_ACT_REQUEST_GET_PRIVATE (self);
if (g_slist_find (priv->secrets_calls, call_id))
g_return_if_reached ();
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self)); connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
for (iter = priv->secrets_calls; iter; iter = g_slist_next (iter)) { nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), call_id->call_id_s);
GetSecretsInfo *info = iter->data;
/* Remove the matching info */
if (info->call_id == 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);
g_free (info);
break;
}
}
} }
/********************************************************************/ /********************************************************************/
@@ -431,7 +445,6 @@ dispose (GObject *object)
{ {
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object); NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
NMConnection *connection; NMConnection *connection;
GSList *iter;
/* Clear any share rules */ /* Clear any share rules */
if (priv->share_rules) { if (priv->share_rules) {
@@ -441,14 +454,13 @@ dispose (GObject *object)
/* Kill any in-progress secrets requests */ /* Kill any in-progress secrets requests */
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object)); connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object));
for (iter = priv->secrets_calls; connection && iter; iter = g_slist_next (iter)) { while (priv->secrets_calls) {
GetSecretsInfo *info = iter->data; GetSecretsInfo *info = priv->secrets_calls->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_return_if_fail (!priv->secrets_calls || info != priv->secrets_calls->data);
} }
g_slist_free (priv->secrets_calls);
priv->secrets_calls = NULL;
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object); G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
} }

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_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)) #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 { struct _NMActRequest {
NMActiveConnection parent; NMActiveConnection parent;
}; };
@@ -62,19 +65,19 @@ void nm_act_request_add_share_rule (NMActRequest *req,
/* Secrets handling */ /* Secrets handling */
typedef void (*NMActRequestSecretsFunc) (NMActRequest *req, typedef void (*NMActRequestSecretsFunc) (NMActRequest *req,
guint32 call_id, NMActRequestGetSecretsCallId call_id,
NMConnection *connection, NMConnection *connection,
GError *error, GError *error,
gpointer user_data); gpointer user_data);
guint32 nm_act_request_get_secrets (NMActRequest *req, NMActRequestGetSecretsCallId nm_act_request_get_secrets (NMActRequest *req,
const char *setting_name, const char *setting_name,
NMSecretAgentGetSecretsFlags flags, NMSecretAgentGetSecretsFlags flags,
const char *hint, const char *hint,
NMActRequestSecretsFunc callback, NMActRequestSecretsFunc callback,
gpointer callback_data); 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__ */ #endif /* __NETWORKMANAGER_ACTIVATION_REQUEST_H__ */

View File

@@ -39,6 +39,7 @@ struct NMAuthChain {
GError *error; GError *error;
guint idle_id; guint idle_id;
gboolean done;
NMAuthChainResultFunc done_func; NMAuthChainResultFunc done_func;
gpointer user_data; gpointer user_data;
@@ -56,15 +57,26 @@ typedef struct {
GDestroyNotify destroy; GDestroyNotify destroy;
} ChainData; } ChainData;
static ChainData *
chain_data_new (gpointer data, GDestroyNotify destroy)
{
ChainData *tmp;
tmp = g_slice_new (ChainData);
tmp->data = data;
tmp->destroy = destroy;
return tmp;
}
static void static void
free_data (gpointer data) chain_data_free (gpointer data)
{ {
ChainData *tmp = data; ChainData *tmp = data;
if (tmp->destroy) if (tmp->destroy)
tmp->destroy (tmp->data); tmp->destroy (tmp->data);
memset (tmp, 0, sizeof (ChainData)); memset (tmp, 0, sizeof (ChainData));
g_free (tmp); g_slice_free (ChainData, tmp);
} }
static gboolean static gboolean
@@ -73,8 +85,9 @@ auth_chain_finish (gpointer user_data)
NMAuthChain *self = user_data; NMAuthChain *self = user_data;
self->idle_id = 0; self->idle_id = 0;
self->done = TRUE;
/* Ensure we say alive across the callback */ /* Ensure we stay alive across the callback */
self->refcount++; self->refcount++;
self->done_func (self, self->error, self->context, self->user_data); self->done_func (self, self->error, self->context, self->user_data);
nm_auth_chain_unref (self); nm_auth_chain_unref (self);
@@ -116,27 +129,33 @@ nm_auth_chain_new_subject (NMAuthSubject *subject,
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL); g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
g_return_val_if_fail (nm_auth_subject_is_unix_process (subject) || nm_auth_subject_is_internal (subject), NULL); g_return_val_if_fail (nm_auth_subject_is_unix_process (subject) || nm_auth_subject_is_internal (subject), NULL);
self = g_malloc0 (sizeof (NMAuthChain)); self = g_slice_new0 (NMAuthChain);
self->refcount = 1; self->refcount = 1;
self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_data); self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, chain_data_free);
self->done_func = done_func; self->done_func = done_func;
self->user_data = user_data; self->user_data = user_data;
self->context = context; self->context = context ? g_object_ref (context) : NULL;
self->subject = g_object_ref (subject); self->subject = g_object_ref (subject);
return self; return self;
} }
gpointer static gpointer
nm_auth_chain_get_data (NMAuthChain *self, const char *tag) _get_data (NMAuthChain *self, const char *tag)
{ {
ChainData *tmp; ChainData *tmp;
tmp = g_hash_table_lookup (self->data, tag);
return tmp ? tmp->data : NULL;
}
gpointer
nm_auth_chain_get_data (NMAuthChain *self, const char *tag)
{
g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (tag != NULL, NULL); g_return_val_if_fail (tag != NULL, NULL);
tmp = g_hash_table_lookup (self->data, tag); return _get_data (self, tag);
return tmp ? tmp->data : NULL;
} }
/** /**
@@ -165,7 +184,7 @@ nm_auth_chain_steal_data (NMAuthChain *self, const char *tag)
value = tmp->data; value = tmp->data;
/* Make sure the destroy handler isn't called when freeing */ /* Make sure the destroy handler isn't called when freeing */
tmp->destroy = NULL; tmp->destroy = NULL;
free_data (tmp); chain_data_free (tmp);
g_free (orig_key); g_free (orig_key);
} }
return value; return value;
@@ -177,35 +196,30 @@ nm_auth_chain_set_data (NMAuthChain *self,
gpointer data, gpointer data,
GDestroyNotify data_destroy) GDestroyNotify data_destroy)
{ {
ChainData *tmp;
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
g_return_if_fail (tag != NULL); g_return_if_fail (tag != NULL);
if (data == NULL) if (data == NULL)
g_hash_table_remove (self->data, tag); g_hash_table_remove (self->data, tag);
else { else {
tmp = g_malloc0 (sizeof (ChainData)); g_hash_table_insert (self->data,
tmp->data = data; g_strdup (tag),
tmp->destroy = data_destroy; chain_data_new (data, data_destroy));
g_hash_table_insert (self->data, g_strdup (tag), tmp);
} }
} }
gulong gulong
nm_auth_chain_get_data_ulong (NMAuthChain *self, const char *tag) nm_auth_chain_get_data_ulong (NMAuthChain *self, const char *tag)
{ {
gulong *ptr; gulong *data;
g_return_val_if_fail (self != NULL, 0); g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (tag != NULL, 0); g_return_val_if_fail (tag != NULL, 0);
ptr = nm_auth_chain_get_data (self, tag); data = _get_data (self, tag);
return *ptr; return data ? *data : 0ul;
} }
void void
nm_auth_chain_set_data_ulong (NMAuthChain *self, nm_auth_chain_set_data_ulong (NMAuthChain *self,
const char *tag, const char *tag,
@@ -232,30 +246,13 @@ nm_auth_chain_get_subject (NMAuthChain *self)
NMAuthCallResult NMAuthCallResult
nm_auth_chain_get_result (NMAuthChain *self, const char *permission) nm_auth_chain_get_result (NMAuthChain *self, const char *permission)
{ {
gpointer data;
g_return_val_if_fail (self != NULL, NM_AUTH_CALL_RESULT_UNKNOWN); g_return_val_if_fail (self != NULL, NM_AUTH_CALL_RESULT_UNKNOWN);
g_return_val_if_fail (permission != NULL, NM_AUTH_CALL_RESULT_UNKNOWN); g_return_val_if_fail (permission != NULL, NM_AUTH_CALL_RESULT_UNKNOWN);
return GPOINTER_TO_UINT (nm_auth_chain_get_data (self, permission)); data = _get_data (self, permission);
} return data ? GPOINTER_TO_UINT (data) : NM_AUTH_CALL_RESULT_UNKNOWN;
static void
nm_auth_chain_check_done (NMAuthChain *self)
{
g_return_if_fail (self != NULL);
if (g_slist_length (self->calls) == 0) {
g_assert (self->idle_id == 0);
self->idle_id = g_idle_add (auth_chain_finish, self);
}
}
static void
nm_auth_chain_remove_call (NMAuthChain *self, AuthCall *call)
{
g_return_if_fail (self != NULL);
g_return_if_fail (call != NULL);
self->calls = g_slist_remove (self->calls, call);
} }
static AuthCall * static AuthCall *
@@ -263,10 +260,9 @@ auth_call_new (NMAuthChain *chain, const char *permission)
{ {
AuthCall *call; AuthCall *call;
call = g_malloc0 (sizeof (AuthCall)); call = g_slice_new0 (AuthCall);
call->chain = chain; call->chain = chain;
call->permission = g_strdup (permission); call->permission = g_strdup (permission);
chain->calls = g_slist_append (chain->calls, call);
return call; return call;
} }
@@ -275,15 +271,27 @@ auth_call_free (AuthCall *call)
{ {
g_free (call->permission); g_free (call->permission);
g_clear_object (&call->cancellable); g_clear_object (&call->cancellable);
g_free (call); g_slice_free (AuthCall, call);
} }
/* This can get used from scheduled idles, hence the boolean return */
static gboolean static gboolean
auth_call_complete (AuthCall *call) auth_call_complete (AuthCall *call)
{ {
nm_auth_chain_remove_call (call->chain, call); NMAuthChain *self;
nm_auth_chain_check_done (call->chain);
g_return_val_if_fail (call, G_SOURCE_REMOVE);
self = call->chain;
g_return_val_if_fail (self, G_SOURCE_REMOVE);
g_return_val_if_fail (g_slist_find (self->calls, call), G_SOURCE_REMOVE);
self->calls = g_slist_remove (self->calls, call);
if (!self->calls) {
g_assert (!self->idle_id && !self->done);
self->idle_id = g_idle_add (auth_chain_finish, self);
}
auth_call_free (call); auth_call_free (call);
return FALSE; return FALSE;
} }
@@ -367,8 +375,10 @@ nm_auth_chain_add_call (NMAuthChain *self,
g_return_if_fail (permission && *permission); g_return_if_fail (permission && *permission);
g_return_if_fail (self->subject); g_return_if_fail (self->subject);
g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject)); g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
g_return_if_fail (!self->idle_id && !self->done);
call = auth_call_new (self, permission); call = auth_call_new (self, permission);
self->calls = g_slist_append (self->calls, call);
if ( nm_auth_subject_is_internal (self->subject) if ( nm_auth_subject_is_internal (self->subject)
|| nm_auth_subject_get_unix_process_uid (self->subject) == 0 || nm_auth_subject_get_unix_process_uid (self->subject) == 0
@@ -398,10 +408,21 @@ nm_auth_chain_add_call (NMAuthChain *self,
} }
} }
/**
* nm_auth_chain_unref:
* @self: the auth-chain
*
* Unrefs the auth-chain. By unrefing the auth-chain, you also cancel
* the receipt of the done-callback. IOW, the callback will not be invoked.
*
* The only exception is, if you call nm_auth_chain_unref() from inside
* the callback. In this case, @self stays alive until the callback returns.
*/
void void
nm_auth_chain_unref (NMAuthChain *self) nm_auth_chain_unref (NMAuthChain *self)
{ {
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
g_return_if_fail (self->refcount > 0);
self->refcount--; self->refcount--;
if (self->refcount > 0) if (self->refcount > 0)
@@ -412,13 +433,16 @@ nm_auth_chain_unref (NMAuthChain *self)
g_object_unref (self->subject); g_object_unref (self->subject);
if (self->context)
g_object_unref (self->context);
g_slist_free_full (self->calls, auth_call_cancel); g_slist_free_full (self->calls, auth_call_cancel);
g_clear_error (&self->error); g_clear_error (&self->error);
g_hash_table_destroy (self->data); g_hash_table_destroy (self->data);
memset (self, 0, sizeof (NMAuthChain)); memset (self, 0, sizeof (NMAuthChain));
g_free (self); g_slice_free (NMAuthChain, self);
} }
/************ utils **************/ /************ utils **************/

View File

@@ -63,7 +63,7 @@ typedef struct {
NMActRequest *act_req; NMActRequest *act_req;
GDBusMethodInvocation *pending_secrets_context; GDBusMethodInvocation *pending_secrets_context;
guint32 secrets_id; NMActRequestGetSecretsCallId secrets_id;
const char *secrets_setting_name; const char *secrets_setting_name;
guint32 ppp_watch_id; guint32 ppp_watch_id;
@@ -229,7 +229,7 @@ static void
remove_timeout_handler (NMPPPManager *manager) remove_timeout_handler (NMPPPManager *manager)
{ {
NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager);
if (priv->ppp_timeout_handler) { if (priv->ppp_timeout_handler) {
g_source_remove (priv->ppp_timeout_handler); g_source_remove (priv->ppp_timeout_handler);
priv->ppp_timeout_handler = 0; priv->ppp_timeout_handler = 0;
@@ -241,11 +241,10 @@ cancel_get_secrets (NMPPPManager *self)
{ {
NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self);
if (priv->secrets_id) { if (priv->secrets_id)
nm_act_request_cancel_secrets (priv->act_req, priv->secrets_id); nm_act_request_cancel_secrets (priv->act_req, priv->secrets_id);
priv->secrets_id = 0;
} g_return_if_fail (!priv->secrets_id && !priv->secrets_setting_name);
priv->secrets_setting_name = NULL;
} }
static gboolean static gboolean
@@ -309,7 +308,7 @@ extract_details_from_connection (NMConnection *connection,
static void static void
ppp_secrets_cb (NMActRequest *req, ppp_secrets_cb (NMActRequest *req,
guint32 call_id, NMActRequestGetSecretsCallId call_id,
NMConnection *connection, NMConnection *connection,
GError *error, GError *error,
gpointer user_data) gpointer user_data)
@@ -324,6 +323,9 @@ ppp_secrets_cb (NMActRequest *req,
g_return_if_fail (req == priv->act_req); g_return_if_fail (req == priv->act_req);
g_return_if_fail (call_id == priv->secrets_id); g_return_if_fail (call_id == priv->secrets_id);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
goto out;
if (error) { if (error) {
nm_log_warn (LOGD_PPP, "%s", error->message); nm_log_warn (LOGD_PPP, "%s", error->message);
g_dbus_method_invocation_return_gerror (priv->pending_secrets_context, error); g_dbus_method_invocation_return_gerror (priv->pending_secrets_context, error);
@@ -348,7 +350,7 @@ ppp_secrets_cb (NMActRequest *req,
out: out:
priv->pending_secrets_context = NULL; priv->pending_secrets_context = NULL;
priv->secrets_id = 0; priv->secrets_id = NULL;
priv->secrets_setting_name = NULL; priv->secrets_setting_name = NULL;
} }

File diff suppressed because it is too large Load Diff

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_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)) #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 { struct _NMAgentManager {
NMExportedObject parent; 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 */ /* If no agent fulfilled the secrets request, agent_dbus_owner will be NULL */
typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager, typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager,
guint32 call_id, NMAgentManagerCallId call_id,
const char *agent_dbus_owner, const char *agent_dbus_owner,
const char *agent_uname, const char *agent_uname,
gboolean agent_has_modify, gboolean agent_has_modify,
@@ -62,27 +65,27 @@ typedef void (*NMAgentSecretsResultFunc) (NMAgentManager *manager,
gpointer other_data2, gpointer other_data2,
gpointer other_data3); gpointer other_data3);
guint32 nm_agent_manager_get_secrets (NMAgentManager *manager, NMAgentManagerCallId nm_agent_manager_get_secrets (NMAgentManager *manager,
NMConnection *connection, NMConnection *connection,
NMAuthSubject *subject, NMAuthSubject *subject,
GVariant *existing_secrets, GVariant *existing_secrets,
const char *setting_name, const char *setting_name,
NMSecretAgentGetSecretsFlags flags, NMSecretAgentGetSecretsFlags flags,
const char **hints, const char **hints,
NMAgentSecretsResultFunc callback, NMAgentSecretsResultFunc callback,
gpointer callback_data, gpointer callback_data,
gpointer other_data2, gpointer other_data2,
gpointer other_data3); gpointer other_data3);
void nm_agent_manager_cancel_secrets (NMAgentManager *manager, void nm_agent_manager_cancel_secrets (NMAgentManager *manager,
guint32 request_id); NMAgentManagerCallId request_id);
guint32 nm_agent_manager_save_secrets (NMAgentManager *manager, void nm_agent_manager_save_secrets (NMAgentManager *manager,
NMConnection *connection, NMConnection *connection,
NMAuthSubject *subject); NMAuthSubject *subject);
guint32 nm_agent_manager_delete_secrets (NMAgentManager *manager, void nm_agent_manager_delete_secrets (NMAgentManager *manager,
NMConnection *connection); NMConnection *connection);
NMSecretAgent *nm_agent_manager_get_agent_by_user (NMAgentManager *manager, NMSecretAgent *nm_agent_manager_get_agent_by_user (NMAgentManager *manager,
const char *username); const char *username);

View File

@@ -446,6 +446,17 @@ do_cancel_secrets (NMSecretAgent *self, Request *r, gboolean disposing)
} }
} }
/**
* nm_secret_agent_cancel_secrets:
* @self: #NMSecretAgent instance
* @call_id: the call id to cancel
*
* It is an error to pass an invalid @call_id or a @call_id for an operation
* that already completed. NMSecretAgent will always invoke the callback,
* also for cancel() and dispose().
* In case of nm_secret_agent_cancel_secrets() this will synchronously invoke the
* callback before nm_secret_agent_cancel_secrets() returns.
*/
void void
nm_secret_agent_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId call_id) nm_secret_agent_cancel_secrets (NMSecretAgent *self, NMSecretAgentCallId call_id)
{ {

View File

@@ -72,6 +72,18 @@ G_DEFINE_TYPE_WITH_CODE (NMSettingsConnection, nm_settings_connection, NM_TYPE_E
NM_TYPE_SETTINGS_CONNECTION, \ NM_TYPE_SETTINGS_CONNECTION, \
NMSettingsConnectionPrivate)) 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 { enum {
PROP_0 = 0, PROP_0 = 0,
PROP_VISIBLE, PROP_VISIBLE,
@@ -103,7 +115,14 @@ typedef struct {
GSList *pending_auths; /* List of pending authentication requests */ GSList *pending_auths; /* List of pending authentication requests */
gboolean visible; /* Is this connection is visible by some session? */ 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). Note that
this list contains NMSettingsConnectionCallId, vs. NMAgentManagerCallId.
So, we should for example cancel the reqs_ext with nm_settings_connection_cancel_secrets()
instead of nm_agent_manager_cancel_secrets().
Actually, the difference doesn't matter, because both are indeed equivalent. */
/* Caches secrets from on-disk connections; were they not cached any /* Caches secrets from on-disk connections; were they not cached any
* call to nm_connection_clear_secrets() wipes them out and we'd have * call to nm_connection_clear_secrets() wipes them out and we'd have
@@ -792,9 +811,19 @@ new_secrets_commit_cb (NMSettingsConnection *self,
} }
} }
static void
_callback_nop (NMSettingsConnection *self,
NMSettingsConnectionCallId call_id,
const char *agent_username,
const char *setting_name,
GError *error,
gpointer user_data)
{
}
static void static void
agent_secrets_done_cb (NMAgentManager *manager, agent_secrets_done_cb (NMAgentManager *manager,
guint32 call_id, NMAgentManagerCallId call_id_a,
const char *agent_dbus_owner, const char *agent_dbus_owner,
const char *agent_username, const char *agent_username,
gboolean agent_has_modify, gboolean agent_has_modify,
@@ -806,6 +835,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
gpointer other_data2, gpointer other_data2,
gpointer other_data3) gpointer other_data3)
{ {
NMSettingsConnectionCallId call_id = NM_SETTINGS_CONNECTION_CALL_ID (call_id_a);
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data); NMSettingsConnection *self = NM_SETTINGS_CONNECTION (user_data);
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMSettingsConnectionSecretsFunc callback = other_data2; NMSettingsConnectionSecretsFunc callback = other_data2;
@@ -815,12 +845,16 @@ agent_secrets_done_cb (NMAgentManager *manager,
gboolean agent_had_system = FALSE; gboolean agent_had_system = FALSE;
ForEachSecretFlags cmp_flags = { NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_SECRET_FLAG_NONE }; ForEachSecretFlags cmp_flags = { NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_SECRET_FLAG_NONE };
if (!callback)
callback = _callback_nop;
g_return_if_fail (g_slist_find (priv->reqs_int, call_id));
priv->reqs_int = g_slist_remove (priv->reqs_int, call_id);
if (error) { if (error) {
_LOGD ("(%s:%u) secrets request error: (%d) %s", _LOGD ("(%s:%p) secrets request error: %s",
setting_name, setting_name, call_id, error->message);
call_id,
error->code,
error->message ? error->message : "(unknown)");
callback (self, call_id, NULL, setting_name, error, callback_data); callback (self, call_id, NULL, setting_name, error, callback_data);
return; return;
@@ -837,7 +871,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
g_assert (secrets); g_assert (secrets);
if (agent_dbus_owner) { if (agent_dbus_owner) {
_LOGD ("(%s:%u) secrets returned from agent %s", _LOGD ("(%s:%p) secrets returned from agent %s",
setting_name, setting_name,
call_id, call_id,
agent_dbus_owner); agent_dbus_owner);
@@ -854,7 +888,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
/* No user interaction was allowed when requesting secrets; the /* No user interaction was allowed when requesting secrets; the
* agent is being bad. Remove system-owned secrets. * 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, setting_name,
call_id, call_id,
agent_dbus_owner); agent_dbus_owner);
@@ -864,7 +898,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
/* Agent didn't successfully authenticate; clear system-owned secrets /* Agent didn't successfully authenticate; clear system-owned secrets
* from the secrets the agent returned. * 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, setting_name,
call_id); call_id);
@@ -872,12 +906,12 @@ agent_secrets_done_cb (NMAgentManager *manager,
} }
} }
} else { } else {
_LOGD ("(%s:%u) existing secrets returned", _LOGD ("(%s:%p) existing secrets returned",
setting_name, setting_name,
call_id); call_id);
} }
_LOGD ("(%s:%u) secrets request completed", _LOGD ("(%s:%p) secrets request completed",
setting_name, setting_name,
call_id); call_id);
@@ -914,19 +948,19 @@ agent_secrets_done_cb (NMAgentManager *manager,
* nothing has changed, since agent-owned secrets don't get saved here. * nothing has changed, since agent-owned secrets don't get saved here.
*/ */
if (agent_had_system) { if (agent_had_system) {
_LOGD ("(%s:%u) saving new secrets to backing storage", _LOGD ("(%s:%p) saving new secrets to backing storage",
setting_name, setting_name,
call_id); call_id);
nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, new_secrets_commit_cb, NULL); nm_settings_connection_commit_changes (self, NM_SETTINGS_CONNECTION_COMMIT_REASON_NONE, new_secrets_commit_cb, NULL);
} else { } else {
_LOGD ("(%s:%u) new agent secrets processed", _LOGD ("(%s:%p) new agent secrets processed",
setting_name, setting_name,
call_id); call_id);
} }
} else { } 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, setting_name,
call_id, call_id,
local ? local->code : -1, local ? local->code : -1,
@@ -934,7 +968,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
} }
g_variant_unref (filtered_secrets); g_variant_unref (filtered_secrets);
} else { } 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, setting_name,
call_id, call_id,
local ? local->code : -1, local ? local->code : -1,
@@ -961,9 +995,15 @@ agent_secrets_done_cb (NMAgentManager *manager,
* Retrieves secrets from persistent storage and queries any secret agents for * Retrieves secrets from persistent storage and queries any secret agents for
* additional secrets. * additional secrets.
* *
* Returns: a call ID which may be used to cancel the ongoing secrets request * With the returned call-id, the call can be cancelled. It is an error
* to cancel a call more then once or a call that already completed.
* The callback will always be invoked exactly once, also for cancellation
* and disposing of @self. In those latter cases, the callback will be invoked
* synchronously during cancellation/disposing.
*
* Returns: a call ID which may be used to cancel the ongoing secrets request.
**/ **/
guint32 NMSettingsConnectionCallId
nm_settings_connection_get_secrets (NMSettingsConnection *self, nm_settings_connection_get_secrets (NMSettingsConnection *self,
NMAuthSubject *subject, NMAuthSubject *subject,
const char *setting_name, const char *setting_name,
@@ -975,7 +1015,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
{ {
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
GVariant *existing_secrets; GVariant *existing_secrets;
guint32 call_id = 0; NMAgentManagerCallId call_id_a;
gs_free char *joined_hints = NULL; gs_free char *joined_hints = NULL;
/* Use priv->secrets to work around the fact that nm_connection_clear_secrets() /* Use priv->secrets to work around the fact that nm_connection_clear_secrets()
@@ -985,7 +1025,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"%s.%d - Internal error; secrets cache invalid.", "%s.%d - Internal error; secrets cache invalid.",
__FILE__, __LINE__); __FILE__, __LINE__);
return 0; return NULL;
} }
/* Make sure the request actually requests something we can return */ /* Make sure the request actually requests something we can return */
@@ -993,46 +1033,49 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND, g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
"%s.%d - Connection didn't have requested setting '%s'.", "%s.%d - Connection didn't have requested setting '%s'.",
__FILE__, __LINE__, setting_name); __FILE__, __LINE__, setting_name);
return 0; return NULL;
} }
existing_secrets = nm_connection_to_dbus (priv->system_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); existing_secrets = nm_connection_to_dbus (priv->system_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS);
if (existing_secrets) if (existing_secrets)
g_variant_ref_sink (existing_secrets); g_variant_ref_sink (existing_secrets);
call_id = nm_agent_manager_get_secrets (priv->agent_mgr, call_id_a = nm_agent_manager_get_secrets (priv->agent_mgr,
NM_CONNECTION (self), NM_CONNECTION (self),
subject, subject,
existing_secrets, existing_secrets,
setting_name, setting_name,
flags, flags,
hints, hints,
agent_secrets_done_cb, agent_secrets_done_cb,
self, self,
callback, callback,
callback_data); callback_data);
if (existing_secrets) if (existing_secrets)
g_variant_unref (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, setting_name,
call_id, call_id_a,
flags, flags,
(hints && hints[0]) ? (joined_hints = g_strjoinv (",", (char **) hints)) : "(none)"); (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 void
nm_settings_connection_cancel_secrets (NMSettingsConnection *self, nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
guint32 call_id) NMSettingsConnectionCallId call_id)
{ {
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
_LOGD ("(%u) secrets canceled", if (!g_slist_find (priv->reqs_int, call_id))
call_id); g_return_if_reached ();
priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id)); _LOGD ("(%p) secrets canceled", call_id);
nm_agent_manager_cancel_secrets (priv->agent_mgr, call_id);
nm_agent_manager_cancel_secrets (priv->agent_mgr, NM_AGENT_MANAGER_CALL_ID (call_id));
} }
/**** User authorization **************************************/ /**** User authorization **************************************/
@@ -1606,7 +1649,7 @@ impl_settings_connection_delete (NMSettingsConnection *self,
{ {
NMAuthSubject *subject = NULL; NMAuthSubject *subject = NULL;
GError *error = NULL; GError *error = NULL;
if (!check_writable (NM_CONNECTION (self), &error)) if (!check_writable (NM_CONNECTION (self), &error))
goto out_err; goto out_err;
@@ -1627,7 +1670,7 @@ out_err:
static void static void
dbus_get_agent_secrets_cb (NMSettingsConnection *self, dbus_get_agent_secrets_cb (NMSettingsConnection *self,
guint32 call_id, NMSettingsConnectionCallId call_id,
const char *agent_username, const char *agent_username,
const char *setting_name, const char *setting_name,
GError *error, GError *error,
@@ -1637,7 +1680,9 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self,
GDBusMethodInvocation *context = user_data; GDBusMethodInvocation *context = user_data;
GVariant *dict; GVariant *dict;
priv->reqs = g_slist_remove (priv->reqs, GUINT_TO_POINTER (call_id)); g_return_if_fail (g_slist_find (priv->reqs_ext, call_id));
priv->reqs_ext = g_slist_remove (priv->reqs_ext, call_id);
if (error) if (error)
g_dbus_method_invocation_return_gerror (context, error); g_dbus_method_invocation_return_gerror (context, error);
@@ -1655,7 +1700,7 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self,
} }
static void static void
dbus_get_secrets_auth_cb (NMSettingsConnection *self, dbus_get_secrets_auth_cb (NMSettingsConnection *self,
GDBusMethodInvocation *context, GDBusMethodInvocation *context,
NMAuthSubject *subject, NMAuthSubject *subject,
GError *error, GError *error,
@@ -1663,22 +1708,22 @@ dbus_get_secrets_auth_cb (NMSettingsConnection *self,
{ {
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
char *setting_name = user_data; char *setting_name = user_data;
guint32 call_id = 0; NMSettingsConnectionCallId call_id;
GError *local = NULL; GError *local = NULL;
if (!error) { if (!error) {
call_id = nm_settings_connection_get_secrets (self, call_id = nm_settings_connection_get_secrets (self,
subject, subject,
setting_name, setting_name,
NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED
| NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS, | NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS,
NULL, NULL,
dbus_get_agent_secrets_cb, dbus_get_agent_secrets_cb,
context, context,
&local); &local);
if (call_id > 0) { if (call_id) {
/* track the request and wait for the callback */ /* 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 +2379,37 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_settings_connection_parent_class)->constructed (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;
/* Cancel will invoke the complete callback, which in
* turn deletes the current call-id from the list. */
nm_agent_manager_cancel_secrets (agent_mgr, call_id_a);
g_return_if_fail (!*preqs || (call_id_a != (*preqs)->data));
}
}
static void static void
dispose (GObject *object) dispose (GObject *object)
{ {
NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object); NMSettingsConnection *self = NM_SETTINGS_CONNECTION (object);
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
GSList *iter;
_LOGD ("disposing"); _LOGD ("disposing");
/* Cancel in-progress secrets requests */
if (priv->agent_mgr) {
/* although @reqs_ext theoretically contains NMSettingsConnectionCallId,
* we still cancel it with nm_agent_manager_cancel_secrets() -- it is
* actually correct. */
_cancel_all (priv->agent_mgr, &priv->reqs_ext);
_cancel_all (priv->agent_mgr, &priv->reqs_int);
}
if (priv->updated_idle_id) { if (priv->updated_idle_id) {
g_source_remove (priv->updated_idle_id); g_source_remove (priv->updated_idle_id);
priv->updated_idle_id = 0; priv->updated_idle_id = 0;
@@ -2363,12 +2430,6 @@ dispose (GObject *object)
g_slist_free_full (priv->pending_auths, (GDestroyNotify) nm_auth_chain_unref); g_slist_free_full (priv->pending_auths, (GDestroyNotify) nm_auth_chain_unref);
priv->pending_auths = NULL; 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); g_clear_pointer (&priv->seen_bssids, (GDestroyNotify) g_hash_table_destroy);
set_visible (self, FALSE); set_visible (self, FALSE);

View File

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

View File

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