summaryrefslogtreecommitdiff
path: root/src/settings/nm-agent-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-agent-manager.c')
-rw-r--r--src/settings/nm-agent-manager.c191
1 files changed, 179 insertions, 12 deletions
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index 8a5ea1068..5ccbdc672 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -49,6 +49,9 @@ typedef struct {
NMDBusManager *dbus_mgr;
NMSessionMonitor *session_monitor;
+ /* Auth chains for checking agent permissions */
+ GSList *chains;
+
/* Hashed by owner name, not identifier, since two agents in different
* sessions can use the same identifier.
*/
@@ -57,6 +60,14 @@ typedef struct {
GHashTable *requests;
} NMAgentManagerPrivate;
+enum {
+ AGENT_REGISTERED,
+
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
typedef struct _Request Request;
static void request_add_agent (Request *req,
@@ -218,6 +229,59 @@ validate_identifier (const char *identifier, GError **error)
}
static void
+agent_register_permissions_done (NMAuthChain *chain,
+ GError *error,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ NMAgentManager *self = NM_AGENT_MANAGER (user_data);
+ NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
+ NMSecretAgent *agent;
+ const char *sender;
+ GError *local = NULL;
+ NMAuthCallResult result;
+ GHashTableIter iter;
+ Request *req;
+
+ priv->chains = g_slist_remove (priv->chains, chain);
+
+ if (error) {
+ local = g_error_new (NM_AGENT_MANAGER_ERROR,
+ NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED,
+ "Failed to request agent permissions: (%d) %s",
+ error->code, error->message);
+ dbus_g_method_return_error (context, local);
+ g_error_free (local);
+ } else {
+ agent = nm_auth_chain_steal_data (chain, "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);
+
+ 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);
+
+ sender = nm_secret_agent_get_dbus_owner (agent);
+ g_hash_table_insert (priv->agents, g_strdup (sender), agent);
+ nm_log_dbg (LOGD_AGENTS, "(%s) agent registered",
+ nm_secret_agent_get_description (agent));
+ dbus_g_method_return (context);
+
+ /* Signal an agent was registered */
+ g_signal_emit (self, signals[AGENT_REGISTERED], 0, agent);
+
+ /* 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))
+ request_add_agent (req, agent, priv->session_monitor);
+ }
+
+ nm_auth_chain_unref (chain);
+}
+
+static void
impl_agent_manager_register (NMAgentManager *self,
const char *identifier,
DBusGMethodInvocation *context)
@@ -227,8 +291,7 @@ impl_agent_manager_register (NMAgentManager *self,
gulong sender_uid = G_MAXULONG;
GError *error = NULL, *local = NULL;
NMSecretAgent *agent;
- GHashTableIter iter;
- gpointer data;
+ NMAuthChain *chain;
if (!nm_auth_get_caller_uid (context,
priv->dbus_mgr,
@@ -272,15 +335,16 @@ impl_agent_manager_register (NMAgentManager *self,
goto done;
}
- g_hash_table_insert (priv->agents, g_strdup (sender), agent);
- nm_log_dbg (LOGD_AGENTS, "(%s) agent registered",
+ nm_log_dbg (LOGD_AGENTS, "(%s) requesting permissions",
nm_secret_agent_get_description (agent));
- dbus_g_method_return (context);
- /* 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, &data))
- request_add_agent ((Request *) data, agent, priv->session_monitor);
+ /* Kick off permissions requests for this agent */
+ chain = nm_auth_chain_new (context, NULL, agent_register_permissions_done, self);
+ 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);
done:
if (error)
@@ -945,8 +1009,8 @@ get_start (gpointer user_data)
g_clear_error (&error);
} else {
/* Do we have everything we need? */
- /* FIXME: handle second check for VPN connections */
- if ((nm_connection_need_secrets (tmp, NULL) == NULL) && (request_new == FALSE)) {
+ if ( (req->flags & NM_SETTINGS_GET_SECRETS_FLAG_ONLY_SYSTEM)
+ || ((nm_connection_need_secrets (tmp, NULL) == NULL) && (request_new == FALSE))) {
nm_log_dbg (LOGD_AGENTS, "(%p/%s) system settings secrets sufficient",
req, req->setting_name);
@@ -1059,7 +1123,8 @@ nm_agent_manager_get_secrets (NMAgentManager *self,
g_hash_table_insert (priv->requests, GUINT_TO_POINTER (req->reqid), req);
/* Kick off the request */
- request_add_agents (self, req);
+ if (!(req->flags & NM_SETTINGS_GET_SECRETS_FLAG_ONLY_SYSTEM))
+ request_add_agents (self, req);
req->idle_id = g_idle_add (get_start, req);
return req->reqid;
@@ -1277,6 +1342,24 @@ nm_agent_manager_delete_secrets (NMAgentManager *self,
/*************************************************************/
+NMSecretAgent *
+nm_agent_manager_get_agent_by_user (NMAgentManager *self, const char *username)
+{
+ NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
+ GHashTableIter iter;
+ 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;
+ }
+
+ return NULL;
+}
+
+/*************************************************************/
+
static void
name_owner_changed_cb (NMDBusManager *dbus_mgr,
const char *name,
@@ -1290,6 +1373,73 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr,
}
}
+static void
+agent_permissions_changed_done (NMAuthChain *chain,
+ GError *error,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ NMAgentManager *self = NM_AGENT_MANAGER (user_data);
+ NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
+ NMSecretAgent *agent;
+ NMAuthCallResult result;
+
+ priv->chains = g_slist_remove (priv->chains, chain);
+
+ agent = nm_auth_chain_get_data (chain, "agent");
+
+ if (error) {
+ nm_log_dbg (LOGD_AGENTS, "(%s) failed to request updated agent permissions",
+ nm_secret_agent_get_description (agent));
+ nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
+ nm_secret_agent_add_permission (agent, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
+ } else {
+ nm_log_dbg (LOGD_AGENTS, "(%s) updated agent permissions",
+ nm_secret_agent_get_description (agent));
+
+ result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
+ nm_secret_agent_add_permission (agent,
+ NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED,
+ (result == NM_AUTH_CALL_RESULT_YES));
+
+ result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
+ nm_secret_agent_add_permission (agent,
+ NM_AUTH_PERMISSION_WIFI_SHARE_OPEN,
+ (result == NM_AUTH_CALL_RESULT_YES));
+ }
+
+ nm_auth_chain_unref (chain);
+}
+
+static void
+authority_changed_cb (gpointer user_data)
+{
+ NMAgentManager *self = NM_AGENT_MANAGER (user_data);
+ 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;
+ const char *sender;
+
+ /* Kick off permissions requests for this agent */
+ sender = nm_secret_agent_get_dbus_owner (agent);
+ chain = nm_auth_chain_new_dbus_sender (sender, agent_permissions_changed_done, self);
+
+ /* 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);
+
+ priv->chains = g_slist_append (priv->chains, chain);
+ }
+}
+
/*************************************************************/
NMAgentManager *
@@ -1319,6 +1469,8 @@ nm_agent_manager_get (void)
G_CALLBACK (name_owner_changed_cb),
singleton);
+ nm_auth_changed_func_register (authority_changed_cb, singleton);
+
return singleton;
}
@@ -1342,6 +1494,10 @@ dispose (GObject *object)
if (!priv->disposed) {
priv->disposed = TRUE;
+ nm_auth_changed_func_unregister (authority_changed_cb, NM_AGENT_MANAGER (object));
+
+ g_slist_foreach (priv->chains, (GFunc) nm_auth_chain_unref, NULL);
+
g_hash_table_destroy (priv->agents);
g_hash_table_destroy (priv->requests);
@@ -1362,6 +1518,17 @@ nm_agent_manager_class_init (NMAgentManagerClass *agent_manager_class)
/* virtual methods */
object_class->dispose = dispose;
+ /* Signals */
+ signals[AGENT_REGISTERED] =
+ g_signal_new ("agent-registered",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMAgentManagerClass, agent_registered),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ G_TYPE_OBJECT);
+
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (agent_manager_class),
&dbus_glib_nm_agent_manager_object_info);