core: PolicyKit-protect sleep/wake
authorDan Williams <dcbw@redhat.com>
Sun, 30 May 2010 06:11:45 +0000 (23:11 -0700)
committerDan Williams <dcbw@redhat.com>
Sun, 30 May 2010 06:11:45 +0000 (23:11 -0700)
Default to 'not allowed', distros that need backwards compatibility
can flip this to 'yes' if they need to. At this point, only power
management scripts should call these functions.

introspection/nm-manager.xml
policy/org.freedesktop.NetworkManager.policy.in
src/nm-manager-auth.h
src/nm-manager.c

index 370d98a..8868656 100644 (file)
@@ -86,6 +86,7 @@
 
     <method name="Sleep">
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_sleep"/>
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
       <tp:docstring>
         Control the NetworkManager daemon's sleep state.  When asleep, all
         interfaces that it manages are deactivated.  When awake, devices are
         DEPRECATED.  Control the NetworkManager daemon's sleep state.  When asleep, all interfaces that it manages are deactivated.
       </tp:docstring>
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_legacy_sleep"/>
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
     </method>
 
     <method name="wake">
         DEPRECATED.  Control the NetworkManager daemon's sleep state.  When awake, all known interfaces are available to be activated.
       </tp:docstring>
       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_manager_legacy_wake"/>
+      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
     </method>
 
     <method name="state">
index fb8654c..a912872 100644 (file)
     </defaults>
   </action>
 
+  <action id="org.freedesktop.NetworkManager.sleep-wake">
+    <_description>Put NetworkManager to sleep or wake it up (should only be used by system power management)</_description>
+    <_message>System policy prevents putting NetworkManager to sleep or waking it up</_message>
+    <defaults>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>no</allow_active>
+    </defaults>
+  </action>
+
   <action id="org.freedesktop.NetworkManager.enable-disable-wifi">
     <_description>Enable or disable WiFi devices</_description>
     <_message>System policy prevents enabling or disabling WiFi devices</_message>
index f0f01c2..faafbdb 100644 (file)
@@ -26,6 +26,7 @@
 #include <dbus/dbus-glib.h>
 
 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK "org.freedesktop.NetworkManager.enable-disable-network"
+#define NM_AUTH_PERMISSION_SLEEP_WAKE             "org.freedesktop.NetworkManager.sleep-wake"
 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI    "org.freedesktop.NetworkManager.enable-disable-wifi"
 #define NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN    "org.freedesktop.NetworkManager.enable-disable-wwan"
 #define NM_AUTH_PERMISSION_USE_USER_CONNECTIONS   "org.freedesktop.NetworkManager.use-user-connections"
index 984db5f..9bf7f4a 100644 (file)
@@ -71,7 +71,9 @@ static gboolean impl_manager_deactivate_connection (NMManager *manager,
                                                     const char *connection_path,
                                                     GError **error);
 
-static gboolean impl_manager_sleep (NMManager *manager, gboolean sleep, GError **err);
+static void impl_manager_sleep (NMManager *manager,
+                                gboolean do_sleep,
+                                DBusGMethodInvocation *context);
 
 static void impl_manager_enable (NMManager *manager,
                                  gboolean enable,
@@ -87,8 +89,8 @@ static gboolean impl_manager_set_logging (NMManager *manager,
 
 /* Legacy 0.6 compatibility interface */
 
-static gboolean impl_manager_legacy_sleep (NMManager *manager, GError **err);
-static gboolean impl_manager_legacy_wake  (NMManager *manager, GError **err);
+static void impl_manager_legacy_sleep (NMManager *manager, DBusGMethodInvocation *context);
+static void impl_manager_legacy_wake  (NMManager *manager, DBusGMethodInvocation *context);
 static gboolean impl_manager_legacy_state (NMManager *manager, guint32 *state, GError **err);
 
 #include "nm-manager-glue.h"
@@ -2750,21 +2752,10 @@ return_permission_denied_error (PolkitAuthority *authority,
        return TRUE;
 }
 
-static gboolean
-impl_manager_sleep (NMManager *self, gboolean do_sleep, GError **error)
+static void
+_internal_sleep (NMManager *self, gboolean do_sleep)
 {
-       NMManagerPrivate *priv;
-
-       g_return_val_if_fail (NM_IS_MANAGER (self), FALSE);
-
-       priv = NM_MANAGER_GET_PRIVATE (self);
-
-       if (priv->sleeping == do_sleep) {
-               g_set_error (error,
-                            NM_MANAGER_ERROR, NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE,
-                            "Already %s", do_sleep ? "asleep" : "awake");
-               return FALSE;
-       }
+       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 
        nm_log_info (LOGD_SUSPEND, "%s requested (sleeping: %s  enabled: %s)",
                     do_sleep ? "sleep" : "wake",
@@ -2776,7 +2767,92 @@ impl_manager_sleep (NMManager *self, gboolean do_sleep, GError **error)
        do_sleep_wake (self);
 
        g_object_notify (G_OBJECT (self), NM_MANAGER_SLEEPING);
-       return TRUE;
+}
+
+static void
+sleep_auth_done_cb (NMAuthChain *chain,
+                    GError *error,
+                    DBusGMethodInvocation *context,
+                    gpointer user_data)
+{
+       NMManager *self = NM_MANAGER (user_data);
+       NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+       GError *ret_error;
+       NMAuthCallResult result;
+       gboolean do_sleep;
+
+       result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "result"));
+       do_sleep = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sleep"));
+
+       priv->auth_chains = g_slist_remove (priv->auth_chains, chain);
+       if (error) {
+               nm_log_dbg (LOGD_CORE, "Sleep/wake request failed: %s", error->message);
+               ret_error = g_error_new (NM_MANAGER_ERROR,
+                                        NM_MANAGER_ERROR_PERMISSION_DENIED,
+                                        "Sleep/wake request failed: %s",
+                                        error->message);
+               dbus_g_method_return_error (context, ret_error);
+               g_error_free (ret_error);
+       } else if (result != NM_AUTH_CALL_RESULT_YES) {
+               ret_error = g_error_new_literal (NM_MANAGER_ERROR,
+                                                NM_MANAGER_ERROR_PERMISSION_DENIED,
+                                                "Not authorized to sleep/wake");
+               dbus_g_method_return_error (context, ret_error);
+               g_error_free (ret_error);
+       } else {
+               _internal_sleep (self, do_sleep);
+               dbus_g_method_return (context);
+       }
+
+       nm_auth_chain_unref (chain);
+}
+
+static void
+sleep_auth_call_done_cb (NMAuthChain *chain,
+                         const char *permission,
+                         GError *error,
+                         NMAuthCallResult result,
+                         gpointer user_data)
+{
+       if (!error)
+               nm_auth_chain_set_data (chain, "result", GUINT_TO_POINTER (result), NULL);
+}
+
+static void
+impl_manager_sleep (NMManager *self,
+                    gboolean do_sleep,
+                    DBusGMethodInvocation *context)
+{
+       NMManagerPrivate *priv;
+       NMAuthChain *chain;
+       GError *error;
+
+       g_return_if_fail (NM_IS_MANAGER (self));
+
+       priv = NM_MANAGER_GET_PRIVATE (self);
+
+       if (priv->sleeping == do_sleep) {
+               error = g_error_new (NM_MANAGER_ERROR,
+                                    NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE,
+                                    "Already %s", do_sleep ? "asleep" : "awake");
+               dbus_g_method_return_error (context, error);
+               g_error_free (error);
+               return;
+       }
+
+       if (!return_permission_denied_error (priv->authority, "Permission", context))
+               return;
+
+       chain = nm_auth_chain_new (priv->authority,
+                                  context,
+                                  sleep_auth_done_cb,
+                                  sleep_auth_call_done_cb,
+                                  self);
+       g_assert (chain);
+       priv->auth_chains = g_slist_append (priv->auth_chains, chain);
+
+       nm_auth_chain_set_data (chain, "sleep", GUINT_TO_POINTER (do_sleep), NULL);
+       nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, TRUE);
 }
 
 static void
@@ -2992,6 +3068,7 @@ impl_manager_get_permissions (NMManager *self,
        nm_auth_chain_set_data (chain, "results", results, (GDestroyNotify) g_hash_table_destroy);
 
        nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE);
+       nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE);
        nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE);
        nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE);
        nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_USE_USER_CONNECTIONS, FALSE);
@@ -2999,16 +3076,16 @@ impl_manager_get_permissions (NMManager *self,
 
 /* Legacy 0.6 compatibility interface */
 
-static gboolean
-impl_manager_legacy_sleep (NMManager *manager, GError **error)
+static void
+impl_manager_legacy_sleep (NMManager *manager, DBusGMethodInvocation *context)
 {
-       return impl_manager_sleep (manager, TRUE, error);
+       return impl_manager_sleep (manager, TRUE, context);
 }
 
-static gboolean
-impl_manager_legacy_wake  (NMManager *manager, GError **error)
+static void
+impl_manager_legacy_wake  (NMManager *manager, DBusGMethodInvocation *context)
 {
-       return impl_manager_sleep (manager, FALSE, error);
+       return impl_manager_sleep (manager, FALSE, context);
 }
 
 static gboolean