PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Sat Nov 17 13:43:19 PST 2007


 configure.in                                |    3 
 doc/man/polkit-action.xml                   |  104 +++++++++
 policy/org.freedesktop.policykit.policy.in  |   10 
 src/kit/kit-file.c                          |    6 
 src/kit/kit-spawn.c                         |   18 +
 src/polkit-dbus/Makefile.am                 |   11 -
 src/polkit-dbus/polkit-set-default-helper.c |  303 ++++++++++++++++++++++++++++
 src/polkit/Makefile.am                      |   14 -
 src/polkit/polkit-error.c                   |    3 
 src/polkit/polkit-error.h                   |    4 
 src/polkit/polkit-policy-default.c          |  127 +++++++++++
 src/polkit/polkit-policy-default.h          |   13 +
 src/polkit/polkit-policy-file-entry.c       |  189 +++++++++++++++++
 src/polkit/polkit-policy-file-entry.h       |    6 
 tools/polkit-action.c                       |  253 ++++++++++++++++++++---
 tools/polkit-bash-completion.sh             |   30 +-
 16 files changed, 1031 insertions(+), 63 deletions(-)

New commits:
commit f631d726602360d16dd8154f88a12754f3af0863
Author: David Zeuthen <davidz at redhat.com>
Date:   Sat Nov 17 16:43:25 2007 -0500

    add API for overriding defaults and make polkit-action(1) use this API.

diff --git a/configure.in b/configure.in
index 1c8cff9..cfc4b98 100644
--- a/configure.in
+++ b/configure.in
@@ -530,6 +530,9 @@ if test "${POLKIT_AUTHDB}" = default ; then
   echo "NOTE: The directories ${localstatedir}/run/PolicyKit and ${localstatedir}/lib/PolicyKit will be"
   echo "      owned by group ${POLKIT_GROUP} and will be mode 770."
   echo
+  echo "NOTE: The directory ${localstatedir}/run/PolicyKit-public will be"
+  echo "      owned by group ${POLKIT_GROUP} and will be mode 775."
+  echo
   echo "NOTE: ${libexecdir}/polkit-read-auth-helper will be owned by"
   echo "      group ${POLKIT_GROUP} and installed with mode 2755 (setgid binary)."
   echo
diff --git a/doc/man/polkit-action.xml b/doc/man/polkit-action.xml
index 430717c..3d1cc29 100644
--- a/doc/man/polkit-action.xml
+++ b/doc/man/polkit-action.xml
@@ -13,13 +13,18 @@
   
   <refnamediv>
     <refname>polkit-action</refname>
-    <refpurpose>List registered PolicyKit actions</refpurpose>
+    <refpurpose>List and modify registered PolicyKit actions</refpurpose>
   </refnamediv>
   
   <refsynopsisdiv>
     <cmdsynopsis>
       <command>polkit-action</command>
       <arg><option>--action <replaceable>action</replaceable></option></arg>
+      <arg><option>--reset-defaults <replaceable>action</replaceable></option></arg>
+      <arg><option>--show-overrides</option></arg>
+      <arg><option>--set-defaults-any <replaceable>action</replaceable> <replaceable>value</replaceable></option></arg>
+      <arg><option>--set-defaults-inactive <replaceable>action</replaceable> <replaceable>value</replaceable></option></arg>
+      <arg><option>--set-defaults-active <replaceable>action</replaceable> <replaceable>value</replaceable></option></arg>
       <arg><option>--version</option></arg>
       <arg><option>--help</option></arg>
     </cmdsynopsis>
@@ -28,8 +33,8 @@
   <refsect1>
     <title>DESCRIPTION</title> 
     <para>
-      polkit-action is used to list the PolicyKit actions that are
-      registered on the system.
+      polkit-action is used to list and modify the PolicyKit actions
+      that are registered on the system.
     </para>
   </refsect1>
   
@@ -44,6 +49,93 @@
           </para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term><option>--reset-defaults <replaceable>action</replaceable></option></term>
+        <listitem>
+          <para>
+            Reset the defaults for the specified action to the factory
+            defaults. The authorization needed to do this is
+            <emphasis>org.freedesktop.policykit.modify-defaults</emphasis>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--show-overrides</option></term>
+        <listitem>
+          <para>
+            Prints all actions for where the defaults are overridden.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--set-defaults-any <replaceable>action</replaceable> <replaceable>value</replaceable></option></term>
+        <listitem>
+          <para>
+            Override the <emphasis>any</emphasis> stanza for the given
+            action with the supplied value. The authorization needed
+            to do this is <emphasis>org.freedesktop.policykit.modify-defaults</emphasis>.
+            Valid values for <emphasis>value</emphasis> are
+            <emphasis>no</emphasis>,
+            <emphasis>auth_admin_one_shot</emphasis>,
+            <emphasis>auth_admin</emphasis>,
+            <emphasis>auth_admin_keep_session</emphasis>,
+            <emphasis>auth_admin_keep_always</emphasis>,
+            <emphasis>auth_self_one_shot</emphasis>,
+            <emphasis>auth_self</emphasis>,
+            <emphasis>auth_self_keep_session</emphasis>,
+            <emphasis>auth_self_keep_always</emphasis>,
+            and <emphasis>yes</emphasis>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--set-defaults-inactive <replaceable>action</replaceable> <replaceable>value</replaceable></option></term>
+        <listitem>
+          <para>
+            Override the <emphasis>inactive</emphasis> stanza for the given
+            action with the supplied value. The authorization needed
+            to do this is <emphasis>org.freedesktop.policykit.modify-defaults</emphasis>.
+            Valid values for <emphasis>value</emphasis> are
+            <emphasis>no</emphasis>,
+            <emphasis>auth_admin_one_shot</emphasis>,
+            <emphasis>auth_admin</emphasis>,
+            <emphasis>auth_admin_keep_session</emphasis>,
+            <emphasis>auth_admin_keep_always</emphasis>,
+            <emphasis>auth_self_one_shot</emphasis>,
+            <emphasis>auth_self</emphasis>,
+            <emphasis>auth_self_keep_session</emphasis>,
+            <emphasis>auth_self_keep_always</emphasis>,
+            and <emphasis>yes</emphasis>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--set-defaults-active <replaceable>action</replaceable> <replaceable>value</replaceable></option></term>
+        <listitem>
+          <para>
+            Override the <emphasis>active</emphasis> stanza for the given
+            action with the supplied value. The authorization needed
+            to do this is <emphasis>org.freedesktop.policykit.modify-defaults</emphasis>.
+            Valid values for <emphasis>value</emphasis> are
+            <emphasis>no</emphasis>,
+            <emphasis>auth_admin_one_shot</emphasis>,
+            <emphasis>auth_admin</emphasis>,
+            <emphasis>auth_admin_keep_session</emphasis>,
+            <emphasis>auth_admin_keep_always</emphasis>,
+            <emphasis>auth_self_one_shot</emphasis>,
+            <emphasis>auth_self</emphasis>,
+            <emphasis>auth_self_keep_session</emphasis>,
+            <emphasis>auth_self_keep_always</emphasis>,
+            and <emphasis>yes</emphasis>.
+          </para>
+        </listitem>
+      </varlistentry>
+
       
       <varlistentry>
         <term><option>--version</option></term>
@@ -69,12 +161,12 @@
     <title>COMPLETION</title> 
     <para>
       PolicyKit ships with a collection of shell functions such that
-      completion on actions works when using the
+      completion on options, <emphasis>action</emphasis>
+      and <emphasis>value</emphasis> works when using the
       <citerefentry>
         <refentrytitle>bash</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>
-      shell. For polkit-action, completion is enabled for
-      the <option>--action</option> argument.
+      shell.
     </para>
   </refsect1>
   
diff --git a/policy/org.freedesktop.policykit.policy.in b/policy/org.freedesktop.policykit.policy.in
index efbeaeb..14e7af6 100644
--- a/policy/org.freedesktop.policykit.policy.in
+++ b/policy/org.freedesktop.policykit.policy.in
@@ -46,4 +46,14 @@ file are instantly applied.
     </defaults>
   </action>
 
+  <action id="org.freedesktop.policykit.modify-defaults">
+    <_description>Modify defaults for implicit authorizations</_description>
+    <_message>Authentication is required to modify the defaults for implicit authorizations</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+
 </policyconfig>
diff --git a/src/kit/kit-file.c b/src/kit/kit-file.c
index 832e058..f6b53c8 100644
--- a/src/kit/kit-file.c
+++ b/src/kit/kit-file.c
@@ -60,7 +60,8 @@
  * Reads an entire file into allocated memory.
  *
  * Returns: #TRUE if the file was read into memory; #FALSE if an error
- * occured and errno will be set.
+ * occured and errno will be set. On OOM, errno will be set to
+ * ENOMEM. If the file doesn't exist, errno will be set to ENOENT.
  */
 kit_bool_t
 kit_file_get_contents (const char *path, char **out_contents, size_t *out_contents_size)
@@ -81,9 +82,10 @@ kit_file_get_contents (const char *path, char **out_contents, size_t *out_conten
         fd = -1;
         ret = FALSE;
         *out_contents = NULL;
+        p = NULL;
 
         fd = open (path, O_RDONLY);
-        if (fd == 0)
+        if (fd == -1)
                 goto out;
 
         p = kit_malloc (BUF_SIZE);
diff --git a/src/kit/kit-spawn.c b/src/kit/kit-spawn.c
index fb4be3e..9fe7739 100644
--- a/src/kit/kit-spawn.c
+++ b/src/kit/kit-spawn.c
@@ -198,23 +198,27 @@ kit_spawn_sync (const char  *working_directory,
                 envp_to_use = environ;
 
         if (stdin != NULL) {
-                if (pipe (stdin_pipe) != 0)
+                if (pipe (stdin_pipe) != 0) {
                         goto out;
+                }
         }
 
         if (stdout != NULL) {
-                if (pipe (stdout_pipe) != 0)
+                if (pipe (stdout_pipe) != 0) {
                         goto out;
+                }
         }
 
         if (stderr != NULL) {
-                if (pipe (stderr_pipe) != 0)
+                if (pipe (stderr_pipe) != 0) {
                         goto out;
+                }
         }
 
         pid = fork ();
-        if (pid == -1)
+        if (pid == -1) {
                 goto out;
+        }
 
         if (pid == 0) {
                 /* child */
@@ -326,6 +330,7 @@ kit_spawn_sync (const char  *working_directory,
                                       NULL);
                         
                         if (ret < 0 && errno != EINTR) {
+                                kit_warning ("4");
                                 goto out;
                         }
                         
@@ -333,6 +338,7 @@ kit_spawn_sync (const char  *working_directory,
                                 num_written = _write_to (stdin_pipe[1], wp);
                                 
                                 if (num_written == -1)  {
+                                        kit_warning ("3");
                                         goto out;
                                 }
                                 
@@ -349,6 +355,7 @@ kit_spawn_sync (const char  *working_directory,
                                         close (stdout_pipe[0]);
                                         stdout_pipe[0] = -1;
                                 } else if (num_read == -1)  {
+                                        kit_warning ("2");
                                         goto out;
                                 }
                         }
@@ -359,12 +366,14 @@ kit_spawn_sync (const char  *working_directory,
                                         close (stderr_pipe[0]);
                                         stderr_pipe[0] = -1;
                                 } else if (num_read == -1)  {
+                                        kit_warning ("1");
                                         goto out;
                                 }
                         }
                 }
 
                 if (waitpid (pid, out_exit_status, 0) == -1) {
+                        kit_warning ("0");
                         goto out;
                 }
                 pid = -1;
@@ -377,6 +386,7 @@ kit_spawn_sync (const char  *working_directory,
         } else {
                 ret = FALSE;
                 errno = WEXITSTATUS (*out_exit_status) - 128;
+                kit_warning ("kiddo died with errno %d: %m!", errno);
         }
 
 out:
diff --git a/src/polkit-dbus/Makefile.am b/src/polkit-dbus/Makefile.am
index e9b5f9a..6c5a165 100644
--- a/src/polkit-dbus/Makefile.am
+++ b/src/polkit-dbus/Makefile.am
@@ -28,19 +28,28 @@ libpolkit_dbus_la_LIBADD = @DBUS_LIBS@ $(top_builddir)/src/polkit/libpolkit.la $
 libpolkit_dbus_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
 if POLKIT_AUTHDB_DEFAULT
-libexec_PROGRAMS = polkit-read-auth-helper
+libexec_PROGRAMS = polkit-read-auth-helper polkit-set-default-helper
 
 polkit_read_auth_helper_SOURCES = polkit-read-auth-helper.c
 polkit_read_auth_helper_CFLAGS = @DBUS_CFLAGS@
 polkit_read_auth_helper_LDADD = $(top_builddir)/src/polkit/libpolkit.la libpolkit-dbus.la
 
+polkit_set_default_helper_SOURCES = polkit-set-default-helper.c
+polkit_set_default_helper_CFLAGS = @DBUS_CFLAGS@
+polkit_set_default_helper_LDADD = $(top_builddir)/src/polkit/libpolkit.la libpolkit-dbus.la
+
 # polkit-read-auth-helper needs to be setgid $POLKIT_GROUP to be able
 # to read authorization files in /var/lib/PolicyKit and
 # /var/run/PolicyKit
 #
+# polkit-set-default-helper needs to be setgid $POLKIT_GROUP to be able
+# to write .override files in /var/lib/PolicyKit-public
+#
 install-exec-hook:
 	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-read-auth-helper
 	-chmod 2755 $(DESTDIR)$(libexecdir)/polkit-read-auth-helper
+	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-set-default-helper
+	-chmod 2755 $(DESTDIR)$(libexecdir)/polkit-set-default-helper
 endif
 
 ## note that TESTS has special meaning (stuff to use in make check)
diff --git a/src/polkit-dbus/polkit-set-default-helper.c b/src/polkit-dbus/polkit-set-default-helper.c
new file mode 100644
index 0000000..ffaaa2a
--- /dev/null
+++ b/src/polkit-dbus/polkit-set-default-helper.c
@@ -0,0 +1,303 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-set-default-helper.c : setgid polkituser helper for PolicyKit
+ * to set defaults
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
+ *
+ **************************************************************************/
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <security/pam_appl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <utime.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <utime.h>
+
+#include <polkit/polkit-private.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+static polkit_bool_t
+check_for_auth (uid_t caller_uid, pid_t caller_pid)
+{
+        polkit_bool_t ret;
+        DBusError error;
+        DBusConnection *bus;
+        PolKitCaller *caller;
+        PolKitAction *action;
+        PolKitContext *context;
+        PolKitError *pk_error;
+        PolKitResult pk_result;
+
+        ret = FALSE;
+
+        dbus_error_init (&error);
+        bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot connect to system bus: %s: %s\n", 
+                         error.name, error.message);
+                dbus_error_free (&error);
+                goto out;
+        }
+
+        caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
+        if (caller == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot get caller from pid: %s: %s\n",
+                         error.name, error.message);
+                goto out;
+        }
+
+        action = polkit_action_new ();
+        if (action == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot allocate PolKitAction\n");
+                goto out;
+        }
+
+        if (!polkit_action_set_action_id (action, "org.freedesktop.policykit.modify-defaults")) {
+                fprintf (stderr, "polkit-set-default-helper: cannot set action_id\n");
+                goto out;
+        }
+
+        context = polkit_context_new ();
+        if (context == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot allocate PolKitContext\n");
+                goto out;
+        }
+
+        pk_error = NULL;
+        if (!polkit_context_init (context, &pk_error)) {
+                fprintf (stderr, "polkit-set-default-helper: cannot initialize polkit context: %s: %s\n",
+                         polkit_error_get_error_name (pk_error),
+                         polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+                goto out;
+        }
+
+        pk_result = polkit_context_is_caller_authorized (context, action, caller, TRUE, &pk_error);
+        if (polkit_error_is_set (pk_error)) {
+
+                fprintf (stderr, "polkit-set-default-helper: cannot determine if caller is authorized: %s: %s\n",
+                         polkit_error_get_error_name (pk_error),
+                         polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+                goto out;
+        }
+        
+        if (pk_result != POLKIT_RESULT_YES) {
+                goto out;
+        }
+
+        ret = TRUE;
+out:
+
+        return ret;
+}
+
+static polkit_bool_t
+set_default (const char *action_id, const char *any, const char *inactive, const char *active)
+{
+        char *path;
+        char *contents;
+        polkit_bool_t ret;
+
+        path = NULL;
+        contents = NULL;
+        ret = FALSE;
+
+        path = kit_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit-public/%s.override", action_id);
+        if (path == NULL)
+                goto out;
+
+        contents = kit_strdup_printf ("%s:%s:%s",
+                                      any, inactive, active);
+        if (contents == NULL)
+                goto out;
+
+        if (!kit_file_set_contents (path, 0464, contents, strlen (contents))) {
+                kit_warning ("Error writing override file '%s': %m\n", path);
+                goto out;
+        }
+
+        ret = TRUE;
+
+out:
+        if (path == NULL)
+                kit_free (path);
+        if (contents == NULL)
+                kit_free (contents);
+        return ret;
+}
+
+static polkit_bool_t
+clear_default (const char *action_id)
+{
+        char *path;
+        polkit_bool_t ret;
+
+        ret = FALSE;
+
+        path = kit_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit-public/%s.override", action_id);
+        if (path == NULL)
+                goto out;
+
+        if (unlink (path) != 0) {
+                kit_warning ("Error unlinking file %s: %m", path);
+        }
+
+        ret = TRUE;
+
+out:
+        if (path == NULL)
+                kit_free (path);
+        return ret;
+
+}
+
+int
+main (int argc, char *argv[])
+{
+        int ret;
+        gid_t egid;
+        struct group *group;
+        uid_t caller_uid;
+        struct passwd *pw;
+        uid_t uid_for_polkit_user;
+
+        ret = 1;
+        /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
+        if (clearenv () != 0)
+                goto out;
+        /* set a minimal environment */
+        setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
+
+        openlog ("polkit-set-default-helper", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+
+        /* check for correct invocation */
+        if (! (argc == 3 || argc == 6)) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-set-default-helper: wrong number of arguments. This incident has been logged.\n");
+                goto out;
+        }
+
+        caller_uid = getuid ();
+
+        /* check we're running with a non-tty stdin */
+        if (isatty (STDIN_FILENO) != 0) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-set-default-helper: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
+                goto out;
+        }
+
+        /* check that we are setgid polkituser */
+        egid = getegid ();
+        group = getgrgid (egid);
+        if (group == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot lookup group info for gid %d\n", egid);
+                goto out;
+        }
+        if (strcmp (group->gr_name, POLKIT_GROUP) != 0) {
+                fprintf (stderr, "polkit-set-default-helper: needs to be setgid " POLKIT_GROUP "\n");
+                goto out;
+        }
+
+        pw = getpwnam (POLKIT_USER);
+        if (pw == NULL) {
+                fprintf (stderr, "polkit-set-default-helper: cannot lookup uid for " POLKIT_USER "\n");
+                goto out;
+        }
+        uid_for_polkit_user = pw->pw_uid;
+
+        /*----------------------------------------------------------------------------------------------------*/
+
+        /* uid 0 is allowed to set anything */
+        if (caller_uid != 0) {
+                /* see if calling user has the
+                 *
+                 *  org.freedesktop.policykit.modify-defaults
+                 *
+                 * authorization
+                 */
+                if (!check_for_auth (caller_uid, getppid ())) {
+                        goto out;
+                }
+        }
+
+        PolKitResult any;
+        PolKitResult inactive;
+        PolKitResult active;
+
+        if (!polkit_action_validate_id (argv[1])) {
+                goto out;
+        }
+
+        /* sanity check */
+        if (argc == 3) {
+                if (strcmp (argv[2], "clear") != 0)
+                        goto out;
+
+                if (!clear_default (argv[1]))
+                        goto out;
+        } else if (argc == 6) {
+                if (strcmp (argv[2], "set") != 0)
+                        goto out;
+
+                if (!polkit_result_from_string_representation (argv[3], &any)) {
+                        goto out;
+                }
+                if (!polkit_result_from_string_representation (argv[4], &inactive)) {
+                        goto out;
+                }
+                if (!polkit_result_from_string_representation (argv[5], &active)) {
+                        goto out;
+                }
+                
+                if (!set_default (argv[1], argv[3], argv[4], argv[5]))
+                        goto out;
+        } else {
+                goto out;
+        }
+
+        /* trigger a reload */
+        if (utimes (PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload", NULL) != 0) {
+                kit_warning ("Error updating access+modification time on file '%s': %m\n", 
+                             PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload");
+        }
+
+        ret = 0;
+
+out:
+        return ret;
+}
+
diff --git a/src/polkit/Makefile.am b/src/polkit/Makefile.am
index f1d2273..caba5e0 100644
--- a/src/polkit/Makefile.am
+++ b/src/polkit/Makefile.am
@@ -125,20 +125,26 @@ if POLKIT_AUTHDB_DEFAULT
 # polkit-auth-read-helper is used to read it) and the $POLKIT_GROUP
 # group needs to be able to write files there.
 #
+# The /var/lib/PolicyKit-public is used for storing world-readable
+# information. Only $POLKIT_GROUP may write to it.
+#
 # The /var/lib/misc/PolicyKit.reload file is used for triggering that
 # authorizations have changed; it needs to be world readable and
 # writeable for the $POLKIT_GROUP group (FHS 2.3 suggests that
 # location)
 #
 install-data-local:
-	-mkdir -p $(DESTDIR)$(localstatedir)/lib/misc
-	-touch $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
+	mkdir -p $(DESTDIR)$(localstatedir)/lib/misc
+	touch $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
 	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
 	-chmod 775 $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
-	-mkdir -p $(DESTDIR)$(localstatedir)/lib/PolicyKit
-	-mkdir -p $(DESTDIR)$(localstatedir)/run/PolicyKit
+	mkdir -p $(DESTDIR)$(localstatedir)/lib/PolicyKit-public
+	mkdir -p $(DESTDIR)$(localstatedir)/lib/PolicyKit
+	mkdir -p $(DESTDIR)$(localstatedir)/run/PolicyKit
+	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/PolicyKit-public
 	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/PolicyKit
 	-chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/run/PolicyKit
+	-chmod 775 $(DESTDIR)$(localstatedir)/lib/PolicyKit-public
 	-chmod 770 $(DESTDIR)$(localstatedir)/lib/PolicyKit
 	-chmod 770 $(DESTDIR)$(localstatedir)/run/PolicyKit
 endif
diff --git a/src/polkit/polkit-error.c b/src/polkit/polkit-error.c
index e7105db..0d8d792 100644
--- a/src/polkit/polkit-error.c
+++ b/src/polkit/polkit-error.c
@@ -86,7 +86,8 @@ static const char *error_names[POLKIT_ERROR_NUM_ERROR_CODES] = {
         "NotAuthorizedToRevokeAuthorizationsFromOtherUsers",
         "NotAuthorizedToGrantAuthorization",
         "AuthorizationAlreadyExists",
-        "NotSupported"
+        "NotSupported",
+        "NotAuthorizedToModifyDefaults",
 };
 
 /**
diff --git a/src/polkit/polkit-error.h b/src/polkit/polkit-error.h
index 472d670..4b47552 100644
--- a/src/polkit/polkit-error.h
+++ b/src/polkit/polkit-error.h
@@ -54,6 +54,9 @@ POLKIT_BEGIN_DECLS
  * similar authorization already (modulo time of grant and who granted).
  * @POLKIT_ERROR_NOT_SUPPORTED: The operation is not supported by the
  * authorization database backend
+ * @POLKIT_ERROR_NOT_AUTHORIZED_TO_MODIFY_DEFAULTS: An attempt was
+ * made to modify the defaults for implicit authorizations and the
+ * calling process is not authorized.
  * @POLKIT_ERROR_NUM_ERROR_CODES: Number of error codes. This may change
  * from version to version; do not rely on it.
  *
@@ -69,6 +72,7 @@ typedef enum
         POLKIT_ERROR_NOT_AUTHORIZED_TO_GRANT_AUTHORIZATION,
         POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS,
         POLKIT_ERROR_NOT_SUPPORTED,
+        POLKIT_ERROR_NOT_AUTHORIZED_TO_MODIFY_DEFAULTS,
 
         POLKIT_ERROR_NUM_ERROR_CODES
 } PolKitErrorCode;
diff --git a/src/polkit/polkit-policy-default.c b/src/polkit/polkit-policy-default.c
index c1e8173..7590b16 100644
--- a/src/polkit/polkit-policy-default.c
+++ b/src/polkit/polkit-policy-default.c
@@ -65,6 +65,88 @@ struct _PolKitPolicyDefault
         PolKitResult default_active;
 };
 
+/**
+ * polkit_policy_default_new:
+ *
+ * Construct a new object with all defaults set as restrictive as possible.
+ *
+ * Returns: a new object or #NULL on OOM.
+ *
+ * Since: 0.7
+ */
+PolKitPolicyDefault *
+polkit_policy_default_new (void)
+{
+        PolKitPolicyDefault *pd;
+
+        pd = kit_new0 (PolKitPolicyDefault, 1);
+        if (pd == NULL)
+                goto out;
+        pd->refcount = 1;
+        pd->default_any = POLKIT_RESULT_NO;
+        pd->default_inactive = POLKIT_RESULT_NO;
+        pd->default_active = POLKIT_RESULT_NO;
+out:
+        return pd;
+}
+
+/**
+ * polkit_policy_default_clone:
+ * @policy_default: object to clone
+ *
+ * Create a new object with the same value as the given object
+ *
+ * Returns: a new object or #NULL on OOM.
+ *
+ * Since: 0.7
+ */
+PolKitPolicyDefault *
+polkit_policy_default_clone (PolKitPolicyDefault *policy_default)
+{
+        PolKitPolicyDefault *pd;
+
+        kit_return_val_if_fail (policy_default != NULL, NULL);
+
+        pd = polkit_policy_default_new ();
+        if (pd == NULL)
+                goto out;
+        pd->refcount = 1;
+        pd->default_any      = policy_default->default_any;
+        pd->default_inactive = policy_default->default_inactive;
+        pd->default_active   = policy_default->default_active;
+out:
+        return pd;
+}
+
+
+/**
+ * polkit_policy_default_equals:
+ * @a: a #PolKitPolicyDefault object
+ * @b: a #PolKitPolicyDefault object
+ *
+ * Compare if two objects are equal.
+ *
+ * Returns: %TRUE only if the objects are equal
+ */
+polkit_bool_t
+polkit_policy_default_equals (PolKitPolicyDefault *a, PolKitPolicyDefault *b)
+{
+        polkit_bool_t ret;
+
+        kit_return_val_if_fail (a != NULL, FALSE);
+        kit_return_val_if_fail (b != NULL, FALSE);
+
+        if (a->default_any      == b->default_any &&
+            a->default_inactive == b->default_inactive &&
+            a->default_active   == b->default_active) {
+                ret = TRUE;
+        } else {
+                ret = FALSE;
+        }
+
+        return ret;
+}
+
 PolKitPolicyDefault *
 _polkit_policy_default_new (PolKitResult defaults_allow_any,
                             PolKitResult defaults_allow_inactive,
@@ -233,6 +315,51 @@ out:
 }
 
 /**
+ * polkit_policy_default_set_allow_any:
+ * @policy_default: the object
+ * @value: the value to set
+ * 
+ * Set default policy.
+ *
+ **/
+void
+polkit_policy_default_set_allow_any (PolKitPolicyDefault *policy_default, PolKitResult value)
+{
+        kit_return_if_fail (policy_default != NULL);
+        policy_default->default_any = value;
+}
+
+/**
+ * polkit_policy_default_set_allow_inactive:
+ * @policy_default: the object
+ * @value: the value to set
+ * 
+ * Set default policy.
+ *
+ **/
+void
+polkit_policy_default_set_allow_inactive (PolKitPolicyDefault *policy_default, PolKitResult value)
+{
+        kit_return_if_fail (policy_default != NULL);
+        policy_default->default_inactive = value;
+}
+
+/**
+ * polkit_policy_default_set_allow_active:
+ * @policy_default: the object
+ * @value: the value to set
+ * 
+ * Set default policy.
+ *
+ **/
+void
+polkit_policy_default_set_allow_active (PolKitPolicyDefault *policy_default, PolKitResult value)
+{
+        kit_return_if_fail (policy_default != NULL);
+        policy_default->default_active = value;
+}
+
+/**
  * polkit_policy_default_get_allow_any:
  * @policy_default: the object
  * 
diff --git a/src/polkit/polkit-policy-default.h b/src/polkit/polkit-policy-default.h
index a9f6146..3da429d 100644
--- a/src/polkit/polkit-policy-default.h
+++ b/src/polkit/polkit-policy-default.h
@@ -42,9 +42,13 @@ POLKIT_BEGIN_DECLS
 struct _PolKitPolicyDefault;
 typedef struct _PolKitPolicyDefault PolKitPolicyDefault;
 
+PolKitPolicyDefault    *polkit_policy_default_new   (void);
 PolKitPolicyDefault    *polkit_policy_default_ref   (PolKitPolicyDefault *policy_default);
 void                    polkit_policy_default_unref (PolKitPolicyDefault *policy_default);
 void                    polkit_policy_default_debug (PolKitPolicyDefault *policy_default);
+PolKitPolicyDefault    *polkit_policy_default_clone (PolKitPolicyDefault *policy_default);
+
+polkit_bool_t           polkit_policy_default_equals (PolKitPolicyDefault *a, PolKitPolicyDefault *b);
 
 PolKitResult polkit_policy_default_can_session_do_action (PolKitPolicyDefault *policy_default,
                                                           PolKitAction        *action,
@@ -54,9 +58,14 @@ PolKitResult polkit_policy_default_can_caller_do_action (PolKitPolicyDefault *po
                                                          PolKitAction        *action,
                                                          PolKitCaller        *caller);
 
-PolKitResult polkit_policy_default_get_allow_any (PolKitPolicyDefault *policy_default);
+PolKitResult polkit_policy_default_get_allow_any      (PolKitPolicyDefault *policy_default);
 PolKitResult polkit_policy_default_get_allow_inactive (PolKitPolicyDefault *policy_default);
-PolKitResult polkit_policy_default_get_allow_active (PolKitPolicyDefault *policy_default);
+PolKitResult polkit_policy_default_get_allow_active   (PolKitPolicyDefault *policy_default);
+
+void         polkit_policy_default_set_allow_any      (PolKitPolicyDefault *policy_default, PolKitResult value);
+void         polkit_policy_default_set_allow_inactive (PolKitPolicyDefault *policy_default, PolKitResult value);
+void         polkit_policy_default_set_allow_active   (PolKitPolicyDefault *policy_default, PolKitResult value);
+
 
 /* TODO: export knobs for "default policy" */
 
diff --git a/src/polkit/polkit-policy-file-entry.c b/src/polkit/polkit-policy-file-entry.c
index 13ddd31..19aa39e 100644
--- a/src/polkit/polkit-policy-file-entry.c
+++ b/src/polkit/polkit-policy-file-entry.c
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <pwd.h>
 #include <grp.h>
 #include <unistd.h>
@@ -63,6 +64,7 @@ struct _PolKitPolicyFileEntry
 {
         int refcount;
         char *action;
+        PolKitPolicyDefault *defaults_factory;
         PolKitPolicyDefault *defaults;
 
         char *policy_description;
@@ -79,9 +81,15 @@ _polkit_policy_file_entry_new   (const char *action_id,
                                  PolKitResult defaults_allow_active,
                                  KitHash *annotations)
 {
+        char *path;
+        char *contents;
+        size_t contents_size;
         PolKitPolicyFileEntry *pfe;
 
-        kit_return_val_if_fail (action_id != NULL, NULL);
+        path = NULL;
+        contents = NULL;
+
+        kit_return_val_if_fail (action_id != NULL && polkit_action_validate_id (action_id), NULL);
 
         pfe = kit_new0 (PolKitPolicyFileEntry, 1);
         if (pfe == NULL)
@@ -100,16 +108,65 @@ _polkit_policy_file_entry_new   (const char *action_id,
                 defaults_allow_active = POLKIT_RESULT_NO;
         }
 
-        pfe->defaults = _polkit_policy_default_new (defaults_allow_any,
-                                                    defaults_allow_inactive,
-                                                    defaults_allow_active);
+        pfe->defaults_factory = _polkit_policy_default_new (defaults_allow_any,
+                                                            defaults_allow_inactive,
+                                                            defaults_allow_active);
+        if (pfe->defaults_factory == NULL)
+                goto error;
+
+        pfe->defaults = polkit_policy_default_clone (pfe->defaults_factory);
         if (pfe->defaults == NULL)
                 goto error;
 
+        /* read override file */
+        path = kit_strdup_printf (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit-public/%s.override", action_id);
+        if (path == NULL)
+                goto error;
+        if (!kit_file_get_contents (path, &contents, &contents_size)) {
+                /* it's not a failure if the file doesn't exist */
+                if (errno != ENOENT)
+                        goto error;
+
+                errno = 0;
+                contents = NULL;
+        }
+
+        if (contents != NULL) {
+                char **tokens;
+                size_t num_tokens;
+                PolKitResult any;
+                PolKitResult inactive;
+                PolKitResult active;
+
+                tokens = kit_strsplit (contents, ':', &num_tokens);
+                if (num_tokens != 3)
+                        goto error;
+
+                if (!polkit_result_from_string_representation (tokens[0], &any)) {
+                        goto error;
+                }
+                if (!polkit_result_from_string_representation (tokens[1], &inactive)) {
+                        goto error;
+                }
+                if (!polkit_result_from_string_representation (tokens[2], &active)) {
+                        goto error;
+                }
+
+                polkit_policy_default_set_allow_any      (pfe->defaults, any);
+                polkit_policy_default_set_allow_inactive (pfe->defaults, inactive);
+                polkit_policy_default_set_allow_active   (pfe->defaults, active);
+        }
+
+
         pfe->annotations = annotations;
 
+        kit_free (path);
+        kit_free (contents);
+
         return pfe;
 error:
+        kit_free (path);
+        kit_free (contents);
         if (pfe != NULL)
                 polkit_policy_file_entry_unref (pfe);
         return NULL;
@@ -218,6 +275,9 @@ polkit_policy_file_entry_unref (PolKitPolicyFileEntry *policy_file_entry)
 
         kit_free (policy_file_entry->action);
 
+        if (policy_file_entry->defaults_factory != NULL)
+                polkit_policy_default_unref (policy_file_entry->defaults_factory);
+
         if (policy_file_entry->defaults != NULL)
                 polkit_policy_default_unref (policy_file_entry->defaults);
 
@@ -267,7 +327,7 @@ polkit_policy_file_entry_get_id (PolKitPolicyFileEntry *policy_file_entry)
  * 
  * Get the the default policy for this policy.
  * 
- * Returns: A #PolKitPolicyDefault object - caller shall not unref this object.
+ * Returns: A #PolKitPolicyDefault object - caller shall not unref or modify this object.
  **/
 PolKitPolicyDefault *
 polkit_policy_file_entry_get_default (PolKitPolicyFileEntry *policy_file_entry)
@@ -276,6 +336,125 @@ polkit_policy_file_entry_get_default (PolKitPolicyFileEntry *policy_file_entry)
         return policy_file_entry->defaults;
 }
 
+/**
+ * polkit_policy_file_entry_get_default_factory:
+ * @policy_file_entry: the file entry
+ * 
+ * Get the factory defaults for the entry. This may be different that
+ * what polkit_policy_file_entry_get_default() returns if the function
+ * polkit_policy_file_entry_set_default() have been used to change the
+ * defaults.
+ *
+ * Returns: A #PolKitPolicyDefault object - caller shall not unref or modify this object.
+ *
+ * Since: 0.7
+ */
+PolKitPolicyDefault *
+polkit_policy_file_entry_get_default_factory (PolKitPolicyFileEntry *policy_file_entry)
+{
+        kit_return_val_if_fail (policy_file_entry != NULL, NULL);
+        return policy_file_entry->defaults_factory;
+}
+
+/**
+ * polkit_policy_file_entry_set_default:
+ * @policy_file_entry: the file entry
+ * @defaults: the new defaults to set
+ * @error: return location for error or #NULL
+ *
+ * Set new defaults for a given policy file entry; subsequent calls to
+ * polkit_policy_file_get_default() will return these values. Note
+ * that the old defaults are not modified; they are still available via
+ * polkit_policy_file_entry_get_default_factory().
+ *
+ * This operation requires the
+ * org.freedesktop.policykit.modify-defaults authorization and will
+ * fail if the caller lacks it.
+ *
+ * Returns: %TRUE if the given defaults was set; %FALSE if @error is set.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_policy_file_entry_set_default (PolKitPolicyFileEntry  *policy_file_entry,
+                                      PolKitPolicyDefault    *defaults,
+                                      PolKitError           **error)
+{
+        char *helper_argv[7] = {PACKAGE_LIBEXEC_DIR "/polkit-set-default-helper", 
+                                NULL, /* arg1: action_id */
+                                NULL, /* arg2: "clear" or "set" */
+                                NULL, /* arg3: result_any */
+                                NULL, /* arg4: result_inactive */
+                                NULL, /* arg5: result_active */
+                                NULL};
+        polkit_bool_t ret;
+        int exit_status;
+        PolKitResult any;
+        PolKitResult inactive;
+        PolKitResult active;
+
+        ret = FALSE;
+
+        kit_return_val_if_fail (policy_file_entry != NULL, FALSE);
+        kit_return_val_if_fail (defaults != NULL, FALSE);
+
+        if (polkit_policy_default_equals (policy_file_entry->defaults, defaults)) {
+                /* no point in doing extra work.. */
+                ret = TRUE;
+                goto out;
+        }
+
+        any = polkit_policy_default_get_allow_any (defaults);
+        inactive = polkit_policy_default_get_allow_inactive (defaults);
+        active = polkit_policy_default_get_allow_active (defaults);
+
+        helper_argv[1] = policy_file_entry->action;
+
+        if (polkit_policy_default_equals (policy_file_entry->defaults_factory, defaults)) {
+                helper_argv[2] = "clear";
+                helper_argv[3] = NULL;
+        } else {
+                helper_argv[2] = "set";
+                helper_argv[3] = (char *) polkit_result_to_string_representation (any);
+                helper_argv[4] = (char *) polkit_result_to_string_representation (inactive);
+                helper_argv[5] = (char *) polkit_result_to_string_representation (active);
+                helper_argv[6] = NULL;
+        }
+
+        if (!kit_spawn_sync (NULL,             /* const char  *working_directory */
+                             helper_argv,      /* char       **argv */
+                             NULL,             /* char       **envp */
+                             NULL,             /* char        *stdin */
+                             NULL,             /* char       **stdout */
+                             NULL,             /* char       **stderr */
+                             &exit_status)) {  /* int         *exit_status */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Error spawning set-default helper: %m");
+                goto out;
+        }
+
+        if (!WIFEXITED (exit_status)) {
+                kit_warning ("Revoke helper crashed!");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "set-default helper crashed!");
+                goto out;
+        } else if (WEXITSTATUS(exit_status) != 0) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_MODIFY_DEFAULTS, 
+                                        "uid %d is not authorized to modify defaults for implicit authorization for action %s (requires org.freedesktop.policykit.modify-defaults)",
+                                        getuid (), policy_file_entry->action);
+        } else {
+                ret = TRUE;
+        }
+        
+out:
+        return ret;
+
+}
+
+
 typedef struct  {
         PolKitPolicyFileEntry *pfe;
         PolKitPolicyFileEntryAnnotationsForeachFunc cb;
diff --git a/src/polkit/polkit-policy-file-entry.h b/src/polkit/polkit-policy-file-entry.h
index 1317025..79375b0 100644
--- a/src/polkit/polkit-policy-file-entry.h
+++ b/src/polkit/polkit-policy-file-entry.h
@@ -33,6 +33,7 @@
 #include <polkit/polkit-types.h>
 #include <polkit/polkit-result.h>
 #include <polkit/polkit-policy-default.h>
+#include <polkit/polkit-error.h>
 
 POLKIT_BEGIN_DECLS
 
@@ -71,6 +72,11 @@ polkit_bool_t          polkit_policy_file_entry_annotations_foreach (PolKitPolic
 const char            *polkit_policy_file_entry_get_annotation (PolKitPolicyFileEntry *policy_file_entry,
                                                                 const char *key);
 
+PolKitPolicyDefault   *polkit_policy_file_entry_get_default_factory (PolKitPolicyFileEntry  *policy_file_entry);
+polkit_bool_t          polkit_policy_file_entry_set_default         (PolKitPolicyFileEntry  *policy_file_entry,
+                                                                     PolKitPolicyDefault    *defaults,
+                                                                     PolKitError           **error);
+
 POLKIT_END_DECLS
 
 #endif /* POLKIT_POLICY_FILE_ENTRY_H */
diff --git a/tools/polkit-action.c b/tools/polkit-action.c
index f0ae680..a4e04a9 100644
--- a/tools/polkit-action.c
+++ b/tools/polkit-action.c
@@ -59,30 +59,54 @@ _print_annotations (PolKitPolicyFileEntry *policy_file_entry,
 static void
 _print_details_for_entry (PolKitPolicyFileEntry *pfe)
 {
+        int n;
         const char *action_id;
         PolKitPolicyDefault *def;
-        PolKitResult default_any;
-        PolKitResult default_inactive;
-        PolKitResult default_active;
+        PolKitPolicyDefault *def_factory;
 
         action_id = polkit_policy_file_entry_get_id (pfe);
         def = polkit_policy_file_entry_get_default (pfe);
-        default_any = polkit_policy_default_get_allow_any (def);
-        default_inactive = polkit_policy_default_get_allow_inactive (def);
-        default_active = polkit_policy_default_get_allow_active (def);
+        def_factory = polkit_policy_file_entry_get_default_factory (pfe);
 
         printf ("action_id:        %s\n"
                 "description:      %s\n"
-                "message:          %s\n"
-                "default_any:      %s\n"
-                "default_inactive: %s\n"
-                "default_active:   %s\n",
+                "message:          %s\n",
                 action_id,
                 polkit_policy_file_entry_get_action_description (pfe),
-                polkit_policy_file_entry_get_action_message (pfe),
-                polkit_result_to_string_representation (default_any),
-                polkit_result_to_string_representation (default_inactive),
-                polkit_result_to_string_representation (default_active));
+                polkit_policy_file_entry_get_action_message (pfe));
+
+        for (n = 0; n < 3; n++) {
+                PolKitResult result;
+                PolKitResult result_factory;
+                char *str;
+
+                switch (n) {
+                default:
+                case 0:
+                        str = "default_any:     ";
+                        result = polkit_policy_default_get_allow_any (def);
+                        result_factory = polkit_policy_default_get_allow_any (def_factory);
+                        break;
+                case 1:
+                        str = "default_inactive:";
+                        result = polkit_policy_default_get_allow_inactive (def);
+                        result_factory = polkit_policy_default_get_allow_inactive (def_factory);
+                        break;
+                case 2:
+                        str = "default_active:  ";
+                        result = polkit_policy_default_get_allow_active (def);
+                        result_factory = polkit_policy_default_get_allow_active (def_factory);
+                        break;
+                }
+
+                if (result == result_factory) {
+                        printf ("%s %s\n", str, polkit_result_to_string_representation (result));
+                } else {
+                        printf ("%s %s (factory default: %s)\n", str, 
+                                polkit_result_to_string_representation (result),
+                                polkit_result_to_string_representation (result_factory));
+                }
+        }
 
         polkit_policy_file_entry_annotations_foreach (pfe, _print_annotations, NULL);
 }
@@ -100,6 +124,26 @@ _print_entry (PolKitPolicyCache *policy_cache,
         return FALSE;
 }
 
+static polkit_bool_t
+_print_entry_override (PolKitPolicyCache *policy_cache,
+                       PolKitPolicyFileEntry *pfe,
+                       void *user_data)
+{
+        const char *action_id;
+        PolKitPolicyDefault *def;
+        PolKitPolicyDefault *def_factory;
+
+        def = polkit_policy_file_entry_get_default (pfe);
+        def_factory = polkit_policy_file_entry_get_default_factory (pfe);
+
+        if (!polkit_policy_default_equals (def, def_factory)) {
+                action_id = polkit_policy_file_entry_get_id (pfe);
+                printf ("%s\n", action_id);
+        }
+
+        return FALSE;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -109,25 +153,54 @@ main (int argc, char *argv[])
         PolKitPolicyCache *cache;
         PolKitError *error;
         char *action_id;
+        char *reset_action_id;
+        char *set_def_any_action_id;
+        char *set_def_inactive_action_id;
+        char *set_def_active_action_id;
+        PolKitResult set_def_any_value;
+        PolKitResult set_def_inactive_value;
+        PolKitResult set_def_active_value;
+        polkit_bool_t show_overrides;
 
         ret = 1;
         action_id = NULL;
+        reset_action_id = NULL;
+        set_def_any_action_id = NULL;
+        set_def_inactive_action_id = NULL;
+        set_def_active_action_id = NULL;
+        show_overrides = FALSE;
 
         for (n = 1; n < argc; n++) {
                 if (strcmp (argv[n], "--help") == 0) {
                         usage (argc, argv);
                         return 0;
-                }
-                if (strcmp (argv[n], "--version") == 0) {
+                } else if (strcmp (argv[n], "--version") == 0) {
                         printf ("polkit-action " PACKAGE_VERSION "\n");
                         return 0;
-                }
-                if (strcmp (argv[n], "--action") == 0 && n + 1 < argc) {
-                        action_id = argv[n+1];
+                } else if (strcmp (argv[n], "--action") == 0 && n + 1 < argc) {
+                        action_id = argv[++n];
+                } else if (strcmp (argv[n], "--reset-defaults") == 0 && n + 1 < argc) {
+                        reset_action_id = argv[++n];
+                } else if (strcmp (argv[n], "--show-overrides") == 0) {
+                        show_overrides = TRUE;
+                } else if (strcmp (argv[n], "--set-defaults-any") == 0 && n + 2 < argc) {
+                        set_def_any_action_id = argv[++n];
+                        if (!polkit_result_from_string_representation (argv[++n], &set_def_any_value))
+                                usage (argc, argv);
+                } else if (strcmp (argv[n], "--set-defaults-inactive") == 0 && n + 2 < argc) {
+                        set_def_inactive_action_id = argv[++n];
+                        if (!polkit_result_from_string_representation (argv[++n], &set_def_inactive_value))
+                                usage (argc, argv);
+                } else if (strcmp (argv[n], "--set-defaults-active") == 0 && n + 2 < argc) {
+                        set_def_active_action_id = argv[++n];
+                        if (!polkit_result_from_string_representation (argv[++n], &set_def_active_value))
+                                usage (argc, argv);
+                } else {
+                        usage (argc, argv);
+                        return 0;
                 }
 	}
 
-
         ctx = polkit_context_new ();
         if (ctx == NULL)
                 goto out;
@@ -145,18 +218,140 @@ main (int argc, char *argv[])
                 goto out;
         }
 
-        if (action_id != NULL) {
-                PolKitPolicyFileEntry *pfe;
-                pfe = polkit_policy_cache_get_entry_by_id (cache, action_id);
-                if (pfe == NULL) {
-                        fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", action_id);
-                        goto out;
-                }
-                _print_details_for_entry (pfe);
-        } else {
+        if (argc == 1) {
                 polkit_policy_cache_foreach (cache, _print_entry, NULL);
+                goto done;
         }
 
+        if (show_overrides) {
+                polkit_policy_cache_foreach (cache, _print_entry_override, NULL);
+                goto done;
+        }
+
+        while (TRUE) {
+                if (reset_action_id != NULL) {
+                        PolKitPolicyDefault *def;
+                        PolKitPolicyFileEntry *pfe;
+                        PolKitError *pk_error;
+
+                        pfe = polkit_policy_cache_get_entry_by_id (cache, reset_action_id);
+                        if (pfe == NULL) {
+                                fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", reset_action_id);
+                                goto out;
+                        }
+                        def = polkit_policy_file_entry_get_default_factory (pfe);
+
+                        pk_error = NULL;
+                        if (!polkit_policy_file_entry_set_default (pfe, def, &pk_error)) {
+                                fprintf (stderr, "Error: code=%d: %s: %s\n",
+                                         polkit_error_get_error_code (pk_error),
+                                         polkit_error_get_error_name (pk_error),
+                                         polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                                goto out;
+                        }
+
+                        reset_action_id = NULL;
+                }
+
+                if (set_def_any_action_id != NULL) {
+                        PolKitPolicyDefault *def;
+                        PolKitPolicyFileEntry *pfe;
+                        PolKitError *pk_error;
+
+                        pfe = polkit_policy_cache_get_entry_by_id (cache, set_def_any_action_id);
+                        if (pfe == NULL) {
+                                fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", set_def_any_action_id);
+                                goto out;
+                        }
+
+                        def = polkit_policy_default_clone (polkit_policy_file_entry_get_default (pfe));
+                        polkit_policy_default_set_allow_any (def, set_def_any_value);
+                        pk_error = NULL;
+                        if (!polkit_policy_file_entry_set_default (pfe, def, &pk_error)) {
+                                fprintf (stderr, "Error: code=%d: %s: %s\n",
+                                         polkit_error_get_error_code (pk_error),
+                                         polkit_error_get_error_name (pk_error),
+                                         polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                                goto out;
+                        }
+                        polkit_policy_default_unref (def);
+
+                        set_def_any_action_id = NULL;
+                }
+
+                if (set_def_inactive_action_id != NULL) {
+                        PolKitPolicyDefault *def;
+                        PolKitPolicyFileEntry *pfe;
+                        PolKitError *pk_error;
+
+                        pfe = polkit_policy_cache_get_entry_by_id (cache, set_def_inactive_action_id);
+                        if (pfe == NULL) {
+                                fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", set_def_inactive_action_id);
+                                goto out;
+                        }
+
+                        def = polkit_policy_default_clone (polkit_policy_file_entry_get_default (pfe));
+                        polkit_policy_default_set_allow_inactive (def, set_def_inactive_value);
+                        pk_error = NULL;
+                        if (!polkit_policy_file_entry_set_default (pfe, def, &pk_error)) {
+                                fprintf (stderr, "Error: code=%d: %s: %s\n",
+                                         polkit_error_get_error_code (pk_error),
+                                         polkit_error_get_error_name (pk_error),
+                                         polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                                goto out;
+                        }
+                        polkit_policy_default_unref (def);
+
+                        set_def_inactive_action_id = NULL;
+                }
+
+                if (set_def_active_action_id != NULL) {
+                        PolKitPolicyDefault *def;
+                        PolKitPolicyFileEntry *pfe;
+                        PolKitError *pk_error;
+
+                        pfe = polkit_policy_cache_get_entry_by_id (cache, set_def_active_action_id);
+                        if (pfe == NULL) {
+                                fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", set_def_active_action_id);
+                                goto out;
+                        }
+
+                        def = polkit_policy_default_clone (polkit_policy_file_entry_get_default (pfe));
+                        polkit_policy_default_set_allow_active (def, set_def_active_value);
+                        pk_error = NULL;
+                        if (!polkit_policy_file_entry_set_default (pfe, def, &pk_error)) {
+                                fprintf (stderr, "Error: code=%d: %s: %s\n",
+                                         polkit_error_get_error_code (pk_error),
+                                         polkit_error_get_error_name (pk_error),
+                                         polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                                goto out;
+                        }
+                        polkit_policy_default_unref (def);
+
+                        set_def_active_action_id = NULL;
+                }
+                
+                if (action_id != NULL) {
+                        PolKitPolicyFileEntry *pfe;
+                        pfe = polkit_policy_cache_get_entry_by_id (cache, action_id);
+                        if (pfe == NULL) {
+                                fprintf (stderr, "Cannot find policy file entry for action id '%s'\n", action_id);
+                                goto out;
+                        }
+                        _print_details_for_entry (pfe);
+
+                        action_id = NULL;
+                } else {
+                        goto done;
+                }
+        }
+
+done:
+
         polkit_context_unref (ctx);
 
         ret = 0;
diff --git a/tools/polkit-bash-completion.sh b/tools/polkit-bash-completion.sh
index 635159e..2f94048 100644
--- a/tools/polkit-bash-completion.sh
+++ b/tools/polkit-bash-completion.sh
@@ -85,15 +85,27 @@ __polkit_action() {
     local IFS=$'\n'
     local cur="${COMP_WORDS[COMP_CWORD]}"
 
-    if [ $COMP_CWORD = 1 ]; then
-        COMPREPLY=($(IFS=: compgen -S' ' -W "--action:--version:--help" -- $cur))
-    else
-	case "${COMP_WORDS[1]}" in
-            --action) 
-                COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
-                ;;
-        esac
-    fi
+    case $COMP_CWORD in
+        1)
+            COMPREPLY=($(IFS=: compgen -S' ' -W "--action:--reset-defaults:--set-defaults-any:--set-defaults-inactive:--set-defaults-active:--show-overrides:--version:--help" -- $cur))
+            ;;
+        2)
+	    case "${COMP_WORDS[1]}" in
+                --action|--set-defaults-any|--set-defaults-inactive|--set-defaults-active) 
+                    COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
+                    ;;
+                --reset-defaults) 
+                    COMPREPLY=($(compgen -W "$(polkit-action --show-overrides)" -- $cur))
+                    ;;
+            esac
+            ;;
+        3)
+	    case "${COMP_WORDS[1]}" in
+                --set-defaults-any|--set-defaults-inactive|--set-defaults-active)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "yes:no:auth_admin_one_shot:auth_admin:auth_admin_keep_session:auth_admin_keep_always:auth_self_one_shot:auth_self:auth_self_keep_session:auth_self_keep_always" -- $cur))
+                    ;;
+            esac
+    esac
 }
 
 ####################################################################################################


More information about the hal-commit mailing list