system-settings: add permissions
authorDan Williams <dcbw@redhat.com>
Mon, 24 Aug 2009 18:03:09 +0000 (13:03 -0500)
committerDan Williams <dcbw@redhat.com>
Mon, 24 Aug 2009 18:03:09 +0000 (13:03 -0500)
Since the new PolicyKit does away with easy checking of authorizations,
we get to implement it by ourselves, but that's OK since we can actually
use it for a lot more stuff.  So add the GetPermissions call which returns
the permissions the caller actually has, and a signal informing callers
that their permissions might have changed.  Hook this all up to
PolicyKit so it's useful.

introspection/nm-settings-system.xml
libnm-glib/libnm_glib.ver
libnm-glib/nm-remote-settings-system.c
libnm-glib/nm-settings-system-interface.c
libnm-glib/nm-settings-system-interface.h
policy/org.freedesktop.network-manager-settings.system.policy.in
src/system-settings/nm-polkit-helpers.h
src/system-settings/nm-sysconfig-connection.c
src/system-settings/nm-sysconfig-settings.c

index ff98719..598274c 100644 (file)
         </arg>
     </signal>
 
+    <signal name="CheckPermissions">
+      <tp:docstring>
+        Emitted when system authorization details change, indicating that clients may wish to recheck permissions with GetPermissions.
+      </tp:docstring>
+    </signal>
+
+    <method name="GetPermissions">
+      <tp:docstring>
+        Returns a bitfield indicating certain operations the caller is permitted to perform.  Some of these operations may require authorization by the user.
+      </tp:docstring>
+      <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_settings_get_permissions"/>
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+      <arg name="permissions" type="u" direction="out" tp:type="NM_SETTINGS_SYSTEM_PERMISSIONS">
+        <tp:docstring>
+          A bitfield of permitted operations.  Some of these operations may require the user to authorize via password entry or other means.
+        </tp:docstring>
+      </arg>
+    </method>
+
+    <tp:flags name="NM_SETTINGS_SYSTEM_PERMISSIONS" value-prefix="NM_SETTINGS_SYSTEM_PERMISSION" type="u">
+      <tp:flag suffix="NONE" value="0x0">
+        <tp:docstring>No permissions.</tp:docstring>
+      </tp:flag>
+      <tp:flag suffix="CONNECTION_MODIFY" value="0x1">
+        <tp:docstring>Can modify/add/delete connections.</tp:docstring>
+      </tp:flag>
+      <tp:flag suffix="WIFI_SHARING_PROTECTED" value="0x2">
+        <tp:docstring>Can share connections via a encrypted user-created WiFi network.</tp:docstring>
+      </tp:flag>
+      <tp:flag suffix="WIFI_SHARING_OPEN" value="0x4">
+        <tp:docstring>Can share connections via a open/unencrypted user-created WiFi network.</tp:docstring>
+      </tp:flag>
+      <tp:flag suffix="HOSTNAME_MODIFY" value="0x8">
+        <tp:docstring>Can modify the persistent system hostname.</tp:docstring>
+      </tp:flag>
+    </tp:flags>
+
   </interface>
 </node>
 
index f1ea6f0..342f713 100644 (file)
@@ -135,6 +135,7 @@ global:
        nm_settings_service_get_type;
        nm_settings_system_interface_get_type;
        nm_settings_system_interface_add_connection;
+       nm_settings_system_interface_get_permissions;
        nm_settings_system_interface_save_hostname;
        nm_settings_error_quark;
        nm_settings_get_type;
index fb9b0e2..34a810d 100644 (file)
@@ -105,9 +105,53 @@ save_hostname (NMSettingsSystemInterface *settings,
                   NMSettingsSystemSaveHostnameFunc callback,
                   gpointer user_data)
 {
+       // FIXME: implement using get_permissions as a template
        return FALSE;
 }
 
+typedef struct {
+       NMSettingsSystemInterface *settings;
+       NMSettingsSystemGetPermissionsFunc callback;
+       gpointer callback_data;
+} GetPermissionsInfo;
+
+static void
+get_permissions_cb  (DBusGProxy *proxy,
+                     DBusGProxyCall *call,
+                     gpointer user_data)
+{
+       GetPermissionsInfo *info = user_data;
+       NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
+       GError *error = NULL;
+
+       dbus_g_proxy_end_call (proxy, call, &error,
+                              G_TYPE_UINT, &permissions,
+                              G_TYPE_INVALID);
+       info->callback (info->settings, permissions, error, info->callback_data);
+       g_clear_error (&error);
+}
+
+static gboolean
+get_permissions (NMSettingsSystemInterface *settings,
+                 NMSettingsSystemGetPermissionsFunc callback,
+                 gpointer user_data)
+{
+       NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings);
+       GetPermissionsInfo *info;
+
+       info = g_malloc0 (sizeof (GetPermissionsInfo));
+       info->settings = settings;
+       info->callback = callback;
+       info->callback_data = user_data;
+
+       dbus_g_proxy_begin_call (priv->proxy, "GetPermissions",
+                                get_permissions_cb,
+                                info,
+                                g_free,
+                                G_TYPE_INVALID);
+       return TRUE;
+}
+
 /****************************************************************/
 
 static void
@@ -115,6 +159,7 @@ settings_system_interface_init (NMSettingsSystemInterface *klass)
 {
        /* interface implementation */
        klass->save_hostname = save_hostname;
+       klass->get_permissions = get_permissions;
 }
 
 /**
index 07114c0..8403793 100644 (file)
@@ -56,9 +56,33 @@ nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings,
        return FALSE;
 }
 
+/**
+ * nm_settings_system_interface_get_permissions:
+ * @settings: a object implementing %NMSettingsSystemInterface
+ * @callback: callback to be called when the permissions operation completes
+ * @user_data: caller-specific data passed to @callback
+ *
+ * Requests an indication of the operations the caller is permitted to perform
+ * including those that may require authorization.
+ **/
+gboolean
+nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
+                                              NMSettingsSystemGetPermissionsFunc callback,
+                                              gpointer user_data)
+{
+       g_return_val_if_fail (settings != NULL, FALSE);
+       g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE);
+       g_return_val_if_fail (callback != NULL, FALSE);
+
+       if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions)
+               return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions (settings, callback, user_data);
+       return FALSE;
+}
+
 static void
 nm_settings_system_interface_init (gpointer g_iface)
 {
+       GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
        static gboolean initialized = FALSE;
 
        if (initialized)
@@ -81,6 +105,15 @@ nm_settings_system_interface_init (gpointer g_iface)
                                       FALSE,
                                       G_PARAM_READABLE));
 
+       /* Signals */
+       g_signal_new (NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS,
+                                 iface_type,
+                                 G_SIGNAL_RUN_FIRST,
+                                 G_STRUCT_OFFSET (NMSettingsSystemInterface, check_permissions),
+                                 NULL, NULL,
+                                 g_cclosure_marshal_VOID__VOID,
+                                 G_TYPE_NONE, 0);
+
        initialized = TRUE;
 }
 
index 6f535aa..b4ea39e 100644 (file)
 
 #include "NetworkManager.h"
 
+typedef enum {
+       NM_SETTINGS_SYSTEM_PERMISSION_NONE = 0x0,
+       NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY = 0x1,
+       NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED = 0x2,
+       NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN = 0x4,
+       NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY = 0x8
+} NMSettingsSystemPermission;
+
 #define NM_TYPE_SETTINGS_SYSTEM_INTERFACE               (nm_settings_system_interface_get_type ())
 #define NM_SETTINGS_SYSTEM_INTERFACE(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface))
 #define NM_IS_SETTINGS_SYSTEM_INTERFACE(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE))
@@ -34,6 +42,8 @@
 #define NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME          "hostname"
 #define NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY        "can-modify"
 
+#define NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS "check-permissions"
+
 typedef enum {
        NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST = 0x1000,
 
@@ -49,6 +59,11 @@ typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *set
                                                   GError *error,
                                                   gpointer user_data);
 
+typedef void (*NMSettingsSystemGetPermissionsFunc) (NMSettingsSystemInterface *settings,
+                                                    NMSettingsSystemPermission permissions,
+                                                    GError *error,
+                                                    gpointer user_data);
+
 struct _NMSettingsSystemInterface {
        GTypeInterface g_iface;
 
@@ -57,6 +72,13 @@ struct _NMSettingsSystemInterface {
                                   const char *hostname,
                                   NMSettingsSystemSaveHostnameFunc callback,
                                   gpointer user_data);
+
+       gboolean (*get_permissions) (NMSettingsSystemInterface *settings,
+                                    NMSettingsSystemGetPermissionsFunc callback,
+                                    gpointer user_data);
+
+       /* Signals */
+       void (*check_permissions) (NMSettingsSystemInterface *settings);
 };
 
 GType nm_settings_system_interface_get_type (void);
@@ -66,4 +88,8 @@ gboolean nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *
                                                      NMSettingsSystemSaveHostnameFunc callback,
                                                      gpointer user_data);
 
+gboolean nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings,
+                                                       NMSettingsSystemGetPermissionsFunc callback,
+                                                       gpointer user_data);
+
 #endif /* NM_SETTINGS_SYSTEM_INTERFACE_H */
index 8b24a23..620e3a6 100644 (file)
     </defaults>
   </action>
 
+  <action id="org.freedesktop.network-manager-settings.system.hostname.modify">
+    <_description>Modify persistent system hostname</_description>
+    <_message>System policy prevents modification of the persistent system hostname</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.freedesktop.network-manager-settings.system.wifi.share.protected">
+    <_description>Connection sharing via a protected WiFi network</_description>
+    <_message>System policy prevents sharing connections via a protected WiFi network</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.freedesktop.network-manager-settings.system.wifi.share.open">
+    <_description>Connection sharing via an open WiFi network</_description>
+    <_message>System policy prevents sharing connections via an open WiFi network</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+  </action>
+
 </policyconfig>
index af7cd7a..c26fcc2 100644 (file)
@@ -24,6 +24,9 @@
 
 #include <polkit/polkit.h>
 
-#define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY    "org.freedesktop.network-manager-settings.system.modify"
+#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.network-manager-settings.system.wifi.share.protected"
+#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN      "org.freedesktop.network-manager-settings.system.wifi.share.open"
+#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY      "org.freedesktop.network-manager-settings.system.hostname.modify"
 
 #endif /* NM_POLKIT_HELPERS_H */
index b711c23..8be95f5 100644 (file)
@@ -296,7 +296,7 @@ dbus_update (NMExportedConnection *exported,
        g_assert (call);
        polkit_authority_check_authorization (priv->authority,
                                              call->subject,
-                                             NM_SYSCONFIG_POLICY_ACTION,
+                                             NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
                                              NULL,
                                              POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
                                              call->cancellable,
@@ -371,7 +371,7 @@ dbus_delete (NMExportedConnection *exported,
        g_assert (call);
        polkit_authority_check_authorization (priv->authority,
                                              call->subject,
-                                             NM_SYSCONFIG_POLICY_ACTION,
+                                             NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
                                              NULL,
                                              POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
                                              call->cancellable,
@@ -453,7 +453,7 @@ dbus_get_secrets (NMExportedConnection *exported,
        g_assert (call);
        polkit_authority_check_authorization (priv->authority,
                                              call->subject,
-                                             NM_SYSCONFIG_POLICY_ACTION,
+                                             NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
                                              NULL,
                                              POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
                                              call->cancellable,
index f07ab8d..6f925de 100644 (file)
@@ -70,6 +70,9 @@ static void impl_settings_save_hostname (NMSysconfigSettings *self,
                                          const char *hostname,
                                          DBusGMethodInvocation *context);
 
+static void impl_settings_get_permissions (NMSysconfigSettings *self,
+                                           DBusGMethodInvocation *context);
+
 #include "nm-settings-system-glue.h"
 
 static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data);
@@ -513,15 +516,19 @@ typedef struct {
        NMSysconfigSettings *self;
        DBusGMethodInvocation *context;
        PolkitSubject *subject;
-       GCancellable *cancellable;
 
        NMConnection *connection;
        NMSettingsAddConnectionFunc callback;
        gpointer callback_data;
 
        char *hostname;
+
+       NMSettingsSystemPermission permissions;
+       guint32 permissions_calls;
 } PolkitCall;
 
+#include "nm-dbus-manager.h"
+
 static PolkitCall *
 polkit_call_new (NMSysconfigSettings *self,
                  DBusGMethodInvocation *context,
@@ -547,7 +554,6 @@ polkit_call_new (NMSysconfigSettings *self,
        }
        if (hostname)
                call->hostname = g_strdup (hostname);
-       call->cancellable = g_cancellable_new ();
 
        sender = dbus_g_method_get_sender (context);
        call->subject = polkit_system_bus_name_new (sender);
@@ -563,7 +569,6 @@ polkit_call_free (PolkitCall *call)
                g_object_unref (call->connection);
        g_free (call->hostname);
        g_object_unref (call->subject);
-       g_object_unref (call->cancellable);
        g_free (call);
 }
 
@@ -670,10 +675,10 @@ add_connection (NMSettingsService *service,
        g_assert (call);
        polkit_authority_check_authorization (priv->authority,
                                              call->subject,
-                                             NM_SYSCONFIG_POLICY_ACTION,
+                                             NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
                                              NULL,
                                              POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
-                                             call->cancellable,
+                                             NULL,
                                              pk_add_cb,
                                              call);
 }
@@ -757,14 +762,169 @@ impl_settings_save_hostname (NMSysconfigSettings *self,
        g_assert (call);
        polkit_authority_check_authorization (priv->authority,
                                              call->subject,
-                                             NM_SYSCONFIG_POLICY_ACTION,
+                                             NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY,
                                              NULL,
                                              POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
-                                             call->cancellable,
+                                             NULL,
                                              pk_hostname_cb,
                                              call);
 }
 
+static void
+pk_authority_changed_cb (GObject *object, gpointer user_data)
+{
+       /* Let clients know they should re-check their authorization */
+       g_signal_emit_by_name (NM_SYSCONFIG_SETTINGS (user_data),
+                           NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS);
+}
+
+typedef struct {
+       PolkitCall *pk_call;
+       const char *pk_action;
+       NMSettingsSystemPermission permission;
+} PermissionsCall;
+
+static void
+permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+       PermissionsCall *call = user_data;
+       PolkitCall *pk_call = call->pk_call;
+       NMSysconfigSettings *self = pk_call->self;
+       NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+       PolkitAuthorizationResult *pk_result;
+       GError *error = NULL;
+
+       pk_result = polkit_authority_check_authorization_finish (priv->authority,
+                                                                result,
+                                                                &error);
+       /* Some random error happened */
+       if (error) {
+               g_warning ("%s.%d (%s): error checking '%s' permission: (%d) %s",
+                          __FILE__, __LINE__, __func__,
+                          call->pk_action,
+                          error ? error->code : -1,
+                          error && error->message ? error->message : "(unknown)");
+               if (error)
+                       g_error_free (error);
+       } else {
+               /* If the caller is authorized, or the caller could authorize via a
+                * challenge, then authorization is possible.  Otherwise, caller is out of
+                * luck.
+                */
+               if (   polkit_authorization_result_get_is_authorized (pk_result)
+                   || polkit_authorization_result_get_is_challenge (pk_result))
+                   pk_call->permissions |= call->permission;
+       }
+
+       g_object_unref (pk_result);
+
+       pk_call->permissions_calls--;
+       if (pk_call->permissions_calls == 0) {
+               /* All the permissions calls are done, return the full permissions
+                * bitfield back to the user.
+                */
+               dbus_g_method_return (pk_call->context, pk_call->permissions);
+
+               polkit_call_free (pk_call);
+       }
+       memset (call, 0, sizeof (PermissionsCall));
+       g_free (call);
+}
+
+static void
+start_permission_check (NMSysconfigSettings *self,
+                        PolkitCall *pk_call,
+                        const char *pk_action,
+                        NMSettingsSystemPermission permission)
+{
+       NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+       PermissionsCall *call;
+
+       g_return_if_fail (pk_call != NULL);
+       g_return_if_fail (pk_action != NULL);
+       g_return_if_fail (permission != NM_SETTINGS_SYSTEM_PERMISSION_NONE);
+
+       call = g_malloc0 (sizeof (PermissionsCall));
+       call->pk_call = pk_call;
+       call->pk_action = pk_action;
+       call->permission = permission;
+
+       pk_call->permissions_calls++;
+
+       polkit_authority_check_authorization (priv->authority,
+                                             pk_call->subject,
+                                             pk_action,
+                                             NULL,
+                                             0,
+                                             NULL,
+                                             permission_call_done,
+                                             call);
+}
+
+static void
+impl_settings_get_permissions (NMSysconfigSettings *self,
+                               DBusGMethodInvocation *context)
+{
+       PolkitCall *call;
+
+       call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE);
+       g_assert (call);
+
+       /* Start checks for the various permissions */
+
+       /* Only check for connection-modify if one of our plugins supports it. */
+       if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) {
+               start_permission_check (self, call,
+                                       NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY,
+                                       NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY);
+       }
+
+       /* Only check for hostname-modify if one of our plugins supports it. */
+       if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) {
+               start_permission_check (self, call,
+                                       NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY,
+                                       NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY);
+       }
+
+       // FIXME: hook these into plugin permissions like the modify permissions */
+       start_permission_check (self, call,
+                               NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN,
+                               NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN);
+       start_permission_check (self, call,
+                               NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED,
+                               NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED);
+}
+
+static gboolean
+get_permissions (NMSettingsSystemInterface *settings,
+                 NMSettingsSystemGetPermissionsFunc callback,
+                 gpointer user_data)
+{
+       NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings);
+       NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE;
+
+       /* Local caller (ie, NM) gets full permissions by default because it doesn't
+        * need authorization.  However, permissions are still subject to plugin's
+        * restrictions.  i.e. if no plugins support connection-modify, then even
+        * the local caller won't get that permission.
+        */
+
+       /* Only check for connection-modify if one of our plugins supports it. */
+       if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS))
+               permissions |= NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY;
+
+       /* Only check for hostname-modify if one of our plugins supports it. */
+       if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME))
+               permissions |= NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY;
+
+       // FIXME: hook these into plugin permissions like the modify permissions */
+       permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN;
+       permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED;
+
+       callback (settings, permissions, NULL, user_data);
+       return TRUE;
+}
+
 static gboolean
 have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac)
 {
@@ -1115,6 +1275,8 @@ finalize (GObject *object)
 static void
 settings_system_interface_init (NMSettingsSystemInterface *iface)
 {
+       iface->get_permissions = get_permissions;
+
        dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface),
                                         &dbus_glib_nm_settings_system_object_info);
 }
@@ -1206,7 +1368,9 @@ nm_sysconfig_settings_init (NMSysconfigSettings *self)
        priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL);
 
        priv->authority = polkit_authority_get ();
-       if (!priv->authority)
+       if (priv->authority)
+               g_signal_connect (priv->authority, "changed", G_CALLBACK (pk_authority_changed_cb), self);
+       else
                g_warning ("%s: failed to create PolicyKit authority.", __func__);
 
        /* Grab hostname on startup and use that if no plugins provide one */