diff options
21 files changed, 511 insertions, 79 deletions
@@ -9,6 +9,60 @@ 2008-05-08 Tambet Ingo <tambet@gmail.com> + Use PolicyKit to authorize the system settings' AddConnection method + and the system settings connections' Update and Delete methods. + + * libnm-glib/nm-settings.c (impl_exported_connection_update) + (impl_exported_connection_delete, nm_exported_connection_update) + (nm_exported_connection_delete): Return boolean and fill GError + to notify the callers of the reasons why it might have failed. + + * libnm-glib/nm-dbus-settings-system.c + (nm_dbus_settings_system_add_connection): Return the error from dbus + call so that the callers can see why it failed. + + * libnm-glib/nm-dbus-connection.c (update, delete): Update the + signatures. + + * system-settings/src/nm-polkit-helpers.[ch]: Implement. + + * system-settings/src/nm-sysconfig-connection.[ch]: Implement. New + abstract base class that checks PolicyKit permissions. + + * system-settings/src/dbus-settings.c: + (impl_settings_add_connection): Check the policy before carring out + the request. + + * system-settings/plugins/keyfile/nm-keyfile-connection.c: + Inherit from NMSysconfigConnection, check the policies before + allowing updating or removing. + + * system-settings/plugins/ifcfg-suse/nm-suse-connection.c: + Inherit from NMSysconfigConnection. + + * introspection/nm-exported-connection.xml: Annotate "Update" and + "Delete" methods with async flag so that the implementations can get + access to DBusGMethodInvocation. + + * system-settings/src/dbus-settings.c + (settings_add_connection_check_privileges): Implement. + (impl_settings_add_connection): Check the privileges before adding a new + connection. Improve error reporting. + + * introspection/nm-settings-system.xml: Make the 'AddConnection' method + async so that the implementation can access DBusGMethodInvocation. + + * configure.in: Check for PolicyKit. + + * policy/org.freedesktop.network-manager-settings.system.policy: + New file. + + * policy/Makefile.am: Install the policy file. + + * configure.in: Add 'policy' subdir. + +2008-05-08 Tambet Ingo <tambet@gmail.com> + Rewrite the suse system settings plugin. * system-settings/plugins/ifcfg-suse/plugin.c: Rewrite. diff --git a/Makefile.am b/Makefile.am index cd4d3e4650..89f24b7c87 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,7 +34,8 @@ SUBDIRS = \ introspection \ callouts \ system-settings \ - tools + tools \ + policy EXTRA_DIST = \ CONTRIBUTING \ diff --git a/configure.in b/configure.in index 95e430a268..f138e0256b 100644 --- a/configure.in +++ b/configure.in @@ -219,6 +219,14 @@ PKG_CHECK_MODULES(LIBNL, libnl-1 >= 1.0-pre8) AC_SUBST(LIBNL_CFLAGS) AC_SUBST(LIBNL_LIBS) +PKG_CHECK_MODULES(POLKIT, polkit-dbus) + +AC_CHECK_PROG([POLKIT_POLICY_FILE_VALIDATE], + [polkit-policy-file-validate], [polkit-policy-file-validate]) +if test -z "$POLKIT_POLICY_FILE_VALIDATE"; then + AC_MSG_ERROR([polkit-policy-file-validate not found]) +fi + GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` AC_SUBST(GLIB_GENMARSHAL) @@ -331,6 +339,7 @@ man/Makefile man/NetworkManager.8 man/nm-tool.1 po/Makefile.in +policy/Makefile NetworkManager.pc ]) AC_OUTPUT diff --git a/introspection/nm-exported-connection.xml b/introspection/nm-exported-connection.xml index 251ccafd40..d0a8a707fa 100644 --- a/introspection/nm-exported-connection.xml +++ b/introspection/nm-exported-connection.xml @@ -23,6 +23,7 @@ Update the connection. </tp:docstring> <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_exported_connection_update"/> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <arg name="properties" type="a{sa{sv}}" direction="in"> <tp:docstring> New connection properties. @@ -35,6 +36,7 @@ Delete the connection. </tp:docstring> <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_exported_connection_delete"/> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> </method> <method name="GetSettings"> diff --git a/introspection/nm-settings-system.xml b/introspection/nm-settings-system.xml index a6e0e3b490..c7579714ef 100644 --- a/introspection/nm-settings-system.xml +++ b/introspection/nm-settings-system.xml @@ -11,6 +11,7 @@ Add new connection. </tp:docstring> <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_add_connection"/> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <arg name="connection" type="a{sa{sv}}" direction="in"> <tp:docstring> Connection properties. diff --git a/libnm-glib/nm-dbus-connection.c b/libnm-glib/nm-dbus-connection.c index 116bf557cf..ba649d9e08 100644 --- a/libnm-glib/nm-dbus-connection.c +++ b/libnm-glib/nm-dbus-connection.c @@ -69,28 +69,20 @@ get_secrets (NMExportedConnection *connection, g_warning ("Implement me"); } -static void -update (NMExportedConnection *exported, GHashTable *new_settings) +static gboolean +update (NMExportedConnection *exported, GHashTable *new_settings, GError **err) { NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported); - GError *err = NULL; - if (!org_freedesktop_NetworkManagerSettings_Connection_update (priv->proxy, new_settings, &err)) { - nm_warning ("Can not update dbus connection: %s", err->message); - g_error_free (err); - } + return org_freedesktop_NetworkManagerSettings_Connection_update (priv->proxy, new_settings, err); } -static void -delete (NMExportedConnection *exported) +static gboolean +delete (NMExportedConnection *exported, GError **err) { NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported); - GError *err = NULL; - if (!org_freedesktop_NetworkManagerSettings_Connection_delete (priv->proxy, &err)) { - nm_warning ("Can not delete dbus connection: %s", err->message); - g_error_free (err); - } + return org_freedesktop_NetworkManagerSettings_Connection_delete (priv->proxy, err); } static void diff --git a/libnm-glib/nm-dbus-settings-system.c b/libnm-glib/nm-dbus-settings-system.c index e1bd037cc0..9c4fbb78cb 100644 --- a/libnm-glib/nm-dbus-settings-system.c +++ b/libnm-glib/nm-dbus-settings-system.c @@ -37,27 +37,25 @@ nm_dbus_settings_system_new (DBusGConnection *dbus_connection) NULL); } -void +gboolean nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self, - NMConnection *connection) + NMConnection *connection, + GError **err) { NMDBusSettingsSystemPrivate *priv; GHashTable *settings; - GError *err = NULL; + gboolean ret; - g_return_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self)); - g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); settings = nm_connection_to_hash (connection); - org_freedesktop_NetworkManagerSettings_System_add_connection (priv->settings_proxy, settings, &err); - if (err) { - g_warning ("Could not add system settings: %s", err->message); - g_error_free (err); - } - + ret = org_freedesktop_NetworkManagerSettings_System_add_connection (priv->settings_proxy, settings, err); g_hash_table_destroy (settings); + + return ret; } static void diff --git a/libnm-glib/nm-dbus-settings-system.h b/libnm-glib/nm-dbus-settings-system.h index a378ad63cd..30146c6fb0 100644 --- a/libnm-glib/nm-dbus-settings-system.h +++ b/libnm-glib/nm-dbus-settings-system.h @@ -28,8 +28,9 @@ GType nm_dbus_settings_system_get_type (void); NMDBusSettingsSystem *nm_dbus_settings_system_new (DBusGConnection *dbus_connection); -void nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self, - NMConnection *connection); +gboolean nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self, + NMConnection *connection, + GError **err); GSList *nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self); diff --git a/libnm-glib/nm-settings.c b/libnm-glib/nm-settings.c index c8e5a064fe..303f93cfc5 100644 --- a/libnm-glib/nm-settings.c +++ b/libnm-glib/nm-settings.c @@ -131,10 +131,10 @@ static gboolean impl_exported_connection_get_settings (NMExportedConnection *con static gboolean impl_exported_connection_update (NMExportedConnection *connection, GHashTable *new_settings, - GError *err); + DBusGMethodInvocation *context); static gboolean impl_exported_connection_delete (NMExportedConnection *connection, - GError *err); + DBusGMethodInvocation *context); static void impl_exported_connection_get_secrets (NMExportedConnection *connection, const gchar *setting_name, @@ -241,19 +241,46 @@ impl_exported_connection_get_settings (NMExportedConnection *connection, static gboolean impl_exported_connection_update (NMExportedConnection *connection, GHashTable *new_settings, - GError *err) + DBusGMethodInvocation *context) { - nm_exported_connection_update (connection, new_settings); + GError *err = NULL; + gboolean success; + + /* A hack to share the DBusGMethodInvocation with the possible overriders of connection::delete */ + g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context); + success = nm_exported_connection_update (connection, new_settings, &err); + g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL); + + if (success) { + dbus_g_method_return (context); + } else { + dbus_g_method_return_error (context, err); + g_error_free (err); + } - return TRUE; + return success; } static gboolean -impl_exported_connection_delete (NMExportedConnection *connection, GError *err) +impl_exported_connection_delete (NMExportedConnection *connection, + DBusGMethodInvocation *context) { - nm_exported_connection_delete (connection); + GError *err = NULL; + gboolean success; + + /* A hack to share the DBusGMethodInvocation with the possible overriders of connection::delete */ + g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context); + success = nm_exported_connection_delete (connection, &err); + g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL); + + if (success) { + dbus_g_method_return (context); + } else { + dbus_g_method_return_error (context, err); + g_error_free (err); + } - return TRUE; + return success; } static void @@ -425,30 +452,41 @@ nm_exported_connection_register_object (NMExportedConnection *connection, g_free (path); } -void +gboolean nm_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings) + GHashTable *new_settings, + GError **err) { - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); - g_return_if_fail (new_settings != NULL); + gboolean success = TRUE; - nm_connection_replace_settings (NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped, new_settings); + g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE); + g_return_val_if_fail (new_settings != NULL, FALSE); if (EXPORTED_CONNECTION_CLASS (connection)->update) - EXPORTED_CONNECTION_CLASS (connection)->update (connection, new_settings); + success = EXPORTED_CONNECTION_CLASS (connection)->update (connection, new_settings, err); - nm_exported_connection_signal_updated (connection, new_settings); + if (success) { + nm_connection_replace_settings (NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped, new_settings); + nm_exported_connection_signal_updated (connection, new_settings); + } + + return success; } -void -nm_exported_connection_delete (NMExportedConnection *connection) +gboolean +nm_exported_connection_delete (NMExportedConnection *connection, GError **err) { - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); + gboolean success = TRUE; + + g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE); if (EXPORTED_CONNECTION_CLASS (connection)->delete) - EXPORTED_CONNECTION_CLASS (connection)->delete (connection); + success = EXPORTED_CONNECTION_CLASS (connection)->delete (connection, err); + + if (success) + nm_exported_connection_signal_removed (connection); - nm_exported_connection_signal_removed (connection); + return success; } void diff --git a/libnm-glib/nm-settings.h b/libnm-glib/nm-settings.h index 58d15f1365..35c5022848 100644 --- a/libnm-glib/nm-settings.h +++ b/libnm-glib/nm-settings.h @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ #ifndef __NM_SETTINGS_H__ #define __NM_SETTINGS_H__ @@ -21,6 +22,8 @@ GQuark nm_settings_error_quark (void); #define NM_EXPORTED_CONNECTION_CONNECTION "connection" +#define NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION "nm-exported-connection-dbus-method-invocation" + typedef struct { GObject parent; } NMExportedConnection; @@ -37,10 +40,12 @@ typedef struct { gboolean request_new, DBusGMethodInvocation *context); - void (*update) (NMExportedConnection *connection, - GHashTable *new_settings); + gboolean (*update) (NMExportedConnection *connection, + GHashTable *new_settings, + GError **err); - void (*delete) (NMExportedConnection *connection); + gboolean (*delete) (NMExportedConnection *connection, + GError **err); /* signals */ void (* updated) (NMExportedConnection *connection, GHashTable *settings); @@ -59,13 +64,15 @@ NMConnection *nm_exported_connection_get_connection (NMExportedConnection *conne const char *nm_exported_connection_get_id (NMExportedConnection *connection); -void nm_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings); +gboolean nm_exported_connection_update (NMExportedConnection *connection, + GHashTable *new_settings, + GError **err); -void nm_exported_connection_delete (NMExportedConnection *connection); +gboolean nm_exported_connection_delete (NMExportedConnection *connection, + GError **err); void nm_exported_connection_signal_updated (NMExportedConnection *connection, - GHashTable *new_settings); + GHashTable *new_settings); void nm_exported_connection_signal_removed (NMExportedConnection *connection); diff --git a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c b/system-settings/plugins/ifcfg-suse/nm-suse-connection.c index 2f31e6e3bb..470a8a8e65 100644 --- a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c +++ b/system-settings/plugins/ifcfg-suse/nm-suse-connection.c @@ -7,7 +7,7 @@ #include "nm-suse-connection.h" #include "parser.h" -G_DEFINE_TYPE (NMSuseConnection, nm_suse_connection, NM_TYPE_EXPORTED_CONNECTION) +G_DEFINE_TYPE (NMSuseConnection, nm_suse_connection, NM_TYPE_SYSCONFIG_CONNECTION) #define NM_SUSE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionPrivate)) @@ -37,14 +37,14 @@ file_changed (GFileMonitor *monitor, new_connection = parse_ifcfg (priv->iface, priv->dev_type); if (new_connection) { new_settings = nm_connection_to_hash (new_connection); - nm_exported_connection_update (exported, new_settings); + nm_exported_connection_update (exported, new_settings, NULL); g_hash_table_destroy (new_settings); g_object_unref (new_connection); } else - nm_exported_connection_delete (exported); + nm_exported_connection_delete (exported, NULL); break; case G_FILE_MONITOR_EVENT_DELETED: - nm_exported_connection_delete (exported); + nm_exported_connection_delete (exported, NULL); break; default: break; diff --git a/system-settings/plugins/ifcfg-suse/nm-suse-connection.h b/system-settings/plugins/ifcfg-suse/nm-suse-connection.h index 571ead62ba..75d5337b5c 100644 --- a/system-settings/plugins/ifcfg-suse/nm-suse-connection.h +++ b/system-settings/plugins/ifcfg-suse/nm-suse-connection.h @@ -4,7 +4,7 @@ #define NM_SUSE_CONNECTION_H #include <NetworkManager.h> -#include <nm-settings.h> +#include <nm-sysconfig-connection.h> G_BEGIN_DECLS @@ -16,11 +16,11 @@ G_BEGIN_DECLS #define NM_SUSE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionClass)) typedef struct { - NMExportedConnection parent; + NMSysconfigConnection parent; } NMSuseConnection; typedef struct { - NMExportedConnectionClass parent; + NMSysconfigConnectionClass parent; } NMSuseConnectionClass; GType nm_suse_connection_get_type (void); diff --git a/system-settings/plugins/keyfile/nm-keyfile-connection.c b/system-settings/plugins/keyfile/nm-keyfile-connection.c index d653874f41..b64f2c9146 100644 --- a/system-settings/plugins/keyfile/nm-keyfile-connection.c +++ b/system-settings/plugins/keyfile/nm-keyfile-connection.c @@ -7,7 +7,7 @@ #include "reader.h" #include "writer.h" -G_DEFINE_TYPE (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_EXPORTED_CONNECTION) +G_DEFINE_TYPE (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SYSCONFIG_CONNECTION) #define NM_KEYFILE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_KEYFILE_CONNECTION, NMKeyfileConnectionPrivate)) @@ -52,18 +52,33 @@ get_id (NMExportedConnection *exported) return NM_KEYFILE_CONNECTION_GET_PRIVATE (exported)->filename; } -static void -update (NMExportedConnection *exported, GHashTable *new_settings) +static gboolean +update (NMExportedConnection *exported, + GHashTable *new_settings, + GError **err) { - write_connection (nm_exported_connection_get_connection (exported)); + gboolean success; + + success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, err); + + if (success) + write_connection (nm_exported_connection_get_connection (exported)); + + return success; } -static void -delete (NMExportedConnection *exported) +static gboolean +delete (NMExportedConnection *exported, GError **err) { NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported); + gboolean success; + + success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->delete (exported, err); + + if (success) + g_unlink (priv->filename); - g_unlink (priv->filename); + return success; } /* GObject */ diff --git a/system-settings/plugins/keyfile/nm-keyfile-connection.h b/system-settings/plugins/keyfile/nm-keyfile-connection.h index bdd538c31f..28dfa96490 100644 --- a/system-settings/plugins/keyfile/nm-keyfile-connection.h +++ b/system-settings/plugins/keyfile/nm-keyfile-connection.h @@ -3,7 +3,7 @@ #ifndef NM_KEYFILE_CONNECTION_H #define NM_KEYFILE_CONNECTION_H -#include <nm-settings.h> +#include <nm-sysconfig-connection.h> G_BEGIN_DECLS @@ -17,11 +17,11 @@ G_BEGIN_DECLS #define NM_KEYFILE_CONNECTION_FILENAME "filename" typedef struct { - NMExportedConnection parent; + NMSysconfigConnection parent; } NMKeyfileConnection; typedef struct { - NMExportedConnectionClass parent; + NMSysconfigConnectionClass parent; } NMKeyfileConnectionClass; GType nm_keyfile_connection_get_type (void); diff --git a/system-settings/plugins/keyfile/plugin.c b/system-settings/plugins/keyfile/plugin.c index 5be931f73b..5320fb22b4 100644 --- a/system-settings/plugins/keyfile/plugin.c +++ b/system-settings/plugins/keyfile/plugin.c @@ -101,6 +101,7 @@ dir_changed (GFileMonitor *monitor, nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection)); } break; + case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: if (connection) { /* Update */ @@ -111,7 +112,7 @@ dir_changed (GFileMonitor *monitor, GHashTable *settings; settings = nm_connection_to_hash (nm_exported_connection_get_connection (tmp)); - nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings); + nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL); g_hash_table_destroy (settings); g_object_unref (tmp); } diff --git a/system-settings/src/Makefile.am b/system-settings/src/Makefile.am index 24e1b9ded8..0fbf652190 100644 --- a/system-settings/src/Makefile.am +++ b/system-settings/src/Makefile.am @@ -13,11 +13,15 @@ nm_system_settings_SOURCES = \ dbus-settings.c \ dbus-settings.h \ main.c \ + nm-polkit-helpers.c \ + nm-polkit-helpers.h \ nm-system-config-interface.c \ nm-system-config-interface.h \ nm-system-config-hal-manager.c \ nm-system-config-hal-manager.h \ nm-system-config-hal-manager-private.h \ + nm-sysconfig-connection.c \ + nm-sysconfig-connection.h \ sha1.c \ sha1.h @@ -25,6 +29,7 @@ nm_system_settings_CPPFLAGS = \ $(DBUS_CFLAGS) \ $(GTHREAD_CFLAGS) \ $(GMODULE_CFLAGS) \ + $(POLKIT_CFLAGS) \ -DDBUS_API_SUBJECT_TO_CHANGE \ -DG_DISABLE_DEPRECATED \ -DBINDIR=\"$(bindir)\" \ @@ -40,6 +45,7 @@ nm_system_settings_LDADD = \ $(DBUS_LIBS) \ $(GTHREAD_LIBS) \ $(GMODULE_LIBS) \ + $(POLKIT_LIBS) \ $(top_builddir)/libnm-util/libnm-util.la \ $(top_builddir)/libnm-glib/libnm_glib.la \ $(top_builddir)/marshallers/libmarshallers.la diff --git a/system-settings/src/dbus-settings.c b/system-settings/src/dbus-settings.c index 6e741feb4f..0dd84d974b 100644 --- a/system-settings/src/dbus-settings.c +++ b/system-settings/src/dbus-settings.c @@ -25,15 +25,15 @@ #include <nm-connection.h> #include <dbus/dbus.h> #include <string.h> - #include <nm-setting-connection.h> #include "nm-dbus-glib-types.h" #include "dbus-settings.h" +#include "nm-polkit-helpers.h" #include "nm-utils.h" static gboolean -impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, GError **err); +impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, DBusGMethodInvocation *context); #include "nm-settings-system-glue.h" @@ -41,6 +41,7 @@ static void unmanaged_devices_changed (NMSystemConfigInterface *config, gpointer typedef struct { DBusGConnection *g_connection; + PolKitContext *pol_ctx; NMSystemConfigHalManager *hal_mgr; GSList *plugins; @@ -126,6 +127,9 @@ settings_finalize (GObject *object) g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); g_slist_free (priv->plugins); + if (priv->pol_ctx) + polkit_context_unref (priv->pol_ctx); + g_object_unref (priv->hal_mgr); dbus_g_connection_unref (priv->g_connection); @@ -218,7 +222,7 @@ nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) GObjectClass *object_class = G_OBJECT_CLASS (class); NMSettingsClass *settings_class = NM_SETTINGS_CLASS (class); - g_type_class_add_private (settings_class, sizeof (NMSysconfigSettingsPrivate)); + g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate)); /* virtual methods */ object_class->notify = notify; @@ -247,6 +251,8 @@ nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (settings_class), &dbus_glib_nm_settings_system_object_info); + + dbus_g_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR, NULL, NM_TYPE_SYSCONFIG_SETTINGS_ERROR); } static void @@ -256,6 +262,8 @@ nm_sysconfig_settings_init (NMSysconfigSettings *self) priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); priv->unmanaged_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + priv->pol_ctx = create_polkit_context (); } NMSysconfigSettings * @@ -404,13 +412,22 @@ nm_sysconfig_settings_is_device_managed (NMSysconfigSettings *self, } static gboolean -impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, GError **err) +impl_settings_add_connection (NMSysconfigSettings *self, + GHashTable *hash, + DBusGMethodInvocation *context) { + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); NMConnection *connection; + GError *err = NULL; + + if (!check_polkit_privileges (priv->g_connection, priv->pol_ctx, context, &err)) { + dbus_g_method_return_error (context, err); + g_error_free (err); + return FALSE; + } connection = nm_connection_new_from_hash (hash); if (connection) { - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); GSList *iter; /* Here's how it works: @@ -429,10 +446,15 @@ impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, GErro nm_system_config_interface_add_connection (NM_SYSTEM_CONFIG_INTERFACE (iter->data), connection); g_object_unref (connection); + dbus_g_method_return (context); return TRUE; } else { /* Invalid connection hash */ - /* FIXME: Set error */ + err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_INVALID_CONNECTION, + "%s", "Invalid connection"); + dbus_g_method_return_error (context, err); + g_error_free (err); return FALSE; } } diff --git a/system-settings/src/nm-polkit-helpers.c b/system-settings/src/nm-polkit-helpers.c new file mode 100644 index 0000000000..2a2382886f --- /dev/null +++ b/system-settings/src/nm-polkit-helpers.c @@ -0,0 +1,140 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include "nm-polkit-helpers.h" +#include <nm-dbus-settings.h> + +GQuark +nm_sysconfig_settings_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + ret = g_quark_from_static_string ("nm_sysconfig_settings_error"); + + return ret; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_sysconfig_settings_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, "GeneralError"), + ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, "NotPrivileged"), + ENUM_ENTRY (NM_SYSCONFIG_SETTINGS_ERROR_INVALID_CONNECTION, "InvalidConnection"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static ("NMSysconfigSettingsError", values); + } + + return etype; +} + +static gboolean +pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + int fd; + PolKitContext *pk_context = (PolKitContext *) user_data; + + fd = g_io_channel_unix_get_fd (channel); + polkit_context_io_func (pk_context, fd); + + return TRUE; +} + +static int +pk_io_add_watch (PolKitContext *pk_context, int fd) +{ + guint id = 0; + GIOChannel *channel; + + channel = g_io_channel_unix_new (fd); + if (channel == NULL) + goto out; + id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context); + if (id == 0) { + g_io_channel_unref (channel); + goto out; + } + g_io_channel_unref (channel); + + out: + return id; +} + +static void +pk_io_remove_watch (PolKitContext *pk_context, int watch_id) +{ + g_source_remove (watch_id); +} + +PolKitContext * +create_polkit_context (void) +{ + PolKitContext *pol_ctx; + PolKitError *err = NULL; + + pol_ctx = polkit_context_new (); + polkit_context_set_io_watch_functions (pol_ctx, pk_io_add_watch, pk_io_remove_watch); + if (!polkit_context_init (pol_ctx, &err)) { + g_warning ("Cannot initialize libpolkit: %s", polkit_error_get_error_message (err)); + polkit_error_free (err); + + polkit_context_unref (pol_ctx); + pol_ctx = NULL; + } + + return pol_ctx; +} + +gboolean +check_polkit_privileges (DBusGConnection *dbus_connection, + PolKitContext *pol_ctx, + DBusGMethodInvocation *context, + GError **err) +{ + DBusError dbus_error; + const char *sender; + PolKitCaller *pk_caller; + PolKitAction *pk_action; + PolKitResult pk_result; + + dbus_error_init (&dbus_error); + sender = dbus_g_method_get_sender (context); + pk_caller = polkit_caller_new_from_dbus_name (dbus_g_connection_get_connection (dbus_connection), + sender, + &dbus_error); + if (!pk_caller) { + *err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Error getting information about caller: %s: %s", + dbus_error.name, dbus_error.message); + dbus_error_free (&dbus_error); + polkit_caller_unref (pk_caller); + + return FALSE; + } + + pk_action = polkit_action_new (); + polkit_action_set_action_id (pk_action, NM_SYSCONFIG_POLICY_ACTION); + + pk_result = polkit_context_is_caller_authorized (pol_ctx, pk_action, pk_caller, TRUE, NULL); + polkit_caller_unref (pk_caller); + polkit_action_unref (pk_action); + + if (pk_result != POLKIT_RESULT_YES) { + *err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "%s %s", + NM_SYSCONFIG_POLICY_ACTION, + polkit_result_to_string_representation (pk_result)); + return FALSE; + } + + return TRUE; +} diff --git a/system-settings/src/nm-polkit-helpers.h b/system-settings/src/nm-polkit-helpers.h new file mode 100644 index 0000000000..6b200aceae --- /dev/null +++ b/system-settings/src/nm-polkit-helpers.h @@ -0,0 +1,30 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_POLKIT_HELPERS_H +#define NM_POLKIT_HELPERS_H + +#include <polkit-dbus/polkit-dbus.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify" + +enum { + NM_SYSCONFIG_SETTINGS_ERROR_GENERAL = 0, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + NM_SYSCONFIG_SETTINGS_ERROR_INVALID_CONNECTION +}; + +#define NM_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_quark ()) +#define NM_TYPE_SYSCONFIG_SETTINGS_ERROR (nm_sysconfig_settings_error_get_type ()) + +GQuark nm_sysconfig_settings_error_quark (void); +GType nm_sysconfig_settings_error_get_type (void); + +PolKitContext *create_polkit_context (void); +gboolean check_polkit_privileges (DBusGConnection *dbus_connection, + PolKitContext *pol_ctx, + DBusGMethodInvocation *context, + GError **err); + +#endif /* NM_POLKIT_HELPERS_H */ diff --git a/system-settings/src/nm-sysconfig-connection.c b/system-settings/src/nm-sysconfig-connection.c new file mode 100644 index 0000000000..4c1626cf35 --- /dev/null +++ b/system-settings/src/nm-sysconfig-connection.c @@ -0,0 +1,86 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#include <NetworkManager.h> +#include "nm-sysconfig-connection.h" +#include "nm-polkit-helpers.h" + +G_DEFINE_ABSTRACT_TYPE (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION) + +#define NM_SYSCONFIG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionPrivate)) + +typedef struct { + DBusGConnection *dbus_connection; + PolKitContext *pol_ctx; +} NMSysconfigConnectionPrivate; + +static gboolean +update (NMExportedConnection *exported, + GHashTable *new_settings, + GError **err) +{ + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported); + DBusGMethodInvocation *context; + + context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION); + g_return_val_if_fail (context != NULL, FALSE); + + return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err); +} + +static gboolean +delete (NMExportedConnection *exported, GError **err) +{ + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported); + DBusGMethodInvocation *context; + + context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION); + g_return_val_if_fail (context != NULL, FALSE); + + return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err); +} + +/* GObject */ + +static void +nm_sysconfig_connection_init (NMSysconfigConnection *self) +{ + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + GError *err = NULL; + + priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); + if (err) { + g_warning ("Could not get DBus connection: %s", err->message); + g_error_free (err); + } + + priv->pol_ctx = create_polkit_context (); +} + +static void +finalize (GObject *object) +{ + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (object); + + if (priv->pol_ctx) + polkit_context_unref (priv->pol_ctx); + + if (priv->dbus_connection) + dbus_g_connection_unref (priv->dbus_connection); + + G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->finalize (object); +} + +static void +nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *sysconfig_connection_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (sysconfig_connection_class); + NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (sysconfig_connection_class); + + g_type_class_add_private (sysconfig_connection_class, sizeof (NMSysconfigConnectionPrivate)); + + /* Virtual methods */ + object_class->finalize = finalize; + + connection_class->update = update; + connection_class->delete = delete; +} diff --git a/system-settings/src/nm-sysconfig-connection.h b/system-settings/src/nm-sysconfig-connection.h new file mode 100644 index 0000000000..8526460f86 --- /dev/null +++ b/system-settings/src/nm-sysconfig-connection.h @@ -0,0 +1,29 @@ +/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */ + +#ifndef NM_SYSCONFIG_CONNECTION_H +#define NM_SYSCONFIG_CONNECTION_H + +#include <nm-settings.h> + +G_BEGIN_DECLS + +#define NM_TYPE_SYSCONFIG_CONNECTION (nm_sysconfig_connection_get_type ()) +#define NM_SYSCONFIG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnection)) +#define NM_SYSCONFIG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionClass)) +#define NM_IS_SYSCONFIG_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSCONFIG_CONNECTION)) +#define NM_IS_SYSCONFIG_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SYSCONFIG_CONNECTION)) +#define NM_SYSCONFIG_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SYSCONFIG_CONNECTION, NMSysconfigConnectionClass)) + +typedef struct { + NMExportedConnection parent; +} NMSysconfigConnection; + +typedef struct { + NMExportedConnectionClass parent; +} NMSysconfigConnectionClass; + +GType nm_sysconfig_connection_get_type (void); + +G_END_DECLS + +#endif /* NM_SYSCONFIG_CONNECTION_H */ |