settings: rework NMSecretAgent disconnection detection

Have NMSecretAgent emit "disconnected" when it detects that it has
been disconnected, rather than having both the agent and the agent
manager monitor it separately.
This commit is contained in:
Dan Winship
2015-04-27 14:54:32 -04:00
parent 1bcf42f37b
commit 2a2fd1216b
3 changed files with 69 additions and 41 deletions

View File

@@ -50,7 +50,6 @@ G_DEFINE_TYPE (NMAgentManager, nm_agent_manager, NM_TYPE_EXPORTED_OBJECT)
NMAgentManagerPrivate)) NMAgentManagerPrivate))
typedef struct { typedef struct {
NMDBusManager *dbus_mgr;
NMAuthManager *auth_mgr; NMAuthManager *auth_mgr;
/* Auth chains for checking agent permissions */ /* Auth chains for checking agent permissions */
@@ -263,6 +262,14 @@ find_agent_by_identifier_and_uid (NMAgentManager *self,
return NULL; return NULL;
} }
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));
}
static void static void
impl_agent_manager_register_with_capabilities (NMAgentManager *self, impl_agent_manager_register_with_capabilities (NMAgentManager *self,
const char *identifier, const char *identifier,
@@ -305,6 +312,8 @@ impl_agent_manager_register_with_capabilities (NMAgentManager *self,
"Failed to initialize the agent"); "Failed to initialize the agent");
goto done; goto done;
} }
g_signal_connect (agent, NM_SECRET_AGENT_DISCONNECTED,
G_CALLBACK (agent_disconnected_cb), self);
nm_log_dbg (LOGD_AGENTS, "(%s) requesting permissions", nm_log_dbg (LOGD_AGENTS, "(%s) requesting permissions",
nm_secret_agent_get_description (agent)); nm_secret_agent_get_description (agent));
@@ -343,11 +352,10 @@ static void
impl_agent_manager_unregister (NMAgentManager *self, impl_agent_manager_unregister (NMAgentManager *self,
DBusGMethodInvocation *context) DBusGMethodInvocation *context)
{ {
NMAgentManagerPrivate *priv = NM_AGENT_MANAGER_GET_PRIVATE (self);
GError *error = NULL; GError *error = NULL;
char *sender = NULL; char *sender = NULL;
if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, if (!nm_dbus_manager_get_caller_info (nm_dbus_manager_get (),
context, context,
&sender, &sender,
NULL, NULL,
@@ -1450,19 +1458,6 @@ nm_agent_manager_all_agents_have_capability (NMAgentManager *manager,
/*************************************************************/ /*************************************************************/
static void
name_owner_changed_cb (NMDBusManager *dbus_mgr,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
{
if (old_owner) {
/* The agent quit, so remove it and let interested clients know */
remove_agent (NM_AGENT_MANAGER (user_data), old_owner);
}
}
static void static void
agent_permissions_changed_done (NMAuthChain *chain, agent_permissions_changed_done (NMAuthChain *chain,
GError *error, GError *error,
@@ -1550,16 +1545,10 @@ constructed (GObject *object)
G_OBJECT_CLASS (nm_agent_manager_parent_class)->constructed (object); G_OBJECT_CLASS (nm_agent_manager_parent_class)->constructed (object);
priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ());
priv->auth_mgr = g_object_ref (nm_auth_manager_get ()); priv->auth_mgr = g_object_ref (nm_auth_manager_get ());
nm_exported_object_export (NM_EXPORTED_OBJECT (object)); nm_exported_object_export (NM_EXPORTED_OBJECT (object));
g_signal_connect (priv->dbus_mgr,
NM_DBUS_MANAGER_NAME_OWNER_CHANGED,
G_CALLBACK (name_owner_changed_cb),
object);
g_signal_connect (priv->auth_mgr, g_signal_connect (priv->auth_mgr,
NM_AUTH_MANAGER_SIGNAL_CHANGED, NM_AUTH_MANAGER_SIGNAL_CHANGED,
G_CALLBACK (authority_changed_cb), G_CALLBACK (authority_changed_cb),
@@ -1589,13 +1578,8 @@ dispose (GObject *object)
object); object);
g_clear_object (&priv->auth_mgr); g_clear_object (&priv->auth_mgr);
} }
if (priv->dbus_mgr) {
g_signal_handlers_disconnect_by_func (priv->dbus_mgr, nm_exported_object_unexport (NM_EXPORTED_OBJECT (object));
G_CALLBACK (name_owner_changed_cb),
object);
nm_exported_object_unexport (NM_EXPORTED_OBJECT (object));
g_clear_object (&priv->dbus_mgr);
}
G_OBJECT_CLASS (nm_agent_manager_parent_class)->dispose (object); G_OBJECT_CLASS (nm_agent_manager_parent_class)->dispose (object);
} }

View File

@@ -47,17 +47,24 @@ typedef struct {
NMAuthSubject *subject; NMAuthSubject *subject;
char *identifier; char *identifier;
char *owner_username; char *owner_username;
char *dbus_owner;
NMSecretAgentCapabilities capabilities; NMSecretAgentCapabilities capabilities;
guint32 hash; guint32 hash;
GSList *permissions; GSList *permissions;
DBusGProxy *proxy; DBusGProxy *proxy;
guint proxy_destroy_id;
GHashTable *requests; GHashTable *requests;
} NMSecretAgentPrivate; } NMSecretAgentPrivate;
enum {
DISCONNECTED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
/*************************************************************/ /*************************************************************/
typedef struct { typedef struct {
@@ -107,7 +114,7 @@ nm_secret_agent_get_description (NMSecretAgent *agent)
priv = NM_SECRET_AGENT_GET_PRIVATE (agent); priv = NM_SECRET_AGENT_GET_PRIVATE (agent);
if (!priv->description) { if (!priv->description) {
priv->description = g_strdup_printf ("%s/%s/%lu", priv->description = g_strdup_printf ("%s/%s/%lu",
nm_auth_subject_get_unix_process_dbus_sender (priv->subject), priv->dbus_owner,
priv->identifier, priv->identifier,
nm_auth_subject_get_unix_process_uid (priv->subject)); nm_auth_subject_get_unix_process_uid (priv->subject));
} }
@@ -120,7 +127,7 @@ nm_secret_agent_get_dbus_owner (NMSecretAgent *agent)
{ {
g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL); g_return_val_if_fail (NM_IS_SECRET_AGENT (agent), NULL);
return nm_auth_subject_get_unix_process_dbus_sender (NM_SECRET_AGENT_GET_PRIVATE (agent)->subject); return NM_SECRET_AGENT_GET_PRIVATE (agent)->dbus_owner;
} }
const char * const char *
@@ -450,15 +457,35 @@ nm_secret_agent_delete_secrets (NMSecretAgent *self,
callback_data); callback_data);
} }
static void proxy_cleanup (NMSecretAgent *self);
static void
name_owner_changed_cb (NMDBusManager *dbus_mgr,
const char *name,
const char *old_owner,
const char *new_owner,
gpointer user_data)
{
NMSecretAgent *self = NM_SECRET_AGENT (user_data);
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
if (!new_owner && !g_strcmp0 (old_owner, priv->dbus_owner))
proxy_cleanup (self);
}
static void static void
proxy_cleanup (NMSecretAgent *self) proxy_cleanup (NMSecretAgent *self)
{ {
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
if (priv->proxy) { if (priv->proxy) {
g_signal_handler_disconnect (priv->proxy, priv->proxy_destroy_id); g_signal_handlers_disconnect_by_func (priv->proxy, proxy_cleanup, self);
priv->proxy_destroy_id = 0;
g_clear_object (&priv->proxy); g_clear_object (&priv->proxy);
g_signal_handlers_disconnect_by_func (nm_dbus_manager_get (), name_owner_changed_cb, self);
g_clear_pointer (&priv->dbus_owner, g_free);
g_signal_emit (self, signals[DISCONNECTED], 0);
} }
} }
@@ -472,7 +499,7 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
{ {
NMSecretAgent *self; NMSecretAgent *self;
NMSecretAgentPrivate *priv; NMSecretAgentPrivate *priv;
char *hash_str, *username; char *hash_str;
struct passwd *pw; struct passwd *pw;
g_return_val_if_fail (context != NULL, NULL); g_return_val_if_fail (context != NULL, NULL);
@@ -483,13 +510,13 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
pw = getpwuid (nm_auth_subject_get_unix_process_uid (subject)); pw = getpwuid (nm_auth_subject_get_unix_process_uid (subject));
g_return_val_if_fail (pw != NULL, NULL); g_return_val_if_fail (pw != NULL, NULL);
g_return_val_if_fail (pw->pw_name[0] != '\0', NULL); g_return_val_if_fail (pw->pw_name[0] != '\0', NULL);
username = g_strdup (pw->pw_name);
self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL); self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL);
priv = NM_SECRET_AGENT_GET_PRIVATE (self); priv = NM_SECRET_AGENT_GET_PRIVATE (self);
priv->identifier = g_strdup (identifier); priv->identifier = g_strdup (identifier);
priv->owner_username = g_strdup (username); priv->owner_username = g_strdup (pw->pw_name);
priv->dbus_owner = g_strdup (nm_auth_subject_get_unix_process_dbus_sender (subject));
priv->capabilities = capabilities; priv->capabilities = capabilities;
priv->subject = g_object_ref (subject); priv->subject = g_object_ref (subject);
@@ -499,14 +526,17 @@ nm_secret_agent_new (DBusGMethodInvocation *context,
priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (), priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (),
context, context,
nm_auth_subject_get_unix_process_dbus_sender (subject), priv->dbus_owner,
NM_DBUS_PATH_SECRET_AGENT, NM_DBUS_PATH_SECRET_AGENT,
NM_DBUS_INTERFACE_SECRET_AGENT); NM_DBUS_INTERFACE_SECRET_AGENT);
g_assert (priv->proxy); g_assert (priv->proxy);
priv->proxy_destroy_id = g_signal_connect_swapped (priv->proxy, "destroy", g_signal_connect_swapped (priv->proxy, "destroy",
G_CALLBACK (proxy_cleanup), self); G_CALLBACK (proxy_cleanup), self);
g_signal_connect (nm_dbus_manager_get (),
NM_DBUS_MANAGER_NAME_OWNER_CHANGED,
G_CALLBACK (name_owner_changed_cb),
self);
g_free (username);
return self; return self;
} }
@@ -555,5 +585,15 @@ nm_secret_agent_class_init (NMSecretAgentClass *config_class)
/* virtual methods */ /* virtual methods */
object_class->dispose = dispose; object_class->dispose = dispose;
object_class->finalize = finalize; object_class->finalize = finalize;
/* signals */
signals[DISCONNECTED] =
g_signal_new (NM_SECRET_AGENT_DISCONNECTED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMSecretAgentClass, disconnected),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
} }

View File

@@ -33,12 +33,16 @@
#define NM_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT)) #define NM_IS_SECRET_AGENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SECRET_AGENT))
#define NM_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentClass)) #define NM_SECRET_AGENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SECRET_AGENT, NMSecretAgentClass))
#define NM_SECRET_AGENT_DISCONNECTED "disconnected"
struct _NMSecretAgent { struct _NMSecretAgent {
GObject parent; GObject parent;
}; };
typedef struct { typedef struct {
GObjectClass parent; GObjectClass parent;
void (*disconnected) (NMSecretAgent *self);
} NMSecretAgentClass; } NMSecretAgentClass;
GType nm_secret_agent_get_type (void); GType nm_secret_agent_get_type (void);