libnm-glib: use private connection before trying the system bus

Use the D-Bus connection helper whenever we need a connection to
NM, which by default tries to use a private connection instead of
the shared bus connection whenever the user is root.  Doing this
by default will not change the behavior of libnm-glib, and allows
tools like nmcli and libnm-glib-using clients to work in minimal
environments (those without a bus daemon) by default.
This commit is contained in:
Dan Williams 2012-12-03 15:36:46 -06:00
parent 661d09852d
commit a87b5a15df
6 changed files with 167 additions and 142 deletions

View file

@ -1271,25 +1271,9 @@ client_device_removed (NMObject *client, NMObject *device)
NMClient * NMClient *
nm_client_new (void) nm_client_new (void)
{ {
DBusGConnection *connection;
GError *err = NULL;
NMClient *client; NMClient *client;
#ifdef LIBNM_GLIB_TEST client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
#else
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
#endif
if (!connection) {
g_warning ("Couldn't connect to system bus: %s", err->message);
g_error_free (err);
return NULL;
}
client = g_object_new (NM_TYPE_CLIENT,
NM_OBJECT_DBUS_CONNECTION, connection,
NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
NULL);
_nm_object_ensure_inited (NM_OBJECT (client)); _nm_object_ensure_inited (NM_OBJECT (client));
return client; return client;
} }
@ -1323,32 +1307,15 @@ client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
* #NMRemoteSettings object. * #NMRemoteSettings object.
**/ **/
void void
nm_client_new_async (GCancellable *cancellable, GAsyncReadyCallback callback, nm_client_new_async (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
DBusGConnection *connection;
GError *err = NULL;
NMClient *client; NMClient *client;
GSimpleAsyncResult *simple; GSimpleAsyncResult *simple;
simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async); simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
client = g_object_new (NM_TYPE_CLIENT, NM_OBJECT_DBUS_PATH, NM_DBUS_PATH, NULL);
#ifdef LIBNM_GLIB_TEST
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
#else
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
#endif
if (!connection) {
g_simple_async_result_take_error (simple, err);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
return;
}
client = g_object_new (NM_TYPE_CLIENT,
NM_OBJECT_DBUS_CONNECTION, connection,
NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
NULL);
g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT, g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT,
cancellable, client_inited, simple); cancellable, client_inited, simple);
} }
@ -1495,18 +1462,23 @@ constructed (GObject *object)
object, object,
NULL); NULL);
priv->bus_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)), if (_nm_object_is_connection_private (NM_OBJECT (object)))
DBUS_SERVICE_DBUS, priv->manager_running = TRUE;
DBUS_PATH_DBUS, else {
DBUS_INTERFACE_DBUS); priv->bus_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
g_assert (priv->bus_proxy);
dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged", dbus_g_proxy_add_signal (priv->bus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID); G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->bus_proxy, dbus_g_proxy_connect_signal (priv->bus_proxy,
"NameOwnerChanged", "NameOwnerChanged",
G_CALLBACK (proxy_name_owner_changed), G_CALLBACK (proxy_name_owner_changed),
object, NULL); object, NULL);
}
g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED, g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED,
G_CALLBACK (wireless_enabled_cb), NULL); G_CALLBACK (wireless_enabled_cb), NULL);
@ -1527,13 +1499,15 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
if (!nm_client_parent_initable_iface->init (initable, cancellable, error)) if (!nm_client_parent_initable_iface->init (initable, cancellable, error))
return FALSE; return FALSE;
if (!dbus_g_proxy_call (priv->bus_proxy, if (!_nm_object_is_connection_private (NM_OBJECT (client))) {
"NameHasOwner", error, if (!dbus_g_proxy_call (priv->bus_proxy,
G_TYPE_STRING, NM_DBUS_SERVICE, "NameHasOwner", error,
G_TYPE_INVALID, G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_BOOLEAN, &priv->manager_running, G_TYPE_INVALID,
G_TYPE_INVALID)) G_TYPE_BOOLEAN, &priv->manager_running,
return FALSE; G_TYPE_INVALID))
return FALSE;
}
if (priv->manager_running && !get_permissions_sync (client, error)) if (priv->manager_running && !get_permissions_sync (client, error))
return FALSE; return FALSE;
@ -1589,6 +1563,22 @@ init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_
init_async_complete (init_data); init_async_complete (init_data);
} }
static void
finish_init (NMClientInitData *init_data)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client),
G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
init_async_got_properties, init_data);
init_data->properties_pending = TRUE;
dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
init_async_got_permissions, init_data, NULL,
G_TYPE_INVALID);
init_data->permissions_pending = TRUE;
}
static void static void
init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
gpointer user_data) gpointer user_data)
@ -1610,15 +1600,7 @@ init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
return; return;
} }
nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client), finish_init (init_data);
G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
init_async_got_properties, init_data);
init_data->properties_pending = TRUE;
dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
init_async_got_permissions, init_data, NULL,
G_TYPE_INVALID);
init_data->permissions_pending = TRUE;
} }
static void static void
@ -1635,12 +1617,16 @@ init_async (GAsyncInitable *initable, int io_priority,
user_data, init_async); user_data, init_async);
g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE); g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
/* Check if NM is running */ if (_nm_object_is_connection_private (NM_OBJECT (init_data->client)))
dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner", finish_init (init_data);
init_async_got_manager_running, else {
init_data, NULL, /* Check if NM is running */
G_TYPE_STRING, NM_DBUS_SERVICE, dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
G_TYPE_INVALID); init_async_got_manager_running,
init_data, NULL,
G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_INVALID);
}
} }
static gboolean static gboolean

View file

@ -43,6 +43,8 @@ DBusGProxy *_nm_object_new_proxy (NMObject *self,
const char *path, const char *path,
const char *interface); const char *interface);
gboolean _nm_object_is_connection_private (NMObject *self);
void _nm_object_register_properties (NMObject *object, void _nm_object_register_properties (NMObject *object,
DBusGProxy *proxy, DBusGProxy *proxy,
const NMPropertiesInfo *info); const NMPropertiesInfo *info);

View file

@ -259,15 +259,13 @@ set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec) const GValue *value, GParamSpec *pspec)
{ {
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object); NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
DBusGConnection *connection;
switch (prop_id) { switch (prop_id) {
case PROP_CONNECTION: case PROP_CONNECTION:
/* Construct only */ /* Construct only */
connection = (DBusGConnection *) g_value_get_boxed (value); priv->connection = g_value_dup_boxed (value);
if (!connection) if (!priv->connection)
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); priv->connection = _nm_dbus_new_connection (NULL);
priv->connection = dbus_g_connection_ref (connection);
break; break;
case PROP_PATH: case PROP_PATH:
/* Construct only */ /* Construct only */
@ -1459,3 +1457,9 @@ _nm_object_new_proxy (NMObject *self, const char *path, const char *interface)
return _nm_dbus_new_proxy_for_connection (priv->connection, path ? path : priv->path, interface); return _nm_dbus_new_proxy_for_connection (priv->connection, path ? path : priv->path, interface);
} }
gboolean
_nm_object_is_connection_private (NMObject *self)
{
return _nm_dbus_is_connection_private (NM_OBJECT_GET_PRIVATE (self)->connection);
}

View file

@ -512,8 +512,15 @@ set_property (GObject *object, guint prop_id,
case PROP_BUS: case PROP_BUS:
case PROP_DBUS_CONNECTION: case PROP_DBUS_CONNECTION:
/* Construct only */ /* Construct only */
if (g_value_get_boxed (value)) /* priv->bus is set from either of two properties so that it (a) remains
priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); * backwards compatible with the previous "bus" property, and that (b)
* it can be created just like an NMObject using the "dbus-connection",
* even though it's not a subclass of NMObject. So don't overwrite the
* a valid value that the other property set with NULL, if one of the
* properties isn't specified at construction time.
*/
if (!priv->bus)
priv->bus = g_value_dup_boxed (value);
break; break;
case PROP_DBUS_PATH: case PROP_DBUS_PATH:
/* Don't need to do anything; see constructor(). */ /* Don't need to do anything; see constructor(). */

View file

@ -32,6 +32,7 @@
#include "nm-object-private.h" #include "nm-object-private.h"
#include "nm-dbus-helpers-private.h" #include "nm-dbus-helpers-private.h"
#include "nm-glib-compat.h" #include "nm-glib-compat.h"
#include "nm-object-private.h"
static void nm_remote_settings_initable_iface_init (GInitableIface *iface); static void nm_remote_settings_initable_iface_init (GInitableIface *iface);
static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface); static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface);
@ -45,6 +46,7 @@ G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT,
typedef struct { typedef struct {
DBusGConnection *bus; DBusGConnection *bus;
gboolean private_bus;
gboolean inited; gboolean inited;
DBusGProxy *proxy; DBusGProxy *proxy;
@ -876,24 +878,26 @@ constructed (GObject *object)
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
/* D-Bus proxy for clearing connections on NameOwnerChanged */ if (priv->private_bus == FALSE) {
priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, /* D-Bus proxy for clearing connections on NameOwnerChanged */
"org.freedesktop.DBus", priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
"/org/freedesktop/DBus", DBUS_SERVICE_DBUS,
"org.freedesktop.DBus"); DBUS_PATH_DBUS,
g_assert (priv->dbus_proxy); DBUS_INTERFACE_DBUS);
g_assert (priv->dbus_proxy);
dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING, dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE, G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID); G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID); G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy, dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged", "NameOwnerChanged",
G_CALLBACK (name_owner_changed), G_CALLBACK (name_owner_changed),
object, NULL); object, NULL);
}
priv->proxy = _nm_dbus_new_proxy_for_connection (priv->bus, priv->proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
NM_DBUS_PATH_SETTINGS, NM_DBUS_PATH_SETTINGS,
@ -940,20 +944,23 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
GHashTable *props; GHashTable *props;
if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error, if (priv->private_bus == FALSE) {
G_TYPE_STRING, NM_DBUS_SERVICE, if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
G_TYPE_INVALID, G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_BOOLEAN, &priv->service_running, G_TYPE_INVALID,
G_TYPE_INVALID)) { G_TYPE_BOOLEAN, &priv->service_running,
priv->service_running = FALSE; G_TYPE_INVALID)) {
return FALSE; priv->service_running = FALSE;
} return FALSE;
}
/* If NM isn't running we'll grab properties from name_owner_changed() /* If NM isn't running we'll grab properties from name_owner_changed()
* when it starts. * when it starts.
*/ */
if (!priv->service_running) if (!priv->service_running)
return TRUE; return TRUE;
} else
priv->service_running = TRUE;
/* Get properties */ /* Get properties */
if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error, if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
@ -1023,6 +1030,17 @@ init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
init_async_complete (init_data); init_async_complete (init_data);
} }
static void
init_get_properties (NMRemoteSettingsInitData *init_data)
{
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
init_async_got_properties, init_data, NULL,
G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
G_TYPE_INVALID);
}
static void static void
init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call, init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
gpointer user_data) gpointer user_data)
@ -1045,10 +1063,7 @@ init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
return; return;
} }
dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", init_get_properties (init_data);
init_async_got_properties, init_data, NULL,
G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
G_TYPE_INVALID);
} }
static void static void
@ -1064,12 +1079,16 @@ init_async (GAsyncInitable *initable, int io_priority,
init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback, init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
user_data, init_async); user_data, init_async);
/* Check if NM is running */ if (priv->private_bus)
dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner", init_get_properties (init_data);
init_async_got_manager_running, else {
init_data, NULL, /* Check if NM is running */
G_TYPE_STRING, NM_DBUS_SERVICE, dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner",
G_TYPE_INVALID); init_async_got_manager_running,
init_data, NULL,
G_TYPE_STRING, NM_DBUS_SERVICE,
G_TYPE_INVALID);
}
} }
static gboolean static gboolean
@ -1127,15 +1146,15 @@ set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec) const GValue *value, GParamSpec *pspec)
{ {
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
DBusGConnection *connection;
switch (prop_id) { switch (prop_id) {
case PROP_BUS: case PROP_BUS:
/* Construct only */ /* Construct only */
connection = (DBusGConnection *) g_value_get_boxed (value); priv->bus = g_value_dup_boxed (value);
if (!connection) if (!priv->bus) {
connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); priv->bus = _nm_dbus_new_connection (NULL);
priv->bus = dbus_g_connection_ref (connection); priv->private_bus = _nm_dbus_is_connection_private (priv->bus);
}
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

View file

@ -66,6 +66,7 @@ typedef struct {
gboolean registered; gboolean registered;
DBusGConnection *bus; DBusGConnection *bus;
gboolean private_bus;
DBusGProxy *dbus_proxy; DBusGProxy *dbus_proxy;
DBusGProxy *manager_proxy; DBusGProxy *manager_proxy;
DBusGProxyCall *reg_call; DBusGProxyCall *reg_call;
@ -226,6 +227,12 @@ verify_sender (NMSecretAgent *self,
g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (context != NULL, FALSE);
/* Private bus connection is always to NetworkManager, which is always
* UID 0.
*/
if (priv->private_bus)
return TRUE;
/* Verify the sender's UID is 0, and that the sender is the same as /* Verify the sender's UID is 0, and that the sender is the same as
* NetworkManager's bus name owner. * NetworkManager's bus name owner.
*/ */
@ -796,34 +803,34 @@ nm_secret_agent_init (NMSecretAgent *self)
NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self); NMSecretAgentPrivate *priv = NM_SECRET_AGENT_GET_PRIVATE (self);
GError *error = NULL; GError *error = NULL;
priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); priv->bus = _nm_dbus_new_connection (&error);
if (!priv->bus) { if (!priv->bus) {
g_warning ("Couldn't connect to system bus: %s", error->message); g_warning ("Couldn't connect to system bus: %s", error->message);
g_error_free (error); g_error_free (error);
return; return;
} }
priv->private_bus = _nm_dbus_is_connection_private (priv->bus);
priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, if (priv->private_bus == FALSE) {
DBUS_SERVICE_DBUS, priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus,
DBUS_PATH_DBUS, DBUS_SERVICE_DBUS,
DBUS_INTERFACE_DBUS); DBUS_PATH_DBUS,
if (!priv->dbus_proxy) { DBUS_INTERFACE_DBUS);
g_warning ("Couldn't create messagebus proxy."); g_assert (priv->dbus_proxy);
return;
dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged",
G_CALLBACK (name_owner_changed),
self, NULL);
} }
dbus_g_object_register_marshaller (_nm_glib_marshal_VOID__STRING_STRING_STRING,
G_TYPE_NONE,
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged",
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->dbus_proxy,
"NameOwnerChanged",
G_CALLBACK (name_owner_changed),
self, NULL);
priv->manager_proxy = _nm_dbus_new_proxy_for_connection (priv->bus, priv->manager_proxy = _nm_dbus_new_proxy_for_connection (priv->bus,
NM_DBUS_PATH_AGENT_MANAGER, NM_DBUS_PATH_AGENT_MANAGER,
NM_DBUS_INTERFACE_AGENT_MANAGER); NM_DBUS_INTERFACE_AGENT_MANAGER);