PolicyKit: Branch 'master' - 60 commits

David Zeuthen david at kemper.freedesktop.org
Mon Jun 4 10:51:29 PDT 2012


 Makefile.am                                                      |    7 
 actions/org.freedesktop.policykit.policy.in                      |   25 
 configure.ac                                                     |   90 
 data/Makefile.am                                                 |   36 
 data/org.freedesktop.PolicyKit1.conf                             |   20 
 data/org.freedesktop.PolicyKit1.conf.in                          |   20 
 data/org.freedesktop.PolicyKit1.service.in                       |    3 
 data/polkit.service.in                                           |    8 
 dev/null                                                         |binary
 docs/man/Makefile.am                                             |    2 
 docs/man/pkaction.xml                                            |   19 
 docs/man/pkcheck.xml                                             |   25 
 docs/man/pkexec.xml                                              |  251 -
 docs/man/pklocalauthority.xml                                    |  471 --
 docs/man/pkttyagent.xml                                          |   21 
 docs/man/polkit.xml                                              |  823 +++-
 docs/man/polkitd.xml                                             |   27 
 docs/polkit-1-diagrams.svg                                       |  376 +-
 docs/polkit-architecture.png                                     |binary
 docs/polkit-authentication-agent-example-wheel.png               |binary
 docs/polkit-authentication-agent-example.png                     |binary
 docs/polkit/Makefile.am                                          |   11 
 docs/polkit/overview.xml                                         |  300 +
 docs/polkit/polkit-1-docs.xml                                    |   10 
 docs/polkit/polkit-1-sections.txt                                |   80 
 docs/polkit/polkit-1.types                                       |    9 
 po/POTFILES.in                                                   |    1 
 src/Makefile.am                                                  |    2 
 src/examples/org.freedesktop.policykit.examples.pkexec.policy.in |   13 
 src/nullbackend/50-nullbackend.conf                              |   16 
 src/nullbackend/Makefile.am                                      |   50 
 src/nullbackend/nullbackend.c                                    |   34 
 src/nullbackend/polkitbackendnullauthority.c                     |  195 -
 src/nullbackend/polkitbackendnullauthority.h                     |   59 
 src/polkit/Makefile.am                                           |    6 
 src/polkit/polkitdetails.c                                       |    7 
 src/polkitagent/Makefile.am                                      |   10 
 src/polkitagent/polkitagentsession.c                             |    2 
 src/polkitbackend/50-default.rules                               |   12 
 src/polkitbackend/50-localauthority.conf                         |   10 
 src/polkitbackend/Makefile.am                                    |   76 
 src/polkitbackend/init.js                                        |   83 
 src/polkitbackend/polkitbackend.h                                |    1 
 src/polkitbackend/polkitbackendauthority.c                       |  167 
 src/polkitbackend/polkitbackendauthority.h                       |    7 
 src/polkitbackend/polkitbackendinteractiveauthority.c            |  182 -
 src/polkitbackend/polkitbackendinteractiveauthority.h            |    6 
 src/polkitbackend/polkitbackendjsauthority.c                     | 1789 ++++++++++
 src/polkitbackend/polkitbackendjsauthority.h                     |   75 
 src/polkitbackend/polkitbackendlocalauthority.c                  |  787 ----
 src/polkitbackend/polkitbackendlocalauthority.h                  |  107 
 src/polkitbackend/polkitbackendlocalauthorizationstore.c         |  776 ----
 src/polkitbackend/polkitbackendlocalauthorizationstore.h         |   87 
 src/polkitbackend/polkitbackendtypes.h                           |    4 
 src/polkitbackend/polkitd.c                                      |  257 +
 src/polkitbackend/toarray.pl                                     |   15 
 src/polkitd/Makefile.am                                          |   40 
 src/polkitd/gposixsignal.c                                       |  148 
 src/polkitd/gposixsignal.h                                       |   42 
 src/polkitd/main.c                                               |  188 -
 src/programs/pkexec.c                                            |    7 
 test/Makefile.am                                                 |    3 
 test/data/etc/polkit-1/rules.d/10-testing.rules                  |  175 
 test/data/etc/polkit-1/rules.d/15-testing.rules                  |   21 
 test/data/usr/share/polkit-1/rules.d/10-testing.rules            |   17 
 test/data/usr/share/polkit-1/rules.d/20-testing.rules            |   21 
 test/polkitbackend/Makefile.am                                   |    8 
 test/polkitbackend/polkitbackendlocalauthoritytest.c             |  264 -
 test/polkitbackend/polkitbackendlocalauthorizationstoretest.c    |  142 
 test/polkitbackend/test-polkitbackendjsauthority.c               |  409 ++
 70 files changed, 4663 insertions(+), 4292 deletions(-)

New commits:
commit bdc6fd7f84d2c99604a790faa622ba84ac9fde59
Author: David Zeuthen <zeuthen at gmail.com>
Date:   Mon Jun 4 13:40:45 2012 -0400

    State that authorization rules must not rely on SpiderMonkey features
    
    ... e.g. we reserve the right to switch out the JS engine.
    
    Signed-off-by: David Zeuthen <zeuthen at gmail.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 1bcb296..a055707 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -117,11 +117,11 @@ System Context         |                        |
     <para>
       For convenience, the <literal>libpolkit-gobject-1</literal>
       library wraps the polkit D-Bus API and is usable from any C/C++
-      program as well as higher-level languages <ulink
+      program as well as higher-level languages supporting <ulink
       url="https://live.gnome.org/GObjectIntrospection">GObjectIntrospection</ulink>
-      support such as Javascript and Python.  A mechanism can also use
-      the D-Bus API or the
-      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+      such as Javascript and Python.  A mechanism can also use the
+      D-Bus API or the <link
+      linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
       command to check authorizations. The
       <literal>libpolkit-agent-1</literal> library provides an
       abstraction of the native authentication system, e.g.
@@ -472,7 +472,7 @@ System Context         |                        |
       <filename class='directory'>/etc/polkit-1/rules.d</filename> and
       <filename class='directory'>/usr/share/polkit-1/rules.d</filename>
       directories by sorting the files in lexical order based on the
-      basename on each file (and if there's a tie, files in
+      basename on each file (if there's a tie, files in
       <filename class='directory'>/etc</filename>
       are processed before files in
       <filename class='directory'>/usr</filename>).
@@ -494,6 +494,14 @@ System Context         |                        |
       through the global
       <literal>polkit</literal> object (of type <type>Polkit</type>).
     </para>
+    <para>
+      While the JavaScript interpreter used in particular versions of
+      polkit may support non-standard features (such as the
+      <emphasis>let</emphasis> keyword), authorization rules must
+      conform to
+      <ulink url="http://en.wikipedia.org/wiki/ECMAScript#ECMAScript.2C_5th_Edition">ECMA-262 edition 5</ulink>
+      (in other words, the JavaScript interpreter used may change in future versions of polkit).
+    </para>
 
     <refsect2 id="polkit-rules-polkit">
       <title>The <type>Polkit</type> type</title>
commit b87f5fcafc64ff4a6ad8f1eac69fa7e00b51ec46
Author: David Zeuthen <zeuthen at gmail.com>
Date:   Mon Jun 4 13:24:39 2012 -0400

    Small updates to the "Writing polkit applications" chapter
    
    Signed-off-by: David Zeuthen <zeuthen at gmail.com>

diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml
index 19834d2..a979172 100644
--- a/docs/polkit/overview.xml
+++ b/docs/polkit/overview.xml
@@ -20,16 +20,14 @@
   <chapter id="polkit-apps">
     <title>Writing polkit applications</title>
     <para>
-      polkit applications are privileged mechanisms (typically) using
-      the polkit authority as a decider component. They do this by
-      installing a <filename class='extension'>.policy</filename> file
-      into the
-      <filename class='directory'>/usr/share/polkit-1/actions</filename>
+      polkit applications are applications using the polkit authority
+      as a decider component. They do this by installing a <filename
+      class='extension'>.policy</filename> file into the <filename
+      class='directory'>/usr/share/polkit-1/actions</filename>
       directory and communicating with the polkit authority at runtime
-      (either via the
-      <link linkend="ref-dbus-api">D-Bus API</link> or indirectly
-      via the
-      <link linkend="ref-api">libpolkit-gobject-1</link> library or the
+      (either via the <link linkend="ref-dbus-api">D-Bus API</link> or
+      indirectly through the <link
+      linkend="ref-api">libpolkit-gobject-1</link> library or the
       <link linkend="pkcheck.1">pkcheck</link> command).
     </para>
 
@@ -37,55 +35,139 @@
       <title>Best practices</title>
       <itemizedlist mark='opencircle' spacing='compact'>
 
-        <listitem><para>
-          <emphasis role='bold'>DO</emphasis> use polkit if you are writing a mechanism that is intended to be used by unprivileged programs.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DO</emphasis> use polkit if you are
+            writing a privileged mechanism (that is, running as
+            <emphasis>root</emphasis> or otherwise has special
+            permissions) that is intended to be used by unprivileged
+            programs.
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DO</emphasis> carefully consider what actions to define. In many cases there is not a 1:1 mapping between operations and polkit actions (often a polkit action has more to do with the object the operation is acting on than the operation itself). It is important to strike the right balance between too fine-grained and too coarse-grained.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DO</emphasis> carefully consider
+            what actions to define. In many cases there isn't a 1:1
+            mapping between operations and polkit actions. Often a
+            polkit action has more to do with the object the operation
+            is acting on than the operation itself. It is important to
+            strike the right balance between too fine-grained and too
+            coarse-grained.
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DO</emphasis> try to pick actions and implicit authorizations so applications using your mechanism will work out-of-the box for users logged in at the console (e.g. without interrupting the user with authentication dialogs).
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DO</emphasis> try to pick actions
+            and implicit authorizations so applications using your
+            mechanism will work out-of-the box for users logged in at
+            the console. Not interrupting console users with
+            authentication dialogs should be considered a
+            priority. For example, it is not wise to require console
+            users to authenticate for such mundane tasks as adding a
+            printer queue (if the administrator really wants the OS to
+            act this way, he can always deploy suitable authorization
+            rules).
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DO</emphasis> pass polkit variables along with
-        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
-requests so it's possible to write <emphasis>authorization rules</emphasis> matching on these. Also document these variables in your documentation (for example, see the
-<ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">udisks2 actions and variables</ulink>).
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DO</emphasis> pass polkit variables
+            along with <link
+            linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+            requests so it's possible to write <emphasis>authorization
+            rules</emphasis> matching on these. Also document these
+            variables in your documentation (for example, see the
+            <ulink
+            url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">udisks2
+            actions and variables</ulink>).
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DO</emphasis> pass a customized authentication message (using the <literal>polkit.message</literal> and <literal>polkit.gettext_domain</literal> variables) that includes more detailed information about the request than whatever is declared in the <filename class='extension'>.policy</filename> file's <literal>message</literal> element. For example, it's better to show <quote>Authentication is needed to format INTEL SSDSA2MH080G1GC (/dev/sda)</quote> than just <quote>Authentication is needed to format the device</quote>.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DO</emphasis> pass a customized
+            authentication message (using the
+            <literal>polkit.message</literal> and
+            <literal>polkit.gettext_domain</literal> variables) that
+            include more detailed information about the request than
+            whatever is declared in the <filename
+            class='extension'>.policy</filename> file's
+            <literal>message</literal> element. For example, it's
+            better to show <quote>Authentication is needed to format
+            INTEL SSDSA2MH080G1GC (/dev/sda)</quote> than just
+            <quote>Authentication is needed to format the
+            device</quote>.
+          </para>
+        </listitem>
 
 
-        <listitem><para>
-          <emphasis role='bold'>DON'T</emphasis> use polkit if your program isn't intended to be used by unprivileged programs. For example, if you are writing developer tools or low-level core OS command it's fine to just require the user to be root. Users can always run your tool through e.g.
-<citerefentry><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-<link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
-or write a simple polkit-using mechanism that allows access to a (safe) subset of your tool.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DON'T</emphasis> use polkit if your
+            program isn't intended to be used by unprivileged
+            programs. For example, if you are writing developer tools
+            or low-level core OS command-line tools it's fine to just
+            require the user to be root. Users can always run your
+            tool through e.g.
+            <citerefentry><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+            <link
+            linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+            or write a simple polkit-using mechanism that allows
+            access to a (safe) subset of your tool.
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DON'T</emphasis> use polkit unless you actually have to. In other words, not every single privileged program providing a service to an unprivileged programs has to use polkit. For example, if you have a small well-written <ulink url="http://en.wikipedia.org/wiki/Setuid">setuid</ulink> helper to help deal with some implementation-detail of the OS (such as elevating the priority of the sound server process to real-time for sessions on local seats) it's not really helpful to define a polkit action for this since no-one is going to choose to not grant the privilige (in the example, no-one is going run the sound server process without real-time priority).
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DON'T</emphasis> use polkit unless
+            you actually have to. In other words, not every single
+            privileged program providing service to unprivileged
+            programs has to use polkit. For example, if you have a
+            small well-written <ulink
+            url="http://en.wikipedia.org/wiki/Setuid">setuid</ulink>
+            helper to help deal with some implementation-detail of the
+            OS (such as elevating the priority of the sound server
+            process to real-time for console users) it's not really
+            helpful to define a polkit action for this since,
+            realistically, no-one is going to choose to
+            <emphasis>not</emphasis> grant the privilege. Remember, a
+            secure program is often one with little amount of code and
+            few dependencies.
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DON'T</emphasis> call
-        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
-        for all your actions every time the authority emits the
-        <link linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link> signal. Not only is this a waste of resources, the result may also be inaccurate as authorization rules can return whatever they want, whenever they want.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DON'T</emphasis> call <link
+            linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+            for all your actions every time the authority emits the
+            <link
+            linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link>
+            signal. Not only is this a waste of resources, the result
+            may also be inaccurate as authorization rules can return
+            whatever they want, whenever they want.
+          </para>
+        </listitem>
 
-        <listitem><para>
-          <emphasis role='bold'>DON'T</emphasis> block the main thread in your mechanism (e.g. the one used to service IPC requests from unprivileged programs) while waiting for the authority to reply - calls to
-        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
-        may take a very long time (seconds, even minutes) to complete as user interaction may be involved.
-        Instead, use either the <link linkend="polkit-authority-check-authorization">asynchronous API</link> or
-        a dedicated thread with the <link linkend="polkit-authority-check-authorization-sync">synchronous API</link>.
-        </para></listitem>
+        <listitem>
+          <para>
+            <emphasis role='bold'>DON'T</emphasis> block the main
+            thread in your mechanism (e.g. the one used to service IPC
+            requests from unprivileged programs) while waiting for the
+            authority to reply - calls to <link
+            linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+            may take a very long time (seconds, even minutes) to
+            complete as user interaction may be involved.  Instead,
+            use either the <link
+            linkend="polkit-authority-check-authorization">asynchronous
+            API</link> or a dedicated thread with the <link
+            linkend="polkit-authority-check-authorization-sync">synchronous
+            API</link>.
+          </para>
+        </listitem>
 
       </itemizedlist>
     </simplesect>
@@ -94,30 +176,32 @@ or write a simple polkit-using mechanism that allows access to a (safe) subset o
       <title>Usage in unprivileged programs</title>
 
       <para>
-        Unprivileged programs consuming privileged mechanisms normally
-        does use polkit directly - they simply call into the mechanism
-        and the mechanism either renders service (or refuses the
-        request) after checking with polkit (which may include
-        presenting an authentication dialog). In either case, the
-        unprivileged program in question is oblivious to the fact that
-        polkit is being used - it simply just waits for the privileged
-        mechanism to carry out the request (which, if authentication
-        dialogs are involved may take many seconds).
+        An unprivileged program normally does not use polkit directly
+        - it simply calls into a privileged mechanism and the
+        mechanism either renders service (or refuses the request)
+        after checking with polkit (which may include presenting an
+        authentication dialog). In this setup, the unprivileged
+        program is oblivious to the fact that polkit is being used -
+        it simply just waits for the privileged mechanism to carry out
+        the request (which, if authentication dialogs are involved may
+        take many seconds). This is a good thing because not worrying
+        about implementation details like polkit, helps simplify the
+        unprivileged program.
       </para>
       <para>
-        Note that unprivileged programs often need to disable, modify
-        or remove UI elements to e.g. convey to the user that a certain
-        action cannot be carried out (because e.g. the user is not
+        Occasionally unprivileged programs need to disable, modify or
+        remove UI elements to convey to the user that a certain action
+        cannot be carried out (because e.g. the user is not
         authorized) or authentication is needed (by e.g. displaying a
-        padlock icon in the UI).
-        In this case, the best approach is
+        padlock icon in the UI). In this case, the best approach is
         usually to have the unprivileged program get this information
-        from the privileged mechanism - especially because there often
-        is no reliable way that the unprivileged program can know what
-        polkit action is going to be used.  In general, there is no
-        guarantee that operations (such as D-Bus methods) map 1:1: to
-        polkit action - for example, a disk manager service's
-        <literal>Format()</literal> method may check for the action
+        from the privileged mechanism instead of polkit. This is
+        especially true because often there is no reliable way that
+        the unprivileged program can know what polkit action is going
+        to be used. In general, there is no guarantee that operations
+        (such as D-Bus methods) map 1:1: to polkit action - for
+        example, a disk manager service's <literal>Format()</literal>
+        method may check for the action
         <literal>net.company.diskmanager.format-removable</literal> if
         the disk is removable and
         <literal>net.company.diskmanager.format-fixed</literal>
@@ -128,7 +212,7 @@ or write a simple polkit-using mechanism that allows access to a (safe) subset o
         <emphasis>org.freedesktop.policykit.imply</emphasis> annotation
         (see the
         <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> man page),
-        it does make sense for an unprivileged program to query the
+        it is meaningful for an unprivileged program to query the
         polkit authority (to e.g. update UI elements) and it is
         in fact allowed to do so as long as the unprivileged program doesn't pass any variables along with the
         <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
@@ -138,13 +222,16 @@ or write a simple polkit-using mechanism that allows access to a (safe) subset o
         <link linkend="PolkitPermission"><type>PolkitPermission</type></link> type (which is derived from
         <ulink url="http://developer.gnome.org/gio/unstable/GPermission.html"><type>GPermission</type></ulink>)
         that can be used together with
-        <ulink url="http://developer.gnome.org/gtk3/unstable/GtkLockButton.html"><type>GtkLockButton</type></ulink>
-        (often used to implement an
-        <ulink url="http://developer.gnome.org/hig-book/3.2/hig-book.html#windows-instant-apply">instant apply</ulink>
-        paradigm).
+        <ulink url="http://developer.gnome.org/gtk3/unstable/GtkLockButton.html"><type>GtkLockButton</type></ulink>.
         Note that for <type>GtkLockButton</type> to work well, the
         polkit action backing it should use <literal>auth_self_keep</literal> or
         <literal>auth_admin_keep</literal> for its implicit authorizations.
+        This is often used to implement an <ulink
+        url="http://developer.gnome.org/hig-book/3.2/hig-book.html#windows-instant-apply">instant
+        apply</ulink> paradigm whereby the user
+        <emphasis>unlocks</emphasis> (by authenticating) e.g. a
+        preference pane window and is then free to change settings
+        until the authorization expires or is revoked.
       </para>
     </simplesect>
 
commit 8614c753db5090c353282b1cfa4a6d840b75ddad
Author: David Zeuthen <zeuthen at gmail.com>
Date:   Mon Jun 4 12:34:22 2012 -0400

    Update pkexec(1) man page with example
    
    Signed-off-by: David Zeuthen <zeuthen at gmail.com>

diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml
index 236f9f1..a8868b2 100644
--- a/docs/man/pkexec.xml
+++ b/docs/man/pkexec.xml
@@ -197,6 +197,7 @@
             that is suitable for display in an authentication dialog.
             Is typically set to a combination of the user name and the
             full name.
+            Example: <quote>David Zeuthen (davidz)</quote>
           </para>
         </listitem>
       </varlistentry>
commit b331d433dc65764208440b370347bcd6a67d615b
Author: David Zeuthen <zeuthen at gmail.com>
Date:   Mon Jun 4 12:32:09 2012 -0400

    Update links to udisks docs
    
    Signed-off-by: David Zeuthen <zeuthen at gmail.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index b19b92c..1bcb296 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -874,10 +874,8 @@ polkit.addRule(function(action, subject) {
         mechanism. In this case, the mechanism is
         <ulink url="http://udisks.freedesktop.org/docs/latest/udisks.8.html">UDisks</ulink>
         which defines a set of
-        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">actions</ulink>
-        and also documents the set of possible
-        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks2-Utilities.html#udisks-polkit-details">variables</ulink>
-        passed along with each request.
+        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">actions and variables</ulink>
+        that is used to match on:
       </para>
       <programlisting><![CDATA[
 // Allow users in group 'engineers' to perform any operation on
commit d84f291cd271774129ccd7f5b8ade157f58d3282
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 17:12:17 2012 -0400

    Rewrite the "Writing polkit applications" chapter
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml
index 9f5a1a9..19834d2 100644
--- a/docs/polkit/overview.xml
+++ b/docs/polkit/overview.xml
@@ -20,45 +20,149 @@
   <chapter id="polkit-apps">
     <title>Writing polkit applications</title>
     <para>
-      polkit applications are privileged mechanisms using the
-      polkit authority as a decider component. To do this, a
-      <emphasis>mechanism</emphasis> use either
-      the <link linkend="ref-api">GObject API</link>,
-      the <link linkend="ref-dbus-api">D-Bus API</link> or
-      the <link linkend="pkcheck.1">pkcheck</link> command to
-      communicate with the polkit Authority.
+      polkit applications are privileged mechanisms (typically) using
+      the polkit authority as a decider component. They do this by
+      installing a <filename class='extension'>.policy</filename> file
+      into the
+      <filename class='directory'>/usr/share/polkit-1/actions</filename>
+      directory and communicating with the polkit authority at runtime
+      (either via the
+      <link linkend="ref-dbus-api">D-Bus API</link> or indirectly
+      via the
+      <link linkend="ref-api">libpolkit-gobject-1</link> library or the
+      <link linkend="pkcheck.1">pkcheck</link> command).
     </para>
-    <para>
-      Note that <emphasis>clients</emphasis> normally doesn't use the
-      polkit API directly – it is intended for privileged
-      <emphasis>mechanisms</emphasis>. If a client needs to disable,
-      modify or remove UI elements to e.g. convey to the user that a
-      certain action cannot be carried out (because e.g. the user is
-      not authorized) or authentication is needed (by e.g. displaying
-      a padlock icon in the UI), it is usually better to have the
-      mechanism provide an API for this.
-    </para>
-    <para>
-      If a polkit application wants to handle the case where no
-      authentication agent exists (for example if the app is launched
-      via a
-      <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      login), it is trivial for the application to use the <link
-      linkend="PolkitAgentTextListener">PolkitAgentTextListener</link>
-      class to spawn its own authentication agent as
-      needed. Alternatively, the <xref linkend="pkttyagent.1"/>
-      helper can be used to do this.
-    </para>
-    <para>
-      As an example of code using the GObject API, see <xref linkend="cancel-example"/>.
-      For an example using the D-Bus API, see <xref linkend="polkit-raw-dbus-py"/>.
-    </para>
-    <example id="cancel-example"><title>Querying the Authority</title>
-      <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../src/examples/cancel.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
-    </example>
-    <example id="polkit-raw-dbus-py"><title>Accessing the Authority via D-Bus</title>
-      <programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../src/examples/polkit-raw-dbus.py"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
-    </example>
+
+    <simplesect id="polkit-apps-best-practices">
+      <title>Best practices</title>
+      <itemizedlist mark='opencircle' spacing='compact'>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> use polkit if you are writing a mechanism that is intended to be used by unprivileged programs.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> carefully consider what actions to define. In many cases there is not a 1:1 mapping between operations and polkit actions (often a polkit action has more to do with the object the operation is acting on than the operation itself). It is important to strike the right balance between too fine-grained and too coarse-grained.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> try to pick actions and implicit authorizations so applications using your mechanism will work out-of-the box for users logged in at the console (e.g. without interrupting the user with authentication dialogs).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> pass polkit variables along with
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+requests so it's possible to write <emphasis>authorization rules</emphasis> matching on these. Also document these variables in your documentation (for example, see the
+<ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">udisks2 actions and variables</ulink>).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DO</emphasis> pass a customized authentication message (using the <literal>polkit.message</literal> and <literal>polkit.gettext_domain</literal> variables) that includes more detailed information about the request than whatever is declared in the <filename class='extension'>.policy</filename> file's <literal>message</literal> element. For example, it's better to show <quote>Authentication is needed to format INTEL SSDSA2MH080G1GC (/dev/sda)</quote> than just <quote>Authentication is needed to format the device</quote>.
+        </para></listitem>
+
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> use polkit if your program isn't intended to be used by unprivileged programs. For example, if you are writing developer tools or low-level core OS command it's fine to just require the user to be root. Users can always run your tool through e.g.
+<citerefentry><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+<link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+or write a simple polkit-using mechanism that allows access to a (safe) subset of your tool.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> use polkit unless you actually have to. In other words, not every single privileged program providing a service to an unprivileged programs has to use polkit. For example, if you have a small well-written <ulink url="http://en.wikipedia.org/wiki/Setuid">setuid</ulink> helper to help deal with some implementation-detail of the OS (such as elevating the priority of the sound server process to real-time for sessions on local seats) it's not really helpful to define a polkit action for this since no-one is going to choose to not grant the privilige (in the example, no-one is going run the sound server process without real-time priority).
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> call
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        for all your actions every time the authority emits the
+        <link linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link> signal. Not only is this a waste of resources, the result may also be inaccurate as authorization rules can return whatever they want, whenever they want.
+        </para></listitem>
+
+        <listitem><para>
+          <emphasis role='bold'>DON'T</emphasis> block the main thread in your mechanism (e.g. the one used to service IPC requests from unprivileged programs) while waiting for the authority to reply - calls to
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        may take a very long time (seconds, even minutes) to complete as user interaction may be involved.
+        Instead, use either the <link linkend="polkit-authority-check-authorization">asynchronous API</link> or
+        a dedicated thread with the <link linkend="polkit-authority-check-authorization-sync">synchronous API</link>.
+        </para></listitem>
+
+      </itemizedlist>
+    </simplesect>
+
+    <simplesect id="polkit-apps-unprivileged">
+      <title>Usage in unprivileged programs</title>
+
+      <para>
+        Unprivileged programs consuming privileged mechanisms normally
+        does use polkit directly - they simply call into the mechanism
+        and the mechanism either renders service (or refuses the
+        request) after checking with polkit (which may include
+        presenting an authentication dialog). In either case, the
+        unprivileged program in question is oblivious to the fact that
+        polkit is being used - it simply just waits for the privileged
+        mechanism to carry out the request (which, if authentication
+        dialogs are involved may take many seconds).
+      </para>
+      <para>
+        Note that unprivileged programs often need to disable, modify
+        or remove UI elements to e.g. convey to the user that a certain
+        action cannot be carried out (because e.g. the user is not
+        authorized) or authentication is needed (by e.g. displaying a
+        padlock icon in the UI).
+        In this case, the best approach is
+        usually to have the unprivileged program get this information
+        from the privileged mechanism - especially because there often
+        is no reliable way that the unprivileged program can know what
+        polkit action is going to be used.  In general, there is no
+        guarantee that operations (such as D-Bus methods) map 1:1: to
+        polkit action - for example, a disk manager service's
+        <literal>Format()</literal> method may check for the action
+        <literal>net.company.diskmanager.format-removable</literal> if
+        the disk is removable and
+        <literal>net.company.diskmanager.format-fixed</literal>
+        otherwise.
+      </para>
+      <para>
+        However, in certain cases, for example when using the
+        <emphasis>org.freedesktop.policykit.imply</emphasis> annotation
+        (see the
+        <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> man page),
+        it does make sense for an unprivileged program to query the
+        polkit authority (to e.g. update UI elements) and it is
+        in fact allowed to do so as long as the unprivileged program doesn't pass any variables along with the
+        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+        call (otherwise it would be easy to spoof authentication dialogs and bypass authorization rules).
+        In fact, since this use-case is so common,
+        <link linkend="ref-api">libpolkit-gobject-1</link> provides the
+        <link linkend="PolkitPermission"><type>PolkitPermission</type></link> type (which is derived from
+        <ulink url="http://developer.gnome.org/gio/unstable/GPermission.html"><type>GPermission</type></ulink>)
+        that can be used together with
+        <ulink url="http://developer.gnome.org/gtk3/unstable/GtkLockButton.html"><type>GtkLockButton</type></ulink>
+        (often used to implement an
+        <ulink url="http://developer.gnome.org/hig-book/3.2/hig-book.html#windows-instant-apply">instant apply</ulink>
+        paradigm).
+        Note that for <type>GtkLockButton</type> to work well, the
+        polkit action backing it should use <literal>auth_self_keep</literal> or
+        <literal>auth_admin_keep</literal> for its implicit authorizations.
+      </para>
+    </simplesect>
+
+    <simplesect id="polkit-apps-no-auth-agent">
+      <title>No authentication agent</title>
+      <para>
+        If a polkit application wants to handle the case where no
+        authentication agent exists (for example if the app is launched
+        via a
+        <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        login), the application can use the <link
+        linkend="PolkitAgentTextListener">PolkitAgentTextListener</link>
+        type to spawn its own authentication agent as
+        needed. Alternatively, the <xref linkend="pkttyagent.1"/>
+        helper can be used to do this.
+      </para>
+    </simplesect>
+
   </chapter>
 
   <chapter id="polkit-agents">
commit da49ff95f2d136fd929f0ba5e75408a106f5de3b
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 13:37:49 2012 -0400

    Log when the name org.fd.PolicyKit1 has been acquired
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitd.c b/src/polkitbackend/polkitd.c
index 6a1bfb0..4cbef2f 100644
--- a/src/polkitbackend/polkitd.c
+++ b/src/polkitbackend/polkitd.c
@@ -53,12 +53,8 @@ on_bus_acquired (GDBusConnection *connection,
 
   g_print ("Connected to the system bus\n");
 
-  g_assert (authority == NULL);
   g_assert (registration_id == NULL);
 
-  authority = polkit_backend_authority_get ();
-  g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
-
   error = NULL;
   registration_id = polkit_backend_authority_register (authority,
                                                        connection,
@@ -77,7 +73,8 @@ on_name_lost (GDBusConnection *connection,
               const gchar     *name,
               gpointer         user_data)
 {
-  g_print ("Lost the name org.freedesktop.PolicyKit1 - exiting\n");
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "Lost the name org.freedesktop.PolicyKit1 - exiting");
   g_main_loop_quit (loop);
 }
 
@@ -86,7 +83,8 @@ on_name_acquired (GDBusConnection *connection,
                   const gchar     *name,
                   gpointer         user_data)
 {
-  g_print ("Acquired the name org.freedesktop.PolicyKit1\n");
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "Acquired the name org.freedesktop.PolicyKit1 on the system bus");
 }
 
 static gboolean
@@ -216,6 +214,8 @@ main (int    argc,
   if (g_getenv ("PATH") == NULL)
     g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE);
 
+  authority = polkit_backend_authority_get ();
+
   loop = g_main_loop_new (NULL, FALSE);
 
   sigint_id = g_unix_signal_add (SIGINT,
commit 8e0383cb9972f5b3b86e64f9b015f53671ce0323
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 12:40:42 2012 -0400

    Run polkitd as an unprivileged user
    
    There's really no reason to run all this code as uid 0.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index d9559cc..b26b333 100644
--- a/configure.ac
+++ b/configure.ac
@@ -194,6 +194,20 @@ fi
 AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"])
 
 dnl ---------------------------------------------------------------------------
+dnl - User for running polkitd
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(polkitd_user, AS_HELP_STRING([--with-polkitd-user=<user>],[User for running polkitd (polkitd)]))
+
+if test -z "$with_polkitd_user" ; then
+    POLKITD_USER=polkitd
+else
+    POLKITD_USER=$with_polkitd_user
+fi
+AC_SUBST(POLKITD_USER)
+AC_DEFINE_UNQUOTED(POLKITD_USER,"$POLKITD_USER", [User for running polkitd])
+
+dnl ---------------------------------------------------------------------------
 dnl - Select which authentication framework to use
 dnl ---------------------------------------------------------------------------
 
@@ -496,7 +510,8 @@ echo "
         Authentication framework:   ${POLKIT_AUTHFW}
         Session tracking:           ${SESSION_TRACKING}
         PAM support:                ${have_pam}
-        systemdsystemunitdir:       ${systemdsystemunitdir}"
+        systemdsystemunitdir:       ${systemdsystemunitdir}
+        polkitd user:               ${POLKITD_USER}"
 
 if test "$have_pam" = yes ; then
 echo "
@@ -522,10 +537,10 @@ echo "NOTE: The file ${bindir}/pkexec must be owned by root and"
 echo "      have mode 4755 (setuid root binary)"
 echo
 
-echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d"
-echo "      should have mode 700"
+echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d must be owned"
+echo "      by user '$POLKITD_USER' and have mode 700"
 echo
 
-echo "NOTE: The directory ${datadir}/polkit-1/rules.d"
-echo "      should have mode 700"
+echo "NOTE: The directory ${datadir}/polkit-1/rules.d must be owned"
+echo "      by user '$POLKITD_USER' and have mode 700"
 echo
diff --git a/data/Makefile.am b/data/Makefile.am
index 6623286..b2d0cde 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -4,6 +4,8 @@ NULL =
 
 libprivdir = $(prefix)/lib/polkit-1
 
+# ----------------------------------------------------------------------------------------------------
+
 servicedir       = $(datadir)/dbus-1/system-services
 service_in_files = org.freedesktop.PolicyKit1.service.in
 service_DATA     = $(service_in_files:.service.in=.service)
@@ -11,17 +13,28 @@ service_DATA     = $(service_in_files:.service.in=.service)
 $(service_DATA): $(service_in_files) Makefile
 	@sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@
 
+# ----------------------------------------------------------------------------------------------------
+
 dbusconfdir = $(sysconfdir)/dbus-1/system.d
-dbusconf_DATA = org.freedesktop.PolicyKit1.conf
+dbusconf_in_files = org.freedesktop.PolicyKit1.conf.in
+dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
+
+$(dbusconf_DATA): $(dbusconf_in_files) Makefile
+	@sed -e "s|\@polkitd_user\@|$(POLKITD_USER)|" $< > $@
+
+# ----------------------------------------------------------------------------------------------------
 
 if POLKIT_AUTHFW_PAM
 pamdir = $(sysconfdir)/pam.d
 pam_DATA = polkit-1
 endif
 
+# ----------------------------------------------------------------------------------------------------
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = polkit-gobject-1.pc polkit-backend-1.pc polkit-agent-1.pc
 
+# ----------------------------------------------------------------------------------------------------
 
 systemdservice_in_files = polkit.service.in
 
@@ -32,16 +45,18 @@ $(systemdservice_DATA): $(systemdservice_in_files) Makefile
 	@sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@
 endif
 
+# ----------------------------------------------------------------------------------------------------
+
 CLEANFILES = $(BUILT_SOURCES)
 
 EXTRA_DIST = 							\
 	org.freedesktop.PolicyKit1.Authority.xml 		\
 	org.freedesktop.PolicyKit1.AuthenticationAgent.xml 	\
 	$(service_in_files) 					\
+	$(dbusconf_in_files) 					\
 	$(systemdservice_in_files) 				\
-	$(dbusconf_DATA) 					\
 	$(NULL)
 
 
 clean-local :
-	rm -f *~ $(service_DATA) $(systemdservice_DATA)
+	rm -f *~ $(service_DATA) $(dbusconf_DATA) $(systemdservice_DATA)
diff --git a/data/org.freedesktop.PolicyKit1.conf b/data/org.freedesktop.PolicyKit1.conf
deleted file mode 100644
index c8ef513..0000000
--- a/data/org.freedesktop.PolicyKit1.conf
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
-
-<!DOCTYPE busconfig PUBLIC
- "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
-  <policy user="root">
-    <allow own="org.freedesktop.PolicyKit1"/>
-  </policy>
-
-  <policy context="default">
-    <allow send_destination="org.freedesktop.PolicyKit1"/>
-  </policy>
-
-  <!-- Allow uid 0 to send messages on the org.freedesktop.PolicyKit1.AuthenticationAgent interface -->
-  <policy user="root">
-    <allow send_interface="org.freedesktop.PolicyKit1.AuthenticationAgent"/>
-  </policy>
-
-</busconfig>
diff --git a/data/org.freedesktop.PolicyKit1.conf.in b/data/org.freedesktop.PolicyKit1.conf.in
new file mode 100644
index 0000000..c749207
--- /dev/null
+++ b/data/org.freedesktop.PolicyKit1.conf.in
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <policy user="@polkitd_user@">
+    <allow own="org.freedesktop.PolicyKit1"/>
+  </policy>
+
+  <policy context="default">
+    <allow send_destination="org.freedesktop.PolicyKit1"/>
+  </policy>
+
+  <!-- Allow uid 0 to send messages on the org.freedesktop.PolicyKit1.AuthenticationAgent interface -->
+  <policy user="@polkitd_user@">
+    <allow send_interface="org.freedesktop.PolicyKit1.AuthenticationAgent"/>
+  </policy>
+
+</busconfig>
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index bd39299..b19b92c 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -31,7 +31,16 @@
       untrusted. For every request from a subject, the mechanism needs
       to determine if the request is authorized or if it should refuse
       to service the subject. Using the polkit APIs, a mechanism can
-      offload this decision to a trusted party: The polkit Authority.
+      offload this decision to a trusted party: The polkit authority.
+    </para>
+
+    <para>
+      The polkit authority is implemented as an system daemon,
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      which itself has little privilege as it is running as the
+      <emphasis>polkitd</emphasis> system user. Mechanisms, subjects
+      and authentication agents communicate with the authority using
+      the system message bus.
     </para>
 
     <para>
@@ -204,7 +213,7 @@ System Context         |                        |
 
   <refsect1 id="polkit-declaring-actions"><title>DECLARING ACTIONS</title>
     <para>
-      A mechanism need to declare a set of <quote>ACTIONS</quote> in
+      A mechanism need to declare a set of <emphasis>actions</emphasis> in
       order to use polkit. Actions correspond to operations that
       clients can request the mechanism to carry out and are defined
       in XML files that the mechanism installs into the <filename
@@ -591,7 +600,9 @@ System Context         |                        |
         The <function>spawn()</function> method should be used sparingly
         as helpers may take a very long or indeterminate amount of time
         to complete and no other authorization check can be handled
-        while the helper is running.
+        while the helper is running. Note that the spawned programs
+        will run as the unprivileged <emphasis>polkitd</emphasis> system
+        user.
       </para>
 
       <para>
diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 879da2d..5fee8d4 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -41,6 +41,12 @@
     </para>
 
     <para>
+      <command>polkitd</command> must be started with superuser
+      privileges but drops privileges early by switching to the
+      unprivileged <emphasis>polkitd</emphasis> system user.
+    </para>
+
+    <para>
       See the <link
       linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
       man page for more information.
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index a173125..9f430d0 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -103,8 +103,10 @@ dist-hook :
 clean-local :
 	rm -f *~ $(BUILT_SOURCES)
 
-install-exec-hook:
+install-data-hook:
 	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
 	-chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
+	-chown $(POLKITD_USER) $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
 	mkdir -p $(DESTDIR)$(datadir)/polkit-1/rules.d
 	-chmod 700 $(DESTDIR)$(datadir)/polkit-1/rules.d
+	-chown $(POLKITD_USER) $(DESTDIR)$(datadir)/polkit-1/rules.d
diff --git a/src/polkitbackend/polkitd.c b/src/polkitbackend/polkitd.c
index 0bb3f32..6a1bfb0 100644
--- a/src/polkitbackend/polkitd.c
+++ b/src/polkitbackend/polkitd.c
@@ -25,6 +25,9 @@
 
 #include <glib-unix.h>
 
+#include <pwd.h>
+#include <grp.h>
+
 #include <polkit/polkit.h>
 #include <polkitbackend/polkitbackend.h>
 
@@ -94,6 +97,63 @@ on_sigint (gpointer user_data)
   return FALSE;
 }
 
+static gboolean
+become_user (const gchar  *user,
+             GError      **error)
+{
+  gboolean ret = FALSE;
+  struct passwd *pw;
+
+  g_return_val_if_fail (user != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  pw = getpwnam (user);
+  if (pw == NULL)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Error calling getpwnam(): %m");
+      goto out;
+    }
+
+  if (setgroups (0, NULL) != 0)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Error clearing groups: %m");
+      goto out;
+    }
+  if (initgroups (pw->pw_name, pw->pw_gid) != 0)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Error initializing groups: %m");
+      goto out;
+    }
+
+  setregid (pw->pw_gid, pw->pw_gid);
+  setreuid (pw->pw_uid, pw->pw_uid);
+  if ((geteuid () != pw->pw_uid) || (getuid () != pw->pw_uid) ||
+      (getegid () != pw->pw_gid) || (getgid () != pw->pw_gid))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Error becoming real+effective uid %d and gid %d: %m",
+                   (int) pw->pw_uid, (int) pw->pw_gid);
+      goto out;
+    }
+
+  if (chdir (pw->pw_dir) != 0)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Error changing to home directory %s: %m",
+                   pw->pw_dir);
+      goto out;
+    }
+
+
+  ret = TRUE;
+
+ out:
+  return ret;
+}
+
 int
 main (int    argc,
       char **argv)
@@ -142,6 +202,19 @@ main (int    argc,
         }
     }
 
+  error = NULL;
+  if (!become_user (POLKITD_USER, &error))
+    {
+      g_printerr ("Error switcing to user %s: %s\n",
+                  POLKITD_USER, error->message);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  g_print ("Successfully changed to user %s\n", POLKITD_USER);
+
+  if (g_getenv ("PATH") == NULL)
+    g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE);
 
   loop = g_main_loop_new (NULL, FALSE);
 
commit e5dafb816bcefdceb617e32fbfb527f865c8879c
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 11:20:05 2012 -0400

    Remove unused DBUS_GLIB_* and GIO_* variables
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/polkit/Makefile.am b/docs/polkit/Makefile.am
index a9bac88..8c6e58a 100644
--- a/docs/polkit/Makefile.am
+++ b/docs/polkit/Makefile.am
@@ -26,9 +26,7 @@ IGNORE_HFILES= \
 # CFLAGS and LDFLAGS for compiling scan program. Only needed
 # if $(DOC_MODULE).types is non-empty.
 INCLUDES = \
-	$(DBUS_GLIB_CFLAGS)					\
 	$(GLIB_CFLAGS)						\
-	$(GIO_CFLAGS)						\
 	-I$(top_srcdir)/src/polkit 				\
 	-I$(top_builddir)/src/polkit				\
 	-I$(top_srcdir)/src/polkitagent 			\
@@ -36,9 +34,7 @@ INCLUDES = \
 	$(NULL)
 
 GTKDOC_LIBS = \
-	$(DBUS_GLIB_LIBS)					\
 	$(GLIB_LIBS)						\
-	$(GIO_LIBS)						\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la	\
 	$(top_builddir)/src/polkitagent/libpolkit-agent-1.la	\
 	$(NULL)
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 8a0e76b..a173125 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -81,7 +81,6 @@ polkitd_CFLAGS = 							\
 	$(NULL)
 
 polkitd_LDADD = 				        		\
-	$(DBUS_GLIB_LIBS)						\
 	$(GLIB_LIBS)							\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
 	libpolkit-backend-1.la						\
commit 6415f6fd56ecf6e28d77b0ef6720f03e2a216f8d
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 11:12:26 2012 -0400

    Ensure polkitd is rebuilt if libpolkit-backend-1.la changes
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 3f6c043..8a0e76b 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -84,7 +84,7 @@ polkitd_LDADD = 				        		\
 	$(DBUS_GLIB_LIBS)						\
 	$(GLIB_LIBS)							\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
-	$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la	\
+	libpolkit-backend-1.la						\
 	$(NULL)
 
 # ----------------------------------------------------------------------------------------------------
commit d973961df4aeaf7cf02ec60f9d4167fee2324bf8
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 11:09:02 2012 -0400

    Move polkitd into src/polkitbackend
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index 930d8de..d9559cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -458,7 +458,6 @@ src/Makefile
 src/polkit/Makefile
 src/polkitbackend/Makefile
 src/polkitagent/Makefile
-src/polkitd/Makefile
 src/programs/Makefile
 src/examples/Makefile
 docs/version.xml
diff --git a/src/Makefile.am b/src/Makefile.am
index 3380fb2..96c1e0c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
 
-SUBDIRS = polkit polkitbackend polkitagent polkitd programs
+SUBDIRS = polkit polkitbackend polkitagent programs
 
 if BUILD_EXAMPLES
 SUBDIRS += examples
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 1bafd94..3f6c043 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -65,6 +65,31 @@ libpolkit_backend_1_la_LIBADD =                               		\
 rulesdir = $(sysconfdir)/polkit-1/rules.d
 rules_DATA = 50-default.rules
 
+# ----------------------------------------------------------------------------------------------------
+
+libprivdir = $(prefix)/lib/polkit-1
+libpriv_PROGRAMS = polkitd
+
+polkitd_SOURCES = 							\
+					polkitd.c			\
+	$(NULL)
+
+polkitd_CFLAGS = 							\
+	-DPOLKIT_BACKEND_I_KNOW_API_IS_SUBJECT_TO_CHANGE		\
+	-DG_LOG_DOMAIN=\"polkitd-1\"					\
+	$(GLIB_CFLAGS)							\
+	$(NULL)
+
+polkitd_LDADD = 				        		\
+	$(DBUS_GLIB_LIBS)						\
+	$(GLIB_LIBS)							\
+	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
+	$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la	\
+	$(NULL)
+
+# ----------------------------------------------------------------------------------------------------
+
+
 CLEANFILES = $(BUILT_SOURCES)
 
 EXTRA_DIST =								\
diff --git a/src/polkitbackend/polkitd.c b/src/polkitbackend/polkitd.c
new file mode 100644
index 0000000..0bb3f32
--- /dev/null
+++ b/src/polkitbackend/polkitd.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2008-2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#include "config.h"
+
+#include <signal.h>
+
+#include <glib-unix.h>
+
+#include <polkit/polkit.h>
+#include <polkitbackend/polkitbackend.h>
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static PolkitBackendAuthority *authority = NULL;
+static gpointer                registration_id = NULL;
+static GMainLoop              *loop = NULL;
+static gboolean                opt_replace = FALSE;
+static gboolean                opt_no_debug = FALSE;
+static GOptionEntry            opt_entries[] = {
+  {"replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace existing daemon", NULL},
+  {"no-debug", 'n', 0, G_OPTION_ARG_NONE, &opt_no_debug, "Don't print debug information", NULL},
+  {NULL }
+};
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+                 const gchar     *name,
+                 gpointer         user_data)
+{
+  GError *error;
+
+  g_print ("Connected to the system bus\n");
+
+  g_assert (authority == NULL);
+  g_assert (registration_id == NULL);
+
+  authority = polkit_backend_authority_get ();
+  g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
+
+  error = NULL;
+  registration_id = polkit_backend_authority_register (authority,
+                                                       connection,
+                                                       "/org/freedesktop/PolicyKit1/Authority",
+                                                       &error);
+  if (registration_id == NULL)
+    {
+      g_printerr ("Error registering authority: %s\n", error->message);
+      g_error_free (error);
+      g_main_loop_quit (loop); /* exit */
+    }
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  g_print ("Lost the name org.freedesktop.PolicyKit1 - exiting\n");
+  g_main_loop_quit (loop);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+  g_print ("Acquired the name org.freedesktop.PolicyKit1\n");
+}
+
+static gboolean
+on_sigint (gpointer user_data)
+{
+  g_print ("Handling SIGINT\n");
+  g_main_loop_quit (loop);
+  return FALSE;
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+  GError *error;
+  GOptionContext *opt_context;
+  gint ret;
+  guint name_owner_id;
+  guint sigint_id;
+
+  ret = 1;
+  loop = NULL;
+  opt_context = NULL;
+  name_owner_id = 0;
+  sigint_id = 0;
+  registration_id = NULL;
+
+  g_type_init ();
+
+  opt_context = g_option_context_new ("polkit system daemon");
+  g_option_context_add_main_entries (opt_context, opt_entries, NULL);
+  error = NULL;
+  if (!g_option_context_parse (opt_context, &argc, &argv, &error))
+    {
+      g_printerr ("Error parsing options: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  /* If --no-debug is requested don't clutter stdout/stderr etc.
+   */
+  if (opt_no_debug)
+    {
+      gint dev_null_fd;
+      dev_null_fd = open ("/dev/null", O_RDWR);
+      if (dev_null_fd >= 0)
+        {
+          dup2 (dev_null_fd, STDIN_FILENO);
+          dup2 (dev_null_fd, STDOUT_FILENO);
+          dup2 (dev_null_fd, STDERR_FILENO);
+          close (dev_null_fd);
+        }
+      else
+        {
+          g_warning ("Error opening /dev/null: %m");
+        }
+    }
+
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  sigint_id = g_unix_signal_add (SIGINT,
+                                 on_sigint,
+                                 NULL);
+
+  name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
+                                  "org.freedesktop.PolicyKit1",
+                                  G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+                                    (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
+                                  on_bus_acquired,
+                                  on_name_acquired,
+                                  on_name_lost,
+                                  NULL,
+                                  NULL);
+
+  g_print ("Entering main event loop\n");
+  g_main_loop_run (loop);
+
+  ret = 0;
+
+  g_print ("Shutting down\n");
+ out:
+  if (sigint_id > 0)
+    g_source_remove (sigint_id);
+  if (name_owner_id != 0)
+    g_bus_unown_name (name_owner_id);
+  if (registration_id != NULL)
+    polkit_backend_authority_unregister (registration_id);
+  if (authority != NULL)
+    g_object_unref (authority);
+  if (loop != NULL)
+    g_main_loop_unref (loop);
+  if (opt_context != NULL)
+    g_option_context_free (opt_context);
+
+  g_print ("Exiting with code %d\n", ret);
+  return ret;
+}
diff --git a/src/polkitd/Makefile.am b/src/polkitd/Makefile.am
deleted file mode 100644
index 8132fa7..0000000
--- a/src/polkitd/Makefile.am
+++ /dev/null
@@ -1,40 +0,0 @@
-NULL =
-
-INCLUDES =                                              		\
-	-I$(top_builddir)/src                           		\
-	-I$(top_srcdir)/src                             		\
-	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\"       		\
-	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"       		\
-	-DPACKAGE_DATA_DIR=\""$(datadir)"\"             		\
-	-DPACKAGE_BIN_DIR=\""$(bindir)"\"               		\
-	-DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" 		\
-	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\"         		\
-	-DPACKAGE_LIB_DIR=\""$(libdir)"\"               		\
-	-D_POSIX_PTHREAD_SEMANTICS                      		\
-	-D_REENTRANT	                                		\
-	$(NULL)
-
-libprivdir = $(prefix)/lib/polkit-1
-libpriv_PROGRAMS = polkitd
-
-polkitd_SOURCES = 							\
-					main.c				\
-	$(NULL)
-
-polkitd_CFLAGS = 							\
-	-DPOLKIT_BACKEND_I_KNOW_API_IS_SUBJECT_TO_CHANGE		\
-	-DG_LOG_DOMAIN=\"polkitd-1\"					\
-	$(GLIB_CFLAGS)							\
-	$(NULL)
-
-polkitd_LDADD = 				        		\
-	$(DBUS_GLIB_LIBS)						\
-	$(GLIB_LIBS)							\
-	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
-	$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la	\
-	$(NULL)
-
-CLEANFILES = $(BUILT_SOURCES)
-
-clean-local :
-	rm -f *~
diff --git a/src/polkitd/main.c b/src/polkitd/main.c
deleted file mode 100644
index f77a12f..0000000
--- a/src/polkitd/main.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2008-2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "config.h"
-
-#include <signal.h>
-
-#include <glib-unix.h>
-
-#include <polkit/polkit.h>
-#include <polkitbackend/polkitbackend.h>
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static PolkitBackendAuthority *authority = NULL;
-static gpointer                registration_id = NULL;
-static GMainLoop              *loop = NULL;
-static gboolean                opt_replace = FALSE;
-static gboolean                opt_no_debug = FALSE;
-static GOptionEntry            opt_entries[] = {
-  {"replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace existing daemon", NULL},
-  {"no-debug", 'n', 0, G_OPTION_ARG_NONE, &opt_no_debug, "Don't print debug information", NULL},
-  {NULL }
-};
-
-static void
-on_bus_acquired (GDBusConnection *connection,
-                 const gchar     *name,
-                 gpointer         user_data)
-{
-  GError *error;
-
-  g_print ("Connected to the system bus\n");
-
-  g_assert (authority == NULL);
-  g_assert (registration_id == NULL);
-
-  authority = polkit_backend_authority_get ();
-  g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
-
-  error = NULL;
-  registration_id = polkit_backend_authority_register (authority,
-                                                       connection,
-                                                       "/org/freedesktop/PolicyKit1/Authority",
-                                                       &error);
-  if (registration_id == NULL)
-    {
-      g_printerr ("Error registering authority: %s\n", error->message);
-      g_error_free (error);
-      g_main_loop_quit (loop); /* exit */
-    }
-}
-
-static void
-on_name_lost (GDBusConnection *connection,
-              const gchar     *name,
-              gpointer         user_data)
-{
-  g_print ("Lost the name org.freedesktop.PolicyKit1 - exiting\n");
-  g_main_loop_quit (loop);
-}
-
-static void
-on_name_acquired (GDBusConnection *connection,
-                  const gchar     *name,
-                  gpointer         user_data)
-{
-  g_print ("Acquired the name org.freedesktop.PolicyKit1\n");
-}
-
-static gboolean
-on_sigint (gpointer user_data)
-{
-  g_print ("Handling SIGINT\n");
-  g_main_loop_quit (loop);
-  return FALSE;
-}
-
-int
-main (int    argc,
-      char **argv)
-{
-  GError *error;
-  GOptionContext *opt_context;
-  gint ret;
-  guint name_owner_id;
-  guint sigint_id;
-
-  ret = 1;
-  loop = NULL;
-  opt_context = NULL;
-  name_owner_id = 0;
-  sigint_id = 0;
-  registration_id = NULL;
-
-  g_type_init ();
-
-  opt_context = g_option_context_new ("polkit authority");
-  g_option_context_add_main_entries (opt_context, opt_entries, NULL);
-  error = NULL;
-  if (!g_option_context_parse (opt_context, &argc, &argv, &error))
-    {
-      g_printerr ("Error parsing options: %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* If --no-debug is requested don't clutter stdout/stderr etc.
-   */
-  if (opt_no_debug)
-    {
-      gint dev_null_fd;
-      dev_null_fd = open ("/dev/null", O_RDWR);
-      if (dev_null_fd >= 0)
-        {
-          dup2 (dev_null_fd, STDIN_FILENO);
-          dup2 (dev_null_fd, STDOUT_FILENO);
-          dup2 (dev_null_fd, STDERR_FILENO);
-          close (dev_null_fd);
-        }
-      else
-        {
-          g_warning ("Error opening /dev/null: %m");
-        }
-    }
-
-
-  loop = g_main_loop_new (NULL, FALSE);
-
-  sigint_id = g_unix_signal_add (SIGINT,
-                                 on_sigint,
-                                 NULL);
-
-  name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
-                                  "org.freedesktop.PolicyKit1",
-                                  G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
-                                    (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
-                                  on_bus_acquired,
-                                  on_name_acquired,
-                                  on_name_lost,
-                                  NULL,
-                                  NULL);
-
-  g_print ("Entering main event loop\n");
-  g_main_loop_run (loop);
-
-  ret = 0;
-
-  g_print ("Shutting down\n");
- out:
-  if (sigint_id > 0)
-    g_source_remove (sigint_id);
-  if (name_owner_id != 0)
-    g_bus_unown_name (name_owner_id);
-  if (registration_id != NULL)
-    polkit_backend_authority_unregister (registration_id);
-  if (authority != NULL)
-    g_object_unref (authority);
-  if (loop != NULL)
-    g_main_loop_unref (loop);
-  if (opt_context != NULL)
-    g_option_context_free (opt_context);
-
-  g_print ("Exiting with code %d\n", ret);
-  return ret;
-}
commit 1caa8c2d3636bdd99dbbf0c84002946c432bd6e1
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 25 11:02:15 2012 -0400

    Use g_unix_signal_add() from GLib 2.30
    
    ... instead of the one I wrote myself.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index 961a886..930d8de 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,7 +123,7 @@ if test "x$GCC" = "xyes"; then
   changequote([,])dnl
 fi
 
-PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.28.0])
+PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.30.0])
 AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 
diff --git a/src/polkitd/Makefile.am b/src/polkitd/Makefile.am
index 584b795..8132fa7 100644
--- a/src/polkitd/Makefile.am
+++ b/src/polkitd/Makefile.am
@@ -19,7 +19,6 @@ libpriv_PROGRAMS = polkitd
 
 polkitd_SOURCES = 							\
 					main.c				\
-	gposixsignal.h			gposixsignal.c			\
 	$(NULL)
 
 polkitd_CFLAGS = 							\
diff --git a/src/polkitd/gposixsignal.c b/src/polkitd/gposixsignal.c
deleted file mode 100644
index 0dbd8e8..0000000
--- a/src/polkitd/gposixsignal.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "config.h"
-
-#include "gposixsignal.h"
-
-#if defined(__linux__)
-#include <unistd.h>
-#include <sys/signalfd.h>
-#include <signal.h>
-
-typedef struct
-{
-  GSource source;
-  GPollFD pollfd;
-  gint signum;
-} _GPosixSignalSource;
-
-static gboolean
-_g_posix_signal_source_prepare (GSource  *_source,
-                                gint     *timeout)
-{
-  *timeout = -1;
-  return FALSE;
-}
-
-static gboolean
-_g_posix_signal_source_check (GSource  *_source)
-{
-  _GPosixSignalSource *source = (_GPosixSignalSource *) _source;
-  return source->pollfd.revents != 0;
-}
-
-static gboolean
-_g_posix_signal_source_dispatch (GSource     *_source,
-                                 GSourceFunc  callback,
-                                 gpointer     user_data)
-
-{
-  _GPosixSignalWatchFunc func = (_GPosixSignalWatchFunc) callback;
-  g_warn_if_fail (func != NULL);
-  return (*func) (user_data);
-}
-
-static void
-_g_posix_signal_source_finalize (GSource *_source)
-{
-  _GPosixSignalSource *source = (_GPosixSignalSource *) _source;
-  close (source->pollfd.fd);
-}
-
-static GSourceFuncs _g_posix_signal_source_funcs =
-{
-  _g_posix_signal_source_prepare,
-  _g_posix_signal_source_check,
-  _g_posix_signal_source_dispatch,
-  _g_posix_signal_source_finalize
-};
-
-GSource *
-_g_posix_signal_source_new (gint signum)
-{
-  sigset_t sigset;
-  gint fd;
-  GSource *_source;
-  _GPosixSignalSource *source;
-
-  _source = NULL;
-
-  sigemptyset (&sigset);
-  sigaddset (&sigset, signum);
-
-  if (sigprocmask (SIG_BLOCK, &sigset, NULL) == -1)
-    g_assert_not_reached ();
-
-  fd = signalfd (-1, &sigset, SFD_NONBLOCK | SFD_CLOEXEC);
-
-  _source = g_source_new (&_g_posix_signal_source_funcs, sizeof (_GPosixSignalSource));
-  source = (_GPosixSignalSource *) _source;
-
-  source->pollfd.fd = fd;
-  source->pollfd.events = G_IO_IN;
-  g_source_add_poll (_source, &source->pollfd);
-
-  source->signum = signum;
-  return _source;
-}
-
-guint
-_g_posix_signal_watch_add (gint                   signum,
-                           gint                   priority,
-                           _GPosixSignalWatchFunc function,
-                           gpointer               user_data,
-                           GDestroyNotify         notify)
-{
-  GSource *source;
-  guint id;
-
-  g_return_val_if_fail (function != NULL, 0);
-
-  source = _g_posix_signal_source_new (signum);
-  if (priority != G_PRIORITY_DEFAULT_IDLE)
-    g_source_set_priority (source, priority);
-  g_source_set_callback (source, (GSourceFunc) function, user_data, notify);
-  id = g_source_attach (source, NULL);
-  g_source_unref (source);
-
-  return id;
-}
-#else  /* __linux__ */
-
-GSource *
-_g_posix_signal_source_new (gint signum)
-{
-  return NULL;
-}
-
-guint
-_g_posix_signal_watch_add (gint                   signum,
-                           gint                   priority,
-                           _GPosixSignalWatchFunc function,
-                           gpointer               user_data,
-                           GDestroyNotify         notify)
-{
-  return 0;
-}
-
-#endif /* __linux__ */
diff --git a/src/polkitd/gposixsignal.h b/src/polkitd/gposixsignal.h
deleted file mode 100644
index f9b3249..0000000
--- a/src/polkitd/gposixsignal.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/* 
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#ifndef ___G_POSIX_SIGNAL_H__
-#define ___G_POSIX_SIGNAL_H__
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef gboolean (*_GPosixSignalWatchFunc) (gpointer user_data);
-
-GSource *_g_posix_signal_source_new (gint signum);
-
-guint _g_posix_signal_watch_add (gint                   signum,
-                                 gint                   priority,
-                                 _GPosixSignalWatchFunc function,
-                                 gpointer               user_data,
-                                 GDestroyNotify         notify);
-
-G_END_DECLS
-
-#endif /* ___G_POSIX_SIGNAL_H__ */
diff --git a/src/polkitd/main.c b/src/polkitd/main.c
index b21723f..f77a12f 100644
--- a/src/polkitd/main.c
+++ b/src/polkitd/main.c
@@ -28,8 +28,6 @@
 #include <polkit/polkit.h>
 #include <polkitbackend/polkitbackend.h>
 
-#include "gposixsignal.h"
-
 /* ---------------------------------------------------------------------------------------------------- */
 
 static PolkitBackendAuthority *authority = NULL;
@@ -147,11 +145,9 @@ main (int    argc,
 
   loop = g_main_loop_new (NULL, FALSE);
 
-  sigint_id = _g_posix_signal_watch_add (SIGINT,
-                                         G_PRIORITY_DEFAULT,
-                                         on_sigint,
-                                         NULL,
-                                         NULL);
+  sigint_id = g_unix_signal_add (SIGINT,
+                                 on_sigint,
+                                 NULL);
 
   name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
                                   "org.freedesktop.PolicyKit1",
commit 587deddf80b2ad72d1ff21a2d5858c720303106c
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu May 24 15:50:59 2012 -0400

    Clarify pkexec(1) variables
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/actions/org.freedesktop.policykit.policy.in b/actions/org.freedesktop.policykit.policy.in
index 23608ee..7400b08 100644
--- a/actions/org.freedesktop.policykit.policy.in
+++ b/actions/org.freedesktop.policykit.policy.in
@@ -1,16 +1,15 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
+"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
 
-<!-- Policy definitions for core PolicyKit actions. Copyright (c) 2008 Red Hat, Inc. -->
+<!-- Policy definitions for core polkit actions. Copyright (c) 2008-2012 Red Hat, Inc. -->
 
 <policyconfig>
-  <vendor>The PolicyKit Project</vendor>
-  <vendor_url>http://hal.freedesktop.org/docs/PolicyKit/</vendor_url>
+  <vendor>The polkit project</vendor>
+  <vendor_url>http://www.freedesktop.org/wiki/Software/polkit/</vendor_url>
 
   <action id="org.freedesktop.policykit.exec">
-    <_description>Run programs as another user</_description>
+    <_description>Run a program as another user</_description>
     <_message>Authentication is required to run a program as another user</_message>
     <defaults>
       <allow_any>auth_admin</allow_any>
@@ -19,14 +18,4 @@
     </defaults>
   </action>
 
-  <action id="org.freedesktop.policykit.lockdown">
-    <_description>Configure lock down for an action</_description>
-    <_message>Authentication is required to configure lock down policy</_message>
-    <defaults>
-      <allow_any>no</allow_any>
-      <allow_inactive>no</allow_inactive>
-      <allow_active>auth_admin</allow_active>
-    </defaults>
-    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/pklalockdown</annotate>
-  </action>
 </policyconfig>
diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml
index d84aa1d..236f9f1 100644
--- a/docs/man/pkexec.xml
+++ b/docs/man/pkexec.xml
@@ -82,8 +82,8 @@
   <refsect1 id="pkexec-security-notes"><title>SECURITY NOTES</title>
     <para>
       Executing a program as another user is a privileged
-      operation. By default the required authorization (See
-      <xref linkend="pkexec-required-authz"/>) requires administrator
+      operation. By default the action to check for (see
+      <xref linkend="pkexec-action"/>) requires administrator
       authentication. In addition, the authentication dialog presented
       to the user will display the full path to the program to be
       executed so the user is aware of what will happen.
@@ -125,7 +125,7 @@
     </para>
   </refsect1>
 
-  <refsect1 id="pkexec-required-authz"><title>REQUIRED AUTHORIZATIONS</title>
+  <refsect1 id="pkexec-action"><title>ACTION AND AUTHORIZATIONS</title>
     <para>
       By default, the
       <emphasis>org.freedesktop.policykit.exec</emphasis> action is
@@ -134,10 +134,13 @@
       annotation on an action with the value set to the full path of
       the program. In addition to specifying the program, the
       authentication message, description, icon and defaults can be
-      specified. The strings <literal>$(user)</literal>,
-      <literal>$(program)</literal> and
-      <literal>$(command_line)</literal> in the message will be
-      expanded, see <xref linkend="pkexec-variables"/>.
+      specified.
+    </para>
+    <para>
+      Note that authentication messages may reference variables (see
+      <xref linkend="pkexec-variables"/>), for example
+      <literal>$(user)</literal> will be expanded to the value of the
+      <literal>user</literal> variable.
     </para>
   </refsect1>
 
@@ -178,7 +181,7 @@
         </listitem>
       </varlistentry>
       <varlistentry>
-        <term><emphasis>user_full</emphasis></term>
+        <term><emphasis>user.gecos</emphasis></term>
         <listitem>
           <para>
             The full name of the user to execute the program as.
@@ -186,6 +189,17 @@
           </para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><emphasis>user.display</emphasis></term>
+        <listitem>
+          <para>
+            A representation of the user to execute the program as
+            that is suitable for display in an authentication dialog.
+            Is typically set to a combination of the user name and the
+            full name.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
 
   </refsect1>
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 9718541..bd39299 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -486,7 +486,7 @@ System Context         |                        |
       <literal>polkit</literal> object (of type <type>Polkit</type>).
     </para>
 
-    <refsect2 id="polkit-rules-actions">
+    <refsect2 id="polkit-rules-polkit">
       <title>The <type>Polkit</type> type</title>
 
       <para>
@@ -616,10 +616,10 @@ polkit.addRule(function(action, subject) {
 });
 ]]></programlisting>
       <para>
-        will produce the following when the user runs 'pkexec bash -i' from a shelll:
+        will produce the following when the user runs 'pkexec -u bateman bash -i' from a shell:
       </para>
       <programlisting><![CDATA[
-May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:3: action=[Action id='org.freedesktop.policykit.exec' command_line='/usr/bin/bash -i' program='/usr/bin/bash' user_full='root (root)' user='root']
+May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:3: action=[Action id='org.freedesktop.policykit.exec' command_line='/usr/bin/bash -i' program='/usr/bin/bash' user='bateman' user.gecos='Patrick Bateman' user.display='Patrick Bateman (bateman)']
 May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:4: subject=[Subject pid=1352 user='davidz' groups=davidz,wheel, seat='seat0' session='1' local=true active=true]
 ]]></programlisting>
 
diff --git a/src/examples/org.freedesktop.policykit.examples.pkexec.policy.in b/src/examples/org.freedesktop.policykit.examples.pkexec.policy.in
index 9c05b77..049c024 100644
--- a/src/examples/org.freedesktop.policykit.examples.pkexec.policy.in
+++ b/src/examples/org.freedesktop.policykit.examples.pkexec.policy.in
@@ -1,15 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
+"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
 <policyconfig>
 
-  <vendor>Examples for the PolicyKit Project</vendor>
-  <vendor_url>http://hal.freedesktop.org/docs/PolicyKit/</vendor_url>
+  <vendor>Examples for the polkit project</vendor>
+  <vendor_url>http://www.freedesktop.org/wiki/Software/polkit/</vendor_url>
 
   <action id="org.freedesktop.policykit.example.pkexec.run-frobnicate">
-    <_description>Run the PolicyKit example program Frobnicate</_description>
-    <_message>Authentication is required to run the PolicyKit example program Frobnicate (user=$(user), program=$(program), command_line=$(command_line))</_message>
+    <_description>Run the polkit example program Frobnicate</_description>
+    <_message>Authentication is required to run the polkit example program Frobnicate (user=$(user), user.gecos=$(user.gecos), user.display=$(user.display), program=$(program), command_line=$(command_line))</_message>
     <icon_name>audio-x-generic</icon_name> <!-- just an example -->
     <defaults>
       <allow_any>no</allow_any>
diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
index db13cf9..d87825c 100644
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -669,11 +669,13 @@ main (int argc, char *argv[])
 
   details = polkit_details_new ();
   polkit_details_insert (details, "user", pw->pw_name);
+  if (pw->pw_gecos != NULL)
+    polkit_details_insert (details, "user.gecos", pw->pw_gecos);
   if (pw->pw_gecos != NULL && strlen (pw->pw_gecos) > 0)
     s = g_strdup_printf ("%s (%s)", pw->pw_gecos, pw->pw_name);
   else
     s = g_strdup_printf ("%s", pw->pw_name);
-  polkit_details_insert (details, "user_full", s);
+  polkit_details_insert (details, "user.display", s);
   g_free (s);
   polkit_details_insert (details, "program", path);
   polkit_details_insert (details, "command_line", command_line);
@@ -696,7 +698,7 @@ main (int argc, char *argv[])
                                   * be expanded to the path of the program e.g. "/bin/bash" and the latter
                                   * to the user e.g. "John Doe (johndoe)" or "johndoe".
                                   */
-                                 N_("Authentication is needed to run `$(program)' as user $(user)"));
+                                 N_("Authentication is needed to run `$(program)' as user $(user.display)"));
         }
     }
   polkit_details_insert (details, "polkit.gettext_domain", GETTEXT_PACKAGE);
commit 0e85f07781f8eab9670e06cee32b38657e3b62ce
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu May 24 14:51:46 2012 -0400

    Combine action and details parameters
    
    This also removes the ability to change detail parameters which is
    actually a good thing. If we later need a way to change the
    authentication message, we can always add something like
    polkit.addAuthenticationMessageRule() so the user can register a
    function returning a string.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index de4bb4a..9718541 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -484,120 +484,196 @@ System Context         |                        |
       programming language and interface with <command>polkitd</command>
       through the global
       <literal>polkit</literal> object (of type <type>Polkit</type>).
-      The following methods are available:
     </para>
 
-    <funcsynopsis>
-      <funcprototype>
-        <?dbhtml funcsynopsis-style='ansi'?>
-        <funcdef>void <function>addRule</function></funcdef>
-        <paramdef>string <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
-      </funcprototype>
-    </funcsynopsis>
-
-    <funcsynopsis>
-      <funcprototype>
-        <?dbhtml funcsynopsis-style='ansi'?>
-        <funcdef>void <function>addAdminRule</function></funcdef>
-        <paramdef>string[] <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
-      </funcprototype>
-    </funcsynopsis>
-
-    <funcsynopsis>
-      <funcprototype>
-        <?dbhtml funcsynopsis-style='ansi'?>
-        <funcdef>void <function>log</function></funcdef>
-        <paramdef>string <parameter>message</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
-
-    <funcsynopsis>
-      <funcprototype>
-        <?dbhtml funcsynopsis-style='ansi'?>
-        <funcdef>string <function>spawn</function></funcdef>
-        <paramdef>string[] <parameter>argv</parameter></paramdef>
-      </funcprototype>
-    </funcsynopsis>
+    <refsect2 id="polkit-rules-actions">
+      <title>The <type>Polkit</type> type</title>
 
-    <para>
-      The <function>addRule()</function> method is used for adding a
-      function that may be called whenever an authorization check for
-      <parameter>action</parameter>, <parameter>subject</parameter>
-      and <parameter>details</parameter> is performed. Functions are
-      called in the order they have been added until one of the
-      functions returns a value. Hence, to add an authorization rule
-      that is processed before other rules, put it in a file in
-      <filename class='directory'>/etc/polkit-1/rules.d</filename>
-      with a name that sorts before other rules files, for example
-      <filename>00-early-checks.rules</filename>. Each function should
-      return one of the values <literal>"no"</literal>,
-      <literal>"yes"</literal>, <literal>"auth_self"</literal>,
-      <literal>"auth_self_keep"</literal>,
-      <literal>"auth_admin"</literal>,
-      <literal>"auth_admin_keep"</literal> as defined above. If the
-      function returns <constant>null</constant>,
-      <constant>undefined</constant> or does not return a value at
-      all, the next function is tried.
-    </para>
+      <para>
+        The following methods are available on the <literal>polkit</literal> object:
+      </para>
 
-    <para>
-      The <function>addAdminRule()</function> method is used for
-      adding a function may be called whenever administrator
-      authentication is required. The function is used to specify what
-      identies may be used for administrator authentication for the
-      authorization check identified by <parameter>action</parameter>,
-      <parameter>subject</parameter> and
-      <parameter>details</parameter>. Functions added are called in
-      the order they have been added until one of the functions
-      returns a value. Each function should return an array of strings
-      where each string is of the form
-      <literal>"unix-group:&lt;group&gt;"</literal>,
-      <literal>"unix-netgroup:&lt;netgroup&gt;"</literal> or
-      <literal>"unix-user:&lt;user&gt;"</literal>.  If the function
-      returns <constant>null</constant>,
-      <constant>undefined</constant> or does not return a value at
-      all, the next function is tried.
-    </para>
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>void <function>addRule</function></funcdef>
+          <paramdef>string <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>) {...}</paramdef>
+        </funcprototype>
+      </funcsynopsis>
 
-    <para>
-      There is no guarantee that a function registered with
-      <function>addRule()</function> or
-      <function>addAdminRule()</function> is ever called - for example
-      an early rules file could register a function that always return
-      a value, hence ensuring that functions added later are never
-      called.
-    </para>
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>void <function>addAdminRule</function></funcdef>
+          <paramdef>string[] <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>) {...}</paramdef>
+        </funcprototype>
+      </funcsynopsis>
 
-    <para>
-      If user-provided code takes a long time to execute an exception
-      will be thrown which normally results in the function being
-      terminated (the current limit is 15 seconds). This is used to
-      catch runaway scripts.
-    </para>
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>void <function>log</function></funcdef>
+          <paramdef>string <parameter>message</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
 
-    <para>
-      The <function>log()</function> method writes the given
-      <parameter>message</parameter> to the system logger. Log entries
-      are emitted using the <constant>LOG_AUTHPRIV</constant> flag
-      meaning that the log entries usually ends up in the file
-      <filename>/var/log/secure</filename>. The
-      <function>log()</function> method is usually only used when
-      debugging rules.
-    </para>
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>string <function>spawn</function></funcdef>
+          <paramdef>string[] <parameter>argv</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
 
-    <para>
-      The <function>spawn()</function> method spawns an external
-      helper identified by the argument vector
-      <parameter>argv</parameter> and waits for it to terminate. If an
-      error occurs or the helper doesn't exit normally with exit code
-      0, an exception is thrown. If the helper does not exit within 10
-      seconds it is killed. Otherwise, the program's
-      <emphasis>standard output</emphasis> is returned as a string.
-      The <function>spawn()</function> method should be used sparingly
-      as helpers may take a very long or indeterminate amount of time
-      to complete and no other authorization check can be handled
-      while the helper is running.
-    </para>
+      <para>
+        The <function>addRule()</function> method is used for adding a
+        function that may be called whenever an authorization check for
+        <parameter>action</parameter> and <parameter>subject</parameter>
+        is performed. Functions are
+        called in the order they have been added until one of the
+        functions returns a value. Hence, to add an authorization rule
+        that is processed before other rules, put it in a file in
+        <filename class='directory'>/etc/polkit-1/rules.d</filename>
+        with a name that sorts before other rules files, for example
+        <filename>00-early-checks.rules</filename>. Each function should
+        return one of the values <literal>"no"</literal>,
+        <literal>"yes"</literal>, <literal>"auth_self"</literal>,
+        <literal>"auth_self_keep"</literal>,
+        <literal>"auth_admin"</literal>,
+        <literal>"auth_admin_keep"</literal> as defined above. If the
+        function returns <constant>null</constant>,
+        <constant>undefined</constant> or does not return a value at
+        all, the next function is tried.
+      </para>
+
+      <para>
+        The <function>addAdminRule()</function> method is used for
+        adding a function may be called whenever administrator
+        authentication is required. The function is used to specify what
+        identies may be used for administrator authentication for the
+        authorization check identified by <parameter>action</parameter>
+        and <parameter>subject</parameter>. Functions added are called in
+        the order they have been added until one of the functions
+        returns a value. Each function should return an array of strings
+        where each string is of the form
+        <literal>"unix-group:&lt;group&gt;"</literal>,
+        <literal>"unix-netgroup:&lt;netgroup&gt;"</literal> or
+        <literal>"unix-user:&lt;user&gt;"</literal>.  If the function
+        returns <constant>null</constant>,
+        <constant>undefined</constant> or does not return a value at
+        all, the next function is tried.
+      </para>
+
+      <para>
+        There is no guarantee that a function registered with
+        <function>addRule()</function> or
+        <function>addAdminRule()</function> is ever called - for example
+        an early rules file could register a function that always return
+        a value, hence ensuring that functions added later are never
+        called.
+      </para>
+
+      <para>
+        If user-provided code takes a long time to execute an exception
+        will be thrown which normally results in the function being
+        terminated (the current limit is 15 seconds). This is used to
+        catch runaway scripts.
+      </para>
+
+      <para>
+        The <function>spawn()</function> method spawns an external
+        helper identified by the argument vector
+        <parameter>argv</parameter> and waits for it to terminate. If an
+        error occurs or the helper doesn't exit normally with exit code
+        0, an exception is thrown. If the helper does not exit within 10
+        seconds it is killed. Otherwise, the program's
+        <emphasis>standard output</emphasis> is returned as a string.
+        The <function>spawn()</function> method should be used sparingly
+        as helpers may take a very long or indeterminate amount of time
+        to complete and no other authorization check can be handled
+        while the helper is running.
+      </para>
+
+      <para>
+        The <function>log()</function> method writes the given
+        <parameter>message</parameter> to the system logger prefixed
+        with the JavaScript filename and line number. Log entries are
+        emitted using the <constant>LOG_AUTHPRIV</constant> flag meaning
+        that the log entries usually ends up in the file
+        <filename>/var/log/secure</filename>. The
+        <function>log()</function> method is usually only used when
+        debugging rules. The <type>Action</type> and
+        <type>Subject</type> types has suitable
+        <function>toString()</function> methods defined for easy
+        logging, for example,
+      </para>
+      <programlisting><![CDATA[
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.freedesktop.policykit.exec") {
+        polkit.log("action=" + action);
+        polkit.log("subject=" + subject);
+    }
+});
+]]></programlisting>
+      <para>
+        will produce the following when the user runs 'pkexec bash -i' from a shelll:
+      </para>
+      <programlisting><![CDATA[
+May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:3: action=[Action id='org.freedesktop.policykit.exec' command_line='/usr/bin/bash -i' program='/usr/bin/bash' user_full='root (root)' user='root']
+May 24 14:28:50 thinkpad polkitd[32217]: /etc/polkit-1/rules.d/10-test.rules:4: subject=[Subject pid=1352 user='davidz' groups=davidz,wheel, seat='seat0' session='1' local=true active=true]
+]]></programlisting>
+
+    </refsect2>
+
+    <refsect2 id="polkit-rules-actions">
+      <title>The <type>Action</type> type</title>
+
+      <para>
+        The <parameter>action</parameter> parameter passed to user
+        functions is an object with information about the action
+        being checked. It is of type <type>Action</type> and has
+        the following attribute:
+      </para>
+
+      <variablelist id="polkit-js-action-attributes">
+        <varlistentry>
+          <term><type>string</type> id</term>
+          <listitem>
+            <para>
+              The action identifier, for example
+              <emphasis>org.freedesktop.policykit.exec</emphasis>.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+
+      <para>
+        The following methods are available on the <type>Action</type> type:
+      </para>
+
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>string <function>lookup</function></funcdef>
+          <paramdef>string <parameter>key</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The <function>lookup()</function> method is used to lookup the
+        polkit variables passed from the mechanism. For example, the
+        <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+        mechanism sets the variable <parameter>program</parameter>
+        which can be obtained in Javascript using the expression
+        <literal>action.lookup("program")</literal>. If there is
+        no value for the given <parameter>key</parameter>,
+        then <constant>undefined</constant> is returned.
+      </para>
+      <para>
+        Consult the documentation for each mechanism for what
+        variables are available for each action.
+      </para>
+    </refsect2>
 
     <refsect2 id="polkit-rules-subject">
       <title>The <type>Subject</type> type</title>
@@ -700,52 +776,6 @@ System Context         |                        |
         <function>isInNetGroup()</function> can be used to check if
         the subject is in a given netgroup.
       </para>
-
-    </refsect2>
-
-    <refsect2 id="polkit-rules-details">
-      <title>The <type>Details</type> type</title>
-
-      <para>
-        The <parameter>details</parameter> parameter passed to user
-        functions is an object with more information about the action
-        being checked. It is of type <type>Details</type> and has
-        details being set by the mechanism as attributes. For example,
-        the <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
-        mechanism sets the variable <parameter>program</parameter>
-        which can be obtained in Javascript using the expression
-        <literal>details["program"]</literal>. Consult the
-        documentation for each mechanism for what variables are
-        available for each action.
-      </para>
-
-      <para>
-        The <parameter>details</parameter> also has the following
-        well-known attributes:
-      </para>
-      <variablelist>
-        <varlistentry>
-          <term><emphasis>polkit.message</emphasis></term>
-          <listitem>
-            <para>
-              The message to show in the authentication dialog (only
-              used if authentication is needed). Its initial value is
-              taken from the action declaration (the <literal>message</literal> element in the <filename
-              class='extension'>.policy</filename> file) but the value
-              can be overridden by the mechanism setting this key in
-              the <parameter>details</parameter> passed when doing the
-              <link
-              linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
-              call.
-            </para>
-          </listitem>
-        </varlistentry>
-      </variablelist>
-      <para>
-        Note that a rule can set the
-        <parameter>polkit.message</parameter> attribute to change the
-        message shown in the authentication dialog.
-      </para>
     </refsect2>
 
     <refsect2 id="polkit-rules-examples">
@@ -757,8 +787,8 @@ System Context         |                        |
         users:
       </para>
       <programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
-    if (action == "org.freedesktop.accounts.user-administration" &&
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.freedesktop.accounts.user-administration" &&
         subject.isInGroup("admin")) {
         return "yes";
     }
@@ -769,20 +799,21 @@ polkit.addRule(function(action, subject, details) {
         Define administrative users to be the users in the <literal>wheel</literal> group:
       </para>
       <programlisting><![CDATA[
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
     return ["unix-group:wheel"];
 });
 ]]></programlisting>
 
       <para>
         Forbid users in group <literal>children</literal> to change
-        hostname configuration (that is, any action starting with
-        <literal>org.freedesktop.hostname1.</literal>) and allow
-        anyone else to do it after authenticating as themselves:
+        hostname configuration (that is, any action with an identifier
+        starting with <literal>org.freedesktop.hostname1.</literal>)
+        and allow anyone else to do it after authenticating as
+        themselves:
       </para>
       <programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
-    if (action.indexOf("org.freedesktop.hostname1.") == 0) {
+polkit.addRule(function(action, subject) {
+    if (action.id.indexOf("org.freedesktop.hostname1.") == 0) {
         if (subject.isInGroup("children")) {
             return "no";
         } else {
@@ -796,8 +827,8 @@ polkit.addRule(function(action, subject, details) {
         Run an external helper to determine if the current user may reboot the system:
       </para>
       <programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
-    if (action.indexOf("org.freedesktop.login1.reboot") == 0) {
+polkit.addRule(function(action, subject) {
+    if (action.id.indexOf("org.freedesktop.login1.reboot") == 0) {
         try {
             // user-may-reboot exits with succeess (exit code 0)
             // only if the passed username is authorized
@@ -813,17 +844,15 @@ polkit.addRule(function(action, subject, details) {
 ]]></programlisting>
 
       <para>
-        The following example showcases two things
+        The following example shows how the authorization decision
+        can depend on variables passed by the
+        <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+        mechanism:
       </para>
-      <itemizedlist mark='opencircle' spacing='compact'>
-        <listitem><para>how the authorization decision can depend on variables passed by the mechanism</para></listitem>
-        <listitem><para>how to override the message shown in the authentication dialog</para></listitem>
-      </itemizedlist>
       <programlisting><![CDATA[
-polkit.addRule(function(action, subject, details) {
-    if (action == "org.freedesktop.policykit.exec" &&
-        details["program"] == "/usr/bin/cat") {
-        details["polkit.message"] = "Achtung! You need to authenticate as yourself to cat(1) files!";
+polkit.addRule(function(action, subject) {
+    if (action.id == "org.freedesktop.policykit.exec" &&
+        action.lookup("program") == "/usr/bin/cat") {
         return "auth_self";
     }
 });
@@ -843,10 +872,10 @@ polkit.addRule(function(action, subject, details) {
 // Allow users in group 'engineers' to perform any operation on
 // some drives without having to authenticate
 //
-polkit.addRule(function(action, subject, details) {
-    if (action.indexOf("org.freedesktop.udisks2.") == 0 &&
-        details["drive.vendor"] == "SEAGATE" &&
-        details["drive.model"] == "ST3300657SS" &&
+polkit.addRule(function(action, subject) {
+    if (action.id.indexOf("org.freedesktop.udisks2.") == 0 &&
+        action.lookup("drive.vendor") == "SEAGATE" &&
+        action.lookup("drive.model") == "ST3300657SS" &&
         subject.isInGroup("engineers")) {
             return "yes";
         }
diff --git a/src/polkitbackend/50-default.rules b/src/polkitbackend/50-default.rules
index 9d3c33d..f427ae1 100644
--- a/src/polkitbackend/50-default.rules
+++ b/src/polkitbackend/50-default.rules
@@ -7,6 +7,6 @@
 // See the polkit(8) man page for more information
 // about configuring polkit.
 
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
     return ["unix-group:wheel"];
 });
diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 29f13fc..16862d4 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -1,14 +1,17 @@
 /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
 
-function Details() {
+function Action() {
+    this.lookup = function(name) {
+        return this["_detail_" + name];
+    },
+
     this.toString = function() {
-        var ret = "[Details";
+        var ret = "[Action id='" + this.id + "'";
         for (var i in this) {
-            if (typeof this[i] != "function") {
-                if (typeof this[i] == "string")
-                    ret += " " + i + "='" + this[i] + "'";
-                else
-                    ret += " " + i + "=" + this[i];
+            if (i.indexOf("_detail_") == 0) {
+                var key = i.substr(8);
+                var value = this[i];
+                ret += " " + key + "='" + value + "'";
             }
         }
         ret += "]";
@@ -17,7 +20,6 @@ function Details() {
 };
 
 function Subject() {
-
     this.isInGroup = function(group) {
         for (var n = 0; n < this.groups.length; n++) {
             if (this.groups[n] == group)
@@ -47,11 +49,11 @@ function Subject() {
 
 polkit._adminRuleFuncs = [];
 polkit.addAdminRule = function(callback) {this._adminRuleFuncs.push(callback);};
-polkit._runAdminRules = function(action, subject, details) {
+polkit._runAdminRules = function(action, subject) {
     var ret = null;
     for (var n = 0; n < this._adminRuleFuncs.length; n++) {
         var func = this._adminRuleFuncs[n];
-        var func_ret = func(action, subject, details);
+        var func_ret = func(action, subject);
         if (func_ret) {
             ret = func_ret;
             break
@@ -62,11 +64,11 @@ polkit._runAdminRules = function(action, subject, details) {
 
 polkit._ruleFuncs = [];
 polkit.addRule = function(callback) {this._ruleFuncs.push(callback);};
-polkit._runRules = function(action, subject, details) {
+polkit._runRules = function(action, subject) {
     var ret = null;
     for (var n = 0; n < this._ruleFuncs.length; n++) {
         var func = this._ruleFuncs[n];
-        var func_ret = func(action, subject, details);
+        var func_ret = func(action, subject);
         if (func_ret) {
             ret = func_ret;
             break
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index cc805e8..d71f85f 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -806,10 +806,11 @@ subject_to_jsval (PolkitBackendJsAuthority  *authority,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static gboolean
-details_to_jsval (PolkitBackendJsAuthority  *authority,
-                  PolkitDetails             *details,
-                  jsval                     *out_jsval,
-                  GError                   **error)
+action_and_details_to_jsval (PolkitBackendJsAuthority  *authority,
+                             const gchar               *action_id,
+                             PolkitDetails             *details,
+                             jsval                     *out_jsval,
+                             GError                   **error)
 {
   gboolean ret = FALSE;
   jsval ret_jsval;
@@ -818,8 +819,7 @@ details_to_jsval (PolkitBackendJsAuthority  *authority,
   gchar **keys;
   guint n;
 
-  src = "new Details();";
-
+  src = "new Action();";
   if (!JS_EvaluateScript (authority->priv->cx,
                           authority->priv->js_global,
                           src, strlen (src),
@@ -831,18 +831,18 @@ details_to_jsval (PolkitBackendJsAuthority  *authority,
     }
 
   obj = JSVAL_TO_OBJECT (ret_jsval);
+
+  set_property_str (authority, obj, "id", action_id);
+
   keys = polkit_details_get_keys (details);
   for (n = 0; keys != NULL && keys[n] != NULL; n++)
     {
-      const gchar *key = keys[n];
-      JSString *value_jsstr;
-      jsval value_jsval;
+      gchar *key;
       const gchar *value;
-
+      key = g_strdup_printf ("_detail_%s", keys[n]);
       value = polkit_details_lookup (details, keys[n]);
-      value_jsstr = JS_NewStringCopyZ (authority->priv->cx, value);
-      value_jsval = STRING_TO_JSVAL (value_jsstr);
-      JS_SetProperty (authority->priv->cx, obj, key, &value_jsval);
+      set_property_str (authority, obj, key, value);
+      g_free (key);
     }
   g_free (keys);
 
@@ -990,31 +990,27 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   GList *ret = NULL;
-  jsval argv[3] = {0};
+  jsval argv[2] = {0};
   jsval rval = {0};
-  JSString *action_id_jstr;
   guint n;
   GError *error = NULL;
   JSString *ret_jsstr;
   gchar *ret_str = NULL;
   gchar **ret_strs = NULL;
 
-  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
-  argv[0] = STRING_TO_JSVAL (action_id_jstr);
-
-  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
+  if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error converting subject to JS object: %s",
+                                    "Error converting action and details to JS object: %s",
                                     error->message);
       g_clear_error (&error);
       goto out;
     }
 
-  if (!details_to_jsval (authority, details, &argv[2], &error))
+  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error converting details to JS object: %s",
+                                    "Error converting subject to JS object: %s",
                                     error->message);
       g_clear_error (&error);
       goto out;
@@ -1022,7 +1018,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 
   if (!call_js_function_with_runaway_killer (authority,
                                              "_runAdminRules",
-                                             3,
+                                             2,
                                              argv,
                                              &rval))
     {
@@ -1093,34 +1089,27 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   PolkitImplicitAuthorization ret = implicit;
-  jsval argv[3] = {0};
+  jsval argv[2] = {0};
   jsval rval = {0};
-  JSString *action_id_jstr;
   GError *error = NULL;
   JSString *ret_jsstr;
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
   gboolean good = FALSE;
-  JSIdArray *ids;
-  JSObject *details_obj;
-  gint n;
 
-  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
-  argv[0] = STRING_TO_JSVAL (action_id_jstr);
-
-  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
+  if (!action_and_details_to_jsval (authority, action_id, details, &argv[0], &error))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error converting subject to JS object: %s",
+                                    "Error converting action and details to JS object: %s",
                                     error->message);
       g_clear_error (&error);
       goto out;
     }
 
-  if (!details_to_jsval (authority, details, &argv[2], &error))
+  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error converting details to JS object: %s",
+                                    "Error converting subject to JS object: %s",
                                     error->message);
       g_clear_error (&error);
       goto out;
@@ -1169,53 +1158,6 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
       goto out;
     }
 
-
-  /* the JS code may have modifed @details - update PolkitDetails
-   * object accordingly
-   */
-  details_obj = JSVAL_TO_OBJECT (argv[2]);
-  ids = JS_Enumerate (authority->priv->cx, details_obj);
-  if (ids == NULL)
-    {
-      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Failed to enumerate properties of Details object");
-      goto out;
-    }
-  for (n = 0; n < ids->length; n++)
-    {
-      jsval id_val;
-      jsval value_val;
-      char *id_s = NULL;
-      char *value_s = NULL;
-
-      if (!JS_IdToValue (authority->priv->cx, ids->vector[n], &id_val))
-        {
-          g_warning ("Error getting string for property id %d", n);
-          goto cont;
-        }
-      id_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (id_val));
-
-      if (!JS_GetPropertyById (authority->priv->cx, details_obj, ids->vector[n], &value_val))
-        {
-          g_warning ("Error getting value string for property value %s", id_s);
-          goto cont;
-        }
-
-      /* skip e.g. functions */
-      if (!JSVAL_IS_STRING (value_val) && !JSVAL_IS_NULL (value_val))
-        goto cont;
-
-      value_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (value_val));
-
-      polkit_details_insert (details, id_s, value_s);
-    cont:
-      if (id_s != NULL)
-        JS_free (authority->priv->cx, id_s);
-      if (value_s != NULL)
-        JS_free (authority->priv->cx, value_s);
-    }
-  JS_DestroyIdArray (authority->priv->cx, ids);
-
   good = TRUE;
 
  out:
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 1dba38a..4a17f8c 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -4,55 +4,75 @@
 
 /* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
 
-polkit.addAdminRule(function(action, subject, details) {
-    if (action == "net.company.action1") {
+// ---------------------------------------------------------------------
+// admin rules
+
+polkit.addAdminRule(function(action, subject) {
+    if (action.id == "net.company.action1") {
         return ["unix-group:admin"];
     }
 });
 
-polkit.addAdminRule(function(action, subject, details) {
-    if (action == "net.company.action2") {
+polkit.addAdminRule(function(action, subject) {
+    if (action.id == "net.company.action2") {
         return ["unix-group:users"];
     }
 });
 
-polkit.addAdminRule(function(action, subject, details) {
-    if (action == "net.company.action3") {
+polkit.addAdminRule(function(action, subject) {
+    if (action.id == "net.company.action3") {
         return ["unix-netgroup:foo"];
     }
 });
 
 // Fallback
-polkit.addAdminRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject) {
     return ["unix-group:admin", "unix-user:root"];
 });
 
 // -----
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.productA.action0") {
+// ---------------------------------------------------------------------
+// basics
+
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.productA.action0") {
         return "auth_admin";
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.productA.action1") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.productA.action1") {
         return "auth_self";
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order0") {
-        details["test_detail"] = "a";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order0") {
         return "yes";
     }
 });
 
 // ---------------------------------------------------------------------
+// variables
+
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.group.variables") {
+        if (action.lookup("foo") == "1")
+            return "yes";
+        else if (action.lookup("foo") == "2")
+            return "auth_self";
+        else
+            return "auth_admin";
+    }
+});
+
+
+// ---------------------------------------------------------------------
 // group membership
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.group.only_group_users") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.group.only_group_users") {
         if (subject.isInGroup("users"))
             return "yes";
         else
@@ -63,8 +83,8 @@ polkit.addRule(function(action, subject, details) {
 // ---------------------------------------------------------------------
 // netgroup membership
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.group.only_netgroup_users") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.group.only_netgroup_users") {
         if (subject.isInNetGroup("foo"))
             return "yes";
         else
@@ -75,8 +95,8 @@ polkit.addRule(function(action, subject, details) {
 // ---------------------------------------------------------------------
 // spawning
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.spawning.non_existing_helper") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.spawning.non_existing_helper") {
         try {
             polkit.spawn(["/path/to/non/existing/helper"]);
             return "no";
@@ -86,8 +106,8 @@ polkit.addRule(function(action, subject, details) {
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.spawning.successful_helper") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.spawning.successful_helper") {
         try {
             polkit.spawn(["/bin/true"]);
             return "yes";
@@ -97,8 +117,8 @@ polkit.addRule(function(action, subject, details) {
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.spawning.failing_helper") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.spawning.failing_helper") {
         try {
             polkit.spawn(["/bin/false"]);
             return "no";
@@ -108,8 +128,8 @@ polkit.addRule(function(action, subject, details) {
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.spawning.helper_with_output") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.spawning.helper_with_output") {
         try {
             var out = polkit.spawn(["echo", "-n", "-e", "Hello\nWorld"]);
             if (out == "Hello\nWorld")
@@ -122,8 +142,8 @@ polkit.addRule(function(action, subject, details) {
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.spawning.helper_timeout") {
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.spawning.helper_timeout") {
         try {
             polkit.spawn(["sleep", "20"]);
             return "no";
@@ -135,8 +155,11 @@ polkit.addRule(function(action, subject, details) {
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.run_away_script") {
+// ---------------------------------------------------------------------
+// runaway scripts
+
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.run_away_script") {
         try {
             // The following code will never terminate so the runaway
             // script killer will step in after 15 seconds and throw
diff --git a/test/data/etc/polkit-1/rules.d/15-testing.rules b/test/data/etc/polkit-1/rules.d/15-testing.rules
index 9968aa7..b64d731 100644
--- a/test/data/etc/polkit-1/rules.d/15-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/15-testing.rules
@@ -2,23 +2,20 @@
 
 /* see test/polkitbackend/test-polkitbackendjsauthority.c */
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order0") {
-        details["test_detail"] = "c";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order0") {
+        return "no"; // earlier rule should win
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order1") {
-        details["test_detail"] = "c";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order1") {
+        return "no"; // earlier rule should win
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order2") {
-        details["test_detail"] = "c";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order2") {
         return "yes";
     }
 });
diff --git a/test/data/usr/share/polkit-1/rules.d/10-testing.rules b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
index 48c4957..c60e262 100644
--- a/test/data/usr/share/polkit-1/rules.d/10-testing.rules
+++ b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
@@ -4,16 +4,14 @@
 
 /* NOTE: this is the /usr/share/polkit-1/rules.d version of 10-testing.rules */
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order0") {
-        details["test_detail"] = "c";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order0") {
+        return "no"; // earlier rule should win
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order1") {
-        details["test_detail"] = "b";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order1") {
         return "yes";
     }
 });
diff --git a/test/data/usr/share/polkit-1/rules.d/20-testing.rules b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
index 16dd039..5c5bb2c 100644
--- a/test/data/usr/share/polkit-1/rules.d/20-testing.rules
+++ b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
@@ -2,24 +2,20 @@
 
 /* see test/polkitbackend/test-polkitbackendjsauthority.c */
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order0") {
-        polkit.log("blabla");
-        details["test_detail"] = "d";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order0") {
+        return "no"; // earlier rule should win
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order1") {
-        details["test_detail"] = "d";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order1") {
+        return "no"; // earlier rule should win
     }
 });
 
-polkit.addRule(function(action, subject, details) {
-    if (action == "net.company.order2") {
-        details["test_detail"] = "d";
-        return "yes";
+polkit.addRule(function(action, subject) {
+    if (action.id == "net.company.order2") {
+        return "no"; // earlier rule should win
     }
 });
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 728b433..0a5d0e8 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -24,6 +24,8 @@
 #include "glib.h"
 
 #include <locale.h>
+#include <string.h>
+
 #include <polkit/polkit.h>
 #include <polkitbackend/polkitbackendjsauthority.h>
 #include <polkittesthelper.h>
@@ -156,8 +158,8 @@ struct RulesTestCase
   const gchar *test_name;
   const gchar *action_id;
   const gchar *identity;
+  const gchar *vars;
   PolkitImplicitAuthorization expected_result;
-  const gchar *expected_detail;
 };
 
 static const RulesTestCase rules_test_cases[] = {
@@ -166,15 +168,15 @@ static const RulesTestCase rules_test_cases[] = {
     "basic0",
     "net.company.productA.action0",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
-    NULL
   },
   {
     "basic1",
     "net.company.productA.action1",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
-    NULL
   },
 
   /* Ordering tests ... we have four rules files, check they are
@@ -192,24 +194,47 @@ static const RulesTestCase rules_test_cases[] = {
     "order0",
     "net.company.order0",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    "a"
   },
   {
     /* defined in file b, c, d - should pick file b */
     "order1",
     "net.company.order1",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    "b"
   },
   {
     /* defined in file c, d - should pick file c */
     "order2",
     "net.company.order2",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    "c"
+  },
+
+  /* variables */
+  {
+    "variables1",
+    "net.company.group.variables",
+    "unix-user:root",
+    "foo=1",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+  },
+  {
+    "variables2",
+    "net.company.group.variables",
+    "unix-user:root",
+    "foo=2",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
+  },
+  {
+    "variables3",
+    "net.company.group.variables",
+    "unix-user:root",
+    NULL,
+    POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
   },
 
   /* check group membership */
@@ -218,16 +243,16 @@ static const RulesTestCase rules_test_cases[] = {
     "group_membership_with_member",
     "net.company.group.only_group_users",
     "unix-user:john",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
     /* sally is not a member of group 'users', see test/etc/group */
     "group_membership_with_non_member",
     "net.company.group.only_group_users",
     "unix-user:sally",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
-    NULL
   },
 
   /* check netgroup membership */
@@ -236,16 +261,16 @@ static const RulesTestCase rules_test_cases[] = {
     "netgroup_membership_with_member",
     "net.company.group.only_netgroup_users",
     "unix-user:john",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
     /* sally is not a member of netgroup 'foo', see test/etc/netgroup */
     "netgroup_membership_with_non_member",
     "net.company.group.only_netgroup_users",
     "unix-user:sally",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
-    NULL
   },
 
   /* spawning */
@@ -253,43 +278,45 @@ static const RulesTestCase rules_test_cases[] = {
     "spawning_non_existing_helper",
     "net.company.spawning.non_existing_helper",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
     "spawning_successful_helper",
     "net.company.spawning.successful_helper",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
     "spawning_failing_helper",
     "net.company.spawning.failing_helper",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
     "spawning_helper_with_output",
     "net.company.spawning.helper_with_output",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
   {
-    "runaway_script",
-    "net.company.run_away_script",
+    "spawning_helper_timeout",
+    "net.company.spawning.helper_timeout",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
+
+  /* runaway scripts */
   {
-    "spawning_helper_timeout",
-    "net.company.spawning.helper_timeout",
+    "runaway_script",
+    "net.company.run_away_script",
     "unix-user:root",
+    NULL,
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
-    NULL
   },
 };
 
@@ -316,6 +343,23 @@ rules_test_func (gconstpointer user_data)
 
   details = polkit_details_new ();
 
+  if (tc->vars != NULL)
+    {
+      gchar *s;
+      const gchar *key;
+      const gchar *value;
+
+      s = g_strdup (tc->vars);
+      key = s;
+      value = strchr (key, '=');
+      g_assert (value != NULL);
+      *((gchar *) value) = '\0';
+      value += 1;
+
+      polkit_details_insert (details, key, value);
+      g_free (s);
+    }
+
   result = polkit_backend_interactive_authority_check_authorization_sync (POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
                                                                           caller,
                                                                           subject,
@@ -326,7 +370,6 @@ rules_test_func (gconstpointer user_data)
                                                                           details,
                                                                           POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN);
   g_assert_cmpint (result, ==, tc->expected_result);
-  g_assert_cmpstr (polkit_details_lookup (details, "test_detail"), ==, tc->expected_detail);
 
   g_clear_object (&user_for_subject);
   g_clear_object (&subject);
commit 2ec9e681e0ee17bcc60a0724b201b2e19b573abb
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu May 24 11:39:57 2012 -0400

    Use a condition variable to signal that runaway killer thread is ready
    
    ... instead of the unsafe g_thread_yield() busy-wait loop.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index a05d022..cc805e8 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -65,9 +65,10 @@ struct _PolkitBackendJsAuthorityPrivate
   JSObject *js_polkit;
 
   GThread *runaway_killer_thread;
+  GMutex rkt_init_mutex;
+  GCond rkt_init_cond;
   GMainContext *rkt_context;
   GMainLoop *rkt_loop;
-
   GSource *rkt_source;
 
   /* A list of JSObject instances */
@@ -472,13 +473,17 @@ polkit_backend_js_authority_constructed (GObject *object)
       authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
     }
 
+  g_mutex_init (&authority->priv->rkt_init_mutex);
+  g_cond_init (&authority->priv->rkt_init_cond);
+
   authority->priv->runaway_killer_thread = g_thread_new ("runaway-killer-thread",
                                                          runaway_killer_thread_func,
                                                          authority);
 
-  /* TODO: use a condition variable */
-  while (authority->priv->rkt_loop == NULL)
-    g_thread_yield ();
+  /* wait for runaway_killer_thread to set up its GMainContext */
+  g_cond_wait (&authority->priv->rkt_init_cond, &authority->priv->rkt_init_mutex);
+  g_mutex_unlock (&authority->priv->rkt_init_mutex);
+  g_assert (authority->priv->rkt_context != NULL);
 
   setup_file_monitors (authority);
   load_scripts (authority);
@@ -497,6 +502,9 @@ polkit_backend_js_authority_finalize (GObject *object)
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
   guint n;
 
+  g_mutex_clear (&authority->priv->rkt_init_mutex);
+  g_cond_clear (&authority->priv->rkt_init_cond);
+
   /* shut down the killer thread */
   g_assert (authority->priv->rkt_loop != NULL);
   g_main_loop_quit (authority->priv->rkt_loop);
@@ -859,7 +867,10 @@ runaway_killer_thread_func (gpointer user_data)
 
   g_main_context_push_thread_default (authority->priv->rkt_context);
 
-  /* TODO: signal the main thread that we're done constructing */
+  /* Signal the main thread that we're done constructing */
+  g_mutex_lock (&authority->priv->rkt_init_mutex);
+  g_cond_signal (&authority->priv->rkt_init_cond);
+  g_mutex_unlock (&authority->priv->rkt_init_mutex);
 
   g_main_loop_run (authority->priv->rkt_loop);
 
commit be4c87252e8031c3427ca14ad036981f09fd6369
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu May 24 11:26:34 2012 -0400

    Terminate runaway scripts
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index e822d79..de4bb4a 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -569,6 +569,13 @@ System Context         |                        |
     </para>
 
     <para>
+      If user-provided code takes a long time to execute an exception
+      will be thrown which normally results in the function being
+      terminated (the current limit is 15 seconds). This is used to
+      catch runaway scripts.
+    </para>
+
+    <para>
       The <function>log()</function> method writes the given
       <parameter>message</parameter> to the system logger. Log entries
       are emitted using the <constant>LOG_AUTHPRIV</constant> flag
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 297b7f2..a05d022 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -64,10 +64,20 @@ struct _PolkitBackendJsAuthorityPrivate
   JSObject *js_global;
   JSObject *js_polkit;
 
+  GThread *runaway_killer_thread;
+  GMainContext *rkt_context;
+  GMainLoop *rkt_loop;
+
+  GSource *rkt_source;
+
   /* A list of JSObject instances */
   GList *scripts;
 };
 
+static JSBool execute_script_with_runaway_killer (PolkitBackendJsAuthority *authority,
+                                                  JSObject                 *script,
+                                                  jsval                    *rval);
+
 static void utils_spawn (const gchar *const  *argv,
                          guint                timeout_seconds,
                          GCancellable        *cancellable,
@@ -96,6 +106,8 @@ enum
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static gpointer runaway_killer_thread_func (gpointer user_data);
+
 static GList *polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
                                                                      PolkitSubject                     *caller,
                                                                      PolkitSubject                     *subject,
@@ -271,10 +283,9 @@ load_scripts (PolkitBackendJsAuthority  *authority)
 
       /* evaluate the script */
       jsval rval;
-      if (!JS_ExecuteScript (authority->priv->cx,
-                             authority->priv->js_global,
-                             script,
-                             &rval))
+      if (!execute_script_with_runaway_killer (authority,
+                                               script,
+                                               &rval))
         {
           polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                         "Error executing script %s",
@@ -411,10 +422,12 @@ polkit_backend_js_authority_constructed (GObject *object)
   if (authority->priv->cx == NULL)
     goto fail;
 
+  /* TODO: JIT'ing doesn't work will with killing runaway scripts... I think
+   *       this is just a SpiderMonkey bug. So disable the JIT for now.
+   */
   JS_SetOptions (authority->priv->cx,
-                 JSOPTION_VAROBJFIX |
-                 JSOPTION_JIT |
-                 JSOPTION_METHODJIT);
+                 JSOPTION_VAROBJFIX
+                 /* | JSOPTION_JIT | JSOPTION_METHODJIT*/);
   JS_SetVersion(authority->priv->cx, JSVERSION_LATEST);
   JS_SetErrorReporter(authority->priv->cx, report_error);
   JS_SetContextPrivate (authority->priv->cx, authority);
@@ -428,12 +441,12 @@ polkit_backend_js_authority_constructed (GObject *object)
   if (!JS_InitStandardClasses (authority->priv->cx, authority->priv->js_global))
     goto fail;
 
-  authority->priv->js_polkit = JS_DefineObject(authority->priv->cx,
-                                               authority->priv->js_global,
-                                               "polkit",
-                                               &js_polkit_class,
-                                               NULL,
-                                               JSPROP_ENUMERATE);
+  authority->priv->js_polkit = JS_DefineObject (authority->priv->cx,
+                                                authority->priv->js_global,
+                                                "polkit",
+                                                &js_polkit_class,
+                                                NULL,
+                                                JSPROP_ENUMERATE);
   if (authority->priv->js_polkit == NULL)
     goto fail;
 
@@ -459,6 +472,14 @@ polkit_backend_js_authority_constructed (GObject *object)
       authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
     }
 
+  authority->priv->runaway_killer_thread = g_thread_new ("runaway-killer-thread",
+                                                         runaway_killer_thread_func,
+                                                         authority);
+
+  /* TODO: use a condition variable */
+  while (authority->priv->rkt_loop == NULL)
+    g_thread_yield ();
+
   setup_file_monitors (authority);
   load_scripts (authority);
 
@@ -476,6 +497,12 @@ polkit_backend_js_authority_finalize (GObject *object)
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
   guint n;
 
+  /* shut down the killer thread */
+  g_assert (authority->priv->rkt_loop != NULL);
+  g_main_loop_quit (authority->priv->rkt_loop);
+  g_thread_join (authority->priv->runaway_killer_thread);
+  g_assert (authority->priv->rkt_loop == NULL);
+
   for (n = 0; authority->priv->dir_monitors != NULL && authority->priv->dir_monitors[n] != NULL; n++)
     {
       GFileMonitor *monitor = authority->priv->dir_monitors[n];
@@ -636,6 +663,7 @@ set_property_bool (PolkitBackendJsAuthority  *authority,
   JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
 
 static gboolean
 subject_to_jsval (PolkitBackendJsAuthority  *authority,
@@ -767,6 +795,8 @@ subject_to_jsval (PolkitBackendJsAuthority  *authority,
   return ret;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
 static gboolean
 details_to_jsval (PolkitBackendJsAuthority  *authority,
                   PolkitDetails             *details,
@@ -817,6 +847,128 @@ details_to_jsval (PolkitBackendJsAuthority  *authority,
   return ret;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gpointer
+runaway_killer_thread_func (gpointer user_data)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
+
+  authority->priv->rkt_context = g_main_context_new ();
+  authority->priv->rkt_loop = g_main_loop_new (authority->priv->rkt_context, FALSE);
+
+  g_main_context_push_thread_default (authority->priv->rkt_context);
+
+  /* TODO: signal the main thread that we're done constructing */
+
+  g_main_loop_run (authority->priv->rkt_loop);
+
+  g_main_context_pop_thread_default (authority->priv->rkt_context);
+
+  g_main_loop_unref (authority->priv->rkt_loop);
+  authority->priv->rkt_loop = NULL;
+  g_main_context_unref (authority->priv->rkt_context);
+  authority->priv->rkt_context = NULL;
+
+  return NULL;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static JSBool
+js_operation_callback (JSContext *cx)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx));
+  JSString *val_str;
+  jsval val;
+
+  /* Log that we are terminating the script */
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority), "Terminating runaway script");
+
+  /* Throw an exception - this way the JS code can ignore the runaway script handling */
+  val_str = JS_NewStringCopyZ (cx, "Terminating runaway script");
+  val = STRING_TO_JSVAL (val_str);
+  JS_SetPendingException (authority->priv->cx, val);
+  return JS_FALSE;
+}
+
+static gboolean
+rkt_on_timeout (gpointer user_data)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
+
+  /* Supposedly this is thread-safe... */
+  JS_TriggerOperationCallback (authority->priv->cx);
+
+  /* keep source around so we keep trying to kill even if the JS bit catches the exception
+   * thrown in js_operation_callback()
+   */
+  return TRUE;
+}
+
+static void
+runaway_killer_setup (PolkitBackendJsAuthority *authority)
+{
+  g_assert (authority->priv->rkt_source == NULL);
+
+  /* set-up timer for runaway scripts, will be executed in runaway_killer_thread */
+  authority->priv->rkt_source = g_timeout_source_new_seconds (15);
+  g_source_set_callback (authority->priv->rkt_source, rkt_on_timeout, authority, NULL);
+  g_source_attach (authority->priv->rkt_source, authority->priv->rkt_context);
+
+  /* ... rkt_on_timeout() will then poke the JSContext so js_operation_callback() is
+   * called... and from there we throw an exception
+   */
+  JS_SetOperationCallback (authority->priv->cx, js_operation_callback);
+}
+
+static void
+runaway_killer_teardown (PolkitBackendJsAuthority *authority)
+{
+  JS_SetOperationCallback (authority->priv->cx, NULL);
+  g_source_destroy (authority->priv->rkt_source);
+  g_source_unref (authority->priv->rkt_source);
+  authority->priv->rkt_source = NULL;
+}
+
+static JSBool
+execute_script_with_runaway_killer (PolkitBackendJsAuthority *authority,
+                                    JSObject                 *script,
+                                    jsval                    *rval)
+{
+  JSBool ret;
+
+  runaway_killer_setup (authority);
+  ret = JS_ExecuteScript (authority->priv->cx,
+                          authority->priv->js_global,
+                          script,
+                          rval);
+  runaway_killer_teardown (authority);
+
+  return ret;
+}
+
+static JSBool
+call_js_function_with_runaway_killer (PolkitBackendJsAuthority *authority,
+                                      const char               *function_name,
+                                      uintN                     argc,
+                                      jsval                    *argv,
+                                      jsval                    *rval)
+{
+  JSBool ret;
+  runaway_killer_setup (authority);
+  ret = JS_CallFunctionName(authority->priv->cx,
+                            authority->priv->js_polkit,
+                            function_name,
+                            argc,
+                            argv,
+                            rval);
+  runaway_killer_teardown (authority);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static GList *
 polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
                                                        PolkitSubject                     *caller,
@@ -857,12 +1009,11 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
       goto out;
     }
 
-  if (!JS_CallFunctionName(authority->priv->cx,
-                           authority->priv->js_polkit,
-                           "_runAdminRules",
-                           3,
-                           argv,
-                           &rval))
+  if (!call_js_function_with_runaway_killer (authority,
+                                             "_runAdminRules",
+                                             3,
+                                             argv,
+                                             &rval))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                     "Error evaluating admin rules");
@@ -964,12 +1115,11 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
       goto out;
     }
 
-  if (!JS_CallFunctionName(authority->priv->cx,
-                           authority->priv->js_polkit,
-                           "_runRules",
-                           3,
-                           argv,
-                           &rval))
+  if (!call_js_function_with_runaway_killer (authority,
+                                             "_runRules",
+                                             3,
+                                             argv,
+                                             &rval))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                     "Error evaluating authorization rules");
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 4a35e48..1dba38a 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -134,3 +134,19 @@ polkit.addRule(function(action, subject, details) {
         }
     }
 });
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.run_away_script") {
+        try {
+            // The following code will never terminate so the runaway
+            // script killer will step in after 15 seconds and throw
+            // an exception...
+            while (true)
+                ;
+        } catch (error) {
+            if (error == "Terminating runaway script")
+                return "yes"
+            return "no";
+        }
+    }
+});
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 24e599e..728b433 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -278,6 +278,13 @@ static const RulesTestCase rules_test_cases[] = {
     NULL
   },
   {
+    "runaway_script",
+    "net.company.run_away_script",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
     "spawning_helper_timeout",
     "net.company.spawning.helper_timeout",
     "unix-user:root",
commit d11c872dc2f14fb4b1661740e311087aa188263d
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 17:57:55 2012 -0400

    Use "rules", not "scripts" to refer to files in rules.d
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 39a6376..297b7f2 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -226,7 +226,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
       GDir *dir = NULL;
 
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Loading scripts from directory %s",
+                                    "Loading rules from directory %s",
                                     dir_name);
 
       dir = g_dir_open (dir_name,
@@ -288,7 +288,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
     }
 
   polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                "Finished loading, compiling and executing %d scripts",
+                                "Finished loading, compiling and executing %d rules",
                                 num_scripts);
   g_list_free_full (files, g_free);
 }
@@ -351,7 +351,7 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
            event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
         {
           polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                        "Reloading scripts");
+                                        "Reloading rules");
           reload_scripts (authority);
         }
       g_free (name);
commit 956d4e81d0dbb5182a7070f6367c391d69924270
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 17:44:43 2012 -0400

    Pass expanded identity list to the AuthenticationSession
    
    ... otherwise it things like admin-identities being set to
    ["unix-group:session"] won't work.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index 171e686..86e7134 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -2211,13 +2211,36 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
       identities = g_list_prepend (identities, g_object_ref (user_of_subject));
     }
 
+  /* expand groups/netgroups to users */
+  user_identities = NULL;
+  for (l = identities; l != NULL; l = l->next)
+    {
+      PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
+      if (POLKIT_IS_UNIX_USER (identity))
+        {
+          user_identities = g_list_append (user_identities, g_object_ref (identity));
+        }
+      else if (POLKIT_IS_UNIX_GROUP (identity))
+        {
+          user_identities = g_list_concat (user_identities, get_users_in_group (identity, FALSE));
+        }
+      else if (POLKIT_IS_UNIX_NETGROUP (identity))
+        {
+          user_identities =  g_list_concat (user_identities, get_users_in_net_group (identity, FALSE));
+        }
+      else
+        {
+          g_warning ("Unsupported identity");
+        }
+    }
+
   session = authentication_session_new (agent,
                                         cookie,
                                         subject,
                                         user_of_subject,
                                         caller,
                                         authority,
-                                        identities,
+                                        user_identities,
                                         action_id,
                                         details,
                                         polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
@@ -2236,29 +2259,6 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
   details_gvariant = polkit_details_to_gvariant (localized_details);
   g_variant_ref_sink (details_gvariant);
 
-  /* expand groups/netgroups to users */
-  user_identities = NULL;
-  for (l = identities; l != NULL; l = l->next)
-    {
-      PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
-      if (POLKIT_IS_UNIX_USER (identity))
-        {
-          user_identities = g_list_append (user_identities, g_object_ref (identity));
-        }
-      else if (POLKIT_IS_UNIX_GROUP (identity))
-        {
-          user_identities = g_list_concat (user_identities, get_users_in_group (identity, FALSE));
-        }
-      else if (POLKIT_IS_UNIX_NETGROUP (identity))
-        {
-          user_identities =  g_list_concat (user_identities, get_users_in_net_group (identity, FALSE));
-        }
-      else
-        {
-          g_warning ("Unsupported identity");
-        }
-    }
-
   g_variant_builder_init (&identities_builder, G_VARIANT_TYPE ("a(sa{sv})"));
   for (l = user_identities; l != NULL; l = l->next)
     {
commit 9b06da6b9b630b589affc9d555ba56af96888e9c
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 17:30:51 2012 -0400

    Add default rules
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/50-default.rules b/src/polkitbackend/50-default.rules
new file mode 100644
index 0000000..9d3c33d
--- /dev/null
+++ b/src/polkitbackend/50-default.rules
@@ -0,0 +1,12 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+// DO NOT EDIT THIS FILE, it will be overwritten on update
+//
+// Default rules for polkit
+//
+// See the polkit(8) man page for more information
+// about configuring polkit.
+
+polkit.addAdminRule(function(action, subject, details) {
+    return ["unix-group:wheel"];
+});
diff --git a/src/polkitbackend/50-localauthority.conf b/src/polkitbackend/50-localauthority.conf
deleted file mode 100644
index 5e44bde..0000000
--- a/src/polkitbackend/50-localauthority.conf
+++ /dev/null
@@ -1,10 +0,0 @@
-# Configuration file for the PolicyKit Local Authority.
-#
-# DO NOT EDIT THIS FILE, it will be overwritten on update.
-#
-# See the pklocalauthority(8) man page for more information
-# about configuring the Local Authority.
-#
-
-[Configuration]
-AdminIdentities=unix-group:wheel
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index c5b8d8a..1bafd94 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -62,11 +62,15 @@ libpolkit_backend_1_la_LIBADD =                               		\
 	$(LIBJS_LIBS)							\
         $(NULL)
 
+rulesdir = $(sysconfdir)/polkit-1/rules.d
+rules_DATA = 50-default.rules
+
 CLEANFILES = $(BUILT_SOURCES)
 
 EXTRA_DIST =								\
 	init.js								\
 	toarray.pl							\
+	$(rules_DATA)							\
 	$(NULL)
 
 dist-hook :
commit 6fbcc6cd839680fcefd81c4a43676e7c031c9859
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 17:11:29 2012 -0400

    Store private binaries in /usr/lib/polkit-1 instead of /usr/libexec
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index f75b8d9..961a886 100644
--- a/configure.ac
+++ b/configure.ac
@@ -515,15 +515,7 @@ echo "
 
 "
 
-echo "NOTE: The directory ${sysconfdir}/polkit-1/localauthority must be owned"
-echo "      by root and have mode 700"
-echo
-
-echo "NOTE: The directory ${localstatedir}/lib/polkit-1 must be owned"
-echo "      by root and have mode 700"
-echo
-
-echo "NOTE: The file ${libexecdir}/polkit-agent-helper-1 must be owned"
+echo "NOTE: The file ${prefix}/lib/polkit-1/polkit-agent-helper-1 must be owned"
 echo "      by root and have mode 4755 (setuid root binary)"
 echo
 
diff --git a/data/Makefile.am b/data/Makefile.am
index 83bcc20..6623286 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -2,12 +2,14 @@
 
 NULL =
 
+libprivdir = $(prefix)/lib/polkit-1
+
 servicedir       = $(datadir)/dbus-1/system-services
 service_in_files = org.freedesktop.PolicyKit1.service.in
 service_DATA     = $(service_in_files:.service.in=.service)
 
 $(service_DATA): $(service_in_files) Makefile
-	@sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+	@sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@
 
 dbusconfdir = $(sysconfdir)/dbus-1/system.d
 dbusconf_DATA = org.freedesktop.PolicyKit1.conf
@@ -27,7 +29,7 @@ if HAVE_SYSTEMD
 systemdservicedir       = $(systemdsystemunitdir)
 systemdservice_DATA     = $(systemdservice_in_files:.service.in=.service)
 $(systemdservice_DATA): $(systemdservice_in_files) Makefile
-	@sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+	@sed -e "s|\@libprivdir\@|$(libprivdir)|" $< > $@
 endif
 
 CLEANFILES = $(BUILT_SOURCES)
diff --git a/data/org.freedesktop.PolicyKit1.service.in b/data/org.freedesktop.PolicyKit1.service.in
index fbceb3f..10bbab0 100644
--- a/data/org.freedesktop.PolicyKit1.service.in
+++ b/data/org.freedesktop.PolicyKit1.service.in
@@ -1,5 +1,5 @@
 [D-BUS Service]
 Name=org.freedesktop.PolicyKit1
-Exec=@libexecdir@/polkitd --no-debug
+Exec=@libprivdir@/polkitd --no-debug
 User=root
 SystemdService=polkit.service
diff --git a/data/polkit.service.in b/data/polkit.service.in
index efd2948..9665043 100644
--- a/data/polkit.service.in
+++ b/data/polkit.service.in
@@ -5,4 +5,4 @@ Documentation=man:polkit(8)
 [Service]
 Type=dbus
 BusName=org.freedesktop.PolicyKit1
-ExecStart=@libexecdir@/polkitd --no-debug
+ExecStart=@libprivdir@/polkitd --no-debug
diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am
index e8c9fb1..1cfb73c 100644
--- a/src/polkitagent/Makefile.am
+++ b/src/polkitagent/Makefile.am
@@ -5,6 +5,7 @@ INCLUDES =                                                      \
         -I$(top_srcdir)/src                                     \
         -I$(top_builddir)/src/polkit                            \
         -I$(top_srcdir)/src/polkit                              \
+        -DPACKAGE_PREFIX=\""$(prefix)"\"                    	\
         -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\"               \
         -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"               \
         -DPACKAGE_DATA_DIR=\""$(datadir)"\"                     \
@@ -77,7 +78,8 @@ libpolkit_agent_1_la_LIBADD =                               		\
 
 libpolkit_agent_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
 
-libexec_PROGRAMS = polkit-agent-helper-1
+libprivdir = $(prefix)/lib/polkit-1
+libpriv_PROGRAMS = polkit-agent-helper-1
 
 polkit_agent_helper_1_SOURCES = 					\
 	polkitagenthelperprivate.c polkitagenthelperprivate.h		\
@@ -132,9 +134,9 @@ endif # HAVE_INTROSPECTION
 # authenticate not only the invoking user, but possibly also root
 # and/or other users.
 #
-install-exec-hook:
-	-chown root $(DESTDIR)$(libexecdir)/polkit-agent-helper-1
-	-chmod 4755 $(DESTDIR)$(libexecdir)/polkit-agent-helper-1
+install-data-hook:
+	-chown root $(DESTDIR)$(libprivdir)/polkit-agent-helper-1
+	-chmod 4755 $(DESTDIR)$(libprivdir)/polkit-agent-helper-1
 
 EXTRA_DIST = polkitagentmarshal.list polkitagentenumtypes.h.template polkitagentenumtypes.c.template
 
diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
index 8129cd9..1c7a2dc 100644
--- a/src/polkitagent/polkitagentsession.c
+++ b/src/polkitagent/polkitagentsession.c
@@ -620,7 +620,7 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
       goto error;
     }
 
-  helper_argv[0] = PACKAGE_LIBEXEC_DIR "/polkit-agent-helper-1";
+  helper_argv[0] = PACKAGE_PREFIX "/lib/polkit-1/polkit-agent-helper-1";
   helper_argv[1] = passwd->pw_name;
   helper_argv[2] = session->cookie;
   helper_argv[3] = NULL;
diff --git a/src/polkitd/Makefile.am b/src/polkitd/Makefile.am
index 5ea3e95..584b795 100644
--- a/src/polkitd/Makefile.am
+++ b/src/polkitd/Makefile.am
@@ -14,7 +14,8 @@ INCLUDES =                                              		\
 	-D_REENTRANT	                                		\
 	$(NULL)
 
-libexec_PROGRAMS = polkitd
+libprivdir = $(prefix)/lib/polkit-1
+libpriv_PROGRAMS = polkitd
 
 polkitd_SOURCES = 							\
 					main.c				\
commit 56293fa41d4f04d5261056491451f4cb80b16e11
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 16:49:20 2012 -0400

    Mention systemd(1) in the polkitd(8) man page
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 243539f..879da2d 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -35,8 +35,14 @@
       should never need to start this daemon as it will be
       automatically started by
       <citerefentry><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      whenever an application calls into the service. See the
-      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      or
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+      whenever an application calls into the service.
+    </para>
+
+    <para>
+      See the <link
+      linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
       man page for more information.
 
     </para>
@@ -66,7 +72,9 @@
       <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
-      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <citerefentry><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
     </para>
   </refsect1>
 </refentry>
commit 0f830c76048229895164837f8ce01869d88a2616
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 16:39:25 2012 -0400

    Nuke polkitbackend library, localauthority backend and extension system
    
    Any backend can now be implemented in JavaScript (if so desired) so we
    don't need any of this any more.
    
    Note that the libpolkitbackend library was never declared stable (the
    preprocessor symbol POLKIT_BACKEND_I_KNOW_API_IS_SUBJECT_TO_CHANGE had
    to be defined) so removing it is not an API/ABI break.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index 7c7ca7a..f75b8d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -461,7 +461,6 @@ src/polkitagent/Makefile
 src/polkitd/Makefile
 src/programs/Makefile
 src/examples/Makefile
-src/nullbackend/Makefile
 docs/version.xml
 docs/extensiondir.xml
 docs/Makefile
diff --git a/docs/polkit/Makefile.am b/docs/polkit/Makefile.am
index 72d2fb8..a9bac88 100644
--- a/docs/polkit/Makefile.am
+++ b/docs/polkit/Makefile.am
@@ -31,8 +31,6 @@ INCLUDES = \
 	$(GIO_CFLAGS)						\
 	-I$(top_srcdir)/src/polkit 				\
 	-I$(top_builddir)/src/polkit				\
-	-I$(top_srcdir)/src/polkitbackend			\
-	-I$(top_builddir)/src/polkitbackend			\
 	-I$(top_srcdir)/src/polkitagent 			\
 	-I$(top_builddir)/src/polkitagent			\
 	$(NULL)
@@ -42,7 +40,6 @@ GTKDOC_LIBS = \
 	$(GLIB_LIBS)						\
 	$(GIO_LIBS)						\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la	\
-	$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la \
 	$(top_builddir)/src/polkitagent/libpolkit-agent-1.la	\
 	$(NULL)
 
diff --git a/docs/polkit/overview.xml b/docs/polkit/overview.xml
index 24440d2..9f5a1a9 100644
--- a/docs/polkit/overview.xml
+++ b/docs/polkit/overview.xml
@@ -90,37 +90,4 @@
     </para>
   </chapter>
 
-  <chapter id="polkit-extending">
-    <title>Extending polkit</title>
-    <para>
-      polkit exports a number of extension points to
-      replace/customize behavior of the polkit daemon. Note that
-      all extensions run with super user privileges in the same
-      process as the polkit daemon.
-    </para>
-    <para>
-      The polkit daemons loads extensions
-      from the <filename>&extensiondir;</filename> directory. See
-      the <link linkend="gio-Extension-Points">GIO Extension Point
-        documentation</link> for more information about the extension
-      system used by polkit.
-    </para>
-    <para>
-      The following extension points are currently defined by
-      polkit:
-    </para>
-
-    <formalpara>
-      <title>POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME</title>
-      <para>
-        Allows replacing the Authority – the entity responsible for
-        making authorization decisions. Implementations of this
-        extension point must be derived from the
-        PolkitBackendAuthority class. See
-        the <filename>src/nullbackend/</filename> directory in the
-        polkit sources for an example.
-      </para>
-    </formalpara>
-
-  </chapter>
 </part>
diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml
index 84158ef..549768c 100644
--- a/docs/polkit/polkit-1-docs.xml
+++ b/docs/polkit/polkit-1-docs.xml
@@ -23,7 +23,7 @@
   </part>
 
   <part id="ref-api">
-    <title>Client API Reference</title>
+    <title>Library API Reference</title>
     <xi:include href="xml/polkitauthority.xml"/>
     <xi:include href="xml/polkitauthorizationresult.xml"/>
     <xi:include href="xml/polkitdetails.xml"/>
@@ -47,13 +47,6 @@
     </chapter>
   </part>
 
-  <part id="ref-backend-api">
-    <title>Backend API Reference</title>
-    <xi:include href="xml/polkitbackendauthority.xml"/>
-    <xi:include href="xml/polkitbackendinteractiveauthority.xml"/>
-    <xi:include href="xml/polkitbackendlocalauthority.xml"/>
-  </part>
-
   <part id="ref-authentication-agent-api">
     <title>Authentication Agent API Reference</title>
     <xi:include href="xml/polkitagentlistener.xml"/>
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index 3881004..41b37e3 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -291,86 +291,6 @@ POLKIT_DETAILS_GET_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>polkitbackendauthority</FILE>
-<TITLE>PolkitBackendAuthority</TITLE>
-POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME
-PolkitBackendAuthority
-PolkitBackendAuthorityClass
-polkit_backend_authority_get_name
-polkit_backend_authority_get_version
-polkit_backend_authority_get_features
-polkit_backend_authority_check_authorization
-polkit_backend_authority_check_authorization_finish
-polkit_backend_authority_register_authentication_agent
-polkit_backend_authority_unregister_authentication_agent
-polkit_backend_authority_authentication_agent_response
-polkit_backend_authority_enumerate_actions
-polkit_backend_authority_enumerate_temporary_authorizations
-polkit_backend_authority_revoke_temporary_authorizations
-polkit_backend_authority_revoke_temporary_authorization_by_id
-polkit_backend_authority_get
-polkit_backend_authority_register
-polkit_backend_authority_unregister
-<SUBSECTION Standard>
-POLKIT_BACKEND_AUTHORITY
-POLKIT_BACKEND_IS_AUTHORITY
-POLKIT_BACKEND_TYPE_AUTHORITY
-polkit_backend_authority_get_type
-POLKIT_BACKEND_AUTHORITY_CLASS
-POLKIT_BACKEND_IS_AUTHORITY_CLASS
-POLKIT_BACKEND_AUTHORITY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>polkitbackendactionlookup</FILE>
-<TITLE>PolkitBackendActionLookup</TITLE>
-POLKIT_BACKEND_ACTION_LOOKUP_EXTENSION_POINT_NAME
-PolkitBackendActionLookup
-PolkitBackendActionLookupIface
-polkit_backend_action_lookup_get_message
-polkit_backend_action_lookup_get_icon_name
-polkit_backend_action_lookup_get_details
-<SUBSECTION Standard>
-POLKIT_BACKEND_ACTION_LOOKUP
-POLKIT_BACKEND_IS_ACTION_LOOKUP
-POLKIT_BACKEND_TYPE_ACTION_LOOKUP
-polkit_backend_action_lookup_get_type
-POLKIT_BACKEND_ACTION_LOOKUP_GET_IFACE
-</SECTION>
-
-<SECTION>
-<FILE>polkitbackendlocalauthority</FILE>
-<TITLE>PolkitBackendLocalAuthority</TITLE>
-PolkitBackendLocalAuthority
-PolkitBackendLocalAuthorityClass
-<SUBSECTION Standard>
-POLKIT_BACKEND_LOCAL_AUTHORITY
-POLKIT_BACKEND_IS_LOCAL_AUTHORITY
-POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY
-polkit_backend_local_authority_get_type
-POLKIT_BACKEND_LOCAL_AUTHORITY_CLASS
-POLKIT_BACKEND_IS_LOCAL_AUTHORITY_CLASS
-POLKIT_BACKEND_LOCAL_AUTHORITY_GET_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>polkitbackendinteractiveauthority</FILE>
-<TITLE>PolkitBackendInteractiveAuthority</TITLE>
-PolkitBackendInteractiveAuthority
-PolkitBackendInteractiveAuthorityClass
-polkit_backend_interactive_authority_get_admin_identities
-polkit_backend_interactive_authority_check_authorization_sync
-<SUBSECTION Standard>
-POLKIT_BACKEND_INTERACTIVE_AUTHORITY
-POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY
-POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY
-polkit_backend_interactive_authority_get_type
-POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS
-POLKIT_BACKEND_IS_INTERACTIVE_AUTHORITY_CLASS
-POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>polkitagentsession</FILE>
 <TITLE>PolkitAgentSession</TITLE>
 PolkitAgentSession
diff --git a/docs/polkit/polkit-1.types b/docs/polkit/polkit-1.types
index b1e13cc..6354d12 100644
--- a/docs/polkit/polkit-1.types
+++ b/docs/polkit/polkit-1.types
@@ -16,15 +16,6 @@ polkit_authorization_result_get_type
 polkit_temporary_authorization_get_type
 polkit_permission_get_type
 
-polkit_backend_authority_get_type
-polkit_backend_interactive_authority_get_type
-polkit_backend_local_authority_get_type
-polkit_backend_action_lookup_get_type
-polkit_backend_action_pool_get_type
-polkit_backend_session_monitor_get_type
-polkit_backend_config_source_get_type
-polkit_backend_local_authorization_store_get_type
-
 polkit_agent_session_get_type
 polkit_agent_listener_get_type
 polkit_agent_text_listener_get_type
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 02f8255..6e76bdd 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,5 +3,4 @@
 [encoding: UTF-8]
 actions/org.freedesktop.policykit.policy.in
 src/examples/org.freedesktop.policykit.examples.pkexec.policy.in
-src/polkitbackend/polkitbackendlocalauthority.c
 src/programs/pkexec.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 28c7bfa..3380fb2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,5 +1,5 @@
 
-SUBDIRS = polkit polkitbackend polkitagent polkitd nullbackend programs
+SUBDIRS = polkit polkitbackend polkitagent polkitd programs
 
 if BUILD_EXAMPLES
 SUBDIRS += examples
diff --git a/src/nullbackend/50-nullbackend.conf b/src/nullbackend/50-nullbackend.conf
deleted file mode 100644
index 3497677..0000000
--- a/src/nullbackend/50-nullbackend.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Configuration file for the PolicyKit null backend.
-#
-# DO NOT EDIT THIS FILE, it will be overwritten on update.
-#
-# To change configuration, create another file in this directory with
-# a filename that is sorted after the 50-nullback.conf and make
-# sure it has the .conf extension.
-#
-# Only a single configuration item, Priority, is supported.
-#
-# See the PolicyKit documentation for more information about PolicyKit.
-#
-
-[Configuration]
-Priority=-10
diff --git a/src/nullbackend/Makefile.am b/src/nullbackend/Makefile.am
deleted file mode 100644
index c683818..0000000
--- a/src/nullbackend/Makefile.am
+++ /dev/null
@@ -1,50 +0,0 @@
-
-NULL =
-
-module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
-
-INCLUDES =                                              	\
-	-I$(top_builddir)/src                           	\
-	-I$(top_srcdir)/src                             	\
-	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\"       	\
-	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\"       	\
-	-DPACKAGE_DATA_DIR=\""$(datadir)"\"             	\
-	-DPACKAGE_BIN_DIR=\""$(bindir)"\"               	\
-	-DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" 	\
-	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\"         	\
-	-DPACKAGE_LIB_DIR=\""$(libdir)"\"               	\
-	-D_POSIX_PTHREAD_SEMANTICS                      	\
-	-D_REENTRANT	                                	\
-	-D_POLKIT_BACKEND_COMPILATION				\
-	$(NULL)
-
-polkitmodulesdir = $(libdir)/polkit-1/extensions
-polkitmodules_LTLIBRARIES = libnullbackend.la
-
-libnullbackend_la_SOURCES = 						\
-	nullbackend.c							\
-	polkitbackendnullauthority.c	polkitbackendnullauthority.h	\
-	$(NULL)
-
-libnullbackend_la_CFLAGS =                             			\
-	-DPOLKIT_BACKEND_I_KNOW_API_IS_SUBJECT_TO_CHANGE		\
-	-DG_LOG_DOMAIN=\"PolkitNullBackend\"				\
-	$(GLIB_CFLAGS)							\
-	$(NULL)
-
-libnullbackend_la_LDFLAGS =  	                      			\
-	$(module_flags)               					\
-	$(GLIB_LIBS)							\
-	$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la	\
-	$(NULL)
-
-libnullbackend_la_LIBADD =  	                      			\
-	$(NULL)
-
-nullconfigdir = $(sysconfdir)/polkit-1/nullbackend.conf.d
-nullconfig_DATA = 50-nullbackend.conf
-
-EXTRA_DIST = $(nullconfig_DATA)
-
-clean-local :
-	rm -f *~
diff --git a/src/nullbackend/nullbackend.c b/src/nullbackend/nullbackend.c
deleted file mode 100644
index 0436cf0..0000000
--- a/src/nullbackend/nullbackend.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "polkitbackendnullauthority.h"
-
-void
-g_io_module_load (GIOModule *module)
-{
-  polkit_backend_null_authority_register (module);
-}
-
-void
-g_io_module_unload (GIOModule *module)
-{
-}
-
diff --git a/src/nullbackend/polkitbackendnullauthority.c b/src/nullbackend/polkitbackendnullauthority.c
deleted file mode 100644
index 7491540..0000000
--- a/src/nullbackend/polkitbackendnullauthority.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "config.h"
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <string.h>
-#include <glib/gstdio.h>
-
-#include "polkitbackend/polkitbackendconfigsource.h"
-#include "polkitbackendnullauthority.h"
-
-struct _PolkitBackendNullAuthorityPrivate
-{
-  gint foo;
-};
-
-static GList *authority_enumerate_actions  (PolkitBackendAuthority   *authority,
-                                            PolkitSubject            *caller,
-                                            const gchar              *locale,
-                                            GError                  **error);
-
-static void authority_check_authorization (PolkitBackendAuthority        *authority,
-                                           PolkitSubject                 *caller,
-                                           PolkitSubject                 *subject,
-                                           const gchar                   *action_id,
-                                           PolkitDetails                 *details,
-                                           PolkitCheckAuthorizationFlags  flags,
-                                           GCancellable                  *cancellable,
-                                           GAsyncReadyCallback            callback,
-                                           gpointer                       user_data);
-
-static PolkitAuthorizationResult *authority_check_authorization_finish (PolkitBackendAuthority  *authority,
-                                                                        GAsyncResult            *res,
-                                                                        GError                 **error);
-
-G_DEFINE_DYNAMIC_TYPE (PolkitBackendNullAuthority, polkit_backend_null_authority,POLKIT_BACKEND_TYPE_AUTHORITY);
-
-static void
-polkit_backend_null_authority_init (PolkitBackendNullAuthority *authority)
-{
-  authority->priv = G_TYPE_INSTANCE_GET_PRIVATE (authority,
-                                                 POLKIT_BACKEND_TYPE_NULL_AUTHORITY,
-                                                 PolkitBackendNullAuthorityPrivate);
-}
-
-static void
-polkit_backend_null_authority_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (polkit_backend_null_authority_parent_class)->finalize (object);
-}
-
-static const gchar *
-authority_get_name (PolkitBackendAuthority *authority)
-{
-  return "null";
-}
-
-static const gchar *
-authority_get_version (PolkitBackendAuthority *authority)
-{
-  return PACKAGE_VERSION;
-}
-
-static PolkitAuthorityFeatures
-authority_get_features (PolkitBackendAuthority *authority)
-{
-  return POLKIT_AUTHORITY_FEATURES_NONE;
-}
-
-static void
-polkit_backend_null_authority_class_init (PolkitBackendNullAuthorityClass *klass)
-{
-  GObjectClass *gobject_class;
-  PolkitBackendAuthorityClass *authority_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
-
-  gobject_class->finalize = polkit_backend_null_authority_finalize;
-
-  authority_class->get_name                        = authority_get_name;
-  authority_class->get_version                     = authority_get_version;
-  authority_class->get_features                    = authority_get_features;
-  authority_class->enumerate_actions               = authority_enumerate_actions;
-  authority_class->check_authorization             = authority_check_authorization;
-  authority_class->check_authorization_finish      = authority_check_authorization_finish;
-
-  g_type_class_add_private (klass, sizeof (PolkitBackendNullAuthorityPrivate));
-}
-
-static void
-polkit_backend_null_authority_class_finalize (PolkitBackendNullAuthorityClass *klass)
-{
-}
-
-void
-polkit_backend_null_authority_register (GIOModule *module)
-{
-  gint priority;
-  GFile *directory;
-  PolkitBackendConfigSource *source;
-
-  directory = g_file_new_for_path (PACKAGE_SYSCONF_DIR "/polkit-1/nullbackend.conf.d");
-  source = polkit_backend_config_source_new (directory);
-
-  priority = polkit_backend_config_source_get_integer (source, "Configuration", "Priority", NULL);
-
-  polkit_backend_null_authority_register_type (G_TYPE_MODULE (module));
-
-  g_print ("Registering null backend at priority %d\n", priority);
-
-  g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
-                                  POLKIT_BACKEND_TYPE_NULL_AUTHORITY,
-                                  "null backend " PACKAGE_VERSION,
-                                  priority);
-
-  g_object_unref (directory);
-  g_object_unref (source);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *
-authority_enumerate_actions  (PolkitBackendAuthority   *authority,
-                              PolkitSubject            *caller,
-                              const gchar              *locale,
-                              GError                  **error)
-{
-  /* We don't know any actions */
-  return NULL;
-}
-
-static void
-authority_check_authorization (PolkitBackendAuthority        *authority,
-                               PolkitSubject                 *caller,
-                               PolkitSubject                 *subject,
-                               const gchar                   *action_id,
-                               PolkitDetails                 *details,
-                               PolkitCheckAuthorizationFlags  flags,
-                               GCancellable                  *cancellable,
-                               GAsyncReadyCallback            callback,
-                               gpointer                       user_data)
-{
-  GSimpleAsyncResult *simple;
-
-  /* complete immediately */
-  simple = g_simple_async_result_new (G_OBJECT (authority),
-                                      callback,
-                                      user_data,
-                                      authority_check_authorization);
-  g_simple_async_result_complete (simple);
-  g_object_unref (simple);
-}
-
-static PolkitAuthorizationResult *
-authority_check_authorization_finish (PolkitBackendAuthority  *authority,
-                                      GAsyncResult            *res,
-                                      GError                 **error)
-{
-  GSimpleAsyncResult *simple;
-  PolkitAuthorizationResult *result;
-
-  simple = G_SIMPLE_ASYNC_RESULT (res);
-
-  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == authority_check_authorization);
-
-  /* we always return NOT_AUTHORIZED, never an error */
-  result = polkit_authorization_result_new (FALSE, FALSE, NULL);
-
-  if (g_simple_async_result_propagate_error (simple, error))
-    goto out;
-
- out:
-  return result;
-}
diff --git a/src/nullbackend/polkitbackendnullauthority.h b/src/nullbackend/polkitbackendnullauthority.h
deleted file mode 100644
index 318e482..0000000
--- a/src/nullbackend/polkitbackendnullauthority.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#ifndef __POLKIT_BACKEND_NULL_AUTHORITY_H
-#define __POLKIT_BACKEND_NULL_AUTHORITY_H
-
-#include <polkitbackend/polkitbackend.h>
-
-G_BEGIN_DECLS
-
-#define POLKIT_BACKEND_TYPE_NULL_AUTHORITY         (polkit_backend_null_authority_get_type ())
-#define POLKIT_BACKEND_NULL_AUTHORITY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY, PolkitBackendNullAuthority))
-#define POLKIT_BACKEND_NULL_AUTHORITY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_NULL_AUTHORITY, PolkitBackendNullAuthorityClass))
-#define POLKIT_BACKEND_NULL_AUTHORITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY,PolkitBackendNullAuthorityClass))
-#define POLKIT_BACKEND_IS_NULL_AUTHORITY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY))
-#define POLKIT_BACKEND_IS_NULL_AUTHORITY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_NULL_AUTHORITY))
-
-typedef struct _PolkitBackendNullAuthority PolkitBackendNullAuthority;
-typedef struct _PolkitBackendNullAuthorityClass PolkitBackendNullAuthorityClass;
-typedef struct _PolkitBackendNullAuthorityPrivate PolkitBackendNullAuthorityPrivate;
-
-struct _PolkitBackendNullAuthority
-{
-  PolkitBackendAuthority parent_instance;
-  PolkitBackendNullAuthorityPrivate *priv;
-};
-
-struct _PolkitBackendNullAuthorityClass
-{
-  PolkitBackendAuthorityClass parent_class;
-
-};
-
-GType  polkit_backend_null_authority_get_type (void) G_GNUC_CONST;
-
-void   polkit_backend_null_authority_register (GIOModule *module);
-
-G_END_DECLS
-
-#endif /* __POLKIT_BACKEND_NULL_AUTHORITY_H */
-
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 17d8310..c5b8d8a 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -18,25 +18,13 @@ INCLUDES =                                                      \
         -D_REENTRANT                                            \
         $(NULL)
 
-lib_LTLIBRARIES=libpolkit-backend-1.la
-
-libpolkit_backend_1includedir=$(includedir)/polkit-1/polkitbackend
-
+noinst_LTLIBRARIES=libpolkit-backend-1.la
 
 initjs.h : init.js
 	$(PERL) $(srcdir)/toarray.pl $(srcdir)/init.js init_js > $@
 
 BUILT_SOURCES += initjs.h
 
-libpolkit_backend_1include_HEADERS =                        		\
-	polkitbackend.h							\
-	polkitbackendtypes.h						\
-	polkitbackendauthority.h					\
-	polkitbackendinteractiveauthority.h				\
-	polkitbackendlocalauthority.h					\
-	polkitbackendactionlookup.h					\
-        $(NULL)
-
 libpolkit_backend_1_la_SOURCES =                                   			\
 	$(BUILT_SOURCES)								\
         polkitbackend.h									\
@@ -44,12 +32,10 @@ libpolkit_backend_1_la_SOURCES =                                   			\
 	polkitbackendprivate.h								\
 	polkitbackendauthority.h		polkitbackendauthority.c		\
 	polkitbackendinteractiveauthority.h	polkitbackendinteractiveauthority.c	\
-	polkitbackendlocalauthority.h		polkitbackendlocalauthority.c		\
 	polkitbackendjsauthority.h		polkitbackendjsauthority.c		\
 	polkitbackendactionpool.h		polkitbackendactionpool.c		\
 	polkitbackendconfigsource.h		polkitbackendconfigsource.c		\
 	polkitbackendactionlookup.h		polkitbackendactionlookup.c		\
-	polkitbackendlocalauthorizationstore.h	polkitbackendlocalauthorizationstore.c	\
         $(NULL)
 
 if HAVE_LIBSYSTEMD_LOGIN
@@ -76,15 +62,9 @@ libpolkit_backend_1_la_LIBADD =                               		\
 	$(LIBJS_LIBS)							\
         $(NULL)
 
-libpolkit_backend_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
-
 CLEANFILES = $(BUILT_SOURCES)
 
-localauthorityconfigdir = $(sysconfdir)/polkit-1/localauthority.conf.d
-localauthorityconfig_DATA = 50-localauthority.conf
-
 EXTRA_DIST =								\
-	$(localauthorityconfig_DATA)					\
 	init.js								\
 	toarray.pl							\
 	$(NULL)
@@ -96,13 +76,6 @@ clean-local :
 	rm -f *~ $(BUILT_SOURCES)
 
 install-exec-hook:
-	mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1
-	mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1/localauthority/{10-vendor.d,20-org.d,30-site.d,50-local.d,90-mandatory.d}
-	-chmod 700 $(DESTDIR)$(localstatedir)/lib/polkit-1
-	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1
-	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/localauthority/{10-vendor.d,20-org.d,30-site.d,50-local.d,90-mandatory.d}
-	-chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/localauthority
-	mkdir -p $(DESTDIR)$(libdir)/polkit-1/extensions
 	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
 	-chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
 	mkdir -p $(DESTDIR)$(datadir)/polkit-1/rules.d
diff --git a/src/polkitbackend/polkitbackend.h b/src/polkitbackend/polkitbackend.h
index 9b79d14..afa4be3 100644
--- a/src/polkitbackend/polkitbackend.h
+++ b/src/polkitbackend/polkitbackend.h
@@ -32,7 +32,6 @@
 #include <polkitbackend/polkitbackendtypes.h>
 #include <polkitbackend/polkitbackendauthority.h>
 #include <polkitbackend/polkitbackendinteractiveauthority.h>
-#include <polkitbackend/polkitbackendlocalauthority.h>
 #include <polkitbackend/polkitbackendactionlookup.h>
 #undef _POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H
 
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index e127247..91ece26 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -30,7 +30,6 @@
 #include <polkit/polkitprivate.h>
 
 #include "polkitbackendauthority.h"
-#include "polkitbackendlocalauthority.h"
 #include "polkitbackendjsauthority.h"
 
 #include "polkitbackendprivate.h"
@@ -40,7 +39,7 @@
  * @title: PolkitBackendAuthority
  * @short_description: Abstract base class for authority backends
  * @stability: Unstable
- * @see_also: PolkitBackendLocalAuthority
+ * @see_also: PolkitBackendJsAuthority
  *
  * To implement an authority backend, simply subclass #PolkitBackendAuthority
  * and implement the required VFuncs.
@@ -57,7 +56,7 @@ static guint signals[LAST_SIGNAL] = {0};
 G_DEFINE_ABSTRACT_TYPE (PolkitBackendAuthority, polkit_backend_authority, G_TYPE_OBJECT);
 
 static void
-polkit_backend_authority_init (PolkitBackendAuthority *local_authority)
+polkit_backend_authority_init (PolkitBackendAuthority *authority)
 {
 }
 
@@ -1349,71 +1348,30 @@ polkit_backend_authority_register (PolkitBackendAuthority   *authority,
 /**
  * polkit_backend_authority_get:
  *
- * Loads all #GIOModule<!-- -->s from <filename>$(libdir)/polkit-1/extensions</filename> to determine
- * what implementation of #PolkitBackendAuthority to use. Then instantiates an object of the
- * implementation with the highest priority and unloads all other modules.
+ * Gets the #PolkitBackendAuthority to use.
  *
  * Returns: A #PolkitBackendAuthority. Free with g_object_unref().
- **/
+ */
 PolkitBackendAuthority *
 polkit_backend_authority_get (void)
 {
-  static GIOExtensionPoint *ep = NULL;
-  static volatile GType local_authority_type = G_TYPE_INVALID;
-  static volatile GType js_authority_type = G_TYPE_INVALID;
-  GList *modules;
-  GList *authority_implementations;
-  GType authority_type;
   PolkitBackendAuthority *authority;
-  gchar *s;
-
-  /* define extension points */
-  if (ep == NULL)
-    {
-      ep = g_io_extension_point_register (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME);
-      g_io_extension_point_set_required_type (ep, POLKIT_BACKEND_TYPE_AUTHORITY);
-    }
-
-  /* make sure local types are registered */
-  if (local_authority_type == G_TYPE_INVALID)
-    local_authority_type = POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY;
-  if (js_authority_type == G_TYPE_INVALID)
-    js_authority_type = POLKIT_BACKEND_TYPE_JS_AUTHORITY;
-
-  /* load all modules */
-  modules = g_io_modules_load_all_in_directory (PACKAGE_LIB_DIR "/polkit-1/extensions");
 
-  /* find all extensions; we have at least one here since we've registered the local backend */
-  authority_implementations = g_io_extension_point_get_extensions (ep);
+  /* TODO: move to polkitd/main.c */
 
-  /* the returned list is sorted according to priority so just take the highest one */
-  authority_type = g_io_extension_get_type ((GIOExtension*) authority_implementations->data);
-  authority = POLKIT_BACKEND_AUTHORITY (g_object_new (authority_type, NULL));
-
-  /* unload all modules; the module our instantiated authority is in won't be unloaded because
-   * we've instantiated a reference to a type in this module
-   */
-  g_list_foreach (modules, (GFunc) g_type_module_unuse, NULL);
-  g_list_free (modules);
-
-  /* First announce that we've started in the generic log */
+  /* Announce that we've started in the generic log */
   openlog ("polkitd",
            LOG_PID,
            LOG_DAEMON);  /* system daemons without separate facility value */
-  syslog (LOG_INFO,
-          "started daemon version %s using authority implementation `%s' version `%s'",
-          VERSION,
-          polkit_backend_authority_get_name (authority),
-          polkit_backend_authority_get_version (authority));
+  syslog (LOG_INFO, "Started polkitd version %s", VERSION);
   closelog ();
 
-  /* and then log to the secure log */
-  s = g_strdup_printf ("polkitd(authority=%s)", polkit_backend_authority_get_name (authority));
-  openlog (s,
-           0,
+  /* then start logging to the secure log */
+  openlog ("polkitd",
+           LOG_PID,
            LOG_AUTHPRIV); /* security/authorization messages (private) */
-  /* Ugh, can't free the string - gah, thanks openlog(3) */
-  /*g_free (s);*/
+
+  authority = POLKIT_BACKEND_AUTHORITY (g_object_new (POLKIT_BACKEND_TYPE_JS_AUTHORITY, NULL));
 
   return authority;
 }
diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h
index a564054..f9f7385 100644
--- a/src/polkitbackend/polkitbackendauthority.h
+++ b/src/polkitbackend/polkitbackendauthority.h
@@ -43,13 +43,6 @@ G_BEGIN_DECLS
 typedef struct _PolkitBackendAuthorityClass    PolkitBackendAuthorityClass;
 
 /**
- * POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME:
- *
- * Extension point name for authority backend implementations.
- */
-#define POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME "polkit-backend-authority-1"
-
-/**
  * PolkitBackendAuthority:
  *
  * The #PolkitBackendAuthority struct should not be accessed directly.
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index a7bf50b..39a6376 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -114,13 +114,7 @@ static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorizati
                                                           PolkitDetails                     *details,
                                                           PolkitImplicitAuthorization        implicit);
 
-G_DEFINE_TYPE_WITH_CODE (PolkitBackendJsAuthority,
-                         polkit_backend_js_authority,
-                         POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY,
-                         g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
-                                                         g_define_type_id,
-                                                         "js-authority" PACKAGE_VERSION,
-                                                         10));
+G_DEFINE_TYPE (PolkitBackendJsAuthority, polkit_backend_js_authority, POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY);
 
 /* ---------------------------------------------------------------------------------------------------- */
 
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
deleted file mode 100644
index 2e5e8fe..0000000
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "config.h"
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <netdb.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <locale.h>
-#include <glib/gi18n-lib.h>
-
-#include <polkit/polkit.h>
-#include "polkitbackendconfigsource.h"
-#include "polkitbackendlocalauthority.h"
-#include "polkitbackendlocalauthorizationstore.h"
-
-#include <polkit/polkitprivate.h>
-
-/**
- * SECTION:polkitbackendlocalauthority
- * @title: PolkitBackendLocalAuthority
- * @short_description: Local Authority
- * @stability: Unstable
- *
- * An implementation of #PolkitBackendAuthority that stores
- * authorizations on the local file system, supports interaction with
- * authentication agents (virtue of being based on
- * #PolkitBackendInteractiveAuthority).
- */
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *get_users_in_group (PolkitIdentity              *group,
-                                  gboolean                     include_root);
-
-static GList *get_users_in_net_group (PolkitIdentity          *group,
-                                      gboolean                 include_root);
-
-static GList *get_groups_for_user (PolkitIdentity              *user);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
-  gchar *config_path;
-  PolkitBackendConfigSource *config_source;
-
-  gchar **authorization_store_paths;
-  GList *authorization_stores;
-  GList *authorization_store_monitors;
-
-} PolkitBackendLocalAuthorityPrivate;
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-enum
-{
-  PROP_0,
-
-  // Path overrides used for unit testing
-  PROP_CONFIG_PATH,
-  PROP_AUTH_STORE_PATHS,
-};
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *polkit_backend_local_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
-                                                                        PolkitSubject                     *caller,
-                                                                        PolkitSubject                     *subject,
-                                                                        PolkitIdentity                    *user_for_subject,
-                                                                        const gchar                       *action_id,
-                                                                        PolkitDetails                     *details);
-
-static PolkitImplicitAuthorization polkit_backend_local_authority_check_authorization_sync (
-                                                          PolkitBackendInteractiveAuthority *authority,
-                                                          PolkitSubject                     *caller,
-                                                          PolkitSubject                     *subject,
-                                                          PolkitIdentity                    *user_for_subject,
-                                                          gboolean                           subject_is_local,
-                                                          gboolean                           subject_is_active,
-                                                          const gchar                       *action_id,
-                                                          PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit);
-
-G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority,
-                         polkit_backend_local_authority,
-                         POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY,
-                         g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
-                                                         g_define_type_id,
-                                                         "local-authority" PACKAGE_VERSION,
-                                                         0));
-
-#define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityPrivate))
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-on_store_changed (PolkitBackendLocalAuthorizationStore *store,
-                  gpointer                              user_data)
-{
-  PolkitBackendLocalAuthority *authority = POLKIT_BACKEND_LOCAL_AUTHORITY (user_data);
-
-  g_signal_emit_by_name (authority, "changed");
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-purge_all_authorization_stores (PolkitBackendLocalAuthority *authority)
-{
-  PolkitBackendLocalAuthorityPrivate *priv;
-  GList *l;
-
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
-  for (l = priv->authorization_stores; l != NULL; l = l->next)
-    {
-      PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
-      g_signal_handlers_disconnect_by_func (store,
-                                            G_CALLBACK (on_store_changed),
-                                            authority);
-      g_object_unref (store);
-    }
-  g_list_free (priv->authorization_stores);
-  priv->authorization_stores = NULL;
-
-  g_debug ("Purged all local authorization stores");
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-add_one_authorization_store (PolkitBackendLocalAuthority *authority,
-                             GFile                       *directory)
-{
-  PolkitBackendLocalAuthorizationStore *store;
-  PolkitBackendLocalAuthorityPrivate *priv;
-
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
-  store = polkit_backend_local_authorization_store_new (directory, ".pkla");
-  priv->authorization_stores = g_list_append (priv->authorization_stores, store);
-
-  g_signal_connect (store,
-                    "changed",
-                    G_CALLBACK (on_store_changed),
-                    authority);
-}
-
-static gint
-authorization_store_path_compare_func (GFile *file_a,
-                                       GFile *file_b)
-{
-  const gchar *a;
-  const gchar *b;
-
-  a = g_object_get_data (G_OBJECT (file_a), "sort-key");
-  b = g_object_get_data (G_OBJECT (file_b), "sort-key");
-
-  return g_strcmp0 (a, b);
-}
-
-static void
-add_all_authorization_stores (PolkitBackendLocalAuthority *authority)
-{
-  PolkitBackendLocalAuthorityPrivate *priv;
-  guint n;
-  GList *directories;
-  GList *l;
-
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-  directories = NULL;
-
-  for (n = 0; priv->authorization_store_paths && priv->authorization_store_paths[n]; n++)
-    {
-      const gchar *toplevel_path;
-      GFile *toplevel_directory;
-      GFileEnumerator *directory_enumerator;
-      GFileInfo *file_info;
-      GError *error;
-
-      error = NULL;
-
-      toplevel_path = priv->authorization_store_paths[n];
-      toplevel_directory = g_file_new_for_path (toplevel_path);
-      directory_enumerator = g_file_enumerate_children (toplevel_directory,
-                                                        "standard::name,standard::type",
-                                                        G_FILE_QUERY_INFO_NONE,
-                                                        NULL,
-                                                        &error);
-      if (directory_enumerator == NULL)
-        {
-          g_warning ("Error getting enumerator for %s: %s", toplevel_path, error->message);
-          g_error_free (error);
-          g_object_unref (toplevel_directory);
-          continue;
-        }
-
-      while ((file_info = g_file_enumerator_next_file (directory_enumerator, NULL, &error)) != NULL)
-        {
-          /* only consider directories */
-          if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
-            {
-              const gchar *name;
-              GFile *directory;
-              gchar *sort_key;
-
-              name = g_file_info_get_name (file_info);
-
-              /* This makes entries in directories in /etc take precedence to entries in directories in /var */
-              sort_key = g_strdup_printf ("%s-%d", name, n);
-
-              directory = g_file_get_child (toplevel_directory, name);
-              g_object_set_data_full (G_OBJECT (directory), "sort-key", sort_key, g_free);
-
-              directories = g_list_prepend (directories, directory);
-            }
-          g_object_unref (file_info);
-        }
-      if (error != NULL)
-        {
-          g_warning ("Error enumerating files in %s: %s", toplevel_path, error->message);
-          g_error_free (error);
-          g_object_unref (toplevel_directory);
-          g_object_unref (directory_enumerator);
-          continue;
-        }
-      g_object_unref (directory_enumerator);
-      g_object_unref (toplevel_directory);
-    }
-
-  /* Sort directories */
-  directories = g_list_sort (directories, (GCompareFunc) authorization_store_path_compare_func);
-
-  /* And now add an authorization store for each one */
-  for (l = directories; l != NULL; l = l->next)
-    {
-      GFile *directory = G_FILE (l->data);
-      gchar *name;
-
-      name = g_file_get_path (directory);
-      g_debug ("Added `%s' as a local authorization store", name);
-      g_free (name);
-
-      add_one_authorization_store (authority, directory);
-    }
-
-  g_list_foreach (directories, (GFunc) g_object_unref, NULL);
-  g_list_free (directories);
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-on_toplevel_authority_store_monitor_changed (GFileMonitor     *monitor,
-                                             GFile            *file,
-                                             GFile            *other_file,
-                                             GFileMonitorEvent event_type,
-                                             gpointer          user_data)
-{
-  PolkitBackendLocalAuthority *authority = POLKIT_BACKEND_LOCAL_AUTHORITY (user_data);
-
-  purge_all_authorization_stores (authority);
-  add_all_authorization_stores (authority);
-}
-
-static void
-polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
-{
-  PolkitBackendLocalAuthorityPrivate *priv;
-
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
-  priv->config_path = NULL;
-  priv->authorization_store_paths = NULL;
-}
-
-static void
-polkit_backend_local_authority_constructed (GObject *object)
-{
-  PolkitBackendLocalAuthority *authority;
-  PolkitBackendLocalAuthorityPrivate *priv;
-  GFile *config_directory;
-  guint n;
-
-  authority = POLKIT_BACKEND_LOCAL_AUTHORITY (object);
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
-
-  g_debug ("Using config directory `%s'", priv->config_path);
-  config_directory = g_file_new_for_path (priv->config_path);
-  priv->config_source = polkit_backend_config_source_new (config_directory);
-  g_object_unref (config_directory);
-
-  add_all_authorization_stores (authority);
-
-  /* Monitor the toplevels */
-  priv->authorization_store_monitors = NULL;
-  for (n = 0; priv->authorization_store_paths && priv->authorization_store_paths[n]; n++)
-    {
-      const gchar *toplevel_path;
-      GFile *toplevel_directory;
-      GFileMonitor *monitor;
-      GError *error;
-
-      toplevel_path = priv->authorization_store_paths[n];
-      toplevel_directory = g_file_new_for_path (toplevel_path);
-
-      error = NULL;
-      monitor = g_file_monitor_directory (toplevel_directory,
-                                          G_FILE_MONITOR_NONE,
-                                          NULL,
-                                          &error);
-      if (monitor == NULL)
-        {
-          g_warning ("Error creating file monitor for %s: %s", toplevel_path, error->message);
-          g_error_free (error);
-          g_object_unref (toplevel_directory);
-          continue;
-        }
-
-      g_debug ("Monitoring `%s' for changes", toplevel_path);
-
-      g_signal_connect (monitor,
-                        "changed",
-                        G_CALLBACK (on_toplevel_authority_store_monitor_changed),
-                        authority);
-
-      priv->authorization_store_monitors = g_list_append (priv->authorization_store_monitors, monitor);
-
-      g_object_unref (toplevel_directory);
-    }
-
-  G_OBJECT_CLASS (polkit_backend_local_authority_parent_class)->constructed (object);
-}
-
-static void
-polkit_backend_local_authority_finalize (GObject *object)
-{
-  PolkitBackendLocalAuthority *local_authority;
-  PolkitBackendLocalAuthorityPrivate *priv;
-
-  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (object);
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
-  purge_all_authorization_stores (local_authority);
-
-  g_list_free_full (priv->authorization_store_monitors, g_object_unref);
-
-  if (priv->config_source != NULL)
-    g_object_unref (priv->config_source);
-
-  g_free (priv->config_path);
-  g_strfreev (priv->authorization_store_paths);
-
-  G_OBJECT_CLASS (polkit_backend_local_authority_parent_class)->finalize (object);
-}
-
-static const gchar *
-polkit_backend_local_authority_get_name (PolkitBackendAuthority *authority)
-{
-  return "local";
-}
-
-static const gchar *
-polkit_backend_local_authority_get_version (PolkitBackendAuthority *authority)
-{
-  return PACKAGE_VERSION;
-}
-
-static PolkitAuthorityFeatures
-polkit_backend_local_authority_get_features (PolkitBackendAuthority *authority)
-{
-  return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
-}
-
-static void
-polkit_backend_local_authority_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
-{
-  PolkitBackendLocalAuthority *local_authority;
-  PolkitBackendLocalAuthorityPrivate *priv;
-
-  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (object);
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
-  switch (property_id)
-    {
-      case PROP_CONFIG_PATH:
-        g_free (priv->config_path);
-        priv->config_path = g_value_dup_string (value);
-        break;
-      case PROP_AUTH_STORE_PATHS:
-        g_strfreev (priv->authorization_store_paths);
-        priv->authorization_store_paths = g_strsplit (g_value_get_string (value), ";", 0);
-        break;
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-        break;
-    }
-}
-
-static void
-polkit_backend_local_authority_class_init (PolkitBackendLocalAuthorityClass *klass)
-{
-  GObjectClass *gobject_class;
-  PolkitBackendAuthorityClass *authority_class;
-  PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
-  GParamSpec *pspec;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-  authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
-  interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
-
-  gobject_class->set_property                           = polkit_backend_local_authority_set_property;
-  gobject_class->finalize                               = polkit_backend_local_authority_finalize;
-  gobject_class->constructed                            = polkit_backend_local_authority_constructed;
-  authority_class->get_name                             = polkit_backend_local_authority_get_name;
-  authority_class->get_version                          = polkit_backend_local_authority_get_version;
-  authority_class->get_features                         = polkit_backend_local_authority_get_features;
-  interactive_authority_class->get_admin_identities     = polkit_backend_local_authority_get_admin_auth_identities;
-  interactive_authority_class->check_authorization_sync = polkit_backend_local_authority_check_authorization_sync;
-
-  pspec = g_param_spec_string ("config-path",
-                               "Local Authority Configuration Path",
-                               "Path to directory of LocalAuthority config files.",
-                               PACKAGE_SYSCONF_DIR "/polkit-1/localauthority.conf.d",
-                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
-  g_object_class_install_property (gobject_class, PROP_CONFIG_PATH, pspec);
-
-  pspec = g_param_spec_string ("auth-store-paths",
-                               "Local Authorization Store Paths",
-                               "Semi-colon separated list of Authorization Store 'top' directories.",
-                               PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority;"
-                               PACKAGE_SYSCONF_DIR "/polkit-1/localauthority",
-                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
-  g_object_class_install_property (gobject_class, PROP_AUTH_STORE_PATHS, pspec);
-
-  g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorityPrivate));
-}
-
-static GList *
-polkit_backend_local_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
-                                                          PolkitSubject                     *caller,
-                                                          PolkitSubject                     *subject,
-                                                          PolkitIdentity                    *user_for_subject,
-                                                          const gchar                       *action_id,
-                                                          PolkitDetails                     *details)
-{
-  PolkitBackendLocalAuthority *local_authority;
-  PolkitBackendLocalAuthorityPrivate *priv;
-  GList *ret;
-  guint n;
-  gchar **admin_identities;
-  GError *error;
-
-  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
-  ret = NULL;
-
-  error = NULL;
-  admin_identities = polkit_backend_config_source_get_string_list (priv->config_source,
-                                                                   "Configuration",
-                                                                   "AdminIdentities",
-                                                                   &error);
-  if (admin_identities == NULL)
-    {
-      g_warning ("Error getting admin_identities configuration item: %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  for (n = 0; admin_identities[n] != NULL; n++)
-    {
-      PolkitIdentity *identity;
-
-      error = NULL;
-      identity = polkit_identity_from_string (admin_identities[n], &error);
-      if (identity == NULL)
-        {
-          g_warning ("Error parsing identity %s: %s", admin_identities[n], error->message);
-          g_error_free (error);
-          continue;
-        }
-
-      if (POLKIT_IS_UNIX_USER (identity))
-        {
-          ret = g_list_append (ret, identity);
-        }
-      else if (POLKIT_IS_UNIX_GROUP (identity))
-        {
-          ret = g_list_concat (ret, get_users_in_group (identity, FALSE));
-        }
-      else if (POLKIT_IS_UNIX_NETGROUP (identity))
-        {
-          ret =  g_list_concat (ret, get_users_in_net_group (identity, FALSE));
-        }
-      else
-        {
-          g_warning ("Unsupported identity %s", admin_identities[n]);
-        }
-    }
-
-  g_strfreev (admin_identities);
-
- out:
-
-  /* default to uid 0 if no admin identities has been found */
-  if (ret == NULL)
-    ret = g_list_prepend (ret, polkit_unix_user_new (0));
-
-  return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static PolkitImplicitAuthorization
-polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *authority,
-                                                         PolkitSubject                     *caller,
-                                                         PolkitSubject                     *subject,
-                                                         PolkitIdentity                    *user_for_subject,
-                                                         gboolean                           subject_is_local,
-                                                         gboolean                           subject_is_active,
-                                                         const gchar                       *action_id,
-                                                         PolkitDetails                     *details,
-                                                         PolkitImplicitAuthorization        implicit)
-{
-  PolkitBackendLocalAuthority *local_authority;
-  PolkitBackendLocalAuthorityPrivate *priv;
-  PolkitImplicitAuthorization ret;
-  PolkitImplicitAuthorization ret_any;
-  PolkitImplicitAuthorization ret_inactive;
-  PolkitImplicitAuthorization ret_active;
-  GList *groups;
-  GList *l, *ll;
-
-  ret = implicit;
-
-  local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
-  priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
-
-#if 0
-  g_debug ("local: checking `%s' for subject `%s' (user `%s')",
-           action_id,
-           polkit_subject_to_string (subject),
-           polkit_identity_to_string (user_for_subject));
-#endif
-
-  /* First lookup for all groups the user belong to */
-  groups = get_groups_for_user (user_for_subject);
-  for (ll = groups; ll != NULL; ll = ll->next)
-    {
-      PolkitIdentity *group = POLKIT_IDENTITY (ll->data);
-
-      for (l = priv->authorization_stores; l != NULL; l = l->next)
-        {
-          PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
-
-          if (polkit_backend_local_authorization_store_lookup (store,
-                                                               group,
-                                                               action_id,
-                                                               details,
-                                                               &ret_any,
-                                                               &ret_inactive,
-                                                               &ret_active))
-            {
-              if (subject_is_local && subject_is_active)
-                {
-                  if (ret_active != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                    ret = ret_active;
-                }
-              else if (subject_is_local)
-                {
-                  if (ret_inactive != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                    ret = ret_inactive;
-                }
-              else
-                {
-                  if (ret_any != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                    ret = ret_any;
-                }
-            }
-        }
-    }
-  g_list_foreach (groups, (GFunc) g_object_unref, NULL);
-  g_list_free (groups);
-
-  /* Then do it for the user */
-  for (l = priv->authorization_stores; l != NULL; l = l->next)
-    {
-      PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
-
-      if (polkit_backend_local_authorization_store_lookup (store,
-                                                           user_for_subject,
-                                                           action_id,
-                                                           details,
-                                                           &ret_any,
-                                                           &ret_inactive,
-                                                           &ret_active))
-        {
-          if (subject_is_local && subject_is_active)
-            {
-              if (ret_active != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                ret = ret_active;
-            }
-          else if (subject_is_local)
-            {
-              if (ret_inactive != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                ret = ret_inactive;
-            }
-          else
-            {
-              if (ret_any != POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN)
-                ret = ret_any;
-            }
-        }
-    }
-
-  return ret;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static GList *
-get_users_in_group (PolkitIdentity                    *group,
-                    gboolean                           include_root)
-{
-  gid_t gid;
-  struct group *grp;
-  GList *ret;
-  guint n;
-
-  ret = NULL;
-
-  gid = polkit_unix_group_get_gid (POLKIT_UNIX_GROUP (group));
-  grp = getgrgid (gid);
-  if (grp == NULL)
-    {
-      g_warning ("Error looking up group with gid %d: %s", gid, g_strerror (errno));
-      goto out;
-    }
-
-  for (n = 0; grp->gr_mem != NULL && grp->gr_mem[n] != NULL; n++)
-    {
-      PolkitIdentity *user;
-      GError *error;
-
-      if (!include_root && g_strcmp0 (grp->gr_mem[n], "root") == 0)
-        continue;
-
-      error = NULL;
-      user = polkit_unix_user_new_for_name (grp->gr_mem[n], &error);
-      if (user == NULL)
-        {
-          g_warning ("Unknown username '%s' in group: %s", grp->gr_mem[n], error->message);
-          g_error_free (error);
-        }
-      else
-        {
-          ret = g_list_prepend (ret, user);
-        }
-    }
-
-  ret = g_list_reverse (ret);
-
- out:
-  return ret;
-}
-
-static GList *
-get_users_in_net_group (PolkitIdentity                    *group,
-                        gboolean                           include_root)
-{
-  const gchar *name;
-  GList *ret;
-
-  ret = NULL;
-  name = polkit_unix_netgroup_get_name (POLKIT_UNIX_NETGROUP (group));
-
-  if (setnetgrent (name) == 0)
-    {
-      g_warning ("Error looking up net group with name %s: %s", name, g_strerror (errno));
-      goto out;
-    }
-
-  for (;;)
-    {
-      char *hostname, *username, *domainname;
-      PolkitIdentity *user;
-      GError *error = NULL;
-
-      if (getnetgrent (&hostname, &username, &domainname) == 0)
-        break;
-
-      /* Skip NULL entries since we never want to make everyone an admin
-       * Skip "-" entries which mean "no match ever" in netgroup land */
-      if (username == NULL || g_strcmp0 (username, "-") == 0)
-        continue;
-
-      /* TODO: Should we match on hostname? Maybe only allow "-" as a hostname
-       * for safety. */
-
-      user = polkit_unix_user_new_for_name (username, &error);
-      if (user == NULL)
-        {
-          g_warning ("Unknown username '%s' in unix-netgroup: %s", username, error->message);
-          g_error_free (error);
-        }
-      else
-        {
-          ret = g_list_prepend (ret, user);
-        }
-    }
-
-  ret = g_list_reverse (ret);
-
- out:
-  endnetgrent ();
-  return ret;
-}
-
-
-static GList *
-get_groups_for_user (PolkitIdentity *user)
-{
-  uid_t uid;
-  struct passwd *passwd;
-  GList *result;
-  gid_t groups[512];
-  int num_groups = 512;
-  int n;
-
-  result = NULL;
-
-  /* TODO: it would be, uhm, good to cache this information */
-
-  uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user));
-  passwd = getpwuid (uid);
-  if (passwd == NULL)
-    {
-      g_warning ("No user with uid %d", uid);
-      goto out;
-    }
-
-  /* TODO: should resize etc etc etc */
-
-  if (getgrouplist (passwd->pw_name,
-                    passwd->pw_gid,
-                    groups,
-                    &num_groups) < 0)
-    {
-      g_warning ("Error looking up groups for uid %d: %s", uid, g_strerror (errno));
-      goto out;
-    }
-
-  for (n = 0; n < num_groups; n++)
-    result = g_list_prepend (result, polkit_unix_group_new (groups[n]));
-
- out:
-
-  return result;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkitbackend/polkitbackendlocalauthority.h b/src/polkitbackend/polkitbackendlocalauthority.h
deleted file mode 100644
index 553da3b..0000000
--- a/src/polkitbackend/polkitbackendlocalauthority.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
-#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
-#endif
-
-#ifndef __POLKIT_BACKEND_LOCAL_AUTHORITY_H
-#define __POLKIT_BACKEND_LOCAL_AUTHORITY_H
-
-#include <glib-object.h>
-#include <polkitbackend/polkitbackendtypes.h>
-#include <polkitbackend/polkitbackendinteractiveauthority.h>
-
-G_BEGIN_DECLS
-
-#define POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY         (polkit_backend_local_authority_get_type ())
-#define POLKIT_BACKEND_LOCAL_AUTHORITY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthority))
-#define POLKIT_BACKEND_LOCAL_AUTHORITY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityClass))
-#define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY,PolkitBackendLocalAuthorityClass))
-#define POLKIT_BACKEND_IS_LOCAL_AUTHORITY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY))
-#define POLKIT_BACKEND_IS_LOCAL_AUTHORITY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY))
-
-typedef struct _PolkitBackendLocalAuthorityClass    PolkitBackendLocalAuthorityClass;
-
-/**
- * PolkitBackendLocalAuthority:
- *
- * The #PolkitBackendLocalAuthority struct should not be accessed directly.
- */
-struct _PolkitBackendLocalAuthority
-{
-  /*< private >*/
-  PolkitBackendInteractiveAuthority parent_instance;
-};
-
-/**
- * PolkitBackendLocalAuthorityClass:
- * @parent_class: The parent class.
- *
- * Class structure for #PolkitBackendLocalAuthority.
- */
-struct _PolkitBackendLocalAuthorityClass
-{
-  /*< public >*/
-  PolkitBackendInteractiveAuthorityClass parent_class;
-
-  /*< private >*/
-  /* Padding for future expansion */
-  void (*_polkit_reserved1) (void);
-  void (*_polkit_reserved2) (void);
-  void (*_polkit_reserved3) (void);
-  void (*_polkit_reserved4) (void);
-  void (*_polkit_reserved5) (void);
-  void (*_polkit_reserved6) (void);
-  void (*_polkit_reserved7) (void);
-  void (*_polkit_reserved8) (void);
-  void (*_polkit_reserved9) (void);
-  void (*_polkit_reserved10) (void);
-  void (*_polkit_reserved11) (void);
-  void (*_polkit_reserved12) (void);
-  void (*_polkit_reserved13) (void);
-  void (*_polkit_reserved14) (void);
-  void (*_polkit_reserved15) (void);
-  void (*_polkit_reserved16) (void);
-  void (*_polkit_reserved17) (void);
-  void (*_polkit_reserved18) (void);
-  void (*_polkit_reserved19) (void);
-  void (*_polkit_reserved20) (void);
-  void (*_polkit_reserved21) (void);
-  void (*_polkit_reserved22) (void);
-  void (*_polkit_reserved23) (void);
-  void (*_polkit_reserved24) (void);
-  void (*_polkit_reserved25) (void);
-  void (*_polkit_reserved26) (void);
-  void (*_polkit_reserved27) (void);
-  void (*_polkit_reserved28) (void);
-  void (*_polkit_reserved29) (void);
-  void (*_polkit_reserved30) (void);
-  void (*_polkit_reserved31) (void);
-  void (*_polkit_reserved32) (void);
-};
-
-GType                   polkit_backend_local_authority_get_type (void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __POLKIT_BACKEND_LOCAL_AUTHORITY_H */
-
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
deleted file mode 100644
index f40a943..0000000
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.c
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#include "config.h"
-
-#include <netdb.h>
-#include <string.h>
-#include <polkit/polkit.h>
-#include "polkitbackendlocalauthorizationstore.h"
-
-/* <internal>
- * SECTION:polkitbackendlocalauthorizationstore
- * @title: PolkitBackendLocalAuthorizationStore
- * @short_description: Watches a directory for authorization files
- *
- * #PolkitBackendLocalAuthorizationStore is a utility class to watch
- * and read authorization files from a directory.
- */
-
-struct _PolkitBackendLocalAuthorizationStorePrivate
-{
-  GFile *directory;
-  gchar *extension;
-
-  GFileMonitor *directory_monitor;
-
-  /* List of LocalAuthorization objects */
-  GList *authorizations;
-
-  gboolean has_data;
-};
-
-enum
-{
-  PROP_0,
-  PROP_DIRECTORY,
-  PROP_EXTENSION,
-};
-
-enum
-{
-  CHANGED_SIGNAL,
-  LAST_SIGNAL,
-};
-
-static guint signals[LAST_SIGNAL] = {0};
-
-static void polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store);
-
-static void polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store);
-
-G_DEFINE_TYPE (PolkitBackendLocalAuthorizationStore, polkit_backend_local_authorization_store, G_TYPE_OBJECT);
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-typedef struct
-{
-  gchar *id;
-
-  /* Identities with glob support */
-  GList *identity_specs;
-
-  /* Netgroup identity strings, which can not support glob syntax */
-  GList *netgroup_identities;
-
-  GList *action_specs;
-
-  PolkitImplicitAuthorization result_any;
-  PolkitImplicitAuthorization result_inactive;
-  PolkitImplicitAuthorization result_active;
-
-  GHashTable *return_value;
-} LocalAuthorization;
-
-static void
-local_authorization_free (LocalAuthorization *authorization)
-{
-  g_free (authorization->id);
-  g_list_foreach (authorization->identity_specs, (GFunc) g_pattern_spec_free, NULL);
-  g_list_free (authorization->identity_specs);
-  g_list_free_full (authorization->netgroup_identities, g_free);
-  g_list_foreach (authorization->action_specs, (GFunc) g_pattern_spec_free, NULL);
-  g_list_free (authorization->action_specs);
-  if (authorization->return_value != NULL)
-    g_hash_table_unref (authorization->return_value);
-  g_free (authorization);
-}
-
-
-static LocalAuthorization *
-local_authorization_new (GKeyFile      *key_file,
-                         const gchar   *filename,
-                         const gchar   *group,
-                         GError       **error)
-{
-  LocalAuthorization *authorization;
-  gchar **identity_strings;
-  gchar **action_strings;
-  gchar *result_any_string;
-  gchar *result_inactive_string;
-  gchar *result_active_string;
-  gchar **return_value_strings;
-  guint n;
-
-  identity_strings = NULL;
-  action_strings = NULL;
-  result_any_string = NULL;
-  result_inactive_string = NULL;
-  result_active_string = NULL;
-  return_value_strings = NULL;
-
-  authorization = g_new0 (LocalAuthorization, 1);
-
-  identity_strings = g_key_file_get_string_list (key_file,
-                                                 group,
-                                                 "Identity",
-                                                 NULL,
-                                                 error);
-  if (identity_strings == NULL)
-    {
-      local_authorization_free (authorization);
-      authorization = NULL;
-      goto out;
-    }
-  for (n = 0; identity_strings[n] != NULL; n++)
-    {
-      /* Put netgroup entries in a seperate list from other identities who support glob syntax */
-      if (g_str_has_prefix (identity_strings[n], "unix-netgroup:"))
-        authorization->netgroup_identities = g_list_prepend (authorization->netgroup_identities,
-                                                             g_strdup (identity_strings[n] + sizeof "unix-netgroup:" - 1));
-      else
-        authorization->identity_specs = g_list_prepend (authorization->identity_specs,
-                                                        g_pattern_spec_new (identity_strings[n]));
-    }
-
-  action_strings = g_key_file_get_string_list (key_file,
-                                                 group,
-                                                 "Action",
-                                                 NULL,
-                                                 error);
-  if (action_strings == NULL)
-    {
-      local_authorization_free (authorization);
-      authorization = NULL;
-      goto out;
-    }
-  for (n = 0; action_strings[n] != NULL; n++)
-    {
-      authorization->action_specs = g_list_prepend (authorization->action_specs,
-                                                    g_pattern_spec_new (action_strings[n]));
-    }
-
-  authorization->result_any = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
-  authorization->result_inactive = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
-  authorization->result_active = POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN;
-
-  result_any_string = g_key_file_get_string (key_file,
-                                             group,
-                                             "ResultAny",
-                                             NULL);
-  if (result_any_string != NULL)
-    {
-      if (!polkit_implicit_authorization_from_string (result_any_string,
-                                                      &authorization->result_any))
-        {
-          g_set_error (error,
-                       POLKIT_ERROR,
-                       POLKIT_ERROR_FAILED,
-                       "Cannot parse ResultAny string `%s'", result_any_string);
-          local_authorization_free (authorization);
-          authorization = NULL;
-          goto out;
-        }
-    }
-
-  result_inactive_string = g_key_file_get_string (key_file,
-                                                  group,
-                                                  "ResultInactive",
-                                                  NULL);
-  if (result_inactive_string != NULL)
-    {
-      if (!polkit_implicit_authorization_from_string (result_inactive_string,
-                                                      &authorization->result_inactive))
-        {
-          g_set_error (error,
-                       POLKIT_ERROR,
-                       POLKIT_ERROR_FAILED,
-                       "Cannot parse ResultInactive string `%s'", result_inactive_string);
-          local_authorization_free (authorization);
-          authorization = NULL;
-          goto out;
-        }
-    }
-
-  result_active_string = g_key_file_get_string (key_file,
-                                                group,
-                                                "ResultActive",
-                                                NULL);
-  if (result_active_string != NULL)
-    {
-      if (!polkit_implicit_authorization_from_string (result_active_string,
-                                                      &authorization->result_active))
-        {
-          g_set_error (error,
-                       POLKIT_ERROR,
-                       POLKIT_ERROR_FAILED,
-                       "Cannot parse ResultActive string `%s'", result_active_string);
-          local_authorization_free (authorization);
-          authorization = NULL;
-          goto out;
-        }
-    }
-
-  if (result_any_string == NULL && result_inactive_string == NULL && result_active_string == NULL)
-    {
-          g_set_error (error,
-                       POLKIT_ERROR,
-                       POLKIT_ERROR_FAILED,
-                       "Must have at least one of ResultAny, ResultInactive and ResultActive");
-          local_authorization_free (authorization);
-          authorization = NULL;
-          goto out;
-    }
-
-  return_value_strings = g_key_file_get_string_list (key_file,
-                                                     group,
-                                                     "ReturnValue",
-                                                     NULL,
-                                                     error);
-  if (return_value_strings != NULL)
-    {
-      for (n = 0; return_value_strings[n] != NULL; n++)
-        {
-          gchar *p;
-          const gchar *key;
-          const gchar *value;
-
-          p = strchr (return_value_strings[n], '=');
-          if (p == NULL)
-            {
-              g_warning ("Item `%s' in ReturnValue is malformed. Ignoring.",
-                         return_value_strings[n]);
-              continue;
-            }
-
-          *p = '\0';
-          key = return_value_strings[n];
-          value = p + 1;
-
-          if (authorization->return_value == NULL)
-            {
-              authorization->return_value = g_hash_table_new_full (g_str_hash,
-                                                                   g_str_equal,
-                                                                   g_free,
-                                                                   g_free);
-            }
-          g_hash_table_insert (authorization->return_value, g_strdup (key), g_strdup (value));
-        }
-    }
-
-  authorization->id = g_strdup_printf ("%s::%s", filename, group);
-
- out:
-  g_strfreev (identity_strings);
-  g_free (action_strings);
-  g_free (result_any_string);
-  g_free (result_inactive_string);
-  g_free (result_active_string);
-  g_strfreev (return_value_strings);
-  return authorization;
-}
-
-/* ---------------------------------------------------------------------------------------------------- */
-
-static void
-polkit_backend_local_authorization_store_init (PolkitBackendLocalAuthorizationStore *store)
-{
-  store->priv = G_TYPE_INSTANCE_GET_PRIVATE (store,
-                                             POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
-                                             PolkitBackendLocalAuthorizationStorePrivate);
-}
-
-static void
-polkit_backend_local_authorization_store_finalize (GObject *object)
-{
-  PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
-  if (store->priv->directory != NULL)
-    g_object_unref (store->priv->directory);
-  g_free (store->priv->extension);
-
-  if (store->priv->directory_monitor != NULL)
-    g_object_unref (store->priv->directory_monitor);
-
-  g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
-  g_list_free (store->priv->authorizations);
-
-  if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize != NULL)
-    G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize (object);
-}
-
-
-static void
-polkit_backend_local_authorization_store_get_property (GObject    *object,
-                                                       guint       prop_id,
-                                                       GValue     *value,
-                                                       GParamSpec *pspec)
-{
-  PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
-  switch (prop_id)
-    {
-    case PROP_DIRECTORY:
-      g_value_set_object (value, store->priv->directory);
-      break;
-
-    case PROP_EXTENSION:
-      g_value_set_string (value, store->priv->extension);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-polkit_backend_local_authorization_store_set_property (GObject      *object,
-                                                       guint         prop_id,
-                                                       const GValue *value,
-                                                       GParamSpec   *pspec)
-{
-  PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-
-  switch (prop_id)
-    {
-    case PROP_DIRECTORY:
-      store->priv->directory = g_value_dup_object (value);
-      break;
-
-    case PROP_EXTENSION:
-      store->priv->extension = g_value_dup_string (value);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-    }
-}
-
-static void
-directory_monitor_changed (GFileMonitor     *monitor,
-                           GFile            *file,
-                           GFile            *other_file,
-                           GFileMonitorEvent event_type,
-                           gpointer          user_data)
-{
-  PolkitBackendLocalAuthorizationStore *store;
-
-  store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (user_data);
-
-  if (file != NULL)
-    {
-      gchar *name;
-
-      name = g_file_get_basename (file);
-
-      //g_debug ("event_type=%d file=%p name=%s", event_type, file, name);
-
-      if (!g_str_has_prefix (name, ".") &&
-          !g_str_has_prefix (name, "#") &&
-          g_str_has_suffix (name, store->priv->extension) &&
-          (event_type == G_FILE_MONITOR_EVENT_CREATED ||
-           event_type == G_FILE_MONITOR_EVENT_DELETED ||
-           event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
-        {
-
-          //g_debug ("match");
-
-          /* now throw away all caches */
-          polkit_backend_local_authorization_store_purge (store);
-          g_signal_emit_by_name (store, "changed");
-        }
-
-      g_free (name);
-    }
-}
-
-static void
-polkit_backend_local_authorization_store_constructed (GObject *object)
-{
-  PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
-  GError *error;
-
-  error = NULL;
-  store->priv->directory_monitor = g_file_monitor_directory (store->priv->directory,
-                                                              G_FILE_MONITOR_NONE,
-                                                              NULL,
-                                                              &error);
-  if (store->priv->directory_monitor == NULL)
-    {
-      gchar *dir_name;
-      dir_name = g_file_get_uri (store->priv->directory);
-      g_warning ("Error monitoring directory %s: %s", dir_name, error->message);
-      g_free (dir_name);
-      g_error_free (error);
-    }
-  else
-    {
-      g_signal_connect (store->priv->directory_monitor,
-                        "changed",
-                        (GCallback) directory_monitor_changed,
-                        store);
-    }
-
-  if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed != NULL)
-    G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed (object);
-}
-
-static void
-polkit_backend_local_authorization_store_class_init (PolkitBackendLocalAuthorizationStoreClass *klass)
-{
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (klass);
-
-  gobject_class->get_property = polkit_backend_local_authorization_store_get_property;
-  gobject_class->set_property = polkit_backend_local_authorization_store_set_property;
-  gobject_class->constructed  = polkit_backend_local_authorization_store_constructed;
-  gobject_class->finalize     = polkit_backend_local_authorization_store_finalize;
-
-  g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorizationStorePrivate));
-
-  /**
-   * PolkitBackendLocalAuthorizationStore:directory:
-   *
-   * The directory to watch for authorization files.
-   */
-  g_object_class_install_property (gobject_class,
-                                   PROP_DIRECTORY,
-                                   g_param_spec_object ("directory",
-                                                        "Directory",
-                                                        "The directory to watch for configuration files",
-                                                        G_TYPE_FILE,
-                                                        G_PARAM_CONSTRUCT_ONLY |
-                                                        G_PARAM_READWRITE |
-                                                        G_PARAM_STATIC_NAME |
-                                                        G_PARAM_STATIC_BLURB |
-                                                        G_PARAM_STATIC_NICK));
-
-  /**
-   * PolkitBackendLocalAuthorizationStore:extension:
-   *
-   * The file extension for files to consider, e.g. <quote>.pkla</quote>.
-   */
-  g_object_class_install_property (gobject_class,
-                                   PROP_EXTENSION,
-                                   g_param_spec_string ("extension",
-                                                        "Extension",
-                                                        "The extension of files to consider",
-                                                        NULL,
-                                                        G_PARAM_CONSTRUCT_ONLY |
-                                                        G_PARAM_READWRITE |
-                                                        G_PARAM_STATIC_NAME |
-                                                        G_PARAM_STATIC_BLURB |
-                                                        G_PARAM_STATIC_NICK));
-
-  /**
-   * PolkitBackendConfiguStore::changed:
-   * @store: A #PolkitBackendLocalAuthorizationStore.
-   *
-   * Emitted when configuration files in #PolkitBackendConfiguStore:directory changes.
-   */
-  signals[CHANGED_SIGNAL] = g_signal_new ("changed",
-                                          POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
-                                          G_SIGNAL_RUN_LAST,
-                                          G_STRUCT_OFFSET (PolkitBackendLocalAuthorizationStoreClass, changed),
-                                          NULL,
-                                          NULL,
-                                          g_cclosure_marshal_VOID__VOID,
-                                          G_TYPE_NONE,
-                                          0);
-}
-
-/**
- * polkit_backend_local_authorization_store_new:
- * @directory: The directory to watch.
- * @extension: The extension of files to consider e.g. <quote>.pkla</quote>.
- *
- * Creates a new #PolkitBackendLocalAuthorizationStore object that
- * reads authorizations from @directory with file extension
- * @extension. To watch for configuration changes, connect to the
- * #PolkitBackendLocalAuthorizationStore::changed signal.
- *
- * Returns: A #PolkitBackendLocalAuthorizationStore. Free with
- * g_object_unref().
- **/
-PolkitBackendLocalAuthorizationStore *
-polkit_backend_local_authorization_store_new (GFile       *directory,
-                                              const gchar *extension)
-{
-  PolkitBackendLocalAuthorizationStore *store;
-
-  store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (g_object_new (POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
-                                                                  "directory", directory,
-                                                                  "extension", extension,
-                                                                  NULL));
-
-  return store;
-}
-
-static void
-polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store)
-{
-  gchar *path;
-
-  path = g_file_get_path (store->priv->directory);
-  g_debug ("Dropping all .pkla caches for directory `%s'", path);
-  g_free (path);
-
-  g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
-  g_list_free (store->priv->authorizations);
-  store->priv->authorizations = NULL;
-
-  store->priv->has_data = FALSE;
-}
-
-static void
-polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store)
-{
-  GFileEnumerator *enumerator;
-  GFileInfo *file_info;
-  GError *error;
-  GList *files;
-  GList *l;
-
-  files = NULL;
-
-  if (store->priv->has_data)
-    goto out;
-
-  polkit_backend_local_authorization_store_purge (store);
-
-  error = NULL;
-  enumerator = g_file_enumerate_children (store->priv->directory,
-                                          "standard::name",
-                                          G_FILE_QUERY_INFO_NONE,
-                                          NULL,
-                                          &error);
-  if (enumerator == NULL)
-    {
-      gchar *dir_name;
-      dir_name = g_file_get_uri (store->priv->directory);
-      g_warning ("Error enumerating files in %s: %s", dir_name, error->message);
-      g_free (dir_name);
-      g_error_free (error);
-      goto out;
-    }
-
-  while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
-    {
-      const gchar *name;
-
-      name = g_file_info_get_name (file_info);
-
-      /* only consider files with the appropriate extension */
-      if (g_str_has_suffix (name, store->priv->extension) && name[0] != '.')
-        files = g_list_prepend (files, g_file_get_child (store->priv->directory, name));
-
-      g_object_unref (file_info);
-    }
-  g_object_unref (enumerator);
-  if (error != NULL)
-    {
-      g_warning ("Error enumerating files: %s", error->message);
-      g_error_free (error);
-      goto out;
-    }
-
-  /* process files; highest priority comes first */
-  for (l = files; l != NULL; l = l->next)
-    {
-      GFile *file = G_FILE (l->data);
-      gchar *filename;
-      GKeyFile *key_file;
-
-      filename = g_file_get_path (file);
-
-      key_file = g_key_file_new ();
-
-      error = NULL;
-      if (!g_key_file_load_from_file (key_file,
-                                      filename,
-                                      G_KEY_FILE_NONE,
-                                      &error))
-        {
-          g_warning ("Error loading key-file %s: %s", filename, error->message);
-          g_error_free (error);
-          error = NULL;
-          g_key_file_free (key_file);
-        }
-      else
-        {
-          gchar **groups;
-          guint n;
-
-          groups = g_key_file_get_groups (key_file, NULL);
-          for (n = 0; groups[n] != NULL; n++)
-            {
-              LocalAuthorization *authorization;
-
-              error = NULL;
-              authorization = local_authorization_new (key_file, filename, groups[n], &error);
-              if (authorization == NULL)
-                {
-                  g_warning ("Error parsing group `%s' in file `%s': %s",
-                             groups[n],
-                             filename,
-                             error->message);
-                  g_error_free (error);
-                }
-              else
-                {
-                  store->priv->authorizations = g_list_prepend (store->priv->authorizations,
-                                                                authorization);
-                }
-            }
-          g_strfreev (groups);
-
-          store->priv->authorizations = g_list_reverse (store->priv->authorizations);
-
-          g_key_file_free (key_file);
-        }
-
-      g_free (filename);
-    }
-
-  store->priv->has_data = TRUE;
-
- out:
-  g_list_foreach (files, (GFunc) g_object_unref, NULL);
-  g_list_free (files);
-}
-
-/**
- * polkit_backend_local_authorization_store_lookup:
- * @store: A #PolkitBackendLocalAuthorizationStore.
- * @identity: The identity to check for.
- * @action_id: The action id to check for.
- * @details: Details for @action.
- * @out_result_any: Return location for the result for any subjects if the look up matched.
- * @out_result_inactive: Return location for the result for subjects in local inactive sessions if the look up matched.
- * @out_result_active: Return location for the result for subjects in local active sessions if the look up matched.
- *
- * Checks if an authorization entry from @store matches @identity,
- * @action_id and @details. May append information to @details if
- * found.
- *
- * Returns: %TRUE if @store has an authorization entry that matches
- *     @identity, @action_id and @details. Otherwise %FALSE.
- */
-gboolean
-polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorizationStore *store,
-                                                 PolkitIdentity                       *identity,
-                                                 const gchar                          *action_id,
-                                                 PolkitDetails                        *details,
-                                                 PolkitImplicitAuthorization          *out_result_any,
-                                                 PolkitImplicitAuthorization          *out_result_inactive,
-                                                 PolkitImplicitAuthorization          *out_result_active)
-{
-  GList *l, *ll;
-  gboolean ret;
-  gchar *identity_string;
-
-  g_return_val_if_fail (POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE (store), FALSE);
-  g_return_val_if_fail (POLKIT_IS_IDENTITY (identity), FALSE);
-  g_return_val_if_fail (action_id != NULL, FALSE);
-  g_return_val_if_fail (POLKIT_IS_DETAILS (details), FALSE);
-  g_return_val_if_fail (out_result_any != NULL, FALSE);
-  g_return_val_if_fail (out_result_inactive != NULL, FALSE);
-  g_return_val_if_fail (out_result_active != NULL, FALSE);
-
-  ret = FALSE;
-  identity_string = NULL;
-
-  polkit_backend_local_authorization_store_ensure (store);
-
-  for (l = store->priv->authorizations; l != NULL; l = l->next)
-    {
-      LocalAuthorization *authorization = l->data;
-
-      /* first match the action */
-      for (ll = authorization->action_specs; ll != NULL; ll = ll->next)
-        {
-          if (g_pattern_match_string ((GPatternSpec *) ll->data, action_id))
-            break;
-        }
-      if (ll == NULL)
-        continue;
-
-      /* then match the identity against identity specs */
-      if (identity_string == NULL)
-        identity_string = polkit_identity_to_string (identity);
-      for (ll = authorization->identity_specs; ll != NULL; ll = ll->next)
-        {
-          if (g_pattern_match_string ((GPatternSpec *) ll->data, identity_string))
-            break;
-        }
-
-      /* if no identity specs matched and identity is a user, match against netgroups */
-      if (ll == NULL && POLKIT_IS_UNIX_USER (identity))
-        {
-          PolkitUnixUser *user_identity = POLKIT_UNIX_USER (identity);
-          const gchar *user_name = polkit_unix_user_get_name (user_identity);
-          if (!user_name)
-            continue;
-
-          for (ll = authorization->netgroup_identities; ll != NULL; ll = ll->next)
-            {
-              if (innetgr ((const gchar *) ll->data, NULL, user_name, NULL))
-                break;
-            }
-        }
-
-      if (ll == NULL)
-        continue;
-
-      /* Yay, a match! However, keep going since subsequent authorization entries may modify the result */
-      *out_result_any = authorization->result_any;
-      *out_result_inactive = authorization->result_inactive;
-      *out_result_active = authorization->result_active;
-      ret = TRUE;
-
-      if (details != NULL && authorization->return_value != NULL)
-        {
-          GHashTableIter iter;
-          const gchar *key;
-          const gchar *value;
-
-          g_hash_table_iter_init (&iter, authorization->return_value);
-          while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
-            {
-              polkit_details_insert (details, key, value);
-            }
-        }
-
-#if 0
-      g_debug ("authorization with id `%s' matched action_id `%s' for identity `%s'",
-               authorization->id,
-               action_id,
-               polkit_identity_to_string (identity));
-#endif
-    }
-
-  g_free (identity_string);
-
-  return ret;
-}
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.h b/src/polkitbackend/polkitbackendlocalauthorizationstore.h
deleted file mode 100644
index 4f198e9..0000000
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: David Zeuthen <davidz at redhat.com>
- */
-
-#if !defined (_POLKIT_BACKEND_COMPILATION) || defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
-#error "This is a private header file."
-#endif
-
-#ifndef __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H
-#define __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H
-
-#include <glib-object.h>
-#include <gio/gio.h>
-#include <polkitbackend/polkitbackendtypes.h>
-
-G_BEGIN_DECLS
-
-#define POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE         (polkit_backend_local_authorization_store_get_type ())
-#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE, PolkitBackendLocalAuthorizationStore))
-#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE, PolkitBackendLocalAuthorizationStoreClass))
-#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,PolkitBackendLocalAuthorizationStoreClass))
-#define POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE))
-#define POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE))
-
-typedef struct _PolkitBackendLocalAuthorizationStore         PolkitBackendLocalAuthorizationStore;
-typedef struct _PolkitBackendLocalAuthorizationStoreClass    PolkitBackendLocalAuthorizationStoreClass;
-typedef struct _PolkitBackendLocalAuthorizationStorePrivate  PolkitBackendLocalAuthorizationStorePrivate;
-
-struct _PolkitBackendLocalAuthorizationStore
-{
-  GObject parent_instance;
-  PolkitBackendLocalAuthorizationStorePrivate *priv;
-};
-
-struct _PolkitBackendLocalAuthorizationStoreClass
-{
-  /*< public >*/
-  GObjectClass parent_class;
-
-  /* Signals */
-  void (*changed)  (PolkitBackendLocalAuthorizationStore *store);
-
-  /*< private >*/
-  /* Padding for future expansion */
-  void (*_polkit_reserved1) (void);
-  void (*_polkit_reserved2) (void);
-  void (*_polkit_reserved3) (void);
-  void (*_polkit_reserved4) (void);
-  void (*_polkit_reserved5) (void);
-  void (*_polkit_reserved6) (void);
-  void (*_polkit_reserved7) (void);
-  void (*_polkit_reserved8) (void);
-};
-
-GType                                 polkit_backend_local_authorization_store_get_type (void) G_GNUC_CONST;
-PolkitBackendLocalAuthorizationStore *polkit_backend_local_authorization_store_new      (GFile       *directory,
-                                                                                         const gchar *extension);
-gboolean  polkit_backend_local_authorization_store_lookup   (PolkitBackendLocalAuthorizationStore *store,
-                                                             PolkitIdentity                       *identity,
-                                                             const gchar                          *action_id,
-                                                             PolkitDetails                        *details,
-                                                             PolkitImplicitAuthorization          *out_result_any,
-                                                             PolkitImplicitAuthorization          *out_result_inactive,
-                                                             PolkitImplicitAuthorization          *out_result_active);
-
-G_END_DECLS
-
-#endif /* __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H */
-
diff --git a/src/polkitbackend/polkitbackendtypes.h b/src/polkitbackend/polkitbackendtypes.h
index 2fe36ac..3777991 100644
--- a/src/polkitbackend/polkitbackendtypes.h
+++ b/src/polkitbackend/polkitbackendtypes.h
@@ -33,9 +33,6 @@ typedef struct _PolkitBackendAuthority PolkitBackendAuthority;
 struct _PolkitBackendInteractiveAuthority;
 typedef struct _PolkitBackendInteractiveAuthority PolkitBackendInteractiveAuthority;
 
-struct _PolkitBackendLocalAuthority;
-typedef struct _PolkitBackendLocalAuthority PolkitBackendLocalAuthority;
-
 struct _PolkitBackendJsAuthority;
 typedef struct _PolkitBackendJsAuthority PolkitBackendJsAuthority;
 
diff --git a/test/polkitbackend/Makefile.am b/test/polkitbackend/Makefile.am
index 46706d3..bb82dd4 100644
--- a/test/polkitbackend/Makefile.am
+++ b/test/polkitbackend/Makefile.am
@@ -33,12 +33,6 @@ TEST_PROGS =
 
 # ----------------------------------------------------------------------------------------------------
 
-TEST_PROGS += polkitbackendlocalauthorizationstoretest
-polkitbackendlocalauthorizationstoretest_SOURCES = polkitbackendlocalauthorizationstoretest.c
-
-TEST_PROGS += polkitbackendlocalauthoritytest
-polkitbackendlocalauthoritytest_SOURCES = polkitbackendlocalauthoritytest.c
-
 TEST_PROGS += polkitbackendjsauthoritytest
 polkitbackendjsauthoritytest_SOURCES = test-polkitbackendjsauthority.c
 
diff --git a/test/polkitbackend/polkitbackendlocalauthoritytest.c b/test/polkitbackend/polkitbackendlocalauthoritytest.c
deleted file mode 100644
index 40e9619..0000000
--- a/test/polkitbackend/polkitbackendlocalauthoritytest.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Nikki VonHollen <vonhollen at google.com>
- */
-
-#include "glib.h"
-
-#include <polkittesthelper.h>
-#include <polkit/polkit.h>
-#include <polkitbackend/polkitbackendlocalauthority.h>
-
-#define TEST_CONFIG_PATH "etc/polkit-1/localauthority.conf.d"
-#define TEST_AUTH_PATH1 "etc/polkit-1/localauthority"
-#define TEST_AUTH_PATH2 "var/lib/polkit-1/localauthority"
-
-/* Test helper types */
-
-struct auth_context {
-  const gchar *identity;
-  gboolean subject_is_local;
-  gboolean subject_is_active;
-  const gchar *action_id;
-  PolkitImplicitAuthorization implicit;
-  PolkitImplicitAuthorization expect;
-};
-
-static PolkitBackendLocalAuthority *create_authority (void);
-
-
-/* Test implementations */
-
-static void
-test_check_authorization_sync (const void *_ctx)
-{
-  const struct auth_context *ctx = (const struct auth_context *) _ctx;
-
-  PolkitBackendLocalAuthority *authority = create_authority ();
-
-  PolkitSubject *caller = polkit_unix_session_new ("caller-session");
-  g_assert (caller);
-
-  PolkitSubject *subject = polkit_unix_session_new ("subject-session");;
-  g_assert (subject);
-
-  GError *error = NULL;
-  PolkitIdentity *user_for_subject = polkit_identity_from_string (ctx->identity, &error);
-  g_assert_no_error (error);
-  g_assert (user_for_subject);
-
-  PolkitDetails *details = polkit_details_new ();
-  g_assert (details);
-
-  PolkitImplicitAuthorization auth;
-
-  auth = polkit_backend_interactive_authority_check_authorization_sync (
-      POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
-      caller,
-      subject,
-      user_for_subject,
-      ctx->subject_is_local,
-      ctx->subject_is_active,
-      ctx->action_id,
-      details,
-      ctx->implicit);
-
-  g_assert_cmpint (auth, ==, ctx->expect);
-
-  g_object_unref (authority);
-  g_object_unref (caller);
-  g_object_unref (subject);
-  g_object_unref (user_for_subject);
-  g_object_unref (details);
-}
-
-static void
-test_get_admin_identities (void)
-{
-  /* Note: The implementation for get_admin_identities is called
-   * get_admin_auth_identities in PolkitBackendLocalAuthority */
-
-  PolkitBackendLocalAuthority *authority = create_authority ();
-
-  /* Setup required arguments, but none of their values matter */
-  PolkitSubject *caller = polkit_unix_session_new ("caller-session");
-  g_assert (caller);
-
-  PolkitSubject *subject = polkit_unix_session_new ("subject-session");;
-  g_assert (subject);
-
-  GError *error = NULL;
-  PolkitIdentity *user_for_subject = polkit_identity_from_string ("unix-user:root", &error);
-  g_assert_no_error (error);
-  g_assert (user_for_subject);
-
-  PolkitDetails *details = polkit_details_new ();
-  g_assert (details);
-
-  /* Get the list of PolkitUnixUser objects who are admins */
-  GList *result;
-  result = polkit_backend_interactive_authority_get_admin_identities (
-      POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
-      caller,
-      subject,
-      user_for_subject,
-      "com.example.doesntmatter",
-      details);
-
-  guint result_len = g_list_length (result);
-  g_assert_cmpint (result_len, >, 0);
-
-  /* Test against each of the admins in the following list */
-  const gchar *expect_admins [] = {
-    "unix-user:root",
-    "unix-user:jane",
-    "unix-user:sally",
-    "unix-user:henry",
-    NULL,
-  };
-
-  unsigned int i;
-  for (i = 0; expect_admins[i] != NULL; i++)
-  {
-    g_assert_cmpint (i, <, result_len);
-
-    PolkitIdentity *test_identity = POLKIT_IDENTITY (g_list_nth_data (result, i));
-    g_assert (test_identity);
-
-    gchar *test_identity_str = polkit_identity_to_string (test_identity);
-    g_assert_cmpstr (expect_admins[i], ==, test_identity_str);
-  }
-}
-
-
-/* Factory for mock local authority. */
-static PolkitBackendLocalAuthority *
-create_authority (void)
-{
-  gchar *config_path = polkit_test_get_data_path (TEST_CONFIG_PATH);
-  gchar *auth_path1 = polkit_test_get_data_path (TEST_AUTH_PATH1);
-  gchar *auth_path2 = polkit_test_get_data_path (TEST_AUTH_PATH2);
-  gchar *auth_paths = g_strconcat (auth_path1, ";", auth_path2, NULL);
-
-  g_assert (config_path);
-  g_assert (auth_path1);
-  g_assert (auth_path2);
-  g_assert (auth_paths);
-  
-  PolkitBackendLocalAuthority *authority = g_object_new (
-      POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY,
-      "config-path", config_path,
-      "auth-store-paths", auth_paths,
-      NULL);
-  
-  g_free (config_path);
-  g_free (auth_path1);
-  g_free (auth_path2);
-  g_free (auth_paths);
-  return authority;
-}
-
-
-/* Variations of the check_authorization_sync */
-struct auth_context check_authorization_test_data [] = {
-  /* Test root, john, and jane on action awesomeproduct.foo (all users are ok) */
-  {"unix-user:root", TRUE, TRUE, "com.example.awesomeproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED},
-  {"unix-user:root", TRUE, FALSE, "com.example.awesomeproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED},
-  {"unix-user:root", FALSE, FALSE, "com.example.awesomeproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED},
-  {"unix-user:john", TRUE, TRUE, "com.example.awesomeproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED},
-  {"unix-user:jane", TRUE, TRUE, "com.example.awesomeproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED},
-
-  /* Test root, john, and jane on action restrictedproduct.foo (only root is ok) */
-  {"unix-user:root", TRUE, TRUE, "com.example.restrictedproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED},
-  {"unix-user:john", TRUE, TRUE, "com.example.restrictedproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN},
-  {"unix-user:jane", TRUE, TRUE, "com.example.restrictedproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN},
-
-  /* Test root against some missing actions */
-  {"unix-user:root", TRUE, TRUE, "com.example.missingproduct.foo",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN},
-
-  /* Test root, john, and jane against action awesomeproduct.bar
-   * which uses "unix-netgroup:baz" for auth (john and jane are OK, root is not) */
-  {"unix-user:root", TRUE, TRUE, "com.example.awesomeproduct.bar",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN},
-  {"unix-user:john", TRUE, TRUE, "com.example.awesomeproduct.bar",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED},
-  {"unix-user:jane", TRUE, TRUE, "com.example.awesomeproduct.bar",
-      POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN,
-      POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED},
-
-  {NULL},
-};
-
-
-/* Automatically create many variations of the check_authorization_sync test */
-static void
-add_check_authorization_tests (void) {
-  unsigned int i;
-  for (i = 0; check_authorization_test_data[i].identity; i++) {
-    struct auth_context *ctx = &check_authorization_test_data[i];
-    gchar *test_name = g_strdup_printf (
-        "/PolkitBackendLocalAuthority/check_authorization_sync_%d", i);
-    g_test_add_data_func (test_name, ctx, test_check_authorization_sync);
-  }
-};
-
-
-int
-main (int argc, char *argv[])
-{
-  g_type_init ();
-  g_test_init (&argc, &argv, NULL);
-  polkit_test_redirect_logs ();
-
-  // Register extension point only once. Required to create authority.
-  GIOExtensionPoint *ep = g_io_extension_point_register (
-      POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME);
-  g_io_extension_point_set_required_type (ep,
-      POLKIT_BACKEND_TYPE_AUTHORITY);
-
-  add_check_authorization_tests ();
-  g_test_add_func ("/PolkitBackendJsAuthority/get_admin_identities", test_get_admin_identities);
-
-  return g_test_run ();
-};
diff --git a/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c b/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c
deleted file mode 100644
index e787c17..0000000
--- a/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Nikki VonHollen <vonhollen at google.com>
- */
-
-#include "glib.h"
-
-#include <polkittesthelper.h>
-#include <polkit/polkit.h>
-#include <polkitbackend/polkitbackendlocalauthorizationstore.h>
-
-#define DATA_DIR "etc/polkit-1/localauthority/10-test"
-#define DATA_EXT ".pkla"
-
-static void
-test_new (void)
-{
-  PolkitBackendLocalAuthorizationStore *store;
-  gchar *data_dir_path;
-  GFile *data_dir;
-
-  data_dir_path = polkit_test_get_data_path (DATA_DIR);
-  g_assert (data_dir_path);
-
-  data_dir = g_file_new_for_path (data_dir_path);
-  g_assert (data_dir);
-
-  g_free (data_dir_path);
-
-  store = polkit_backend_local_authorization_store_new (data_dir, DATA_EXT);
-  g_assert (store);
-}
-
-
-static void
-test_lookup (void)
-{
-  gchar *data_dir_path;
-  GFile *data_dir;
-  PolkitBackendLocalAuthorizationStore *store;
-  GError *error = NULL;
-  PolkitIdentity *identity;
-  gboolean ok;
-  PolkitImplicitAuthorization ret_any;
-  PolkitImplicitAuthorization ret_inactive;
-  PolkitImplicitAuthorization ret_active;
-  PolkitDetails *details;
-
-  // Get auth store path
-  data_dir_path = polkit_test_get_data_path (DATA_DIR);
-  g_assert (data_dir_path);
-
-  data_dir = g_file_new_for_path (data_dir_path);
-  g_assert (data_dir);
-  
-  // Create the auth store
-  store = polkit_backend_local_authorization_store_new (data_dir, DATA_EXT);
-  g_assert (store);
-
-  // We don't care about details
-  details = polkit_details_new ();
-
-  // Create an identity to query with
-  identity = polkit_identity_from_string ("unix-group:users", &error);
-  g_assert (identity);
-  g_assert_no_error (error);
-
-  // Lookup an exisiting record
-  ok = polkit_backend_local_authorization_store_lookup (
-      store,
-      identity,
-      "com.example.awesomeproduct.foo",
-      details,
-      &ret_any,
-      &ret_inactive,
-      &ret_active);
-  g_assert (ok);
-  g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
-  g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
-  g_assert_cmpstr ("yes", ==, polkit_implicit_authorization_to_string (ret_active));
-
-  // Create another identity to query with
-  identity = polkit_identity_from_string ("unix-user:root", &error);
-  g_assert (identity);
-  g_assert_no_error (error);
-
-  // Lookup another exisiting record
-  ok = polkit_backend_local_authorization_store_lookup (
-      store,
-      identity,
-      "com.example.awesomeproduct.foo",
-      details,
-      &ret_any,
-      &ret_inactive,
-      &ret_active);
-  g_assert (ok);
-  g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
-  g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
-  g_assert_cmpstr ("yes", ==, polkit_implicit_authorization_to_string (ret_active));
-
-  // Lookup a missing record
-  ok = polkit_backend_local_authorization_store_lookup (
-      store,
-      identity,
-      "com.example.restrictedproduct.dobar",
-      details,
-      &ret_any,
-      &ret_inactive,
-      &ret_active);
-  g_assert (!ok);
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  g_type_init ();
-  g_test_init (&argc, &argv, NULL);
-  polkit_test_redirect_logs ();
-  g_test_add_func ("/PolkitBackendLocalAuthorizationStore/new", test_new);
-  g_test_add_func ("/PolkitBackendLocalAuthorizationStore/lookup", test_lookup);
-  return g_test_run ();
-}
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 948cbc1..24e599e 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -346,17 +346,12 @@ add_rules_tests (void)
 int
 main (int argc, char *argv[])
 {
-  GIOExtensionPoint *ep;
-
   setlocale (LC_ALL, "");
 
   g_type_init ();
   g_test_init (&argc, &argv, NULL);
   //polkit_test_redirect_logs ();
 
-  ep = g_io_extension_point_register (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME);
-  g_io_extension_point_set_required_type (ep, POLKIT_BACKEND_TYPE_AUTHORITY);
-
   g_test_add_func ("/PolkitBackendJsAuthority/get_admin_identities", test_get_admin_identities);
   add_rules_tests ();
 
commit 29950854f6b9e9b8ea2d96d67c79eeec1046a4f1
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 16:16:20 2012 -0400

    Add a systemd .service file
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/Makefile.am b/Makefile.am
index 01f0a4b..16bd0bc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,12 @@ EXTRA_DIST = 			\
 	$(NULL)
 
 # xsltproc barfs on 'make distcheck'; disable for now
-DISTCHECK_CONFIGURE_FLAGS=--disable-man-pages --disable-gtk-doc --disable-introspection
+DISTCHECK_CONFIGURE_FLAGS=							\
+	--disable-man-pages 							\
+	--disable-gtk-doc 							\
+	--disable-introspection							\
+	--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)	\
+	$(NULL)
 
 sign : dist
 	gpg --armor --detach-sign --output polkit-$(VERSION).tar.gz.sign polkit-$(VERSION).tar.gz
diff --git a/configure.ac b/configure.ac
index 2712e19..7c7ca7a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -181,6 +181,19 @@ AC_SUBST(LIBSYSTEMD_LOGIN_LIBS)
 AM_CONDITIONAL(HAVE_LIBSYSTEMD_LOGIN, [test "$have_libsystemd_login" = "yes"], [Using libsystemd-login])
 
 dnl ---------------------------------------------------------------------------
+dnl - systemd unit / service files
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([systemdsystemunitdir],
+            AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+            [],
+            [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+if test "x$with_systemdsystemunitdir" != "xno"; then
+  AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$systemdsystemunitdir"])
+
+dnl ---------------------------------------------------------------------------
 dnl - Select which authentication framework to use
 dnl ---------------------------------------------------------------------------
 
@@ -484,7 +497,8 @@ echo "
         Distribution/OS:            ${with_os_type}
         Authentication framework:   ${POLKIT_AUTHFW}
         Session tracking:           ${SESSION_TRACKING}
-        PAM support:                ${have_pam}"
+        PAM support:                ${have_pam}
+        systemdsystemunitdir:       ${systemdsystemunitdir}"
 
 if test "$have_pam" = yes ; then
 echo "
diff --git a/data/Makefile.am b/data/Makefile.am
index f0beeba..83bcc20 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -20,15 +20,26 @@ endif
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = polkit-gobject-1.pc polkit-backend-1.pc polkit-agent-1.pc
 
+
+systemdservice_in_files = polkit.service.in
+
+if HAVE_SYSTEMD
+systemdservicedir       = $(systemdsystemunitdir)
+systemdservice_DATA     = $(systemdservice_in_files:.service.in=.service)
+$(systemdservice_DATA): $(systemdservice_in_files) Makefile
+	@sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+endif
+
 CLEANFILES = $(BUILT_SOURCES)
 
 EXTRA_DIST = 							\
 	org.freedesktop.PolicyKit1.Authority.xml 		\
 	org.freedesktop.PolicyKit1.AuthenticationAgent.xml 	\
 	$(service_in_files) 					\
+	$(systemdservice_in_files) 				\
 	$(dbusconf_DATA) 					\
 	$(NULL)
 
 
 clean-local :
-	rm -f *~ $(service_DATA)
+	rm -f *~ $(service_DATA) $(systemdservice_DATA)
diff --git a/data/org.freedesktop.PolicyKit1.service.in b/data/org.freedesktop.PolicyKit1.service.in
index b6cd02b..fbceb3f 100644
--- a/data/org.freedesktop.PolicyKit1.service.in
+++ b/data/org.freedesktop.PolicyKit1.service.in
@@ -2,3 +2,4 @@
 Name=org.freedesktop.PolicyKit1
 Exec=@libexecdir@/polkitd --no-debug
 User=root
+SystemdService=polkit.service
diff --git a/data/polkit.service.in b/data/polkit.service.in
new file mode 100644
index 0000000..efd2948
--- /dev/null
+++ b/data/polkit.service.in
@@ -0,0 +1,8 @@
+[Unit]
+Description=Authorization Manager
+Documentation=man:polkit(8)
+
+[Service]
+Type=dbus
+BusName=org.freedesktop.PolicyKit1
+ExecStart=@libexecdir@/polkitd --no-debug
commit ebb7c616cc5b2cc6b71008321ba62a0b818d82b0
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 15:58:15 2012 -0400

    Fix distcheck
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 4fae20a..17d8310 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -24,7 +24,7 @@ libpolkit_backend_1includedir=$(includedir)/polkit-1/polkitbackend
 
 
 initjs.h : init.js
-	$(PERL) $(srcdir)/toarray.pl init.js init_js > $@
+	$(PERL) $(srcdir)/toarray.pl $(srcdir)/init.js init_js > $@
 
 BUILT_SOURCES += initjs.h
 
@@ -86,6 +86,7 @@ localauthorityconfig_DATA = 50-localauthority.conf
 EXTRA_DIST =								\
 	$(localauthorityconfig_DATA)					\
 	init.js								\
+	toarray.pl							\
 	$(NULL)
 
 dist-hook :
commit b8f326194efab5feac819079ca9abb0b9f477103
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 15:53:35 2012 -0400

    Rename --enable-systemd to --enable-libsystemd-login
    
    It's useful to be more specific because we also want an option to
    install a systemd .service file which you may not want even if you are
    using libsystemd-login...
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index 7b7f3eb..2712e19 100644
--- a/configure.ac
+++ b/configure.ac
@@ -152,33 +152,33 @@ if test "x$GCC" = "xyes"; then
 fi
 
 dnl ---------------------------------------------------------------------------
-dnl - Select wether to use systemd or ConsoleKit for session tracking
+dnl - Select wether to use libsystemd-login or ConsoleKit for session tracking
 dnl ---------------------------------------------------------------------------
 
-have_systemd=no
+have_libsystemd_login=no
 SESSION_TRACKING=ConsoleKit
 
-AC_ARG_ENABLE([systemd],
-              AS_HELP_STRING([--enable-systemd[=@<:@auto/yes/no@:>@]], [Use systemd (auto/yes/no)]),
-              [enable_systemd=$enableval],
-              [enable_systemd=auto])
-if test "$enable_systemd" != "no"; then
-  PKG_CHECK_MODULES(SYSTEMD,
+AC_ARG_ENABLE([libsystemd-login],
+              AS_HELP_STRING([--enable-libsystemd-login[=@<:@auto/yes/no@:>@]], [Use libsystemd-login (auto/yes/no)]),
+              [enable_libsystemd_login=$enableval],
+              [enable_libsystemd_login=auto])
+if test "$enable_libsystemd_login" != "no"; then
+  PKG_CHECK_MODULES(LIBSYSTEMD_LOGIN,
                     [libsystemd-login],
-                    have_systemd=yes,
-                    have_systemd=no)
-  if test "$have_systemd" = "yes"; then
-    SESSION_TRACKING=systemd
+                    have_libsystemd_login=yes,
+                    have_libsystemd_login=no)
+  if test "$have_libsystemd_login" = "yes"; then
+    SESSION_TRACKING=libsystemd-login
   else
-    if test "$enable_systemd" = "yes"; then
-      AC_MSG_ERROR([systemd support requested but libsystemd-login1 library not found])
+    if test "$enable_libsystemd_login" = "yes"; then
+      AC_MSG_ERROR([libsystemd-login support requested but libsystemd-login library not found])
     fi
   fi
 fi
 
-AC_SUBST(SYSTEMD_CFLAGS)
-AC_SUBST(SYSTEMD_LIBS)
-AM_CONDITIONAL(HAVE_SYSTEMD, [test "$have_systemd" = "yes"], [Using systemd])
+AC_SUBST(LIBSYSTEMD_LOGIN_CFLAGS)
+AC_SUBST(LIBSYSTEMD_LOGIN_LIBS)
+AM_CONDITIONAL(HAVE_LIBSYSTEMD_LOGIN, [test "$have_libsystemd_login" = "yes"], [Using libsystemd-login])
 
 dnl ---------------------------------------------------------------------------
 dnl - Select which authentication framework to use
diff --git a/src/polkit/Makefile.am b/src/polkit/Makefile.am
index 1068ea1..39d6d84 100644
--- a/src/polkit/Makefile.am
+++ b/src/polkit/Makefile.am
@@ -81,7 +81,7 @@ libpolkit_gobject_1_la_SOURCES =                                   			\
 	polkitpermission.c			polkitpermission.h			\
         $(NULL)
 
-if HAVE_SYSTEMD
+if HAVE_LIBSYSTEMD_LOGIN
 libpolkit_gobject_1_la_SOURCES += \
 	polkitunixsession-systemd.c		polkitunixsession.h
 else
@@ -92,12 +92,12 @@ endif
 libpolkit_gobject_1_la_CFLAGS =                                        	\
         -D_POLKIT_COMPILATION                                  		\
         $(GLIB_CFLAGS)							\
-	$(SYSTEMD_CFLAGS)						\
+	$(LIBSYSTEMD_LOGIN_CFLAGS)					\
         $(NULL)
 
 libpolkit_gobject_1_la_LIBADD =                               		\
         $(GLIB_LIBS)							\
-	$(SYSTEMD_LIBS)							\
+	$(LIBSYSTEMD_LOGIN_LIBS)					\
         $(NULL)
 
 libpolkit_gobject_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index b1a70c0..4fae20a 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -52,7 +52,7 @@ libpolkit_backend_1_la_SOURCES =                                   			\
 	polkitbackendlocalauthorizationstore.h	polkitbackendlocalauthorizationstore.c	\
         $(NULL)
 
-if HAVE_SYSTEMD
+if HAVE_LIBSYSTEMD_LOGIN
 libpolkit_backend_1_la_SOURCES += \
 	polkitbackendsessionmonitor.h		polkitbackendsessionmonitor-systemd.c
 else
@@ -64,13 +64,13 @@ libpolkit_backend_1_la_CFLAGS =                                        	\
         -D_POLKIT_COMPILATION                                  		\
         -D_POLKIT_BACKEND_COMPILATION                                  	\
         $(GLIB_CFLAGS)							\
-	$(SYSTEMD_CFLAGS)						\
+	$(LIBSYSTEMD_LOGIN_CFLAGS)					\
 	$(LIBJS_CFLAGS)							\
         $(NULL)
 
 libpolkit_backend_1_la_LIBADD =                               		\
         $(GLIB_LIBS)							\
-	$(SYSTEMD_LIBS)							\
+	$(LIBSYSTEMD_LOGIN_LIBS)					\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
 	$(EXPAT_LIBS)							\
 	$(LIBJS_LIBS)							\
commit 1724ece5c7b5a9f70969fd88e1a2dede8936e768
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 14:12:38 2012 -0400

    Add real-world example featuring udisks2 and the drive.* variables it passes
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 0632c95..e822d79 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -809,7 +809,7 @@ polkit.addRule(function(action, subject, details) {
         The following example showcases two things
       </para>
       <itemizedlist mark='opencircle' spacing='compact'>
-        <listitem><para>how the authorization decision can depend on data passed by the mechanism</para></listitem>
+        <listitem><para>how the authorization decision can depend on variables passed by the mechanism</para></listitem>
         <listitem><para>how to override the message shown in the authentication dialog</para></listitem>
       </itemizedlist>
       <programlisting><![CDATA[
@@ -822,6 +822,30 @@ polkit.addRule(function(action, subject, details) {
 });
 ]]></programlisting>
 
+      <para>
+        The following example shows another use of variables passed from the
+        mechanism. In this case, the mechanism is
+        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks.8.html">UDisks</ulink>
+        which defines a set of
+        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">actions</ulink>
+        and also documents the set of possible
+        <ulink url="http://udisks.freedesktop.org/docs/latest/udisks2-Utilities.html#udisks-polkit-details">variables</ulink>
+        passed along with each request.
+      </para>
+      <programlisting><![CDATA[
+// Allow users in group 'engineers' to perform any operation on
+// some drives without having to authenticate
+//
+polkit.addRule(function(action, subject, details) {
+    if (action.indexOf("org.freedesktop.udisks2.") == 0 &&
+        details["drive.vendor"] == "SEAGATE" &&
+        details["drive.model"] == "ST3300657SS" &&
+        subject.isInGroup("engineers")) {
+            return "yes";
+        }
+    }
+});
+]]></programlisting>
     </refsect2>
   </refsect1>
 
commit 224f7b892478302dccbe7e567b013d3c73d376fd
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 13:37:21 2012 -0400

    Make polkit_details_insert() remove the key if passed value is NULL
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkit/polkitdetails.c b/src/polkit/polkitdetails.c
index 9c5c7e7..07a6f63 100644
--- a/src/polkit/polkitdetails.c
+++ b/src/polkit/polkitdetails.c
@@ -142,6 +142,8 @@ polkit_details_lookup (PolkitDetails *details,
  * @value: (allow-none): A value.
  *
  * Inserts a copy of @key and @value on @details.
+ *
+ * If @value is %NULL, the key will be removed.
  */
 void
 polkit_details_insert (PolkitDetails *details,
@@ -155,7 +157,10 @@ polkit_details_insert (PolkitDetails *details,
                                            g_str_equal,
                                            g_free,
                                            g_free);
-  g_hash_table_insert (details->hash, g_strdup (key), g_strdup (value));
+  if (value != NULL)
+    g_hash_table_insert (details->hash, g_strdup (key), g_strdup (value));
+  else
+    g_hash_table_remove (details->hash, key);
 }
 
 /**
commit 13ac46935c801d9253971abee88a7d71c36c268e
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 12:57:34 2012 -0400

    Use <variablelist> instead of <informaltable> for Subject attributes
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 0e1e41b..0632c95 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -602,54 +602,70 @@ System Context         |                        |
         following attributes
       </para>
 
-      <informaltable id="polkit-js-subject-attributes">
-        <tgroup cols="3" align="left">
-          <thead>
-            <row>
-              <entry>Attribute</entry>
-              <entry>Type</entry>
-              <entry>Description</entry>
-            </row>
-          </thead>
-          <tbody>
-            <row>
-              <entry><parameter>pid</parameter></entry>
-              <entry><type>int</type></entry>
-              <entry>The process id</entry>
-            </row>
-            <row>
-              <entry><parameter>user</parameter></entry>
-              <entry><type>string</type></entry>
-              <entry>The user name</entry>
-            </row>
-            <row>
-              <entry><parameter>groups</parameter></entry>
-              <entry><type>string[]</type></entry>
-              <entry>Array of groups that <parameter>user</parameter> user belongs to</entry>
-            </row>
-            <row>
-              <entry><parameter>seat</parameter></entry>
-              <entry><type>string</type></entry>
-              <entry>The seat that the subject is associated with - blank if not on a local seat</entry>
-            </row>
-            <row>
-              <entry><parameter>session</parameter></entry>
-              <entry><type>string</type></entry>
-              <entry>The session that the subject is associated with</entry>
-            </row>
-            <row>
-              <entry><parameter>local</parameter></entry>
-              <entry><type>boolean</type></entry>
-              <entry>Set to <constant>true</constant> only if seat is local</entry>
-            </row>
-            <row>
-              <entry><parameter>active</parameter></entry>
-              <entry><type>boolean</type></entry>
-              <entry>Set to <constant>true</constant> only if the session is active</entry>
-            </row>
-          </tbody>
-        </tgroup>
-      </informaltable>
+      <variablelist id="polkit-js-subject-attributes">
+        <varlistentry>
+          <term><type>int</type> pid</term>
+          <listitem>
+            <para>
+              The process id.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>string</type> user</term>
+          <listitem>
+            <para>
+              The user name.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>string[]</type> groups</term>
+          <listitem>
+            <para>
+              Array of groups that <parameter>user</parameter> user belongs to.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>string</type> seat</term>
+          <listitem>
+            <para>
+              The seat that the subject is associated with - blank if not on a local seat.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>string</type> session</term>
+          <listitem>
+            <para>
+              The session that the subject is associated with.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>boolean</type> local</term>
+          <listitem>
+            <para>
+              Set to <constant>true</constant> only if seat is local.
+            </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><type>boolean</type> active</term>
+          <listitem>
+            <para>
+              Set to <constant>true</constant> only if the session is active.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
 
       <para>
         The following methods are available on the <type>Subject</type> type:
commit bb6850d986fff739149506e7a5d654d1588b614c
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 12:51:19 2012 -0400

    Mention details["polkit.message"] and add an example using details
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 9be4fb3..0e1e41b 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -689,14 +689,40 @@ System Context         |                        |
         being checked. It is of type <type>Details</type> and has
         details being set by the mechanism as attributes. For example,
         the <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
-        mechanism sets the details <literal>user</literal>,
-        <literal>program</literal> and <literal>command_line</literal>
-        which can be obtained through e.g. the following JavaScript
-        expression: <literal>details["program"]</literal>. Consult the
-        documentation for each mechanism for what details are
+        mechanism sets the variable <parameter>program</parameter>
+        which can be obtained in Javascript using the expression
+        <literal>details["program"]</literal>. Consult the
+        documentation for each mechanism for what variables are
         available for each action.
       </para>
 
+      <para>
+        The <parameter>details</parameter> also has the following
+        well-known attributes:
+      </para>
+      <variablelist>
+        <varlistentry>
+          <term><emphasis>polkit.message</emphasis></term>
+          <listitem>
+            <para>
+              The message to show in the authentication dialog (only
+              used if authentication is needed). Its initial value is
+              taken from the action declaration (the <literal>message</literal> element in the <filename
+              class='extension'>.policy</filename> file) but the value
+              can be overridden by the mechanism setting this key in
+              the <parameter>details</parameter> passed when doing the
+              <link
+              linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
+              call.
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
+      <para>
+        Note that a rule can set the
+        <parameter>polkit.message</parameter> attribute to change the
+        message shown in the authentication dialog.
+      </para>
     </refsect2>
 
     <refsect2 id="polkit-rules-examples">
@@ -763,6 +789,23 @@ polkit.addRule(function(action, subject, details) {
 });
 ]]></programlisting>
 
+      <para>
+        The following example showcases two things
+      </para>
+      <itemizedlist mark='opencircle' spacing='compact'>
+        <listitem><para>how the authorization decision can depend on data passed by the mechanism</para></listitem>
+        <listitem><para>how to override the message shown in the authentication dialog</para></listitem>
+      </itemizedlist>
+      <programlisting><![CDATA[
+polkit.addRule(function(action, subject, details) {
+    if (action == "org.freedesktop.policykit.exec" &&
+        details["program"] == "/usr/bin/cat") {
+        details["polkit.message"] = "Achtung! You need to authenticate as yourself to cat(1) files!";
+        return "auth_self";
+    }
+});
+]]></programlisting>
+
     </refsect2>
   </refsect1>
 
commit 85a36232189ad7e5006d2233b7f8e098f7815bcf
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed May 23 12:14:44 2012 -0400

    Fix a couple typos in the docs
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/pkaction.xml b/docs/man/pkaction.xml
index 5957315..f5542d0 100644
--- a/docs/man/pkaction.xml
+++ b/docs/man/pkaction.xml
@@ -92,8 +92,8 @@
   <refsect1 id="pkaction-see-also">
     <title>SEE ALSO</title>
     <para>
-      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
-      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
       <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 3722343..9be4fb3 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -727,7 +727,7 @@ polkit.addAdminRule(function(action, subject, details) {
 
       <para>
         Forbid users in group <literal>children</literal> to change
-        hostname configuration (that is, any action starting wth
+        hostname configuration (that is, any action starting with
         <literal>org.freedesktop.hostname1.</literal>) and allow
         anyone else to do it after authenticating as themselves:
       </para>
@@ -786,7 +786,7 @@ polkit.addRule(function(action, subject, details) {
   <refsect1 id="polkit-see-also">
     <title>SEE ALSO</title>
     <para>
-      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
       <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 3d177c5..243539f 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -62,7 +62,7 @@
   <refsect1 id="polkitd-see-also">
     <title>SEE ALSO</title>
     <para>
-      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
       <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
commit 39a5ae6927e16b4703bfba16eaf0c2e84ef9873b
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 15:45:06 2012 -0400

    Fix speling
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index e36f05a..3722343 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -700,7 +700,7 @@ System Context         |                        |
     </refsect2>
 
     <refsect2 id="polkit-rules-examples">
-      <title>Authorzation Rules Examples</title>
+      <title>Authorization Rules Examples</title>
 
       <para>
         Allow all users in the <literal>admin</literal> group to
commit c8e89cea421bf57ffebef67513c0e043244e146d
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 14:18:19 2012 -0400

    polkitd: add reference to polkit(8) from its man page
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 8342d54..3d177c5 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -35,7 +35,10 @@
       should never need to start this daemon as it will be
       automatically started by
       <citerefentry><refentrytitle>dbus-daemon</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      whenever an application calls into the service.
+      whenever an application calls into the service. See the
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      man page for more information.
+
     </para>
   </refsect1>
 
commit 875fc6d6c243f51bb94daa7f562be74da59cf5a8
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 14:00:36 2012 -0400

    Clarify docs a bit
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 0d560dc..e36f05a 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -25,14 +25,13 @@
     <para>
       polkit provides an authorization API intended to be used by
       privileged programs (<quote>MECHANISMS</quote>) offering service
-      to unprivileged programs (<quote>SUBJECTS</quote>) through some
-      form of IPC mechanism such as D-Bus or Unix pipes. In this
+      to unprivileged programs (<quote>SUBJECTS</quote>) often through
+      some form of inter-process communication mechanism. In this
       scenario, the mechanism typically treats the subject as
       untrusted. For every request from a subject, the mechanism needs
       to determine if the request is authorized or if it should refuse
       to service the subject. Using the polkit APIs, a mechanism can
-      offload this decision to a trusted party: The polkit
-      Authority.
+      offload this decision to a trusted party: The polkit Authority.
     </para>
 
     <para>
@@ -52,11 +51,10 @@
       <emphasis>Authority</emphasis> (implemented as a service on the
       system message bus) and an <emphasis>Authentication
       Agent</emphasis> per user session (provided and started by the
-      user's graphical environment, for example <ulink
-      url="http://www.gnome.org/">GNOME</ulink>). <emphasis>Actions</emphasis>
-      are defined by applications and vendors, sites and system
+      user's graphical environment). <emphasis>Actions</emphasis> are
+      defined by applications. Vendors, sites and system
       administrators can control authorization policy through
-      <emphasis>Authorization Rules</emphasis>
+      <emphasis>Authorization Rules</emphasis>.
     </para>
     <mediaobject id="polkit-architecture">
       <imageobject>
commit f3ea405c1f8833bd8e6f8ebd6d46be59aea85826
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 13:51:18 2012 -0400

    docs: update SEE ALSO to make each man page point to all other man pages
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/pkaction.xml b/docs/man/pkaction.xml
index b76711f..5957315 100644
--- a/docs/man/pkaction.xml
+++ b/docs/man/pkaction.xml
@@ -92,10 +92,11 @@
   <refsect1 id="pkaction-see-also">
     <title>SEE ALSO</title>
     <para>
-      <link linkend=""><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/pkcheck.xml b/docs/man/pkcheck.xml
index 971fa3e..fc54054 100644
--- a/docs/man/pkcheck.xml
+++ b/docs/man/pkcheck.xml
@@ -204,6 +204,7 @@ KEY3=VALUE3
     <title>SEE ALSO</title>
     <para>
       <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
       <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml
index 3d95cd2..d84aa1d 100644
--- a/docs/man/pkexec.xml
+++ b/docs/man/pkexec.xml
@@ -210,10 +210,11 @@
   <refsect1 id="pkexec-see-also">
     <title>SEE ALSO</title>
     <para>
-      <link linkend=""><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
-      <link linkend=""><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/pkttyagent.xml b/docs/man/pkttyagent.xml
index 1c264d0..fc3383a 100644
--- a/docs/man/pkttyagent.xml
+++ b/docs/man/pkttyagent.xml
@@ -147,6 +147,7 @@
     <title>SEE ALSO</title>
     <para>
       <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
       <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
       <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 94e52c0..8342d54 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -60,6 +60,10 @@
     <title>SEE ALSO</title>
     <para>
       <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
commit 98f2fe360a41633d97e22c7db19feb3dbbd24961
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 13:47:32 2012 -0400

    docs: enclose local <citerefentry> in <link> to make links work
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/pkaction.xml b/docs/man/pkaction.xml
index f22cecf..b76711f 100644
--- a/docs/man/pkaction.xml
+++ b/docs/man/pkaction.xml
@@ -92,18 +92,10 @@
   <refsect1 id="pkaction-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
+      <link linkend=""><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/pkcheck.xml b/docs/man/pkcheck.xml
index fa5a3b6..971fa3e 100644
--- a/docs/man/pkcheck.xml
+++ b/docs/man/pkcheck.xml
@@ -165,9 +165,7 @@ KEY3=VALUE3
       to check for authorization when using the <option>--process</option> option.
       The value of <replaceable>pid-start-time</replaceable>
       can be determined by consulting e.g. the
-      <citerefentry>
-        <refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum>
-      </citerefentry>
+      <citerefentry><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>
       file system depending on the operating system. If only <replaceable>pid</replaceable>
       is passed to the <option>--process</option> option, then <command>pkcheck</command>
       will look up the start time itself but note that this may be racy.
@@ -205,18 +203,10 @@ KEY3=VALUE3
   <refsect1 id="pkcheck-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml
index af6b499..3d95cd2 100644
--- a/docs/man/pkexec.xml
+++ b/docs/man/pkexec.xml
@@ -210,18 +210,10 @@
   <refsect1 id="pkexec-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
+      <link linkend=""><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend=""><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/pkttyagent.xml b/docs/man/pkttyagent.xml
index a5bab8a..1c264d0 100644
--- a/docs/man/pkttyagent.xml
+++ b/docs/man/pkttyagent.xml
@@ -119,9 +119,7 @@
       using the <option>--process</option> option.  The value of
       <replaceable>pid-start-time</replaceable> can be determined by
       consulting e.g. the
-      <citerefentry>
-        <refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum>
-      </citerefentry>
+      <citerefentry><refentrytitle>proc</refentrytitle><manvolnum>5</manvolnum></citerefentry>
       file system depending on the operating system. If only <replaceable>pid</replaceable>
       is passed to the <option>--process</option> option, then <command>pkttyagent</command>
       will look up the start time itself but note that this may be racy.
@@ -148,18 +146,10 @@
   <refsect1 id="pkttyagent-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>,
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index ad688a5..0d560dc 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -114,7 +114,7 @@ System Context         |                        |
       url="https://live.gnome.org/GObjectIntrospection">GObjectIntrospection</ulink>
       support such as Javascript and Python.  A mechanism can also use
       the D-Bus API or the
-      <citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
       command to check authorizations. The
       <literal>libpolkit-agent-1</literal> library provides an
       abstraction of the native authentication system, e.g.
@@ -199,7 +199,7 @@ System Context         |                        |
       them. Such applications may use the <link
       linkend="PolkitAgentTextListener-struct">PolkitAgentTextListener</link>
       type or the
-      <citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
       helper so the user can authenticate using a textual interface.
     </para>
   </refsect1>
@@ -417,7 +417,7 @@ System Context         |                        |
     </para>
     <para>
       To list installed polkit actions, use the
-      <citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
       command.
     </para>
 
@@ -427,7 +427,7 @@ System Context         |                        |
         The <literal>org.freedesktop.policykit.exec.path</literal>
         annotation is used by the <command>pkexec</command> program
         shipped with polkit - see the
-        <citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
         man page for details.
       </para>
       <para>
@@ -690,8 +690,7 @@ System Context         |                        |
         functions is an object with more information about the action
         being checked. It is of type <type>Details</type> and has
         details being set by the mechanism as attributes. For example,
-        the <link
-        linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+        the <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
         mechanism sets the details <literal>user</literal>,
         <literal>program</literal> and <literal>command_line</literal>
         which can be obtained through e.g. the following JavaScript
@@ -789,21 +788,11 @@ polkit.addRule(function(action, subject, details) {
   <refsect1 id="polkit-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>
-      <citerefentry>
-        <refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>,
-      <citerefentry>
-        <refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
+      <link linkend="polkitd.8"><citerefentry><refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
+      <link linkend="pkaction.1"><citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkcheck.1"><citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>,
+      <link linkend="pkttyagent.1"><citerefentry><refentrytitle>pkttyagent</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 065bdf6..94e52c0 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -59,9 +59,7 @@
   <refsect1 id="polkitd-see-also">
     <title>SEE ALSO</title>
     <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>
+      <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link>
     </para>
   </refsect1>
 </refentry>
commit baedc80e03146957964a2c7804381b9270fb8b8f
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 13:38:51 2012 -0400

    Update docs
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am
index b71c1d2..86e1532 100644
--- a/docs/man/Makefile.am
+++ b/docs/man/Makefile.am
@@ -6,7 +6,6 @@ if MAN_PAGES_ENABLED
 man_MANS = 				\
 	polkit.8			\
 	polkitd.8			\
-	pklocalauthority.8		\
 	pkexec.1			\
 	pkcheck.1			\
 	pkaction.1			\
@@ -21,7 +20,6 @@ endif # MAN_PAGES_ENABLED
 EXTRA_DIST = 				\
 	polkit.xml                 	\
 	polkitd.xml			\
-	pklocalauthority.xml		\
 	pkexec.xml			\
 	pkcheck.xml			\
 	pkaction.xml			\
diff --git a/docs/man/pkaction.xml b/docs/man/pkaction.xml
index 24c156f..f22cecf 100644
--- a/docs/man/pkaction.xml
+++ b/docs/man/pkaction.xml
@@ -56,7 +56,7 @@
     <title>DESCRIPTION</title>
     <para>
       <command>pkaction</command> is used to obtain information about registered
-      PolicyKit actions. If called with <option>--action-id</option> then all
+      polkit actions. If called with <option>--action-id</option> then all
       actions are displayed. Otherwise the action <replaceable>action</replaceable>.
       If called without the <option>--verbose</option> option only the name
       of the action is shown. Otherwise details about the actions are shown.
diff --git a/docs/man/pkcheck.xml b/docs/man/pkcheck.xml
index 6b8a874..fa5a3b6 100644
--- a/docs/man/pkcheck.xml
+++ b/docs/man/pkcheck.xml
@@ -103,7 +103,7 @@
       temporary authorizations for the current session.
     </para>
     <para>
-      This command is a simple wrapper around the PolicyKit D-Bus interface; see the
+      This command is a simple wrapper around the polkit D-Bus interface; see the
       D-Bus interface documentation for details.
     </para>
   </refsect1>
@@ -176,7 +176,7 @@ KEY3=VALUE3
 
   <refsect1 id="pkcheck-auth-agent"><title>AUTHENTICATION AGENT</title>
     <para>
-      <command>pkcheck</command>, like any other PolicyKit
+      <command>pkcheck</command>, like any other polkit
       application, will use the authentication agent registered for
       the process in question. However, if no authentication agent is
       available, then <command>pkcheck</command> can register its own
diff --git a/docs/man/pkexec.xml b/docs/man/pkexec.xml
index 1734033..af6b499 100644
--- a/docs/man/pkexec.xml
+++ b/docs/man/pkexec.xml
@@ -70,12 +70,12 @@
 
   <refsect1 id="pkexec-auth-agent"><title>AUTHENTICATION AGENT</title>
     <para>
-      <command>pkexec</command>, like any other PolicyKit application,
+      <command>pkexec</command>, like any other polkit application,
       will use the authentication agent registered for the calling
-      process. However, if no authentication agent is available, then
-      <command>pkexec</command> will register its own textual
-      authentication agent. This behavior can be turned off by passing
-      the <option>--disable-internal-agent</option> option.
+      process or session. However, if no authentication agent is
+      available, then <command>pkexec</command> will register its own
+      textual authentication agent. This behavior can be turned off by
+      passing the <option>--disable-internal-agent</option> option.
     </para>
   </refsect1>
 
@@ -86,39 +86,8 @@
       <xref linkend="pkexec-required-authz"/>) requires administrator
       authentication. In addition, the authentication dialog presented
       to the user will display the full path to the program to be
-      executed so the user is aware of what will happen:
+      executed so the user is aware of what will happen.
     </para>
-    <mediaobject id="pkexec-bash">
-      <imageobject>
-        <imagedata fileref="pkexec-bash.png" format="PNG"/>
-      </imageobject>
-      <textobject>
-        <programlisting><![CDATA[
-+----------------------------------------------------------+
-|                     Authenticate                     [X] |
-+----------------------------------------------------------+
-|                                                          |
-|  [Icon]  Authentication is needed to run `/bin/bash'     |
-|          as the super user                               |
-|                                                          |
-|          An application is attempting to perform an      |
-|          action that requires privileges. Authentication |
-|          as the super user is required to perform this   |
-|          action.                                         |
-|                                                          |
-|          Password for root: [_________________________]  |
-|                                                          |
-| [V] Details:                                             |
-|  Command: /bin/bash                                      |
-|  Run As:  Super User (root)                              |
-|  Action:  org.freedesktop.policykit.exec                 |
-|  Vendor:  The PolicyKit Project                          |
-|                                                          |
-|                                  [Cancel] [Authenticate] |
-+----------------------------------------------------------+
-]]></programlisting>
-      </textobject>
-    </mediaobject>
     <para>
       The environment that <replaceable>PROGRAM</replaceable> will run
       it, will be set to a minimal known and safe environment in order
@@ -127,7 +96,7 @@
       mechanisms. In addition the <literal>PKEXEC_UID</literal>
       environment variable is set to the user id of the process
       invoking <command>pkexec</command>. As a
-      result, <command>pkexec</command> will not allow you to run
+      result, <command>pkexec</command> will not by default allow you to run
       X11 applications as another user since
       the <literal>$DISPLAY</literal> and <literal>$XAUTHORITY</literal>
       environment variables are not set. These two variables will be retained
@@ -135,106 +104,7 @@
       on an action is set to a nonempty value; this is discouraged, though, and
       should only be used for legacy programs.
     </para>
-  </refsect1>
 
-  <refsect1 id="pkexec-required-authz"><title>REQUIRED AUTHORIZATIONS</title>
-    <para>
-      By default,
-      the <emphasis>org.freedesktop.policykit.exec</emphasis>
-      authorization is required unless an action definition file is
-      present for the program in question. To require another
-      authorization, it can be specified using the <emphasis>org.freedesktop.policykit.exec.path</emphasis> annotation on an action (See <xref linkend="pkexec-example"/> for details).
-    </para>
-  </refsect1>
-
-  <refsect1 id="pkexec-example"><title>EXAMPLE</title>
-    <para>
-      To specify what kind of authorization is needed to execute the
-      program <filename>/usr/bin/pk-example-frobnicate</filename> as
-      another user, simply write an action definition file like this
-    </para>
-    <programlisting>
-<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../src/examples/org.freedesktop.policykit.examples.pkexec.policy"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
-    <para>
-      and drop it in the
-      <filename>/usr/share/polkit-1/actions</filename> directory under
-      a suitable name (e.g. matching the namespace of the action).
-      Note that in addition to specifying the program, the
-      authentication message, description, icon and defaults can be
-      specified. Note that occurences of the strings
-      <literal>$(user)</literal>, <literal>$(program)</literal> and
-      <literal>$(command_line)</literal> in the message will be
-      replaced with respectively the user (of the form "Real Name
-      (username)" or just "username" if there is no real name for the
-      username), the binary to execute (a fully-qualified path,
-      e.g. "<literal>/usr/bin/pk-example-frobnicate</literal>") and
-      the command-line, e.g. "<literal>pk-example-frobnicate foo
-      bar</literal>". For example, for the action defined above, the
-      following authentication dialog will be shown:
-    </para>
-    <mediaobject id="pkexec-frobnicate">
-      <imageobject>
-        <imagedata fileref="pkexec-frobnicate.png" format="PNG"/>
-      </imageobject>
-      <textobject>
-        <programlisting><![CDATA[
-+----------------------------------------------------------+
-|                     Authenticate                     [X] |
-+----------------------------------------------------------+
-|                                                          |
-|  [Icon]  Authentication is required to run the PolicyKit |
-|          example program Frobnicate                      |
-|                                                          |
-|          An application is attempting to perform an      |
-|          action that requires privileges. Authentication |
-|          is required to perform this action.             |
-|                                                          |
-|          Password: [__________________________________]  |
-|                                                          |
-| [V] Details:                                             |
-|  Command: /usr/bin/pk-example-frobnicate                 |
-|  Run As:  Super User (root)                              |
-|  Action:  org.fd.pk.example.pkexec.run-frobnicate        |
-|  Vendor:  Examples for the PolicyKit Project             |
-|                                                          |
-|                                  [Cancel] [Authenticate] |
-+----------------------------------------------------------+
-]]></programlisting>
-      </textobject>
-    </mediaobject>
-    <para>
-      If the user is using the <literal>da_DK</literal> locale, the
-      dialog looks like this:
-    </para>
-    <mediaobject id="pkexec-frobnicate-da">
-      <imageobject>
-        <imagedata fileref="pkexec-frobnicate-da.png" format="PNG"/>
-      </imageobject>
-      <textobject>
-        <programlisting><![CDATA[
-+----------------------------------------------------------+
-|                     Autorisering                     [X] |
-+----------------------------------------------------------+
-|                                                          |
-|  [Icon]  Autorisering er påkrævet for at afvikle         |
-|          PolicyKit eksemplet Frobnicate                  |
-|                                                          |
-|          Et program forsøger at udføre en handling der   |
-|          kræver privilegier. Autorisering er påkrævet.   |
-|                                                          |
-|          Kodeord: [___________________________________]  |
-|                                                          |
-| [V] Detaljer:                                            |
-|  Bruger:   Super User (root)                             |
-|  Program:  /usr/bin/pk-example-frobnicate                |
-|  Handling: org.fd.pk.example.pkexec.run-frobnicate       |
-|  Vendor:   Examples for the PolicyKit Project            |
-|                                                          |
-|                                [Annullér] [Autorisering] |
-+----------------------------------------------------------+
-]]></programlisting>
-      </textobject>
-    </mediaobject>
     <para>
       Note that <command>pkexec</command> does no validation of
       the <replaceable>ARGUMENTS</replaceable> passed
@@ -244,17 +114,82 @@
       since if the user is an administrator he might as well just
       run <command>pkexec bash</command> to get root.
     </para>
+
     <para>
       However, if an action is used for which the user can retain
-      authorization (or if the user is implicitly authorized), such as
-      with <filename>pk-example-frobnicate</filename> above, this
+      authorization (or if the user is implicitly authorized) this
       could be a security hole. Therefore, as a rule of thumb,
       programs for which the default required authorization is
-      changed, should never implicitly trust user input (e.g. like any
+      changed, should <emphasis role='strong'>never</emphasis> implicitly trust user input (e.g. like any
       other well-written <emphasis>suid</emphasis> program).
     </para>
   </refsect1>
 
+  <refsect1 id="pkexec-required-authz"><title>REQUIRED AUTHORIZATIONS</title>
+    <para>
+      By default, the
+      <emphasis>org.freedesktop.policykit.exec</emphasis> action is
+      used. To use another action, use the
+      <emphasis>org.freedesktop.policykit.exec.path</emphasis>
+      annotation on an action with the value set to the full path of
+      the program. In addition to specifying the program, the
+      authentication message, description, icon and defaults can be
+      specified. The strings <literal>$(user)</literal>,
+      <literal>$(program)</literal> and
+      <literal>$(command_line)</literal> in the message will be
+      expanded, see <xref linkend="pkexec-variables"/>.
+    </para>
+  </refsect1>
+
+  <refsect1 id="pkexec-variables"><title>VARIABLES</title>
+    <para>
+      The following variables are set by
+      <command>pkexec</command>. They can be used in authorization
+      rules and messages shown in authentication dialogs:
+    </para>
+
+    <variablelist>
+      <varlistentry>
+        <term><emphasis>program</emphasis></term>
+        <listitem>
+          <para>
+            Fully qualified path to the program to be executed.
+            Example: <quote>/bin/cat</quote>
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><emphasis>command_line</emphasis></term>
+        <listitem>
+          <para>
+            The requested command-line (do not use this for any
+            security checks, it is not secure).
+            Example: <quote>cat /srv/xyz/foobar</quote>
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><emphasis>user</emphasis></term>
+        <listitem>
+          <para>
+            The user name of the user to execute the program as.
+            Example: <quote>davidz</quote>
+          </para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><emphasis>user_full</emphasis></term>
+        <listitem>
+          <para>
+            The full name of the user to execute the program as.
+            Example: <quote>David Zeuthen</quote>
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+
+  </refsect1>
+
   <refsect1 id="pkexec-author"><title>AUTHOR</title>
     <para>
       Written by David Zeuthen <email>davidz at redhat.com</email> with
diff --git a/docs/man/pklocalauthority.xml b/docs/man/pklocalauthority.xml
deleted file mode 100644
index a03a434..0000000
--- a/docs/man/pklocalauthority.xml
+++ /dev/null
@@ -1,471 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY version SYSTEM "../version.xml">
-]>
-<refentry id="pklocalauthority.8">
-  <refentryinfo>
-    <title>pklocalauthority</title>
-    <date>May 2009</date>
-    <productname>polkit</productname>
-  </refentryinfo>
-
-  <refmeta>
-    <refentrytitle>pklocalauthority</refentrytitle>
-    <manvolnum>8</manvolnum>
-    <refmiscinfo class="version"></refmiscinfo>
-  </refmeta>
-
-  <refnamediv>
-    <refname>pklocalauthority</refname>
-    <refpurpose>PolicyKit Local Authority</refpurpose>
-  </refnamediv>
-
-  <refsect1 id="pklocalauthority-description">
-    <title>DESCRIPTION</title>
-    <para>
-      The Local Authority is the default PolicyKit authority
-      implementation. Configuration for the Local Authority and
-      information pertaining to authorization decisions are read from
-      local files on the disk. One design goal of the Local Authority
-      is to split configuration items into separate files such that
-      3rd party packages and users won't conflict trying to edit the
-      same files. This policy also ensures smooth upgrades when
-      distributing PolicyKit using a package management system.
-    </para>
-    <para>
-      Files shipped with PolicyKit and 3rd party packages (e.g. under
-      package manager control) typically have comments (such
-      as <quote>DO NOT EDIT THIS FILE, it will be overwritten on
-      update</quote>) telling the system administrator that changes
-      will be overwritten on update.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-admin-authentication">
-    <title>ADMINISTRATOR AUTHENTICATION</title>
-    <para>
-      PolicyKit makes a distinction between <emphasis>user
-      authentication</emphasis> (to make the user in front of the
-      system prove he really is the user) and <emphasis>administrator
-      authentication</emphasis> (to make the user in front of the
-      system prove he really is an administrator). Since various
-      operating systems (or even flavors of the same operating system)
-      has different ways of defining "administrator", the Local
-      Authority provides a way to specify what "administrator
-      authentication" means.
-    </para>
-    <para>
-      By default, "administrator authentication" is defined as asking
-      for the root password. Since some systems, for usability
-      reasons, don't have a root password and instead rely on a group
-      of users being member of an administrative group that gives them
-      super-user privileges, the Local Authority can be configured to
-      support this use-case as well.
-    </para>
-    <para>
-      Configuration for the Local Authority is read from files in
-      the <filename>/etc/polkit-1/localauthority.conf.d</filename>
-      directory. All files are read in lexigraphical order (using the
-      C locale) meaning that later files can override earlier
-      ones. The file <filename>50-localauthority.conf</filename>
-      contains the settings provided by the OS vendor. Users and 3rd
-      party packages can drop configuration files with a priority
-      higher than 60 to change the defaults. The configuration file
-      format is simple. Each configuration file is a <emphasis>key
-      file</emphasis> (also commonly known as a <emphasis>ini
-      file</emphasis>) with a single group
-      called <literal>[Configuration]</literal>.  Only a single
-      key, <literal>AdminIdentities</literal> is read.  The value of
-      this key is a semi-colon separated list of identities that can
-      be used when administrator authentication is required. Users are
-      specified by prefixing the user name with
-      <literal>unix-user:</literal>, groups of users are specified by 
-      prefixing with <literal>unix-group:</literal>, and netgroups of
-      users are specified with <literal>unix-netgroup:</literal>. See
-      <xref linkend="pklocalauthority-examples"/> for an example of a
-      configuration file.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-directory-structure">
-    <title>DIRECTORY STRUCTURE</title>
-    <para>
-      The Local Authority reads files with <filename>.pkla</filename>
-      extension from all directories located inside the
-      <filename>/etc/polkit-1/localauthority</filename>
-      and <filename>/var/lib/polkit-1/localauthority</filename>
-      directories. By default, the following sub-directories are installed.
-    </para>
-    <programlisting>
-/etc/polkit-1/
-`-- localauthority
-    |-- 10-vendor.d
-    |-- 20-org.d
-    |-- 30-site.d
-    |-- 50-local.d
-    `-- 90-mandatory.d
-    </programlisting>
-    <para>
-      and
-    </para>
-    <programlisting>
-/var/lib/polkit-1/
-`-- localauthority
-    |-- 10-vendor.d
-    |-- 20-org.d
-    |-- 30-site.d
-    |-- 50-local.d
-    `-- 90-mandatory.d
-    </programlisting>
-    <para>
-      The <filename>/etc/polkit-1/localauthority</filename> hierarchy
-      is inteded for local configuration and
-      the <filename>/var/lib/polkit-1/localauthority</filename> is
-      intended for 3rd party packages.
-    </para>
-    <para>
-      Each <filename>.pkla</filename> file contains one or more
-      authorization entries. If the underlying filesystem supports
-      file monitoring, the Local Authority will reload information
-      whenever <filename>.pkla</filename> files are added, removed or
-      changed.
-    </para>
-    <para>
-      Each directory is intended for a specific audience
-    </para>
-    <variablelist>
-      <varlistentry>
-        <term><emphasis>10-vendor.d</emphasis></term>
-        <listitem>
-          <para>
-            Intended for use by the OS vendor.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>20-org.d</emphasis></term>
-        <listitem>
-          <para>
-            Intended for the organization deploying the OS.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>30-site.d</emphasis></term>
-        <listitem>
-          <para>
-            Intended for the site deploying the system.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>50-local.d</emphasis></term>
-        <listitem>
-          <para>
-            Intended for local usage.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>90-mandatory.d</emphasis></term>
-        <listitem>
-          <para>
-            Intended for the organization deploying the OS.
-          </para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-    <para>
-      and new directories can be added/removed as needed.
-    </para>
-    <para>
-      As to regards to the content, each <filename>.pkla</filename>
-      file is a standard <emphasis>key file</emphasis> and contains
-      key/value pairs in one or more groups with each group
-      representing an authorization entry.
-      A <filename>.pkla</filename> file MUST be named by using a
-      scheme to ensure that the name is unique, e.g. reverse DNS
-      notation or similar. For example, if the organization is
-      <quote>Acme Corp</quote> needs to modify policy for the
-      product <quote>Frobnicator</quote>, a name
-      like <filename>com.acme.frobnicator.pkla</filename> would be
-      suitable.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-authorization-entry">
-    <title>AUTHORIZATION ENTRY</title>
-    <para>
-      Each group in a <filename>.pkla</filename> file must have a name
-      that is unique within the file it belongs to. The following keys
-      are are recognized:
-    </para>
-    <variablelist>
-      <varlistentry>
-        <term><emphasis>Identity</emphasis></term>
-        <listitem>
-          <para>
-            A semi-colon separated list of globs to match identities. Each glob
-            should start with <literal>unix-user:</literal> or
-            <literal>unix-group:</literal> to specify whether to match on a
-            UNIX user name or a UNIX group name. Netgroups are supported with
-            the <literal>unix-netgroup:</literal> prefix, but cannot support
-            glob syntax.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>Action</emphasis></term>
-        <listitem>
-          <para>
-            A semi-colon separated list of globs to match action identifiers.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>ResultActive</emphasis></term>
-        <listitem>
-          <para>
-            The result to return for subjects in an active local
-            session that matches one or more of the given identities.
-            Allowed values are similar to what can be used in
-            the <emphasis>defaults</emphasis> section
-            of <filename>.policy</filename> files used to define
-            actions, e.g.
-            <literal>yes</literal>,
-            <literal>no</literal>,
-            <literal>auth_self</literal>,
-            <literal>auth_self_keep</literal>,
-            <literal>auth_admin</literal> and
-            <literal>auth_admin_keep</literal>.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>ResultInactive</emphasis></term>
-        <listitem>
-          <para>
-            Like <emphasis>ResultActive</emphasis> but instead applies
-            to subjects in inactive local sessions.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>ResultAny</emphasis></term>
-        <listitem>
-          <para>
-            Like <emphasis>ResultActive</emphasis> but instead applies
-            to any subject.
-          </para>
-        </listitem>
-      </varlistentry>
-      <varlistentry>
-        <term><emphasis>ReturnValue</emphasis></term>
-        <listitem>
-          <para>
-            A semi-colon separated list of key/value pairs (of the
-            form key=value) that are added to the details of
-            authorization result on positive matches.
-          </para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-    <para>
-      All keys specified above are required except that only at least
-      one
-      of <emphasis>ResultAny</emphasis>, <emphasis>ResultInactive</emphasis>
-      and <emphasis>ResultActive</emphasis> must
-      be present. The <emphasis>ReturnValue</emphasis> key is optional.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-evaluation-order">
-    <title>EVALUATION ORDER</title>
-    <para>
-      When a Mechanism requests services from the Authority to check
-      if a given Subject is authorized for a given Action, the
-      authorization entries discussed above are consulted using the
-      following algorithm.
-    </para>
-    <para>
-      The authorization entries from all .pkla files are ordered using
-      the following rules. First all the basename of all
-      sub-directories (e.g. <emphasis>30-site.d</emphasis>) from both
-      the <filename>/etc/polkit-1/localauthority</filename>
-      and <filename>/var/lib/polkit-1/localauthority</filename>
-      directories are enumerated and sorted (using the C locale). If a
-      name exists in both <filename>/etc</filename>
-      and <filename>/var</filename>, the one
-      in <filename>/etc</filename> takes precedence. Then
-      all <filename>.pkla</filename> files are read in order from this
-      list of sub-directories. For each <filename>.pkla</filename>
-      file, authorizations from each file are appended in order resulting
-      in an ordered list of authorization entries.
-    </para>
-    <para>
-      For example, given the following files
-    </para>
-    <programlisting>
-/var/lib/polkit-1
-└── localauthority
-    ├── 10-vendor.d
-    │   └── 10-desktop-policy.pkla
-    ├── 20-org.d
-    ├── 30-site.d
-    ├── 50-local.d
-    ├── 55-org.my.company.d
-    │   └── 10-org.my.company.product.pkla
-    └── 90-mandatory.d
-
-/etc/polkit-1
-└── localauthority
-    ├── 10-vendor.d
-    │   └── 01-some-changes-from-a-subvendor.pkla
-    ├── 20-org.d
-    ├── 30-site.d
-    ├── 50-local.d
-    ├── 55-org.my.company.d
-    │   └── 10-org.my.company.product.pkla
-    └── 90-mandatory.d
-    </programlisting>
-    <para>
-      the evaluation order of the <filename>.pkla</filename> files is:
-    </para>
-    <orderedlist>
-      <listitem>
-	<para>
-          <filename>10-desktop-policy.pkla</filename>
-        </para>
-      </listitem>
-      <listitem>
-	<para>
-          <filename>01-some-changes-from-a-subvendor.pkla</filename>
-        </para>
-      </listitem>
-      <listitem>
-	<para>
-          <filename>10-org.my.company.product.pkla</filename> (the <filename>/var</filename> one)
-        </para>
-      </listitem>
-      <listitem>
-	<para>
-          <filename>10-org.my.company.product.pkla</filename> (the <filename>/etc</filename> one)
-        </para>
-      </listitem>
-    </orderedlist>
-    <para>
-      When the list of authorization entries has been calculated, the
-      authorization check can be made. First, the user of the Subject
-      is determined and the groups that the user belongs are looked
-      up. For each group identity, the authorization entries are
-      consulted in order. If the authorization check matches the data
-      from the authorization check, then the authorization result
-      from <emphasis>RequireAny</emphasis>, <emphasis>RequireInactive</emphasis>
-      or <emphasis>RequireActive</emphasis> is used
-      and <emphasis>ReturnValue</emphasis> is added to the
-      authorization result.
-    </para>
-    <para>
-      Finally, the authorization entries are consulted using the user
-      identity in the same manner.
-    </para>
-    <para>
-      Note that processing continues even after a match. This allows
-      for socalled <quote>negative authorizations</quote>, see
-      <xref linkend="pklocalauthority-examples"/> for further
-      discussion.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-examples">
-    <title>EXAMPLES</title>
-    <para>
-      The following <filename>.conf</filename> file
-    </para>
-    <programlisting>
-[Configuration]
-AdminIdentities=unix-group:staff
-    </programlisting>
-    <para>
-      specifies that any user in the <literal>staff</literal> UNIX
-      group can be used for authentication when administrator
-      authentication is needed. This file would typically be installed
-      in the <filename>/etc/polkit-1/localauthority.conf.d</filename>
-      directory and given the
-      name <filename>60-desktop-policy.conf</filename> to ensure that
-      it is evaluted after
-      the <filename>50-localauthority.conf</filename> file shipped
-      with PolicyKit. If the local administrator wants to override this (suppose <filename>60-desktop-policy.conf</filename> was shipped as part of the OS) he can simply create a file <filename>99-my-admin-configuration.conf</filename> with the following content
-    </para>
-    <programlisting>
-[Configuration]
-AdminIdentities=unix-user:lisa;unix-user:marge
-    </programlisting>
-    <para>
-      to specify that only the users <literal>lisa</literal>
-      and <literal>marge</literal> can authenticate when
-      administrator authentication is needed.
-    </para>
-    <para>
-      The following <filename>.pkla</filename> file grants
-      authorization to all users in the <literal>staff</literal> group
-      for actions matching the
-      glob <literal>com.example.awesomeproduct.*</literal> provided
-      they are in an active session on the local console:
-    </para>
-    <programlisting>
-[Normal Staff Permissions]
-Identity=unix-group:staff
-Action=com.example.awesomeproduct.*
-ResultAny=no
-ResultInactive=no
-ResultActive=yes
-    </programlisting>
-    <para>
-      If the users <literal>homer</literal> and <literal>grimes</literal> are member of
-      the <literal>staff</literal> group but policy requires that an
-      administrator needs to authenticate every time authorization for
-      any action
-      matching <literal>com.example.awesomeproduct.*</literal> is
-      required, one would add
-    </para>
-    <programlisting>
-[Exclude Some Problematic Users]
-Identity=unix-user:homer;unix-user:grimes
-Action=com.example.awesomeproduct.*
-ResultAny=no
-ResultInactive=no
-ResultActive=auth_admin
-    </programlisting>
-    <para>
-      and make sure this authorization entry is after the first one.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-author"><title>AUTHOR</title>
-    <para>
-      Written by David Zeuthen <email>davidz at redhat.com</email> with
-      a lot of help from many others.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-bugs">
-    <title>BUGS</title>
-    <para>
-      Please send bug reports to either the distribution or the
-      polkit-devel mailing list,
-      see the link <ulink url="http://lists.freedesktop.org/mailman/listinfo/polkit-devel"/>
-      on how to subscribe.
-    </para>
-  </refsect1>
-
-  <refsect1 id="pklocalauthority-see-also">
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>
-    </para>
-  </refsect1>
-</refentry>
diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 6ec15ac..ad688a5 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -18,25 +18,25 @@
 
   <refnamediv>
     <refname>polkit</refname>
-    <refpurpose>Authorization Framework</refpurpose>
+    <refpurpose>Authorization Manager</refpurpose>
   </refnamediv>
 
   <refsect1 id="polkit-overview"><title>OVERVIEW</title>
     <para>
-      PolicyKit provides an authorization API intended to be used by
+      polkit provides an authorization API intended to be used by
       privileged programs (<quote>MECHANISMS</quote>) offering service
-      to unprivileged programs (<quote>CLIENTS</quote>) through some
+      to unprivileged programs (<quote>SUBJECTS</quote>) through some
       form of IPC mechanism such as D-Bus or Unix pipes. In this
-      scenario, the mechanism typically treats the client as
-      untrusted. For every request from a client, the mechanism needs
+      scenario, the mechanism typically treats the subject as
+      untrusted. For every request from a subject, the mechanism needs
       to determine if the request is authorized or if it should refuse
-      to service the client. Using the PolicyKit API, a mechanism can
-      offload this decision to a trusted party: The PolicyKit
+      to service the subject. Using the polkit APIs, a mechanism can
+      offload this decision to a trusted party: The polkit
       Authority.
     </para>
 
     <para>
-      In addition to acting as an authority, PolicyKit allows users to
+      In addition to acting as an authority, polkit allows users to
       obtain temporary authorization through authenticating either an
       administrative user or the owner of the session the client
       belongs to. This is useful for scenarios where a mechanism needs
@@ -48,15 +48,15 @@
 
   <refsect1 id="polkit-system-architecture"><title>SYSTEM ARCHITECTURE</title>
     <para>
-      The system architecture of PolicyKit is comprised of
-      the <emphasis>Authority</emphasis> (implemented as a service on
-      the system message bus) and a
-      <emphasis>Authentication Agent</emphasis> per user session
-      (provided and started by the user session e.g. GNOME or KDE).
-      Additionally, PolicyKit supports a number of extension points –
-      specifically, vendors and/or sites can write extensions to
-      completely control authorization policy. In a block diagram, the
-      architecture looks like this:
+      The system architecture of polkit is comprised of the
+      <emphasis>Authority</emphasis> (implemented as a service on the
+      system message bus) and an <emphasis>Authentication
+      Agent</emphasis> per user session (provided and started by the
+      user's graphical environment, for example <ulink
+      url="http://www.gnome.org/">GNOME</ulink>). <emphasis>Actions</emphasis>
+      are defined by applications and vendors, sites and system
+      administrators can control authorization policy through
+      <emphasis>Authorization Rules</emphasis>
     </para>
     <mediaobject id="polkit-architecture">
       <imageobject>
@@ -70,9 +70,9 @@
  +-------------------+
  | libpolkit-agent-1 |
  +-------------------+
-        ^                                  +--------+
-        |                                  | Client |
-        +--------------+                   +--------+
+        ^                                  +---------+
+        |                                  | Subject |
+        +--------------+                   +---------+
                        |                        ^
                        |                        |
 User Session           |                        |
@@ -90,49 +90,44 @@ System Context         |                        |
         |                       |      +---------------------+
         V                       +----> | libpolkit-gobject-1 |
 +------------------+                   +---------------------+
-| org.freedesktop. |
-|    PolicyKit1    |
-+------------------+
-|   Backends and   |
-|    Extensions    |
+|    polkitd(8)    |
 +------------------+
+| org.freedesktop. |
+|    PolicyKit1    |<---------+
++------------------+          |
+          ^                   |
+          |            +--------------------------------------+
+          |            | /usr/share/polkit-1/actions/*.policy |
+          |            +--------------------------------------+
+          |
+   +--------------------------------------+
+   | /etc/polkit-1/rules.d/*.rules        |
+   | /usr/share/polkit-1/rules.d/*.rules  |
+   +--------------------------------------+
 ]]></programlisting>
       </textobject>
     </mediaobject>
     <para>
       For convenience, the <literal>libpolkit-gobject-1</literal>
-      library wraps the PolicyKit D-Bus API using GObject. However, a
-      mechanism can also use the D-Bus API or the
+      library wraps the polkit D-Bus API and is usable from any C/C++
+      program as well as higher-level languages <ulink
+      url="https://live.gnome.org/GObjectIntrospection">GObjectIntrospection</ulink>
+      support such as Javascript and Python.  A mechanism can also use
+      the D-Bus API or the
       <citerefentry><refentrytitle>pkcheck</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      command to check authorizations.
-    </para>
-
-    <para>
-      The <literal>libpolkit-agent-1</literal> library provides an
+      command to check authorizations. The
+      <literal>libpolkit-agent-1</literal> library provides an
       abstraction of the native authentication system, e.g.
       <citerefentry><refentrytitle>pam</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       and also facilities registration and communication with the
-      PolicyKit D-Bus service.
-    </para>
-
-    <para>
-      PolicyKit extensions and authority backends are implemented
-      using the
-      <literal>libpolkit-backend-1</literal> library.
-    </para>
-
-    <para>
-      See the
-      <ulink url="file:///usr/share/gtk-doc/html/polkit-1/index.html">developer
-      documentation</ulink> for more information about using and
-      extending PolicyKit.
+      polkit D-Bus service.
     </para>
 
     <para>
-      See
-      <citerefentry><refentrytitle>pklocalauthority</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-      for information about the Local Authority - the default
-      authority implementation shipped with PolicyKit.
+      See the <ulink
+      url="http://www.freedesktop.org/software/polkit/docs/latest/">developer
+      documentation</ulink> for more information about writing polkit
+      applications.
     </para>
   </refsect1>
 
@@ -154,34 +149,25 @@ System Context         |                        |
       <textobject>
         <programlisting><![CDATA[
 +----------------------------------------------------------+
-|                     Authenticate                     [X] |
-+----------------------------------------------------------+
 |                                                          |
-|  [Icon]  Authentication is required to run ATA SMART     |
-|          self tests                                      |
+|  [Icon]  Authentication required                         |
 |                                                          |
-|          An application is attempting to perform an      |
-|          action that requires privileges. Authentication |
-|          as the super user is required to perform this   |
-|          action.                                         |
+|          Authentication is required to format INTEL      |
+|          SSDSA2MH080G1GC (/dev/sda)                      |
 |                                                          |
-|          Password for root: [_________________________]  |
+|          Administrator                                   |
 |                                                          |
-| [V] Details:                                             |
-|  Drive:  ATA INTEL SSDSA2MH08 (045C)                     |
-|  Device: /dev/sda                                        |
-|  Action: org.fd.devicekit.disks.drive-ata-smart-selftest |
-|  Vendor: The DeviceKit Project                           |
+|          Password: [__________________________________]  |
 |                                                          |
-|                                  [Cancel] [Authenticate] |
+| [Cancel]                                  [Authenticate] |
 +----------------------------------------------------------+
 ]]></programlisting>
       </textobject>
     </mediaobject>
     <para>
       If the system is configured without a <emphasis>root</emphasis>
-      account it may allow you to select the administrative user who
-      is authenticating:
+      account it may prompt for a specific user designated as the
+      administrative user:
     </para>
     <mediaobject id="polkit-authentication-agent-example-wheel">
       <imageobject>
@@ -190,41 +176,22 @@ System Context         |                        |
       <textobject>
         <programlisting><![CDATA[
 +----------------------------------------------------------+
-|                     Authenticate                     [X] |
-+----------------------------------------------------------+
 |                                                          |
-|  [Icon]  Authentication is required to run ATA SMART     |
-|          self tests                                      |
+|  [Icon]  Authentication required                         |
 |                                                          |
-|          An application is attempting to perform an      |
-|          action that requires privileges. Authentication |
-|          as one of the users below is required to        |
-|          perform this action.                            |
+|          Authentication is required to format INTEL      |
+|          SSDSA2MH080G1GC (/dev/sda)                      |
 |                                                          |
-|          [[Face] Patrick Bateman (bateman)         [V]]  |
+|          [Icon] David Zeuthen                            |
 |                                                          |
-|          Password for bateman: [______________________]  |
+|          Password: [__________________________________]  |
 |                                                          |
-| [V] Details:                                             |
-|  Drive:  ATA INTEL SSDSA2MH08 (045C)                     |
-|  Device: /dev/sda                                        |
-|  Action: org.fd.devicekit.disks.drive-ata-smart-selftest |
-|  Vendor: The DeviceKit Project                           |
-|                                                          |
-|                                  [Cancel] [Authenticate] |
+| [Cancel]                                  [Authenticate] |
 +----------------------------------------------------------+
 ]]></programlisting>
       </textobject>
     </mediaobject>
     <para>
-      See
-      <citerefentry><refentrytitle>pklocalauthority</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-      on how to set up the local authority
-      implemention for systems without a <literal>root</literal>
-      account.
-    </para>
-
-    <para>
       Applications that do not run under a desktop environment (for
       example, if launched from a
       <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
@@ -240,19 +207,20 @@ System Context         |                        |
   <refsect1 id="polkit-declaring-actions"><title>DECLARING ACTIONS</title>
     <para>
       A mechanism need to declare a set of <quote>ACTIONS</quote> in
-      order to use PolicyKit. Actions correspond to operations that
+      order to use polkit. Actions correspond to operations that
       clients can request the mechanism to carry out and are defined
-      in XML files that the mechanism installs into
-      the <filename>/usr/share/polkit-1/actions</filename> directory.
+      in XML files that the mechanism installs into the <filename
+      class='directory'>/usr/share/polkit-1/actions</filename>
+      directory.
     </para>
 
     <para>
-      PolicyKit actions are namespaced and can only contain the
-      characters <literal>[a-z][0-9].-</literal> e.g. lower-case
-      ASCII, digits, period and hyphen. Each XML file can contain more
-      than one action but all actions need to be in the same namespace
-      and the file needs to be named after the namespace and have the
-      extension <literal>.policy</literal>.
+      polkit actions are namespaced and can only contain the
+      characters <literal>[A-Z][a-z][0-9].-</literal> e.g. ASCII,
+      digits, period and hyphen. Each XML file can contain more than
+      one action but all actions need to be in the same namespace and
+      the file needs to be named after the namespace and have the
+      extension <filename class='extension'>.policy</filename>.
     </para>
 
     <para>
@@ -260,8 +228,8 @@ System Context         |                        |
     </para>
     <programlisting><![CDATA[
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
-"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
+<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
+"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
 ]]></programlisting>
     <para>
       The <emphasis>policyconfig</emphasis> element must be present
@@ -271,50 +239,77 @@ System Context         |                        |
     <variablelist>
       <varlistentry>
         <term><emphasis>vendor</emphasis></term>
-        <listitem><para>The name of the project or vendor that is
-            supplying the actions in the XML
-            document. Optional.</para></listitem>
+        <listitem>
+          <para>
+            The name of the project or vendor that is supplying the
+            actions in the XML document. Optional.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>vendor_url</emphasis></term>
-        <listitem><para>A URL to the project or vendor that is
-        supplying the actions in the XML document.
-        Optional.</para></listitem>
+        <listitem>
+          <para>
+            A URL to the project or vendor that is supplying the
+            actions in the XML document.  Optional.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>icon_name</emphasis></term>
-        <listitem><para>An icon representing the project or vendor
-        that is supplying the actions in the XML document. The icon
-        name must adhere to
-        the <ulink url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Freedesktop.org
-        Icon Naming Specification</ulink>. Optional.</para></listitem>
+        <listitem>
+          <para>
+            An icon representing the project or vendor that is
+            supplying the actions in the XML document. The icon name
+            must adhere to the <ulink
+            url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">Freedesktop.org
+            Icon Naming Specification</ulink>. Optional.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>action</emphasis></term>
-        <listitem><para>Declares an action. The action name is
-        specified using the <literal>id</literal> attribute and can
-        only contain the characters <literal>[a-z][0-9].-</literal>
-        e.g. lower-case ASCII, digits, period and
-        hyphen.</para></listitem>
+        <listitem>
+          <para>
+            Declares an action. The action name is specified using the
+            <literal>id</literal> attribute and can only contain the
+            characters <literal>[A-Z][a-z][0-9].-</literal>
+            e.g. ASCII, digits, period and hyphen.
+          </para>
+        </listitem>
       </varlistentry>
     </variablelist>
     <para>
-      Elements that can be used inside <emphasis>action</emphasis> includes:
+      Elements that can be used inside <emphasis>action</emphasis> include:
     </para>
     <variablelist>
       <varlistentry>
         <term><emphasis>description</emphasis></term>
-        <listitem><para>A human readable description of the action, e.g. <quote>Install unsigned software</quote>.</para></listitem>
+        <listitem>
+          <para>
+            A human readable description of the action,
+            e.g. <quote>Install unsigned software</quote>.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>message</emphasis></term>
-        <listitem><para>A human readable message displayed to the user when asking for credentials when authentication is needed, e.g. <quote>Installing unsigned software requires authentication</quote>.</para></listitem>
+        <listitem>
+          <para>
+            A human readable message displayed to the user when asking
+            for credentials when authentication is needed,
+            e.g. <quote>Installing unsigned software requires
+            authentication</quote>.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>defaults</emphasis></term>
-        <listitem><para>This element is used to specify implicit authorizations for clients.</para>
+        <listitem>
           <para>
-            Elements that can be used inside <emphasis>defaults</emphasis> includes:
+            This element is used to specify implicit authorizations
+            for clients. Elements that can be used inside
+            <emphasis>defaults</emphasis> include:
           </para>
           <variablelist>
             <varlistentry>
@@ -376,74 +371,91 @@ System Context         |                        |
       </varlistentry>
       <varlistentry>
         <term><emphasis>annotate</emphasis></term>
-        <listitem><para>Used for annotating an action with a key/value
-        pair. The key is specified using the
-        the <literal>key</literal> attribute and the value is
-        specified using the <literal>value</literal> attribute. This
-        element may appear zero or more times. See
-            below for known annotations. </para></listitem>
+        <listitem>
+          <para>
+            Used for annotating an action with a key/value pair. The
+            key is specified using the the <literal>key</literal>
+            attribute and the value is specified using the
+            <literal>value</literal> attribute. This element may
+            appear zero or more times. See below for known
+            annotations.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>vendor</emphasis></term>
-        <listitem><para>Used for overriding the vendor on a per-action
-        basis. Optional.</para></listitem>
+        <listitem>
+          <para>
+            Used for overriding the vendor on a per-action
+            basis. Optional.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>vendor_url</emphasis></term>
-        <listitem><para>Used for overriding the vendor URL on a
-        per-action basis. Optional.</para></listitem>
+        <listitem>
+          <para>
+            Used for overriding the vendor URL on a per-action
+            basis. Optional.
+          </para>
+        </listitem>
       </varlistentry>
       <varlistentry>
         <term><emphasis>icon_name</emphasis></term>
-        <listitem><para>Used for overriding the icon name on a
-        per-action basis. Optional.</para></listitem>
+        <listitem>
+          <para>
+            Used for overriding the icon name on a per-action
+            basis. Optional.
+          </para>
+        </listitem>
       </varlistentry>
     </variablelist>
     <para>
-      For localization, <emphasis>description</emphasis>
-      and <emphasis>message</emphasis> elements may occur multiple
-      times with different <literal>xml:lang</literal> attributes.
+      For localization, <emphasis>description</emphasis> and
+      <emphasis>message</emphasis> elements may occur multiple times
+      with different <literal>xml:lang</literal> attributes.
     </para>
     <para>
-      To list installed PolicyKit actions, use the
+      To list installed polkit actions, use the
       <citerefentry><refentrytitle>pkaction</refentrytitle><manvolnum>1</manvolnum></citerefentry>
       command.
     </para>
 
-    <refsect2><title>Known annotations</title>
-    <para>
-      The <literal>org.freedesktop.policykit.exec.path</literal>
-      annotation is used by the <command>pkexec</command> program
-      shipped with PolicyKit - see the
-      <citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-      man page for details.
-    </para>
-    <para>
-      The <literal>org.freedesktop.policykit.imply</literal>
-      annotation (its value is a string containing a space separated
-      list of action identifiers) can be used to define <emphasis>meta
-      actions</emphasis>. The way it works is that if a subject is
-      authorized for an action with this annotation, then it is also
-      authorized for any action specified by the annotation. A typical
-      use of this annotation is when defining an UI shell with a
-      single lock button that should unlock multiple actions from
-      distinct mechanisms.
-    </para>
-    <para>
-      The <literal>org.freedesktop.policykit.owner</literal>
-      annotation can be used to define a set of users who can query
-      whether a client is authorized to perform this action.  If this
-      annotation is not specified then only root can query whether a
-      client running as a different user is authorized for an action.
-      The value of this annotation is a string containing a space
-      separated list of <link
-      linkend="PolkitIdentity-struct">PolkitIdentity</link> entries,
-      for example <literal>"unix-user:42 unix-user:colord"</literal>.
-      A typical use of this annotation is for a daemon process that
-      runs as a system user rather than root.
-    </para>
+    <refsect2>
+      <title>Known annotations</title>
+      <para>
+        The <literal>org.freedesktop.policykit.exec.path</literal>
+        annotation is used by the <command>pkexec</command> program
+        shipped with polkit - see the
+        <citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+        man page for details.
+      </para>
+      <para>
+        The <literal>org.freedesktop.policykit.imply</literal>
+        annotation (its value is a string containing a space separated
+        list of action identifiers) can be used to define
+        <emphasis>meta actions</emphasis>. The way it works is that if
+        a subject is authorized for an action with this annotation,
+        then it is also authorized for any action specified by the
+        annotation. A typical use of this annotation is when defining
+        an UI shell with a single lock button that should unlock
+        multiple actions from distinct mechanisms.
+      </para>
+      <para>
+        The <literal>org.freedesktop.policykit.owner</literal>
+        annotation can be used to define a set of users who can query
+        whether a client is authorized to perform this action.  If
+        this annotation is not specified then only root can query
+        whether a client running as a different user is authorized for
+        an action.  The value of this annotation is a string
+        containing a space separated list of <link
+        linkend="PolkitIdentity-struct">PolkitIdentity</link> entries,
+        for example <literal>"unix-user:42
+        unix-user:colord"</literal>.  A typical use of this annotation
+        is for a daemon process that runs as a system user rather than
+        root.
+      </para>
     </refsect2>
-
   </refsect1>
 
   <refsect1 id="polkit-rules"><title>AUTHORIZATION RULES</title>
@@ -778,9 +790,6 @@ polkit.addRule(function(action, subject, details) {
     <title>SEE ALSO</title>
     <para>
       <citerefentry>
-        <refentrytitle>pklocalauthority</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>
-      <citerefentry>
         <refentrytitle>polkitd</refentrytitle><manvolnum>8</manvolnum>
       </citerefentry>
       <citerefentry>
diff --git a/docs/man/polkitd.xml b/docs/man/polkitd.xml
index 7e5cc02..065bdf6 100644
--- a/docs/man/polkitd.xml
+++ b/docs/man/polkitd.xml
@@ -18,7 +18,7 @@
 
   <refnamediv>
     <refname>polkitd</refname>
-    <refpurpose>PolicyKit daemon</refpurpose>
+    <refpurpose>The polkit system daemon</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
diff --git a/docs/pkexec-bash.png b/docs/pkexec-bash.png
deleted file mode 100644
index b2d2208..0000000
Binary files a/docs/pkexec-bash.png and /dev/null differ
diff --git a/docs/pkexec-frobnicate-da.png b/docs/pkexec-frobnicate-da.png
deleted file mode 100644
index 5c242d4..0000000
Binary files a/docs/pkexec-frobnicate-da.png and /dev/null differ
diff --git a/docs/pkexec-frobnicate.png b/docs/pkexec-frobnicate.png
deleted file mode 100644
index 60050da..0000000
Binary files a/docs/pkexec-frobnicate.png and /dev/null differ
diff --git a/docs/polkit-1-diagrams.svg b/docs/polkit-1-diagrams.svg
index a213bbe..d595ce8 100644
--- a/docs/polkit-1-diagrams.svg
+++ b/docs/polkit-1-diagrams.svg
@@ -14,9 +14,10 @@
    height="1052.3622047"
    id="svg270"
    sodipodi:version="0.32"
-   inkscape:version="0.46+devel"
+   inkscape:version="0.48.2 r9819"
    sodipodi:docname="polkit-1-diagrams.svg"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.1">
   <defs
      id="defs272">
     <marker
@@ -227,7 +228,7 @@
        xlink:href="#linearGradient14609"
        id="linearGradient13600"
        gradientUnits="userSpaceOnUse"
-       gradientTransform="matrix(0.7347995,0,0,0.5175383,193.46355,269.41609)"
+       gradientTransform="matrix(0.7347995,0,0,0.5175383,193.46355,289.41609)"
        x1="52.07793"
        y1="89.181732"
        x2="196.4196"
@@ -352,16 +353,6 @@
          offset="1"
          id="stop28970-9" />
     </linearGradient>
-    <linearGradient
-       y2="89.181732"
-       x2="196.4196"
-       y1="89.181732"
-       x1="52.07793"
-       gradientTransform="matrix(0.73549098,0,0,0.34876094,193.37764,330.54439)"
-       gradientUnits="userSpaceOnUse"
-       id="linearGradient624"
-       xlink:href="#linearGradient28966-4"
-       inkscape:collect="always" />
     <inkscape:perspective
        id="perspective697"
        inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
@@ -514,6 +505,169 @@
        id="linearGradient860"
        xlink:href="#linearGradient28966-4-1-6"
        inkscape:collect="always" />
+    <linearGradient
+       y2="89.181732"
+       x2="196.4196"
+       y1="89.181732"
+       x1="52.07793"
+       gradientTransform="matrix(1.0156707,0,0,0.51700825,362.58942,235.61128)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient782-4"
+       xlink:href="#linearGradient3144-1-7"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3144-1-7">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3146-3-8" />
+      <stop
+         style="stop-color:#898585;stop-opacity:0;"
+         offset="1"
+         id="stop3148-7-7" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3144-1-7"
+       id="linearGradient3982"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.5328769,0,0,0.51700825,256.34481,384.82592)"
+       x1="52.07793"
+       y1="89.181732"
+       x2="196.4196"
+       y2="89.181732" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3144-1-7-5"
+       id="linearGradient3982-1"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.5328769,0,0,0.51700825,256.34481,364.82592)"
+       x1="52.07793"
+       y1="89.181732"
+       x2="196.4196"
+       y2="89.181732" />
+    <linearGradient
+       id="linearGradient3144-1-7-5">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3146-3-8-1" />
+      <stop
+         style="stop-color:#898585;stop-opacity:0;"
+         offset="1"
+         id="stop3148-7-7-5" />
+    </linearGradient>
+    <linearGradient
+       y2="89.181732"
+       x2="196.4196"
+       y1="89.181732"
+       x1="52.07793"
+       gradientTransform="matrix(1.5328769,0,0,0.51700825,173.82749,458.25449)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4001"
+       xlink:href="#linearGradient3144-1-7-5"
+       inkscape:collect="always" />
+    <marker
+       inkscape:stockid="Arrow2Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lstart-7"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1742-4"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(1.1,0,0,1.1,1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1745-4"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lstart-9"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1742-3"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(1.1,0,0,1.1,1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-9"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1745-3"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lstart-73"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path1742-2"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(1.1,0,0,1.1,1.1,0)" />
+    </marker>
+    <linearGradient
+       y2="89.181732"
+       x2="196.4196"
+       y1="89.181732"
+       x1="52.07793"
+       gradientTransform="matrix(0.7361648,0,0,0.2163389,153.65639,99.058497)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient860-3"
+       xlink:href="#linearGradient28966-4-1-6-8"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient28966-4-1-6-8">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop28968-5-1-4-4" />
+      <stop
+         style="stop-color:#9dff9d;stop-opacity:0;"
+         offset="1"
+         id="stop28970-9-7-0-8" />
+    </linearGradient>
+    <linearGradient
+       y2="89.181732"
+       x2="196.4196"
+       y1="89.181732"
+       x1="52.07793"
+       gradientTransform="matrix(0.7361648,0,0,0.2163389,193.24673,277.06866)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3144-3"
+       xlink:href="#linearGradient28966-4-1-6-8"
+       inkscape:collect="always" />
   </defs>
   <sodipodi:namedview
      id="base"
@@ -522,16 +676,17 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="0.7"
-     inkscape:cx="342.5823"
-     inkscape:cy="812.67628"
+     inkscape:zoom="1.4"
+     inkscape:cx="347.45975"
+     inkscape:cy="686.70778"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="false"
-     inkscape:window-width="1024"
-     inkscape:window-height="724"
+     inkscape:window-width="1600"
+     inkscape:window-height="841"
      inkscape:window-x="0"
-     inkscape:window-y="0" />
+     inkscape:window-y="27"
+     inkscape:window-maximized="1" />
   <metadata
      id="metadata275">
     <rdf:RDF>
@@ -555,7 +710,7 @@
        height="54.89323"
        x="192.42352"
        y="51.90543"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <rect
@@ -565,7 +720,7 @@
        height="54.837009"
        x="415.94064"
        y="254.30046"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <rect
@@ -575,7 +730,7 @@
        height="3.3034956"
        x="42.631001"
        y="165.95226"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <rect
@@ -585,7 +740,7 @@
        height="54.89323"
        x="427.33624"
        y="59.769047"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <text
@@ -594,21 +749,21 @@
        x="481.04681"
        y="90.185196"
        id="text7646"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
          x="481.04681"
          y="90.185196"
          id="tspan7654"
-         style="text-align:center;text-anchor:middle">Client</tspan></text>
+         style="text-align:center;text-anchor:middle">Subject</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
        x="243.28027"
        y="77.398422"
        id="text7678"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -627,27 +782,27 @@
        width="105.40086"
        height="54.89323"
        x="232.06105"
-       y="288.12442"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       y="308.12442"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <text
        xml:space="preserve"
        style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
        x="286.21173"
-       y="312.54059"
+       y="332.54059"
        id="text13586"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
          x="286.21173"
-         y="312.54059"
+         y="332.54059"
          style="text-align:center;text-anchor:middle"
          id="tspan13590">org.freedesktop.</tspan><tspan
          sodipodi:role="line"
          x="286.21173"
-         y="327.54059"
+         y="347.54059"
          style="text-align:center;text-anchor:middle"
          id="tspan13606">PolicyKit1</tspan></text>
     <text
@@ -656,7 +811,7 @@
        x="489.5925"
        y="283.14468"
        id="text13594"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -674,7 +829,7 @@
        sodipodi:ry="34.345188"
        d="m 248.49753,161.40764 a 34.345188,34.345188 0 1 1 -68.69037,0 34.345188,34.345188 0 1 1 68.69037,0 z"
        transform="translate(134.97058,58.198921)"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <text
@@ -683,7 +838,7 @@
        x="349.52975"
        y="210.38663"
        id="text16841"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -707,7 +862,7 @@
        x="93.62104"
        y="143.63353"
        id="text22909"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -723,49 +878,20 @@
        id="text22919"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"><tspan
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"><tspan
          sodipodi:role="line"
          x="108.55364"
          y="202.5914"
          style="font-size:18px;text-align:center;text-anchor:middle"
          id="tspan22927">System Context</tspan></text>
     <rect
-       style="fill:url(#linearGradient624);fill-opacity:1;stroke:#030000;stroke-width:0.45582184;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:19"
-       id="rect28982"
-       width="105.50005"
-       height="36.991695"
-       x="232.01146"
-       y="343.1517"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
-       inkscape:export-xdpi="96.720001"
-       inkscape:export-ydpi="96.720001" />
-    <text
-       xml:space="preserve"
-       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
-       x="284.86676"
-       y="358.26434"
-       id="text28990"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
-       inkscape:export-xdpi="96.720001"
-       inkscape:export-ydpi="96.720001"><tspan
-         sodipodi:role="line"
-         x="284.86676"
-         y="358.26434"
-         style="font-style:italic;text-align:center;text-anchor:middle"
-         id="tspan28992">Backends +</tspan><tspan
-         sodipodi:role="line"
-         x="284.86676"
-         y="373.26434"
-         style="font-style:italic;text-align:center;text-anchor:middle"
-         id="tspan649">Extensions</tspan></text>
-    <rect
        style="fill:url(#linearGradient709);fill-opacity:1;stroke:#030000;stroke-width:0.42205292;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:19"
        id="rect28982-0"
        width="145.96021"
        height="22.922712"
        x="415.80527"
        y="309.43832"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <text
@@ -774,7 +900,7 @@
        x="487.01651"
        y="325.36105"
        id="text28990-4"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -789,7 +915,7 @@
        height="22.946213"
        x="192.32559"
        y="106.87891"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <text
@@ -798,7 +924,7 @@
        x="244.12958"
        y="122.78507"
        id="text28990-4-5"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001"><tspan
          sodipodi:role="line"
@@ -811,7 +937,7 @@
        d="m 411.63462,322.0219 c -73.68449,-1.49124 -6.00174,-74.90542 -67.16623,-76.02779 -24.77688,-7.92418 -44.02981,-7.38813 -43.95096,34.61152"
        id="path2409"
        sodipodi:nodetypes="ccc"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <path
@@ -819,7 +945,7 @@
        d="m 268.19295,136.15382 c 3.55124,52.7952 56.8059,41.36616 51.73617,77.56075 -5.15994,33.07396 -56.01669,4.80866 -57.79705,67.90122"
        id="path4701"
        sodipodi:nodetypes="ccc"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
     <path
@@ -827,8 +953,112 @@
        d="m 463.15239,122.01168 c 0.65982,39.40007 27.62042,24.1776 26.81502,70.68828 1.07889,31.05898 22.63119,1.38255 22.68258,56.59095"
        id="path5124"
        sodipodi:nodetypes="ccc"
-       inkscape:export-filename="/home/davidz/Hacking/PolicyKit/docs/polkit-architecture.png"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001" />
+    <rect
+       style="fill:url(#linearGradient3982);fill-opacity:1;stroke:#030000;stroke-width:0.80120724;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:19"
+       id="rect7676-4-5"
+       width="219.8784"
+       height="54.837009"
+       x="336.86383"
+       y="403.51511"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
        inkscape:export-xdpi="96.720001"
        inkscape:export-ydpi="96.720001" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="445.0928"
+       y="434.35934"
+       id="text13594-3"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001"><tspan
+         sodipodi:role="line"
+         x="445.0928"
+         y="434.35934"
+         style="text-align:center;text-anchor:middle"
+         id="tspan740-0">/usr/share/polkit-1/actions/*.policy</tspan></text>
+    <rect
+       style="fill:url(#linearGradient4001);fill-opacity:1;stroke:#030000;stroke-width:0.80120724;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:19"
+       id="rect7676-4-5-7"
+       width="219.8784"
+       height="54.837009"
+       x="254.34653"
+       y="476.94366"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="362.57547"
+       y="513.7879"
+       id="text13594-3-0"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001"><tspan
+         sodipodi:role="line"
+         x="362.57547"
+         y="513.7879"
+         style="text-align:center;text-anchor:middle"
+         id="tspan740-0-5">/usr/share/polkit-1/rules.d/*.rules</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="343.2959"
+       y="494.95844"
+       id="text13594-3-0-8"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001"><tspan
+         sodipodi:role="line"
+         x="343.2959"
+         y="494.95844"
+         style="text-align:center;text-anchor:middle"
+         id="tspan740-0-5-4">/etc/polkit-1/rules.d/*.rules</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:none"
+       d="m 342.3631,344.48627 c 41.38224,15.43253 92.15719,21.9995 93.22484,54.0334"
+       id="path4701-9"
+       sodipodi:nodetypes="cc"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:none"
+       d="m 301.61996,369.48834 c -2.18919,49.00395 -32.12853,71.9995 -31.06088,104.0334"
+       id="path4701-9-6"
+       sodipodi:nodetypes="cc"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001" />
+    <rect
+       style="fill:url(#linearGradient3144-3);fill-opacity:1;stroke:#030000;stroke-width:0.35916778;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:19"
+       id="rect28982-0-3-6"
+       width="105.5967"
+       height="22.946213"
+       x="231.91594"
+       y="284.88907"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="283.71991"
+       y="300.79523"
+       id="text28990-4-5-6"
+       inkscape:export-filename="/home/davidz/Hacking/polkit/docs/polkit-architecture.png"
+       inkscape:export-xdpi="96.720001"
+       inkscape:export-ydpi="96.720001"><tspan
+         sodipodi:role="line"
+         x="283.71991"
+         y="300.79523"
+         style="text-align:center;text-anchor:middle"
+         id="tspan649-8-8-7">polkitd(8)</tspan></text>
   </g>
 </svg>
diff --git a/docs/polkit-architecture.png b/docs/polkit-architecture.png
index 11342e5..57e1ba2 100644
Binary files a/docs/polkit-architecture.png and b/docs/polkit-architecture.png differ
diff --git a/docs/polkit-authentication-agent-example-wheel.png b/docs/polkit-authentication-agent-example-wheel.png
index bafe5a8..be6e982 100644
Binary files a/docs/polkit-authentication-agent-example-wheel.png and b/docs/polkit-authentication-agent-example-wheel.png differ
diff --git a/docs/polkit-authentication-agent-example.png b/docs/polkit-authentication-agent-example.png
index b2f6559..c5c5131 100644
Binary files a/docs/polkit-authentication-agent-example.png and b/docs/polkit-authentication-agent-example.png differ
diff --git a/docs/polkit/Makefile.am b/docs/polkit/Makefile.am
index fd7123f..72d2fb8 100644
--- a/docs/polkit/Makefile.am
+++ b/docs/polkit/Makefile.am
@@ -61,7 +61,6 @@ content_files =  			    								\
 	docbook-interface-org.freedesktop.PolicyKit1.AuthenticationAgent.xml				\
 	../man/polkit.xml										\
 	../man/polkitd.xml										\
-	../man/pklocalauthority.xml									\
 	../man/pkcheck.xml										\
 	../man/pkaction.xml										\
 	../man/pkexec.xml										\
@@ -73,9 +72,6 @@ HTML_IMAGES = 						\
 	../polkit-architecture.png			\
 	../polkit-authentication-agent-example.png	\
 	../polkit-authentication-agent-example-wheel.png \
-	../pkexec-bash.png				\
-	../pkexec-frobnicate.png			\
-	../pkexec-frobnicate-da.png			\
 	$(NULL)
 
 # Extra options to supply to gtkdoc-fixref
diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml
index 21b3681..84158ef 100644
--- a/docs/polkit/polkit-1-docs.xml
+++ b/docs/polkit/polkit-1-docs.xml
@@ -68,7 +68,6 @@
     <xi:include href="../man/pkcheck.xml"/>
     <xi:include href="../man/pkaction.xml"/>
     <xi:include href="../man/pkexec.xml"/>
-    <xi:include href="../man/pklocalauthority.xml"/>
     <xi:include href="../man/pkttyagent.xml"/>
   </part>
 
diff --git a/src/programs/pkexec.c b/src/programs/pkexec.c
index 373977b..db13cf9 100644
--- a/src/programs/pkexec.c
+++ b/src/programs/pkexec.c
@@ -668,11 +668,12 @@ main (int argc, char *argv[])
   g_assert (action_id != NULL);
 
   details = polkit_details_new ();
+  polkit_details_insert (details, "user", pw->pw_name);
   if (pw->pw_gecos != NULL && strlen (pw->pw_gecos) > 0)
     s = g_strdup_printf ("%s (%s)", pw->pw_gecos, pw->pw_name);
   else
     s = g_strdup_printf ("%s", pw->pw_name);
-  polkit_details_insert (details, "user", s);
+  polkit_details_insert (details, "user_full", s);
   g_free (s);
   polkit_details_insert (details, "program", path);
   polkit_details_insert (details, "command_line", command_line);
commit fc2bb7af79b5c45521d71ca1b1e7b35c1824f86c
Author: David Zeuthen <davidz at redhat.com>
Date:   Tue May 22 09:57:20 2012 -0400

    Create rules.d directories
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index 4f2ac6f..7b7f3eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -518,3 +518,10 @@ echo "NOTE: The file ${bindir}/pkexec must be owned by root and"
 echo "      have mode 4755 (setuid root binary)"
 echo
 
+echo "NOTE: The directory ${sysconfdir}/polkit-1/rules.d"
+echo "      should have mode 700"
+echo
+
+echo "NOTE: The directory ${datadir}/polkit-1/rules.d"
+echo "      should have mode 700"
+echo
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 982c3ea..b1a70c0 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -102,3 +102,7 @@ install-exec-hook:
 	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/localauthority/{10-vendor.d,20-org.d,30-site.d,50-local.d,90-mandatory.d}
 	-chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/localauthority
 	mkdir -p $(DESTDIR)$(libdir)/polkit-1/extensions
+	mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
+	-chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/rules.d
+	mkdir -p $(DESTDIR)$(datadir)/polkit-1/rules.d
+	-chmod 700 $(DESTDIR)$(datadir)/polkit-1/rules.d
commit 28ce5634df0a109d15f2b307e56fbfac92d7c876
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 14:38:49 2012 -0400

    Add test-cases and 10 second timeout for polkit.spawn()
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 7798d45..a7bf50b 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -68,6 +68,18 @@ struct _PolkitBackendJsAuthorityPrivate
   GList *scripts;
 };
 
+static void utils_spawn (const gchar *const  *argv,
+                         guint                timeout_seconds,
+                         GCancellable        *cancellable,
+                         GAsyncReadyCallback  callback,
+                         gpointer             user_data);
+
+gboolean utils_spawn_finish (GAsyncResult   *res,
+                             gint           *out_exit_status,
+                             gchar         **out_standard_output,
+                             gchar         **out_standard_error,
+                             GError        **error);
+
 static void on_dir_monitor_changed (GFileMonitor     *monitor,
                                     GFile            *file,
                                     GFile            *other_file,
@@ -1130,6 +1142,22 @@ get_signal_name (gint signal_number)
   return "UNKNOWN_SIGNAL";
 }
 
+typedef struct
+{
+  GMainLoop *loop;
+  GAsyncResult *res;
+} SpawnData;
+
+static void
+spawn_cb (GObject       *source_object,
+          GAsyncResult  *res,
+          gpointer       user_data)
+{
+  SpawnData *data = user_data;
+  data->res = g_object_ref (res);
+  g_main_loop_quit (data->loop);
+}
+
 static JSBool
 js_polkit_spawn (JSContext  *cx,
                  uintN       js_argc,
@@ -1145,6 +1173,9 @@ js_polkit_spawn (JSContext  *cx,
   JSString *ret_jsstr;
   jsuint array_len;
   gchar **argv = NULL;
+  GMainContext *context = NULL;
+  GMainLoop *loop = NULL;
+  SpawnData data = {0};
   guint n;
 
   if (!JS_ConvertArguments (cx, js_argc, JS_ARGV (cx, vp), "o", &array_object))
@@ -1172,19 +1203,30 @@ js_polkit_spawn (JSContext  *cx,
       JS_free (cx, s);
     }
 
-  /* TODO: set a timeout */
-  if (!g_spawn_sync (NULL, /* working dir */
-                     argv,
-                     NULL, /* envp */
-                     G_SPAWN_SEARCH_PATH,
-                     NULL, NULL, /* child_setup, user_data */
-                     &standard_output,
-                     &standard_error,
-                     &exit_status,
-                     &error))
+  context = g_main_context_new ();
+  loop = g_main_loop_new (context, FALSE);
+
+  g_main_context_push_thread_default (context);
+
+  data.loop = loop;
+  utils_spawn ((const gchar *const *) argv,
+               10, /* timeout_seconds */
+               NULL, /* cancellable */
+               spawn_cb,
+               &data);
+
+  g_main_loop_run (loop);
+
+  g_main_context_pop_thread_default (context);
+
+  if (!utils_spawn_finish (data.res,
+                           &exit_status,
+                           &standard_output,
+                           &standard_error,
+                           &error))
     {
       JS_ReportError (cx,
-                      "Failed to spawn helper: %s (%s, %d)",
+                      "Error spawning helper: %s (%s, %d)",
                       error->message, g_quark_to_string (error->domain), error->code);
       g_clear_error (&error);
       goto out;
@@ -1223,6 +1265,11 @@ js_polkit_spawn (JSContext  *cx,
   g_strfreev (argv);
   g_free (standard_output);
   g_free (standard_error);
+  g_clear_object (&data.res);
+  if (loop != NULL)
+    g_main_loop_unref (loop);
+  if (context != NULL)
+    g_main_context_unref (context);
   return ret;
 }
 
@@ -1266,3 +1313,380 @@ js_polkit_user_is_in_netgroup (JSContext  *cx,
   return ret;
 }
 
+
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  GSimpleAsyncResult *simple; /* borrowed reference */
+  GMainContext *main_context; /* may be NULL */
+
+  GCancellable *cancellable;  /* may be NULL */
+  gulong cancellable_handler_id;
+
+  GPid child_pid;
+  gint child_stdout_fd;
+  gint child_stderr_fd;
+
+  GIOChannel *child_stdout_channel;
+  GIOChannel *child_stderr_channel;
+
+  GSource *child_watch_source;
+  GSource *child_stdout_source;
+  GSource *child_stderr_source;
+
+  guint timeout_seconds;
+  gboolean timed_out;
+  GSource *timeout_source;
+
+  GString *child_stdout;
+  GString *child_stderr;
+
+  gint exit_status;
+} UtilsSpawnData;
+
+static void
+utils_child_watch_from_release_cb (GPid     pid,
+                                   gint     status,
+                                   gpointer user_data)
+{
+}
+
+static void
+utils_spawn_data_free (UtilsSpawnData *data)
+{
+  if (data->timeout_source != NULL)
+    {
+      g_source_destroy (data->timeout_source);
+      data->timeout_source = NULL;
+    }
+
+  /* Nuke the child, if necessary */
+  if (data->child_watch_source != NULL)
+    {
+      g_source_destroy (data->child_watch_source);
+      data->child_watch_source = NULL;
+    }
+
+  if (data->child_pid != 0)
+    {
+      GSource *source;
+      kill (data->child_pid, SIGTERM);
+      /* OK, we need to reap for the child ourselves - we don't want
+       * to use waitpid() because that might block the calling
+       * thread (the child might handle SIGTERM and use several
+       * seconds for cleanup/rollback).
+       *
+       * So we use GChildWatch instead.
+       *
+       * Avoid taking a references to ourselves. but note that we need
+       * to pass the GSource so we can nuke it once handled.
+       */
+      source = g_child_watch_source_new (data->child_pid);
+      g_source_set_callback (source,
+                             (GSourceFunc) utils_child_watch_from_release_cb,
+                             source,
+                             (GDestroyNotify) g_source_destroy);
+      g_source_attach (source, data->main_context);
+      g_source_unref (source);
+      data->child_pid = 0;
+    }
+
+  if (data->child_stdout != NULL)
+    {
+      g_string_free (data->child_stdout, TRUE);
+      data->child_stdout = NULL;
+    }
+
+  if (data->child_stderr != NULL)
+    {
+      g_string_free (data->child_stderr, TRUE);
+      data->child_stderr = NULL;
+    }
+
+  if (data->child_stdout_channel != NULL)
+    {
+      g_io_channel_unref (data->child_stdout_channel);
+      data->child_stdout_channel = NULL;
+    }
+  if (data->child_stderr_channel != NULL)
+    {
+      g_io_channel_unref (data->child_stderr_channel);
+      data->child_stderr_channel = NULL;
+    }
+
+  if (data->child_stdout_source != NULL)
+    {
+      g_source_destroy (data->child_stdout_source);
+      data->child_stdout_source = NULL;
+    }
+  if (data->child_stderr_source != NULL)
+    {
+      g_source_destroy (data->child_stderr_source);
+      data->child_stderr_source = NULL;
+    }
+
+  if (data->child_stdout_fd != -1)
+    {
+      g_warn_if_fail (close (data->child_stdout_fd) == 0);
+      data->child_stdout_fd = -1;
+    }
+  if (data->child_stderr_fd != -1)
+    {
+      g_warn_if_fail (close (data->child_stderr_fd) == 0);
+      data->child_stderr_fd = -1;
+    }
+
+  if (data->cancellable_handler_id > 0)
+    {
+      g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id);
+      data->cancellable_handler_id = 0;
+    }
+
+  if (data->main_context != NULL)
+    g_main_context_unref (data->main_context);
+
+  if (data->cancellable != NULL)
+    g_object_unref (data->cancellable);
+
+  g_slice_free (UtilsSpawnData, data);
+}
+
+/* called in the thread where @cancellable was cancelled */
+static void
+utils_on_cancelled (GCancellable *cancellable,
+                    gpointer      user_data)
+{
+  UtilsSpawnData *data = user_data;
+  GError *error;
+
+  error = NULL;
+  g_warn_if_fail (g_cancellable_set_error_if_cancelled (cancellable, &error));
+  g_simple_async_result_take_error (data->simple, error);
+  g_simple_async_result_complete_in_idle (data->simple);
+  g_object_unref (data->simple);
+}
+
+static gboolean
+utils_read_child_stderr (GIOChannel *channel,
+                         GIOCondition condition,
+                         gpointer user_data)
+{
+  UtilsSpawnData *data = user_data;
+  gchar buf[1024];
+  gsize bytes_read;
+
+  g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
+  g_string_append_len (data->child_stderr, buf, bytes_read);
+  return TRUE;
+}
+
+static gboolean
+utils_read_child_stdout (GIOChannel *channel,
+                         GIOCondition condition,
+                         gpointer user_data)
+{
+  UtilsSpawnData *data = user_data;
+  gchar buf[1024];
+  gsize bytes_read;
+
+  g_io_channel_read_chars (channel, buf, sizeof buf, &bytes_read, NULL);
+  g_string_append_len (data->child_stdout, buf, bytes_read);
+  return TRUE;
+}
+
+static void
+utils_child_watch_cb (GPid     pid,
+                      gint     status,
+                      gpointer user_data)
+{
+  UtilsSpawnData *data = user_data;
+  gchar *buf;
+  gsize buf_size;
+
+  if (g_io_channel_read_to_end (data->child_stdout_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
+    {
+      g_string_append_len (data->child_stdout, buf, buf_size);
+      g_free (buf);
+    }
+  if (g_io_channel_read_to_end (data->child_stderr_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL)
+    {
+      g_string_append_len (data->child_stderr, buf, buf_size);
+      g_free (buf);
+    }
+
+  data->exit_status = status;
+
+  /* ok, child watch is history, make sure we don't free it in spawn_data_free() */
+  data->child_pid = 0;
+  data->child_watch_source = NULL;
+
+  /* we're done */
+  g_simple_async_result_complete_in_idle (data->simple);
+  g_object_unref (data->simple);
+}
+
+static gboolean
+utils_timeout_cb (gpointer user_data)
+{
+  UtilsSpawnData *data = user_data;
+
+  data->timed_out = TRUE;
+
+  /* ok, timeout is history, make sure we don't free it in spawn_data_free() */
+  data->timeout_source = NULL;
+
+  /* we're done */
+  g_simple_async_result_complete_in_idle (data->simple);
+  g_object_unref (data->simple);
+
+  return FALSE; /* remove source */
+}
+
+static void
+utils_spawn (const gchar *const  *argv,
+             guint                timeout_seconds,
+             GCancellable        *cancellable,
+             GAsyncReadyCallback  callback,
+             gpointer             user_data)
+{
+  UtilsSpawnData *data;
+  GError *error;
+
+  data = g_slice_new0 (UtilsSpawnData);
+  data->timeout_seconds = timeout_seconds;
+  data->simple = g_simple_async_result_new (NULL,
+                                            callback,
+                                            user_data,
+                                            utils_spawn);
+  data->main_context = g_main_context_get_thread_default ();
+  if (data->main_context != NULL)
+    g_main_context_ref (data->main_context);
+
+  data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
+
+  data->child_stdout = g_string_new (NULL);
+  data->child_stderr = g_string_new (NULL);
+  data->child_stdout_fd = -1;
+  data->child_stderr_fd = -1;
+
+  /* the life-cycle of UtilsSpawnData is tied to its GSimpleAsyncResult */
+  g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) utils_spawn_data_free);
+
+  error = NULL;
+  if (data->cancellable != NULL)
+    {
+      /* could already be cancelled */
+      error = NULL;
+      if (g_cancellable_set_error_if_cancelled (data->cancellable, &error))
+        {
+          g_simple_async_result_take_error (data->simple, error);
+          g_simple_async_result_complete_in_idle (data->simple);
+          g_object_unref (data->simple);
+          goto out;
+        }
+
+      data->cancellable_handler_id = g_cancellable_connect (data->cancellable,
+                                                            G_CALLBACK (utils_on_cancelled),
+                                                            data,
+                                                            NULL);
+    }
+
+  error = NULL;
+  if (!g_spawn_async_with_pipes (NULL, /* working directory */
+                                 (gchar **) argv,
+                                 NULL, /* envp */
+                                 G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+                                 NULL, /* child_setup */
+                                 NULL, /* child_setup's user_data */
+                                 &(data->child_pid),
+                                 NULL, /* gint *stdin_fd */
+                                 &(data->child_stdout_fd),
+                                 &(data->child_stderr_fd),
+                                 &error))
+    {
+      g_prefix_error (&error, "Error spawning: ");
+      g_simple_async_result_take_error (data->simple, error);
+      g_simple_async_result_complete_in_idle (data->simple);
+      g_object_unref (data->simple);
+      goto out;
+    }
+
+  if (timeout_seconds > 0)
+    {
+      data->timeout_source = g_timeout_source_new_seconds (timeout_seconds);
+      g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT);
+      g_source_set_callback (data->timeout_source, utils_timeout_cb, data, NULL);
+      g_source_attach (data->timeout_source, data->main_context);
+      g_source_unref (data->timeout_source);
+    }
+
+  data->child_watch_source = g_child_watch_source_new (data->child_pid);
+  g_source_set_callback (data->child_watch_source, (GSourceFunc) utils_child_watch_cb, data, NULL);
+  g_source_attach (data->child_watch_source, data->main_context);
+  g_source_unref (data->child_watch_source);
+
+  data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd);
+  g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL);
+  data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN);
+  g_source_set_callback (data->child_stdout_source, (GSourceFunc) utils_read_child_stdout, data, NULL);
+  g_source_attach (data->child_stdout_source, data->main_context);
+  g_source_unref (data->child_stdout_source);
+
+  data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd);
+  g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL);
+  data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN);
+  g_source_set_callback (data->child_stderr_source, (GSourceFunc) utils_read_child_stderr, data, NULL);
+  g_source_attach (data->child_stderr_source, data->main_context);
+  g_source_unref (data->child_stderr_source);
+
+ out:
+  ;
+}
+
+gboolean
+utils_spawn_finish (GAsyncResult   *res,
+                    gint           *out_exit_status,
+                    gchar         **out_standard_output,
+                    gchar         **out_standard_error,
+                    GError        **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  UtilsSpawnData *data;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == utils_spawn);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    goto out;
+
+  data = g_simple_async_result_get_op_res_gpointer (simple);
+
+  if (data->timed_out)
+    {
+      g_set_error (error,
+                   G_IO_ERROR,
+                   G_IO_ERROR_TIMED_OUT,
+                   "Timed out after %d seconds",
+                   data->timeout_seconds);
+      goto out;
+    }
+
+  if (out_exit_status != NULL)
+    *out_exit_status = data->exit_status;
+
+  if (out_standard_output != NULL)
+    *out_standard_output = g_strdup (data->child_stdout->str);
+
+  if (out_standard_error != NULL)
+    *out_standard_error = g_strdup (data->child_stderr->str);
+
+  ret = TRUE;
+
+ out:
+  return ret;
+}
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 0cad62c..4a35e48 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -71,3 +71,66 @@ polkit.addRule(function(action, subject, details) {
             return "no";
     }
 });
+
+// ---------------------------------------------------------------------
+// spawning
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.spawning.non_existing_helper") {
+        try {
+            polkit.spawn(["/path/to/non/existing/helper"]);
+            return "no";
+        } catch (error) {
+            return "yes";
+        }
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.spawning.successful_helper") {
+        try {
+            polkit.spawn(["/bin/true"]);
+            return "yes";
+        } catch (error) {
+            return "no";
+        }
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.spawning.failing_helper") {
+        try {
+            polkit.spawn(["/bin/false"]);
+            return "no";
+        } catch (error) {
+            return "yes";
+        }
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.spawning.helper_with_output") {
+        try {
+            var out = polkit.spawn(["echo", "-n", "-e", "Hello\nWorld"]);
+            if (out == "Hello\nWorld")
+                return "yes";
+            else
+                return "no";
+        } catch (error) {
+            return "no";
+        }
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.spawning.helper_timeout") {
+        try {
+            polkit.spawn(["sleep", "20"]);
+            return "no";
+        } catch (error) {
+            if (error == "Error: Error spawning helper: Timed out after 10 seconds (g-io-error-quark, 24)")
+                return "yes";
+            return "no";
+        }
+    }
+});
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index f81c7fb..948cbc1 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -23,6 +23,7 @@
 
 #include "glib.h"
 
+#include <locale.h>
 #include <polkit/polkit.h>
 #include <polkitbackend/polkitbackendjsauthority.h>
 #include <polkittesthelper.h>
@@ -246,6 +247,43 @@ static const RulesTestCase rules_test_cases[] = {
     POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
     NULL
   },
+
+  /* spawning */
+  {
+    "spawning_non_existing_helper",
+    "net.company.spawning.non_existing_helper",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    "spawning_successful_helper",
+    "net.company.spawning.successful_helper",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    "spawning_failing_helper",
+    "net.company.spawning.failing_helper",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    "spawning_helper_with_output",
+    "net.company.spawning.helper_with_output",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    "spawning_helper_timeout",
+    "net.company.spawning.helper_timeout",
+    "unix-user:root",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
 };
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -310,6 +348,8 @@ main (int argc, char *argv[])
 {
   GIOExtensionPoint *ep;
 
+  setlocale (LC_ALL, "");
+
   g_type_init ();
   g_test_init (&argc, &argv, NULL);
   //polkit_test_redirect_logs ();
commit e7f01d6a37b0d922e9fe005e38fe9a958eb18e7f
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 13:56:11 2012 -0400

    Mention unix-netgroup:xyz as a valid return value in addAdminRule() functions
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 57dd366..6ec15ac 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -541,7 +541,8 @@ System Context         |                        |
       the order they have been added until one of the functions
       returns a value. Each function should return an array of strings
       where each string is of the form
-      <literal>"unix-group:&lt;group&gt;"</literal> or
+      <literal>"unix-group:&lt;group&gt;"</literal>,
+      <literal>"unix-netgroup:&lt;netgroup&gt;"</literal> or
       <literal>"unix-user:&lt;user&gt;"</literal>.  If the function
       returns <constant>null</constant>,
       <constant>undefined</constant> or does not return a value at
commit 5b393dfb9d193a997303b7682d10f479a5e327ec
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 13:54:35 2012 -0400

    Minor doc fixes
    
    Nuke the has_prefix() helper, it's just confusing.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index ee658c5..57dd366 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -717,16 +717,13 @@ polkit.addAdminRule(function(action, subject, details) {
 
       <para>
         Forbid users in group <literal>children</literal> to change
-        hostname configuration and allow anyone else to do it (after
-        authenticating as themselves):
+        hostname configuration (that is, any action starting wth
+        <literal>org.freedesktop.hostname1.</literal>) and allow
+        anyone else to do it after authenticating as themselves:
       </para>
       <programlisting><![CDATA[
-function has_prefix(str, prefix) {
-    return str.indexOf(prefix) == 0;
-}
-
 polkit.addRule(function(action, subject, details) {
-    if (has_prefix(action, "org.freedesktop.hostname1.")) {
+    if (action.indexOf("org.freedesktop.hostname1.") == 0) {
         if (subject.isInGroup("children")) {
             return "no";
         } else {
commit 31c0ce425a03c59726b7c1a83aaf8cd8dfab79f7
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 13:42:43 2012 -0400

    Add netgroup support
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 4fbc117..ee658c5 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -652,6 +652,21 @@ System Context         |                        |
         </funcprototype>
       </funcsynopsis>
 
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>boolean <function>isInNetGroup</function></funcdef>
+          <paramdef>string <parameter>netGroupName</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The <function>isInGroup()</function> method can be used to
+        check if the subject is in a given group and
+        <function>isInNetGroup()</function> can be used to check if
+        the subject is in a given netgroup.
+      </para>
+
     </refsect2>
 
     <refsect2 id="polkit-rules-details">
diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 0e8bcfb..29f13fc 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -26,6 +26,10 @@ function Subject() {
         return false;
     };
 
+    this.isInNetGroup = function(netGroup) {
+        return polkit._userIsInNetGroup(this.user, netGroup);
+    };
+
     this.toString = function() {
         var ret = "[Subject";
         for (var i in this) {
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 8c1d189..7798d45 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -144,11 +144,13 @@ static JSClass js_polkit_class = {
 
 static JSBool js_polkit_log (JSContext *cx, uintN argc, jsval *vp);
 static JSBool js_polkit_spawn (JSContext *cx, uintN argc, jsval *vp);
+static JSBool js_polkit_user_is_in_netgroup (JSContext *cx, uintN argc, jsval *vp);
 
 static JSFunctionSpec js_polkit_functions[] =
 {
   JS_FS("log",            js_polkit_log,            0, 0),
   JS_FS("spawn",          js_polkit_spawn,          0, 0),
+  JS_FS("_userIsInNetGroup", js_polkit_user_is_in_netgroup,          0, 0),
   JS_FS_END
 };
 
@@ -1225,3 +1227,42 @@ js_polkit_spawn (JSContext  *cx,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+
+
+static JSBool
+js_polkit_user_is_in_netgroup (JSContext  *cx,
+                               uintN       argc,
+                               jsval      *vp)
+{
+  /* PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx)); */
+  JSBool ret = JS_FALSE;
+  JSString *user_str;
+  JSString *netgroup_str;
+  char *user;
+  char *netgroup;
+  JSBool is_in_netgroup = JS_FALSE;
+
+  if (!JS_ConvertArguments (cx, argc, JS_ARGV (cx, vp), "SS", &user_str, &netgroup_str))
+    goto out;
+
+  user = JS_EncodeString (cx, user_str);
+  netgroup = JS_EncodeString (cx, netgroup_str);
+
+  if (innetgr (netgroup,
+               NULL,  /* host */
+               user,
+               NULL)) /* domain */
+    {
+      is_in_netgroup =  JS_TRUE;
+    }
+
+  JS_free (cx, netgroup);
+  JS_free (cx, user);
+
+  ret = JS_TRUE;
+
+  JS_SET_RVAL (cx, vp, BOOLEAN_TO_JSVAL (is_in_netgroup));
+ out:
+  return ret;
+}
+
diff --git a/test/Makefile.am b/test/Makefile.am
index 8426977..598e426 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,7 @@
 SUBDIRS = mocklibc . polkit polkitbackend
 AM_CFLAGS = $(GLIB_CFLAGS)
 
-check_LTLIBRARIES = libpolkit-test-helper.la
+noinst_LTLIBRARIES = libpolkit-test-helper.la
 libpolkit_test_helper_la_SOURCES = polkittesthelper.c polkittesthelper.h
 libpolkit_test_helper_la_LIBADD = $(GLIB_LIBS)
 
@@ -17,7 +17,6 @@ export TESTS_ENVIRONMENT := $(abs_top_builddir)/test/mocklibc/bin/mocklibc
 # Include path to mock config files
 export POLKIT_TEST_DATA := $(abs_top_srcdir)/test/data
 
-
 clean-local :
 	rm -f *~
 
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 4cd184c..0cad62c 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -16,6 +16,12 @@ polkit.addAdminRule(function(action, subject, details) {
     }
 });
 
+polkit.addAdminRule(function(action, subject, details) {
+    if (action == "net.company.action3") {
+        return ["unix-netgroup:foo"];
+    }
+});
+
 // Fallback
 polkit.addAdminRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
@@ -53,3 +59,15 @@ polkit.addRule(function(action, subject, details) {
             return "no";
     }
 });
+
+// ---------------------------------------------------------------------
+// netgroup membership
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.group.only_netgroup_users") {
+        if (subject.isInNetGroup("foo"))
+            return "yes";
+        else
+            return "no";
+    }
+});
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index a210f68..f81c7fb 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -130,6 +130,12 @@ test_get_admin_identities (void)
         "unix-group:users"
       }
     },
+    {
+      "net.company.action3",
+      {
+        "unix-netgroup:foo"
+      }
+    },
   };
   guint n;
 
@@ -222,6 +228,24 @@ static const RulesTestCase rules_test_cases[] = {
     POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
     NULL
   },
+
+  /* check netgroup membership */
+  {
+    /* john is a member of netgroup 'foo', see test/etc/netgroup */
+    "netgroup_membership_with_member",
+    "net.company.group.only_netgroup_users",
+    "unix-user:john",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    /* sally is not a member of netgroup 'foo', see test/etc/netgroup */
+    "netgroup_membership_with_non_member",
+    "net.company.group.only_netgroup_users",
+    "unix-user:sally",
+    POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
+    NULL
+  },
 };
 
 /* ---------------------------------------------------------------------------------------------------- */
commit 8e0c53ecf7129cd1be8bc9ac322aab4af992ce61
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 12:29:01 2012 -0400

    Test that subject.isInGroup() works
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 4fce8c5..4cd184c 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -41,3 +41,15 @@ polkit.addRule(function(action, subject, details) {
         return "yes";
     }
 });
+
+// ---------------------------------------------------------------------
+// group membership
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.group.only_group_users") {
+        if (subject.isInGroup("users"))
+            return "yes";
+        else
+            return "no";
+    }
+});
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 8057707..a210f68 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -148,6 +148,7 @@ struct RulesTestCase
 {
   const gchar *test_name;
   const gchar *action_id;
+  const gchar *identity;
   PolkitImplicitAuthorization expected_result;
   const gchar *expected_detail;
 };
@@ -157,12 +158,14 @@ static const RulesTestCase rules_test_cases[] = {
   {
     "basic0",
     "net.company.productA.action0",
+    "unix-user:root",
     POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
     NULL
   },
   {
     "basic1",
     "net.company.productA.action1",
+    "unix-user:root",
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
     NULL
   },
@@ -181,6 +184,7 @@ static const RulesTestCase rules_test_cases[] = {
     /* defined in file a, b, c, d - should pick file a */
     "order0",
     "net.company.order0",
+    "unix-user:root",
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
     "a"
   },
@@ -188,6 +192,7 @@ static const RulesTestCase rules_test_cases[] = {
     /* defined in file b, c, d - should pick file b */
     "order1",
     "net.company.order1",
+    "unix-user:root",
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
     "b"
   },
@@ -195,9 +200,28 @@ static const RulesTestCase rules_test_cases[] = {
     /* defined in file c, d - should pick file c */
     "order2",
     "net.company.order2",
+    "unix-user:root",
     POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
     "c"
   },
+
+  /* check group membership */
+  {
+    /* john is a member of group 'users', see test/etc/group */
+    "group_membership_with_member",
+    "net.company.group.only_group_users",
+    "unix-user:john",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    NULL
+  },
+  {
+    /* sally is not a member of group 'users', see test/etc/group */
+    "group_membership_with_non_member",
+    "net.company.group.only_group_users",
+    "unix-user:sally",
+    POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED,
+    NULL
+  },
 };
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -218,7 +242,7 @@ rules_test_func (gconstpointer user_data)
 
   caller = polkit_unix_process_new (getpid ());
   subject = polkit_unix_process_new (getpid ());
-  user_for_subject = polkit_identity_from_string ("unix-user:root", &error);
+  user_for_subject = polkit_identity_from_string (tc->identity, &error);
   g_assert_no_error (error);
 
   details = polkit_details_new ();
commit bbf0ea5fff7e397e6170f280ca7e8f4d3d596934
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 12:15:10 2012 -0400

    Add test cases for evaluation order
    
    In fact, this test uncovered that we were evaluating the rules in the
    wrong order. Fix this.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index cf6a65d..0e8bcfb 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -45,7 +45,7 @@ polkit._adminRuleFuncs = [];
 polkit.addAdminRule = function(callback) {this._adminRuleFuncs.push(callback);};
 polkit._runAdminRules = function(action, subject, details) {
     var ret = null;
-    for (var n = this._adminRuleFuncs.length - 1; n >= 0; n--) {
+    for (var n = 0; n < this._adminRuleFuncs.length; n++) {
         var func = this._adminRuleFuncs[n];
         var func_ret = func(action, subject, details);
         if (func_ret) {
@@ -60,7 +60,7 @@ polkit._ruleFuncs = [];
 polkit.addRule = function(callback) {this._ruleFuncs.push(callback);};
 polkit._runRules = function(action, subject, details) {
     var ret = null;
-    for (var n = this._ruleFuncs.length - 1; n >= 0; n--) {
+    for (var n = 0; n < this._ruleFuncs.length; n++) {
         var func = this._ruleFuncs[n];
         var func_ret = func(action, subject, details);
         if (func_ret) {
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 1c3a562..4fce8c5 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -5,10 +5,6 @@
 /* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
 
 polkit.addAdminRule(function(action, subject, details) {
-    return ["unix-group:admin", "unix-user:root"];
-});
-
-polkit.addAdminRule(function(action, subject, details) {
     if (action == "net.company.action1") {
         return ["unix-group:admin"];
     }
@@ -20,14 +16,28 @@ polkit.addAdminRule(function(action, subject, details) {
     }
 });
 
+// Fallback
+polkit.addAdminRule(function(action, subject, details) {
+    return ["unix-group:admin", "unix-user:root"];
+});
+
 // -----
 
 polkit.addRule(function(action, subject, details) {
-    return "auth_admin";
+    if (action == "net.company.productA.action0") {
+        return "auth_admin";
+    }
 });
 
 polkit.addRule(function(action, subject, details) {
-    if (action == "org.freedesktop.policykit.exec") {
-        return "auth_admin";
+    if (action == "net.company.productA.action1") {
+        return "auth_self";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order0") {
+        details["test_detail"] = "a";
+        return "yes";
     }
 });
diff --git a/test/data/etc/polkit-1/rules.d/15-testing.rules b/test/data/etc/polkit-1/rules.d/15-testing.rules
new file mode 100644
index 0000000..9968aa7
--- /dev/null
+++ b/test/data/etc/polkit-1/rules.d/15-testing.rules
@@ -0,0 +1,24 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+/* see test/polkitbackend/test-polkitbackendjsauthority.c */
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order0") {
+        details["test_detail"] = "c";
+        return "yes";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order1") {
+        details["test_detail"] = "c";
+        return "yes";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order2") {
+        details["test_detail"] = "c";
+        return "yes";
+    }
+});
diff --git a/test/data/usr/share/polkit-1/rules.d/10-testing.rules b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
index ab2fd97..48c4957 100644
--- a/test/data/usr/share/polkit-1/rules.d/10-testing.rules
+++ b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
@@ -3,3 +3,17 @@
 /* see test/polkitbackend/test-polkitbackendjsauthority.c */
 
 /* NOTE: this is the /usr/share/polkit-1/rules.d version of 10-testing.rules */
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order0") {
+        details["test_detail"] = "c";
+        return "yes";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order1") {
+        details["test_detail"] = "b";
+        return "yes";
+    }
+});
diff --git a/test/data/usr/share/polkit-1/rules.d/20-testing.rules b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
new file mode 100644
index 0000000..16dd039
--- /dev/null
+++ b/test/data/usr/share/polkit-1/rules.d/20-testing.rules
@@ -0,0 +1,25 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+/* see test/polkitbackend/test-polkitbackendjsauthority.c */
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order0") {
+        polkit.log("blabla");
+        details["test_detail"] = "d";
+        return "yes";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order1") {
+        details["test_detail"] = "d";
+        return "yes";
+    }
+});
+
+polkit.addRule(function(action, subject, details) {
+    if (action == "net.company.order2") {
+        details["test_detail"] = "d";
+        return "yes";
+    }
+});
diff --git a/test/polkitbackend/polkitbackendlocalauthoritytest.c b/test/polkitbackend/polkitbackendlocalauthoritytest.c
index 9fc7848..40e9619 100644
--- a/test/polkitbackend/polkitbackendlocalauthoritytest.c
+++ b/test/polkitbackend/polkitbackendlocalauthoritytest.c
@@ -253,7 +253,7 @@ main (int argc, char *argv[])
       POLKIT_BACKEND_TYPE_AUTHORITY);
 
   add_check_authorization_tests ();
-  g_test_add_func ("/PolkitBackendLocalAuthority/get_admin_identities", test_get_admin_identities);
+  g_test_add_func ("/PolkitBackendJsAuthority/get_admin_identities", test_get_admin_identities);
 
   return g_test_run ();
 };
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index 67f5d8b..8057707 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -102,7 +102,7 @@ test_get_admin_identities_for_action_id (const gchar         *action_id,
   g_clear_object (&subject);
   g_clear_object (&caller);
   g_clear_object (&authority);
-}
+ }
 
 static void
 test_get_admin_identities (void)
@@ -140,6 +140,122 @@ test_get_admin_identities (void)
     }
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct RulesTestCase RulesTestCase;
+
+struct RulesTestCase
+{
+  const gchar *test_name;
+  const gchar *action_id;
+  PolkitImplicitAuthorization expected_result;
+  const gchar *expected_detail;
+};
+
+static const RulesTestCase rules_test_cases[] = {
+  /* Check basics */
+  {
+    "basic0",
+    "net.company.productA.action0",
+    POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED,
+    NULL
+  },
+  {
+    "basic1",
+    "net.company.productA.action1",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED,
+    NULL
+  },
+
+  /* Ordering tests ... we have four rules files, check they are
+   * evaluated in order by checking the detail set by each rules
+   *
+   * -       etc/polkit-1/rules.d/10-testing.rules (file a)
+   * - usr/share/polkit-1/rules.d/10-testing.rules (file b)
+   * -       etc/polkit-1/rules.d/15-testing.rules (file c)
+   * - usr/share/polkit-1/rules.d/20-testing.rules (file d)
+   *
+   * file.
+   */
+  {
+    /* defined in file a, b, c, d - should pick file a */
+    "order0",
+    "net.company.order0",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    "a"
+  },
+  {
+    /* defined in file b, c, d - should pick file b */
+    "order1",
+    "net.company.order1",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    "b"
+  },
+  {
+    /* defined in file c, d - should pick file c */
+    "order2",
+    "net.company.order2",
+    POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED,
+    "c"
+  },
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+rules_test_func (gconstpointer user_data)
+{
+  const RulesTestCase *tc = user_data;
+  PolkitBackendJsAuthority *authority = NULL;
+  PolkitSubject *caller = NULL;
+  PolkitSubject *subject = NULL;
+  PolkitIdentity *user_for_subject = NULL;
+  PolkitDetails *details = NULL;
+  GError *error = NULL;
+  PolkitImplicitAuthorization result;
+
+  authority = get_authority ();
+
+  caller = polkit_unix_process_new (getpid ());
+  subject = polkit_unix_process_new (getpid ());
+  user_for_subject = polkit_identity_from_string ("unix-user:root", &error);
+  g_assert_no_error (error);
+
+  details = polkit_details_new ();
+
+  result = polkit_backend_interactive_authority_check_authorization_sync (POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
+                                                                          caller,
+                                                                          subject,
+                                                                          user_for_subject,
+                                                                          TRUE,
+                                                                          TRUE,
+                                                                          tc->action_id,
+                                                                          details,
+                                                                          POLKIT_IMPLICIT_AUTHORIZATION_UNKNOWN);
+  g_assert_cmpint (result, ==, tc->expected_result);
+  g_assert_cmpstr (polkit_details_lookup (details, "test_detail"), ==, tc->expected_detail);
+
+  g_clear_object (&user_for_subject);
+  g_clear_object (&subject);
+  g_clear_object (&caller);
+  g_clear_object (&authority);
+}
+
+static void
+add_rules_tests (void)
+{
+  guint n;
+  for (n = 0; n < G_N_ELEMENTS (rules_test_cases); n++)
+    {
+      const RulesTestCase *tc = &rules_test_cases[n];
+      gchar *s;
+      s = g_strdup_printf ("/PolkitBackendJsAuthority/rules_%s", tc->test_name);
+      g_test_add_data_func (s, &rules_test_cases[n], rules_test_func);
+      g_free (s);
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
 
 int
 main (int argc, char *argv[])
@@ -154,6 +270,7 @@ main (int argc, char *argv[])
   g_io_extension_point_set_required_type (ep, POLKIT_BACKEND_TYPE_AUTHORITY);
 
   g_test_add_func ("/PolkitBackendJsAuthority/get_admin_identities", test_get_admin_identities);
+  add_rules_tests ();
 
   return g_test_run ();
 };
commit cc039fe06d0905732bfa12cb5dd245c5535185ad
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 11:30:24 2012 -0400

    docs: emphasize that registered functions may actually never be called
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 2aa1da1..4fbc117 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -511,7 +511,7 @@ System Context         |                        |
 
     <para>
       The <function>addRule()</function> method is used for adding a
-      function that is called whenever an authorization check for
+      function that may be called whenever an authorization check for
       <parameter>action</parameter>, <parameter>subject</parameter>
       and <parameter>details</parameter> is performed. Functions are
       called in the order they have been added until one of the
@@ -532,7 +532,7 @@ System Context         |                        |
 
     <para>
       The <function>addAdminRule()</function> method is used for
-      adding a function that is called whenever administrator
+      adding a function may be called whenever administrator
       authentication is required. The function is used to specify what
       identies may be used for administrator authentication for the
       authorization check identified by <parameter>action</parameter>,
@@ -549,6 +549,15 @@ System Context         |                        |
     </para>
 
     <para>
+      There is no guarantee that a function registered with
+      <function>addRule()</function> or
+      <function>addAdminRule()</function> is ever called - for example
+      an early rules file could register a function that always return
+      a value, hence ensuring that functions added later are never
+      called.
+    </para>
+
+    <para>
       The <function>log()</function> method writes the given
       <parameter>message</parameter> to the system logger. Log entries
       are emitted using the <constant>LOG_AUTHPRIV</constant> flag
commit 6f550da889c9ad313c9944888c8a263ac5e4e0f2
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 11:03:50 2012 -0400

    Use addRule() and addAdminRule()
    
    ... as the man page already says.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index ec6b7ae..cf6a65d 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -41,33 +41,37 @@ function Subject() {
     };
 };
 
-polkit._administratorRuleFuncs = [];
-polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};
-polkit._runAdministratorRules = function(action, subject, details) {
+polkit._adminRuleFuncs = [];
+polkit.addAdminRule = function(callback) {this._adminRuleFuncs.push(callback);};
+polkit._runAdminRules = function(action, subject, details) {
     var ret = null;
-    for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {
-        var func = this._administratorRuleFuncs[n];
-        ret = func(action, subject, details);
-        if (ret)
+    for (var n = this._adminRuleFuncs.length - 1; n >= 0; n--) {
+        var func = this._adminRuleFuncs[n];
+        var func_ret = func(action, subject, details);
+        if (func_ret) {
+            ret = func_ret;
             break
+        }
     }
     return ret.join(",");
 };
 
-polkit._authorizationRuleFuncs = [];
-polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};
-polkit._runAuthorizationRules = function(action, subject, details) {
+polkit._ruleFuncs = [];
+polkit.addRule = function(callback) {this._ruleFuncs.push(callback);};
+polkit._runRules = function(action, subject, details) {
     var ret = null;
-    for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {
-        var func = this._authorizationRuleFuncs[n];
-        ret = func(action, subject, details);
-        if (ret)
+    for (var n = this._ruleFuncs.length - 1; n >= 0; n--) {
+        var func = this._ruleFuncs[n];
+        var func_ret = func(action, subject, details);
+        if (func_ret) {
+            ret = func_ret;
             break
+        }
     }
     return ret;
 };
 
 polkit._deleteRules = function() {
-    this._administratorRuleFuncs = [];
-    this._authorizationRuleFuncs = [];
+    this._adminRuleFuncs = [];
+    this._ruleFuncs = [];
 };
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 849034a..8c1d189 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -851,13 +851,13 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
-                           "_runAdministratorRules",
+                           "_runAdminRules",
                            3,
                            argv,
                            &rval))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error evaluating administrator rules");
+                                    "Error evaluating admin rules");
       goto out;
     }
 
@@ -958,7 +958,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
-                           "_runAuthorizationRules",
+                           "_runRules",
                            3,
                            argv,
                            &rval))
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index d4bb324..1c3a562 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -4,33 +4,30 @@
 
 /* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
 
-polkit.addAdministratorRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
 });
 
-polkit.addAdministratorRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject, details) {
     if (action == "net.company.action1") {
         return ["unix-group:admin"];
     }
-    return null;
 });
 
-polkit.addAdministratorRule(function(action, subject, details) {
+polkit.addAdminRule(function(action, subject, details) {
     if (action == "net.company.action2") {
         return ["unix-group:users"];
     }
-    return null;
 });
 
 // -----
 
-polkit.addAuthorizationRule(function(action, subject, details) {
+polkit.addRule(function(action, subject, details) {
     return "auth_admin";
 });
 
-polkit.addAuthorizationRule(function(action, subject, details) {
+polkit.addRule(function(action, subject, details) {
     if (action == "org.freedesktop.policykit.exec") {
         return "auth_admin";
     }
-    return null;
 });
commit 89865529ec98067ba8eada3b59938204534de7b2
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 10:45:08 2012 -0400

    Also load rules from /usr/share/polkit/rules.d
    
    ... in addition to /etc/polkit/rules.d.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 1d6e156..849034a 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -56,8 +56,8 @@
 
 struct _PolkitBackendJsAuthorityPrivate
 {
-  gchar *rules_dir;
-  GFileMonitor *dir_monitor;
+  gchar **rules_dirs;
+  GFileMonitor **dir_monitors; /* NULL-terminated array of GFileMonitor instances */
 
   JSRuntime *rt;
   JSContext *cx;
@@ -79,7 +79,7 @@ static void on_dir_monitor_changed (GFileMonitor     *monitor,
 enum
 {
   PROP_0,
-  PROP_RULES_DIR,
+  PROP_RULES_DIRS,
 };
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -174,40 +174,76 @@ polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
                                                  PolkitBackendJsAuthorityPrivate);
 }
 
+static gint
+rules_file_name_cmp (const gchar *a,
+                     const gchar *b)
+{
+  gint ret;
+  const gchar *a_base;
+  const gchar *b_base;
+
+  a_base = strrchr (a, '/');
+  b_base = strrchr (b, '/');
+
+  g_assert (a_base != NULL);
+  g_assert (b_base != NULL);
+  a_base += 1;
+  b_base += 1;
+
+  ret = g_strcmp0 (a_base, b_base);
+  if (ret == 0)
+    {
+      /* /etc wins over /usr */
+      ret = g_strcmp0 (a, b);
+      g_assert (ret != 0);
+    }
+
+  return ret;
+}
+
 static void
 load_scripts (PolkitBackendJsAuthority  *authority)
 {
-  GDir *dir = NULL;
   GList *files = NULL;
   GList *l;
-  const gchar *name;
   guint num_scripts = 0;
   GError *error = NULL;
+  guint n;
 
-  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                "Loading scripts from directory %s",
-                                authority->priv->rules_dir);
+  files = NULL;
 
-  dir = g_dir_open (authority->priv->rules_dir,
-                    0,
-                    &error);
-  if (dir == NULL)
+  for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
     {
+      const gchar *dir_name = authority->priv->rules_dirs[n];
+      GDir *dir = NULL;
+
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error opening rules directory: %s (%s, %d)",
-                                    error->message, g_quark_to_string (error->domain), error->code);
-      g_clear_error (&error);
-      goto out;
-    }
+                                    "Loading scripts from directory %s",
+                                    dir_name);
 
-  files = NULL;
-  while ((name = g_dir_read_name (dir)) != NULL)
-    {
-      if (g_str_has_suffix (name, ".rules"))
-        files = g_list_prepend (files, g_strdup_printf ("%s/%s", authority->priv->rules_dir, name));
+      dir = g_dir_open (dir_name,
+                        0,
+                        &error);
+      if (dir == NULL)
+        {
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Error opening rules directory: %s (%s, %d)",
+                                        error->message, g_quark_to_string (error->domain), error->code);
+          g_clear_error (&error);
+        }
+      else
+        {
+          const gchar *name;
+          while ((name = g_dir_read_name (dir)) != NULL)
+            {
+              if (g_str_has_suffix (name, ".rules"))
+                files = g_list_prepend (files, g_strdup_printf ("%s/%s", dir_name, name));
+            }
+          g_dir_close (dir);
+        }
     }
 
-  files = g_list_sort (files, (GCompareFunc) g_strcmp0);
+  files = g_list_sort (files, (GCompareFunc) rules_file_name_cmp);
 
   for (l = files; l != NULL; l = l->next)
     {
@@ -246,11 +282,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
   polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                 "Finished loading, compiling and executing %d scripts",
                                 num_scripts);
-
- out:
   g_list_free_full (files, g_free);
-  if (dir != NULL)
-    g_dir_close (dir);
 }
 
 static void
@@ -318,6 +350,46 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
     }
 }
 
+
+static void
+setup_file_monitors (PolkitBackendJsAuthority *authority)
+{
+  guint n;
+  GPtrArray *p;
+
+  p = g_ptr_array_new ();
+  for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
+    {
+      GFile *file;
+      GError *error;
+      GFileMonitor *monitor;
+
+      file = g_file_new_for_path (authority->priv->rules_dirs[n]);
+      error = NULL;
+      monitor = g_file_monitor_directory (file,
+                                          G_FILE_MONITOR_NONE,
+                                          NULL,
+                                          &error);
+      if (monitor == NULL)
+        {
+          g_warning ("Error monitoring directory %s: %s",
+                     authority->priv->rules_dirs[n],
+                     error->message);
+          g_clear_error (&error);
+        }
+      else
+        {
+          g_signal_connect (monitor,
+                            "changed",
+                            G_CALLBACK (on_dir_monitor_changed),
+                            authority);
+          g_ptr_array_add (p, monitor);
+        }
+    }
+  g_ptr_array_add (p, NULL);
+  authority->priv->dir_monitors = (GFileMonitor**) g_ptr_array_free (p, FALSE);
+}
+
 static void
 polkit_backend_js_authority_constructed (GObject *object)
 {
@@ -372,6 +444,14 @@ polkit_backend_js_authority_constructed (GObject *object)
       goto fail;
     }
 
+  if (authority->priv->rules_dirs == NULL)
+    {
+      authority->priv->rules_dirs = g_new0 (gchar *, 3);
+      authority->priv->rules_dirs[0] = g_strdup (PACKAGE_SYSCONF_DIR "/polkit-1/rules.d");
+      authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
+    }
+
+  setup_file_monitors (authority);
   load_scripts (authority);
 
   G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
@@ -386,15 +466,18 @@ static void
 polkit_backend_js_authority_finalize (GObject *object)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
+  guint n;
 
-  g_free (authority->priv->rules_dir);
-  if (authority->priv->dir_monitor != NULL)
+  for (n = 0; authority->priv->dir_monitors != NULL && authority->priv->dir_monitors[n] != NULL; n++)
     {
-      g_signal_handlers_disconnect_by_func (authority->priv->dir_monitor,
+      GFileMonitor *monitor = authority->priv->dir_monitors[n];
+      g_signal_handlers_disconnect_by_func (monitor,
                                             G_CALLBACK (on_dir_monitor_changed),
                                             authority);
-      g_object_unref (authority->priv->dir_monitor);
+      g_object_unref (monitor);
     }
+  g_free (authority->priv->dir_monitors);
+  g_strfreev (authority->priv->rules_dirs);
 
   JS_DestroyContext (authority->priv->cx);
   JS_DestroyRuntime (authority->priv->rt);
@@ -410,35 +493,12 @@ polkit_backend_js_authority_set_property (GObject      *object,
                                           GParamSpec   *pspec)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
-  GFile *file;
-  GError *error;
 
   switch (property_id)
     {
-      case PROP_RULES_DIR:
-        g_assert (authority->priv->rules_dir == NULL);
-        authority->priv->rules_dir = g_value_dup_string (value);
-
-        file = g_file_new_for_path (authority->priv->rules_dir);
-        error = NULL;
-        authority->priv->dir_monitor = g_file_monitor_directory (file,
-                                                                 G_FILE_MONITOR_NONE,
-                                                                 NULL,
-                                                                 &error);
-        if (authority->priv->dir_monitor == NULL)
-          {
-            g_warning ("Error monitoring directory %s: %s",
-                       authority->priv->rules_dir,
-                       error->message);
-            g_clear_error (&error);
-          }
-        else
-          {
-            g_signal_connect (authority->priv->dir_monitor,
-                              "changed",
-                              G_CALLBACK (on_dir_monitor_changed),
-                              authority);
-          }
+      case PROP_RULES_DIRS:
+        g_assert (authority->priv->rules_dirs == NULL);
+        authority->priv->rules_dirs = (gchar **) g_value_dup_boxed (value);
         break;
 
       default:
@@ -488,12 +548,12 @@ polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
   interactive_authority_class->check_authorization_sync = polkit_backend_js_authority_check_authorization_sync;
 
   g_object_class_install_property (gobject_class,
-                                   PROP_RULES_DIR,
-                                   g_param_spec_string ("rules-dir",
-                                                        NULL,
-                                                        NULL,
-                                                        PACKAGE_SYSCONF_DIR "/polkit-1/rules.d",
-                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+                                   PROP_RULES_DIRS,
+                                   g_param_spec_boxed ("rules-dirs",
+                                                       NULL,
+                                                       NULL,
+                                                       G_TYPE_STRV,
+                                                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
 
 
   g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 9453c44..d4bb324 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -2,6 +2,8 @@
 
 /* see test/polkitbackend/test-polkitbackendjsauthority.c */
 
+/* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
+
 polkit.addAdministratorRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
 });
diff --git a/test/data/usr/share/polkit-1/rules.d/10-testing.rules b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
new file mode 100644
index 0000000..ab2fd97
--- /dev/null
+++ b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
@@ -0,0 +1,5 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+/* see test/polkitbackend/test-polkitbackendjsauthority.c */
+
+/* NOTE: this is the /usr/share/polkit-1/rules.d version of 10-testing.rules */
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index bc1b242..67f5d8b 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -36,16 +36,20 @@ static PolkitBackendJsAuthority *get_authority (void);
 static PolkitBackendJsAuthority *
 get_authority (void)
 {
-  gchar *rules_dir;
+  gchar *rules_dirs[3] = {0};
   PolkitBackendJsAuthority *authority;
 
-  rules_dir = polkit_test_get_data_path ("etc/polkit-1/rules.d");
-  g_assert (rules_dir != NULL);
+  rules_dirs[0] = polkit_test_get_data_path ("etc/polkit-1/rules.d");
+  rules_dirs[1] = polkit_test_get_data_path ("usr/share/polkit-1/rules.d");
+  rules_dirs[2] = NULL;
+  g_assert (rules_dirs[0] != NULL);
+  g_assert (rules_dirs[1] != NULL);
 
   authority = g_object_new (POLKIT_BACKEND_TYPE_JS_AUTHORITY,
-                            "rules-dir", rules_dir,
+                            "rules-dirs", rules_dirs,
                             NULL);
-  g_free (rules_dir);
+  g_free (rules_dirs[0]);
+  g_free (rules_dirs[1]);
   return authority;
 }
 
commit 55b3314cb1f4fd887f50b7a312efd8703dfa8889
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 10:17:19 2012 -0400

    docs: clarify how rules files work
    
    After feedback from Matthias Clasen <mclasen at redhat.com>.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index bbe44f7..2aa1da1 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -448,18 +448,33 @@ System Context         |                        |
 
   <refsect1 id="polkit-rules"><title>AUTHORIZATION RULES</title>
     <para>
-      <command>polkitd</command> reads <filename
-      class='extension'>.rules</filename> files from the <filename
-      class='directory'>/etc/polkit-1/rules.d</filename> directory in
-      lexical order. This directory is monitored so if a rules file is
-      changed, added or removed, existing rules are purged and all
-      files are read and processed again.  Rules files are written in
-      the <ulink
-      url="http://en.wikipedia.org/wiki/JavaScript">JavaScript</ulink>
-      programming language and interface with
-      <command>polkitd</command> through the global
-      <literal>polkit</literal> object (of type <type>Polkit</type>)
-      using the following methods:
+      <command>polkitd</command> reads
+      <filename class='extension'>.rules</filename> files from the
+      <filename class='directory'>/etc/polkit-1/rules.d</filename> and
+      <filename class='directory'>/usr/share/polkit-1/rules.d</filename>
+      directories by sorting the files in lexical order based on the
+      basename on each file (and if there's a tie, files in
+      <filename class='directory'>/etc</filename>
+      are processed before files in
+      <filename class='directory'>/usr</filename>).
+      For example, for the following four
+      files, the order is
+    </para>
+    <itemizedlist mark='opencircle' spacing='compact'>
+      <listitem><para><filename>/etc/polkit-1/rules.d/10-auth.rules</filename></para></listitem>
+      <listitem><para><filename>/usr/share/polkit-1/rules.d/10-auth.rules</filename></para></listitem>
+      <listitem><para><filename>/etc/polkit-1/rules.d/15-auth.rules</filename></para></listitem>
+      <listitem><para><filename>/usr/share/polkit-1/rules.d/20-auth.rules</filename></para></listitem>
+    </itemizedlist>
+    <para>
+      Both directories are monitored so if a rules file is changed,
+      added or removed, existing rules are purged and all files are
+      read and processed again.  Rules files are written in the
+      <ulink url="http://en.wikipedia.org/wiki/JavaScript">JavaScript</ulink>
+      programming language and interface with <command>polkitd</command>
+      through the global
+      <literal>polkit</literal> object (of type <type>Polkit</type>).
+      The following methods are available:
     </para>
 
     <funcsynopsis>
@@ -498,12 +513,21 @@ System Context         |                        |
       The <function>addRule()</function> method is used for adding a
       function that is called whenever an authorization check for
       <parameter>action</parameter>, <parameter>subject</parameter>
-      and <parameter>details</parameter> is performed. The function
-      should return one of the values <literal>"no"</literal>,
+      and <parameter>details</parameter> is performed. Functions are
+      called in the order they have been added until one of the
+      functions returns a value. Hence, to add an authorization rule
+      that is processed before other rules, put it in a file in
+      <filename class='directory'>/etc/polkit-1/rules.d</filename>
+      with a name that sorts before other rules files, for example
+      <filename>00-early-checks.rules</filename>. Each function should
+      return one of the values <literal>"no"</literal>,
       <literal>"yes"</literal>, <literal>"auth_self"</literal>,
       <literal>"auth_self_keep"</literal>,
       <literal>"auth_admin"</literal>,
-      <literal>"auth_admin_keep"</literal> as defined above.
+      <literal>"auth_admin_keep"</literal> as defined above. If the
+      function returns <constant>null</constant>,
+      <constant>undefined</constant> or does not return a value at
+      all, the next function is tried.
     </para>
 
     <para>
@@ -513,10 +537,15 @@ System Context         |                        |
       identies may be used for administrator authentication for the
       authorization check identified by <parameter>action</parameter>,
       <parameter>subject</parameter> and
-      <parameter>details</parameter>. The function should return an
-      array of strings where each string is of the form
+      <parameter>details</parameter>. Functions added are called in
+      the order they have been added until one of the functions
+      returns a value. Each function should return an array of strings
+      where each string is of the form
       <literal>"unix-group:&lt;group&gt;"</literal> or
-      <literal>"unix-user:&lt;user&gt;"</literal>.
+      <literal>"unix-user:&lt;user&gt;"</literal>.  If the function
+      returns <constant>null</constant>,
+      <constant>undefined</constant> or does not return a value at
+      all, the next function is tried.
     </para>
 
     <para>
@@ -640,7 +669,9 @@ System Context         |                        |
       <title>Authorzation Rules Examples</title>
 
       <para>
-        Allow all users in the <literal>admin</literal> group to perform user administration:
+        Allow all users in the <literal>admin</literal> group to
+        perform user administration without changing policy for other
+        users:
       </para>
       <programlisting><![CDATA[
 polkit.addRule(function(action, subject, details) {
@@ -667,7 +698,7 @@ polkit.addAdminRule(function(action, subject, details) {
       </para>
       <programlisting><![CDATA[
 function has_prefix(str, prefix) {
-  return str.indexOf(prefix) == 0;
+    return str.indexOf(prefix) == 0;
 }
 
 polkit.addRule(function(action, subject, details) {
commit 3f2b970e28bd10e8cac93673e2f250406e84ccb9
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun May 20 15:04:03 2012 -0400

    Also add an example of polkit.spawn() to polkit(8) man page
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 7634a44..bbe44f7 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -681,6 +681,26 @@ polkit.addRule(function(action, subject, details) {
 });
 ]]></programlisting>
 
+      <para>
+        Run an external helper to determine if the current user may reboot the system:
+      </para>
+      <programlisting><![CDATA[
+polkit.addRule(function(action, subject, details) {
+    if (action.indexOf("org.freedesktop.login1.reboot") == 0) {
+        try {
+            // user-may-reboot exits with succeess (exit code 0)
+            // only if the passed username is authorized
+            polkit.spawn(["/opt/company/bin/user-may-reboot",
+                          subject.user]);
+            return "yes";
+        } catch (error) {
+            // Nope, but do allow admin authentication
+            return "auth_admin";
+        }
+    }
+});
+]]></programlisting>
+
     </refsect2>
   </refsect1>
 
commit b72839d3a525409ba39962ce91f499e74cb37e16
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun May 20 14:55:56 2012 -0400

    docs: add AUTHORIZATION RULES section to the polkit(8) man page
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/docs/man/polkit.xml b/docs/man/polkit.xml
index 188c514..7634a44 100644
--- a/docs/man/polkit.xml
+++ b/docs/man/polkit.xml
@@ -446,6 +446,244 @@ System Context         |                        |
 
   </refsect1>
 
+  <refsect1 id="polkit-rules"><title>AUTHORIZATION RULES</title>
+    <para>
+      <command>polkitd</command> reads <filename
+      class='extension'>.rules</filename> files from the <filename
+      class='directory'>/etc/polkit-1/rules.d</filename> directory in
+      lexical order. This directory is monitored so if a rules file is
+      changed, added or removed, existing rules are purged and all
+      files are read and processed again.  Rules files are written in
+      the <ulink
+      url="http://en.wikipedia.org/wiki/JavaScript">JavaScript</ulink>
+      programming language and interface with
+      <command>polkitd</command> through the global
+      <literal>polkit</literal> object (of type <type>Polkit</type>)
+      using the following methods:
+    </para>
+
+    <funcsynopsis>
+      <funcprototype>
+        <?dbhtml funcsynopsis-style='ansi'?>
+        <funcdef>void <function>addRule</function></funcdef>
+        <paramdef>string <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
+      </funcprototype>
+    </funcsynopsis>
+
+    <funcsynopsis>
+      <funcprototype>
+        <?dbhtml funcsynopsis-style='ansi'?>
+        <funcdef>void <function>addAdminRule</function></funcdef>
+        <paramdef>string[] <function>function</function>(<parameter>action</parameter>, <parameter>subject</parameter>, <parameter>details</parameter>) {...}</paramdef>
+      </funcprototype>
+    </funcsynopsis>
+
+    <funcsynopsis>
+      <funcprototype>
+        <?dbhtml funcsynopsis-style='ansi'?>
+        <funcdef>void <function>log</function></funcdef>
+        <paramdef>string <parameter>message</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+
+    <funcsynopsis>
+      <funcprototype>
+        <?dbhtml funcsynopsis-style='ansi'?>
+        <funcdef>string <function>spawn</function></funcdef>
+        <paramdef>string[] <parameter>argv</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+
+    <para>
+      The <function>addRule()</function> method is used for adding a
+      function that is called whenever an authorization check for
+      <parameter>action</parameter>, <parameter>subject</parameter>
+      and <parameter>details</parameter> is performed. The function
+      should return one of the values <literal>"no"</literal>,
+      <literal>"yes"</literal>, <literal>"auth_self"</literal>,
+      <literal>"auth_self_keep"</literal>,
+      <literal>"auth_admin"</literal>,
+      <literal>"auth_admin_keep"</literal> as defined above.
+    </para>
+
+    <para>
+      The <function>addAdminRule()</function> method is used for
+      adding a function that is called whenever administrator
+      authentication is required. The function is used to specify what
+      identies may be used for administrator authentication for the
+      authorization check identified by <parameter>action</parameter>,
+      <parameter>subject</parameter> and
+      <parameter>details</parameter>. The function should return an
+      array of strings where each string is of the form
+      <literal>"unix-group:&lt;group&gt;"</literal> or
+      <literal>"unix-user:&lt;user&gt;"</literal>.
+    </para>
+
+    <para>
+      The <function>log()</function> method writes the given
+      <parameter>message</parameter> to the system logger. Log entries
+      are emitted using the <constant>LOG_AUTHPRIV</constant> flag
+      meaning that the log entries usually ends up in the file
+      <filename>/var/log/secure</filename>. The
+      <function>log()</function> method is usually only used when
+      debugging rules.
+    </para>
+
+    <para>
+      The <function>spawn()</function> method spawns an external
+      helper identified by the argument vector
+      <parameter>argv</parameter> and waits for it to terminate. If an
+      error occurs or the helper doesn't exit normally with exit code
+      0, an exception is thrown. If the helper does not exit within 10
+      seconds it is killed. Otherwise, the program's
+      <emphasis>standard output</emphasis> is returned as a string.
+      The <function>spawn()</function> method should be used sparingly
+      as helpers may take a very long or indeterminate amount of time
+      to complete and no other authorization check can be handled
+      while the helper is running.
+    </para>
+
+    <refsect2 id="polkit-rules-subject">
+      <title>The <type>Subject</type> type</title>
+
+      <para>
+        The <parameter>subject</parameter> parameter passed to user
+        functions is an object with information about the process
+        being checked. It is of type <type>Subject</type> and has the
+        following attributes
+      </para>
+
+      <informaltable id="polkit-js-subject-attributes">
+        <tgroup cols="3" align="left">
+          <thead>
+            <row>
+              <entry>Attribute</entry>
+              <entry>Type</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><parameter>pid</parameter></entry>
+              <entry><type>int</type></entry>
+              <entry>The process id</entry>
+            </row>
+            <row>
+              <entry><parameter>user</parameter></entry>
+              <entry><type>string</type></entry>
+              <entry>The user name</entry>
+            </row>
+            <row>
+              <entry><parameter>groups</parameter></entry>
+              <entry><type>string[]</type></entry>
+              <entry>Array of groups that <parameter>user</parameter> user belongs to</entry>
+            </row>
+            <row>
+              <entry><parameter>seat</parameter></entry>
+              <entry><type>string</type></entry>
+              <entry>The seat that the subject is associated with - blank if not on a local seat</entry>
+            </row>
+            <row>
+              <entry><parameter>session</parameter></entry>
+              <entry><type>string</type></entry>
+              <entry>The session that the subject is associated with</entry>
+            </row>
+            <row>
+              <entry><parameter>local</parameter></entry>
+              <entry><type>boolean</type></entry>
+              <entry>Set to <constant>true</constant> only if seat is local</entry>
+            </row>
+            <row>
+              <entry><parameter>active</parameter></entry>
+              <entry><type>boolean</type></entry>
+              <entry>Set to <constant>true</constant> only if the session is active</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+
+      <para>
+        The following methods are available on the <type>Subject</type> type:
+      </para>
+
+      <funcsynopsis>
+        <funcprototype>
+          <?dbhtml funcsynopsis-style='ansi'?>
+          <funcdef>boolean <function>isInGroup</function></funcdef>
+          <paramdef>string <parameter>groupName</parameter></paramdef>
+        </funcprototype>
+      </funcsynopsis>
+
+    </refsect2>
+
+    <refsect2 id="polkit-rules-details">
+      <title>The <type>Details</type> type</title>
+
+      <para>
+        The <parameter>details</parameter> parameter passed to user
+        functions is an object with more information about the action
+        being checked. It is of type <type>Details</type> and has
+        details being set by the mechanism as attributes. For example,
+        the <link
+        linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
+        mechanism sets the details <literal>user</literal>,
+        <literal>program</literal> and <literal>command_line</literal>
+        which can be obtained through e.g. the following JavaScript
+        expression: <literal>details["program"]</literal>. Consult the
+        documentation for each mechanism for what details are
+        available for each action.
+      </para>
+
+    </refsect2>
+
+    <refsect2 id="polkit-rules-examples">
+      <title>Authorzation Rules Examples</title>
+
+      <para>
+        Allow all users in the <literal>admin</literal> group to perform user administration:
+      </para>
+      <programlisting><![CDATA[
+polkit.addRule(function(action, subject, details) {
+    if (action == "org.freedesktop.accounts.user-administration" &&
+        subject.isInGroup("admin")) {
+        return "yes";
+    }
+});
+]]></programlisting>
+
+      <para>
+        Define administrative users to be the users in the <literal>wheel</literal> group:
+      </para>
+      <programlisting><![CDATA[
+polkit.addAdminRule(function(action, subject, details) {
+    return ["unix-group:wheel"];
+});
+]]></programlisting>
+
+      <para>
+        Forbid users in group <literal>children</literal> to change
+        hostname configuration and allow anyone else to do it (after
+        authenticating as themselves):
+      </para>
+      <programlisting><![CDATA[
+function has_prefix(str, prefix) {
+  return str.indexOf(prefix) == 0;
+}
+
+polkit.addRule(function(action, subject, details) {
+    if (has_prefix(action, "org.freedesktop.hostname1.")) {
+        if (subject.isInGroup("children")) {
+            return "no";
+        } else {
+            return "auth_self_keep";
+        }
+    }
+});
+]]></programlisting>
+
+    </refsect2>
+  </refsect1>
+
   <refsect1 id="polkit-author"><title>AUTHOR</title>
     <para>
       Written by David Zeuthen <email>davidz at redhat.com</email> with
commit 26b01b5057a38149a5a5fdbe04a39e0488273acb
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 20:27:56 2012 -0400

    Don't include command-line in spawning error messages
    
    We don't even know it and it's not worth reconstructing it.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index c2023b8..1d6e156 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -1076,7 +1076,6 @@ js_polkit_spawn (JSContext  *cx,
   /* PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx)); */
   JSBool ret = JS_FALSE;
   JSObject *array_object;
-  gchar *command_line = NULL;
   gchar *standard_output = NULL;
   gchar *standard_error = NULL;
   gint exit_status;
@@ -1123,8 +1122,7 @@ js_polkit_spawn (JSContext  *cx,
                      &error))
     {
       JS_ReportError (cx,
-                      "Failed to spawn command-line `%s': %s (%s, %d)",
-                      command_line,
+                      "Failed to spawn helper: %s (%s, %d)",
                       error->message, g_quark_to_string (error->domain), error->code);
       g_clear_error (&error);
       goto out;
@@ -1137,15 +1135,13 @@ js_polkit_spawn (JSContext  *cx,
       if (WIFEXITED (exit_status))
         {
           g_string_append_printf (gstr,
-                                  "Command-line `%s' exited with non-zero exit status %d",
-                                  command_line,
+                                  "Helper exited with non-zero exit status %d",
                                   WEXITSTATUS (exit_status));
         }
       else if (WIFSIGNALED (exit_status))
         {
           g_string_append_printf (gstr,
-                                  "Command-line `%s' was signaled with signal %s (%d)",
-                                  command_line,
+                                  "Helper was signaled with signal %s (%d)",
                                   get_signal_name (WTERMSIG (exit_status)),
                                   WTERMSIG (exit_status));
         }
@@ -1163,7 +1159,6 @@ js_polkit_spawn (JSContext  *cx,
 
  out:
   g_strfreev (argv);
-  g_free (command_line);
   g_free (standard_output);
   g_free (standard_error);
   return ret;
commit 2dddf282215a54ffa9be1b78e62e0c78e3ee8bea
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 20:18:01 2012 -0400

    Make polkit.spawn() take an array of arguments instead of a command-line
    
    Much safer and easier this way.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 427994d..ec6b7ae 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -71,7 +71,3 @@ polkit._deleteRules = function() {
     this._administratorRuleFuncs = [];
     this._authorizationRuleFuncs = [];
 };
-
-polkit.quote = function(str) {
-    return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
-};
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 9b840fa..c2023b8 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -1070,30 +1070,57 @@ get_signal_name (gint signal_number)
 
 static JSBool
 js_polkit_spawn (JSContext  *cx,
-                 uintN       argc,
+                 uintN       js_argc,
                  jsval      *vp)
 {
   /* PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx)); */
   JSBool ret = JS_FALSE;
-  JSString *str;
-  char *command_line = NULL;
+  JSObject *array_object;
+  gchar *command_line = NULL;
   gchar *standard_output = NULL;
   gchar *standard_error = NULL;
   gint exit_status;
   GError *error = NULL;
   JSString *ret_jsstr;
+  jsuint array_len;
+  gchar **argv = NULL;
+  guint n;
 
-  if (!JS_ConvertArguments (cx, argc, JS_ARGV (cx, vp), "S", &str))
+  if (!JS_ConvertArguments (cx, js_argc, JS_ARGV (cx, vp), "o", &array_object))
     goto out;
 
-  command_line = JS_EncodeString (cx, str);
+  if (!JS_GetArrayLength (cx, array_object, &array_len))
+    {
+      JS_ReportError (cx, "Failed to get array length");
+      goto out;
+    }
+
+  argv = g_new0 (gchar*, array_len + 1);
+  for (n = 0; n < array_len; n++)
+    {
+      jsval elem_val;
+      char *s;
+
+      if (!JS_GetElement (cx, array_object, n, &elem_val))
+        {
+          JS_ReportError (cx, "Failed to get element %d", n);
+          goto out;
+        }
+      s = JS_EncodeString (cx, JSVAL_TO_STRING (elem_val));
+      argv[n] = g_strdup (s);
+      JS_free (cx, s);
+    }
 
-  /* TODO: timeout */
-  if (!g_spawn_command_line_sync (command_line,
-                                  &standard_output,
-                                  &standard_error,
-                                  &exit_status,
-                                  &error))
+  /* TODO: set a timeout */
+  if (!g_spawn_sync (NULL, /* working dir */
+                     argv,
+                     NULL, /* envp */
+                     G_SPAWN_SEARCH_PATH,
+                     NULL, NULL, /* child_setup, user_data */
+                     &standard_output,
+                     &standard_error,
+                     &exit_status,
+                     &error))
     {
       JS_ReportError (cx,
                       "Failed to spawn command-line `%s': %s (%s, %d)",
@@ -1135,10 +1162,10 @@ js_polkit_spawn (JSContext  *cx,
   JS_SET_RVAL (cx, vp, STRING_TO_JSVAL (ret_jsstr));
 
  out:
+  g_strfreev (argv);
+  g_free (command_line);
   g_free (standard_output);
   g_free (standard_error);
-  if (command_line != NULL)
-    JS_free (cx, command_line);
   return ret;
 }
 
commit d6e87bcda9b3b3eedfad58c4444c140000a731a8
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 19:57:50 2012 -0400

    Add polkit.spawn() to spawn external programs
    
    ... and also add polkit.quote() for quoting arguments when
    constructing the command-line.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 4f1cc72..427994d 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -72,3 +72,6 @@ polkit._deleteRules = function() {
     this._authorizationRuleFuncs = [];
 };
 
+polkit.quote = function(str) {
+    return '"' + str.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
+};
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 81cccd0..9b840fa 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -143,10 +143,12 @@ static JSClass js_polkit_class = {
 };
 
 static JSBool js_polkit_log (JSContext *cx, uintN argc, jsval *vp);
+static JSBool js_polkit_spawn (JSContext *cx, uintN argc, jsval *vp);
 
 static JSFunctionSpec js_polkit_functions[] =
 {
   JS_FS("log",            js_polkit_log,            0, 0),
+  JS_FS("spawn",          js_polkit_spawn,          0, 0),
   JS_FS_END
 };
 
@@ -929,6 +931,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
       goto out;
     }
 
+  g_strstrip (ret_str);
   if (!polkit_implicit_authorization_from_string (ret_str, &ret))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
@@ -1023,3 +1026,120 @@ js_polkit_log (JSContext  *cx,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+
+static const gchar *
+get_signal_name (gint signal_number)
+{
+  switch (signal_number)
+    {
+#define _HANDLE_SIG(sig) case sig: return #sig;
+    _HANDLE_SIG (SIGHUP);
+    _HANDLE_SIG (SIGINT);
+    _HANDLE_SIG (SIGQUIT);
+    _HANDLE_SIG (SIGILL);
+    _HANDLE_SIG (SIGABRT);
+    _HANDLE_SIG (SIGFPE);
+    _HANDLE_SIG (SIGKILL);
+    _HANDLE_SIG (SIGSEGV);
+    _HANDLE_SIG (SIGPIPE);
+    _HANDLE_SIG (SIGALRM);
+    _HANDLE_SIG (SIGTERM);
+    _HANDLE_SIG (SIGUSR1);
+    _HANDLE_SIG (SIGUSR2);
+    _HANDLE_SIG (SIGCHLD);
+    _HANDLE_SIG (SIGCONT);
+    _HANDLE_SIG (SIGSTOP);
+    _HANDLE_SIG (SIGTSTP);
+    _HANDLE_SIG (SIGTTIN);
+    _HANDLE_SIG (SIGTTOU);
+    _HANDLE_SIG (SIGBUS);
+    _HANDLE_SIG (SIGPOLL);
+    _HANDLE_SIG (SIGPROF);
+    _HANDLE_SIG (SIGSYS);
+    _HANDLE_SIG (SIGTRAP);
+    _HANDLE_SIG (SIGURG);
+    _HANDLE_SIG (SIGVTALRM);
+    _HANDLE_SIG (SIGXCPU);
+    _HANDLE_SIG (SIGXFSZ);
+#undef _HANDLE_SIG
+    default:
+      break;
+    }
+  return "UNKNOWN_SIGNAL";
+}
+
+static JSBool
+js_polkit_spawn (JSContext  *cx,
+                 uintN       argc,
+                 jsval      *vp)
+{
+  /* PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx)); */
+  JSBool ret = JS_FALSE;
+  JSString *str;
+  char *command_line = NULL;
+  gchar *standard_output = NULL;
+  gchar *standard_error = NULL;
+  gint exit_status;
+  GError *error = NULL;
+  JSString *ret_jsstr;
+
+  if (!JS_ConvertArguments (cx, argc, JS_ARGV (cx, vp), "S", &str))
+    goto out;
+
+  command_line = JS_EncodeString (cx, str);
+
+  /* TODO: timeout */
+  if (!g_spawn_command_line_sync (command_line,
+                                  &standard_output,
+                                  &standard_error,
+                                  &exit_status,
+                                  &error))
+    {
+      JS_ReportError (cx,
+                      "Failed to spawn command-line `%s': %s (%s, %d)",
+                      command_line,
+                      error->message, g_quark_to_string (error->domain), error->code);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  if (!(WIFEXITED (exit_status) && WEXITSTATUS (exit_status) == 0))
+    {
+      GString *gstr;
+      gstr = g_string_new (NULL);
+      if (WIFEXITED (exit_status))
+        {
+          g_string_append_printf (gstr,
+                                  "Command-line `%s' exited with non-zero exit status %d",
+                                  command_line,
+                                  WEXITSTATUS (exit_status));
+        }
+      else if (WIFSIGNALED (exit_status))
+        {
+          g_string_append_printf (gstr,
+                                  "Command-line `%s' was signaled with signal %s (%d)",
+                                  command_line,
+                                  get_signal_name (WTERMSIG (exit_status)),
+                                  WTERMSIG (exit_status));
+        }
+      g_string_append_printf (gstr, ", stdout=`%s', stderr=`%s'",
+                              standard_output, standard_error);
+      JS_ReportError (cx, gstr->str);
+      g_string_free (gstr, TRUE);
+      goto out;
+    }
+
+  ret = JS_TRUE;
+
+  ret_jsstr = JS_NewStringCopyZ (cx, standard_output);
+  JS_SET_RVAL (cx, vp, STRING_TO_JSVAL (ret_jsstr));
+
+ out:
+  g_free (standard_output);
+  g_free (standard_error);
+  if (command_line != NULL)
+    JS_free (cx, command_line);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
commit 3b7868b33033ed8dde17bb6b88ef461f4ecbb93f
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 17:23:18 2012 -0400

    Make it possible for JS code to change details
    
    For example, to set the authentication message, a JS function can
    simply do
    
     details["polkit.message"] = "Hey dude, XYZ, I need your password";
    
    This can also be used to pass data back to the mechanism.
    
    To make this work properly, we also introduce a slight change: the
    a{ss} passed back to the mechanism (part of the AuthorizationResult
    structure) will be initialized with the a{ss} the app passed itself in
    the CheckAuthorization() call.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index 5f6eea5..171e686 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -80,6 +80,7 @@ typedef void (*AuthenticationAgentCallback) (AuthenticationAgent         *agent,
                                              PolkitSubject               *caller,
                                              PolkitBackendInteractiveAuthority *authority,
                                              const gchar                 *action_id,
+                                             PolkitDetails               *details,
                                              PolkitImplicitAuthorization  implicit_authorization,
                                              gboolean                     authentication_success,
                                              gboolean                     was_dismissed,
@@ -595,6 +596,7 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
                                   PolkitSubject               *caller,
                                   PolkitBackendInteractiveAuthority *authority,
                                   const gchar                 *action_id,
+                                  PolkitDetails               *details,
                                   PolkitImplicitAuthorization  implicit_authorization,
                                   gboolean                     authentication_success,
                                   gboolean                     was_dismissed,
@@ -610,7 +612,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
   gchar *authenticated_identity_str;
   gchar *subject_cmdline;
   gboolean is_temp;
-  PolkitDetails *details;
 
   priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (authority);
 
@@ -637,7 +638,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
            was_dismissed,
            authentication_success);
 
-  details = polkit_details_new ();
   if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
       implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
     polkit_details_insert (details, "polkit.retains_authorization_after_challenge", "true");
@@ -715,7 +715,6 @@ check_authorization_challenge_cb (AuthenticationAgent         *agent,
 
   /* log_result (authority, action_id, subject, caller, result); */
 
-  g_object_unref (details);
   g_simple_async_result_set_op_res_gpointer (simple,
                                              result,
                                              g_object_unref);
@@ -1047,7 +1046,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   gboolean session_is_active;
   PolkitImplicitAuthorization implicit_authorization;
   const gchar *tmp_authz_id;
-  PolkitDetails *result_details;
   GList *actions;
   GList *l;
 
@@ -1061,7 +1059,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   groups_of_user = NULL;
   subject_str = NULL;
   session_for_subject = NULL;
-  result_details = NULL;
 
   session_is_local = FALSE;
   session_is_active = FALSE;
@@ -1130,8 +1127,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
       implicit_authorization = polkit_action_description_get_implicit_any (action_desc);
     }
 
-  result_details = polkit_details_new ();
-
   /* allow subclasses to rewrite implicit_authorization */
   implicit_authorization = polkit_backend_interactive_authority_check_authorization_sync (interactive_authority,
                                                                                           caller,
@@ -1141,16 +1136,14 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
                                                                                           session_is_active,
                                                                                           action_id,
                                                                                           details,
-                                                                                          implicit_authorization,
-                                                                                          result_details);
-
+                                                                                          implicit_authorization);
   /* first see if there's an implicit authorization for subject available */
   if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHORIZED)
     {
       g_debug (" is authorized (has implicit authorization local=%d active=%d)",
                session_is_local,
                session_is_active);
-      result = polkit_authorization_result_new (TRUE, FALSE, result_details);
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
       goto out;
     }
 
@@ -1162,8 +1155,8 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
     {
 
       g_debug (" is authorized (has temporary authorization)");
-      polkit_details_insert (result_details, "polkit.temporary_authorization_id", tmp_authz_id);
-      result = polkit_authorization_result_new (TRUE, FALSE, result_details);
+      polkit_details_insert (details, "polkit.temporary_authorization_id", tmp_authz_id);
+      result = polkit_authorization_result_new (TRUE, FALSE, details);
       goto out;
     }
 
@@ -1210,7 +1203,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
                               g_debug (" is authorized (implied by %s)", imply_action_id);
                               result = implied_result;
                               /* cleanup */
-                              g_object_unref (result_details);
                               g_strfreev (tokens);
                               goto out;
                             }
@@ -1230,10 +1222,10 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
       if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED ||
           implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED)
         {
-          polkit_details_insert (result_details, "polkit.retains_authorization_after_challenge", "1");
+          polkit_details_insert (details, "polkit.retains_authorization_after_challenge", "1");
         }
 
-      result = polkit_authorization_result_new (FALSE, TRUE, result_details);
+      result = polkit_authorization_result_new (FALSE, TRUE, details);
 
       /* return implicit_authorization so the caller can use an authentication agent if applicable */
       if (out_implicit_authorization != NULL)
@@ -1244,7 +1236,7 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
     }
   else
     {
-      result = polkit_authorization_result_new (FALSE, FALSE, result_details);
+      result = polkit_authorization_result_new (FALSE, FALSE, details);
       g_debug (" not authorized");
     }
  out:
@@ -1265,9 +1257,6 @@ check_authorization_sync (PolkitBackendAuthority         *authority,
   if (action_desc != NULL)
     g_object_unref (action_desc);
 
-  if (result_details != NULL)
-    g_object_unref (result_details);
-
   g_debug (" ");
 
   return result;
@@ -1332,12 +1321,10 @@ polkit_backend_interactive_authority_get_admin_identities (PolkitBackendInteract
  * @action_id: The action we are checking an authorization for.
  * @details: Details about the action.
  * @implicit: A #PolkitImplicitAuthorization value computed from the policy file and @subject.
- * @out_details: A #PolkitDetails object that will be return to @caller.
  *
  * Checks whether @subject is authorized to perform the action
- * specified by @action_id and @details. The implementation may
- * append key/value pairs to @out_details to return extra information
- * to @caller.
+ * specified by @action_id and @details. The implementation may append
+ * key/value pairs to @details to return extra information to @caller.
  *
  * The default implementation of this method simply returns @implicit.
  *
@@ -1353,8 +1340,7 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte
                                                                gboolean                           subject_is_active,
                                                                const gchar                       *action_id,
                                                                PolkitDetails                     *details,
-                                                               PolkitImplicitAuthorization        implicit,
-                                                               PolkitDetails                     *out_details)
+                                                               PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendInteractiveAuthorityClass *klass;
   PolkitImplicitAuthorization ret;
@@ -1375,8 +1361,7 @@ polkit_backend_interactive_authority_check_authorization_sync (PolkitBackendInte
                                              subject_is_active,
                                              action_id,
                                              details,
-                                             implicit,
-                                             out_details);
+                                             implicit);
     }
 
   return ret;
@@ -1402,6 +1387,8 @@ struct AuthenticationSession
 
   gchar                       *action_id;
 
+  PolkitDetails               *details;
+
   gchar                       *initiated_by_system_bus_unique_name;
 
   PolkitImplicitAuthorization  implicit_authorization;
@@ -1436,6 +1423,7 @@ authentication_session_new (AuthenticationAgent         *agent,
                             PolkitBackendInteractiveAuthority *authority,
                             GList                       *identities,
                             const gchar                 *action_id,
+                            PolkitDetails               *details,
                             const gchar                 *initiated_by_system_bus_unique_name,
                             PolkitImplicitAuthorization  implicit_authorization,
                             GCancellable                *cancellable,
@@ -1454,6 +1442,7 @@ authentication_session_new (AuthenticationAgent         *agent,
   session->identities = g_list_copy (identities);
   g_list_foreach (session->identities, (GFunc) g_object_ref, NULL);
   session->action_id = g_strdup (action_id);
+  session->details = g_object_ref (details);
   session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name);
   session->implicit_authorization = implicit_authorization;
   session->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
@@ -1483,6 +1472,7 @@ authentication_session_free (AuthenticationSession *session)
   g_object_unref (session->caller);
   g_object_unref (session->authority);
   g_free (session->action_id);
+  g_object_unref (session->details);
   g_free (session->initiated_by_system_bus_unique_name);
   if (session->cancellable_signal_handler_id > 0)
     g_signal_handler_disconnect (session->cancellable, session->cancellable_signal_handler_id);
@@ -1832,6 +1822,7 @@ authentication_agent_begin_cb (GDBusProxy   *proxy,
                      session->caller,
                      session->authority,
                      session->action_id,
+                     session->details,
                      session->implicit_authorization,
                      gained_authorization,
                      was_dismissed,
@@ -2228,6 +2219,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
                                         authority,
                                         identities,
                                         action_id,
+                                        details,
                                         polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)),
                                         implicit_authorization,
                                         cancellable,
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.h b/src/polkitbackend/polkitbackendinteractiveauthority.h
index 408c3e4..9820dac 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.h
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.h
@@ -83,8 +83,7 @@ struct _PolkitBackendInteractiveAuthorityClass
                                                            gboolean                           subject_is_active,
                                                            const gchar                       *action_id,
                                                            PolkitDetails                     *details,
-                                                           PolkitImplicitAuthorization        implicit,
-                                                           PolkitDetails                     *out_details);
+                                                           PolkitImplicitAuthorization        implicit);
 
   /*< private >*/
   /* Padding for future expansion */
@@ -139,8 +138,7 @@ PolkitImplicitAuthorization polkit_backend_interactive_authority_check_authoriza
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_END_DECLS
 
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index b3669d5..81cccd0 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -100,8 +100,7 @@ static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorizati
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_DEFINE_TYPE_WITH_CODE (PolkitBackendJsAuthority,
                          polkit_backend_js_authority,
@@ -193,7 +192,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
   if (dir == NULL)
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error opening rules directory: %s (%s, %d)\n",
+                                    "Error opening rules directory: %s (%s, %d)",
                                     error->message, g_quark_to_string (error->domain), error->code);
       g_clear_error (&error);
       goto out;
@@ -858,8 +857,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
                                                       gboolean                           subject_is_active,
                                                       const gchar                       *action_id,
                                                       PolkitDetails                     *details,
-                                                      PolkitImplicitAuthorization        implicit,
-                                                      PolkitDetails                     *out_details)
+                                                      PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   PolkitImplicitAuthorization ret = implicit;
@@ -871,6 +869,9 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
   gboolean good = FALSE;
+  JSIdArray *ids;
+  JSObject *details_obj;
+  gint n;
 
   action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
   argv[0] = STRING_TO_JSVAL (action_id_jstr);
@@ -931,11 +932,58 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   if (!polkit_implicit_authorization_from_string (ret_str, &ret))
     {
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Returned result `%s' is not valid\n",
+                                    "Returned result `%s' is not valid",
                                     ret_str);
       goto out;
     }
 
+
+  /* the JS code may have modifed @details - update PolkitDetails
+   * object accordingly
+   */
+  details_obj = JSVAL_TO_OBJECT (argv[2]);
+  ids = JS_Enumerate (authority->priv->cx, details_obj);
+  if (ids == NULL)
+    {
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Failed to enumerate properties of Details object");
+      goto out;
+    }
+  for (n = 0; n < ids->length; n++)
+    {
+      jsval id_val;
+      jsval value_val;
+      char *id_s = NULL;
+      char *value_s = NULL;
+
+      if (!JS_IdToValue (authority->priv->cx, ids->vector[n], &id_val))
+        {
+          g_warning ("Error getting string for property id %d", n);
+          goto cont;
+        }
+      id_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (id_val));
+
+      if (!JS_GetPropertyById (authority->priv->cx, details_obj, ids->vector[n], &value_val))
+        {
+          g_warning ("Error getting value string for property value %s", id_s);
+          goto cont;
+        }
+
+      /* skip e.g. functions */
+      if (!JSVAL_IS_STRING (value_val) && !JSVAL_IS_NULL (value_val))
+        goto cont;
+
+      value_s = JS_EncodeString (authority->priv->cx, JSVAL_TO_STRING (value_val));
+
+      polkit_details_insert (details, id_s, value_s);
+    cont:
+      if (id_s != NULL)
+        JS_free (authority->priv->cx, id_s);
+      if (value_s != NULL)
+        JS_free (authority->priv->cx, value_s);
+    }
+  JS_DestroyIdArray (authority->priv->cx, ids);
+
   good = TRUE;
 
  out:
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index b53eda3..2e5e8fe 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -100,8 +100,7 @@ static PolkitImplicitAuthorization polkit_backend_local_authority_check_authoriz
                                                           gboolean                           subject_is_active,
                                                           const gchar                       *action_id,
                                                           PolkitDetails                     *details,
-                                                          PolkitImplicitAuthorization        implicit,
-                                                          PolkitDetails                     *out_details);
+                                                          PolkitImplicitAuthorization        implicit);
 
 G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority,
                          polkit_backend_local_authority,
@@ -543,8 +542,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                          gboolean                           subject_is_active,
                                                          const gchar                       *action_id,
                                                          PolkitDetails                     *details,
-                                                         PolkitImplicitAuthorization        implicit,
-                                                         PolkitDetails                     *out_details)
+                                                         PolkitImplicitAuthorization        implicit)
 {
   PolkitBackendLocalAuthority *local_authority;
   PolkitBackendLocalAuthorityPrivate *priv;
@@ -583,8 +581,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                                details,
                                                                &ret_any,
                                                                &ret_inactive,
-                                                               &ret_active,
-                                                               out_details))
+                                                               &ret_active))
             {
               if (subject_is_local && subject_is_active)
                 {
@@ -618,8 +615,7 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
                                                            details,
                                                            &ret_any,
                                                            &ret_inactive,
-                                                           &ret_active,
-                                                           out_details))
+                                                           &ret_active))
         {
           if (subject_is_local && subject_is_active)
             {
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
index 2ddfe75..f40a943 100644
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.c
+++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
@@ -669,9 +669,10 @@ polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorization
  * @out_result_any: Return location for the result for any subjects if the look up matched.
  * @out_result_inactive: Return location for the result for subjects in local inactive sessions if the look up matched.
  * @out_result_active: Return location for the result for subjects in local active sessions if the look up matched.
- * @out_details: %NULL or a #PolkitDetails object to append key/value pairs to on a positive match.
  *
- * Checks if an authorization entry from @store matches @identity, @action_id and @details.
+ * Checks if an authorization entry from @store matches @identity,
+ * @action_id and @details. May append information to @details if
+ * found.
  *
  * Returns: %TRUE if @store has an authorization entry that matches
  *     @identity, @action_id and @details. Otherwise %FALSE.
@@ -683,8 +684,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
                                                  PolkitDetails                        *details,
                                                  PolkitImplicitAuthorization          *out_result_any,
                                                  PolkitImplicitAuthorization          *out_result_inactive,
-                                                 PolkitImplicitAuthorization          *out_result_active,
-                                                 PolkitDetails                        *out_details)
+                                                 PolkitImplicitAuthorization          *out_result_active)
 {
   GList *l, *ll;
   gboolean ret;
@@ -749,7 +749,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
       *out_result_active = authorization->result_active;
       ret = TRUE;
 
-      if (out_details != NULL && authorization->return_value != NULL)
+      if (details != NULL && authorization->return_value != NULL)
         {
           GHashTableIter iter;
           const gchar *key;
@@ -758,7 +758,7 @@ polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorization
           g_hash_table_iter_init (&iter, authorization->return_value);
           while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
             {
-              polkit_details_insert (out_details, key, value);
+              polkit_details_insert (details, key, value);
             }
         }
 
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.h b/src/polkitbackend/polkitbackendlocalauthorizationstore.h
index c15d9a6..4f198e9 100644
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.h
+++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.h
@@ -78,8 +78,7 @@ gboolean  polkit_backend_local_authorization_store_lookup   (PolkitBackendLocalA
                                                              PolkitDetails                        *details,
                                                              PolkitImplicitAuthorization          *out_result_any,
                                                              PolkitImplicitAuthorization          *out_result_inactive,
-                                                             PolkitImplicitAuthorization          *out_result_active,
-                                                             PolkitDetails                        *out_details);
+                                                             PolkitImplicitAuthorization          *out_result_active);
 
 G_END_DECLS
 
diff --git a/test/polkitbackend/polkitbackendlocalauthoritytest.c b/test/polkitbackend/polkitbackendlocalauthoritytest.c
index 617c254..9fc7848 100644
--- a/test/polkitbackend/polkitbackendlocalauthoritytest.c
+++ b/test/polkitbackend/polkitbackendlocalauthoritytest.c
@@ -66,9 +66,6 @@ test_check_authorization_sync (const void *_ctx)
   PolkitDetails *details = polkit_details_new ();
   g_assert (details);
 
-  PolkitDetails *out_details = polkit_details_new ();
-  g_assert (out_details);
-
   PolkitImplicitAuthorization auth;
 
   auth = polkit_backend_interactive_authority_check_authorization_sync (
@@ -80,8 +77,7 @@ test_check_authorization_sync (const void *_ctx)
       ctx->subject_is_active,
       ctx->action_id,
       details,
-      ctx->implicit,
-      out_details);
+      ctx->implicit);
 
   g_assert_cmpint (auth, ==, ctx->expect);
 
@@ -90,7 +86,6 @@ test_check_authorization_sync (const void *_ctx)
   g_object_unref (subject);
   g_object_unref (user_for_subject);
   g_object_unref (details);
-  g_object_unref (out_details);
 }
 
 static void
diff --git a/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c b/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c
index 945e163..e787c17 100644
--- a/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c
+++ b/test/polkitbackend/polkitbackendlocalauthorizationstoretest.c
@@ -89,8 +89,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (ok);
   g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
   g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
@@ -109,8 +108,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (ok);
   g_assert_cmpstr ("no", ==, polkit_implicit_authorization_to_string (ret_any));
   g_assert_cmpstr ("auth_self", ==, polkit_implicit_authorization_to_string (ret_inactive));
@@ -124,8 +122,7 @@ test_lookup (void)
       details,
       &ret_any,
       &ret_inactive,
-      &ret_active,
-      NULL);
+      &ret_active);
   g_assert (!ok);
 }
 
commit ff18d9a8a23f11f76babc696082750f3f4b74239
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 16:04:12 2012 -0400

    Reformat init.js and also avoid quoting non-string properties in toString()
    
    Otherwise it's hard to tell whether 'true' is a string or a boolean...
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
index 0767d3c..4f1cc72 100644
--- a/src/polkitbackend/init.js
+++ b/src/polkitbackend/init.js
@@ -1,66 +1,74 @@
 /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
 
 function Details() {
-  this.toString = function() {
-    var ret = "[Details";
-    for (var i in this) {
-      if (typeof this[i] != "function")
-        ret += " " + i + "='" + this[i] + "'";
-    }
-    ret += "]";
-    return ret;
-  };
+    this.toString = function() {
+        var ret = "[Details";
+        for (var i in this) {
+            if (typeof this[i] != "function") {
+                if (typeof this[i] == "string")
+                    ret += " " + i + "='" + this[i] + "'";
+                else
+                    ret += " " + i + "=" + this[i];
+            }
+        }
+        ret += "]";
+        return ret;
+    };
 };
 
 function Subject() {
 
-  this.isInGroup = function(group) {
-    for (var n = 0; n < this.groups.length; n++) {
-    if (this.groups[n] == group)
-      return true;
-    }
-    return false;
-  };
+    this.isInGroup = function(group) {
+        for (var n = 0; n < this.groups.length; n++) {
+            if (this.groups[n] == group)
+                return true;
+        }
+        return false;
+    };
 
-  this.toString = function() {
-    var ret = "[Subject";
-    for (var i in this) {
-      if (typeof this[i] != "function")
-        ret += " " + i + "='" + this[i] + "'";
-    }
-    ret += "]";
-    return ret;
-  };
+    this.toString = function() {
+        var ret = "[Subject";
+        for (var i in this) {
+            if (typeof this[i] != "function") {
+                if (typeof this[i] == "string")
+                    ret += " " + i + "='" + this[i] + "'";
+                else
+                    ret += " " + i + "=" + this[i];
+            }
+        }
+        ret += "]";
+        return ret;
+    };
 };
 
 polkit._administratorRuleFuncs = [];
 polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};
 polkit._runAdministratorRules = function(action, subject, details) {
-  var ret = null;
-  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {
-    var func = this._administratorRuleFuncs[n];
-    ret = func(action, subject, details);
-    if (ret)
-      break
-  }
-  return ret.join(",");
+    var ret = null;
+    for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {
+        var func = this._administratorRuleFuncs[n];
+        ret = func(action, subject, details);
+        if (ret)
+            break
+    }
+    return ret.join(",");
 };
 
 polkit._authorizationRuleFuncs = [];
 polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};
 polkit._runAuthorizationRules = function(action, subject, details) {
-  var ret = null;
-  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {
-    var func = this._authorizationRuleFuncs[n];
-    ret = func(action, subject, details);
-    if (ret)
-      break
-  }
-  return ret;
+    var ret = null;
+    for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {
+        var func = this._authorizationRuleFuncs[n];
+        ret = func(action, subject, details);
+        if (ret)
+            break
+    }
+    return ret;
 };
 
 polkit._deleteRules = function() {
-  this._administratorRuleFuncs = [];
-  this._authorizationRuleFuncs = [];
+    this._administratorRuleFuncs = [];
+    this._authorizationRuleFuncs = [];
 };
 
commit 41e56847bf00f7068a01db4be5f441777859fc84
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 15:35:51 2012 -0400

    Emit ::Changed signal after reloading rules
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index bd881a2..b3669d5 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -276,6 +276,8 @@ reload_scripts (PolkitBackendJsAuthority *authority)
 
   load_scripts (authority);
 
+  /* Let applications know we have new rules... */
+  g_signal_emit_by_name (authority, "changed");
  out:
   ;
 }
commit fcc49885d8198f404bcb9ff70d09b5dcc5e81db2
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 15:34:50 2012 -0400

    Collect garbage
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 9d721f3..bd881a2 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -270,7 +270,12 @@ reload_scripts (PolkitBackendJsAuthority *authority)
       goto out;
     }
 
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "Collecting garbage unconditionally...");
+  JS_GC (authority->priv->cx);
+
   load_scripts (authority);
+
  out:
   ;
 }
@@ -834,6 +839,9 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
   /* fallback to root password auth */
   if (ret == NULL)
     ret = g_list_prepend (ret, polkit_unix_user_new (0));
+
+  JS_MaybeGC (authority->priv->cx);
+
   return ret;
 }
 
@@ -932,6 +940,9 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   if (!good)
     ret = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
   g_free (ret_str);
+
+  JS_MaybeGC (authority->priv->cx);
+
   return ret;
 }
 
commit 82e468369c3a8a0ec49b912660cba107252308b6
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 15:30:48 2012 -0400

    Add a couple of more error checks
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index a0f9e27..9d721f3 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -584,11 +584,15 @@ subject_to_jsval (PolkitBackendJsAuthority  *authority,
 
   src = "new Subject();";
 
-  JS_EvaluateScript (authority->priv->cx,
-                     authority->priv->js_global,
-                     src, strlen (src),
-                     __FILE__, __LINE__,
-                     &ret_jsval);
+  if (!JS_EvaluateScript (authority->priv->cx,
+                          authority->priv->js_global,
+                          src, strlen (src),
+                          __FILE__, __LINE__,
+                          &ret_jsval))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Evaluting '%s' failed", src);
+      goto out;
+    }
 
   obj = JSVAL_TO_OBJECT (ret_jsval);
 
@@ -702,11 +706,15 @@ details_to_jsval (PolkitBackendJsAuthority  *authority,
 
   src = "new Details();";
 
-  JS_EvaluateScript (authority->priv->cx,
-                     authority->priv->js_global,
-                     src, strlen (src),
-                     __FILE__, __LINE__,
-                     &ret_jsval);
+  if (!JS_EvaluateScript (authority->priv->cx,
+                          authority->priv->js_global,
+                          src, strlen (src),
+                          __FILE__, __LINE__,
+                          &ret_jsval))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Evaluting '%s' failed", src);
+      goto out;
+    }
 
   obj = JSVAL_TO_OBJECT (ret_jsval);
   keys = polkit_details_get_keys (details);
@@ -726,6 +734,7 @@ details_to_jsval (PolkitBackendJsAuthority  *authority,
 
   ret = TRUE;
 
+ out:
   if (ret && out_jsval != NULL)
     *out_jsval = ret_jsval;
 
commit 5957b6c4f148794710bab8dd05c7f654871c7455
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 15:24:30 2012 -0400

    Clean up code a bit
    
    Also, move init code into init.js instead of using a C string for
    it...
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 2f6fd05..982c3ea 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -1,5 +1,7 @@
 NULL =
 
+BUILT_SOURCES =
+
 INCLUDES =                                                      \
         -I$(top_builddir)/src                                   \
         -I$(top_srcdir)/src                                     \
@@ -20,6 +22,12 @@ lib_LTLIBRARIES=libpolkit-backend-1.la
 
 libpolkit_backend_1includedir=$(includedir)/polkit-1/polkitbackend
 
+
+initjs.h : init.js
+	$(PERL) $(srcdir)/toarray.pl init.js init_js > $@
+
+BUILT_SOURCES += initjs.h
+
 libpolkit_backend_1include_HEADERS =                        		\
 	polkitbackend.h							\
 	polkitbackendtypes.h						\
@@ -77,6 +85,7 @@ localauthorityconfig_DATA = 50-localauthority.conf
 
 EXTRA_DIST =								\
 	$(localauthorityconfig_DATA)					\
+	init.js								\
 	$(NULL)
 
 dist-hook :
diff --git a/src/polkitbackend/init.js b/src/polkitbackend/init.js
new file mode 100644
index 0000000..0767d3c
--- /dev/null
+++ b/src/polkitbackend/init.js
@@ -0,0 +1,66 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+function Details() {
+  this.toString = function() {
+    var ret = "[Details";
+    for (var i in this) {
+      if (typeof this[i] != "function")
+        ret += " " + i + "='" + this[i] + "'";
+    }
+    ret += "]";
+    return ret;
+  };
+};
+
+function Subject() {
+
+  this.isInGroup = function(group) {
+    for (var n = 0; n < this.groups.length; n++) {
+    if (this.groups[n] == group)
+      return true;
+    }
+    return false;
+  };
+
+  this.toString = function() {
+    var ret = "[Subject";
+    for (var i in this) {
+      if (typeof this[i] != "function")
+        ret += " " + i + "='" + this[i] + "'";
+    }
+    ret += "]";
+    return ret;
+  };
+};
+
+polkit._administratorRuleFuncs = [];
+polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};
+polkit._runAdministratorRules = function(action, subject, details) {
+  var ret = null;
+  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {
+    var func = this._administratorRuleFuncs[n];
+    ret = func(action, subject, details);
+    if (ret)
+      break
+  }
+  return ret.join(",");
+};
+
+polkit._authorizationRuleFuncs = [];
+polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};
+polkit._runAuthorizationRules = function(action, subject, details) {
+  var ret = null;
+  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {
+    var func = this._authorizationRuleFuncs[n];
+    ret = func(action, subject, details);
+    if (ret)
+      break
+  }
+  return ret;
+};
+
+polkit._deleteRules = function() {
+  this._administratorRuleFuncs = [];
+  this._authorizationRuleFuncs = [];
+};
+
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index ff41bef..a0f9e27 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -38,6 +38,8 @@
 
 #include <jsapi.h>
 
+#include "initjs.h" /* init.js */
+
 /**
  * SECTION:polkitbackendjsauthority
  * @title: PolkitBackendJsAuthority
@@ -263,8 +265,8 @@ reload_scripts (PolkitBackendJsAuthority *authority)
                            argv,
                            &rval))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, faileded clearing rules\n");
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error deleting old rules, not loading new ones");
       goto out;
     }
 
@@ -308,81 +310,19 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
     }
 }
 
-static const gchar js_polkit_init[] =
-  "function Details() {\n"
-  "  this.toString = function() {\n"
-  "    var ret = '[Details';\n"
-  "    for (var i in this) {\n"
-  "      if (typeof this[i] != 'function')\n"
-  "        ret += ' ' + i + '=\\'' + this[i] + '\\'';\n"
-  "    }"
-  "    ret += ']';\n"
-  "    return ret;\n"
-  "  };\n"
-  "};\n"
-  "\n"
-  "function Subject() {\n"
-  "  this.isInGroup = function(group) {\n"
-  "    for (var n = 0; n < this.groups.length; n++) {\n"
-  "    if (this.groups[n] == group)\n"
-  "      return true;\n"
-  "    }\n"
-  "    return false;\n"
-  "  };\n"
-  "  \n"
-  "  this.toString = function() {\n"
-  "    var ret = '[Subject';\n"
-  "    for (var i in this) {\n"
-  "      if (typeof this[i] != 'function')\n"
-  "        ret += ' ' + i + '=\\'' + this[i] + '\\'';\n"
-  "    }"
-  "    ret += ']';\n"
-  "    return ret;\n"
-  "  };\n"
-  "};\n"
-  "\n"
-  "polkit._administratorRuleFuncs = [];\n"
-  "polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};\n"
-  "polkit._runAdministratorRules = function(action, subject, details) {\n"
-  "  var ret = null;\n"
-  "  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {\n"
-  "    var func = this._administratorRuleFuncs[n];\n"
-  "    ret = func(action, subject, details);\n"
-  "    if (ret)\n"
-  "      break\n"
-  "  }\n"
-  "  return ret.join(',');\n"
-  "};\n"
-  "\n"
-  "polkit._authorizationRuleFuncs = [];\n"
-  "polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};\n"
-  "polkit._runAuthorizationRules = function(action, subject, details) {\n"
-  "  var ret = null;\n"
-  "  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {\n"
-  "    var func = this._authorizationRuleFuncs[n];\n"
-  "    ret = func(action, subject, details);\n"
-  "    if (ret)\n"
-  "      break\n"
-  "  }\n"
-  "  return ret;\n"
-  "};\n"
-  "\n"
-  "polkit._deleteRules = function() {\n"
-  "  this._administratorRuleFuncs = [];\n"
-  "  this._authorizationRuleFuncs = [];\n"
-  "};\n"
-  "\n"
-  "";
-
-
 static void
 polkit_backend_js_authority_constructed (GObject *object)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
 
-  /* TODO: error checking */
   authority->priv->rt = JS_NewRuntime (8L * 1024L * 1024L);
+  if (authority->priv->rt == NULL)
+    goto fail;
+
   authority->priv->cx = JS_NewContext (authority->priv->rt, 8192);
+  if (authority->priv->cx == NULL)
+    goto fail;
+
   JS_SetOptions (authority->priv->cx,
                  JSOPTION_VAROBJFIX |
                  JSOPTION_JIT |
@@ -394,7 +334,11 @@ polkit_backend_js_authority_constructed (GObject *object)
   authority->priv->js_global = JS_NewCompartmentAndGlobalObject (authority->priv->cx,
                                                                  &js_global_class,
                                                                  NULL);
-  JS_InitStandardClasses (authority->priv->cx, authority->priv->js_global);
+  if (authority->priv->js_global == NULL)
+    goto fail;
+
+  if (!JS_InitStandardClasses (authority->priv->cx, authority->priv->js_global))
+    goto fail;
 
   authority->priv->js_polkit = JS_DefineObject(authority->priv->cx,
                                                authority->priv->js_global,
@@ -402,24 +346,32 @@ polkit_backend_js_authority_constructed (GObject *object)
                                                &js_polkit_class,
                                                NULL,
                                                JSPROP_ENUMERATE);
-  JS_DefineFunctions (authority->priv->cx,
-                      authority->priv->js_polkit,
-                      js_polkit_functions);
+  if (authority->priv->js_polkit == NULL)
+    goto fail;
+
+  if (!JS_DefineFunctions (authority->priv->cx,
+                           authority->priv->js_polkit,
+                           js_polkit_functions))
+    goto fail;
 
   if (!JS_EvaluateScript (authority->priv->cx,
                           authority->priv->js_global,
-                          js_polkit_init,
-                          strlen (js_polkit_init),
-                          NULL,  /* filename */
+                          init_js, strlen (init_js), /* init.js */
+                          "init.js",  /* filename */
                           0,     /* lineno */
                           NULL)) /* rval */
     {
-      g_printerr ("Error running init code\n");
+      goto fail;
     }
 
   load_scripts (authority);
 
   G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
+  return;
+
+ fail:
+  g_critical ("Error initializing JavaScript environment");
+  g_assert_not_reached ();
 }
 
 static void
@@ -804,16 +756,18 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 
   if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
-      /* TODO: syslog? */
-      g_printerr ("Error converting subject to JS object: %s\n", error->message);
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error converting subject to JS object: %s",
+                                    error->message);
       g_clear_error (&error);
       goto out;
     }
 
   if (!details_to_jsval (authority, details, &argv[2], &error))
     {
-      /* TODO: syslog? */
-      g_printerr ("Error converting details to JS object: %s\n", error->message);
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error converting details to JS object: %s",
+                                    error->message);
       g_clear_error (&error);
       goto out;
     }
@@ -825,15 +779,14 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
                            argv,
                            &rval))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, failed\n");
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error evaluating administrator rules");
       goto out;
     }
 
   if (!JSVAL_IS_STRING (rval) && !JSVAL_IS_NULL (rval))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, not string\n");
+      g_warning ("Expected a string");
       goto out;
     }
 
@@ -841,13 +794,10 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
   ret_str = g_utf16_to_utf8 (JS_GetStringCharsZ (authority->priv->cx, ret_jsstr), -1, NULL, NULL, NULL);
   if (ret_str == NULL)
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, error converting to UTF-8\n");
+      g_warning ("Error converting resulting string to UTF-8: %s", error->message);
       goto out;
     }
 
-  //g_print ("yay, worked `%s'\n", ret_str);
-
   ret_strs = g_strsplit (ret_str, ",", -1);
   for (n = 0; ret_strs != NULL && ret_strs[n] != NULL; n++)
     {
@@ -858,8 +808,9 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
       identity = polkit_identity_from_string (identity_str, &error);
       if (identity == NULL)
         {
-          /* TODO: syslog? */
-          g_printerr ("boo, identity `%s' is not valid, ignoring\n", identity_str);
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Identity `%s' is not valid, ignoring",
+                                        identity_str);
         }
       else
         {
@@ -900,22 +851,25 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   JSString *ret_jsstr;
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
+  gboolean good = FALSE;
 
   action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
   argv[0] = STRING_TO_JSVAL (action_id_jstr);
 
   if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
-      /* TODO: syslog? */
-      g_printerr ("Error converting subject to JS object: %s\n", error->message);
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error converting subject to JS object: %s",
+                                    error->message);
       g_clear_error (&error);
       goto out;
     }
 
   if (!details_to_jsval (authority, details, &argv[2], &error))
     {
-      /* TODO: syslog? */
-      g_printerr ("Error converting details to JS object: %s\n", error->message);
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error converting details to JS object: %s",
+                                    error->message);
       g_clear_error (&error);
       goto out;
     }
@@ -927,45 +881,47 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
                            argv,
                            &rval))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, failed\n");
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error evaluating authorization rules");
       goto out;
     }
 
   if (!JSVAL_IS_STRING (rval) && !JSVAL_IS_NULL (rval))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, not string\n");
+      g_warning ("Expected a string");
       goto out;
     }
 
   ret_jsstr = JSVAL_TO_STRING (rval);
   if (ret_jsstr == NULL)
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, string is null\n");
+      /* this fine, means there was no match, use implicit authorizations */
+      good = TRUE;
       goto out;
     }
 
   ret_utf16 = JS_GetStringCharsZ (authority->priv->cx, ret_jsstr);
-  ret_str = g_utf16_to_utf8 (ret_utf16, -1, NULL, NULL, NULL);
+  ret_str = g_utf16_to_utf8 (ret_utf16, -1, NULL, NULL, &error);
   if (ret_str == NULL)
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, error converting to UTF-8\n");
+      g_warning ("Error converting resulting string to UTF-8: %s", error->message);
+      g_clear_error (&error);
       goto out;
     }
 
   if (!polkit_implicit_authorization_from_string (ret_str, &ret))
     {
-      /* TODO: syslog? */
-      g_printerr ("boo, returned result `%s' is not valid\n", ret_str);
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Returned result `%s' is not valid\n",
+                                    ret_str);
       goto out;
     }
 
-  g_print ("yay, worked `%s'\n", ret_str);
+  good = TRUE;
 
  out:
+  if (!good)
+    ret = POLKIT_IMPLICIT_AUTHORIZATION_NOT_AUTHORIZED;
   g_free (ret_str);
   return ret;
 }
diff --git a/src/polkitbackend/toarray.pl b/src/polkitbackend/toarray.pl
new file mode 100755
index 0000000..e430885
--- /dev/null
+++ b/src/polkitbackend/toarray.pl
@@ -0,0 +1,15 @@
+#!/usr/bin/perl -w
+
+my $FILENAME = $ARGV[0];
+
+open FILE, $FILENAME or die "Cannot open $FILENAME";
+
+my $ARRAYNAME = $ARGV[1];
+print "static const char $ARRAYNAME\[\] =";
+while (<FILE>) {
+    s@\\@\\\\@g;
+    s@"@\\"@g;
+    chomp ($_);
+    print "\n  \"$_\\n\"";
+}
+print ";\n";
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index bea8262..9453c44 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -1,5 +1,7 @@
 /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
 
+/* see test/polkitbackend/test-polkitbackendjsauthority.c */
+
 polkit.addAdministratorRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
 });
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index c5015ff..bc1b242 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -27,6 +27,8 @@
 #include <polkitbackend/polkitbackendjsauthority.h>
 #include <polkittesthelper.h>
 
+/* see test/data/etc/polkit-1/rules.d/10-testing.rules */
+
 /* Test helper types */
 
 static PolkitBackendJsAuthority *get_authority (void);
commit 2b8a47984515a617b3be8c630960a6b271a0a110
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 12:01:44 2012 -0400

    Pass details to JS functions and simplify how Subject instances are constructed
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 0a36e06..ff41bef 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -309,15 +309,19 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
 }
 
 static const gchar js_polkit_init[] =
-  "function Subject(pid, user, groups, seat, session, local, active) {\n"
-  "  this.pid = pid;\n"
-  "  this.user = user;\n"
-  "  this.groups = groups.split(',');\n"
-  "  this.seat = seat;\n"
-  "  this.session = session;\n"
-  "  this.local = local;\n"
-  "  this.active = active;\n"
-  "  \n"
+  "function Details() {\n"
+  "  this.toString = function() {\n"
+  "    var ret = '[Details';\n"
+  "    for (var i in this) {\n"
+  "      if (typeof this[i] != 'function')\n"
+  "        ret += ' ' + i + '=\\'' + this[i] + '\\'';\n"
+  "    }"
+  "    ret += ']';\n"
+  "    return ret;\n"
+  "  };\n"
+  "};\n"
+  "\n"
+  "function Subject() {\n"
   "  this.isInGroup = function(group) {\n"
   "    for (var n = 0; n < this.groups.length; n++) {\n"
   "    if (this.groups[n] == group)\n"
@@ -327,24 +331,23 @@ static const gchar js_polkit_init[] =
   "  };\n"
   "  \n"
   "  this.toString = function() {\n"
-  "    return '[Subject pid=' + this.pid +\n"
-  "                ' seat=' + this.seat +\n"
-  "                ' session=' + this.session +\n"
-  "                ' local=' + this.local +\n"
-  "                ' active=' + this.active +\n"
-  "                ' user=' + this.user +\n"
-  "                ' groups=' + this.groups + ']';\n"
+  "    var ret = '[Subject';\n"
+  "    for (var i in this) {\n"
+  "      if (typeof this[i] != 'function')\n"
+  "        ret += ' ' + i + '=\\'' + this[i] + '\\'';\n"
+  "    }"
+  "    ret += ']';\n"
+  "    return ret;\n"
   "  };\n"
-  "}\n"
+  "};\n"
   "\n"
   "polkit._administratorRuleFuncs = [];\n"
   "polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};\n"
-  "polkit._runAdministratorRules = function(action, pid, user, groups, seat, session, local, active) {\n"
+  "polkit._runAdministratorRules = function(action, subject, details) {\n"
   "  var ret = null;\n"
-  "  var subject = new Subject(pid, user, groups, seat, session, local, active);\n"
   "  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {\n"
   "    var func = this._administratorRuleFuncs[n];\n"
-  "    ret = func(action, subject);\n"
+  "    ret = func(action, subject, details);\n"
   "    if (ret)\n"
   "      break\n"
   "  }\n"
@@ -353,12 +356,11 @@ static const gchar js_polkit_init[] =
   "\n"
   "polkit._authorizationRuleFuncs = [];\n"
   "polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};\n"
-  "polkit._runAuthorizationRules = function(action, pid, user, groups, seat, session, local, active) {\n"
+  "polkit._runAuthorizationRules = function(action, subject, details) {\n"
   "  var ret = null;\n"
-  "  var subject = new Subject(pid, user, groups, seat, session, local, active);\n"
   "  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {\n"
   "    var func = this._authorizationRuleFuncs[n];\n"
-  "    ret = func(action, subject);\n"
+  "    ret = func(action, subject, details);\n"
   "    if (ret)\n"
   "      break\n"
   "  }\n"
@@ -539,34 +541,104 @@ polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static void
+set_property_str (PolkitBackendJsAuthority  *authority,
+                  JSObject                  *obj,
+                  const gchar               *name,
+                  const gchar               *value)
+{
+  JSString *value_jsstr;
+  jsval value_jsval;
+  value_jsstr = JS_NewStringCopyZ (authority->priv->cx, value);
+  value_jsval = STRING_TO_JSVAL (value_jsstr);
+  JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
+}
+
+static void
+set_property_strv (PolkitBackendJsAuthority  *authority,
+                   JSObject                  *obj,
+                   const gchar               *name,
+                   const gchar *const        *value,
+                   gssize                     len)
+{
+  jsval value_jsval;
+  JSObject *array_object;
+  jsval *jsvals;
+  guint n;
+
+  if (len < 0)
+    len = g_strv_length ((gchar **) value);
+
+  jsvals = g_new0 (jsval, len);
+  for (n = 0; n < len; n++)
+    {
+      JSString *jsstr;
+      jsstr = JS_NewStringCopyZ (authority->priv->cx, value[n]);
+      jsvals[n] = STRING_TO_JSVAL (jsstr);
+    }
+
+  array_object = JS_NewArrayObject (authority->priv->cx, (jsint) len, jsvals);
+
+  value_jsval = OBJECT_TO_JSVAL (array_object);
+  JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
+
+  g_free (jsvals);
+}
+
+
+static void
+set_property_int32 (PolkitBackendJsAuthority  *authority,
+                    JSObject                  *obj,
+                    const gchar               *name,
+                    gint32                     value)
+{
+  jsval value_jsval;
+  value_jsval = INT_TO_JSVAL ((int32) value);
+  JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
+}
+
+static void
+set_property_bool (PolkitBackendJsAuthority  *authority,
+                   JSObject                  *obj,
+                   const gchar               *name,
+                   gboolean                   value)
+{
+  jsval value_jsval;
+  value_jsval = BOOLEAN_TO_JSVAL ((JSBool) value);
+  JS_SetProperty (authority->priv->cx, obj, name, &value_jsval);
+}
+
+
 static gboolean
-subject_to_js (PolkitBackendJsAuthority *authority,
-               PolkitSubject            *subject,
-               PolkitIdentity           *user_for_subject,
-               jsval                    *jsval_pid,
-               jsval                    *jsval_user,
-               jsval                    *jsval_groups,
-               jsval                    *jsval_seat,
-               jsval                    *jsval_session,
-               GError                  **error)
+subject_to_jsval (PolkitBackendJsAuthority  *authority,
+                  PolkitSubject             *subject,
+                  PolkitIdentity            *user_for_subject,
+                  jsval                     *out_jsval,
+                  GError                   **error)
 {
   gboolean ret = FALSE;
-  JSString *user_name_jstr;
-  JSString *groups_jstr;
-  JSString *seat_jstr;
-  JSString *session_jstr;
+  jsval ret_jsval;
+  const char *src;
+  JSObject *obj;
   pid_t pid;
   uid_t uid;
   gchar *user_name = NULL;
-  GString *groups = NULL;
+  GPtrArray *groups = NULL;
   struct passwd *passwd;
   char *seat_str = NULL;
   char *session_str = NULL;
+  gboolean is_local = FALSE;
+  gboolean is_active = FALSE;
+
+  src = "new Subject();";
 
-  g_return_val_if_fail (jsval_pid != NULL, FALSE);
-  g_return_val_if_fail (jsval_user != NULL, FALSE);
-  g_return_val_if_fail (jsval_groups != NULL, FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  JS_EvaluateScript (authority->priv->cx,
+                     authority->priv->js_global,
+                     src, strlen (src),
+                     __FILE__, __LINE__,
+                     &ret_jsval);
+
+  obj = JSVAL_TO_OBJECT (ret_jsval);
 
   if (POLKIT_IS_UNIX_PROCESS (subject))
     {
@@ -588,13 +660,16 @@ subject_to_js (PolkitBackendJsAuthority *authority,
 
   if (sd_pid_get_session (pid, &session_str) == 0)
     {
-      sd_session_get_seat (session_str, &seat_str);
+      if (sd_session_get_seat (session_str, &seat_str) == 0)
+        is_local = TRUE;
+      if (sd_session_is_active (session_str))
+        is_active = TRUE;
     }
 
   g_assert (POLKIT_IS_UNIX_USER (user_for_subject));
   uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_for_subject));
 
-  groups = g_string_new (NULL);
+  groups = g_ptr_array_new_with_free_func (g_free);
 
   passwd = getpwuid (uid);
   if (passwd == NULL)
@@ -622,44 +697,88 @@ subject_to_js (PolkitBackendJsAuthority *authority,
           for (n = 0; n < num_gids; n++)
             {
               struct group *group;
-              if (n > 0)
-                g_string_append_c (groups, ',');
-
               group = getgrgid (gids[n]);
               if (group == NULL)
                 {
-                  g_string_append_printf (groups, "%d", (gint) gids[n]);
+                  g_ptr_array_add (groups, g_strdup_printf ("%d", (gint) gids[n]));
                 }
               else
                 {
-                  g_string_append_printf (groups, "%s", group->gr_name);
+                  g_ptr_array_add (groups, g_strdup (group->gr_name));
                 }
             }
         }
     }
 
-  user_name_jstr = JS_NewStringCopyZ (authority->priv->cx, user_name);
-  groups_jstr = JS_NewStringCopyZ (authority->priv->cx, groups->str);
-  seat_jstr = JS_NewStringCopyZ (authority->priv->cx, seat_str);
-  session_jstr = JS_NewStringCopyZ (authority->priv->cx, session_str);
-  *jsval_pid = INT_TO_JSVAL ((int32) pid);
-  *jsval_user = STRING_TO_JSVAL (user_name_jstr);
-  *jsval_groups = STRING_TO_JSVAL (groups_jstr);
-  *jsval_seat = STRING_TO_JSVAL (seat_jstr);
-  *jsval_session = STRING_TO_JSVAL (session_jstr);
+  g_ptr_array_add (groups, NULL);
+
+  set_property_int32 (authority, obj, "pid", pid);
+  set_property_str (authority, obj, "user", user_name);
+  set_property_strv (authority, obj, "groups", (const gchar* const *) groups->pdata, groups->len);
+  set_property_str (authority, obj, "seat", seat_str);
+  set_property_str (authority, obj, "session", session_str);
+  set_property_bool (authority, obj, "local", is_local);
+  set_property_bool (authority, obj, "active", is_active);
 
   ret = TRUE;
 
  out:
-  /* TODO: are we leaking _jstr ? */
   free (session_str);
   free (seat_str);
   g_free (user_name);
   if (groups != NULL)
-    g_string_free (groups, TRUE);
+    g_ptr_array_unref (groups);
+
+  if (ret && out_jsval != NULL)
+    *out_jsval = ret_jsval;
+
   return ret;
 }
 
+static gboolean
+details_to_jsval (PolkitBackendJsAuthority  *authority,
+                  PolkitDetails             *details,
+                  jsval                     *out_jsval,
+                  GError                   **error)
+{
+  gboolean ret = FALSE;
+  jsval ret_jsval;
+  const char *src;
+  JSObject *obj;
+  gchar **keys;
+  guint n;
+
+  src = "new Details();";
+
+  JS_EvaluateScript (authority->priv->cx,
+                     authority->priv->js_global,
+                     src, strlen (src),
+                     __FILE__, __LINE__,
+                     &ret_jsval);
+
+  obj = JSVAL_TO_OBJECT (ret_jsval);
+  keys = polkit_details_get_keys (details);
+  for (n = 0; keys != NULL && keys[n] != NULL; n++)
+    {
+      const gchar *key = keys[n];
+      JSString *value_jsstr;
+      jsval value_jsval;
+      const gchar *value;
+
+      value = polkit_details_lookup (details, keys[n]);
+      value_jsstr = JS_NewStringCopyZ (authority->priv->cx, value);
+      value_jsval = STRING_TO_JSVAL (value_jsstr);
+      JS_SetProperty (authority->priv->cx, obj, key, &value_jsval);
+    }
+  g_free (keys);
+
+  ret = TRUE;
+
+  if (ret && out_jsval != NULL)
+    *out_jsval = ret_jsval;
+
+  return ret;
+}
 
 static GList *
 polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
@@ -671,7 +790,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   GList *ret = NULL;
-  jsval argv[8] = {0};
+  jsval argv[3] = {0};
   jsval rval = {0};
   JSString *action_id_jstr;
   guint n;
@@ -680,23 +799,29 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
   gchar *ret_str = NULL;
   gchar **ret_strs = NULL;
 
-  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &argv[4], &argv[5], &error))
+  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
+  argv[0] = STRING_TO_JSVAL (action_id_jstr);
+
+  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
       /* TODO: syslog? */
-      g_printerr ("Error converting subject: %s\n", error->message);
+      g_printerr ("Error converting subject to JS object: %s\n", error->message);
       g_clear_error (&error);
       goto out;
     }
 
-  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
-  argv[0] = STRING_TO_JSVAL (action_id_jstr);
-  argv[6] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_local);
-  argv[7] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_active);
+  if (!details_to_jsval (authority, details, &argv[2], &error))
+    {
+      /* TODO: syslog? */
+      g_printerr ("Error converting details to JS object: %s\n", error->message);
+      g_clear_error (&error);
+      goto out;
+    }
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
                            "_runAdministratorRules",
-                           8,
+                           3,
                            argv,
                            &rval))
     {
@@ -768,7 +893,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   PolkitImplicitAuthorization ret = implicit;
-  jsval argv[8] = {0};
+  jsval argv[3] = {0};
   jsval rval = {0};
   JSString *action_id_jstr;
   GError *error = NULL;
@@ -776,23 +901,29 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
 
-  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &argv[4], &argv[5], &error))
+  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
+  argv[0] = STRING_TO_JSVAL (action_id_jstr);
+
+  if (!subject_to_jsval (authority, subject, user_for_subject, &argv[1], &error))
     {
       /* TODO: syslog? */
-      g_printerr ("Error converting subject: %s\n", error->message);
+      g_printerr ("Error converting subject to JS object: %s\n", error->message);
       g_clear_error (&error);
       goto out;
     }
 
-  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
-  argv[0] = STRING_TO_JSVAL (action_id_jstr);
-  argv[6] = BOOLEAN_TO_JSVAL (subject_is_local);
-  argv[7] = BOOLEAN_TO_JSVAL (subject_is_active);
+  if (!details_to_jsval (authority, details, &argv[2], &error))
+    {
+      /* TODO: syslog? */
+      g_printerr ("Error converting details to JS object: %s\n", error->message);
+      g_clear_error (&error);
+      goto out;
+    }
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
                            "_runAuthorizationRules",
-                           8,
+                           3,
                            argv,
                            &rval))
     {
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index adf4f16..bea8262 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -1,17 +1,17 @@
 /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
 
-polkit.addAdministratorRule(function(action, subject) {
+polkit.addAdministratorRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
 });
 
-polkit.addAdministratorRule(function(action, subject) {
+polkit.addAdministratorRule(function(action, subject, details) {
     if (action == "net.company.action1") {
         return ["unix-group:admin"];
     }
     return null;
 });
 
-polkit.addAdministratorRule(function(action, subject) {
+polkit.addAdministratorRule(function(action, subject, details) {
     if (action == "net.company.action2") {
         return ["unix-group:users"];
     }
@@ -20,11 +20,11 @@ polkit.addAdministratorRule(function(action, subject) {
 
 // -----
 
-polkit.addAuthorizationRule(function(action, subject) {
+polkit.addAuthorizationRule(function(action, subject, details) {
     return "auth_admin";
 });
 
-polkit.addAuthorizationRule(function(action, subject) {
+polkit.addAuthorizationRule(function(action, subject, details) {
     if (action == "org.freedesktop.policykit.exec") {
         return "auth_admin";
     }
commit 247fc6d88d2dc1b09eabfd9d600d650c75608913
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri May 18 00:09:02 2012 -0400

    Include seat and session in Subject object
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 23d2640..0a36e06 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -34,6 +34,8 @@
 
 #include <polkit/polkitprivate.h>
 
+#include <systemd/sd-login.h>
+
 #include <jsapi.h>
 
 /**
@@ -307,16 +309,39 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
 }
 
 static const gchar js_polkit_init[] =
+  "function Subject(pid, user, groups, seat, session, local, active) {\n"
+  "  this.pid = pid;\n"
+  "  this.user = user;\n"
+  "  this.groups = groups.split(',');\n"
+  "  this.seat = seat;\n"
+  "  this.session = session;\n"
+  "  this.local = local;\n"
+  "  this.active = active;\n"
+  "  \n"
+  "  this.isInGroup = function(group) {\n"
+  "    for (var n = 0; n < this.groups.length; n++) {\n"
+  "    if (this.groups[n] == group)\n"
+  "      return true;\n"
+  "    }\n"
+  "    return false;\n"
+  "  };\n"
+  "  \n"
+  "  this.toString = function() {\n"
+  "    return '[Subject pid=' + this.pid +\n"
+  "                ' seat=' + this.seat +\n"
+  "                ' session=' + this.session +\n"
+  "                ' local=' + this.local +\n"
+  "                ' active=' + this.active +\n"
+  "                ' user=' + this.user +\n"
+  "                ' groups=' + this.groups + ']';\n"
+  "  };\n"
+  "}\n"
+  "\n"
   "polkit._administratorRuleFuncs = [];\n"
   "polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};\n"
-  "polkit._runAdministratorRules = function(action, pid, user, groups, is_local, is_active) {\n"
+  "polkit._runAdministratorRules = function(action, pid, user, groups, seat, session, local, active) {\n"
   "  var ret = null;\n"
-  "  var subject = {};\n"
-  "  subject.pid = pid;\n"
-  "  subject.user = user;\n"
-  "  subject.local = is_local;\n"
-  "  subject.active = is_active;\n"
-  "  subject.groups = groups.split(',');\n"
+  "  var subject = new Subject(pid, user, groups, seat, session, local, active);\n"
   "  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {\n"
   "    var func = this._administratorRuleFuncs[n];\n"
   "    ret = func(action, subject);\n"
@@ -328,14 +353,9 @@ static const gchar js_polkit_init[] =
   "\n"
   "polkit._authorizationRuleFuncs = [];\n"
   "polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};\n"
-  "polkit._runAuthorizationRules = function(action, pid, user, groups, is_local, is_active) {\n"
+  "polkit._runAuthorizationRules = function(action, pid, user, groups, seat, session, local, active) {\n"
   "  var ret = null;\n"
-  "  var subject = {};\n"
-  "  subject.pid = pid;\n"
-  "  subject.user = user;\n"
-  "  subject.local = is_local;\n"
-  "  subject.active = is_active;\n"
-  "  subject.groups = groups.split(',');\n"
+  "  var subject = new Subject(pid, user, groups, seat, session, local, active);\n"
   "  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {\n"
   "    var func = this._authorizationRuleFuncs[n];\n"
   "    ret = func(action, subject);\n"
@@ -526,16 +546,22 @@ subject_to_js (PolkitBackendJsAuthority *authority,
                jsval                    *jsval_pid,
                jsval                    *jsval_user,
                jsval                    *jsval_groups,
+               jsval                    *jsval_seat,
+               jsval                    *jsval_session,
                GError                  **error)
 {
   gboolean ret = FALSE;
   JSString *user_name_jstr;
   JSString *groups_jstr;
+  JSString *seat_jstr;
+  JSString *session_jstr;
   pid_t pid;
   uid_t uid;
   gchar *user_name = NULL;
   GString *groups = NULL;
   struct passwd *passwd;
+  char *seat_str = NULL;
+  char *session_str = NULL;
 
   g_return_val_if_fail (jsval_pid != NULL, FALSE);
   g_return_val_if_fail (jsval_user != NULL, FALSE);
@@ -560,6 +586,11 @@ subject_to_js (PolkitBackendJsAuthority *authority,
       g_assert_not_reached ();
     }
 
+  if (sd_pid_get_session (pid, &session_str) == 0)
+    {
+      sd_session_get_seat (session_str, &seat_str);
+    }
+
   g_assert (POLKIT_IS_UNIX_USER (user_for_subject));
   uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_for_subject));
 
@@ -609,14 +640,20 @@ subject_to_js (PolkitBackendJsAuthority *authority,
 
   user_name_jstr = JS_NewStringCopyZ (authority->priv->cx, user_name);
   groups_jstr = JS_NewStringCopyZ (authority->priv->cx, groups->str);
+  seat_jstr = JS_NewStringCopyZ (authority->priv->cx, seat_str);
+  session_jstr = JS_NewStringCopyZ (authority->priv->cx, session_str);
   *jsval_pid = INT_TO_JSVAL ((int32) pid);
   *jsval_user = STRING_TO_JSVAL (user_name_jstr);
   *jsval_groups = STRING_TO_JSVAL (groups_jstr);
+  *jsval_seat = STRING_TO_JSVAL (seat_jstr);
+  *jsval_session = STRING_TO_JSVAL (session_jstr);
 
   ret = TRUE;
 
  out:
   /* TODO: are we leaking _jstr ? */
+  free (session_str);
+  free (seat_str);
   g_free (user_name);
   if (groups != NULL)
     g_string_free (groups, TRUE);
@@ -634,7 +671,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   GList *ret = NULL;
-  jsval argv[6] = {0};
+  jsval argv[8] = {0};
   jsval rval = {0};
   JSString *action_id_jstr;
   guint n;
@@ -643,7 +680,7 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
   gchar *ret_str = NULL;
   gchar **ret_strs = NULL;
 
-  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &error))
+  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &argv[4], &argv[5], &error))
     {
       /* TODO: syslog? */
       g_printerr ("Error converting subject: %s\n", error->message);
@@ -653,13 +690,13 @@ polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveA
 
   action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
   argv[0] = STRING_TO_JSVAL (action_id_jstr);
-  argv[4] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_local);
-  argv[5] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_active);
+  argv[6] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_local);
+  argv[7] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_active);
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
                            "_runAdministratorRules",
-                           6,
+                           8,
                            argv,
                            &rval))
     {
@@ -731,7 +768,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
   PolkitImplicitAuthorization ret = implicit;
-  jsval argv[6] = {0};
+  jsval argv[8] = {0};
   jsval rval = {0};
   JSString *action_id_jstr;
   GError *error = NULL;
@@ -739,7 +776,7 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
   const jschar *ret_utf16;
   gchar *ret_str = NULL;
 
-  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &error))
+  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &argv[4], &argv[5], &error))
     {
       /* TODO: syslog? */
       g_printerr ("Error converting subject: %s\n", error->message);
@@ -749,13 +786,13 @@ polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAu
 
   action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
   argv[0] = STRING_TO_JSVAL (action_id_jstr);
-  argv[4] = BOOLEAN_TO_JSVAL (subject_is_local);
-  argv[5] = BOOLEAN_TO_JSVAL (subject_is_active);
+  argv[6] = BOOLEAN_TO_JSVAL (subject_is_local);
+  argv[7] = BOOLEAN_TO_JSVAL (subject_is_active);
 
   if (!JS_CallFunctionName(authority->priv->cx,
                            authority->priv->js_polkit,
                            "_runAuthorizationRules",
-                           6,
+                           8,
                            argv,
                            &rval))
     {
commit aeb2b50a7b0ed1411df81790231cd902d6e76e56
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu May 17 23:27:58 2012 -0400

    Add experimental authority backend using JavaScript rule files
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/configure.ac b/configure.ac
index f325922..4f2ac6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -127,6 +127,10 @@ PKG_CHECK_MODULES(GLIB, [gio-2.0 >= 2.28.0])
 AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 
+PKG_CHECK_MODULES(LIBJS, [libjs >= 1.8.5])
+AC_SUBST(LIBJS_CFLAGS)
+AC_SUBST(LIBJS_LIBS)
+
 EXPAT_LIB=""
 AC_ARG_WITH(expat, [  --with-expat=<dir>      Use expat from here],
                       [
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index b91cafa..2f6fd05 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -37,6 +37,7 @@ libpolkit_backend_1_la_SOURCES =                                   			\
 	polkitbackendauthority.h		polkitbackendauthority.c		\
 	polkitbackendinteractiveauthority.h	polkitbackendinteractiveauthority.c	\
 	polkitbackendlocalauthority.h		polkitbackendlocalauthority.c		\
+	polkitbackendjsauthority.h		polkitbackendjsauthority.c		\
 	polkitbackendactionpool.h		polkitbackendactionpool.c		\
 	polkitbackendconfigsource.h		polkitbackendconfigsource.c		\
 	polkitbackendactionlookup.h		polkitbackendactionlookup.c		\
@@ -56,6 +57,7 @@ libpolkit_backend_1_la_CFLAGS =                                        	\
         -D_POLKIT_BACKEND_COMPILATION                                  	\
         $(GLIB_CFLAGS)							\
 	$(SYSTEMD_CFLAGS)						\
+	$(LIBJS_CFLAGS)							\
         $(NULL)
 
 libpolkit_backend_1_la_LIBADD =                               		\
@@ -63,6 +65,7 @@ libpolkit_backend_1_la_LIBADD =                               		\
 	$(SYSTEMD_LIBS)							\
 	$(top_builddir)/src/polkit/libpolkit-gobject-1.la		\
 	$(EXPAT_LIBS)							\
+	$(LIBJS_LIBS)							\
         $(NULL)
 
 libpolkit_backend_1_la_LDFLAGS = -export-symbols-regex '(^polkit_.*)'
diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c
index fd4f161..e127247 100644
--- a/src/polkitbackend/polkitbackendauthority.c
+++ b/src/polkitbackend/polkitbackendauthority.c
@@ -31,6 +31,7 @@
 
 #include "polkitbackendauthority.h"
 #include "polkitbackendlocalauthority.h"
+#include "polkitbackendjsauthority.h"
 
 #include "polkitbackendprivate.h"
 
@@ -1359,6 +1360,7 @@ polkit_backend_authority_get (void)
 {
   static GIOExtensionPoint *ep = NULL;
   static volatile GType local_authority_type = G_TYPE_INVALID;
+  static volatile GType js_authority_type = G_TYPE_INVALID;
   GList *modules;
   GList *authority_implementations;
   GType authority_type;
@@ -1374,9 +1376,9 @@ polkit_backend_authority_get (void)
 
   /* make sure local types are registered */
   if (local_authority_type == G_TYPE_INVALID)
-    {
-      local_authority_type = POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY;
-    }
+    local_authority_type = POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY;
+  if (js_authority_type == G_TYPE_INVALID)
+    js_authority_type = POLKIT_BACKEND_TYPE_JS_AUTHORITY;
 
   /* load all modules */
   modules = g_io_modules_load_all_in_directory (PACKAGE_LIB_DIR "/polkit-1/extensions");
@@ -1416,17 +1418,114 @@ polkit_backend_authority_get (void)
   return authority;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef enum
+{
+  _COLOR_RESET,
+  _COLOR_BOLD_ON,
+  _COLOR_INVERSE_ON,
+  _COLOR_BOLD_OFF,
+  _COLOR_FG_BLACK,
+  _COLOR_FG_RED,
+  _COLOR_FG_GREEN,
+  _COLOR_FG_YELLOW,
+  _COLOR_FG_BLUE,
+  _COLOR_FG_MAGENTA,
+  _COLOR_FG_CYAN,
+  _COLOR_FG_WHITE,
+  _COLOR_BG_RED,
+  _COLOR_BG_GREEN,
+  _COLOR_BG_YELLOW,
+  _COLOR_BG_BLUE,
+  _COLOR_BG_MAGENTA,
+  _COLOR_BG_CYAN,
+  _COLOR_BG_WHITE
+} _Color;
+
+static gboolean _color_stdin_is_tty = FALSE;
+static gboolean _color_initialized = FALSE;
+
+static void
+_color_init (void)
+{
+  if (_color_initialized)
+    return;
+  _color_initialized = TRUE;
+  _color_stdin_is_tty = (isatty (STDIN_FILENO) != 0 && isatty (STDOUT_FILENO) != 0);
+}
+
+static const gchar *
+_color_get (_Color color)
+{
+  const gchar *str;
+
+  _color_init ();
+
+  if (!_color_stdin_is_tty)
+    return "";
+
+  str = NULL;
+  switch (color)
+    {
+    case _COLOR_RESET:      str="\x1b[0m"; break;
+    case _COLOR_BOLD_ON:    str="\x1b[1m"; break;
+    case _COLOR_INVERSE_ON: str="\x1b[7m"; break;
+    case _COLOR_BOLD_OFF:   str="\x1b[22m"; break;
+    case _COLOR_FG_BLACK:   str="\x1b[30m"; break;
+    case _COLOR_FG_RED:     str="\x1b[31m"; break;
+    case _COLOR_FG_GREEN:   str="\x1b[32m"; break;
+    case _COLOR_FG_YELLOW:  str="\x1b[33m"; break;
+    case _COLOR_FG_BLUE:    str="\x1b[34m"; break;
+    case _COLOR_FG_MAGENTA: str="\x1b[35m"; break;
+    case _COLOR_FG_CYAN:    str="\x1b[36m"; break;
+    case _COLOR_FG_WHITE:   str="\x1b[37m"; break;
+    case _COLOR_BG_RED:     str="\x1b[41m"; break;
+    case _COLOR_BG_GREEN:   str="\x1b[42m"; break;
+    case _COLOR_BG_YELLOW:  str="\x1b[43m"; break;
+    case _COLOR_BG_BLUE:    str="\x1b[44m"; break;
+    case _COLOR_BG_MAGENTA: str="\x1b[45m"; break;
+    case _COLOR_BG_CYAN:    str="\x1b[46m"; break;
+    case _COLOR_BG_WHITE:   str="\x1b[47m"; break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+  return str;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 void
 polkit_backend_authority_log (PolkitBackendAuthority *authority,
                               const gchar *format,
                               ...)
 {
+  GTimeVal now;
+  time_t now_time;
+  struct tm *now_tm;
+  gchar time_buf[128];
+  gchar *message;
   va_list var_args;
 
   g_return_if_fail (POLKIT_BACKEND_IS_AUTHORITY (authority));
 
   va_start (var_args, format);
-  vsyslog (LOG_NOTICE, format, var_args);
-
+  message = g_strdup_vprintf (format, var_args);
   va_end (var_args);
+
+  va_start (var_args, format);
+  syslog (LOG_NOTICE, "%s", message);
+
+  g_get_current_time (&now);
+  now_time = (time_t) now.tv_sec;
+  now_tm = localtime (&now_time);
+  strftime (time_buf, sizeof time_buf, "%H:%M:%S", now_tm);
+  g_print ("%s%s%s.%03d%s: %s\n",
+           _color_get (_COLOR_BOLD_ON), _color_get (_COLOR_FG_YELLOW),
+           time_buf, (gint) now.tv_usec / 1000,
+           _color_get (_COLOR_RESET),
+           message);
+
+  g_free (message);
 }
diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c
index b237e9d..5f6eea5 100644
--- a/src/polkitbackend/polkitbackendinteractiveauthority.c
+++ b/src/polkitbackend/polkitbackendinteractiveauthority.c
@@ -23,6 +23,7 @@
 #include <errno.h>
 #include <pwd.h>
 #include <grp.h>
+#include <netdb.h>
 #include <string.h>
 #include <glib/gstdio.h>
 #include <locale.h>
@@ -2059,6 +2060,110 @@ add_pid (PolkitDetails *details,
   ;
 }
 
+/* ---------------------------------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GList *
+get_users_in_group (PolkitIdentity                    *group,
+                    gboolean                           include_root)
+{
+  gid_t gid;
+  struct group *grp;
+  GList *ret;
+  guint n;
+
+  ret = NULL;
+
+  gid = polkit_unix_group_get_gid (POLKIT_UNIX_GROUP (group));
+  grp = getgrgid (gid);
+  if (grp == NULL)
+    {
+      g_warning ("Error looking up group with gid %d: %s", gid, g_strerror (errno));
+      goto out;
+    }
+
+  for (n = 0; grp->gr_mem != NULL && grp->gr_mem[n] != NULL; n++)
+    {
+      PolkitIdentity *user;
+      GError *error;
+
+      if (!include_root && g_strcmp0 (grp->gr_mem[n], "root") == 0)
+        continue;
+
+      error = NULL;
+      user = polkit_unix_user_new_for_name (grp->gr_mem[n], &error);
+      if (user == NULL)
+        {
+          g_warning ("Unknown username '%s' in group: %s", grp->gr_mem[n], error->message);
+          g_error_free (error);
+        }
+      else
+        {
+          ret = g_list_prepend (ret, user);
+        }
+    }
+
+  ret = g_list_reverse (ret);
+
+ out:
+  return ret;
+}
+
+static GList *
+get_users_in_net_group (PolkitIdentity                    *group,
+                        gboolean                           include_root)
+{
+  const gchar *name;
+  GList *ret;
+
+  ret = NULL;
+  name = polkit_unix_netgroup_get_name (POLKIT_UNIX_NETGROUP (group));
+
+  if (setnetgrent (name) == 0)
+    {
+      g_warning ("Error looking up net group with name %s: %s", name, g_strerror (errno));
+      goto out;
+    }
+
+  for (;;)
+    {
+      char *hostname, *username, *domainname;
+      PolkitIdentity *user;
+      GError *error = NULL;
+
+      if (getnetgrent (&hostname, &username, &domainname) == 0)
+        break;
+
+      /* Skip NULL entries since we never want to make everyone an admin
+       * Skip "-" entries which mean "no match ever" in netgroup land */
+      if (username == NULL || g_strcmp0 (username, "-") == 0)
+        continue;
+
+      /* TODO: Should we match on hostname? Maybe only allow "-" as a hostname
+       * for safety. */
+
+      user = polkit_unix_user_new_for_name (username, &error);
+      if (user == NULL)
+        {
+          g_warning ("Unknown username '%s' in unix-netgroup: %s", username, error->message);
+          g_error_free (error);
+        }
+      else
+        {
+          ret = g_list_prepend (ret, user);
+        }
+    }
+
+  ret = g_list_reverse (ret);
+
+ out:
+  endnetgrent ();
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
                                          PolkitSubject               *subject,
@@ -2080,6 +2185,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
   gchar *localized_icon_name;
   PolkitDetails *localized_details;
   GVariant *details_gvariant;
+  GList *user_identities = NULL;
   GVariantBuilder identities_builder;
   GVariant *parameters;
 
@@ -2138,10 +2244,33 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
   details_gvariant = polkit_details_to_gvariant (localized_details);
   g_variant_ref_sink (details_gvariant);
 
-  g_variant_builder_init (&identities_builder, G_VARIANT_TYPE ("a(sa{sv})"));
+  /* expand groups/netgroups to users */
+  user_identities = NULL;
   for (l = identities; l != NULL; l = l->next)
     {
       PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
+      if (POLKIT_IS_UNIX_USER (identity))
+        {
+          user_identities = g_list_append (user_identities, g_object_ref (identity));
+        }
+      else if (POLKIT_IS_UNIX_GROUP (identity))
+        {
+          user_identities = g_list_concat (user_identities, get_users_in_group (identity, FALSE));
+        }
+      else if (POLKIT_IS_UNIX_NETGROUP (identity))
+        {
+          user_identities =  g_list_concat (user_identities, get_users_in_net_group (identity, FALSE));
+        }
+      else
+        {
+          g_warning ("Unsupported identity");
+        }
+    }
+
+  g_variant_builder_init (&identities_builder, G_VARIANT_TYPE ("a(sa{sv})"));
+  for (l = user_identities; l != NULL; l = l->next)
+    {
+      PolkitIdentity *identity = POLKIT_IDENTITY (l->data);
       GVariant *value;
       value = polkit_identity_to_gvariant (identity);
       g_variant_ref_sink (value);
@@ -2167,6 +2296,7 @@ authentication_agent_initiate_challenge (AuthenticationAgent         *agent,
                      (GAsyncReadyCallback) authentication_agent_begin_cb,
                      session);
 
+  g_list_free_full (user_identities, g_object_unref);
   g_list_foreach (identities, (GFunc) g_object_unref, NULL);
   g_list_free (identities);
   g_free (cookie);
diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
new file mode 100644
index 0000000..23d2640
--- /dev/null
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -0,0 +1,831 @@
+/*
+ * Copyright (C) 2008-2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#include "config.h"
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <netdb.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <locale.h>
+#include <glib/gi18n-lib.h>
+
+#include <polkit/polkit.h>
+#include "polkitbackendjsauthority.h"
+
+#include <polkit/polkitprivate.h>
+
+#include <jsapi.h>
+
+/**
+ * SECTION:polkitbackendjsauthority
+ * @title: PolkitBackendJsAuthority
+ * @short_description: JS Authority
+ * @stability: Unstable
+ *
+ * An implementation of #PolkitBackendAuthority that reads and
+ * evalates Javascript files and supports interaction with
+ * authentication agents (virtue of being based on
+ * #PolkitBackendInteractiveAuthority).
+ */
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+struct _PolkitBackendJsAuthorityPrivate
+{
+  gchar *rules_dir;
+  GFileMonitor *dir_monitor;
+
+  JSRuntime *rt;
+  JSContext *cx;
+  JSObject *js_global;
+  JSObject *js_polkit;
+
+  /* A list of JSObject instances */
+  GList *scripts;
+};
+
+static void on_dir_monitor_changed (GFileMonitor     *monitor,
+                                    GFile            *file,
+                                    GFile            *other_file,
+                                    GFileMonitorEvent event_type,
+                                    gpointer          user_data);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+enum
+{
+  PROP_0,
+  PROP_RULES_DIR,
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GList *polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *authority,
+                                                                     PolkitSubject                     *caller,
+                                                                     PolkitSubject                     *subject,
+                                                                     PolkitIdentity                    *user_for_subject,
+                                                                     const gchar                       *action_id,
+                                                                     PolkitDetails                     *details);
+
+static PolkitImplicitAuthorization polkit_backend_js_authority_check_authorization_sync (
+                                                          PolkitBackendInteractiveAuthority *authority,
+                                                          PolkitSubject                     *caller,
+                                                          PolkitSubject                     *subject,
+                                                          PolkitIdentity                    *user_for_subject,
+                                                          gboolean                           subject_is_local,
+                                                          gboolean                           subject_is_active,
+                                                          const gchar                       *action_id,
+                                                          PolkitDetails                     *details,
+                                                          PolkitImplicitAuthorization        implicit,
+                                                          PolkitDetails                     *out_details);
+
+G_DEFINE_TYPE_WITH_CODE (PolkitBackendJsAuthority,
+                         polkit_backend_js_authority,
+                         POLKIT_BACKEND_TYPE_INTERACTIVE_AUTHORITY,
+                         g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
+                                                         g_define_type_id,
+                                                         "js-authority" PACKAGE_VERSION,
+                                                         10));
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static JSClass js_global_class = {
+  "global",
+  JSCLASS_GLOBAL_FLAGS,
+  JS_PropertyStub,
+  JS_PropertyStub,
+  JS_PropertyStub,
+  JS_StrictPropertyStub,
+  JS_EnumerateStub,
+  JS_ResolveStub,
+  JS_ConvertStub,
+  JS_FinalizeStub,
+  JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static JSClass js_polkit_class = {
+  "Polkit",
+  0,
+  JS_PropertyStub,
+  JS_PropertyStub,
+  JS_PropertyStub,
+  JS_StrictPropertyStub,
+  JS_EnumerateStub,
+  JS_ResolveStub,
+  JS_ConvertStub,
+  JS_FinalizeStub,
+  JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool js_polkit_log (JSContext *cx, uintN argc, jsval *vp);
+
+static JSFunctionSpec js_polkit_functions[] =
+{
+  JS_FS("log",            js_polkit_log,            0, 0),
+  JS_FS_END
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void report_error (JSContext     *cx,
+                          const char    *message,
+                          JSErrorReport *report)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx));
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "%s:%u: %s",
+                                report->filename ? report->filename : "<no filename>",
+                                (unsigned int) report->lineno,
+                                message);
+}
+
+static void
+polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
+{
+  authority->priv = G_TYPE_INSTANCE_GET_PRIVATE (authority,
+                                                 POLKIT_BACKEND_TYPE_JS_AUTHORITY,
+                                                 PolkitBackendJsAuthorityPrivate);
+}
+
+static void
+load_scripts (PolkitBackendJsAuthority  *authority)
+{
+  GDir *dir = NULL;
+  GList *files = NULL;
+  GList *l;
+  const gchar *name;
+  guint num_scripts = 0;
+  GError *error = NULL;
+
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "Loading scripts from directory %s",
+                                authority->priv->rules_dir);
+
+  dir = g_dir_open (authority->priv->rules_dir,
+                    0,
+                    &error);
+  if (dir == NULL)
+    {
+      polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                    "Error opening rules directory: %s (%s, %d)\n",
+                                    error->message, g_quark_to_string (error->domain), error->code);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  files = NULL;
+  while ((name = g_dir_read_name (dir)) != NULL)
+    {
+      if (g_str_has_suffix (name, ".rules"))
+        files = g_list_prepend (files, g_strdup_printf ("%s/%s", authority->priv->rules_dir, name));
+    }
+
+  files = g_list_sort (files, (GCompareFunc) g_strcmp0);
+
+  for (l = files; l != NULL; l = l->next)
+    {
+      const gchar *filename = l->data;
+      JSObject *script;
+
+      script = JS_CompileFile (authority->priv->cx,
+                               authority->priv->js_global,
+                               filename);
+      if (script == NULL)
+        {
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Error compiling script %s",
+                                        filename);
+          continue;
+        }
+
+      /* evaluate the script */
+      jsval rval;
+      if (!JS_ExecuteScript (authority->priv->cx,
+                             authority->priv->js_global,
+                             script,
+                             &rval))
+        {
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Error executing script %s",
+                                        filename);
+          continue;
+        }
+
+      //g_print ("Successfully loaded and evaluated script `%s'\n", filename);
+
+      num_scripts++;
+    }
+
+  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                "Finished loading, compiling and executing %d scripts",
+                                num_scripts);
+
+ out:
+  g_list_free_full (files, g_free);
+  if (dir != NULL)
+    g_dir_close (dir);
+}
+
+static void
+reload_scripts (PolkitBackendJsAuthority *authority)
+{
+  jsval argv[1] = {0};
+  jsval rval = {0};
+
+  if (!JS_CallFunctionName(authority->priv->cx,
+                           authority->priv->js_polkit,
+                           "_deleteRules",
+                           0,
+                           argv,
+                           &rval))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, faileded clearing rules\n");
+      goto out;
+    }
+
+  load_scripts (authority);
+ out:
+  ;
+}
+
+static void
+on_dir_monitor_changed (GFileMonitor     *monitor,
+                        GFile            *file,
+                        GFile            *other_file,
+                        GFileMonitorEvent event_type,
+                        gpointer          user_data)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (user_data);
+
+  /* TODO: maybe rate-limit so storms of events are collapsed into one with a 500ms resolution?
+   *       Because when editing a file with emacs we get 4-8 events..
+   */
+
+  if (file != NULL)
+    {
+      gchar *name;
+
+      name = g_file_get_basename (file);
+
+      /* g_print ("event_type=%d file=%p name=%s\n", event_type, file, name); */
+      if (!g_str_has_prefix (name, ".") &&
+          !g_str_has_prefix (name, "#") &&
+          g_str_has_suffix (name, ".rules") &&
+          (event_type == G_FILE_MONITOR_EVENT_CREATED ||
+           event_type == G_FILE_MONITOR_EVENT_DELETED ||
+           event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
+        {
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Reloading scripts");
+          reload_scripts (authority);
+        }
+      g_free (name);
+    }
+}
+
+static const gchar js_polkit_init[] =
+  "polkit._administratorRuleFuncs = [];\n"
+  "polkit.addAdministratorRule = function(callback) {this._administratorRuleFuncs.push(callback);};\n"
+  "polkit._runAdministratorRules = function(action, pid, user, groups, is_local, is_active) {\n"
+  "  var ret = null;\n"
+  "  var subject = {};\n"
+  "  subject.pid = pid;\n"
+  "  subject.user = user;\n"
+  "  subject.local = is_local;\n"
+  "  subject.active = is_active;\n"
+  "  subject.groups = groups.split(',');\n"
+  "  for (var n = this._administratorRuleFuncs.length - 1; n >= 0; n--) {\n"
+  "    var func = this._administratorRuleFuncs[n];\n"
+  "    ret = func(action, subject);\n"
+  "    if (ret)\n"
+  "      break\n"
+  "  }\n"
+  "  return ret.join(',');\n"
+  "};\n"
+  "\n"
+  "polkit._authorizationRuleFuncs = [];\n"
+  "polkit.addAuthorizationRule = function(callback) {this._authorizationRuleFuncs.push(callback);};\n"
+  "polkit._runAuthorizationRules = function(action, pid, user, groups, is_local, is_active) {\n"
+  "  var ret = null;\n"
+  "  var subject = {};\n"
+  "  subject.pid = pid;\n"
+  "  subject.user = user;\n"
+  "  subject.local = is_local;\n"
+  "  subject.active = is_active;\n"
+  "  subject.groups = groups.split(',');\n"
+  "  for (var n = this._authorizationRuleFuncs.length - 1; n >= 0; n--) {\n"
+  "    var func = this._authorizationRuleFuncs[n];\n"
+  "    ret = func(action, subject);\n"
+  "    if (ret)\n"
+  "      break\n"
+  "  }\n"
+  "  return ret;\n"
+  "};\n"
+  "\n"
+  "polkit._deleteRules = function() {\n"
+  "  this._administratorRuleFuncs = [];\n"
+  "  this._authorizationRuleFuncs = [];\n"
+  "};\n"
+  "\n"
+  "";
+
+
+static void
+polkit_backend_js_authority_constructed (GObject *object)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
+
+  /* TODO: error checking */
+  authority->priv->rt = JS_NewRuntime (8L * 1024L * 1024L);
+  authority->priv->cx = JS_NewContext (authority->priv->rt, 8192);
+  JS_SetOptions (authority->priv->cx,
+                 JSOPTION_VAROBJFIX |
+                 JSOPTION_JIT |
+                 JSOPTION_METHODJIT);
+  JS_SetVersion(authority->priv->cx, JSVERSION_LATEST);
+  JS_SetErrorReporter(authority->priv->cx, report_error);
+  JS_SetContextPrivate (authority->priv->cx, authority);
+
+  authority->priv->js_global = JS_NewCompartmentAndGlobalObject (authority->priv->cx,
+                                                                 &js_global_class,
+                                                                 NULL);
+  JS_InitStandardClasses (authority->priv->cx, authority->priv->js_global);
+
+  authority->priv->js_polkit = JS_DefineObject(authority->priv->cx,
+                                               authority->priv->js_global,
+                                               "polkit",
+                                               &js_polkit_class,
+                                               NULL,
+                                               JSPROP_ENUMERATE);
+  JS_DefineFunctions (authority->priv->cx,
+                      authority->priv->js_polkit,
+                      js_polkit_functions);
+
+  if (!JS_EvaluateScript (authority->priv->cx,
+                          authority->priv->js_global,
+                          js_polkit_init,
+                          strlen (js_polkit_init),
+                          NULL,  /* filename */
+                          0,     /* lineno */
+                          NULL)) /* rval */
+    {
+      g_printerr ("Error running init code\n");
+    }
+
+  load_scripts (authority);
+
+  G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
+}
+
+static void
+polkit_backend_js_authority_finalize (GObject *object)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
+
+  g_free (authority->priv->rules_dir);
+  if (authority->priv->dir_monitor != NULL)
+    {
+      g_signal_handlers_disconnect_by_func (authority->priv->dir_monitor,
+                                            G_CALLBACK (on_dir_monitor_changed),
+                                            authority);
+      g_object_unref (authority->priv->dir_monitor);
+    }
+
+  JS_DestroyContext (authority->priv->cx);
+  JS_DestroyRuntime (authority->priv->rt);
+  /* JS_ShutDown (); */
+
+  G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->finalize (object);
+}
+
+static void
+polkit_backend_js_authority_set_property (GObject      *object,
+                                          guint         property_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
+  GFile *file;
+  GError *error;
+
+  switch (property_id)
+    {
+      case PROP_RULES_DIR:
+        g_assert (authority->priv->rules_dir == NULL);
+        authority->priv->rules_dir = g_value_dup_string (value);
+
+        file = g_file_new_for_path (authority->priv->rules_dir);
+        error = NULL;
+        authority->priv->dir_monitor = g_file_monitor_directory (file,
+                                                                 G_FILE_MONITOR_NONE,
+                                                                 NULL,
+                                                                 &error);
+        if (authority->priv->dir_monitor == NULL)
+          {
+            g_warning ("Error monitoring directory %s: %s",
+                       authority->priv->rules_dir,
+                       error->message);
+            g_clear_error (&error);
+          }
+        else
+          {
+            g_signal_connect (authority->priv->dir_monitor,
+                              "changed",
+                              G_CALLBACK (on_dir_monitor_changed),
+                              authority);
+          }
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static const gchar *
+polkit_backend_js_authority_get_name (PolkitBackendAuthority *authority)
+{
+  return "js";
+}
+
+static const gchar *
+polkit_backend_js_authority_get_version (PolkitBackendAuthority *authority)
+{
+  return PACKAGE_VERSION;
+}
+
+static PolkitAuthorityFeatures
+polkit_backend_js_authority_get_features (PolkitBackendAuthority *authority)
+{
+  return POLKIT_AUTHORITY_FEATURES_TEMPORARY_AUTHORIZATION;
+}
+
+static void
+polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
+{
+  GObjectClass *gobject_class;
+  PolkitBackendAuthorityClass *authority_class;
+  PolkitBackendInteractiveAuthorityClass *interactive_authority_class;
+
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize                               = polkit_backend_js_authority_finalize;
+  gobject_class->set_property                           = polkit_backend_js_authority_set_property;
+  gobject_class->constructed                            = polkit_backend_js_authority_constructed;
+
+  authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
+  authority_class->get_name                             = polkit_backend_js_authority_get_name;
+  authority_class->get_version                          = polkit_backend_js_authority_get_version;
+  authority_class->get_features                         = polkit_backend_js_authority_get_features;
+
+  interactive_authority_class = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_CLASS (klass);
+  interactive_authority_class->get_admin_identities     = polkit_backend_js_authority_get_admin_auth_identities;
+  interactive_authority_class->check_authorization_sync = polkit_backend_js_authority_check_authorization_sync;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_RULES_DIR,
+                                   g_param_spec_string ("rules-dir",
+                                                        NULL,
+                                                        NULL,
+                                                        PACKAGE_SYSCONF_DIR "/polkit-1/rules.d",
+                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+
+  g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+subject_to_js (PolkitBackendJsAuthority *authority,
+               PolkitSubject            *subject,
+               PolkitIdentity           *user_for_subject,
+               jsval                    *jsval_pid,
+               jsval                    *jsval_user,
+               jsval                    *jsval_groups,
+               GError                  **error)
+{
+  gboolean ret = FALSE;
+  JSString *user_name_jstr;
+  JSString *groups_jstr;
+  pid_t pid;
+  uid_t uid;
+  gchar *user_name = NULL;
+  GString *groups = NULL;
+  struct passwd *passwd;
+
+  g_return_val_if_fail (jsval_pid != NULL, FALSE);
+  g_return_val_if_fail (jsval_user != NULL, FALSE);
+  g_return_val_if_fail (jsval_groups != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (POLKIT_IS_UNIX_PROCESS (subject))
+    {
+      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject));
+    }
+  else if (POLKIT_IS_SYSTEM_BUS_NAME (subject))
+    {
+      PolkitSubject *process;
+      process = polkit_system_bus_name_get_process_sync (POLKIT_SYSTEM_BUS_NAME (subject), NULL, error);
+      if (process == NULL)
+        goto out;
+      pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (process));
+      g_object_unref (process);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+
+  g_assert (POLKIT_IS_UNIX_USER (user_for_subject));
+  uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_for_subject));
+
+  groups = g_string_new (NULL);
+
+  passwd = getpwuid (uid);
+  if (passwd == NULL)
+    {
+      user_name = g_strdup_printf ("%d", (gint) uid);
+      g_warning ("Error looking up info for uid %d: %m", (gint) uid);
+    }
+  else
+    {
+      gid_t gids[512];
+      int num_gids = 512;
+
+      user_name = g_strdup (passwd->pw_name);
+
+      if (getgrouplist (passwd->pw_name,
+                        passwd->pw_gid,
+                        gids,
+                        &num_gids) < 0)
+        {
+          g_warning ("Error looking up groups for uid %d: %m", (gint) uid);
+        }
+      else
+        {
+          gint n;
+          for (n = 0; n < num_gids; n++)
+            {
+              struct group *group;
+              if (n > 0)
+                g_string_append_c (groups, ',');
+
+              group = getgrgid (gids[n]);
+              if (group == NULL)
+                {
+                  g_string_append_printf (groups, "%d", (gint) gids[n]);
+                }
+              else
+                {
+                  g_string_append_printf (groups, "%s", group->gr_name);
+                }
+            }
+        }
+    }
+
+  user_name_jstr = JS_NewStringCopyZ (authority->priv->cx, user_name);
+  groups_jstr = JS_NewStringCopyZ (authority->priv->cx, groups->str);
+  *jsval_pid = INT_TO_JSVAL ((int32) pid);
+  *jsval_user = STRING_TO_JSVAL (user_name_jstr);
+  *jsval_groups = STRING_TO_JSVAL (groups_jstr);
+
+  ret = TRUE;
+
+ out:
+  /* TODO: are we leaking _jstr ? */
+  g_free (user_name);
+  if (groups != NULL)
+    g_string_free (groups, TRUE);
+  return ret;
+}
+
+
+static GList *
+polkit_backend_js_authority_get_admin_auth_identities (PolkitBackendInteractiveAuthority *_authority,
+                                                       PolkitSubject                     *caller,
+                                                       PolkitSubject                     *subject,
+                                                       PolkitIdentity                    *user_for_subject,
+                                                       const gchar                       *action_id,
+                                                       PolkitDetails                     *details)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
+  GList *ret = NULL;
+  jsval argv[6] = {0};
+  jsval rval = {0};
+  JSString *action_id_jstr;
+  guint n;
+  GError *error = NULL;
+  JSString *ret_jsstr;
+  gchar *ret_str = NULL;
+  gchar **ret_strs = NULL;
+
+  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &error))
+    {
+      /* TODO: syslog? */
+      g_printerr ("Error converting subject: %s\n", error->message);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
+  argv[0] = STRING_TO_JSVAL (action_id_jstr);
+  argv[4] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_local);
+  argv[5] = BOOLEAN_TO_JSVAL (FALSE);//TODO:subject_is_active);
+
+  if (!JS_CallFunctionName(authority->priv->cx,
+                           authority->priv->js_polkit,
+                           "_runAdministratorRules",
+                           6,
+                           argv,
+                           &rval))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, failed\n");
+      goto out;
+    }
+
+  if (!JSVAL_IS_STRING (rval) && !JSVAL_IS_NULL (rval))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, not string\n");
+      goto out;
+    }
+
+  ret_jsstr = JSVAL_TO_STRING (rval);
+  ret_str = g_utf16_to_utf8 (JS_GetStringCharsZ (authority->priv->cx, ret_jsstr), -1, NULL, NULL, NULL);
+  if (ret_str == NULL)
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, error converting to UTF-8\n");
+      goto out;
+    }
+
+  //g_print ("yay, worked `%s'\n", ret_str);
+
+  ret_strs = g_strsplit (ret_str, ",", -1);
+  for (n = 0; ret_strs != NULL && ret_strs[n] != NULL; n++)
+    {
+      const gchar *identity_str = ret_strs[n];
+      PolkitIdentity *identity;
+
+      error = NULL;
+      identity = polkit_identity_from_string (identity_str, &error);
+      if (identity == NULL)
+        {
+          /* TODO: syslog? */
+          g_printerr ("boo, identity `%s' is not valid, ignoring\n", identity_str);
+        }
+      else
+        {
+          ret = g_list_prepend (ret, identity);
+        }
+    }
+  ret = g_list_reverse (ret);
+
+ out:
+  g_strfreev (ret_strs);
+  g_free (ret_str);
+  /* fallback to root password auth */
+  if (ret == NULL)
+    ret = g_list_prepend (ret, polkit_unix_user_new (0));
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static PolkitImplicitAuthorization
+polkit_backend_js_authority_check_authorization_sync (PolkitBackendInteractiveAuthority *_authority,
+                                                      PolkitSubject                     *caller,
+                                                      PolkitSubject                     *subject,
+                                                      PolkitIdentity                    *user_for_subject,
+                                                      gboolean                           subject_is_local,
+                                                      gboolean                           subject_is_active,
+                                                      const gchar                       *action_id,
+                                                      PolkitDetails                     *details,
+                                                      PolkitImplicitAuthorization        implicit,
+                                                      PolkitDetails                     *out_details)
+{
+  PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (_authority);
+  PolkitImplicitAuthorization ret = implicit;
+  jsval argv[6] = {0};
+  jsval rval = {0};
+  JSString *action_id_jstr;
+  GError *error = NULL;
+  JSString *ret_jsstr;
+  const jschar *ret_utf16;
+  gchar *ret_str = NULL;
+
+  if (!subject_to_js (authority, subject, user_for_subject, &argv[1], &argv[2], &argv[3], &error))
+    {
+      /* TODO: syslog? */
+      g_printerr ("Error converting subject: %s\n", error->message);
+      g_clear_error (&error);
+      goto out;
+    }
+
+  action_id_jstr = JS_NewStringCopyZ (authority->priv->cx, action_id);
+  argv[0] = STRING_TO_JSVAL (action_id_jstr);
+  argv[4] = BOOLEAN_TO_JSVAL (subject_is_local);
+  argv[5] = BOOLEAN_TO_JSVAL (subject_is_active);
+
+  if (!JS_CallFunctionName(authority->priv->cx,
+                           authority->priv->js_polkit,
+                           "_runAuthorizationRules",
+                           6,
+                           argv,
+                           &rval))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, failed\n");
+      goto out;
+    }
+
+  if (!JSVAL_IS_STRING (rval) && !JSVAL_IS_NULL (rval))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, not string\n");
+      goto out;
+    }
+
+  ret_jsstr = JSVAL_TO_STRING (rval);
+  if (ret_jsstr == NULL)
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, string is null\n");
+      goto out;
+    }
+
+  ret_utf16 = JS_GetStringCharsZ (authority->priv->cx, ret_jsstr);
+  ret_str = g_utf16_to_utf8 (ret_utf16, -1, NULL, NULL, NULL);
+  if (ret_str == NULL)
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, error converting to UTF-8\n");
+      goto out;
+    }
+
+  if (!polkit_implicit_authorization_from_string (ret_str, &ret))
+    {
+      /* TODO: syslog? */
+      g_printerr ("boo, returned result `%s' is not valid\n", ret_str);
+      goto out;
+    }
+
+  g_print ("yay, worked `%s'\n", ret_str);
+
+ out:
+  g_free (ret_str);
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static JSBool
+js_polkit_log (JSContext  *cx,
+               uintN       argc,
+               jsval      *vp)
+{
+  /* PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (JS_GetContextPrivate (cx)); */
+  JSBool ret = JS_FALSE;
+  JSString *str;
+  char *s;
+
+  if (!JS_ConvertArguments (cx, argc, JS_ARGV (cx, vp), "S", &str))
+    goto out;
+
+  s = JS_EncodeString (cx, str);
+  JS_ReportWarning (cx, s);
+  JS_free (cx, s);
+
+  ret = JS_TRUE;
+
+  JS_SET_RVAL (cx, vp, JSVAL_VOID);  /* return undefined */
+ out:
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkitbackend/polkitbackendjsauthority.h b/src/polkitbackend/polkitbackendjsauthority.h
new file mode 100644
index 0000000..6fd283b
--- /dev/null
+++ b/src/polkitbackend/polkitbackendjsauthority.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2008-2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz at redhat.com>
+ */
+
+#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
+#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_BACKEND_JS_AUTHORITY_H
+#define __POLKIT_BACKEND_JS_AUTHORITY_H
+
+#include <glib-object.h>
+#include <polkitbackend/polkitbackendtypes.h>
+#include <polkitbackend/polkitbackendinteractiveauthority.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_BACKEND_TYPE_JS_AUTHORITY         (polkit_backend_js_authority_get_type ())
+#define POLKIT_BACKEND_JS_AUTHORITY(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_JS_AUTHORITY, PolkitBackendJsAuthority))
+#define POLKIT_BACKEND_JS_AUTHORITY_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_JS_AUTHORITY, PolkitBackendJsAuthorityClass))
+#define POLKIT_BACKEND_JS_AUTHORITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_JS_AUTHORITY,PolkitBackendJsAuthorityClass))
+#define POLKIT_BACKEND_IS_JS_AUTHORITY(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_JS_AUTHORITY))
+#define POLKIT_BACKEND_IS_JS_AUTHORITY_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_JS_AUTHORITY))
+
+typedef struct _PolkitBackendJsAuthorityClass    PolkitBackendJsAuthorityClass;
+typedef struct _PolkitBackendJsAuthorityPrivate  PolkitBackendJsAuthorityPrivate;
+
+/**
+ * PolkitBackendJsAuthority:
+ *
+ * The #PolkitBackendJsAuthority struct should not be accessed directly.
+ */
+struct _PolkitBackendJsAuthority
+{
+  /*< private >*/
+  PolkitBackendInteractiveAuthority parent_instance;
+  PolkitBackendJsAuthorityPrivate *priv;
+};
+
+/**
+ * PolkitBackendJsAuthorityClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #PolkitBackendJsAuthority.
+ */
+struct _PolkitBackendJsAuthorityClass
+{
+  /*< public >*/
+  PolkitBackendInteractiveAuthorityClass parent_class;
+};
+
+GType                   polkit_backend_js_authority_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __POLKIT_BACKEND_JS_AUTHORITY_H */
+
+
diff --git a/src/polkitbackend/polkitbackendtypes.h b/src/polkitbackend/polkitbackendtypes.h
index d06f62a..2fe36ac 100644
--- a/src/polkitbackend/polkitbackendtypes.h
+++ b/src/polkitbackend/polkitbackendtypes.h
@@ -36,5 +36,8 @@ typedef struct _PolkitBackendInteractiveAuthority PolkitBackendInteractiveAuthor
 struct _PolkitBackendLocalAuthority;
 typedef struct _PolkitBackendLocalAuthority PolkitBackendLocalAuthority;
 
+struct _PolkitBackendJsAuthority;
+typedef struct _PolkitBackendJsAuthority PolkitBackendJsAuthority;
+
 #endif /* __POLKIT_BACKEND_TYPES_H */
 
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
new file mode 100644
index 0000000..adf4f16
--- /dev/null
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -0,0 +1,32 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+polkit.addAdministratorRule(function(action, subject) {
+    return ["unix-group:admin", "unix-user:root"];
+});
+
+polkit.addAdministratorRule(function(action, subject) {
+    if (action == "net.company.action1") {
+        return ["unix-group:admin"];
+    }
+    return null;
+});
+
+polkit.addAdministratorRule(function(action, subject) {
+    if (action == "net.company.action2") {
+        return ["unix-group:users"];
+    }
+    return null;
+});
+
+// -----
+
+polkit.addAuthorizationRule(function(action, subject) {
+    return "auth_admin";
+});
+
+polkit.addAuthorizationRule(function(action, subject) {
+    if (action == "org.freedesktop.policykit.exec") {
+        return "auth_admin";
+    }
+    return null;
+});
diff --git a/test/polkitbackend/Makefile.am b/test/polkitbackend/Makefile.am
index c611b5b..46706d3 100644
--- a/test/polkitbackend/Makefile.am
+++ b/test/polkitbackend/Makefile.am
@@ -39,8 +39,12 @@ polkitbackendlocalauthorizationstoretest_SOURCES = polkitbackendlocalauthorizati
 TEST_PROGS += polkitbackendlocalauthoritytest
 polkitbackendlocalauthoritytest_SOURCES = polkitbackendlocalauthoritytest.c
 
+TEST_PROGS += polkitbackendjsauthoritytest
+polkitbackendjsauthoritytest_SOURCES = test-polkitbackendjsauthority.c
+
 # ----------------------------------------------------------------------------------------------------
 
+noinst_PROGRAMS = $(TEST_PROGS)
 check_PROGRAMS = $(TEST_PROGS)
 TESTS = $(TEST_PROGS)
 
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
new file mode 100644
index 0000000..c5015ff
--- /dev/null
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Nikki VonHollen <vonhollen at google.com>
+ *         David Zeuthen <davidz at redhat.com>
+ */
+
+#include "glib.h"
+
+#include <polkit/polkit.h>
+#include <polkitbackend/polkitbackendjsauthority.h>
+#include <polkittesthelper.h>
+
+/* Test helper types */
+
+static PolkitBackendJsAuthority *get_authority (void);
+
+static PolkitBackendJsAuthority *
+get_authority (void)
+{
+  gchar *rules_dir;
+  PolkitBackendJsAuthority *authority;
+
+  rules_dir = polkit_test_get_data_path ("etc/polkit-1/rules.d");
+  g_assert (rules_dir != NULL);
+
+  authority = g_object_new (POLKIT_BACKEND_TYPE_JS_AUTHORITY,
+                            "rules-dir", rules_dir,
+                            NULL);
+  g_free (rules_dir);
+  return authority;
+}
+
+
+static void
+test_get_admin_identities_for_action_id (const gchar         *action_id,
+                                         const gchar *const *expected_admins)
+{
+  PolkitBackendJsAuthority *authority = NULL;
+  PolkitSubject *caller = NULL;
+  PolkitSubject *subject = NULL;
+  PolkitIdentity *user_for_subject = NULL;
+  PolkitDetails *details = NULL;
+  GError *error = NULL;
+  GList *admin_identities = NULL;
+  GList *l;
+  guint n;
+
+  authority = get_authority ();
+
+  caller = polkit_unix_process_new (getpid ());
+  subject = polkit_unix_process_new (getpid ());
+  user_for_subject = polkit_identity_from_string ("unix-user:root", &error);
+  g_assert_no_error (error);
+
+  details = polkit_details_new ();
+
+  /* Get the list of PolkitUnixUser objects who are admins */
+  admin_identities = polkit_backend_interactive_authority_get_admin_identities (POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority),
+                                                                                caller,
+                                                                                subject,
+                                                                                user_for_subject,
+                                                                                action_id,
+                                                                                details);
+  for (l = admin_identities, n = 0; l != NULL; l = l->next, n++)
+    {
+      PolkitIdentity *test_identity = POLKIT_IDENTITY (l->data);
+      gchar *s;
+
+      g_assert (expected_admins[n] != NULL);
+
+      s = polkit_identity_to_string (test_identity);
+      g_assert_cmpstr (expected_admins[n], ==, s);
+      g_free (s);
+    }
+  g_assert (expected_admins[n] == NULL);
+
+  g_list_free_full (admin_identities, g_object_unref);
+  g_clear_object (&user_for_subject);
+  g_clear_object (&subject);
+  g_clear_object (&caller);
+  g_clear_object (&authority);
+}
+
+static void
+test_get_admin_identities (void)
+{
+  struct {
+    const gchar *action_id;
+    const gchar *expected_admins[5];
+  } test_cases[] = {
+    {
+      "com.example.doesntmatter",
+      {
+        "unix-group:admin",
+        "unix-user:root"
+      }
+    },
+    {
+      "net.company.action1",
+      {
+        "unix-group:admin"
+      }
+    },
+    {
+      "net.company.action2",
+      {
+        "unix-group:users"
+      }
+    },
+  };
+  guint n;
+
+  for (n = 0; n < G_N_ELEMENTS (test_cases); n++)
+    {
+      test_get_admin_identities_for_action_id (test_cases[n].action_id,
+                                               test_cases[n].expected_admins);
+    }
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  GIOExtensionPoint *ep;
+
+  g_type_init ();
+  g_test_init (&argc, &argv, NULL);
+  //polkit_test_redirect_logs ();
+
+  ep = g_io_extension_point_register (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME);
+  g_io_extension_point_set_required_type (ep, POLKIT_BACKEND_TYPE_AUTHORITY);
+
+  g_test_add_func ("/PolkitBackendJsAuthority/get_admin_identities", test_get_admin_identities);
+
+  return g_test_run ();
+};


More information about the hal-commit mailing list