agent-manager: merge branch 'th/agent-manager-cleanup'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/374
This commit is contained in:
Thomas Haller 2019-12-31 02:18:07 +01:00
commit e055bdbbc3
8 changed files with 247 additions and 222 deletions

View file

@ -608,21 +608,30 @@ g_hash_table_steal_extended (GHashTable *hash_table,
gpointer *stolen_key,
gpointer *stolen_value)
{
g_assert (stolen_key);
g_assert (stolen_value);
if (g_hash_table_lookup_extended (hash_table, lookup_key, stolen_key, stolen_value)) {
g_hash_table_steal (hash_table, lookup_key);
return TRUE;
}
if (stolen_key)
*stolen_key = NULL;
if (stolen_value)
*stolen_value = NULL;
*stolen_key = NULL;
*stolen_value = NULL;
return FALSE;
}
#else
#define g_hash_table_steal_extended(hash_table, lookup_key, stolen_key, stolen_value) \
({ \
gpointer *_stolen_key = (stolen_key); \
gpointer *_stolen_value = (stolen_value); \
\
/* we cannot allow NULL arguments, because then we would leak the values in
* the compat implementation. */ \
g_assert (_stolen_key); \
g_assert (_stolen_value); \
\
G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
g_hash_table_steal_extended (hash_table, lookup_key, stolen_key, stolen_value); \
g_hash_table_steal_extended (hash_table, lookup_key, _stolen_key, _stolen_value); \
G_GNUC_END_IGNORE_DEPRECATIONS \
})
#endif

View file

@ -16,7 +16,7 @@
/*****************************************************************************/
struct NMAuthChain {
struct _NMAuthChain {
CList parent_lst;
@ -266,6 +266,14 @@ nm_auth_chain_get_subject (NMAuthChain *self)
return self->subject;
}
GDBusMethodInvocation *
nm_auth_chain_get_context (NMAuthChain *self)
{
g_return_val_if_fail (self, NULL);
return self->context;
}
/*****************************************************************************/
static void

View file

@ -12,7 +12,7 @@
/*****************************************************************************/
typedef struct NMAuthChain NMAuthChain;
typedef struct _NMAuthChain NMAuthChain;
typedef void (*NMAuthChainResultFunc) (NMAuthChain *chain,
GDBusMethodInvocation *context,
@ -53,6 +53,8 @@ void nm_auth_chain_destroy (NMAuthChain *chain);
NMAuthSubject *nm_auth_chain_get_subject (NMAuthChain *self);
GDBusMethodInvocation *nm_auth_chain_get_context (NMAuthChain *self);
/*****************************************************************************/
struct CList;

View file

@ -35,15 +35,9 @@ typedef struct {
NMAuthManager *auth_mgr;
NMSessionMonitor *session_monitor;
/* Auth chains for checking agent permissions */
GSList *chains;
CList agent_lst_head;
/* Hashed by owner name, not identifier, since two agents in different
* sessions can use the same identifier.
*/
GHashTable *agents;
CList requests;
CList request_lst_head;
guint64 agent_version_id;
} NMAgentManagerPrivate;
@ -119,6 +113,8 @@ static void _con_del_request_start (Request *req);
static gboolean _con_get_try_complete_early (Request *req);
static void agent_disconnected_cb (NMSecretAgent *agent, gpointer user_data);
/*****************************************************************************/
guint64
@ -152,7 +148,7 @@ _request_type_to_string (RequestType request_type, gboolean verbose)
/*****************************************************************************/
struct _NMAgentManagerCallId {
CList lst_request;
CList request_lst;
NMAgentManager *self;
@ -201,40 +197,73 @@ struct _NMAgentManagerCallId {
/*****************************************************************************/
static gboolean
remove_agent (NMAgentManager *self, const char *owner)
static NMSecretAgent *
_agent_find_by_owner (NMAgentManagerPrivate *priv,
const char *owner)
{
NMSecretAgent *agent;
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst) {
if (nm_streq (nm_secret_agent_get_dbus_owner (agent), owner))
return agent;
}
return NULL;
}
static NMSecretAgent *
_agent_find_by_identifier_and_uid (NMAgentManagerPrivate *priv,
const char *identifier,
gulong sender_uid)
{
NMSecretAgent *agent;
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst) {
if ( nm_streq0 (nm_secret_agent_get_identifier (agent), identifier)
&& sender_uid == nm_secret_agent_get_owner_uid (agent))
return agent;
}
return NULL;
}
/*****************************************************************************/
static void
_agent_remove (NMAgentManager *self, NMSecretAgent *agent)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMSecretAgent *agent;
CList *iter, *safe;
g_return_val_if_fail (owner != NULL, FALSE);
/* Make sure this agent has already registered */
agent = g_hash_table_lookup (priv->agents, owner);
if (!agent)
return FALSE;
nm_assert (NM_IS_SECRET_AGENT (agent));
nm_assert (c_list_contains (&priv->agent_lst_head, &agent->agent_lst));
_LOGD (agent, "agent unregistered or disappeared");
/* Remove this agent from any in-progress secrets requests */
c_list_for_each_safe (iter, safe, &priv->requests)
request_remove_agent (c_list_entry (iter, Request, lst_request), agent);
nm_clear_pointer (&agent->auth_chain, nm_auth_chain_destroy);
/* And dispose of the agent */
g_hash_table_remove (priv->agents, owner);
return TRUE;
c_list_unlink (&agent->agent_lst);
g_signal_handlers_disconnect_by_func (agent, G_CALLBACK (agent_disconnected_cb), self);
/* Remove this agent from any in-progress secrets requests */
c_list_for_each_safe (iter, safe, &priv->request_lst_head)
request_remove_agent (c_list_entry (iter, Request, request_lst), agent);
g_object_unref (agent);
}
/* Call this *after* calling request_next_agent() */
static void
maybe_remove_agent_on_error (NMSecretAgent *agent,
maybe_remove_agent_on_error (NMAgentManager *self,
NMSecretAgent *agent,
GError *error)
{
if ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_DISCONNECTED)
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
remove_agent (nm_agent_manager_get (), nm_secret_agent_get_dbus_owner (agent));
if ( !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)
&& !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_DISCONNECTED)
&& !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER))
return;
if (!c_list_is_empty (&agent->agent_lst))
_agent_remove (self, agent);
}
/*****************************************************************************/
@ -295,70 +324,92 @@ validate_identifier (const char *identifier, GError **error)
}
static void
agent_register_permissions_done (NMAuthChain *chain,
GDBusMethodInvocation *context,
gpointer user_data)
_agent_permissions_check_done (NMAuthChain *chain,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMAgentManager *self = NM_AGENT_MANAGER (user_data);
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMSecretAgent *agent;
const char *sender;
NMAuthCallResult result;
CList *iter;
Request *request;
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
priv->chains = g_slist_remove (priv->chains, chain);
nm_assert (!context || G_IS_DBUS_METHOD_INVOCATION (context));
agent = nm_auth_chain_steal_data (chain, "agent");
nm_assert (agent);
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, TRUE);
nm_assert (NM_IS_SECRET_AGENT (agent));
nm_assert (agent->auth_chain == chain);
nm_assert (agent->fully_registered == (!context));
nm_assert (c_list_contains (&priv->agent_lst_head, &agent->agent_lst));
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
if (result == NM_AUTH_CALL_RESULT_YES)
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, TRUE);
agent->auth_chain = NULL;
nm_secret_agent_add_permission (agent,
NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED,
(nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED) == NM_AUTH_CALL_RESULT_YES));
nm_secret_agent_add_permission (agent,
NM_AUTH_PERMISSION_WIFI_SHARE_OPEN,
(nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN) == NM_AUTH_CALL_RESULT_YES));
if (agent->fully_registered) {
_LOGD (agent, "updated agent permissions");
return;
}
_LOGI (agent, "agent registered");
agent->fully_registered = TRUE;
priv->agent_version_id += 1;
sender = nm_secret_agent_get_dbus_owner (agent);
g_hash_table_insert (priv->agents, g_strdup (sender), agent);
_LOGI (agent, "agent registered");
g_dbus_method_invocation_return_value (context, NULL);
/* Signal an agent was registered */
g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
c_list_for_each_entry (request, &priv->request_lst_head, request_lst)
request_add_agent (request, agent);
/* Add this agent to any in-progress secrets requests */
c_list_for_each (iter, &priv->requests)
request_add_agent (c_list_entry (iter, Request, lst_request), agent);
g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
}
static NMSecretAgent *
find_agent_by_identifier_and_uid (NMAgentManager *self,
const char *identifier,
gulong sender_uid)
static NMAuthChain *
_agent_create_auth_chain (NMAgentManager *self,
NMSecretAgent *agent,
GDBusMethodInvocation *context)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMSecretAgent *agent;
NMAuthChain *chain;
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) {
if ( g_strcmp0 (nm_secret_agent_get_identifier (agent), identifier) == 0
&& nm_secret_agent_get_owner_uid (agent) == sender_uid)
return agent;
_LOGD (agent, "requesting permissions");
nm_assert ( !agent->auth_chain
|| (agent->fully_registered == (!nm_auth_chain_get_context (agent->auth_chain))));
if ( agent->auth_chain
&& !context
&& !agent->fully_registered) {
/* we restart the authorization check (without a @context), but the currently
* pending auth-chain carries a context. We need to pass it on as we replace
* the auth-chain. */
context = nm_auth_chain_get_context (agent->auth_chain);
nm_assert (context);
}
return NULL;
chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (agent),
context,
_agent_permissions_check_done,
self);
nm_auth_chain_set_data (chain, "agent", agent, NULL);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
nm_clear_pointer (&agent->auth_chain, nm_auth_chain_destroy);
agent->auth_chain = chain;
return chain;
}
static void
agent_disconnected_cb (NMSecretAgent *agent, gpointer user_data)
{
/* The agent quit, so remove it and let interested clients know */
remove_agent (NM_AGENT_MANAGER (user_data),
nm_secret_agent_get_dbus_owner (agent));
_agent_remove (NM_AGENT_MANAGER (user_data), agent);
}
static void
@ -368,65 +419,44 @@ agent_manager_register_with_capabilities (NMAgentManager *self,
guint32 capabilities)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMAuthSubject *subject;
gs_unref_object NMAuthSubject *subject = NULL;
gulong sender_uid = G_MAXULONG;
GError *error = NULL;
NMSecretAgent *agent;
NMAuthChain *chain;
subject = nm_dbus_manager_new_auth_subject_from_context (context);
if (!subject) {
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED,
NM_UTILS_ERROR_MSG_REQ_UID_UKNOWN);
goto done;
g_dbus_method_invocation_take_error (context, error);
return;
}
sender_uid = nm_auth_subject_get_unix_process_uid (subject);
/* Validate the identifier */
if (!validate_identifier (identifier, &error))
goto done;
if (!validate_identifier (identifier, &error)) {
g_dbus_method_invocation_take_error (context, error);
return;
}
/* Only one agent for each identifier is allowed per user */
if (find_agent_by_identifier_and_uid (self, identifier, sender_uid)) {
if (_agent_find_by_identifier_and_uid (priv, identifier, sender_uid)) {
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED,
"An agent with this ID is already registered for this user.");
goto done;
g_dbus_method_invocation_take_error (context, error);
return;
}
/* Success, add the new agent */
agent = nm_secret_agent_new (context, subject, identifier, capabilities);
if (!agent) {
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_FAILED,
"Failed to initialize the agent");
goto done;
}
g_signal_connect (agent, NM_SECRET_AGENT_DISCONNECTED,
G_CALLBACK (agent_disconnected_cb), self);
_LOGD (agent, "requesting permissions");
c_list_link_tail (&priv->agent_lst_head, &agent->agent_lst);
/* Kick off permissions requests for this agent */
chain = nm_auth_chain_new_subject (subject, context, agent_register_permissions_done, self);
if (chain) {
nm_auth_chain_set_data (chain, "agent", agent, g_object_unref);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
priv->chains = g_slist_append (priv->chains, chain);
} else {
g_object_unref (agent);
error = g_error_new_literal (NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_FAILED,
"Unable to start agent authentication.");
}
done:
if (error)
g_dbus_method_invocation_take_error (context, error);
g_clear_object (&subject);
_agent_create_auth_chain (self, agent, context);
}
static void
@ -470,8 +500,11 @@ impl_agent_manager_unregister (NMDBusObject *obj,
GVariant *parameters)
{
NMAgentManager *self = NM_AGENT_MANAGER (obj);
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMSecretAgent *agent;
if (!remove_agent (self, sender)) {
agent = _agent_find_by_owner (priv, sender);
if (!agent) {
g_dbus_method_invocation_return_error_literal (invocation,
NM_AGENT_MANAGER_ERROR,
NM_AGENT_MANAGER_ERROR_NOT_REGISTERED,
@ -479,6 +512,8 @@ impl_agent_manager_unregister (NMDBusObject *obj,
return;
}
_agent_remove (self, agent);
g_dbus_method_invocation_return_value (invocation, NULL);
}
@ -497,7 +532,7 @@ request_new (NMAgentManager *self,
req->request_type = request_type;
req->detail = g_strdup (detail);
req->subject = g_object_ref (subject);
c_list_link_tail (&NM_AGENT_MANAGER_GET_PRIVATE (self)->requests, &req->lst_request);
c_list_link_tail (&NM_AGENT_MANAGER_GET_PRIVATE (self)->request_lst_head, &req->request_lst);
return req;
}
@ -583,7 +618,7 @@ req_complete_cancel (Request *req, gboolean is_disposing)
gs_free_error GError *error = NULL;
nm_assert (req && req->self);
nm_assert (!c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (req->self)->requests, &req->lst_request));
nm_assert (!c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (req->self)->request_lst_head, &req->request_lst));
nm_utils_error_set_cancelled (&error, is_disposing, "NMAgentManager");
req_complete_release (req, NULL, NULL, NULL, error);
@ -598,9 +633,9 @@ req_complete (Request *req,
{
NMAgentManager *self = req->self;
nm_assert (c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (self)->requests, &req->lst_request));
nm_assert (c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (self)->request_lst_head, &req->request_lst));
c_list_unlink (&req->lst_request);
c_list_unlink (&req->request_lst);
req_complete_release (req, secrets, agent_dbus_owner, agent_username, error);
}
@ -710,12 +745,12 @@ static void
request_add_agents (NMAgentManager *self, Request *req)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
gpointer data;
NMSecretAgent *agent;
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, &data))
request_add_agent (req, NM_SECRET_AGENT (data));
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst) {
if (agent->fully_registered)
request_add_agent (req, agent);
}
}
static void
@ -868,7 +903,7 @@ _con_get_request_done (NMSecretAgent *agent,
/* Try the next agent */
request_next_agent (req);
maybe_remove_agent_on_error (agent, error);
maybe_remove_agent_on_error (self, agent, error);
}
return;
}
@ -1037,7 +1072,7 @@ _con_get_request_start (Request *req)
NULL,
_con_get_request_start_validated,
req);
g_assert (req->con.chain);
nm_assert (req->con.chain);
/* If the caller is the only user in the connection's permissions, then
* we use the 'modify.own' permission instead of 'modify.system'. If the
@ -1188,7 +1223,6 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
req->con.get.callback = callback;
req->con.get.callback_data = callback_data;
/* 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);
@ -1203,9 +1237,9 @@ nm_agent_manager_cancel_secrets (NMAgentManager *self,
g_return_if_fail (request_id);
g_return_if_fail (request_id->request_type == REQUEST_TYPE_CON_GET);
nm_assert (c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (self)->requests, &request_id->lst_request));
nm_assert (c_list_contains (&NM_AGENT_MANAGER_GET_PRIVATE (self)->request_lst_head, &request_id->request_lst));
c_list_unlink (&request_id->lst_request);
c_list_unlink (&request_id->request_lst);
req_complete_cancel (request_id, FALSE);
}
@ -1242,7 +1276,7 @@ _con_save_request_done (NMSecretAgent *agent,
LOG_REQ_ARG (req), error->message);
/* Try the next agent */
request_next_agent (req);
maybe_remove_agent_on_error (agent, error);
maybe_remove_agent_on_error (self, agent, error);
return;
}
@ -1291,7 +1325,6 @@ nm_agent_manager_save_secrets (NMAgentManager *self,
req->con.path = g_strdup (path);
req->con.connection = g_object_ref (connection);
/* Kick off the request */
request_add_agents (self, req);
req->idle_id = g_idle_add (request_start, req);
}
@ -1333,7 +1366,7 @@ _con_del_request_done (NMSecretAgent *agent,
/* Tell the next agent to delete secrets */
request_next_agent (req);
if (error)
maybe_remove_agent_on_error (agent, error);
maybe_remove_agent_on_error (self, agent, error);
}
static void
@ -1376,27 +1409,36 @@ nm_agent_manager_delete_secrets (NMAgentManager *self,
req->con.connection = g_object_ref (connection);
g_object_unref (subject);
/* Kick off the request */
request_add_agents (self, req);
req->idle_id = g_idle_add (request_start, req);
}
/*****************************************************************************/
NMSecretAgent *
nm_agent_manager_get_agent_by_user (NMAgentManager *self, const char *username)
gboolean
nm_agent_manager_has_agent_with_permission (NMAgentManager *self,
const char *username,
const char *permission)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMAgentManagerPrivate *priv;
NMSecretAgent *agent;
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) {
if (g_strcmp0 (nm_secret_agent_get_owner_username (agent), username) == 0)
return agent;
g_return_val_if_fail (NM_IS_AGENT_MANAGER (self), FALSE);
g_return_val_if_fail (username, FALSE);
g_return_val_if_fail (permission, FALSE);
priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst) {
if (!agent->fully_registered)
continue;
if (!nm_streq0 (nm_secret_agent_get_owner_username (agent), username))
continue;
if (nm_secret_agent_has_permission (agent, permission))
return TRUE;
}
return NULL;
return FALSE;
}
/*****************************************************************************/
@ -1407,17 +1449,16 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
NMSecretAgentCapabilities capability)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (manager);
GHashTableIter iter;
NMSecretAgent *agent;
gboolean subject_is_unix_process = (nm_auth_subject_get_subject_type (subject) == NM_AUTH_SUBJECT_TYPE_UNIX_PROCESS);
gulong subject_uid = subject_is_unix_process ? nm_auth_subject_get_unix_process_uid (subject) : 0u;
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) {
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst) {
if (!agent->fully_registered)
continue;
if ( subject_is_unix_process
&& nm_secret_agent_get_owner_uid (agent) != subject_uid)
continue;
if (!(nm_secret_agent_get_capabilities (agent) & capability))
return FALSE;
}
@ -1427,59 +1468,14 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
/*****************************************************************************/
static void
agent_permissions_changed_done (NMAuthChain *chain,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMAgentManager *self = NM_AGENT_MANAGER (user_data);
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
NMSecretAgent *agent;
gboolean share_protected = FALSE, share_open = FALSE;
priv->chains = g_slist_remove (priv->chains, chain);
agent = nm_auth_chain_get_data (chain, "agent");
g_assert (agent);
_LOGD (agent, "updated agent permissions");
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED) == NM_AUTH_CALL_RESULT_YES)
share_protected = TRUE;
if (nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN) == NM_AUTH_CALL_RESULT_YES)
share_open = TRUE;
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, share_protected);
nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, share_open);
}
static void
authority_changed_cb (NMAuthManager *auth_manager, NMAgentManager *self)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GHashTableIter iter;
NMSecretAgent *agent;
/* Recheck the permissions of all secret agents */
g_hash_table_iter_init (&iter, priv->agents);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &agent)) {
NMAuthChain *chain;
/* Kick off permissions requests for this agent */
chain = nm_auth_chain_new_subject (nm_secret_agent_get_subject (agent),
NULL,
agent_permissions_changed_done,
self);
g_assert (chain);
priv->chains = g_slist_append (priv->chains, chain);
/* Make sure if the agent quits while the permissions call is in progress
* that the object sticks around until our callback.
*/
nm_auth_chain_set_data (chain, "agent", g_object_ref (agent), g_object_unref);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
}
c_list_for_each_entry (agent, &priv->agent_lst_head, agent_lst)
_agent_create_auth_chain (self, agent, NULL);
}
/*****************************************************************************/
@ -1490,8 +1486,8 @@ nm_agent_manager_init (NMAgentManager *self)
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
priv->agent_version_id = 1;
c_list_init (&priv->requests);
priv->agents = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref);
c_list_init (&priv->agent_lst_head);
c_list_init (&priv->request_lst_head);
}
static void
@ -1515,23 +1511,18 @@ constructed (GObject *object)
static void
dispose (GObject *object)
{
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE ((NMAgentManager *) object);
CList *iter;
NMAgentManager *self = NM_AGENT_MANAGER (object);
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
Request *request;
NMSecretAgent *agent;
cancel_more:
c_list_for_each (iter, &priv->requests) {
c_list_unlink (iter);
req_complete_cancel (c_list_entry (iter, Request, lst_request), TRUE);
goto cancel_more;
while ((request = c_list_first_entry (&priv->request_lst_head, Request, request_lst))) {
c_list_unlink (&request->request_lst);
req_complete_cancel (request, TRUE);
}
g_slist_free_full (priv->chains, (GDestroyNotify) nm_auth_chain_destroy);
priv->chains = NULL;
if (priv->agents) {
g_hash_table_destroy (priv->agents);
priv->agents = NULL;
}
while ((agent = c_list_first_entry (&priv->agent_lst_head, NMSecretAgent, agent_lst)))
_agent_remove (self, agent);
if (priv->auth_mgr) {
g_signal_handlers_disconnect_by_func (priv->auth_mgr,

View file

@ -65,8 +65,9 @@ void nm_agent_manager_delete_secrets (NMAgentManager *manager,
const char *path,
NMConnection *connection);
NMSecretAgent *nm_agent_manager_get_agent_by_user (NMAgentManager *manager,
const char *username);
gboolean nm_agent_manager_has_agent_with_permission (NMAgentManager *self,
const char *username,
const char *permission);
gboolean nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
NMAuthSubject *subject,

View file

@ -34,33 +34,28 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
typedef struct _NMSecretAgentPrivate {
CList permissions;
CList requests;
GDBusConnection *dbus_connection;
char *description;
NMAuthSubject *subject;
char *identifier;
char *owner_username;
char *dbus_owner;
GDBusConnection *dbus_connection;
GCancellable *name_owner_cancellable;
CList requests;
NMSecretAgentCapabilities capabilities;
guint name_owner_changed_id;
NMSecretAgentCapabilities capabilities;
bool shutdown_wait_obj_registered:1;
} NMSecretAgentPrivate;
struct _NMSecretAgent {
GObject parent;
NMSecretAgentPrivate _priv;
};
struct _NMSecretAgentClass {
GObjectClass parent;
};
G_DEFINE_TYPE (NMSecretAgent, nm_secret_agent, G_TYPE_OBJECT)
#define NM_SECRET_AGENT_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSecretAgent, NM_IS_SECRET_AGENT)
#define NM_SECRET_AGENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMSecretAgent, NM_IS_SECRET_AGENT)
/*****************************************************************************/
@ -765,8 +760,13 @@ nm_secret_agent_new (GDBusMethodInvocation *context,
static void
nm_secret_agent_init (NMSecretAgent *self)
{
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
NMSecretAgentPrivate *priv;
priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_SECRET_AGENT, NMSecretAgentPrivate);
self->_priv = priv;
c_list_init (&self->agent_lst);
c_list_init (&priv->permissions);
c_list_init (&priv->requests);
}
@ -777,6 +777,8 @@ dispose (GObject *object)
NMSecretAgent *self = NM_SECRET_AGENT (object);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
nm_assert (c_list_is_empty (&self->agent_lst));
nm_assert (!self->auth_chain);
nm_assert (c_list_is_empty (&priv->requests));
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
@ -814,6 +816,8 @@ nm_secret_agent_class_init (NMSecretAgentClass *config_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (config_class);
g_type_class_add_private (object_class, sizeof (NMSecretAgentPrivate));
object_class->dispose = dispose;
object_class->finalize = finalize;

View file

@ -8,6 +8,8 @@
#include "nm-connection.h"
#include "c-list/src/c-list.h"
#define NM_TYPE_SECRET_AGENT (nm_secret_agent_get_type ())
#define NM_SECRET_AGENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgent))
#define NM_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SECRET_AGENT, NMSecretAgentClass))
@ -20,6 +22,17 @@
typedef struct _NMSecretAgentClass NMSecretAgentClass;
typedef struct _NMSecretAgentCallId NMSecretAgentCallId;
struct _NMAuthChain;
struct _NMSecretAgentPrivate;
struct _NMSecretAgent {
GObject parent;
CList agent_lst;
struct _NMAuthChain *auth_chain;
struct _NMSecretAgentPrivate *_priv;
bool fully_registered:1;
};
GType nm_secret_agent_get_type (void);
NMSecretAgent *nm_secret_agent_new (GDBusMethodInvocation *context,

View file

@ -409,10 +409,7 @@ nm_settings_connection_check_permission (NMSettingsConnection *self,
* either.
*/
if (nm_setting_connection_get_permission (s_con, i, NULL, &puser, NULL)) {
NMSecretAgent *agent = nm_agent_manager_get_agent_by_user (priv->agent_mgr, puser);
if ( agent
&& nm_secret_agent_has_permission (agent, permission))
if (nm_agent_manager_has_agent_with_permission (priv->agent_mgr, puser, permission))
return TRUE;
}
}