rewrite authorization database and polkit-grant (now known as polkit-auth)
authorDavid Zeuthen <davidz@redhat.com>
Sun, 28 Oct 2007 23:18:37 +0000 (19:18 -0400)
committerDavid Zeuthen <davidz@redhat.com>
Sun, 28 Oct 2007 23:18:37 +0000 (19:18 -0400)
Also,

 - Rename polkit-list-actions to polkit-action.
 - Add a bash completion script to the polkit commandline tools.

Authorizations are no longer world-readable. So for this to work with
hal you now need to do this as root

 # polkit-auth --user haldaemon --grant org.freedesktop.policykit.read

Distributions needs to do this in the %post scripts or similar.

Sorry for this huge monster patch.

43 files changed:
Makefile.am
autogen.sh
configure.in
doc/Makefile.am
doc/man/Makefile.am
doc/man/PolicyKit.conf.xml
doc/man/PolicyKit.xml
doc/man/polkit-action.xml [moved from doc/man/polkit-list-actions.xml with 72% similarity]
doc/man/polkit-auth.xml [new file with mode: 0644]
doc/man/polkit-grant.xml [deleted file]
doc/polkit-docs.xml
po/ChangeLog [new file with mode: 0644]
po/LINGUAS [new file with mode: 0644]
po/POTFILES.in [new file with mode: 0644]
policy/Makefile.am
policy/org.freedesktop.policykit.policy.in [new file with mode: 0644]
policy/polkit-example-action.policy [deleted file]
polkit-dbus/Makefile.am
polkit-dbus/polkit-dbus.c
polkit-dbus/polkit-dbus.h
polkit-dbus/polkit-explicit-grant-helper.c [new file with mode: 0644]
polkit-dbus/polkit-read-auth-helper.c [new file with mode: 0644]
polkit-dbus/polkit-revoke-helper.c [new file with mode: 0644]
polkit-grant/polkit-grant-helper-pam.c
polkit-grant/polkit-grant-helper.c
polkit/Makefile.am
polkit/polkit-authorization-constraint.c [new file with mode: 0644]
polkit/polkit-authorization-constraint.h [new file with mode: 0644]
polkit/polkit-authorization-db.c
polkit/polkit-authorization-db.h
polkit/polkit-authorization.c
polkit/polkit-authorization.h
polkit/polkit-context.c
polkit/polkit-error.c
polkit/polkit-error.h
polkit/polkit-session.c
tools/Makefile.am
tools/polkit-action.c [moved from tools/polkit-list-actions.c with 88% similarity]
tools/polkit-auth.c [new file with mode: 0644]
tools/polkit-bash-completion.sh [new file with mode: 0644]
tools/polkit-config-file-validate.c
tools/polkit-grant.c [deleted file]
tools/polkit-policy-file-validate.c

index f925874..23d971f 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = data polkit polkit-dbus polkit-grant doc tools policy
+SUBDIRS = data polkit polkit-dbus polkit-grant doc tools policy po
 
 # Creating ChangeLog from git log (taken from cairo/Makefile.am):
 ChangeLog: $(srcdir)/ChangeLog
@@ -21,7 +21,18 @@ $(srcdir)/ChangeLog:
 
 .PHONY: ChangeLog $(srcdir)/ChangeLog
 
-EXTRA_DIST = HACKING mkinstalldirs ChangeLog
+EXTRA_DIST =                   \
+       HACKING                 \
+       mkinstalldirs           \
+       ChangeLog               \
+       intltool-extract.in     \
+       intltool-merge.in       \
+       intltool-update.in
+
+DISTCLEANFILES = \
+       intltool-extract        \
+       intltool-merge          \
+       intltool-update
 
 # xsltproc barfs on 'make distcheck'; disable for now
 DISTCHECK_CONFIGURE_FLAGS=--disable-man-pages
index a9ab28c..b9e83da 100755 (executable)
@@ -82,6 +82,8 @@ esac
       echo "Running autoconf ..."
       autoconf
 
+intltoolize --copy --force --automake                  || exit 1
+
 conf_flags="--enable-maintainer-mode --enable-gtk-doc"
 
 if test x$NOCONFIGURE = x; then
index 9c1da10..9a58cce 100644 (file)
@@ -25,6 +25,7 @@ AM_PROG_LIBTOOL
 AC_PROG_MAKE_SET
 AC_PROG_LN_S
 AC_SYS_LARGEFILE
+AM_PROG_CC_C_O
 
 # Taken from dbus
 AC_ARG_ENABLE(ansi,             [  --enable-ansi           enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
@@ -366,6 +367,17 @@ AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_ACCOUNT, "$PAM_FILE_INCLUDE_ACCOUNT", [pam f
 AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_PASSWORD, "$PAM_FILE_INCLUDE_PASSWORD", [pam file password])
 AC_DEFINE_UNQUOTED(PAM_FILE_INCLUDE_SESSION, "$PAM_FILE_INCLUDE_SESSION", [pam file session])
 
+# ********************
+# Internationalisation
+# ********************
+
+IT_PROG_INTLTOOL([0.36.0])
+GETTEXT_PACKAGE=PolicyKit
+AC_SUBST([GETTEXT_PACKAGE])
+AM_GLIB_GNU_GETTEXT
+AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain])
+
+
 AC_OUTPUT([
 Makefile
 data/Makefile
@@ -381,6 +393,7 @@ doc/Makefile
 doc/version.xml
 doc/man/Makefile
 policy/Makefile
+po/Makefile.in
 ])
 
 dnl ==========================================================================
@@ -421,13 +434,24 @@ echo "
         Building man pages:         ${enable_man_pages}
 "
 
-echo "NOTE: Remember to create user '${POLKIT_USER}' and group '${POLKIT_GROUP}' before 'make install'"
+echo "NOTE: Remember to create user '${POLKIT_USER}' and group '${POLKIT_GROUP}'"
+echo "      before 'make install'"
+echo
+
+echo "NOTE: The directories ${localstatedir}/run/PolicyKit and ${localstatedir}/lib/PolicyKit will be"
+echo "      owned by group '${POLKIT_GROUP}' and will be of mode 770."
+echo
+
+echo "NOTE: ${libexecdir}/polkit-read-auth-helper will be owned by group"
+echo "      '${POLKIT_GROUP}', and installed with mode 2755 (setgid binary)."
+echo
+
+echo "NOTE: ${libexecdir}/polkit-revoke-helper will be owned by group"
+echo "      '${POLKIT_GROUP}', and installed with mode 2755 (setgid binary)."
 echo
 
 echo "NOTE: ${libexecdir}/polkit-grant-helper will be owned by group"
-echo "      '${POLKIT_USER}', and installed with mode 2755 (setgid binary)."
-echo "      The directories ${localstatedir}/run/PolicyKit and ${localstatedir}/lib/PolicyKit will be"
-echo "      owned by user '${POLKIT_USER}' and group '${POLKIT_GROUP}' and will be of mode 775."
+echo "      '${POLKIT_GROUP}', and installed with mode 2755 (setgid binary)."
 echo
 
 echo "NOTE: ${libexecdir}/polkit-grant-helper-pam will be setuid root."
index 9abea67..70a4744 100644 (file)
@@ -50,8 +50,8 @@ content_files =                           \
        version.xml                         \
        man/PolicyKit.xml                   \
        man/PolicyKit.conf.xml              \
-       man/polkit-grant.xml                \
-       man/polkit-list-actions.xml         \
+       man/polkit-auth.xml                 \
+       man/polkit-action.xml               \
        man/polkit-policy-file-validate.xml \
        man/polkit-config-file-validate.xml \
        spec/polkit-spec-configuration.xml  \
index 4d6479a..51db9b6 100644 (file)
@@ -1,14 +1,13 @@
 
 if MAN_PAGES_ENABLED
 
-man_MANS = polkit-grant.1               \
-          polkit-list-actions.1         \
+man_MANS = polkit-auth.1                \
+          polkit-action.1               \
           polkit-config-file-validate.1 \
           polkit-policy-file-validate.1 \
           PolicyKit.conf.5              \
           PolicyKit.8
 
-# TODO: 
 %.1 %.5 %.8 : %.xml
        $(XSLTPROC) -nonet http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
 
@@ -17,8 +16,8 @@ endif # MAN_PAGES_ENABLED
 EXTRA_DIST= PolicyKit.conf.xml              \
            PolicyKit.xml                   \
            polkit-config-file-validate.xml \
-           polkit-grant.xml                \
-           polkit-list-actions.xml         \
+           polkit-auth.xml                 \
+           polkit-action.xml               \
            polkit-policy-file-validate.xml
 
 clean-local:
index 434a554..52ddbdd 100644 (file)
       the top-level <emphasis>config</emphasis> are omitted in the
       following configuration file examples. The actions used may
       also be fictional,
-      use <citerefentry><refentrytitle>polkit-list-actions</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      use <citerefentry><refentrytitle>polkit-action</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       to learn about the actions available on your system.
     </para>
     
         <refentrytitle>polkit-config-file-validate</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>, 
       <citerefentry>
-        <refentrytitle>polkit-list-actions</refentrytitle><manvolnum>1</manvolnum>
+        <refentrytitle>polkit-action</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>, 
       <citerefentry>
-        <refentrytitle>polkit-grant</refentrytitle><manvolnum>1</manvolnum>
+        <refentrytitle>polkit-auth</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>
     </para>
   </refsect1>
index 703410f..23b11d6 100644 (file)
         <refentrytitle>PolicyKit.conf</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>, 
       <citerefentry>
-        <refentrytitle>polkit-list-actions</refentrytitle><manvolnum>1</manvolnum>
+        <refentrytitle>polkit-action</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>, 
       <citerefentry>
-        <refentrytitle>polkit-grant</refentrytitle><manvolnum>1</manvolnum>
+        <refentrytitle>polkit-auth</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>
     </para>
   </refsect1>
similarity index 72%
rename from doc/man/polkit-list-actions.xml
rename to doc/man/polkit-action.xml
index a1a0c97..430717c 100644 (file)
@@ -1,24 +1,24 @@
-<refentry id="polkit-list-actions.1">
+<refentry id="polkit-action.1">
   <refentryinfo>
-    <title>polkit-list-actions</title>
+    <title>polkit-action</title>
     <date>August 2007</date>
     <productname>PolicyKit</productname>
   </refentryinfo>
   
   <refmeta>
-    <refentrytitle>polkit-list-actions</refentrytitle>
+    <refentrytitle>polkit-action</refentrytitle>
     <manvolnum>1</manvolnum>
     <refmiscinfo class="version"></refmiscinfo>
   </refmeta>
   
   <refnamediv>
-    <refname>polkit-list-actions</refname>
+    <refname>polkit-action</refname>
     <refpurpose>List registered PolicyKit actions</refpurpose>
   </refnamediv>
   
   <refsynopsisdiv>
     <cmdsynopsis>
-      <command>polkit-list-actions</command>
+      <command>polkit-action</command>
       <arg><option>--action <replaceable>action</replaceable></option></arg>
       <arg><option>--version</option></arg>
       <arg><option>--help</option></arg>
@@ -28,8 +28,8 @@
   <refsect1>
     <title>DESCRIPTION</title> 
     <para>
-      polkit-list-actions is used to list the PolicyKit actions
-      that are registered on the system.
+      polkit-action is used to list the PolicyKit actions that are
+      registered on the system.
     </para>
   </refsect1>
   
       </varlistentry>
     </variablelist>
   </refsect1>
+
+  <refsect1>
+    <title>COMPLETION</title> 
+    <para>
+      PolicyKit ships with a collection of shell functions such that
+      completion on actions works when using the
+      <citerefentry>
+        <refentrytitle>bash</refentrytitle><manvolnum>1</manvolnum>
+      </citerefentry>
+      shell. For polkit-action, completion is enabled for
+      the <option>--action</option> argument.
+    </para>
+  </refsect1>
   
   <refsect1>
     <title>BUGS</title> 
@@ -85,7 +98,7 @@
         <refentrytitle>PolicyKit.conf</refentrytitle><manvolnum>5</manvolnum>
       </citerefentry>, 
       <citerefentry>
-        <refentrytitle>polkit-grant</refentrytitle><manvolnum>1</manvolnum>
+        <refentrytitle>polkit-auth</refentrytitle><manvolnum>1</manvolnum>
       </citerefentry>
     </para>
   </refsect1>
diff --git a/doc/man/polkit-auth.xml b/doc/man/polkit-auth.xml
new file mode 100644 (file)
index 0000000..793395a
--- /dev/null
@@ -0,0 +1,187 @@
+<refentry id="polkit-auth.1">
+  <refentryinfo>
+    <title>polkit-auth</title>
+    <date>August 2007</date>
+    <productname>PolicyKit</productname>
+  </refentryinfo>
+  
+  <refmeta>
+    <refentrytitle>polkit-auth</refentrytitle>
+    <manvolnum>1</manvolnum>
+    <refmiscinfo class="version"></refmiscinfo>
+  </refmeta>
+  
+  <refnamediv>
+    <refname>polkit-auth</refname>
+    <refpurpose>Manage authorizations</refpurpose>
+  </refnamediv>
+  
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>polkit-auth</command>
+      <arg><option>--obtain <replaceable>action</replaceable></option></arg>
+      <arg><option>--show-obtainable</option></arg>
+      <arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit</option></arg>
+      <arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit-detail</option></arg>
+      <arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --grant <replaceable>action</replaceable></option><arg><option>--constraint <replaceable>constraint</replaceable></option></arg></arg>
+      <arg><option><arg><option>--user <replaceable>user</replaceable></option></arg> --revoke <replaceable>action</replaceable></option></arg>
+      <arg><option>--version</option></arg>
+      <arg><option>--help</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+  
+  <refsect1>
+    <title>DESCRIPTION</title> 
+    <para>
+      polkit-auth is used to inspect, obtain, grant and revoke
+      PolicyKit authorizations. If invoked without any options, the
+      authorizations of the calling process will be printed.
+    </para>
+  </refsect1>
+  
+  <refsect1>
+    <title>OPTIONS</title> 
+    <variablelist>
+      <varlistentry>
+        <term><option>--obtain <replaceable>action</replaceable></option></term>
+        <listitem>
+          <para>
+            Attempt to obtain the authorization to do an action.  This
+            is only useful for implicit authorizations requiring
+            authentication; e.g. when an appropriate stanza in the
+            defaults section of the .policy file for the action
+            specifies
+            <literal>auth_*</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><option>--show-obtainable</option></term>
+        <listitem>
+          <para>
+             Prints all actions that can be obtained via
+             authentication and for which an authorization does not
+             exist.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit</option></term>
+        <listitem>
+          <para>
+            Show explicit authorizations. Duplicates are not
+            printed. If used with the <option>--user</option> option,
+            the authorization
+            <literal>org.freedesktop.policykit.read</literal> is required.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --explicit-detail</option></term>
+        <listitem>
+          <para>
+            Show detailed information about explicit
+            authorizations. In contrast to
+            the <literal>--explicit</literal>, duplicates are printed
+            as several authorizations with different scope and
+            constraints may exist.
+          </para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --grant <replaceable>action</replaceable></option><arg><option>--constraint <replaceable>constraint</replaceable></option></arg></term>
+        <listitem>
+          <para>
+            Grant an authorization for an action. This is different
+            than <literal>--obtain</literal> insofar that
+            the <literal>defaults</literal> stanza of the .policy file
+            is not consulted. Optionally, a constraint on the granted
+            authorization can be specified; allowed values
+            are: <literal>local</literal>,
+            <literal>active</literal>, <literal>local+active</literal>.
+            The authorization needed to grant authorizations is
+            <literal>org.freedesktop.policykit.grant</literal>.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option><arg><option>--user <replaceable>user</replaceable></option></arg> --revoke <replaceable>action</replaceable></option></term>
+        <listitem>
+          <para>
+            Revoke all authorizations for an action. If the user is
+            not specified the calling user is used. The
+            authorization <literal>org.freedesktop.policykit.revoke</literal>
+            is needed to revoke authorizations from other users.
+          </para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><option>--version</option></term>
+        <listitem>
+          <para>
+            Show version and exit.
+          </para>
+        </listitem>
+      </varlistentry>
+      
+      <varlistentry>
+        <term><option>--help</option></term>
+        <listitem>
+          <para>
+            Show this information.
+          </para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  
+  <refsect1>
+    <title>COMPLETION</title> 
+    <para>
+      PolicyKit ships with a collection of shell functions such that
+      completion on users and actions works when using the
+      <citerefentry>
+        <refentrytitle>bash</refentrytitle><manvolnum>1</manvolnum>
+      </citerefentry>
+      shell. For completion to properly work for polkit-auth,
+      arguments should be entered in the order specified in this
+      manual page; for example. <option>--user</option> should be
+      specified before <option>--revoke</option> to complete only on
+      the authorizations the given user has. Note that if the calling
+      user lacks the <literal>org.freedesktop.policykit.read</literal>
+      authorization, the completion function will fall back to
+      completing on all registered actions.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>BUGS</title> 
+    <para>
+      Please send bug reports to either the distribution or the
+      hal mailing list,
+      see <ulink url="http://lists.freedesktop.org/mailman/listinfo/hal"/>.
+      to subscribe.
+    </para>
+  </refsect1>
+  
+  <refsect1>
+    <title>SEE ALSO</title>
+    <para>
+      <citerefentry>
+        <refentrytitle>PolicyKit</refentrytitle><manvolnum>8</manvolnum>
+      </citerefentry>, 
+      <citerefentry>
+        <refentrytitle>PolicyKit.conf</refentrytitle><manvolnum>5</manvolnum>
+      </citerefentry>, 
+      <citerefentry>
+        <refentrytitle>polkit-action</refentrytitle><manvolnum>1</manvolnum>
+      </citerefentry>
+    </para>
+  </refsect1>
+</refentry>
diff --git a/doc/man/polkit-grant.xml b/doc/man/polkit-grant.xml
deleted file mode 100644 (file)
index e062791..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-<refentry id="polkit-grant.1">
-  <refentryinfo>
-    <title>polkit-grant</title>
-    <date>August 2007</date>
-    <productname>PolicyKit</productname>
-  </refentryinfo>
-  
-  <refmeta>
-    <refentrytitle>polkit-grant</refentrytitle>
-    <manvolnum>1</manvolnum>
-    <refmiscinfo class="version"></refmiscinfo>
-  </refmeta>
-  
-  <refnamediv>
-    <refname>polkit-grant</refname>
-    <refpurpose>manage PolicyKit privilege grants</refpurpose>
-  </refnamediv>
-  
-  <refsynopsisdiv>
-    <cmdsynopsis>
-      <command>polkit-grant</command>
-      <arg><option>--gain <replaceable>action</replaceable></option></arg>
-      <arg><option>--list</option></arg>
-      <arg><option>--delete <replaceable>user</replaceable></option></arg>
-      <arg><option>--version</option></arg>
-      <arg><option>--help</option></arg>
-    </cmdsynopsis>
-  </refsynopsisdiv>
-  
-  <refsect1>
-    <title>DESCRIPTION</title> 
-    <para>
-      polkit-grant is used to inspect and manage the privileges
-      that users obtain through authentication to enable a
-      mechanism to perform a specific action on their behalf.
-    </para>
-  </refsect1>
-  
-  <refsect1>
-    <title>OPTIONS</title> 
-    <variablelist>
-      <varlistentry>
-        <term><option>--gain <replaceable>action</replaceable></option></term>
-        <listitem>
-          <para>
-            Attempt to gain the privilege for the user to do an
-            action. This starts an interactive dialog where,
-            among, other things the user is authenticated.
-          </para>
-        </listitem>
-      </varlistentry>
-      
-      <varlistentry>
-        <term><option>--list</option></term>
-        <listitem>
-          <para>
-            Lists all the privileges previously granted.
-          </para>
-        </listitem>
-      </varlistentry>
-      
-      <varlistentry>
-        <term><option>--delete <replaceable>user</replaceable></option></term>
-        <listitem>
-          <para>
-            Delete all privileges granted to a given user. Needs
-            super user privileges.
-          </para>
-        </listitem>
-      </varlistentry>
-      
-      <varlistentry>
-        <term><option>--version</option></term>
-        <listitem>
-          <para>
-            Show version and exit.
-          </para>
-        </listitem>
-      </varlistentry>
-      
-      <varlistentry>
-        <term><option>--help</option></term>
-        <listitem>
-          <para>
-            Show usage information and exit.
-          </para>
-        </listitem>
-      </varlistentry>
-    </variablelist>
-  </refsect1>
-  
-  <refsect1>
-    <title>BUGS</title> 
-    <para>
-      Please send bug reports to either the distribution or the
-      hal mailing list,
-      see <ulink url="http://lists.freedesktop.org/mailman/listinfo/hal"/>.
-      to subscribe.
-    </para>
-  </refsect1>
-  
-  <refsect1>
-    <title>SEE ALSO</title>
-    <para>
-      <citerefentry>
-        <refentrytitle>PolicyKit</refentrytitle><manvolnum>8</manvolnum>
-      </citerefentry>, 
-      <citerefentry>
-        <refentrytitle>PolicyKit.conf</refentrytitle><manvolnum>5</manvolnum>
-      </citerefentry>, 
-      <citerefentry>
-        <refentrytitle>polkit-list-actions</refentrytitle><manvolnum>1</manvolnum>
-      </citerefentry>
-    </para>
-  </refsect1>
-</refentry>
index b6ae205..cb717ae 100644 (file)
@@ -90,6 +90,7 @@
     <xi:include href="xml/polkit-policy-default.xml"/>
     <xi:include href="xml/polkit-policy-cache.xml"/>
     <xi:include href="xml/polkit-authorization.xml"/>
+    <xi:include href="xml/polkit-authorization-constraint.xml"/>
     <xi:include href="xml/polkit-authorization-db.xml"/>
   </reference>
 
     </partintro>
     <xi:include href="man/PolicyKit.xml"/>
     <xi:include href="man/PolicyKit.conf.xml"/>
-    <xi:include href="man/polkit-grant.xml"/>
-    <xi:include href="man/polkit-list-actions.xml"/>
+    <xi:include href="man/polkit-auth.xml"/>
+    <xi:include href="man/polkit-action.xml"/>
     <xi:include href="man/polkit-policy-file-validate.xml"/>
     <xi:include href="man/polkit-config-file-validate.xml"/>
   </reference>
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644 (file)
index 0000000..b72d517
--- /dev/null
@@ -0,0 +1,4 @@
+# please keep this list sorted alphabetically
+#
+
+
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644 (file)
index 0000000..b93a173
--- /dev/null
@@ -0,0 +1,4 @@
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+[encoding: UTF-8]
+policy/org.freedesktop.policykit.policy.in
index 5a6ff76..59f29a2 100644 (file)
@@ -1,17 +1,16 @@
 
-polkit_privilegedir = $(datadir)/PolicyKit/policy
+polkit_policydir = $(datadir)/PolicyKit/policy
 
-dist_polkit_privilege_DATA =
+dist_polkit_policy_DATA = org.freedesktop.policykit.policy
+
+@INTLTOOL_POLICY_RULE@
 
 check:
-       for f in $(dist_polkit_privilege_DATA); do \
-          echo "Validating privilege file: $$f"; \
-          $(top_builddir)/tools/polkit-policy-file-validate --file $(srcdir)/$$f; \
-          if [ "$$?" != "0" ]; then \
-            echo "failed"; \
-            exit 1; \
-          fi; \
-        done
+       $(top_builddir)/tools/polkit-policy-file-validate $(dist_polkit_policy_DATA)
 
 clean-local :
        rm -f *~
+
+DISTCLEANFILES = org.freedesktop.policykit.policy
+
+EXTRA_DIST = org.freedesktop.policykit.policy.in
diff --git a/policy/org.freedesktop.policykit.policy.in b/policy/org.freedesktop.policykit.policy.in
new file mode 100644 (file)
index 0000000..efbeaeb
--- /dev/null
@@ -0,0 +1,49 @@
+<?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">
+
+<!-- 
+Policy definitions for core PolicyKit actions
+
+Copyright (c) 2007 David Zeuthen <david@fubar.dk>
+
+NOTE: If you make changes to this file, make sure to validate the file
+using the polkit-policy-file-validate(1) tool. Changes made to this
+file are instantly applied.
+-->
+
+<policyconfig>
+
+  <action id="org.freedesktop.policykit.read">
+    <_description>Read authorizations of other users</_description>
+    <_message>Authentication is required to read authorizations of other users</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.freedesktop.policykit.revoke">
+    <_description>Revoke authorizations from other users</_description>
+    <_message>Authentication is required to revoke authorizations other users</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+
+  <action id="org.freedesktop.policykit.grant">
+    <_description>Grant authorizations to other users</_description>
+    <_message>Authentication is required to grant authorizations to other users</_message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>auth_admin_keep_always</allow_active>
+    </defaults>
+  </action>
+
+</policyconfig>
diff --git a/policy/polkit-example-action.policy b/policy/polkit-example-action.policy
deleted file mode 100644 (file)
index 761ccf3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE policyconfig PUBLIC
- "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
-<policyconfig>
-
-  <group id="polkit-example">
-    <description>PolicyKit examples</description>
-    <description_short>PolicyKit</description_short>
-
-    <policy id="polkit-example-frobnicate">
-      <description>Frobnicate devices</description>
-      <missing>System policy prevents frobnicating the device '%s'.</missing>
-      <apply_to_all_mnemonic>Apply to all _frobnicatable devices</apply_to_all_mnemonic>
-      <defaults>
-        <allow_remote_inactive>no</allow_remote_inactive>
-        <allow_remote_active>no</allow_remote_active>
-        <allow_local_inactive>no</allow_local_inactive>
-        <allow_local_active>auth_self_keep_always</allow_local_active>
-      </defaults>
-    </policy>
-
-  </group>
-</policyconfig>
index 3b16b60..30d4c6c 100644 (file)
@@ -6,7 +6,7 @@ INCLUDES = \
        -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
        -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
        -DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-       -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+       -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
        -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
        -DPACKAGE_LIB_DIR=\""$(libdir)"\" \
        -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \
@@ -26,6 +26,39 @@ libpolkit_dbus_la_LIBADD = @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(SEL
 
 libpolkit_dbus_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
+libexec_PROGRAMS = polkit-explicit-grant-helper polkit-revoke-helper polkit-read-auth-helper
+
+polkit_explicit_grant_helper_SOURCES = polkit-explicit-grant-helper.c
+polkit_explicit_grant_helper_CFLAGS = @DBUS_CFLAGS@
+polkit_explicit_grant_helper_LDADD = $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
+
+polkit_revoke_helper_SOURCES = polkit-revoke-helper.c
+polkit_revoke_helper_CFLAGS = @DBUS_CFLAGS@
+polkit_revoke_helper_LDADD = $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
+
+polkit_read_auth_helper_SOURCES = polkit-read-auth-helper.c
+polkit_read_auth_helper_CFLAGS = @DBUS_CFLAGS@
+polkit_read_auth_helper_LDADD = $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
+
 clean-local :
        rm -f *~ $(BUILT_SOURCES)
 
+# polkit-explicit-grant-helper needs to be setgid $POLKIT_GROUP to be
+# able to edit authorization files in /var/lib/PolicyKit and
+# /var/run/PolicyKit
+#
+# polkit-revoke-helper needs to be setgid $POLKIT_GROUP to be able to
+# edit authorization files in /var/lib/PolicyKit and
+# /var/run/PolicyKit
+#
+# polkit-read-auth-helper needs to be setgid $POLKIT_GROUP to be able
+# to read authorization files in /var/lib/PolicyKit and
+# /var/run/PolicyKit
+#
+install-exec-hook:
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-explicit-grant-helper
+       -chmod 2755 $(DESTDIR)$(libexecdir)/polkit-explicit-grant-helper
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-revoke-helper
+       -chmod 2755 $(DESTDIR)$(libexecdir)/polkit-revoke-helper
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(libexecdir)/polkit-read-auth-helper
+       -chmod 2755 $(DESTDIR)$(libexecdir)/polkit-read-auth-helper
index d7c1f8c..4d304d4 100644 (file)
 #include "polkit-dbus.h"
 #include <polkit/polkit-debug.h>
 
+/* TODO FIXME: this is Linux specific */
+static polkit_uint64_t 
+_get_start_time_for_pid (pid_t pid)
+{
+        char *filename;
+        char *contents;
+        gsize length;
+        polkit_uint64_t start_time;
+        GError *error = NULL;
+        char **tokens;
+        char *p;
+        char *endp;
+
+        start_time = 0;
+        contents = NULL;
+
+        filename = g_strdup_printf ("/proc/%d/stat", pid);
+        if (filename == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        if (!g_file_get_contents (filename, &contents, &length, &error)) {
+                //fprintf (stderr, "Cannot get contents of '%s': %s\n", filename, error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        /* start time is the 19th token after the '(process name)' entry */
+
+        p = strchr (contents, ')');
+        if (p == NULL) {
+                goto out;
+        }
+        p += 2; /* skip ') ' */
+        if (p - contents >= (int) length) {
+                goto out;
+        }
+
+        tokens = g_strsplit (p, " ", 0);
+        if (g_strv_length (tokens) < 20) {
+                goto out;
+        }
+
+        start_time = strtoll (tokens[19], &endp, 10);
+        if (endp == tokens[19]) {
+                goto out;
+        }
+
+        g_strfreev (tokens);
+
+out:
+        g_free (filename);
+        g_free (contents);
+        return start_time;
+}
+
 
 /**
  * polkit_session_new_from_objpath:
@@ -330,8 +387,7 @@ polkit_session_new_from_cookie (DBusConnection *con, const char *cookie, DBusErr
        dbus_message_append_args (message, DBUS_TYPE_STRING, &cookie, DBUS_TYPE_INVALID);
        reply = dbus_connection_send_with_reply_and_block (con, message, -1, error);
        if (reply == NULL || dbus_error_is_set (error)) {
-               g_warning ("Error doing Manager.GetSessionForCookie on ConsoleKit: %s: %s", 
-                           error->name, error->message);
+               //g_warning ("Error doing Manager.GetSessionForCookie on ConsoleKit: %s: %s", error->name, error->message);
                dbus_message_unref (message);
                if (reply != NULL)
                        dbus_message_unref (reply);
@@ -461,7 +517,7 @@ polkit_caller_new_from_dbus_name (DBusConnection *con, const char *dbus_name, DB
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &pid);
        reply = dbus_connection_send_with_reply_and_block (con, message, -1, error);
        if (reply == NULL || dbus_error_is_set (error)) {
-               g_warning ("Error doing GetSessionForUnixProcess on ConsoleKit: %s: %s", error->name, error->message);
+               //g_warning ("Error doing GetSessionForUnixProcess on ConsoleKit: %s: %s", error->name, error->message);
                dbus_message_unref (message);
                if (reply != NULL)
                        dbus_message_unref (reply);
@@ -636,7 +692,7 @@ polkit_caller_new_from_pid (DBusConnection *con, pid_t pid, DBusError *error)
        dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &pid);
        reply = dbus_connection_send_with_reply_and_block (con, message, -1, error);
        if (reply == NULL || dbus_error_is_set (error)) {
-               g_warning ("Error doing GetSessionForUnixProcess on ConsoleKit: %s: %s", error->name, error->message);
+               //g_warning ("Error doing GetSessionForUnixProcess on ConsoleKit: %s: %s", error->name, error->message);
                dbus_message_unref (message);
                if (reply != NULL)
                        dbus_message_unref (reply);
@@ -729,6 +785,155 @@ out:
         return caller;
 }
 
+static GSList *
+_get_list_of_sessions (DBusConnection *con, uid_t uid, DBusError *error)
+{
+        GSList *ret;
+        DBusMessage *message;
+        DBusMessage *reply;
+        DBusMessageIter iter;
+        DBusMessageIter iter_array;
+        const char *value;
+
+        ret = NULL;
+
+        message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
+                                                "/org/freedesktop/ConsoleKit/Manager",
+                                                "org.freedesktop.ConsoleKit.Manager",
+                                                "GetSessionsForUnixUser");
+       dbus_message_append_args (message, DBUS_TYPE_UINT32, &uid, DBUS_TYPE_INVALID);
+        reply = dbus_connection_send_with_reply_and_block (con, message, -1, error);
+        if (reply == NULL || dbus_error_is_set (error)) {
+                goto out;
+        }
+
+       dbus_message_iter_init (reply, &iter);
+       if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
+                g_warning ("Wrong reply from ConsoleKit (not an array)");
+                goto out;
+       }
+
+       dbus_message_iter_recurse (&iter, &iter_array);
+        while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID) {
+
+                if (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_OBJECT_PATH) {
+                        g_warning ("Wrong reply from ConsoleKit (element is not a string)");
+                        g_slist_foreach (ret, (GFunc) g_free, NULL);
+                        g_slist_free (ret);
+                        goto out;
+                }
+
+               dbus_message_iter_get_basic (&iter_array, &value);
+                ret = g_slist_append (ret, g_strdup (value));
+
+               dbus_message_iter_next (&iter_array);
+        }
+        
+out:
+        if (message != NULL)
+                dbus_message_unref (message);
+        if (reply != NULL)
+                dbus_message_unref (reply);
+        return ret;
+}
+
+static polkit_bool_t
+_polkit_is_authorization_relevant_internal (DBusConnection *con, 
+                                            PolKitAuthorization *auth, 
+                                            GSList *sessions,
+                                            DBusError *error)
+{
+        pid_t pid;
+        polkit_uint64_t pid_start_time;
+        polkit_bool_t ret;
+        polkit_bool_t del_sessions;
+        GSList *i;
+        uid_t uid;
+
+        g_return_val_if_fail (con != NULL, FALSE);
+        g_return_val_if_fail (auth != NULL, FALSE);
+        g_return_val_if_fail (error != NULL, FALSE);
+        g_return_val_if_fail (! dbus_error_is_set (error), FALSE);
+
+        ret = FALSE;
+
+        uid = polkit_authorization_get_uid (auth);
+
+        switch (polkit_authorization_get_scope (auth)) {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
+                if (!polkit_authorization_scope_process_get_pid (auth,
+                                                                 &pid,
+                                                                 &pid_start_time)) {
+                        /* this should never fail */
+                        g_warning ("Cannot determine (pid,start_time) for authorization");
+                        goto out;
+                }
+                if (_get_start_time_for_pid (pid) == pid_start_time) {
+                        ret = TRUE;
+                        goto out;
+                }
+                break;
+
+        case POLKIT_AUTHORIZATION_SCOPE_SESSION:
+                del_sessions = FALSE;
+                if (sessions == NULL) {
+                        sessions = _get_list_of_sessions (con, uid, error);
+                        del_sessions = TRUE;
+                }
+
+                for (i = sessions; i != NULL; i = i->next) {
+                        char *session_id = i->data;
+                        if (strcmp (session_id, polkit_authorization_scope_session_get_ck_objref (auth)) == 0) {
+                                ret = TRUE;
+                                break;
+                        }
+                }
+
+                if (del_sessions) {
+                        g_slist_foreach (sessions, (GFunc) g_free, NULL);
+                        g_slist_free (sessions);
+                }
+                break;
+
+        case POLKIT_AUTHORIZATION_SCOPE_ALWAYS:
+                ret = TRUE;
+                break;
+        }
+
+out:
+        return ret;
+}
+
+/**
+ * polkit_is_authorization_relevant:
+ * @con: D-Bus system bus connection
+ * @auth: authorization to check for
+ * @error: return location for error
+ *
+ * As explicit authorizations are scoped (process, session or
+ * everything), they become irrelevant once the entity (process or
+ * session) ceases to exist. This function determines whether the
+ * authorization is still relevant; it's useful for reporting
+ * and graphical tools displaying authorizations.
+ *
+ * Note that this may do blocking IO to check for session
+ * authorizations so it is best avoided if your process already
+ * tracks/caches all the information. You can use the
+ * polkit_tracker_is_authorization_relevant() method on the
+ * #PolKitTracker class for this.
+ *
+ * Returns: #TRUE if the authorization still applies, #FALSE if an
+ * error occurred (then error will be set) or if the entity the
+ * authorization refers to has gone out of scope.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_is_authorization_relevant (DBusConnection *con, PolKitAuthorization *auth, DBusError *error)
+{
+        return _polkit_is_authorization_relevant_internal (con, auth, NULL, error);
+}
+
 /**
  * PolKitTracker:
  *
@@ -1077,7 +1282,7 @@ polkit_tracker_dbus_func (PolKitTracker *pk_tracker, DBusMessage *message)
                                             DBUS_TYPE_INVALID)) {
 
                         /* TODO: should be _pk_critical */
-                        _pk_debug ("The ActiveChanged signal on the org.freedesktop.ConsoleKit.Session "
+                        g_warning ("The ActiveChanged signal on the org.freedesktop.ConsoleKit.Session "
                                    "interface for object %s has the wrong signature! "
                                    "Your system is misconfigured.", session_objpath);
 
@@ -1092,6 +1297,59 @@ polkit_tracker_dbus_func (PolKitTracker *pk_tracker, DBusMessage *message)
                 /* now go through all Caller objects and update the is_active field as appropriate */
                 _update_session_is_active (pk_tracker, session_objpath, is_active);
 
+        } else if (dbus_message_is_signal (message, "org.freedesktop.ConsoleKit.Seat", "SessionAdded")) {
+                DBusError error;
+                const char *seat_objpath;
+                const char *session_objpath;
+
+                /* If a session is added, update our list of sessions.. also notify the user.. */
+
+                ret = TRUE;
+
+                dbus_error_init (&error);
+                seat_objpath = dbus_message_get_path (message);
+                if (!dbus_message_get_args (message, &error, 
+                                            DBUS_TYPE_STRING, &session_objpath, 
+                                            DBUS_TYPE_INVALID)) {
+
+                        /* TODO: should be _pk_critical */
+                        g_warning ("The SessionAdded signal on the org.freedesktop.ConsoleKit.Seat "
+                                   "interface for object %s has the wrong signature! "
+                                   "Your system is misconfigured.", seat_objpath);
+
+                        goto out;
+                }
+
+                /* TODO: add to sessions - see polkit_tracker_is_authorization_relevant() */
+
+        } else if (dbus_message_is_signal (message, "org.freedesktop.ConsoleKit.Seat", "SessionRemoved")) {
+                DBusError error;
+                const char *seat_objpath;
+                const char *session_objpath;
+
+                /* If a session is removed, authorizations scoped for that session 
+                 * may become inactive.. so do notify the user about it.. 
+                 */
+
+                ret = TRUE;
+
+                dbus_error_init (&error);
+                seat_objpath = dbus_message_get_path (message);
+                if (!dbus_message_get_args (message, &error, 
+                                            DBUS_TYPE_STRING, &session_objpath, 
+                                            DBUS_TYPE_INVALID)) {
+
+                        /* TODO: should be _pk_critical */
+                        g_warning ("The SessionRemoved signal on the org.freedesktop.ConsoleKit.Seat "
+                                   "interface for object %s has the wrong signature! "
+                                   "Your system is misconfigured.", seat_objpath);
+
+                        goto out;
+                }
+
+                _remove_caller_by_session (pk_tracker, session_objpath);
+
+                /* TODO: remove from sessions - see polkit_tracker_is_authorization_relevant() */
         }
 
         /* TODO: when ConsoleKit gains the ability to attach/detach a session to a seat (think
@@ -1144,62 +1402,6 @@ polkit_tracker_get_caller_from_dbus_name (PolKitTracker *pk_tracker, const char
         return polkit_caller_ref (caller);
 }
 
-/* TODO FIXME: this is Linux specific */
-static polkit_uint64_t 
-_get_start_time_for_pid (pid_t pid)
-{
-        char *filename;
-        char *contents;
-        gsize length;
-        polkit_uint64_t start_time;
-        GError *error = NULL;
-        char **tokens;
-        char *p;
-        char *endp;
-
-        start_time = 0;
-        contents = NULL;
-
-        filename = g_strdup_printf ("/proc/%d/stat", pid);
-        if (filename == NULL) {
-                fprintf (stderr, "Out of memory\n");
-                goto out;
-        }
-
-        if (!g_file_get_contents (filename, &contents, &length, &error)) {
-                fprintf (stderr, "Cannot get contents of '%s': %s\n", filename, error->message);
-                g_error_free (error);
-                goto out;
-        }
-
-        /* start time is the 19th token after the '(process name)' entry */
-
-        p = strchr (contents, ')');
-        if (p == NULL) {
-                goto out;
-        }
-        p += 2; /* skip ') ' */
-        if (p - contents >= (int) length) {
-                goto out;
-        }
-
-        tokens = g_strsplit (p, " ", 0);
-        if (g_strv_length (tokens) < 20) {
-                goto out;
-        }
-
-        start_time = strtoll (tokens[19], &endp, 10);
-        if (endp == tokens[19]) {
-                goto out;
-        }
-
-        g_strfreev (tokens);
-
-out:
-        g_free (filename);
-        g_free (contents);
-        return start_time;
-}
 
 /**
  * polkit_tracker_get_caller_from_pid:
@@ -1273,3 +1475,43 @@ polkit_tracker_get_caller_from_pid (PolKitTracker *pk_tracker, pid_t pid, DBusEr
         g_hash_table_insert (pk_tracker->pid_start_time_to_caller, pst, caller);
         return polkit_caller_ref (caller);
 }
+
+
+/**
+ * polkit_tracker_is_authorization_relevant:
+ * @pk_tracker: the tracker
+ * @auth: authorization to check for
+ * @error: return location for error
+ *
+ * As explicit authorizations are scoped (process, session or
+ * everything), they become irrelevant once the entity (process or
+ * session) ceases to exist. This function determines whether the
+ * authorization is still relevant; it's useful for reporting
+ * and graphical tools displaying authorizations.
+ *
+ * This function is similar to polkit_is_authorization_relevant() only
+ * that it avoids IPC overhead on the 2nd and subsequent calls when
+ * checking authorizations scoped for a session.
+ *
+ * Returns: #TRUE if the authorization still applies, #FALSE if an
+ * error occurred (then error will be set) or if the entity the
+ * authorization refers to has gone out of scope.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t  
+polkit_tracker_is_authorization_relevant (PolKitTracker *pk_tracker, PolKitAuthorization *auth, DBusError *error)
+{
+
+        g_return_val_if_fail (pk_tracker != NULL, FALSE);
+        g_return_val_if_fail (pk_tracker->con != NULL, FALSE);
+        g_return_val_if_fail (! dbus_error_is_set (error), FALSE);
+
+        /* TODO: optimize... in order to do this sanely we need CK's Manager object to export 
+         * a method GetAllSessions() - otherwise we'd need to key off every uid. 
+         *
+         * It's no biggie we don't have this optimization yet.. it's only used by polkit-auth(1)
+         * and the GNOME utility for managing authorizations.
+         */
+        return _polkit_is_authorization_relevant_internal (pk_tracker->con, auth, NULL, error);
+}
index 95166a5..98f2353 100644 (file)
@@ -39,6 +39,7 @@ PolKitCaller  *polkit_caller_new_from_dbus_name  (DBusConnection *con, const cha
 
 PolKitCaller  *polkit_caller_new_from_pid  (DBusConnection *con, pid_t pid, DBusError *error);
 
+polkit_bool_t  polkit_is_authorization_relevant (DBusConnection *con, PolKitAuthorization *auth, DBusError *error);
 
 
 struct _PolKitTracker;
@@ -56,6 +57,8 @@ PolKitCaller  *polkit_tracker_get_caller_from_dbus_name  (PolKitTracker *pk_trac
 
 PolKitCaller  *polkit_tracker_get_caller_from_pid        (PolKitTracker *pk_tracker, pid_t pid, DBusError *error);
 
+polkit_bool_t  polkit_tracker_is_authorization_relevant  (PolKitTracker *pk_tracker, PolKitAuthorization *auth, DBusError *error);
+
 POLKIT_END_DECLS
 
 #endif /* POLKIT_DBUS_H */
diff --git a/polkit-dbus/polkit-explicit-grant-helper.c b/polkit-dbus/polkit-explicit-grant-helper.c
new file mode 100644 (file)
index 0000000..401f1c5
--- /dev/null
@@ -0,0 +1,254 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-explicit-grant-helper.c : setgid polkituser explicit grant
+ * helper for PolicyKit
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
+ *
+ **************************************************************************/
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <security/pam_appl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <utime.h>
+#include <fcntl.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+
+static polkit_bool_t
+check_pid_for_authorization (pid_t caller_pid, const char *action_id)
+{
+        polkit_bool_t ret;
+        DBusError error;
+        DBusConnection *bus;
+        PolKitCaller *caller;
+        PolKitAction *action;
+        PolKitContext *context;
+
+        ret = FALSE;
+
+        dbus_error_init (&error);
+        bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot connect to system bus: %s: %s\n", 
+                         error.name, error.message);
+                dbus_error_free (&error);
+                goto out;
+        }
+
+        caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
+        if (caller == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot get caller from pid: %s: %s\n",
+                         error.name, error.message);
+                goto out;
+        }
+
+        action = polkit_action_new ();
+        if (action == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitAction\n");
+                goto out;
+        }
+        if (!polkit_action_set_action_id (action, action_id)) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot set action_id\n");
+                goto out;
+        }
+
+        context = polkit_context_new ();
+        if (context == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitContext\n");
+                goto out;
+        }
+        if (!polkit_context_init (context, NULL)) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot initialize polkit\n");
+                goto out;
+        }
+
+        if (polkit_context_is_caller_authorized (context, action, caller, FALSE) != POLKIT_RESULT_YES) {
+                //fprintf (stderr, 
+                //         "polkit-read-auth-helper: uid %d (pid %d) does not have the "
+                //         "org.freedesktop.policykit.read-other-authorizations authorization\n", 
+                //         caller_uid, caller_pid);
+                goto out;
+        }
+
+        ret = TRUE;
+out:
+
+        return ret;
+}
+
+/* this function is in polkit/polkit-authorization-db.c */
+extern polkit_bool_t _polkit_authorization_db_auth_file_add (const char *root, polkit_bool_t transient, uid_t uid, char *str_to_add);
+
+int
+main (int argc, char *argv[])
+{
+        int ret;
+        gid_t egid;
+        struct group *group;
+        uid_t invoking_uid;
+        char *action_id;
+        char *endp;
+        char grant_line[512];
+        struct timeval now;
+
+        ret = 1;
+
+        /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
+        if (clearenv () != 0)
+                goto out;
+        /* set a minimal environment */
+        setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
+
+        openlog ("polkit-explicit-grant-helper", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+
+        /* check for correct invocation */
+        if (argc != 5) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-explicit-grant-helper: wrong number of arguments. This incident has been logged.\n");
+                goto out;
+        }
+
+        /* check we're running with a non-tty stdin */
+        if (isatty (STDIN_FILENO) != 0) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-explicit-grant-helper: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
+                goto out;
+        }
+
+        invoking_uid = getuid ();
+
+        /* check that we are setgid polkituser */
+        egid = getegid ();
+        group = getgrgid (egid);
+        if (group == NULL) {
+                fprintf (stderr, "polkit-explicit-grant-helper: cannot lookup group info for gid %d\n", egid);
+                goto out;
+        }
+        if (strcmp (group->gr_name, POLKIT_GROUP) != 0) {
+                fprintf (stderr, "polkit-explicit-grant-helper: needs to be setgid " POLKIT_GROUP "\n");
+                goto out;
+        }
+
+        /*----------------------------------------------------------------------------------------------------*/
+
+        /* check and validate incoming parameters */
+
+        /* first one is action_id */
+        action_id = argv[1];
+        if (!polkit_action_validate_id (action_id)) {
+                syslog (LOG_NOTICE, "action_id is malformed [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-explicit-grant-helper: action_id is malformed. This incident has been logged.\n");
+                goto out;
+        }
+
+        char *authc_str;
+        PolKitAuthorizationConstraint *authc;
+
+        /* second is the auth constraint */
+        authc_str = argv[2];
+        authc = polkit_authorization_constraint_from_string (authc_str);
+        if (authc == NULL) {
+                syslog (LOG_NOTICE, "auth constraint is malformed [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-explicit-grant-helper: auth constraint is malformed. This incident has been logged.\n");
+                goto out;
+        }
+
+#define TARGET_UID 0
+        int target;
+        uid_t target_uid = -1;
+
+        /* (third, fourth) is one of: ("uid", uid) */
+        if (strcmp (argv[3], "uid") == 0) {
+
+                target = TARGET_UID;
+                target_uid = strtol (argv[4], &endp, 10);
+                if  (*endp != '\0') {
+                        syslog (LOG_NOTICE, "target uid is malformed [uid=%d]", getuid ());
+                        fprintf (stderr, "polkit-explicit-grant-helper: target uid is malformed. This incident has been logged.\n");
+                        goto out;
+                }
+        } else {
+                syslog (LOG_NOTICE, "target type is malformed [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-explicit-grant-helper: target type is malformed. This incident has been logged.\n");
+                goto out;
+        }
+
+
+        //fprintf (stderr, "action_id=%s constraint=%s uid=%d\n", action_id, authc_str, target_uid);
+
+        /* OK, we're done parsing ... check if the user is authorized */
+
+        if (invoking_uid != 0) {
+                /* see if calling user is authorized for
+                 *
+                 *  org.freedesktop.policykit.grant
+                 */
+                if (!check_pid_for_authorization (getppid (), "org.freedesktop.policykit.grant")) {
+                        goto out;
+                }
+        }
+
+        /* he is.. proceed to add the grant */
+
+        umask (002);
+
+        if (gettimeofday (&now, NULL) != 0) {
+                fprintf (stderr, "polkit-explicit-grant-helper: error calling gettimeofday: %m");
+                return FALSE;
+        }
+
+        if (snprintf (grant_line, 
+                      sizeof (grant_line), 
+                      "grant:%s:%Lu:%d:%s\n",
+                      action_id,
+                      (polkit_uint64_t) now.tv_sec,
+                      invoking_uid,
+                      authc_str) >= (int) sizeof (grant_line)) {
+                fprintf (stderr, "polkit-explicit-grant-helper: str to add is too long!\n");
+                goto out;
+        }
+
+        if (_polkit_authorization_db_auth_file_add (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", 
+                                                    FALSE, 
+                                                    target_uid, 
+                                                    grant_line)) {
+                ret = 0;
+        }
+
+out:
+
+        return ret;
+}
+
diff --git a/polkit-dbus/polkit-read-auth-helper.c b/polkit-dbus/polkit-read-auth-helper.c
new file mode 100644 (file)
index 0000000..0694c3d
--- /dev/null
@@ -0,0 +1,381 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-read-auth-helper.c : setgid polkituser helper for PolicyKit
+ * to read authorizations
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
+ *
+ **************************************************************************/
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <security/pam_appl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <utime.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+
+/* This is a bit incestuous; we are, effectively, calling into
+ * ourselves.. it's safe though; this function will never get hit..
+ */
+static polkit_bool_t
+check_for_auth (uid_t caller_uid, pid_t caller_pid)
+{
+        polkit_bool_t ret;
+        DBusError error;
+        DBusConnection *bus;
+        PolKitCaller *caller;
+        PolKitAction *action;
+        PolKitContext *context;
+
+        ret = FALSE;
+
+        dbus_error_init (&error);
+        bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot connect to system bus: %s: %s\n", 
+                         error.name, error.message);
+                dbus_error_free (&error);
+                goto out;
+        }
+
+        caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
+        if (caller == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot get caller from pid: %s: %s\n",
+                         error.name, error.message);
+                goto out;
+        }
+
+        action = polkit_action_new ();
+        if (action == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitAction\n");
+                goto out;
+        }
+        if (!polkit_action_set_action_id (action, "org.freedesktop.policykit.read")) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot set action_id\n");
+                goto out;
+        }
+
+        context = polkit_context_new ();
+        if (context == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitContext\n");
+                goto out;
+        }
+        if (!polkit_context_init (context, NULL)) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot initialize polkit\n");
+                goto out;
+        }
+
+        if (polkit_context_is_caller_authorized (context, action, caller, FALSE) != POLKIT_RESULT_YES) {
+                /* having 'grant' (which is a lot more powerful) is also sufficient.. this is because 'read'
+                 * is required to 'grant' (to check if there's a similar authorization already)
+                 */
+                if (!polkit_action_set_action_id (action, "org.freedesktop.policykit.grant")) {
+                        fprintf (stderr, "polkit-read-auth-helper: cannot set action_id\n");
+                        goto out;
+                }
+                if (polkit_context_is_caller_authorized (context, action, caller, FALSE) != POLKIT_RESULT_YES) {
+                        goto out;
+                }
+        }
+
+        ret = TRUE;
+out:
+
+        return ret;
+}
+
+static polkit_bool_t
+dump_auths_from_file (const char *path)
+{
+        int ret;
+        int fd;
+        char buf[256];
+        struct stat statbuf;
+        ssize_t num_bytes_read;
+        ssize_t num_bytes_to_read;
+        ssize_t num_bytes_remaining_to_read;
+        ssize_t num_bytes_to_write;
+        ssize_t num_bytes_written;
+        ssize_t num_bytes_remaining_to_write;
+
+        ret = FALSE;
+
+        if (stat (path, &statbuf) != 0) {
+                /* this is fine; the file does not have to exist.. */
+                if (errno == ENOENT) {
+                        ret = TRUE;
+                        goto out;
+                }
+                fprintf (stderr, "polkit-read-auth-helper: cannot stat %s: %m\n", path);
+                goto out;
+        }
+
+        fd = open (path, O_RDONLY);
+        if (fd < 0) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot open %s: %m\n", path);
+                goto out;
+        }
+
+        num_bytes_remaining_to_read = statbuf.st_size;
+
+        while (num_bytes_remaining_to_read > 0) {
+                if (num_bytes_remaining_to_read > (ssize_t) sizeof (buf))
+                        num_bytes_to_read = (ssize_t) sizeof (buf);
+                else
+                        num_bytes_to_read = num_bytes_remaining_to_read;
+                
+        again:
+                num_bytes_read = read (fd, buf, num_bytes_to_read);
+                if (num_bytes_read == -1) {
+                        if (errno == EAGAIN || errno == EINTR) {
+                                goto again;
+                        } else {
+                                fprintf (stderr, "polkit-read-auth-helper: error reading file %s: %m\n", path);
+                                close (fd);
+                                goto out;
+                        }
+                }
+
+                /* write to stdout */
+                num_bytes_to_write = num_bytes_read;
+                num_bytes_remaining_to_write = num_bytes_read;
+
+                while (num_bytes_remaining_to_write > 0) {
+                again_write:
+                        num_bytes_written = write (STDOUT_FILENO, 
+                                                   buf + (num_bytes_to_write - num_bytes_remaining_to_write), 
+                                                   num_bytes_remaining_to_write);
+                        if (num_bytes_written == -1) {
+                                if (errno == EAGAIN || errno == EINTR) {
+                                        goto again_write;
+                                } else {
+                                        fprintf (stderr, "polkit-read-auth-helper: error writing to stdout: %m\n");
+                                        close (fd);
+                                        goto out;
+                                }
+                        }
+                        
+                        num_bytes_remaining_to_write -= num_bytes_written;
+                }
+
+                
+                
+
+
+                num_bytes_remaining_to_read -= num_bytes_read;
+        }
+
+
+        close (fd);
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+
+static polkit_bool_t
+dump_auths_all (const char *root)
+{
+        DIR *dir;
+        int dfd;
+        struct dirent64 *d;
+        polkit_bool_t ret;
+
+        ret = FALSE;
+
+        dir = opendir (root);
+        if (dir == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: error calling opendir on %s: %m\n", root);
+                goto out;
+        }
+
+        dfd = dirfd (dir);
+        if (dfd == -1) {
+                fprintf (stderr, "polkit-read-auth-helper: error calling dirfd(): %m\n");
+                goto out;
+        }
+
+        while ((d = readdir64(dir)) != NULL) {
+                size_t name_len;
+                char path[PATH_MAX];
+                static const char suffix[] = ".auths";
+
+                if (d->d_type != DT_REG)
+                        continue;
+
+                if (d->d_name == NULL)
+                        continue;
+
+                name_len = strlen (d->d_name);
+                if (name_len < sizeof (suffix))
+                        continue;
+
+                if (strcmp ((d->d_name + name_len - sizeof (suffix) + 1), suffix) != 0)
+                        continue;
+
+                if (snprintf (path, sizeof (path), "%s/%s", root, d->d_name) >= (int) sizeof (path)) {
+                        fprintf (stderr, "polkit-read-auth-helper: string was truncated (1)\n");
+                        goto out;
+                }
+
+                if (!dump_auths_from_file (path))
+                        goto out;
+        }
+
+        ret = TRUE;
+
+out:
+        if (dir != NULL)
+                closedir(dir);
+        return ret;
+}
+
+static polkit_bool_t
+dump_auths_for_uid (const char *root, uid_t uid)
+{
+        char path[256];
+        struct passwd *pw;
+
+        pw = getpwuid (uid);
+        if (pw == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot lookup user name for uid %d\n", uid);
+                return FALSE;
+        }
+
+        if (snprintf (path, sizeof (path), "%s/user-%s.auths", root, pw->pw_name) >= (int) sizeof (path)) {
+                fprintf (stderr, "polkit-read-auth-helper: string was truncated (1)\n");
+                return FALSE;
+        }
+
+        return dump_auths_from_file (path);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+        int ret;
+        gid_t egid;
+        struct group *group;
+        uid_t caller_uid;
+        uid_t requesting_info_for_uid;
+        char *endp;
+
+        ret = 1;
+        /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
+        //if (clearenv () != 0)
+        //        goto out;
+        /* set a minimal environment */
+        //setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
+
+        openlog ("polkit-read-auth-helper", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+
+        /* check for correct invocation */
+        if (argc != 2) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-read-auth-helper: wrong number of arguments. This incident has been logged.\n");
+                goto out;
+        }
+
+        caller_uid = getuid ();
+
+        /* check we're running with a non-tty stdin */
+        if (isatty (STDIN_FILENO) != 0) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-read-auth-helper: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
+                goto out;
+        }
+        
+        /* check that we are setgid polkituser */
+        egid = getegid ();
+        group = getgrgid (egid);
+        if (group == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot lookup group info for gid %d\n", egid);
+                goto out;
+        }
+        if (strcmp (group->gr_name, POLKIT_GROUP) != 0) {
+                fprintf (stderr, "polkit-read-auth-helper: needs to be setgid " POLKIT_GROUP "\n");
+                goto out;
+        }
+
+        /*----------------------------------------------------------------------------------------------------*/
+
+        requesting_info_for_uid = strtoul (argv[1], &endp, 10);
+        if  (*endp != '\0') {
+                fprintf (stderr, "polkit-read-auth-helper: requesting_info_for_uid malformed (3)\n");
+                goto out;
+        }
+
+        /* uid 0 is allowed to read anything */
+        if (caller_uid != 0) {
+                if (caller_uid != requesting_info_for_uid) {
+
+                        /* see if calling user has the
+                         *
+                         *  org.freedesktop.policykit.read
+                         *
+                         * authorization
+                         */
+                        if (!check_for_auth (caller_uid, getppid ())) {
+                                //fprintf (stderr, 
+                                //         "polkit-read-auth-helper: uid %d cannot read authorizations for uid %d.\n", 
+                                //        caller_uid,
+                                //        requesting_info_for_uid);
+                                goto out;
+                        }
+                }
+        }
+
+        if (requesting_info_for_uid == (uid_t) -1) {
+                if (!dump_auths_all (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit"))
+                        goto out;
+                
+                if (!dump_auths_all (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit"))
+                        goto out;                
+        } else {
+                if (!dump_auths_for_uid (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", requesting_info_for_uid))
+                        goto out;
+                
+                if (!dump_auths_for_uid (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", requesting_info_for_uid))
+                        goto out;
+        }
+
+        ret = 0;
+
+out:
+        return ret;
+}
+
diff --git a/polkit-dbus/polkit-revoke-helper.c b/polkit-dbus/polkit-revoke-helper.c
new file mode 100644 (file)
index 0000000..8e28d65
--- /dev/null
@@ -0,0 +1,347 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-revoke-helper.c : setgid polkituser revoke helper for PolicyKit
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
+ *
+ **************************************************************************/
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <security/pam_appl.h>
+#include <grp.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <utime.h>
+#include <fcntl.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+
+static polkit_bool_t
+check_for_revoke_authorization (pid_t caller_pid)
+{
+        polkit_bool_t ret;
+        DBusError error;
+        DBusConnection *bus;
+        PolKitCaller *caller;
+        PolKitAction *action;
+        PolKitContext *context;
+
+        ret = FALSE;
+
+        dbus_error_init (&error);
+        bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
+        if (bus == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot connect to system bus: %s: %s\n", 
+                         error.name, error.message);
+                dbus_error_free (&error);
+                goto out;
+        }
+
+        caller = polkit_caller_new_from_pid (bus, caller_pid, &error);
+        if (caller == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot get caller from pid: %s: %s\n",
+                         error.name, error.message);
+                goto out;
+        }
+
+        action = polkit_action_new ();
+        if (action == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitAction\n");
+                goto out;
+        }
+        if (!polkit_action_set_action_id (action, "org.freedesktop.policykit.revoke")) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot set action_id\n");
+                goto out;
+        }
+
+        context = polkit_context_new ();
+        if (context == NULL) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot allocate PolKitContext\n");
+                goto out;
+        }
+        if (!polkit_context_init (context, NULL)) {
+                fprintf (stderr, "polkit-read-auth-helper: cannot initialize polkit\n");
+                goto out;
+        }
+
+        if (polkit_context_is_caller_authorized (context, action, caller, FALSE) != POLKIT_RESULT_YES) {
+                goto out;
+        }
+
+        ret = TRUE;
+out:
+
+        return ret;
+}
+
+
+static int
+_write_to_fd (int fd, const char *str, ssize_t str_len)
+{
+        int ret;
+        ssize_t written;
+
+        ret = 0;
+
+        written = 0;
+        while (written < str_len) {
+                ssize_t ret;
+                ret = write (fd, str + written, str_len - written);
+                if (ret < 0) {
+                        if (errno == EAGAIN || errno == EINTR) {
+                                continue;
+                        } else {
+                                goto out;
+                        }
+                }
+                written += ret;
+        }
+
+        ret = 1;
+
+out:
+        return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+        int ret;
+        gid_t egid;
+        struct group *group;
+        uid_t invoking_uid;
+        char *entry_to_remove;
+        int n;
+        int len;
+        char *p;
+        char *scope;
+        uid_t uid_to_revoke;
+        char *endp;
+        FILE *f;
+        int fd;
+        char path[256];
+        char path_tmp[256];
+        char line[512];
+        char *root;
+        char *target_type;
+        char *target_value;
+        struct passwd *pw;
+
+        ret = 1;
+
+        /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
+        if (clearenv () != 0)
+                goto out;
+        /* set a minimal environment */
+        setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
+
+        openlog ("polkit-revoke-helper", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
+
+        /* check for correct invocation */
+        if (argc != 4) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-revoke-helper: wrong number of arguments. This incident has been logged.\n");
+                goto out;
+        }
+
+        /* check we're running with a non-tty stdin */
+        if (isatty (STDIN_FILENO) != 0) {
+                syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ());
+                fprintf (stderr, "polkit-revoke-helper: inappropriate use of helper, stdin is a tty. This incident has been logged.\n");
+                goto out;
+        }
+
+        invoking_uid = getuid ();
+
+        /* check that we are setgid polkituser */
+        egid = getegid ();
+        group = getgrgid (egid);
+        if (group == NULL) {
+                fprintf (stderr, "polkit-revoke-helper: cannot lookup group info for gid %d\n", egid);
+                goto out;
+        }
+        if (strcmp (group->gr_name, POLKIT_GROUP) != 0) {
+                fprintf (stderr, "polkit-revoke-helper: needs to be setgid " POLKIT_GROUP "\n");
+                goto out;
+        }
+
+        entry_to_remove = argv[1];
+        target_type = argv[2];
+        target_value = argv[3];
+
+        /*----------------------------------------------------------------------------------------------------*/
+
+        /* paranoia: we have to validate the entry_to_remove argument
+         * and determine if the process who invoked us is sufficiently
+         * privileged. 
+         *
+         * As we're setuid root we don't want to pull in libpolkit and
+         * as we only need to parse the first two entries... we do it
+         * right here
+         */
+        p = entry_to_remove;
+        len = strlen (entry_to_remove);
+        for (n = 0; n < len; n++) {
+                if (p[n] == ':')
+                        goto found;
+        }
+        fprintf (stderr, "polkit-revoke-helper: entry_to_remove malformed\n");
+        goto out;
+found:
+        scope = strndup (entry_to_remove, n);
+        if (scope == NULL) {
+                fprintf (stderr, "polkit-revoke-helper: OOM\n");
+                goto out;
+        }
+
+        if (strcmp (target_type, "uid") == 0) {
+                uid_to_revoke = strtol (target_value, &endp, 10);
+                if  (*endp != '\0') {
+                        fprintf (stderr, "polkit-revoke-helper: cannot parse uid\n");
+                        goto out;
+                }
+        } else {
+                fprintf (stderr, "polkit-revoke-helper: unknown target type\n");
+                goto out;
+        }
+
+        /* OK, we're done parsing ... */
+
+        if (invoking_uid != 0) {
+                /* Check that the caller is privileged to do this... */
+                if (invoking_uid != uid_to_revoke) {
+         
+                        /* see if calling user has the
+                         *
+                         *  org.freedesktop.policykit.revoke
+                         *
+                         * authorization
+                         */
+                        if (!check_for_revoke_authorization (getppid ())) {
+                                goto out;
+                        }
+                }
+        }
+
+        if (strcmp (scope, "process") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
+        } else if (strcmp (scope, "session") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/run/PolicyKit";
+        } else if (strcmp (scope, "always") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
+        } else if (strcmp (scope, "grant") == 0) {
+                root = PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit";
+        } else {
+                fprintf (stderr, "polkit-revoke-helper: unknown scope '%s'\n", scope);
+                goto out;
+        }
+
+        pw = getpwuid (uid_to_revoke);
+        if (pw == NULL) {
+                fprintf (stderr, "polkit-revoke-helper: cannot lookup user name for uid %d\n", uid_to_revoke);
+                goto out;
+        }
+
+        if (snprintf (path, sizeof (path), "%s/user-%s.auths", root, pw->pw_name) >= (int) sizeof (path)) {
+                fprintf (stderr, "polkit-revoke-helper: string was truncated (1)\n");
+                goto out;
+        }
+        if (snprintf (path_tmp, sizeof (path_tmp), "%s/user-%s.auths.XXXXXX", root, pw->pw_name) >= (int) sizeof (path)) {
+                fprintf (stderr, "polkit-revoke-helper: string was truncated (2)\n");
+                goto out;
+        }
+
+        f = fopen (path, "r");
+        if (f == NULL) {
+                fprintf (stderr, "Cannot open file '%s': %m\n", path);
+                goto out;
+        }
+
+        fd = mkstemp (path_tmp);
+        if (fd < 0) {
+                fprintf (stderr, "Cannot create file '%s': %m\n", path_tmp);
+                goto out;
+        }
+        if (fchmod (fd, 0464) != 0) {
+                fprintf (stderr, "Cannot change mode for '%s' to 0460: %m\n", path_tmp);
+                close (fd);
+                unlink (path_tmp);
+                goto out;
+        }
+
+
+        /* read one line at a time */
+        while (fgets (line, sizeof (line), f) != NULL) {
+                size_t line_len;
+
+                line_len = strlen (line);
+                if (line_len > 1 && line[line_len - 1] == '\n') {
+                        if (strncmp (line, entry_to_remove, line_len - 1) == 0) {
+                                /* woho, found it */
+                                continue;
+                        }
+                }
+
+                /* otherwise, just write the line to the temporary file */
+                if (!_write_to_fd (fd, line, line_len)) {
+                        fprintf (stderr, "Error write to file '%s': %m\n", path_tmp);
+                        close (fd);
+                        unlink (path_tmp);
+                        goto out;
+                }
+        }
+        
+        fclose (f);
+        close (fd);
+
+        if (rename (path_tmp, path) != 0) {
+                fprintf (stderr, "Error renaming %s to %s: %m\n", path_tmp, path);
+                unlink (path_tmp);
+                goto out;
+        }
+
+        /* we're good now (if triggering a reload fails, so be it, we
+         * still did what the caller asked...)
+         */
+        ret = 0;
+
+        /* trigger a reload */
+        if (utimes (PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload", NULL) != 0) {
+                fprintf (stderr, "Error updating access+modification time on file '%s': %m\n", 
+                         PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload");
+        }
+
+out:
+
+        return ret;
+}
+
index 6295434..7c9c35a 100644 (file)
@@ -50,6 +50,9 @@ main (int argc, char *argv[])
        pam_handle_t *pam_h;
         const void *authed_user;
 
+        rc = 0;
+        pam_h = NULL;
+
         /* clear the entire environment to avoid attacks using with libraries honoring environment variables */
         if (clearenv () != 0)
                 goto error;
@@ -144,10 +147,12 @@ main (int argc, char *argv[])
         fprintf (stdout, "SUCCESS\n");
         fflush (stdout);
 
-        /* TODO: we should probably clean up */
-
+        pam_end (pam_h, rc);
         return 0;
 error:
+        if (pam_h != NULL)
+                pam_end (pam_h, rc);
+
         fprintf (stdout, "FAILURE\n");
         fflush (stdout);
         return 1;
index bce86d4..a191a15 100644 (file)
@@ -490,7 +490,6 @@ main (int argc, char *argv[])
         const char *invoking_user_name;
         const char *action_name;
         PolKitResult result;
-        PolKitResult original_result;
         const char *user_to_auth;
         uid_t uid_of_user_to_auth;
         char *session_objpath;
@@ -720,8 +719,6 @@ main (int argc, char *argv[])
                 goto out;
         }
 
-        original_result = result;
-
         /* Ask caller if he want to slim down grant type...  e.g. he
          * might want to go from auth_self_keep_always to
          * auth_self_keep_session..
@@ -744,13 +741,15 @@ main (int argc, char *argv[])
                  action_name, session_objpath, caller_pid, polkit_result_to_string_representation (result));
 #endif /* PGH_DEBUG */
 
+        /* make sure write permissions for group is honored */
+        umask (002);
+
         switch (result) {
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
                 dbres = polkit_authorization_db_add_entry_process (polkit_context_get_authorization_db (context), 
                                                                    action, 
                                                                    caller,
-                                                                   original_result,
                                                                    uid_of_user_to_auth);
                 if (dbres) {
                         syslog (LOG_INFO, "granted authorization for %s to pid %d [uid=%d] [auth=%s]",
@@ -762,8 +761,7 @@ main (int argc, char *argv[])
         case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
                 dbres = polkit_authorization_db_add_entry_session (polkit_context_get_authorization_db (context), 
                                                                    action, 
-                                                                   session,
-                                                                   original_result,
+                                                                   caller,
                                                                    uid_of_user_to_auth);
 
                 if (dbres) {
@@ -776,8 +774,7 @@ main (int argc, char *argv[])
         case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
                 dbres = polkit_authorization_db_add_entry_always (polkit_context_get_authorization_db (context), 
                                                                   action, 
-                                                                  caller_uid,
-                                                                  original_result,
+                                                                  caller,
                                                                   uid_of_user_to_auth);
                 if (dbres) {
                         syslog (LOG_INFO, "granted authorization for %s to uid %d [auth=%s]", 
index e7ac1a1..59ef3b5 100644 (file)
@@ -33,29 +33,29 @@ libpolkitinclude_HEADERS =                          \
        polkit-policy-default.h                         \
        polkit-config.h                                 \
        polkit-authorization.h                          \
+       polkit-authorization-constraint.h               \
        polkit-authorization-db.h
 
-libpolkit_la_SOURCES =                                                 \
-       polkit.h                                                        \
-                                       polkit-types.h                  \
-       polkit-error.h                  polkit-error.c                  \
-       polkit-result.h                 polkit-result.c                 \
-       polkit-context.h                polkit-context.c                \
-       polkit-action.h                 polkit-action.c                 \
-       polkit-seat.h                   polkit-seat.c                   \
-       polkit-session.h                polkit-session.c                \
-       polkit-caller.h                 polkit-caller.c                 \
-       polkit-policy-file-entry.h      polkit-policy-file-entry.c      \
-       polkit-policy-file.h            polkit-policy-file.c            \
-       polkit-policy-cache.h           polkit-policy-cache.c           \
-       polkit-policy-default.h         polkit-policy-default.c         \
-       polkit-debug.h                  polkit-debug.c                  \
-       polkit-utils.h                  polkit-utils.c                  \
-       polkit-config.h                 polkit-config.c                 \
-       polkit-authorization.h          polkit-authorization.c          \
-       polkit-authorization-db.h       polkit-authorization-db.c       \
-       polkit-grant-database.h         polkit-grant-database.c
-
+libpolkit_la_SOURCES =                                                                 \
+       polkit.h                                                                        \
+                                               polkit-types.h                          \
+       polkit-error.h                          polkit-error.c                          \
+       polkit-result.h                         polkit-result.c                         \
+       polkit-context.h                        polkit-context.c                        \
+       polkit-action.h                         polkit-action.c                         \
+       polkit-seat.h                           polkit-seat.c                           \
+       polkit-session.h                        polkit-session.c                        \
+       polkit-caller.h                         polkit-caller.c                         \
+       polkit-policy-file-entry.h              polkit-policy-file-entry.c              \
+       polkit-policy-file.h                    polkit-policy-file.c                    \
+       polkit-policy-cache.h                   polkit-policy-cache.c                   \
+       polkit-policy-default.h                 polkit-policy-default.c                 \
+       polkit-debug.h                          polkit-debug.c                          \
+       polkit-utils.h                          polkit-utils.c                          \
+       polkit-config.h                         polkit-config.c                         \
+       polkit-authorization.h                  polkit-authorization.c                  \
+       polkit-authorization-constraint.h       polkit-authorization-constraint.c       \
+       polkit-authorization-db.h               polkit-authorization-db.c
 
 libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@
 
@@ -64,11 +64,23 @@ libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 clean-local :
        rm -f *~ $(BUILT_SOURCES)
 
+# The directories /var/lib/PolicyKit and /var/run/PolicyKit is where
+# authorizations are stored. They must not be world readable (the
+# polkit-auth-read-helper is used to read it) and the $POLKIT_GROUP
+# group needs to be able to write files there.
+#
+# The /var/lib/misc/PolicyKit.reload file is used for triggering that
+# authorizations have changed; it needs to be world readable and
+# writeable for the $POLKIT_GROUP group (FHS 2.3 suggests that
+# location)
+#
 install-data-local:
        -mkdir -p $(DESTDIR)$(localstatedir)/lib/PolicyKit
        -mkdir -p $(DESTDIR)$(localstatedir)/run/PolicyKit
-       -chown $(POLKIT_USER):$(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/PolicyKit
-       -chown $(POLKIT_USER):$(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/run/PolicyKit
-       -chmod 775 $(DESTDIR)$(localstatedir)/lib/PolicyKit
-       -chmod 775 $(DESTDIR)$(localstatedir)/run/PolicyKit
-
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/PolicyKit
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/run/PolicyKit
+       -chmod 770 $(DESTDIR)$(localstatedir)/lib/PolicyKit
+       -chmod 770 $(DESTDIR)$(localstatedir)/run/PolicyKit
+       -touch $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
+       -chgrp $(POLKIT_GROUP) $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
+       -chmod 775 $(DESTDIR)$(localstatedir)/lib/misc/PolicyKit.reload
diff --git a/polkit/polkit-authorization-constraint.c b/polkit/polkit-authorization-constraint.c
new file mode 100644 (file)
index 0000000..db82896
--- /dev/null
@@ -0,0 +1,492 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-authorization-constraint.c : Conditions that must be
+ * satisfied in order for an authorization to apply
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib.h>
+#include "polkit-debug.h"
+#include "polkit-authorization-constraint.h"
+#include "polkit-utils.h"
+
+/**
+ * SECTION:polkit-authorization-constraint
+ * @title: Authorization Constraints
+ * @short_description: Conditions that must be satisfied in
+ * order for an authorization to apply
+ *
+ * This class is used to represent conditions that must be satisfied
+ * in order for an authorization to apply
+ *
+ * Since: 0.7
+ **/
+
+/**
+ * PolKitAuthorizationConstraint:
+ *
+ * Instances of this class are used to represent conditions that must
+ * be satisfied in order for an authorization to apply.
+ *
+ * Since: 0.7
+ **/
+struct _PolKitAuthorizationConstraint
+{
+        int refcount;
+        PolKitAuthorizationConstraintFlags flags;
+};
+
+static PolKitAuthorizationConstraint _null_constraint = {-1, 0};
+
+static PolKitAuthorizationConstraint _local_constraint = {-1, 
+                                                          POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL};
+
+static PolKitAuthorizationConstraint _active_constraint = {-1, 
+                                                          POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE};
+
+static PolKitAuthorizationConstraint _local_active_constraint = {-1, 
+                                                                 POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL |
+                                                                 POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE};
+
+extern PolKitAuthorizationConstraint *_polkit_authorization_constraint_new (const char *entry_in_auth_file);
+
+PolKitAuthorizationConstraint *
+_polkit_authorization_constraint_new (const char *entry_in_auth_file)
+{
+        PolKitAuthorizationConstraint *authc;
+        authc = g_new0 (PolKitAuthorizationConstraint, 1);
+        authc->refcount = 0;
+        return authc;
+}
+
+/**
+ * polkit_authorization_constraint_ref:
+ * @authc: the object
+ * 
+ * Increase reference count.
+ * 
+ * Returns: the object
+ *
+ * Since: 0.7
+ **/
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_ref (PolKitAuthorizationConstraint *authc)
+{
+        g_return_val_if_fail (authc != NULL, authc);
+        if (authc->refcount == -1)
+                return authc;
+        authc->refcount++;
+        return authc;
+}
+
+/**
+ * polkit_authorization_constraint_unref:
+ * @authc: the authorization_constraint object
+ * 
+ * Decreases the reference count of the object. If it becomes zero,
+ * the object is freed. Before freeing, reference counts on embedded
+ * objects are decresed by one.
+ *
+ * Since: 0.7
+ **/
+void
+polkit_authorization_constraint_unref (PolKitAuthorizationConstraint *authc)
+{
+        g_return_if_fail (authc != NULL);
+        if (authc->refcount == -1)
+                return;
+        authc->refcount--;
+        if (authc->refcount > 0) 
+                return;
+
+        g_free (authc);
+}
+
+/**
+ * polkit_authorization_constraint_debug:
+ * @authc: the object
+ * 
+ * Print debug details
+ *
+ * Since: 0.7
+ **/
+void
+polkit_authorization_constraint_debug (PolKitAuthorizationConstraint *authc)
+{
+        g_return_if_fail (authc != NULL);
+        _pk_debug ("PolKitAuthorizationConstraint: refcount=%d", authc->refcount);
+}
+
+/**
+ * polkit_authorization_constraint_validate:
+ * @authc: the object
+ * 
+ * Validate the object
+ * 
+ * Returns: #TRUE iff the object is valid.
+ *
+ * Since: 0.7
+ **/
+polkit_bool_t
+polkit_authorization_constraint_validate (PolKitAuthorizationConstraint *authc)
+{
+        g_return_val_if_fail (authc != NULL, FALSE);
+
+        return TRUE;
+}
+
+/**
+ * polkit_authorization_constraint_check_session:
+ * @authc: the object
+ * @session: the session
+ *
+ * Determine if the given session satisfies the conditions imposed by
+ * the given constraint
+ *
+ * Returns: #TRUE if, and only if, the given session satisfies the
+ * conditions imposed by the given constraint.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_constraint_check_session (PolKitAuthorizationConstraint *authc,
+                                               PolKitSession                 *session)
+{
+        polkit_bool_t ret;
+        polkit_bool_t is_active;
+        polkit_bool_t is_local;
+
+        g_return_val_if_fail (authc != NULL, FALSE);
+        g_return_val_if_fail (session != NULL, FALSE);
+
+        ret = FALSE;
+
+        if (!polkit_session_get_ck_is_local (session, &is_local))
+                is_local = FALSE;
+
+        if (!polkit_session_get_ck_is_active (session, &is_active))
+                is_active = FALSE;
+
+        if (authc->flags & POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL)  {
+                if (!is_local)
+                        goto out;
+        }
+
+        if (authc->flags & POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE)  {
+                if (!is_active)
+                        goto out;
+        }
+
+        ret = TRUE;
+out:
+        return ret;
+}
+
+/**
+ * polkit_authorization_constraint_check_caller:
+ * @authc: the object
+ * @caller: the caller
+ *
+ * Determine if the given caller satisfies the conditions imposed by
+ * the given constraint
+ *
+ * Returns: #TRUE if, and only if, the given caller satisfies the
+ * conditions imposed by the given constraint.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t 
+polkit_authorization_constraint_check_caller (PolKitAuthorizationConstraint *authc,
+                                              PolKitCaller                  *caller)
+{
+        polkit_bool_t ret;
+        PolKitSession *session;
+
+        g_return_val_if_fail (authc != NULL, FALSE);
+        g_return_val_if_fail (caller != NULL, FALSE);
+
+        ret = FALSE;
+
+        /* caller may not be in a session */
+        if (polkit_caller_get_ck_session (caller, &session) && session != NULL) {
+                ret = polkit_authorization_constraint_check_session (authc, session);
+        } else {
+                if (authc->flags == 0) {
+                        ret = TRUE;
+                }
+        }
+
+        return ret;
+}
+
+/**
+ * polkit_authorization_constraint_get_flags:
+ * @authc: the object
+ *
+ * Describe the constraint; this is only useful when inspecting an
+ * authorization to present information to the user (e.g. as
+ * polkit-auth(1) does).
+ *
+ * Note that the flags returned may not fully describe the constraint
+ * and shouldn't be used to perform checking against #PolKitCaller or
+ * #PolKitSession objects. Use the
+ * polkit_authorization_constraint_check_caller() and
+ * polkit_authorization_constraint_check_session() methods for that
+ * instead.
+ *
+ * Returns: flags from #PolKitAuthorizationConstraintFlags
+ *
+ * Since: 0.7
+ */
+PolKitAuthorizationConstraintFlags
+polkit_authorization_constraint_get_flags (PolKitAuthorizationConstraint *authc)
+{
+        g_return_val_if_fail (authc != NULL, FALSE);
+        return authc->flags;
+}
+
+/**
+ * polkit_authorization_constraint_get_null:
+ *
+ * Get a #PolKitAuthorizationConstraint object that represents no constraints.
+ *
+ * Returns: the constraint; the caller shall not unref this object
+ *
+ * Since: 0.7
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_get_null (void)
+{
+        return &_null_constraint;
+}
+
+/**
+ * polkit_authorization_constraint_get_require_local:
+ *
+ * Get a #PolKitAuthorizationConstraint object that represents the
+ * constraint that the session or caller must be local.
+ *
+ * Returns: the constraint; the caller shall not unref this object
+ *
+ * Since: 0.7
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_get_require_local (void)
+{
+        return &_local_constraint;
+}
+
+/**
+ * polkit_authorization_constraint_get_require_active:
+ *
+ * Get a #PolKitAuthorizationConstraint object that represents the
+ * constraint that the session or caller must be active.
+ *
+ * Returns: the constraint; the caller shall not unref this object
+ *
+ * Since: 0.7
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_get_require_active (void)
+{
+        return &_active_constraint;
+}
+
+/**
+ * polkit_authorization_constraint_get_require_local_active:
+ *
+ * Get a #PolKitAuthorizationConstraint object that represents the
+ * constraint that the session or caller must be local and in an
+ * active session.
+ *
+ * Returns: the constraint; the caller shall not unref this object
+ *
+ * Since: 0.7
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_get_require_local_active (void)
+{
+        return &_local_active_constraint;
+}
+
+/**
+ * polkit_authorization_constraint_to_string:
+ * @authc: the object
+ * @out_buf: buffer to store the string representation in
+ * @buf_size: size of buffer
+ *
+ * Get a textual representation of the constraint; this is only useful
+ * for serializing; it's a machine, not human, readable string.
+ *
+ * Returns: Number of characters written (not including trailing
+ * '\0'). If the output was truncated due to the buffer being too
+ * small, buf_size will be returned. Thus, a return value of buf_size
+ * or more indicates that the output was truncated (see snprintf(3))
+ * or an error occured.
+ *
+ * Since: 0.7
+ */
+size_t
+polkit_authorization_constraint_to_string (PolKitAuthorizationConstraint *authc, char *out_buf, size_t buf_size)
+{
+        g_return_val_if_fail (authc != NULL, buf_size);
+
+        switch (authc->flags) {
+        case 0:
+                return snprintf (out_buf, buf_size, "none");
+
+        case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL:
+                return snprintf (out_buf, buf_size, "local");
+
+        case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE:
+                return snprintf (out_buf, buf_size, "active");
+
+        case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL|POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE:
+                return snprintf (out_buf, buf_size, "local+active");
+
+        default:
+                return buf_size;
+        }
+}
+
+/**
+ * polkit_authorization_constraint_from_string:
+ * @str: textual representation of constraint
+ *
+ * Construct a constraint from a textual representation as returned by
+ * polkit_authorization_constraint_to_string().
+ *
+ * Returns: the constraint or #NULL if the string coulnd't be parsed.
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_from_string (const char *str)
+{
+        PolKitAuthorizationConstraint *ret;
+
+        g_return_val_if_fail (str != NULL, NULL);
+
+        ret = NULL;
+
+        if (strcmp (str, "none") == 0) {
+                ret = polkit_authorization_constraint_get_null ();
+                goto out;
+        } else if (strcmp (str, "local") == 0) {
+                ret = polkit_authorization_constraint_get_require_local ();
+                goto out;
+        } else if (strcmp (str, "active") == 0) {
+                ret = polkit_authorization_constraint_get_require_active ();
+                goto out;
+        } else if (strcmp (str, "local+active") == 0) {
+                ret = polkit_authorization_constraint_get_require_local_active ();
+                goto out;
+        }
+
+out:
+        return ret;
+}
+
+/**
+ * polkit_authorization_constraint_get_from_caller:
+ * @caller: caller
+ *
+ * Given a caller, return the most restrictive constraint
+ * possible. For example, if the caller is local and active, a
+ * constraint requiring this will be returned. 
+ *
+ * This function is typically used when the caller obtains an
+ * authorization through authentication; the goal is to put a
+ * constraints on the authorization such that it's only valid when the
+ * caller is in the context as where she obtained it.
+ *
+ * Returns: a #PolKitConstraint object; this function will never return #NULL.
+ */
+PolKitAuthorizationConstraint *
+polkit_authorization_constraint_get_from_caller (PolKitCaller *caller)
+{
+        polkit_bool_t is_local;
+        polkit_bool_t is_active;
+        PolKitSession *session;
+        PolKitAuthorizationConstraint *ret;
+
+        /* caller is not in a session so use the null constraint */
+        if (!polkit_caller_get_ck_session (caller, &session)) {
+                ret = polkit_authorization_constraint_get_null ();
+                goto out;
+        }
+
+        /* if we, for some reason, don't know if the user is local or active, prefer maximal constraint */
+        if (!polkit_session_get_ck_is_local (session, &is_local))
+                is_local = TRUE;
+        if (!polkit_session_get_ck_is_active (session, &is_active))
+                is_active = TRUE;
+
+        if (is_local) {
+                if (is_active) {
+                        ret = polkit_authorization_constraint_get_require_local_active ();
+                } else {
+                        ret = polkit_authorization_constraint_get_require_local ();
+                }
+        } else {
+                if (is_active) {
+                        ret = polkit_authorization_constraint_get_require_active ();
+                } else {
+                        ret = polkit_authorization_constraint_get_null ();
+                }
+        }
+
+out:
+        return ret;
+}
+
+
+/**
+ * polkit_authorization_constraint_equal:
+ * @a: first constraint
+ * @b: first constraint
+ *
+ * Determines if two constraints are equal
+ *
+ * Returns: #TRUE only if the given constraints are equal
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_constraint_equal (PolKitAuthorizationConstraint *a, PolKitAuthorizationConstraint *b)
+{
+        g_return_val_if_fail (a != NULL, FALSE);
+        g_return_val_if_fail (b != NULL, FALSE);
+
+        return a->flags == b->flags;
+}
diff --git a/polkit/polkit-authorization-constraint.h b/polkit/polkit-authorization-constraint.h
new file mode 100644 (file)
index 0000000..30c5219
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-authorization-constraint.h : Conditions that must be
+ * satisfied in order for an authorization to apply
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H)
+#error "Only <polkit/polkit.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef POLKIT_AUTHORIZATION_CONSTRAINT_H
+#define POLKIT_AUTHORIZATION_CONSTRAINT_H
+
+#include <polkit/polkit-types.h>
+#include <polkit/polkit-action.h>
+#include <polkit/polkit-result.h>
+#include <polkit/polkit-session.h>
+#include <polkit/polkit-caller.h>
+
+POLKIT_BEGIN_DECLS
+
+/**
+ * PolKitAuthorizationConstraintFlags:
+ * @POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL: the session or
+ * caller must be local
+ * @POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE: the session or
+ * caller must be in an active session
+ * @POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL_ACTIVE: short
+ * hand for the flags POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL
+ * and POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE.
+ *
+ * This enumeration describes different conditions, not mutually
+ * exclusive, to help describe an authorization constraint.
+ */
+typedef enum {
+        POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL         = 1 << 0,
+        POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE        = 1 << 1,
+        POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL_ACTIVE  = (1 << 0) | (1 << 1)
+} PolKitAuthorizationConstraintFlags;
+
+struct _PolKitAuthorizationConstraint;
+typedef struct _PolKitAuthorizationConstraint PolKitAuthorizationConstraint;
+
+PolKitAuthorizationConstraint *polkit_authorization_constraint_get_null (void);
+PolKitAuthorizationConstraint *polkit_authorization_constraint_get_require_local (void);
+PolKitAuthorizationConstraint *polkit_authorization_constraint_get_require_active (void);
+PolKitAuthorizationConstraint *polkit_authorization_constraint_get_require_local_active (void);
+
+PolKitAuthorizationConstraint *polkit_authorization_constraint_ref      (PolKitAuthorizationConstraint *authc);
+void                           polkit_authorization_constraint_unref    (PolKitAuthorizationConstraint *authc);
+void                           polkit_authorization_constraint_debug    (PolKitAuthorizationConstraint *authc);
+polkit_bool_t                  polkit_authorization_constraint_validate (PolKitAuthorizationConstraint *authc);
+
+PolKitAuthorizationConstraintFlags polkit_authorization_constraint_get_flags (PolKitAuthorizationConstraint *authc);
+
+polkit_bool_t polkit_authorization_constraint_check_session (PolKitAuthorizationConstraint *authc,
+                                                             PolKitSession                 *session);
+
+polkit_bool_t polkit_authorization_constraint_check_caller (PolKitAuthorizationConstraint *authc,
+                                                            PolKitCaller                  *caller);
+
+size_t                         polkit_authorization_constraint_to_string (PolKitAuthorizationConstraint *authc, char *out_buf, size_t buf_size);
+PolKitAuthorizationConstraint *polkit_authorization_constraint_from_string (const char *str);
+
+PolKitAuthorizationConstraint *polkit_authorization_constraint_get_from_caller (PolKitCaller *caller);
+
+polkit_bool_t                  polkit_authorization_constraint_equal (PolKitAuthorizationConstraint *a,
+                                                                      PolKitAuthorizationConstraint *b);
+
+POLKIT_END_DECLS
+
+#endif /* POLKIT_AUTHORIZATION_CONSTRAINT_H */
+
+
index ed8726b..1c546d1 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <sys/stat.h>
 #include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-#include <unistd.h>
+#include <sys/time.h>
+#include <sys/wait.h>
 #include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pwd.h>
 
 #include <glib.h>
+
 #include "polkit-debug.h"
 #include "polkit-authorization-db.h"
 #include "polkit-utils.h"
 
-/* For now, redirect to the old stuff */
-#include "polkit-grant-database.h"
-
 /**
  * SECTION:polkit-authorization-db
  * @title: Authorization Database
@@ -55,6 +56,9 @@
  * Since: 0.7
  **/
 
+extern void _polkit_authorization_db_invalidate_cache (PolKitAuthorizationDB *authdb);
+
+
 /**
  * PolKitAuthorizationDB:
  *
 struct _PolKitAuthorizationDB
 {
         int refcount;
+        GHashTable *uid_to_authlist;
 };
 
+static void
+_free_authlist (GSList *authlist)
+{
+        if (authlist != NULL) {
+                g_slist_foreach (authlist, (GFunc) polkit_authorization_unref, NULL);
+                g_slist_free (authlist);
+        }
+}
+
 /**
  * polkit_authorization_db_new:
  * 
@@ -81,8 +95,12 @@ PolKitAuthorizationDB *
 polkit_authorization_db_new (void)
 {
         PolKitAuthorizationDB *authdb;
+
         authdb = g_new0 (PolKitAuthorizationDB, 1);
         authdb->refcount = 1;
+
+        /* set up the hashtable */
+        _polkit_authorization_db_invalidate_cache (authdb);
         return authdb;
 }
 
@@ -121,6 +139,7 @@ polkit_authorization_db_unref (PolKitAuthorizationDB *authdb)
         authdb->refcount--;
         if (authdb->refcount > 0) 
                 return;
+        g_hash_table_destroy (authdb->uid_to_authlist);
         g_free (authdb);
 }
 
@@ -157,6 +176,424 @@ polkit_authorization_db_validate (PolKitAuthorizationDB *authdb)
         return TRUE;
 }
 
+/**
+ * _polkit_authorization_db_invalidate_cache:
+ * @authdb: authorization database
+ *
+ * Tell the authorization database to invalidate any caches it might
+ * employ. This is called by #PolKitContext whenever configuration or
+ * anything else changes.
+ *
+ * Since: 0.7
+ */
+void
+_polkit_authorization_db_invalidate_cache (PolKitAuthorizationDB *authdb)
+{
+        /* out with the old, in the with new */
+        if (authdb->uid_to_authlist != NULL) {
+                g_hash_table_destroy (authdb->uid_to_authlist);
+        }
+        authdb->uid_to_authlist = g_hash_table_new_full (g_direct_hash,
+                                                         g_direct_equal,
+                                                         NULL,
+                                                         (GDestroyNotify) _free_authlist);
+}
+
+/* TODO FIXME: this is Linux specific */
+static polkit_uint64_t 
+get_start_time_for_pid (pid_t pid)
+{
+        char *filename;
+        char *contents;
+        gsize length;
+        polkit_uint64_t start_time;
+        GError *error = NULL;
+        char **tokens;
+        char *p;
+        char *endp;
+
+        start_time = 0;
+        contents = NULL;
+
+        filename = g_strdup_printf ("/proc/%d/stat", pid);
+        if (filename == NULL) {
+                fprintf (stderr, "Out of memory\n");
+                goto out;
+        }
+
+        if (!g_file_get_contents (filename, &contents, &length, &error)) {
+                fprintf (stderr, "Cannot get contents of '%s': %s\n", filename, error->message);
+                g_error_free (error);
+                goto out;
+        }
+
+        /* start time is the 19th token after the '(process name)' entry */
+
+        p = strchr (contents, ')');
+        if (p == NULL) {
+                goto out;
+        }
+        p += 2; /* skip ') ' */
+        if (p - contents >= (int) length) {
+                goto out;
+        }
+
+        tokens = g_strsplit (p, " ", 0);
+        if (g_strv_length (tokens) < 20) {
+                goto out;
+        }
+
+        start_time = strtoll (tokens[19], &endp, 10);
+        if (endp == tokens[19]) {
+                goto out;
+        }
+
+        g_strfreev (tokens);
+
+out:
+        g_free (filename);
+        g_free (contents);
+        return start_time;
+}
+
+extern PolKitAuthorization *_polkit_authorization_new_for_uid (const char *entry_in_auth_file, uid_t uid);
+
+/**
+ * _authdb_get_auths_for_uid:
+ * @authdb: authorization database
+ * @uid: uid to get authorizations for. If -1 is passed authorizations
+ * for all users will be returned.
+ * @error: return location for error
+ *
+ * Internal function to get authorizations for a uid.
+ *
+ * Returns: A singly-linked list of #PolKitAuthorization
+ * objects. Caller shall not free this list. Returns #NULL if either
+ * calling process is not sufficiently privileged (error will be set)
+ * or if there are no authorizations for the given uid.
+ *
+ * Since: 0.7
+ */
+static GSList *
+_authdb_get_auths_for_uid (PolKitAuthorizationDB *authdb,
+                           uid_t                  uid,
+                           PolKitError          **error)
+{
+        GSList *ret;
+        char *helper_argv[] = {PACKAGE_LIBEXEC_DIR "/polkit-read-auth-helper", NULL, NULL};
+        gint exit_status;
+        GError *g_error;
+        char *standard_output;
+        size_t len;
+        off_t n;
+
+        ret = NULL;
+        standard_output = NULL;
+
+        /* first, see if this is in the cache */
+        ret = g_hash_table_lookup (authdb->uid_to_authlist, (gpointer) uid);
+        if (ret != NULL)
+                goto out;
+
+        helper_argv[1] = g_strdup_printf ("%d", uid);
+
+        /* we need to do this through a setgid polkituser helper
+         * because the auth file is readable only for uid 0 and gid
+         * polkituser.
+         */
+        g_error = NULL;
+        if (!g_spawn_sync (NULL,             /* const gchar *working_directory */
+                           helper_argv,      /* gchar **argv */
+                           NULL,             /* gchar **envp */
+                           0,                /* GSpawnFlags flags */
+                           NULL,             /* GSpawnChildSetupFunc child_setup */
+                           NULL,             /* gpointer user_data */
+                           &standard_output, /* gchar **standard_output */
+                           NULL,             /* gchar **standard_error */
+                           &exit_status,     /* gint *exit_status */
+                           &g_error)) {      /* GError **error */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Error spawning read auth helper: %s",
+                                        g_error->message);
+                g_error_free (g_error);
+                goto out;
+        }
+
+        if (!WIFEXITED (exit_status)) {
+                g_warning ("Read auth helper crashed!");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Read auth helper crashed!");
+                goto out;
+        } else if (WEXITSTATUS(exit_status) != 0) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS, 
+                                        uid > 0 ?
+                                        "uid %d is not authorized to read authorizations for uid %d (requires org.freedesktop.policykit.read)" : 
+                                        "uid %d is not authorized to read all authorizations (requires org.freedesktop.policykit.read)",
+                                        getuid (), uid);
+                goto out;
+        }
+
+        len = strlen (standard_output);
+
+        /* parse one line at a time (modifies standard_output in place) */
+        n = 0;
+        while (n < len) {
+                off_t m;
+                char *line;
+                PolKitAuthorization *auth;
+
+                m = n;
+                while (m < len && standard_output[m] != '\0') {
+                        if (standard_output[m] == '\n')
+                                break;
+                        m++;
+                }
+                /* check EOF */
+                if (standard_output[m] == '\0')
+                        break;
+                standard_output[m] = '\0';
+
+                line = standard_output + n;
+
+                if (strlen (line) >= 2 && line[0] != '#') {
+
+                        auth = _polkit_authorization_new_for_uid (line, uid);
+                        
+                        if (auth != NULL) {
+                                ret = g_slist_prepend (ret, auth);
+                        }
+                }
+
+                n = m + 1;
+        }
+
+        g_hash_table_insert (authdb->uid_to_authlist, (gpointer) uid, ret);
+
+out:
+        g_free (helper_argv[1]);
+        g_free (standard_output);
+        return ret;
+}
+
+
+static polkit_bool_t 
+_internal_foreach (PolKitAuthorizationDB       *authdb,
+                   PolKitAction                *action,
+                   uid_t                        uid,
+                   PolKitAuthorizationDBForeach cb,
+                   void                        *user_data,
+                   PolKitError                **error)
+{
+        GSList *l;
+        GSList *auths;
+        polkit_bool_t ret;
+        char *action_id;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (cb != NULL, FALSE);
+
+        ret = FALSE;
+
+        if (action == NULL) {
+                action_id = NULL;
+        } else {
+                if (!polkit_action_get_action_id (action, &action_id))
+                        goto out;
+        }
+
+        auths = _authdb_get_auths_for_uid (authdb, uid, error);
+        if (auths == NULL)
+                goto out;
+
+        for (l = auths; l != NULL; l = l->next) {
+                PolKitAuthorization *auth = l->data;
+
+                if (action_id != NULL) {
+                        if (strcmp (polkit_authorization_get_action_id (auth), action_id) != 0) {
+                                continue;
+                        }
+                }
+
+                if (cb (authdb, auth, user_data)) {
+                        ret = TRUE;
+                        goto out;
+                }
+        }
+
+out:
+        return ret;
+}
+
+
+/**
+ * polkit_authorization_db_foreach:
+ * @authdb: authorization database
+ * @cb: callback
+ * @user_data: user data to pass to callback
+ * @error: return location for error
+ *
+ * Iterate over all entries in the authorization database.
+ *
+ * Note that unless the calling process has the authorization
+ * org.freedesktop.policykit.read this function may return an error.
+ *
+ * Returns: #TRUE if the callback returned #TRUE to stop iterating. If
+ * #FALSE, either error may be set or the callback returns #FALSE on
+ * every invocation.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_foreach (PolKitAuthorizationDB       *authdb,
+                                 PolKitAuthorizationDBForeach cb,
+                                 void                        *user_data,
+                                 PolKitError                **error)
+{
+        return _internal_foreach (authdb, NULL, -1, cb, user_data, error);
+}
+
+/**
+ * polkit_authorization_db_foreach_for_uid:
+ * @authdb: authorization database
+ * @uid: user to get authorizations for
+ * @cb: callback
+ * @user_data: user data to pass to callback
+ * @error: return location for error
+ *
+ * Iterate over all entries in the authorization database for a given
+ * user.
+ *
+ * Note that if the calling process asks for authorizations for a
+ * different uid than itself and it lacks the authorization
+ * org.freedesktop.policykit.read this function may return an error.
+ *
+ * Returns: #TRUE if the callback returned #TRUE to stop iterating. If
+ * #FALSE, either error may be set or the callback returns #FALSE on
+ * every invocation.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_foreach_for_uid (PolKitAuthorizationDB       *authdb,
+                                         uid_t                        uid,
+                                         PolKitAuthorizationDBForeach cb,
+                                         void                        *user_data,
+                                         PolKitError                **error)
+{
+        return _internal_foreach (authdb, NULL, uid, cb, user_data, error);
+}
+
+/**
+ * polkit_authorization_db_foreach_for_action:
+ * @authdb: authorization database
+ * @action: action to get authorizations for
+ * @cb: callback
+ * @user_data: user data to pass to callback
+ * @error: return location for error
+ *
+ * Iterate over all entries in the authorization database for a given
+ * action.
+ *
+ * Note that unless the calling process has the authorization
+ * org.freedesktop.policykit.read this function may return an error.
+ *
+ * Returns: #TRUE if the callback returned #TRUE to stop iterating. If
+ * #FALSE, either error may be set or the callback returns #FALSE on
+ * every invocation.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t 
+polkit_authorization_db_foreach_for_action (PolKitAuthorizationDB       *authdb,
+                                            PolKitAction                *action,
+                                            PolKitAuthorizationDBForeach cb,
+                                            void                        *user_data,
+                                            PolKitError                **error)
+{
+        g_return_val_if_fail (action != NULL, FALSE);
+        return _internal_foreach (authdb, action, -1, cb, user_data, error);
+}
+
+/**
+ * polkit_authorization_db_foreach_for_action_for_uid:
+ * @authdb: authorization database
+ * @action: action to get authorizations for
+ * @uid: user to get authorizations for
+ * @cb: callback
+ * @user_data: user data to pass to callback
+ * @error: return location for error
+ *
+ * Iterate over all entries in the authorization database for a given
+ * action and user.
+ *
+ * Note that if the calling process asks for authorizations for a
+ * different uid than itself and it lacks the authorization
+ * org.freedesktop.policykit.read this function may return an error.
+ *
+ * Returns: #TRUE if the callback returned #TRUE to stop iterating. If
+ * #FALSE, either error may be set or the callback returns #FALSE on
+ * every invocation.
+ *
+ * Since: 0.7
+ */
+polkit_bool_t 
+polkit_authorization_db_foreach_for_action_for_uid (PolKitAuthorizationDB       *authdb,
+                                                    PolKitAction                *action,
+                                                    uid_t                        uid,
+                                                    PolKitAuthorizationDBForeach cb,
+                                                    void                        *user_data,
+                                                    PolKitError                **error)
+{
+        g_return_val_if_fail (action != NULL, FALSE);
+        return _internal_foreach (authdb, action, uid, cb, user_data, error);
+}
+
+
+typedef struct {
+        char *action_id;
+        uid_t session_uid; 
+        char *session_objpath;
+        PolKitSession *session;
+} CheckDataSession;
+
+static polkit_bool_t 
+_check_auth_for_session (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
+{
+        gboolean ret;
+        CheckDataSession *cd = (CheckDataSession *) user_data;
+        PolKitAuthorizationConstraint *constraint;
+
+        ret = FALSE;
+
+        if (strcmp (polkit_authorization_get_action_id (auth), cd->action_id) != 0)
+                goto no_match;
+
+        constraint = polkit_authorization_get_constraint (auth);
+        if (!polkit_authorization_constraint_check_session (constraint, cd->session))
+                goto no_match;
+
+        switch (polkit_authorization_get_scope (auth))
+        {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
+                goto no_match;
+
+        case POLKIT_AUTHORIZATION_SCOPE_SESSION:
+                if (strcmp (polkit_authorization_scope_session_get_ck_objref (auth), cd->session_objpath) != 0)
+                        goto no_match;
+                break;
+
+        case POLKIT_AUTHORIZATION_SCOPE_ALWAYS:
+                break;
+        }
+
+        ret = TRUE;
+
+no_match:
+        return ret;
+}
 
 /**
  * polkit_authorization_db_is_session_authorized:
@@ -181,7 +618,92 @@ polkit_authorization_db_is_session_authorized (PolKitAuthorizationDB *authdb,
                                                PolKitSession         *session,
                                                polkit_bool_t         *out_is_authorized)
 {
-        return FALSE;
+        polkit_bool_t ret;
+        CheckDataSession cd;
+
+        ret = FALSE;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (action != NULL, FALSE);
+        g_return_val_if_fail (session != NULL, FALSE);
+        g_return_val_if_fail (out_is_authorized != NULL, FALSE);
+
+        if (!polkit_action_get_action_id (action, &cd.action_id))
+                return FALSE;
+
+        if (!polkit_session_get_uid (session, &cd.session_uid))
+                return FALSE;
+
+        cd.session = session;
+
+        if (!polkit_session_get_ck_objref (session, &cd.session_objpath) || cd.session_objpath == NULL)
+                return FALSE;
+
+        ret = TRUE;
+
+        *out_is_authorized = FALSE;
+        if (polkit_authorization_db_foreach_for_uid (authdb,
+                                                     cd.session_uid, 
+                                                     _check_auth_for_session,
+                                                     &cd,
+                                                     NULL)) {
+                *out_is_authorized = TRUE;
+        }
+
+        return ret;
+}
+
+typedef struct {
+        char *action_id;
+        uid_t caller_uid; 
+        pid_t caller_pid;
+        polkit_uint64_t caller_pid_start_time;
+        char *session_objpath;
+        PolKitCaller *caller;
+} CheckData;
+
+static polkit_bool_t 
+_check_auth_for_caller (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
+{
+        gboolean ret;
+        pid_t caller_pid;
+        polkit_uint64_t caller_pid_start_time;
+        CheckData *cd = (CheckData *) user_data;
+        PolKitAuthorizationConstraint *constraint;
+
+        ret = FALSE;
+
+        if (strcmp (polkit_authorization_get_action_id (auth), cd->action_id) != 0)
+                goto no_match;
+
+        constraint = polkit_authorization_get_constraint (auth);
+        if (!polkit_authorization_constraint_check_caller (constraint, cd->caller))
+                goto no_match;
+
+        switch (polkit_authorization_get_scope (auth))
+        {
+        case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
+                if (!polkit_authorization_scope_process_get_pid (auth, &caller_pid, &caller_pid_start_time))
+                        goto no_match;
+                if (!(caller_pid == cd->caller_pid && caller_pid_start_time == cd->caller_pid_start_time))
+                        goto no_match;
+                break;
+
+        case POLKIT_AUTHORIZATION_SCOPE_SESSION:
+                if (cd->session_objpath == NULL)
+                        goto no_match;
+                if (strcmp (polkit_authorization_scope_session_get_ck_objref (auth), cd->session_objpath) != 0)
+                        goto no_match;
+                break;
+
+        case POLKIT_AUTHORIZATION_SCOPE_ALWAYS:
+                break;
+        }
+
+        ret = TRUE;
+
+no_match:
+        return ret;
 }
 
 /**
@@ -206,9 +728,203 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
                                               PolKitCaller          *caller,
                                               polkit_bool_t         *out_is_authorized)
 {
+        PolKitSession *session;
+        polkit_bool_t ret;
+        CheckData cd;
+
+        ret = FALSE;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (action != NULL, FALSE);
+        g_return_val_if_fail (caller != NULL, FALSE);
         g_return_val_if_fail (out_is_authorized != NULL, FALSE);
-        *out_is_authorized = _polkit_grantdb_check_can_caller_do_action (action, caller);
-        return TRUE;
+
+        if (!polkit_action_get_action_id (action, &cd.action_id))
+                return FALSE;
+
+        if (!polkit_caller_get_pid (caller, &cd.caller_pid))
+                return FALSE;
+
+        if (!polkit_caller_get_uid (caller, &cd.caller_uid))
+                return FALSE;
+
+        cd.caller = caller;
+
+        cd.caller_pid_start_time = get_start_time_for_pid (cd.caller_pid);
+        if (cd.caller_pid_start_time == 0)
+                return FALSE;
+
+        /* Caller does not _have_ to be member of a session */
+        cd.session_objpath = NULL;
+        if (polkit_caller_get_ck_session (caller, &session) && session != NULL) {
+                if (!polkit_session_get_ck_objref (session, &cd.session_objpath))
+                        cd.session_objpath = NULL;
+        }
+
+        ret = TRUE;
+
+        *out_is_authorized = FALSE;
+        if (polkit_authorization_db_foreach_for_uid (authdb,
+                                                     cd.caller_uid, 
+                                                     _check_auth_for_caller,
+                                                     &cd,
+                                                     NULL)) {
+                *out_is_authorized = TRUE;
+        }
+
+        return ret;
+}
+
+static polkit_bool_t
+_write_to_fd (int fd, const char *str, ssize_t str_len)
+{
+        polkit_bool_t ret;
+        ssize_t written;
+
+        ret = FALSE;
+
+        written = 0;
+        while (written < str_len) {
+                ssize_t ret;
+                ret = write (fd, str + written, str_len - written);
+                if (ret < 0) {
+                        if (errno == EAGAIN || errno == EINTR) {
+                                continue;
+                        } else {
+                                goto out;
+                        }
+                }
+                written += ret;
+        }
+
+        ret = TRUE;
+
+out:
+        return ret;
+}
+
+/* this function is also used by polkit-dbus/polkit-explicit-grant-helper */
+extern polkit_bool_t _polkit_authorization_db_auth_file_add (const char *root, polkit_bool_t transient, uid_t uid, char *str_to_add);
+
+polkit_bool_t 
+_polkit_authorization_db_auth_file_add (const char *root, polkit_bool_t transient, uid_t uid, char *str_to_add)
+{
+        int fd;
+        char *contents;
+        gsize contents_size;
+        char *path;
+        char *path_tmp;
+        GError *error;
+        polkit_bool_t ret;
+        struct stat statbuf;
+        struct passwd *pw;
+
+        ret = FALSE;
+        path = NULL;
+        path_tmp = NULL;
+        contents = NULL;
+
+        pw = getpwuid (uid);
+        if (pw == NULL) {
+                g_warning ("cannot lookup user name for uid %d\n", uid);
+                goto out;
+        }
+
+        path = g_strdup_printf ("%s/user-%s.auths", root, pw->pw_name);
+        path_tmp = g_strdup_printf ("%s.XXXXXX", path);
+
+        if (stat (path, &statbuf) != 0 && errno == ENOENT) {
+                //fprintf (stderr, "path=%s does not exist (egid=%d): %m!\n", path, getegid ());
+
+                g_free (path_tmp);
+                path_tmp = path;
+                path = NULL;
+
+                /* Write a nice blurb if we're creating the file for the first time */
+
+                contents = g_strdup_printf (
+                        "# This file lists authorizations for user %s\n"
+                        "%s"
+                        "# \n"
+                        "# File format may change at any time; do not rely on it. To manage\n"
+                        "# authorizations use polkit-auth(1) instead.\n"
+                        "\n",
+                        pw->pw_name,
+                        transient ? "# (these are temporary and will be removed on the next system boot)\n" : "");
+                contents_size = strlen (contents);
+        } else {
+                error = NULL;
+                if (!g_file_get_contents (path, &contents, &contents_size, &error)) {
+                        g_warning ("Cannot read authorizations file %s: %s", path, error->message);
+                        g_error_free (error);
+                        goto out;
+                }
+        }
+
+        if (path != NULL) {
+                fd = mkstemp (path_tmp);
+                if (fd < 0) {
+                        fprintf (stderr, "Cannot create file '%s': %m\n", path_tmp);
+                        goto out;
+                }
+                if (fchmod (fd, 0464) != 0) {
+                        fprintf (stderr, "Cannot change mode for '%s' to 0460: %m\n", path_tmp);
+                        close (fd);
+                        unlink (path_tmp);
+                        goto out;
+                }
+        } else {
+                fd = open (path_tmp, O_RDWR|O_CREAT, 0464);
+                if (fd < 0) {
+                        fprintf (stderr, "Cannot create file '%s': %m\n", path_tmp);
+                        goto out;
+                }
+        }
+
+        if (!_write_to_fd (fd, contents, contents_size)) {
+                g_warning ("Cannot write to temporary authorizations file %s: %m", path_tmp);
+                close (fd);
+                if (unlink (path_tmp) != 0) {
+                        g_warning ("Cannot unlink %s: %m", path_tmp);
+                }
+                goto out;
+        }
+        if (!_write_to_fd (fd, str_to_add, strlen (str_to_add))) {
+                g_warning ("Cannot write to temporary authorizations file %s: %m", path_tmp);
+                close (fd);
+                if (unlink (path_tmp) != 0) {
+                        g_warning ("Cannot unlink %s: %m", path_tmp);
+                }
+                goto out;
+        }
+        close (fd);
+
+        if (path != NULL) {
+                if (rename (path_tmp, path) != 0) {
+                        g_warning ("Cannot rename %s to %s: %m", path_tmp, path);
+                        if (unlink (path_tmp) != 0) {
+                                g_warning ("Cannot unlink %s: %m", path_tmp);
+                        }
+                        goto out;
+                }
+        }
+
+        /* trigger a reload */
+        if (utimes (PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload", NULL) != 0) {
+                g_warning ("Error updating access+modification time on file '%s': %m\n", 
+                           PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload");
+        }
+
+        ret = TRUE;
+
+out:
+        if (contents != NULL)
+                g_free (contents);
+        if (path != NULL)
+                g_free (path);
+        if (path_tmp != NULL)
+                g_free (path_tmp);
+        return ret;
 }
 
 
@@ -217,8 +933,6 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
  * @authdb: the authorization database
  * @action: the action
  * @caller: the caller
- * @how: the value from "defaults" section of the
- * <literal>.policy</literal> file
  * @user_authenticated_as: the user that was authenticated
  *
  * Write an entry to the authorization database to indicate that the
@@ -227,7 +941,9 @@ polkit_authorization_db_is_caller_authorized (PolKitAuthorizationDB *authdb,
  * Note that this function should only be used by
  * <literal>libpolkit-grant</literal> or other sufficiently privileged
  * processes that deals with managing authorizations. It should never
- * be used by mechanisms or applications.
+ * be used by mechanisms or applications. The caller must have
+ * egid=polkituser and umask set so creating files with mode 0460 will
+ * work.
  *
  * Returns: #TRUE if an entry was written to the authorization
  * database, #FALSE if the caller of this function is not sufficiently
@@ -239,11 +955,17 @@ polkit_bool_t
 polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authdb,
                                                     PolKitAction          *action,
                                                     PolKitCaller          *caller,
-                                                    PolKitResult           how,
                                                     uid_t                  user_authenticated_as)
 {
         char *action_id;
+        uid_t caller_uid;
         pid_t caller_pid;
+        char *grant_line;
+        polkit_bool_t ret;
+        polkit_uint64_t pid_start_time;
+        struct timeval now;
+        PolKitAuthorizationConstraint *constraint;
+        char cbuf[256];
 
         g_return_val_if_fail (authdb != NULL, FALSE);
         g_return_val_if_fail (action != NULL, FALSE);
@@ -255,25 +977,57 @@ polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authd
         if (!polkit_caller_get_pid (caller, &caller_pid))
                 return FALSE;
 
-        return _polkit_grantdb_write_pid (action_id, caller_pid);;
+        if (!polkit_caller_get_uid (caller, &caller_uid))
+                return FALSE;
+
+        pid_start_time = get_start_time_for_pid (caller_pid);
+        if (pid_start_time == 0)
+                return FALSE;
+
+        if (gettimeofday (&now, NULL) != 0) {
+                g_warning ("Error calling gettimeofday: %m");
+                return FALSE;
+        }
+
+        constraint = polkit_authorization_constraint_get_from_caller (caller);
+        if (polkit_authorization_constraint_to_string (constraint, cbuf, sizeof (cbuf)) >= sizeof (cbuf)) {
+                g_warning ("buffer for auth constraint is too small");
+                return FALSE;
+        }
+
+        grant_line = g_strdup_printf ("process:%d:%Lu:%s:%Lu:%d:%s\n", 
+                                      caller_pid, 
+                                      pid_start_time, 
+                                      action_id,
+                                      (polkit_uint64_t) now.tv_sec,
+                                      user_authenticated_as,
+                                      cbuf);
+
+        ret = _polkit_authorization_db_auth_file_add (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 
+                                                      TRUE, 
+                                                      caller_uid, 
+                                                      grant_line);
+        g_free (grant_line);
+        return ret;
 }
 
 /**
  * polkit_authorization_db_add_entry_session:
  * @authdb: the authorization database
  * @action: the action
- * @session: the session
- * @how: the value from "defaults" section of the
- * <literal>.policy</literal> file
+ * @caller: the caller
  * @user_authenticated_as: the user that was authenticated
  *
  * Write an entry to the authorization database to indicate that the
- * given session is authorized for the given action.
+ * session for the given caller is authorized for the given action for
+ * the remainer of the session.
  *
  * Note that this function should only be used by
  * <literal>libpolkit-grant</literal> or other sufficiently privileged
  * processes that deals with managing authorizations. It should never
- * be used by mechanisms or applications.
+ * be used by mechanisms or applications. The caller must have
+ * egid=polkituser and umask set so creating files with mode 0460 will
+ * work.
  *
  * Returns: #TRUE if an entry was written to the authorization
  * database, #FALSE if the caller of this function is not sufficiently
@@ -284,33 +1038,66 @@ polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authd
 polkit_bool_t
 polkit_authorization_db_add_entry_session          (PolKitAuthorizationDB *authdb,
                                                     PolKitAction          *action,
-                                                    PolKitSession         *session,
-                                                    PolKitResult           how,
+                                                    PolKitCaller          *caller,
                                                     uid_t                  user_authenticated_as)
 {
+        uid_t session_uid;
         char *action_id;
+        char *grant_line;
+        PolKitSession *session;
         char *session_objpath;
+        polkit_bool_t ret;
+        struct timeval now;
+        PolKitAuthorizationConstraint *constraint;
+        char cbuf[256];
 
         g_return_val_if_fail (authdb != NULL, FALSE);
         g_return_val_if_fail (action != NULL, FALSE);
-        g_return_val_if_fail (session != NULL, FALSE);
+        g_return_val_if_fail (caller != NULL, FALSE);
 
         if (!polkit_action_get_action_id (action, &action_id))
                 return FALSE;
 
+        if (!polkit_caller_get_ck_session (caller, &session))
+                return FALSE;
+
         if (!polkit_session_get_ck_objref (session, &session_objpath))
                 return FALSE;
 
-        return _polkit_grantdb_write_keep_session (action_id, session_objpath);;
+        if (!polkit_session_get_uid (session, &session_uid))
+                return FALSE;
+
+        constraint = polkit_authorization_constraint_get_from_caller (caller);
+        if (polkit_authorization_constraint_to_string (constraint, cbuf, sizeof (cbuf)) >= sizeof (cbuf)) {
+                g_warning ("buffer for auth constraint is too small");
+                return FALSE;
+        }
+
+        if (gettimeofday (&now, NULL) != 0) {
+                g_warning ("Error calling gettimeofday: %m");
+                return FALSE;
+        }
+
+        grant_line = g_strdup_printf ("session:%s:%s:%Lu:%d:%s\n", 
+                                      session_objpath,
+                                      action_id,
+                                      (polkit_uint64_t) now.tv_sec,
+                                      user_authenticated_as,
+                                      cbuf);
+
+        ret = _polkit_authorization_db_auth_file_add (PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 
+                                                      TRUE, 
+                                                      session_uid, 
+                                                      grant_line);
+        g_free (grant_line);
+        return ret;
 }
 
 /**
  * polkit_authorization_db_add_entry_always:
  * @authdb: the authorization database
  * @action: the action
- * @uid: the user
- * @how: the value from "defaults" section of the
- * <literal>.policy</literal> file
+ * @caller: the caller
  * @user_authenticated_as: the user that was authenticated
  *
  * Write an entry to the authorization database to indicate that the
@@ -319,7 +1106,9 @@ polkit_authorization_db_add_entry_session          (PolKitAuthorizationDB *authd
  * Note that this function should only be used by
  * <literal>libpolkit-grant</literal> or other sufficiently privileged
  * processes that deals with managing authorizations. It should never
- * be used by mechanisms or applications.
+ * be used by mechanisms or applications. The caller must have
+ * egid=polkituser and umask set so creating files with mode 0460 will
+ * work.
  *
  * Returns: #TRUE if an entry was written to the authorization
  * database, #FALSE if the caller of this function is not sufficiently
@@ -330,17 +1119,273 @@ polkit_authorization_db_add_entry_session          (PolKitAuthorizationDB *authd
 polkit_bool_t
 polkit_authorization_db_add_entry_always           (PolKitAuthorizationDB *authdb,
                                                     PolKitAction          *action,
-                                                    uid_t                  uid,
-                                                    PolKitResult           how,
+                                                    PolKitCaller          *caller,
                                                     uid_t                  user_authenticated_as)
 {
+        uid_t uid;
         char *action_id;
+        char *grant_line;
+        polkit_bool_t ret;
+        struct timeval now;
+        PolKitAuthorizationConstraint *constraint;
+        char cbuf[256];
 
         g_return_val_if_fail (authdb != NULL, FALSE);
         g_return_val_if_fail (action != NULL, FALSE);
+        g_return_val_if_fail (caller != NULL, FALSE);
+
+        if (!polkit_caller_get_uid (caller, &uid))
+                return FALSE;
 
         if (!polkit_action_get_action_id (action, &action_id))
                 return FALSE;
 
-        return _polkit_grantdb_write_keep_always (action_id, uid);
+        if (gettimeofday (&now, NULL) != 0) {
+                g_warning ("Error calling gettimeofday: %m");
+                return FALSE;
+        }
+
+        constraint = polkit_authorization_constraint_get_from_caller (caller);
+        if (polkit_authorization_constraint_to_string (constraint, cbuf, sizeof (cbuf)) >= sizeof (cbuf)) {
+                g_warning ("buffer for auth constraint is too small");
+                return FALSE;
+        }
+
+        grant_line = g_strdup_printf ("always:%s:%Lu:%d:%s\n", 
+                                      action_id,
+                                      (polkit_uint64_t) now.tv_sec,
+                                      user_authenticated_as,
+                                      cbuf);
+
+        ret = _polkit_authorization_db_auth_file_add (PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", 
+                                                      FALSE, 
+                                                      uid, 
+                                                      grant_line);
+        g_free (grant_line);
+        return ret;
+}
+
+
+extern const char *_polkit_authorization_get_authfile_entry (PolKitAuthorization *auth);
+
+/**
+ * polkit_authorization_db_revoke_entry:
+ * @authdb: the authorization database
+ * @auth: the authorization to revoke
+ * @error: return location for error
+ *
+ * Removes an authorization from the authorization database. This uses
+ * a privileged helper /usr/libexec/polkit-revoke-helper.
+ *
+ * Returns: #TRUE if the authorization was revoked, #FALSE otherwise and error is set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
+                                      PolKitAuthorization   *auth,
+                                      PolKitError           **error)
+{
+        GError *g_error;
+        char *helper_argv[] = {PACKAGE_LIBEXEC_DIR "/polkit-revoke-helper", "", NULL, NULL, NULL};
+        const char *auth_file_entry;
+        gboolean ret;
+        gint exit_status;
+
+        ret = FALSE;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (auth != NULL, FALSE);
+
+        auth_file_entry = _polkit_authorization_get_authfile_entry (auth);
+        //g_debug ("should delete line '%s'", auth_file_entry);
+
+        helper_argv[1] = (char *) auth_file_entry;
+        helper_argv[2] = "uid";
+        helper_argv[3] = g_strdup_printf ("%d", polkit_authorization_get_uid (auth));
+
+        g_error = NULL;
+        if (!g_spawn_sync (NULL,         /* const gchar *working_directory */
+                           helper_argv,  /* gchar **argv */
+                           NULL,         /* gchar **envp */
+                           0,            /* GSpawnFlags flags */
+                           NULL,         /* GSpawnChildSetupFunc child_setup */
+                           NULL,         /* gpointer user_data */
+                           NULL,         /* gchar **standard_output */
+                           NULL,         /* gchar **standard_error */
+                           &exit_status, /* gint *exit_status */
+                           &g_error)) {  /* GError **error */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Error spawning revoke helper: %s",
+                                        g_error->message);
+                g_error_free (g_error);
+                goto out;
+        }
+
+        if (!WIFEXITED (exit_status)) {
+                g_warning ("Revoke helper crashed!");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Revoke helper crashed!");
+                goto out;
+        } else if (WEXITSTATUS(exit_status) != 0) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS, 
+                                        "uid %d is not authorized to revoke authorizations from uid %d (requires org.freedesktop.policykit.revoke)",
+                                        getuid (), polkit_authorization_get_uid (auth));
+        } else {
+                ret = TRUE;
+        }
+        
+out:
+        g_free (helper_argv[3]);
+        return ret;
+}
+
+typedef struct {
+        char *action_id;
+        PolKitAuthorizationConstraint  *constraint;
+} CheckDataGrant;
+
+static polkit_bool_t 
+_check_auth_for_grant (PolKitAuthorizationDB *authdb, PolKitAuthorization *auth, void *user_data)
+{
+        uid_t pimp;
+        polkit_bool_t ret;
+        CheckDataGrant *cd = (CheckDataGrant *) user_data;
+
+        ret = FALSE;
+
+        if (strcmp (polkit_authorization_get_action_id (auth), cd->action_id) != 0)
+                goto no_match;
+
+        if (!polkit_authorization_was_granted_explicitly (auth, &pimp))
+                goto no_match;
+
+        if (!polkit_authorization_constraint_equal (polkit_authorization_get_constraint (auth), cd->constraint))
+                goto no_match;
+
+        ret = TRUE;
+
+no_match:
+        return ret;
+}
+
+/**
+ * polkit_authorization_db_grant_to_uid:
+ * @authdb: authorization database
+ * @action: action
+ * @uid: uid to grant to
+ * @constraint: what constraint to put on the authorization
+ * @error: return location for error
+ *
+ * Grants an authorization to a user for a specific action. This
+ * requires the org.freedesktop.policykit.grant authorization.
+ *
+ * Returns: #TRUE if the authorization was granted, #FALSE otherwise
+ * and error will be set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t 
+polkit_authorization_db_grant_to_uid (PolKitAuthorizationDB          *authdb,
+                                      PolKitAction                   *action,
+                                      uid_t                           uid,
+                                      PolKitAuthorizationConstraint  *constraint,
+                                      PolKitError                   **error)
+{
+        GError *g_error;
+        char *helper_argv[6] = {PACKAGE_LIBEXEC_DIR "/polkit-explicit-grant-helper", NULL, NULL, NULL, NULL, NULL};
+        gboolean ret;
+        gint exit_status;
+        char cbuf[256];
+        CheckDataGrant cd;
+
+        ret = FALSE;
+
+        g_return_val_if_fail (authdb != NULL, FALSE);
+        g_return_val_if_fail (action != NULL, FALSE);
+        g_return_val_if_fail (constraint != NULL, FALSE);
+
+        if (!polkit_action_get_action_id (action, &(cd.action_id))) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Given action does not have action_id set");
+                goto out;
+        }
+
+        if (polkit_authorization_constraint_to_string (constraint, cbuf, sizeof (cbuf)) >= sizeof (cbuf)) {
+                g_warning ("buffer for auth constraint is too small");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "buffer for auth constraint is too small");
+                goto out;
+        }
+
+        /* check if we have the auth already */
+        cd.constraint = constraint;
+        if (!polkit_authorization_db_foreach_for_uid (authdb,
+                                                      uid, 
+                                                      _check_auth_for_grant,
+                                                      &cd,
+                                                      error)) {
+                /* happens if caller can't read auths of target user */
+                if (error != NULL && polkit_error_is_set (*error)) {
+                        goto out;
+                }
+        } else {
+                /* so it did exist.. */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS, 
+                                        "An authorization for uid %d for the action %s with constraint '%s' already exists",
+                                        uid, cd.action_id, cbuf);
+                goto out;
+        }
+
+
+        helper_argv[1] = cd.action_id;
+        helper_argv[2] = cbuf;
+        helper_argv[3] = "uid";
+        helper_argv[4] = g_strdup_printf ("%d", uid);
+        helper_argv[5] = NULL;
+
+        g_error = NULL;
+        if (!g_spawn_sync (NULL,         /* const gchar *working_directory */
+                           helper_argv,  /* gchar **argv */
+                           NULL,         /* gchar **envp */
+                           0,            /* GSpawnFlags flags */
+                           NULL,         /* GSpawnChildSetupFunc child_setup */
+                           NULL,         /* gpointer user_data */
+                           NULL,         /* gchar **standard_output */
+                           NULL,         /* gchar **standard_error */
+                           &exit_status, /* gint *exit_status */
+                           &g_error)) {  /* GError **error */
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Error spawning explicit grant helper: %s",
+                                        g_error->message);
+                g_error_free (g_error);
+                goto out;
+        }
+
+        if (!WIFEXITED (exit_status)) {
+                g_warning ("Explicit grant helper crashed!");
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_GENERAL_ERROR, 
+                                        "Explicit grant helper crashed!");
+                goto out;
+        } else if (WEXITSTATUS(exit_status) != 0) {
+                polkit_error_set_error (error, 
+                                        POLKIT_ERROR_NOT_AUTHORIZED_TO_GRANT_AUTHORIZATION, 
+                                        "uid %d is not authorized to grant authorization for action %s to uid %d (requires org.freedesktop.policykit.grant)",
+                                        getuid (), cd.action_id, uid);
+        } else {
+                ret = TRUE;
+        }
+        
+out:
+        g_free (helper_argv[4]);
+        return ret;
+
 }
index c7823e6..c6fd558 100644 (file)
@@ -36,6 +36,7 @@
 #include <polkit/polkit-result.h>
 #include <polkit/polkit-caller.h>
 #include <polkit/polkit-session.h>
+#include <polkit/polkit-error.h>
 
 POLKIT_BEGIN_DECLS
 
@@ -60,26 +61,71 @@ polkit_bool_t polkit_authorization_db_is_caller_authorized (PolKitAuthorizationD
                                                             PolKitCaller          *caller,
                                                             polkit_bool_t         *out_is_authorized);
 
-
+/**
+ * PolKitAuthorizationDBForeach:
+ * @authdb: authorization database
+ * @auth: authorization; user shall not unref this object. Unless
+ * reffed by the user it will be destroyed when the callback function
+ * returns.
+ * @user_data: user data passed
+ *
+ * Type of callback function for iterating over authorizations.
+ *
+ * Returns: pass #TRUE to stop iterating
+ */
+typedef polkit_bool_t (*PolKitAuthorizationDBForeach) (PolKitAuthorizationDB *authdb,
+                                                       PolKitAuthorization   *auth, 
+                                                       void                  *user_data);
+
+polkit_bool_t polkit_authorization_db_foreach (PolKitAuthorizationDB       *authdb,
+                                               PolKitAuthorizationDBForeach cb,
+                                               void                        *user_data,
+                                               PolKitError                **error);
+
+polkit_bool_t polkit_authorization_db_foreach_for_uid (PolKitAuthorizationDB       *authdb,
+                                                       uid_t                        uid,
+                                                       PolKitAuthorizationDBForeach cb,
+                                                       void                        *user_data,
+                                                       PolKitError                **error);
+
+polkit_bool_t polkit_authorization_db_foreach_for_action (PolKitAuthorizationDB       *authdb,
+                                                          PolKitAction                *action,
+                                                          PolKitAuthorizationDBForeach cb,
+                                                          void                        *user_data,
+                                                          PolKitError                **error);
+
+polkit_bool_t polkit_authorization_db_foreach_for_action_for_uid (PolKitAuthorizationDB       *authdb,
+                                                                  PolKitAction                *action,
+                                                                  uid_t                        uid,
+                                                                  PolKitAuthorizationDBForeach cb,
+                                                                  void                        *user_data,
+                                                                  PolKitError                **error);
 
 polkit_bool_t polkit_authorization_db_add_entry_process          (PolKitAuthorizationDB *authdb,
                                                                   PolKitAction          *action,
                                                                   PolKitCaller          *caller,
-                                                                  PolKitResult           how,
                                                                   uid_t                  user_authenticated_as);
 
 polkit_bool_t polkit_authorization_db_add_entry_session          (PolKitAuthorizationDB *authdb,
                                                                   PolKitAction          *action,
-                                                                  PolKitSession         *session,
-                                                                  PolKitResult           how,
+                                                                  PolKitCaller          *caller,
                                                                   uid_t                  user_authenticated_as);
 
 polkit_bool_t polkit_authorization_db_add_entry_always           (PolKitAuthorizationDB *authdb,
                                                                   PolKitAction          *action,
-                                                                  uid_t                  uid,
-                                                                  PolKitResult           how,
+                                                                  PolKitCaller          *caller,
                                                                   uid_t                  user_authenticated_as);
 
+polkit_bool_t polkit_authorization_db_grant_to_uid           (PolKitAuthorizationDB          *authdb,
+                                                              PolKitAction                   *action,
+                                                              uid_t                           uid,
+                                                              PolKitAuthorizationConstraint  *constraint,
+                                                              PolKitError                   **error);
+
+polkit_bool_t polkit_authorization_db_revoke_entry (PolKitAuthorizationDB *authdb,
+                                                    PolKitAuthorization *auth,
+                                                    PolKitError **error);
+
 
 POLKIT_END_DECLS
 
index 1de9ef8..beb0394 100644 (file)
 struct _PolKitAuthorization
 {
         int refcount;
+
+        char *entry_in_auth_file;
+
+        PolKitAuthorizationScope scope;
+        PolKitAuthorizationConstraint *constraint;
+
+        char *action_id;
+        uid_t uid;
+        time_t when;
+        uid_t authenticated_as_uid;
+
+        pid_t pid;
+        polkit_uint64_t pid_start_time;
+
+        polkit_bool_t explicitly_granted;
+        uid_t explicitly_granted_by;
+
+        char *session_id;
 };
 
+extern PolKitAuthorization *_polkit_authorization_new_for_uid (const char *entry_in_auth_file, uid_t uid);
+
+extern const char *_polkit_authorization_get_authfile_entry (PolKitAuthorization *auth);
+
+const char *
+_polkit_authorization_get_authfile_entry (PolKitAuthorization *auth)
+{
+        g_return_val_if_fail (auth != NULL, NULL);
+        return auth->entry_in_auth_file;
+}
+
+PolKitAuthorization *
+_polkit_authorization_new_for_uid (const char *entry_in_auth_file, uid_t uid)
+{
+        char **t;
+        guint num_t;
+        char *ep;
+        PolKitAuthorization *auth;
+        int n;
+
+        g_return_val_if_fail (entry_in_auth_file != NULL, NULL);
+
+        auth = g_new0 (PolKitAuthorization, 1);
+        auth->refcount = 1;
+        auth->entry_in_auth_file = g_strdup (entry_in_auth_file);
+        auth->uid = uid;
+
+        t = g_strsplit (entry_in_auth_file, ":", 0);
+        num_t = g_strv_length (t);
+
+/*
+ * pid:
+ *       grant_line = g_strdup_printf ("process:%d:%Lu:%s:%Lu:%d:%s\n", 
+ *                                     caller_pid, 
+ *                                     pid_start_time, 
+ *                                     action_id,
+ *                                     (polkit_uint64_t) now.tv_sec,
+ *                                     user_authenticated_as,
+ *                                     cbuf);
+ */
+        n = 1;
+
+        if (strcmp (t[0], "process") == 0) {
+                if (num_t != 7)
+                        goto error;
+
+                auth->scope = POLKIT_AUTHORIZATION_SCOPE_PROCESS;
+
+                auth->pid = strtoul (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->pid_start_time = strtoull (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                if (!polkit_action_validate_id (t[n]))
+                        goto error;
+                auth->action_id = g_strdup (t[n++]);
+
+                auth->when = strtoull (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->authenticated_as_uid = strtoul (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->constraint = polkit_authorization_constraint_from_string (t[n++]);
+                if (auth->constraint == NULL)
+                        goto error;
+        }
+/*
+ *        grant_line = g_strdup_printf ("session:%s:%s:%Lu:%s:%d:%s\n", 
+ *                                      session_objpath,
+ *                                      action_id,
+ *                                      (polkit_uint64_t) now.tv_sec,
+ *                                      user_authenticated_as,
+ *                                      cbuf);
+ */
+        else if (strcmp (t[0], "session") == 0) {
+                if (num_t != 6)
+                        goto error;
+
+                auth->scope = POLKIT_AUTHORIZATION_SCOPE_SESSION;
+
+                auth->session_id = g_strdup (t[n++]);
+
+                if (!polkit_action_validate_id (t[n]))
+                        goto error;
+                auth->action_id = g_strdup (t[n++]);
+
+                auth->when = strtoull (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->authenticated_as_uid = strtoul (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->constraint = polkit_authorization_constraint_from_string (t[n++]);
+                if (auth->constraint == NULL)
+                        goto error;
+        }
+
+/*
+ * always:
+ *        grant_line = g_strdup_printf ("always:%s:%Lu:%s:%d:%s\n", 
+ *                                      action_id,
+ *                                      (polkit_uint64_t) now.tv_sec,
+ *                                      user_authenticated_as,
+ *                                      cbuf);
+ *
+ */
+        else if (strcmp (t[0], "always") == 0) {
+                if (num_t != 5)
+                        goto error;
+
+                auth->scope = POLKIT_AUTHORIZATION_SCOPE_ALWAYS;
+
+                if (!polkit_action_validate_id (t[n]))
+                        goto error;
+                auth->action_id = g_strdup (t[n++]);
+
+                auth->when = strtoull (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->authenticated_as_uid = strtoul (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->constraint = polkit_authorization_constraint_from_string (t[n++]);
+                if (auth->constraint == NULL)
+                        goto error;
+        }
+/*
+ * grant:
+ *                     "grant:%d:%s:%Lu:%d:%s\n",
+ *                     action_id,
+ *                     (polkit_uint64_t) now.tv_sec,
+ *                     invoking_uid,
+ *                     authc_str) >= (int) sizeof (grant_line)) {
+ *
+ */
+        else if (strcmp (t[0], "grant") == 0) {
+
+                if (num_t != 5)
+                        goto error;
+
+                auth->scope = POLKIT_AUTHORIZATION_SCOPE_ALWAYS;
+                auth->explicitly_granted = TRUE;
+
+                if (!polkit_action_validate_id (t[n]))
+                        goto error;
+                auth->action_id = g_strdup (t[n++]);
+
+                auth->when = strtoull (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->explicitly_granted_by = strtoul (t[n++], &ep, 10);
+                if (*ep != '\0')
+                        goto error;
+
+                auth->constraint = polkit_authorization_constraint_from_string (t[n++]);
+                if (auth->constraint == NULL)
+                        goto error;
+
+        } else {
+                goto error;
+        }
+
+        g_strfreev (t);
+        return auth;
+
+error:
+        g_warning ("Error parsing token %d in '%s'", n, entry_in_auth_file);
+        polkit_authorization_unref (auth);
+        g_strfreev (t);
+        return NULL;
+}
+
 /**
  * polkit_authorization_ref:
- * @authorization: the authorization object
+ * @auth: the authorization object
  * 
  * Increase reference count.
  * 
@@ -77,16 +278,16 @@ struct _PolKitAuthorization
  * Since: 0.7
  **/
 PolKitAuthorization *
-polkit_authorization_ref (PolKitAuthorization *authorization)
+polkit_authorization_ref (PolKitAuthorization *auth)
 {
-        g_return_val_if_fail (authorization != NULL, authorization);
-        authorization->refcount++;
-        return authorization;
+        g_return_val_if_fail (auth != NULL, auth);
+        auth->refcount++;
+        return auth;
 }
 
 /**
  * polkit_authorization_unref:
- * @authorization: the authorization object
+ * @auth: the authorization object
  * 
  * Decreases the reference count of the object. If it becomes zero,
  * the object is freed. Before freeing, reference counts on embedded
@@ -95,33 +296,45 @@ polkit_authorization_ref (PolKitAuthorization *authorization)
  * Since: 0.7
  **/
 void
-polkit_authorization_unref (PolKitAuthorization *authorization)
+polkit_authorization_unref (PolKitAuthorization *auth)
 {
-        g_return_if_fail (authorization != NULL);
-        authorization->refcount--;
-        if (authorization->refcount > 0) 
+        g_return_if_fail (auth != NULL);
+        auth->refcount--;
+        if (auth->refcount > 0) 
                 return;
-        g_free (authorization);
+
+        g_free (auth->entry_in_auth_file);
+        g_free (auth->action_id);
+        g_free (auth->session_id);
+        if (auth->constraint != NULL)
+                polkit_authorization_constraint_unref (auth->constraint);
+        g_free (auth);
 }
 
 /**
  * polkit_authorization_debug:
- * @authorization: the object
+ * @auth: the object
  * 
  * Print debug details
  *
  * Since: 0.7
  **/
 void
-polkit_authorization_debug (PolKitAuthorization *authorization)
+polkit_authorization_debug (PolKitAuthorization *auth)
 {
-        g_return_if_fail (authorization != NULL);
-        _pk_debug ("PolKitAuthorization: refcount=%d", authorization->refcount);
+        g_return_if_fail (auth != NULL);
+        _pk_debug ("PolKitAuthorization: refcount=%d", auth->refcount);
+        _pk_debug (" scope          = %d",  auth->scope);
+        _pk_debug (" pid            = %d",  auth->pid);
+        _pk_debug (" pid_start_time = %Lu", auth->pid_start_time);
+        _pk_debug (" action_id      = %s",  auth->action_id);
+        _pk_debug (" when           = %Lu", (polkit_uint64_t) auth->when);
+        _pk_debug (" auth_as_uid    = %d",  auth->authenticated_as_uid);
 }
 
 /**
  * polkit_authorization_validate:
- * @authorization: the object
+ * @auth: the object
  * 
  * Validate the object
  * 
@@ -130,51 +343,55 @@ polkit_authorization_debug (PolKitAuthorization *authorization)
  * Since: 0.7
  **/
 polkit_bool_t
-polkit_authorization_validate (PolKitAuthorization *authorization)
+polkit_authorization_validate (PolKitAuthorization *auth)
 {
-        g_return_val_if_fail (authorization != NULL, FALSE);
+        g_return_val_if_fail (auth != NULL, FALSE);
 
         return TRUE;
 }
 
 /**
  * polkit_authorization_get_action_id:
- * @authorization: the object
+ * @auth: the object
  *
  * Get the action this authorization is for
  *
- * Returns: the #PolKitAction object. Caller should not unref the
- * object; it is owned by the #PolKitAuthorization instance and will
- * by unreffed when that object is unreffed.
+ * Returns: the action id. Caller should not free this string.
  *
  * Since: 0.7
  */ 
-PolKitAction *
-polkit_authorization_get_action_id (PolKitAuthorization *authorization)
+const char *
+polkit_authorization_get_action_id (PolKitAuthorization *auth)
 {
-        return NULL;
+        g_return_val_if_fail (auth != NULL, NULL);
+
+        return auth->action_id;
 }
 
 /**
  * polkit_authorization_get_scope:
- * @authorization: the object
+ * @auth: the object
  *
  * Get the scope of the authorization; e.g. whether it's confined to a
- * single process, a single session or can be retained indefinitely.
+ * single process, a single session or can be retained
+ * indefinitely. Also keep in mind that an authorization is subject to
+ * constraints, see polkit_authorization_get_constraint() for details.
  *
  * Returns: the scope
  *
  * Since: 0.7
  */ 
 PolKitAuthorizationScope
-polkit_authorization_get_scope (PolKitAuthorization *authorization)
+polkit_authorization_get_scope (PolKitAuthorization *auth)
 {
-        return 0;
+        g_return_val_if_fail (auth != NULL, 0);
+
+        return auth->scope;
 }
 
 /**
  * polkit_authorization_scope_process_get_pid:
- * @authorization: the object
+ * @auth: the object
  * @out_pid: return location
  * @out_pid_start_time: return location
  *
@@ -191,35 +408,44 @@ polkit_authorization_get_scope (PolKitAuthorization *authorization)
  * Since: 0.7
  */ 
 polkit_bool_t
-polkit_authorization_scope_process_get_pid (PolKitAuthorization *authorization
+polkit_authorization_scope_process_get_pid (PolKitAuthorization *auth, 
                                             pid_t *out_pid, 
                                             polkit_uint64_t *out_pid_start_time)
 {
-        return FALSE;
+        g_return_val_if_fail (auth != NULL, FALSE);
+        g_return_val_if_fail (out_pid != NULL, FALSE);
+        g_return_val_if_fail (out_pid_start_time != NULL, FALSE);
+        g_return_val_if_fail (auth->scope == POLKIT_AUTHORIZATION_SCOPE_PROCESS, FALSE);
+
+        *out_pid = auth->pid;
+        *out_pid_start_time = auth->pid_start_time;
+
+        return TRUE;
 }
 
 /**
  * polkit_authorization_scope_session_get_ck_objref:
- * @authorization: the object
- * @out_ck_session_objref: return location
+ * @auth: the object
  *
  * Gets the ConsoleKit object path for the session the authorization
  * is confined to.
  *
- * Returns: #TRUE if information was returned
+ * Returns: #NULL if scope wasn't session
  *
  * Since: 0.7
  */ 
-polkit_bool_t
-polkit_authorization_scope_session_get_ck_objref (PolKitAuthorization *authorization, 
-                                                  char **out_ck_session_objref)
+const char *
+polkit_authorization_scope_session_get_ck_objref (PolKitAuthorization *auth)
 {
-        return FALSE;
+        g_return_val_if_fail (auth != NULL, FALSE);
+        g_return_val_if_fail (auth->scope == POLKIT_AUTHORIZATION_SCOPE_SESSION, FALSE);
+
+        return auth->session_id;
 }
 
 /**
  * polkit_authorization_get_uid:
- * @authorization: the object
+ * @auth: the object
  *
  * Gets the UNIX user id for the user the authorization is confined
  * to.
@@ -229,14 +455,15 @@ polkit_authorization_scope_session_get_ck_objref (PolKitAuthorization *authoriza
  * Since: 0.7
  */ 
 uid_t
-polkit_authorization_get_uid (PolKitAuthorization *authorization)
+polkit_authorization_get_uid (PolKitAuthorization *auth)
 {
-        return 0;
+        g_return_val_if_fail (auth != NULL, 0);
+        return auth->uid;
 }
 
 /**
  * polkit_authorization_get_time_of_grant:
- * @authorization: the object
+ * @auth: the object
  *
  * Returns the point in time the authorization was granted. The value
  * is UNIX time, e.g. number of seconds since the Epoch Jan 1, 1970
@@ -247,21 +474,21 @@ polkit_authorization_get_uid (PolKitAuthorization *authorization)
  * Since: 0.7
  */ 
 time_t
-polkit_authorization_get_time_of_grant (PolKitAuthorization *authorization)
+polkit_authorization_get_time_of_grant (PolKitAuthorization *auth)
 {
-        return 0;
+        g_return_val_if_fail (auth != NULL, 0);
+        return auth->when;
 }
 
 /**
  * polkit_authorization_was_granted_via_defaults:
- * @authorization: the object
- * @out_how: return location
+ * @auth: the object
  * @out_user_authenticated_as: return location
  *
  * Determine if the authorization was obtained by the user by
  * authenticating as himself or an administrator via the the
  * "defaults" section in the <literal>.policy</literal> file for the
- * action (e.g.  "allow_any", "allow_inactive", "allow_active").
+ * action (e.g.  "allow_any", "allow_inactive", "allow_active"). 
  *
  * Compare with polkit_authorization_was_granted_explicitly() - only
  * one of these functions can return #TRUE.
@@ -272,16 +499,22 @@ polkit_authorization_get_time_of_grant (PolKitAuthorization *authorization)
  * Since: 0.7
  */ 
 polkit_bool_t 
-polkit_authorization_was_granted_via_defaults (PolKitAuthorization *authorization,
-                                               PolKitResult *out_how,
+polkit_authorization_was_granted_via_defaults (PolKitAuthorization *auth,
                                                uid_t *out_user_authenticated_as)
 {
-        return FALSE;
+        g_return_val_if_fail (auth != NULL, FALSE);
+        g_return_val_if_fail (out_user_authenticated_as != NULL, FALSE);
+
+        if (auth->explicitly_granted)
+                return FALSE;
+
+        *out_user_authenticated_as = auth->authenticated_as_uid;
+        return TRUE;
 }
 
 /**
  * polkit_authorization_was_granted_explicitly:
- * @authorization: the object
+ * @auth: the object
  * @out_by_whom: return location
  *
  * Determine if the authorization was explicitly granted by a
@@ -296,8 +529,33 @@ polkit_authorization_was_granted_via_defaults (PolKitAuthorization *authorizatio
  * Since: 0.7
  */ 
 polkit_bool_t 
-polkit_authorization_was_granted_explicitly (PolKitAuthorization *authorization,
+polkit_authorization_was_granted_explicitly (PolKitAuthorization *auth,
                                              uid_t *out_by_whom)
 {
-        return FALSE;
+        g_return_val_if_fail (auth != NULL, FALSE);
+        g_return_val_if_fail (out_by_whom != NULL, FALSE);
+
+        if (!auth->explicitly_granted)
+                return FALSE;
+
+        *out_by_whom = auth->explicitly_granted_by;
+
+        return TRUE;
+}
+
+/**
+ * polkit_authorization_get_constraint:
+ * @auth: the object
+ *
+ * Get the constraint associated with an authorization.
+ *
+ * Returns: The constraint. Caller shall not unref this object.
+ *
+ * Since: 0.7
+ */ 
+PolKitAuthorizationConstraint *
+polkit_authorization_get_constraint (PolKitAuthorization *auth)
+{
+        g_return_val_if_fail (auth != NULL, FALSE);
+        return auth->constraint;
 }
index ab8518d..4f6fe70 100644 (file)
 #include <polkit/polkit-types.h>
 #include <polkit/polkit-action.h>
 #include <polkit/polkit-result.h>
+#include <polkit/polkit-authorization-constraint.h>
 
 POLKIT_BEGIN_DECLS
 
 struct _PolKitAuthorization;
 typedef struct _PolKitAuthorization PolKitAuthorization;
 
-PolKitAuthorization *polkit_authorization_ref            (PolKitAuthorization *authorization);
-void                 polkit_authorization_unref          (PolKitAuthorization *authorization);
+PolKitAuthorization *polkit_authorization_ref            (PolKitAuthorization *auth);
+void                 polkit_authorization_unref          (PolKitAuthorization *auth);
 
-void                 polkit_authorization_debug          (PolKitAuthorization *authorization);
-polkit_bool_t        polkit_authorization_validate       (PolKitAuthorization *authorization);
+void                 polkit_authorization_debug          (PolKitAuthorization *auth);
+polkit_bool_t        polkit_authorization_validate       (PolKitAuthorization *auth);
 
 
 /**
@@ -54,10 +55,10 @@ polkit_bool_t        polkit_authorization_validate       (PolKitAuthorization *a
  * @POLKIT_AUTHORIZATION_SCOPE_SESSION: The authorization is limited
  * for processes originating from a given session
  * @POLKIT_AUTHORIZATION_SCOPE_ALWAYS: The authorization is retained
- * indefinitely. TODO: mention that it's only valid if the defaults
- * for the #PolKitAction is the same.
+ * indefinitely.
  *
- * The scope of an authorization; e.g. how it is confined.
+ * The scope of an authorization; e.g. whether it's limited to a
+ * process, a session or unlimited.
  */
 typedef enum {
         POLKIT_AUTHORIZATION_SCOPE_PROCESS,
@@ -65,28 +66,28 @@ typedef enum {
         POLKIT_AUTHORIZATION_SCOPE_ALWAYS,
 } PolKitAuthorizationScope;
 
-PolKitAction *polkit_authorization_get_action_id (PolKitAuthorization *authorization);
+const char *polkit_authorization_get_action_id (PolKitAuthorization *auth);
 
-uid_t polkit_authorization_get_uid (PolKitAuthorization *authorization);
+uid_t polkit_authorization_get_uid (PolKitAuthorization *auth);
 
-time_t polkit_authorization_get_time_of_grant            (PolKitAuthorization *authorization);
+time_t polkit_authorization_get_time_of_grant            (PolKitAuthorization *auth);
 
+PolKitAuthorizationConstraint *polkit_authorization_get_constraint (PolKitAuthorization *auth);
 
-PolKitAuthorizationScope polkit_authorization_get_scope (PolKitAuthorization *authorization);
+PolKitAuthorizationScope polkit_authorization_get_scope (PolKitAuthorization *auth);
 
-polkit_bool_t polkit_authorization_scope_process_get_pid        (PolKitAuthorization *authorization, 
+
+polkit_bool_t polkit_authorization_scope_process_get_pid        (PolKitAuthorization *auth, 
                                                                  pid_t *out_pid, 
                                                                  polkit_uint64_t *out_pid_start_time);
 
-polkit_bool_t polkit_authorization_scope_session_get_ck_objref  (PolKitAuthorization *authorization, 
-                                                                 char **out_ck_session_objref);
+const char *polkit_authorization_scope_session_get_ck_objref  (PolKitAuthorization *auth);
 
 
-polkit_bool_t polkit_authorization_was_granted_via_defaults  (PolKitAuthorization *authorization,
-                                                              PolKitResult *out_how,
+polkit_bool_t polkit_authorization_was_granted_via_defaults  (PolKitAuthorization *auth,
                                                               uid_t *out_user_authenticated_as);
 
-polkit_bool_t polkit_authorization_was_granted_explicitly  (PolKitAuthorization *authorization,
+polkit_bool_t polkit_authorization_was_granted_explicitly  (PolKitAuthorization *auth,
                                                             uid_t *out_by_whom);
 
 POLKIT_END_DECLS
index 96870d5..0472be7 100644 (file)
@@ -106,7 +106,6 @@ struct _PolKitContext
         int inotify_config_wd;
         int inotify_policy_wd;
         int inotify_grant_perm_wd;
-        int inotify_grant_temp_wd;
 };
 
 /**
@@ -133,22 +132,16 @@ polkit_context_new (void)
  * @error: return location for error
  * 
  * Initializes a new context; loads PolicyKit files from
- * /usr/share/PolicyKit/policy unless the environment variable
- * $POLKIT_POLICY_DIR points to another location.
+ * /usr/share/PolicyKit/policy.
  *
  * Returns: #FALSE if @error was set, otherwise #TRUE
  **/
 polkit_bool_t
 polkit_context_init (PolKitContext *pk_context, PolKitError **error)
 {
-        const char *dirname;
+        g_return_val_if_fail (pk_context != NULL, FALSE);
 
-        dirname = getenv ("POLKIT_POLICY_DIR");
-        if (dirname != NULL) {
-                pk_context->policy_dir = g_strdup (dirname);
-        } else {
-                pk_context->policy_dir = g_strdup (PACKAGE_DATA_DIR "/PolicyKit/policy");
-        }
+        pk_context->policy_dir = g_strdup (PACKAGE_DATA_DIR "/PolicyKit/policy");
         _pk_debug ("Using policy files from directory %s", pk_context->policy_dir);
 
         /* NOTE: we don't populate the cache until it's needed.. */
@@ -185,23 +178,12 @@ polkit_context_init (PolKitContext *pk_context, PolKitError **error)
                         goto error;
                 }
 
-                /* Watch the /var/lib/PolicyKit directory */
+                /* Watch the /var/lib/misc/PolicyKit.reload file */
                 pk_context->inotify_grant_perm_wd = inotify_add_watch (pk_context->inotify_fd, 
-                                                                       PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit", 
-                                                                       IN_MODIFY | IN_CREATE | IN_DELETE| IN_ATTRIB);
+                                                                       PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload", 
+                                                                       IN_MODIFY | IN_CREATE | IN_ATTRIB);
                 if (pk_context->inotify_grant_perm_wd < 0) {
-                        _pk_debug ("failed to add watch on directory '" PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit': %s",
-                                   strerror (errno));
-                        /* TODO: set error */
-                        goto error;
-                }
-
-                /* Watch the /var/run/PolicyKit directory */
-                pk_context->inotify_grant_temp_wd = inotify_add_watch (pk_context->inotify_fd, 
-                                                                       PACKAGE_LOCALSTATE_DIR "/run/PolicyKit", 
-                                                                       IN_MODIFY | IN_CREATE | IN_DELETE| IN_ATTRIB);
-                if (pk_context->inotify_grant_temp_wd < 0) {
-                        _pk_debug ("failed to add watch on directory '" PACKAGE_LOCALSTATE_DIR "/run/PolicyKit': %s",
+                        _pk_debug ("failed to add watch on file '" PACKAGE_LOCALSTATE_DIR "/lib/misc/PolicyKit.reload': %s",
                                    strerror (errno));
                         /* TODO: set error */
                         goto error;
@@ -216,11 +198,7 @@ polkit_context_init (PolKitContext *pk_context, PolKitError **error)
         }
 
         return TRUE;
-
 error:
-        if (pk_context != NULL)
-                polkit_context_unref (pk_context);
-
         return FALSE;
 }
 
@@ -291,6 +269,8 @@ polkit_context_set_config_changed (PolKitContext                *pk_context,
         pk_context->config_changed_user_data = user_data;
 }
 
+extern void _polkit_authorization_db_invalidate_cache (PolKitAuthorizationDB *authdb);
+
 /**
  * polkit_context_io_func:
  * @pk_context: the object
@@ -357,6 +337,9 @@ again:
                         polkit_config_unref (pk_context->config);
                         pk_context->config = NULL;
                 }
+
+                /* Purge authorization entries from the cache */
+                _polkit_authorization_db_invalidate_cache (pk_context->authdb);
                 
                 if (pk_context->config_changed_cb != NULL) {
                         pk_context->config_changed_cb (pk_context, 
@@ -509,6 +492,9 @@ polkit_context_can_session_do_action (PolKitContext   *pk_context,
         PolKitPolicyCache *cache;
         PolKitPolicyFileEntry *pfe;
         PolKitPolicyDefault *policy_default;
+        PolKitResult result_from_config;
+        PolKitResult result_from_grantdb;
+        polkit_bool_t from_authdb;
         PolKitResult result;
         PolKitConfig *config;
 
@@ -551,12 +537,44 @@ polkit_context_can_session_do_action (PolKitContext   *pk_context,
 
         polkit_policy_file_entry_debug (pfe);
 
-        /* check if the config file specifies a result */
-        result = polkit_config_can_session_do_action (config, action, session);
-        if (result != POLKIT_RESULT_UNKNOWN)
+        result_from_config = polkit_config_can_session_do_action (config, action, session);
+
+        result_from_grantdb = POLKIT_RESULT_UNKNOWN;
+        if (polkit_authorization_db_is_session_authorized (pk_context->authdb, 
+                                                           action, 
+                                                           session,
+                                                           &from_authdb)) {
+                if (from_authdb)
+                        result_from_grantdb = POLKIT_RESULT_YES;
+        }
+
+        /* Fist, the config file is authoritative.. so only use the
+         * value from the authdb if the config file allows to gain via
+         * authentication 
+         */
+        if (result_from_config != POLKIT_RESULT_UNKNOWN) {
+                /* it does.. use it.. although try to use an existing grant if there is one */
+                if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
+                     result_from_config == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) &&
+                    result_from_grantdb == POLKIT_RESULT_YES) {
+                        result = POLKIT_RESULT_YES;
+                } else {
+                        result = result_from_config;
+                }
+                goto found;
+        }
+
+        /* If we have a positive answer from the authdb, use it */
+        if (result_from_grantdb == POLKIT_RESULT_YES) {
+                result = POLKIT_RESULT_YES;
                 goto found;
+        }
 
-        /* if no, just use the defaults */
+        /* Otherwise, fall back to defaults as specified in the .policy file */
         policy_default = polkit_policy_file_entry_get_default (pfe);
         if (policy_default == NULL) {
                 g_warning ("no default policy for action!");
@@ -651,7 +669,10 @@ polkit_context_can_caller_do_action (PolKitContext   *pk_context,
                         result_from_grantdb = POLKIT_RESULT_YES;
         }
 
-        /* fist, check if the config file specifies a result */
+        /* Fist, the config file is authoritative.. so only use the
+         * value from the authdb if the config file allows to gain via
+         * authentication 
+         */
         if (result_from_config != POLKIT_RESULT_UNKNOWN) {
                 /* it does.. use it.. although try to use an existing grant if there is one */
                 if ((result_from_config == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
@@ -668,7 +689,13 @@ polkit_context_can_caller_do_action (PolKitContext   *pk_context,
                 goto found;
         }
 
-        /* use defaults as specified in the .policy file */
+        /* If we have a positive answer from the authdb, use it */
+        if (result_from_grantdb == POLKIT_RESULT_YES) {
+                result = POLKIT_RESULT_YES;
+                goto found;
+        }
+
+        /* Otherwise, fall back to defaults as specified in the .policy file */
         policy_default = polkit_policy_file_entry_get_default (pfe);
         if (policy_default == NULL) {
                 g_warning ("no default policy for action!");
@@ -676,17 +703,6 @@ polkit_context_can_caller_do_action (PolKitContext   *pk_context,
         }
         result = polkit_policy_default_can_caller_do_action (policy_default, action, caller);
 
-        /* use this result.. although try to use an existing grant if there is one */
-        if ((result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH ||
-             result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION ||
-             result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS ||
-             result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH ||
-             result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION ||
-             result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS) &&
-            result_from_grantdb == POLKIT_RESULT_YES) {
-                result = POLKIT_RESULT_YES;
-        }
-
 found:
 
         /* Never return UNKNOWN to user */
index 0b166cc..7b9ad43 100644 (file)
@@ -62,7 +62,67 @@ struct _PolKitError
         char *error_message;
 };
 
-//static PolKitError _oom_error = {true, POLKIT_ERROR_OUT_OF_MEMORY, "Out of memory"};
+/**
+ * polkit_error_is_set:
+ * @error: the error
+ *
+ * Determine if an error set
+ *
+ * Returns: #TRUE if, and only if, the error is set
+ *
+ * Since: 0.7
+ */
+polkit_bool_t
+polkit_error_is_set (PolKitError *error)
+{
+        return error != NULL;
+}
+
+/**
+ * polkit_error_get_error_name:
+ * @error: the error
+ * 
+ * Get the CamelCase name for the error;
+ * e.g. #POLKIT_ERROR_OUT_OF_MEMORY maps to "OutOfMemory" and so on.
+ *
+ * Returns: the string
+ *
+ * Since: 0.7
+ */
+const char *
+polkit_error_get_error_name (PolKitError *error)
+{
+        const char *ret;
+        g_return_val_if_fail (error != NULL, NULL);
+
+        switch (error->error_code) {
+        case POLKIT_ERROR_OUT_OF_MEMORY:
+                ret = "OutOfMemory";
+                break;
+        case POLKIT_ERROR_POLICY_FILE_INVALID:
+                ret = "PolicyFileInvalid";
+                break;
+        case POLKIT_ERROR_GENERAL_ERROR:
+                ret = "GeneralError";
+                break;
+        case POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS:
+                ret = "NotAuthorizedToReadAuthorizationsForOtherUsers";
+                break;
+        case POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS:
+                ret = "NotAuthorizedToRevokeAuthorizationsFromOtherUsers";
+                break;
+        case POLKIT_ERROR_NOT_AUTHORIZED_TO_GRANT_AUTHORIZATION:
+                ret = "NotAuthorizedToGrantAuthorization";
+                break;
+        case POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS:
+                ret = "AuthorizationAlreadyExists";
+                break;
+        default:
+                ret = NULL;
+        }
+
+        return ret;
+}
 
 /**
  * polkit_error_get_error_code:
@@ -110,6 +170,9 @@ polkit_error_free (PolKitError *error)
         }
 }
 
+
+//static PolKitError _oom_error = {true, POLKIT_ERROR_OUT_OF_MEMORY, "Out of memory"};
+
 /**
  * polkit_error_set_error:
  * @error: the error object
index 91d85cc..ac5cd08 100644 (file)
@@ -38,18 +38,39 @@ POLKIT_BEGIN_DECLS
  * PolKitErrorCode:
  * @POLKIT_ERROR_OUT_OF_MEMORY: Out of memory
  * @POLKIT_ERROR_POLICY_FILE_INVALID: There was an error parsing the given policy file
+ * @POLKIT_ERROR_GENERAL_ERROR: A general error code typically
+ * indicating problems with the installation of PolicyKit,
+ * e.g. helpers missing or wrong owner / permission.
+ * @POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS:
+ * An attempt was made to read authorizations for other users and the
+ * calling process is not authorized.
+ * @POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS:
+ * An attempt was made to revoke authorizations for other users and the
+ * calling process is not authorized.
+ * @POLKIT_ERROR_NOT_AUTHORIZED_TO_GRANT_AUTHORIZATION: An attempt was
+ * made to grant an authorization and the calling process is not
+ * authorized.
+ * @POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS: Subject already has an
+ * similar authorization already (modulo time of grant and who granted).
  *
- * Error codes returned by PolicyKit
+ * Errors returned by PolicyKit
  */
 typedef enum
 {      
         POLKIT_ERROR_OUT_OF_MEMORY,
-        POLKIT_ERROR_POLICY_FILE_INVALID
+        POLKIT_ERROR_POLICY_FILE_INVALID,
+        POLKIT_ERROR_GENERAL_ERROR,
+        POLKIT_ERROR_NOT_AUTHORIZED_TO_READ_AUTHORIZATIONS_FOR_OTHER_USERS,
+        POLKIT_ERROR_NOT_AUTHORIZED_TO_REVOKE_AUTHORIZATIONS_FROM_OTHER_USERS,
+        POLKIT_ERROR_NOT_AUTHORIZED_TO_GRANT_AUTHORIZATION,
+        POLKIT_ERROR_AUTHORIZATION_ALREADY_EXISTS
 } PolKitErrorCode;
 
 struct _PolKitError;
 typedef struct _PolKitError PolKitError;
 
+polkit_bool_t    polkit_error_is_set (PolKitError *error);
+const char      *polkit_error_get_error_name (PolKitError *error);
 PolKitErrorCode  polkit_error_get_error_code (PolKitError *error);
 const char      *polkit_error_get_error_message (PolKitError *error);
 void             polkit_error_free (PolKitError *error);
index 7e2098a..d16c9b6 100644 (file)
@@ -391,5 +391,5 @@ polkit_session_validate (PolKitSession *session)
         }
         ret = TRUE;
 error:
-        return TRUE;
+        return ret;
 }
index ce555b0..b7ed1de 100644 (file)
@@ -11,7 +11,7 @@ INCLUDES = \
        @GLIB_CFLAGS@ \
        @DBUS_CFLAGS@
 
-bin_PROGRAMS = polkit-config-file-validate polkit-policy-file-validate polkit-list-actions #polkit-grant 
+bin_PROGRAMS = polkit-config-file-validate polkit-policy-file-validate polkit-action polkit-auth
 
 polkit_config_file_validate_SOURCES = polkit-config-file-validate.c
 polkit_config_file_validate_LDADD = $(top_builddir)/polkit/libpolkit.la
@@ -19,18 +19,16 @@ polkit_config_file_validate_LDADD = $(top_builddir)/polkit/libpolkit.la
 polkit_policy_file_validate_SOURCES = polkit-policy-file-validate.c
 polkit_policy_file_validate_LDADD = $(top_builddir)/polkit/libpolkit.la
 
-#polkit_grant_SOURCES = polkit-grant.c
-#polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-grant/libpolkit-grant.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit/libpolkit-grant-private.la
+polkit_auth_SOURCES = polkit-auth.c
+polkit_auth_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-grant/libpolkit-grant.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
 
-polkit_list_actions_SOURCES = polkit-list-actions.c
-polkit_list_actions_LDADD = $(GLIB) $(top_builddir)/polkit/libpolkit.la
+polkit_action_SOURCES = polkit-action.c
+polkit_action_LDADD = $(GLIB) $(top_builddir)/polkit/libpolkit.la
 
-edit = sed \
-       -e 's|@docdir[@]|$(docdir)|g' \
-       -e 's|@sbindir[@]|$(sbindir)|g' \
-       -e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-       -e 's|@datadir[@]|$(datadir)|g' \
-       -e 's|@localstatedir[@]|$(localstatedir)|g'
+profiledir = $(sysconfdir)/profile.d
+profile_SCRIPTS = polkit-bash-completion.sh
+
+EXTRA_DIST = $(profile_SCRIPTS)
 
 clean-local :
        rm -f *~ polkit-reload-config
similarity index 88%
rename from tools/polkit-list-actions.c
rename to tools/polkit-action.c
index 54e381d..9ebdec5 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /***************************************************************************
  *
- * polkit-list-actions.c : list all registered PolicyKit actions
+ * polkit-action.c : list all registered PolicyKit actions
  *
  * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
  *
 static void
 usage (int argc, char *argv[])
 {
-       fprintf (stderr,
-                 "\n"
-                 "usage : polkit-list-actions [--action <action>] [--version] [--help]\n");
-       fprintf (stderr,
-                 "\n"
-                 "        --version        Show version and exit\n"
-                 "        --help           Show this information and exit\n"
-                 "        --action         Show detailed information about a single action\n"
-                 "\n"
-                 "List the actions registered with PolicyKit.\n");
+        execlp ("man", "man", "polkit-action", NULL);
+        fprintf (stderr, "Cannot show man page: %m\n");
+        exit (1);
 }
 
 static void
@@ -123,7 +116,7 @@ main (int argc, char *argv[])
                         return 0;
                 }
                 if (strcmp (argv[n], "--version") == 0) {
-                        printf ("polkit-list-actions " PACKAGE_VERSION "\n");
+                        printf ("polkit-action " PACKAGE_VERSION "\n");
                         return 0;
                 }
                 if (strcmp (argv[n], "--action") == 0 && n + 1 < argc) {
diff --git a/tools/polkit-auth.c b/tools/polkit-auth.c
new file mode 100644 (file)
index 0000000..cb7e94e
--- /dev/null
@@ -0,0 +1,871 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-auth.c : grant privileges to a user through authentication
+ *
+ * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <polkit-dbus/polkit-dbus.h>
+#include <polkit-grant/polkit-grant.h>
+
+#include <glib.h>
+
+static DBusConnection *system_bus;
+static PolKitContext *pk_context;
+static PolKitAuthorizationDB *pk_authdb;
+static PolKitTracker *pk_tracker;
+static PolKitCaller *pk_caller;
+
+static gboolean opt_is_version;
+static char *opt_obtain_action_id;
+static polkit_bool_t opt_show_explicit;
+static polkit_bool_t opt_show_explicit_detail;
+static polkit_bool_t opt_show_obtainable;
+static char *opt_revoke_action_id;
+static char *opt_user;
+static char *opt_grant_action_id;
+static char *opt_constraint;
+
+typedef struct {
+        gboolean obtained_privilege;
+        GMainLoop *loop;
+} UserData;
+
+static void
+conversation_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
+{
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+                printf ("Authentication as an administrative user is required.\n");
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                printf ("Authentication is required.\n");
+                break;
+
+        default:
+                /* should never happen */
+                exit (1);
+        }
+}
+
+static char *
+conversation_select_admin_user (PolKitGrant *polkit_grant, char **admin_users, void *user_data)
+{
+        int n;
+        char *user;
+        char *lineptr = NULL;
+        size_t linelen = 0;
+
+        printf ("The following users qualify as administrative users: ");
+        for (n = 0; admin_users[n] != NULL; n++) {
+                printf ("%s ", admin_users[n]);
+        }
+        printf ("\n");
+        printf ("Select user: ");
+        getline (&lineptr, &linelen, stdin);
+        user = strdup (lineptr);
+        free (lineptr);
+        return user;
+}
+
+static char *
+conversation_pam_prompt_echo_off (PolKitGrant *polkit_grant, const char *request, void *user_data)
+{
+        char *lineptr = NULL;
+        size_t linelen = 0;
+        struct termios old, new;
+        char *result;
+
+        printf ("%s", request);
+
+        /* Turn echo off */
+        if (tcgetattr (fileno (stdout), &old) != 0) {
+                exit (1);
+        }
+        new = old;
+        new.c_lflag &= ~ECHO;
+        if (tcsetattr (fileno (stdout), TCSAFLUSH, &new) != 0) {
+                exit (1);
+        }
+
+        getline (&lineptr, &linelen, stdin);
+  
+        /* Restore terminal. */
+        tcsetattr (fileno (stdout), TCSAFLUSH, &old);
+
+        result = strdup (lineptr);
+        free (lineptr);
+        printf ("\n");
+        return result;
+}
+
+static char *
+conversation_pam_prompt_echo_on (PolKitGrant *polkit_grant, const char *request, void *user_data)
+{
+        char *lineptr = NULL;
+        size_t linelen = 0;
+        char *result;
+        printf ("%s", request);
+        getline (&lineptr, &linelen, stdin);
+        result = strdup (lineptr);
+        free (lineptr);
+        printf ("\n");
+        return result;
+}
+
+static void
+conversation_pam_error_msg (PolKitGrant *polkit_grant, const char *msg, void *user_data)
+{
+        printf ("Error from PAM: %s\n", msg);
+}
+
+static void
+conversation_pam_text_info (PolKitGrant *polkit_grant, const char *msg, void *user_data)
+{
+        printf ("Info from PAM: %s\n", msg);
+}
+
+static PolKitResult
+conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
+{
+        char *lineptr = NULL;
+        size_t linelen = 0;
+        polkit_bool_t keep_session = FALSE;
+        polkit_bool_t keep_always = FALSE;
+        PolKitResult overridden_auth_type;
+
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+                printf ("Keep this privilege for the session? [no/session]?\n");
+        again:
+                getline (&lineptr, &linelen, stdin);
+                if (g_str_has_prefix (lineptr, "no")) {
+                        ;
+                } else if (g_str_has_prefix (lineptr, "session")) {
+                        keep_session = TRUE;
+                } else {
+                        printf ("Valid responses are 'no' and 'session'. Try again.\n");
+                        goto again;
+                }
+                free (lineptr);
+                break;
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                printf ("Keep this privilege for the session or always? [no/session/always]?\n");
+        again2:
+                getline (&lineptr, &linelen, stdin);
+                if (g_str_has_prefix (lineptr, "no")) {
+                        ;
+                } else if (g_str_has_prefix (lineptr, "session")) {
+                        keep_session = TRUE;
+                } else if (g_str_has_prefix (lineptr, "always")) {
+                        keep_always = TRUE;
+                } else {
+                        printf ("Valid responses are 'no', 'session' and 'always'. Try again.\n");
+                        goto again2;
+                }
+                free (lineptr);
+                break;
+        default:
+                /* should never happen */
+                exit (1);
+        }
+
+        switch (auth_type) {
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH;
+                if (keep_session)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION;
+                else if (keep_always)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS;
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH;
+                if (keep_session)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION;
+                else if (keep_always)
+                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS;
+                break;
+
+        default:
+                /* should never happen */
+                exit (1);
+        }
+
+        return overridden_auth_type;
+}
+
+static void 
+conversation_done (PolKitGrant *polkit_grant, 
+                   polkit_bool_t obtained_privilege, 
+                   polkit_bool_t invalid_data, 
+                   void *user_data)
+{
+        UserData *ud = user_data;
+        ud->obtained_privilege = obtained_privilege;
+        g_main_loop_quit (ud->loop);
+}
+
+
+
+
+static void
+child_watch_func (GPid pid,
+                  gint status,
+                  gpointer user_data)
+{
+        PolKitGrant *polkit_grant = user_data;
+        polkit_grant_child_func (polkit_grant, pid, WEXITSTATUS (status));
+}
+
+static int
+add_child_watch (PolKitGrant *polkit_grant, pid_t pid)
+{
+        return g_child_watch_add (pid, child_watch_func, polkit_grant);
+}
+
+static gboolean
+io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+        int fd;
+        PolKitGrant *polkit_grant = user_data;
+        fd = g_io_channel_unix_get_fd (channel);
+        polkit_grant_io_func (polkit_grant, fd);
+        return TRUE;
+}
+
+static int
+add_io_watch (PolKitGrant *polkit_grant, int fd)
+{
+        guint id = 0;
+        GIOChannel *channel;
+        channel = g_io_channel_unix_new (fd);
+        if (channel == NULL)
+                goto out;
+        id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, polkit_grant);
+        if (id == 0) {
+                g_io_channel_unref (channel);
+                goto out;
+        }
+        g_io_channel_unref (channel);
+out:
+        return id;
+}
+
+static void 
+remove_watch (PolKitGrant *polkit_auth, int watch_id)
+{
+        g_source_remove (watch_id);
+}
+
+static polkit_bool_t
+obtain_authorization (const char *action_id)
+{
+        UserData ud;
+        PolKitAction *action;
+        PolKitGrant *polkit_grant;
+
+        /* TODO: Attempt to use a service like PolicyKit-gnome on the session bus if available.. */
+
+        printf ("Attempting to obtain authorization for %s.\n", action_id);
+        
+        ud.loop = g_main_loop_new (NULL, TRUE);
+        ud.obtained_privilege = FALSE;
+
+        action = polkit_action_new ();
+        polkit_action_set_action_id (action, action_id);
+        
+        
+        polkit_grant = polkit_grant_new ();
+        polkit_grant_set_functions (polkit_grant,
+                                    add_io_watch,
+                                    add_child_watch,
+                                    remove_watch,
+                                    conversation_type,
+                                    conversation_select_admin_user,
+                                    conversation_pam_prompt_echo_off,
+                                    conversation_pam_prompt_echo_on,
+                                    conversation_pam_error_msg,
+                                    conversation_pam_text_info,
+                                    conversation_override_grant_type,
+                                    conversation_done,
+                                    &ud);
+        
+        if (!polkit_grant_initiate_auth (polkit_grant,
+                                         action,
+                                         pk_caller)) {
+                fprintf (stderr, "polkit-auth: failed to initiate privilege grant.\n");
+                goto out;
+        }
+        g_main_loop_run (ud.loop);
+        polkit_grant_unref (polkit_grant);
+
+        if (ud.obtained_privilege)
+                printf ("Successfully obtained the authorization for %s.\n", action_id);
+        else
+                printf ("Failed to obtain authorization for %s.\n", action_id);
+
+out:
+        return ud.obtained_privilege;
+}
+
+static char *
+get_exe_for_pid (pid_t pid)
+{
+        char *result;
+        char buf[PATH_MAX];
+        ssize_t len;
+        char proc_name[32];
+
+        result = NULL;
+
+        snprintf (proc_name, sizeof (proc_name), "/proc/%d/exe", pid);
+        len = readlink (proc_name, buf, sizeof (buf) - 1);
+        if (len == -1) {
+                goto out;
+        }
+        g_assert (len >= 0 && len < PATH_MAX - 1);
+
+        buf[len] = '\0';
+        result = g_strdup (buf);
+
+out:
+        return result;
+}
+
+static const char *
+get_name_from_uid (uid_t uid)
+{
+        const char *name;
+        struct passwd *pw;
+
+        pw = getpwuid (uid);
+        if (pw != NULL)
+                name = (const char *) pw->pw_name;
+        else
+                name = "(unknown)";
+
+        return name;
+}
+
+
+static polkit_bool_t
+auth_iterator_cb (PolKitAuthorizationDB *authdb,
+                  PolKitAuthorization   *auth, 
+                  void                  *user_data)
+{
+        const char *action_id;
+        DBusError dbus_error;
+        GHashTable *already_shown = (GHashTable *) user_data;
+
+        action_id = polkit_authorization_get_action_id (auth);
+
+        if (!opt_show_explicit_detail) {
+                if (g_hash_table_lookup (already_shown, action_id) != NULL)
+                        goto out;
+        }
+
+        dbus_error_init (&dbus_error);
+        if (!polkit_tracker_is_authorization_relevant (pk_tracker, auth, &dbus_error)) {
+                if (dbus_error_is_set (&dbus_error)) {
+                        g_warning ("Cannot determine if authorization is relevant: %s: %s",
+                                   dbus_error.name,
+                                   dbus_error.message);
+                        dbus_error_free (&dbus_error);
+                } else {
+                        goto out;
+                }
+        }
+
+        if (!opt_show_explicit_detail) {
+                g_hash_table_insert (already_shown, g_strdup (action_id), (gpointer) 1);
+        }
+
+        printf ("%s\n", action_id);
+
+        if (opt_show_explicit_detail) {
+                char *s;
+                time_t time_granted;
+                struct tm *time_tm;
+                char time_string[128];
+                uid_t auth_uid;
+                uid_t pimp_uid;
+                pid_t pid;
+                polkit_uint64_t pid_start_time;
+                const char *cstr;
+                PolKitAuthorizationConstraint *constraint;
+                PolKitAction *pk_action;
+                PolKitResult pk_result;
+
+                pk_action = polkit_action_new ();
+                polkit_action_set_action_id (pk_action, action_id);
+                pk_result = polkit_context_is_caller_authorized (pk_context, pk_action, pk_caller, FALSE);
+                polkit_action_unref (pk_action);
+                printf ("  Authorized:  %s\n", pk_result == POLKIT_RESULT_YES ? "Yes" : "No");
+
+                switch (polkit_authorization_get_scope (auth)) {
+                case POLKIT_AUTHORIZATION_SCOPE_PROCESS:
+                        polkit_authorization_scope_process_get_pid (auth, &pid, &pid_start_time);
+                        printf ("  Scope:       Confined to pid %d (%s)\n", pid, get_exe_for_pid (pid));
+
+                        break;
+                case POLKIT_AUTHORIZATION_SCOPE_SESSION:
+                        printf ("  Scope:       Confined to session %s\n", polkit_authorization_scope_session_get_ck_objref (auth));
+                        break;
+                case POLKIT_AUTHORIZATION_SCOPE_ALWAYS:
+                        printf ("  Scope:       Indefinitely\n");
+                        break;
+                }
+
+                time_granted = polkit_authorization_get_time_of_grant (auth);
+                time_tm = localtime (&time_granted);
+
+                if (polkit_authorization_was_granted_via_defaults (auth, &auth_uid)) { 
+                        s = g_strdup_printf ("%%c by auth as %s (uid %d)", get_name_from_uid (auth_uid), auth_uid);
+                        strftime (time_string, sizeof (time_string), s, time_tm);
+                        g_free (s);
+                } else if (polkit_authorization_was_granted_explicitly (auth, &pimp_uid)) { 
+                        s = g_strdup_printf ("%%c from %s (uid %d)", get_name_from_uid (pimp_uid), pimp_uid);
+                        strftime (time_string, sizeof (time_string), s, time_tm);
+                        g_free (s);
+                } else {
+                        strftime (time_string, sizeof (time_string), "%c", time_tm);
+                }
+                printf ("  Obtained:    %s\n", time_string);
+
+                constraint = polkit_authorization_get_constraint (auth);
+                cstr = "None";
+                switch (polkit_authorization_constraint_get_flags (constraint)) {
+                case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL:
+                        cstr = "Session must be on a local console";
+                        break;
+                case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_ACTIVE:
+                        cstr = "Session must be active";
+                        break;
+                case POLKIT_AUTHORIZATION_CONSTRAINT_REQUIRE_LOCAL_ACTIVE:
+                        cstr = "Session must be active and on a local console";
+                        break;
+                }
+                printf ("  Constraints: %s\n", cstr);
+
+                printf ("\n");
+        }
+
+
+out:
+        return FALSE;
+}
+
+static void
+pfe_iterator_cb (PolKitPolicyCache *policy_cache,
+                 PolKitPolicyFileEntry *pfe,
+                 void *user_data)
+{
+        PolKitAction *action;
+
+        action = polkit_action_new ();
+        polkit_action_set_action_id (action, polkit_policy_file_entry_get_id (pfe));
+
+        if (polkit_context_is_caller_authorized (pk_context,
+                                                 action,
+                                                 pk_caller,
+                                                 FALSE) == POLKIT_RESULT_YES) {
+                printf ("%s\n", polkit_policy_file_entry_get_id (pfe));
+        }
+
+        polkit_action_unref (action);
+}
+
+static void
+pfe_iterator_show_obtainable_cb (PolKitPolicyCache *policy_cache,
+                                 PolKitPolicyFileEntry *pfe,
+                                 void *user_data)
+{
+        PolKitAction *action;
+
+        action = polkit_action_new ();
+        polkit_action_set_action_id (action, polkit_policy_file_entry_get_id (pfe));
+
+        switch (polkit_context_is_caller_authorized (pk_context,
+                                                     action,
+                                                     pk_caller,
+                                                     FALSE)) {
+        default:
+        case POLKIT_RESULT_UNKNOWN:
+        case POLKIT_RESULT_NO:
+        case POLKIT_RESULT_YES:
+                break;
+
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
+        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
+                printf ("%s\n", polkit_policy_file_entry_get_id (pfe));
+                break;
+        }
+
+        polkit_action_unref (action);
+}
+
+
+static polkit_bool_t
+auth_revoke_iterator_cb (PolKitAuthorizationDB *authdb,
+                         PolKitAuthorization   *auth, 
+                         void                  *user_data)
+{
+        PolKitError *pk_error;
+
+        pk_error = NULL;
+        if (!polkit_authorization_db_revoke_entry (authdb, auth, &pk_error)) {
+                fprintf (stderr, "polkit-auth: %s: %s\n", 
+                         polkit_error_get_error_name (pk_error),
+                         polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+        }
+
+        return FALSE;
+}
+
+static polkit_bool_t
+revoke_authorizations (const char *action_id, uid_t uid)
+{
+        PolKitAction *pk_action;
+        PolKitError *pk_error;
+        polkit_bool_t ret;
+
+        ret = FALSE;
+
+        pk_action = polkit_action_new ();
+        polkit_action_set_action_id (pk_action, action_id);
+
+        pk_error = 0;
+        if (!polkit_authorization_db_foreach_for_action_for_uid (pk_authdb,
+                                                                 pk_action,
+                                                                 uid,
+                                                                 auth_revoke_iterator_cb,
+                                                                 NULL,
+                                                                 &pk_error)) {
+                if (polkit_error_is_set (pk_error)) {
+                        fprintf (stderr, "polkit-auth: %s\n",
+                                 polkit_error_get_error_message (pk_error));
+                        polkit_error_free (pk_error);
+                        goto out;
+                }
+        }
+
+        ret = TRUE;
+out:
+        return ret;
+}
+
+static void
+usage (int argc, char *argv[])
+{
+        execlp ("man", "man", "polkit-auth", NULL);
+        fprintf (stderr, "Cannot show man page: %m\n");
+        exit (1);
+}
+
+static polkit_bool_t
+ensure_dbus_and_ck (void)
+{
+        if (pk_caller != NULL)
+                return TRUE;
+
+        fprintf (stderr, "polkit-auth: This operation requires the system message bus and ConsoleKit to be running\n");
+
+        return FALSE;
+}
+
+int
+main (int argc, char *argv[])
+{
+        int ret;
+        PolKitError *pk_error;
+       DBusError dbus_error;
+        struct passwd *pw;
+        uid_t uid;
+
+        ret = 1;
+
+        pk_error = NULL;
+        pk_context = polkit_context_new ();
+        if (!polkit_context_init (pk_context, &pk_error)) {
+                fprintf (stderr, "polkit-auth: %s: %s\n", 
+                         polkit_error_get_error_name (pk_error),
+                         polkit_error_get_error_message (pk_error));
+                polkit_error_free (pk_error);
+                goto out;
+        }
+
+        pk_authdb = polkit_context_get_authorization_db (pk_context);
+
+        /* Since polkit-auth will be used in e.g. RPM's %post (for example to grant 
+         * org.freedesktop.policykit.read to services dropping privileges (like hald)) 
+         * we need to be able to run even when D-Bus and/or ConsoleKit aren't available...
+         */
+
+        dbus_error_init (&dbus_error);
+        system_bus = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
+        if (system_bus != NULL) {
+                pk_tracker = polkit_tracker_new ();
+                polkit_tracker_set_system_bus_connection (pk_tracker, system_bus);
+                polkit_tracker_init (pk_tracker);
+                
+                pk_caller = polkit_caller_new_from_pid (system_bus, getppid (), &dbus_error);
+                if (pk_caller == NULL) {
+                        if (dbus_error_is_set (&dbus_error)) {
+                                fprintf (stderr, "polkit-auth: polkit_caller_new_from_dbus_name(): %s: %s\n", 
+                                         dbus_error.name, dbus_error.message);
+                                goto out;
+                        }
+                }
+        } else {
+                pk_tracker = NULL;
+                pk_caller = NULL;
+        }
+
+        opt_show_explicit = FALSE;
+        opt_show_explicit_detail = FALSE;
+        opt_is_version = FALSE;
+        opt_obtain_action_id = NULL;
+        opt_grant_action_id = NULL;
+        opt_constraint = NULL;
+        opt_revoke_action_id = NULL;
+        opt_show_obtainable = FALSE;
+        opt_user = NULL;
+
+       while (argc > 1) {
+               int c;
+               int option_index = 0;
+               const char *opt;
+               static struct option long_options[] = {
+                        {"explicit", 0, NULL, 0},
+                        {"explicit-detail", 0, NULL, 0},
+                       {"obtain", 1, NULL, 0},
+                       {"grant", 1, NULL, 0},
+                        {"constraint", 1, NULL, 0},
+                       {"revoke", 1, NULL, 0},
+                       {"show-obtainable", 0, NULL, 0},
+                       {"user", 1, NULL, 0},
+                       {"version", 0, NULL, 0},
+                       {"help", 0, NULL, 0},
+                       {NULL, 0, NULL, 0}
+               };
+
+               c = getopt_long (argc, argv, "", long_options, &option_index);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 0:
+                       opt = long_options[option_index].name;
+
+                       if (strcmp (opt, "help") == 0) {
+                               usage (argc, argv);
+                               return 0;
+                       } else if (strcmp (opt, "version") == 0) {
+                               opt_is_version = TRUE;
+                       } else if (strcmp (opt, "obtain") == 0) {
+                               opt_obtain_action_id = strdup (optarg);
+                       } else if (strcmp (opt, "grant") == 0) {
+                               opt_grant_action_id = strdup (optarg);
+                       } else if (strcmp (opt, "constraint") == 0) {
+                               opt_constraint = strdup (optarg);
+                       } else if (strcmp (opt, "revoke") == 0) {
+                               opt_revoke_action_id = strdup (optarg);
+                       } else if (strcmp (opt, "show-obtainable") == 0) {
+                                opt_show_obtainable = TRUE;
+                       } else if (strcmp (opt, "explicit") == 0) {
+                                opt_show_explicit = TRUE;
+                       } else if (strcmp (opt, "explicit-detail") == 0) {
+                                opt_show_explicit_detail = TRUE;
+                       } else if (strcmp (opt, "user") == 0) {
+                                opt_user = strdup (optarg);
+                       }
+                       break;
+                case '?':
+                        usage (argc, argv);
+                        goto out;
+               }
+       }
+
+       if (opt_is_version) {
+               printf ("polkit-auth " PACKAGE_VERSION "\n");
+                ret = 0;
+                goto out;
+       }
+
+        if (opt_user != NULL) {
+                pw = getpwnam (opt_user);
+                if (pw == NULL) {
+                        fprintf (stderr, "polkit-auth: cannot look up uid for user '%s'\n", opt_user);
+                        goto out;
+                }
+                uid = pw->pw_uid;
+        } else {
+                uid = getuid ();
+        }
+
+        if (opt_obtain_action_id != NULL) {
+                if (!ensure_dbus_and_ck ())
+                        goto out;
+
+                if (!obtain_authorization (opt_obtain_action_id))
+                        goto out;                
+                ret = 0;
+        } else if (opt_grant_action_id != NULL) {
+                PolKitAction *pk_action;
+                PolKitError *pk_error;
+                PolKitAuthorizationConstraint *constraint;
+
+                if (opt_user == NULL && uid == 0) {
+                        fprintf (stderr, "polkit-auth: Cowardly refusing to grant authorization to uid 0 (did you forget to specify what user to grant to?). To force, run with --user root.\n");
+                        goto out;
+                }
+
+                pk_action = polkit_action_new ();
+                polkit_action_set_action_id (pk_action, opt_grant_action_id);
+
+                if (opt_constraint != NULL) {
+                        constraint = polkit_authorization_constraint_from_string (opt_constraint);
+                        if (constraint == NULL) {
+                                fprintf (stderr, "polkit-auth: constraint '%s' not recognized\n", opt_constraint);
+                                goto out;
+                        }
+                } else {
+                        constraint = polkit_authorization_constraint_get_null ();
+                }
+
+                pk_error = NULL;
+                if (!polkit_authorization_db_grant_to_uid (pk_authdb,
+                                                           pk_action,
+                                                           uid,
+                                                           constraint,
+                                                           &pk_error)) {
+                        fprintf (stderr, "polkit-auth: %s: %s\n", 
+                                 polkit_error_get_error_name (pk_error),
+                                 polkit_error_get_error_message (pk_error));
+                        polkit_error_free (pk_error);
+                        goto out;
+                }
+
+                ret = 0;
+
+        } else if (opt_revoke_action_id != NULL) {
+                if (!revoke_authorizations (opt_revoke_action_id, uid))
+                        goto out;                
+                ret = 0;
+        } else if (opt_show_explicit || opt_show_explicit_detail) {
+                GHashTable *already_shown;
+
+                if (!ensure_dbus_and_ck ())
+                        goto out;
+
+                already_shown = g_hash_table_new_full (g_str_hash,
+                                                       g_str_equal,
+                                                       g_free,
+                                                       NULL);
+
+
+                /* first the explicit authorizations */
+                if (!polkit_authorization_db_foreach_for_uid (pk_authdb,
+                                                              uid,
+                                                              auth_iterator_cb,
+                                                              already_shown,
+                                                              &pk_error)) {
+                        if (polkit_error_is_set (pk_error)) {
+                                fprintf (stderr, "polkit-auth: %s: %s\n", 
+                                         polkit_error_get_error_name (pk_error),
+                                         polkit_error_get_error_message (pk_error));
+                                polkit_error_free (pk_error);
+                                goto out;
+                        }                        
+                }
+
+                g_hash_table_destroy (already_shown);
+
+                ret = 0;
+        } else if (opt_show_obtainable) {
+                PolKitPolicyCache *pk_policy_cache;
+
+                if (!ensure_dbus_and_ck ())
+                        goto out;
+
+                /* show all authorizations; we do this by iterating over all actions and 
+                 * then querying whether the caller is authorized 
+                 */
+
+                pk_policy_cache = polkit_context_get_policy_cache (pk_context);
+                polkit_policy_cache_foreach (pk_policy_cache,
+                                             pfe_iterator_show_obtainable_cb,
+                                             NULL);
+                ret = 0;
+        } else {
+                PolKitPolicyCache *pk_policy_cache;
+
+                if (!ensure_dbus_and_ck ())
+                        goto out;
+
+                /* show all authorizations; we do this by iterating over all actions and 
+                 * then querying whether the caller is authorized 
+                 */
+
+                pk_policy_cache = polkit_context_get_policy_cache (pk_context);
+                polkit_policy_cache_foreach (pk_policy_cache,
+                                             pfe_iterator_cb,
+                                             NULL);
+                ret = 0;
+        }
+
+out:
+        return ret;
+}
diff --git a/tools/polkit-bash-completion.sh b/tools/polkit-bash-completion.sh
new file mode 100644 (file)
index 0000000..635159e
--- /dev/null
@@ -0,0 +1,102 @@
+
+####################################################################################################
+
+__polkit_auth() {
+    local IFS=$'\n'
+    local cur="${COMP_WORDS[COMP_CWORD]}"
+
+    case $COMP_CWORD in
+        1)
+            COMPREPLY=($(IFS=: compgen -S' ' -W "--obtain:--show-obtainable:--explicit:--explicit-detail:--grant:--revoke:--user:--version:--help" -- $cur))
+            ;;
+        2)
+           case "${COMP_WORDS[1]}" in
+                --obtain)   
+                    COMPREPLY=($(compgen -W "$(polkit-auth --show-obtainable)" -- $cur))
+                    ;;
+                --revoke) 
+                    COMPREPLY=($(compgen -W "$(polkit-auth --explicit)" -- $cur))
+                    ;;
+                --grant) 
+                    COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
+                    ;;
+                --user)   
+                    COMPREPLY=($(compgen -u -- $cur))
+                    ;;
+            esac
+            ;;
+        3)
+           case "${COMP_WORDS[1]}" in
+                --user)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "--explicit:--explicit-detail:--grant:--revoke" -- $cur))
+                    ;;
+                --grant)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "--constraint" -- $cur))
+                    ;;
+            esac
+            ;;
+        4)
+           case "${COMP_WORDS[3]}" in
+                --revoke) 
+                   case "${COMP_WORDS[1]}" in
+                        --user)
+                            local afou
+                            # we may not be authorized to read the explicit auths for the given user..
+                            afou=$(polkit-auth --user ${COMP_WORDS[2]} --explicit 2> /dev/null) 
+                            if [ $? != 0 ] ; then
+                                # .. so if that fails, fall back to showing all actions
+                                afou=$(polkit-action)
+                            fi
+                            COMPREPLY=($(compgen -W "$afou" -- $cur))
+                            ;;
+                        *)
+                            COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
+                            ;;
+                    esac
+                    ;;
+                --grant)
+                    COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
+                    ;;
+                --constraint)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "none:local:active:local+active" -- $cur))
+                    ;;
+            esac
+            ;;
+        5)
+           case "${COMP_WORDS[3]}" in
+                --grant)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "--constraint" -- $cur))
+                    ;;
+            esac
+            ;;
+        6)
+           case "${COMP_WORDS[5]}" in
+                --constraint)
+                    COMPREPLY=($(IFS=: compgen -S' ' -W "none:local:active:local+active" -- $cur))
+                    ;;
+            esac
+            ;;
+    esac
+}
+
+####################################################################################################
+
+__polkit_action() {
+    local IFS=$'\n'
+    local cur="${COMP_WORDS[COMP_CWORD]}"
+
+    if [ $COMP_CWORD = 1 ]; then
+        COMPREPLY=($(IFS=: compgen -S' ' -W "--action:--version:--help" -- $cur))
+    else
+       case "${COMP_WORDS[1]}" in
+            --action) 
+                COMPREPLY=($(compgen -W "$(polkit-action)" -- $cur))
+                ;;
+        esac
+    fi
+}
+
+####################################################################################################
+
+complete -o nospace -F __polkit_auth polkit-auth
+complete -o nospace -F __polkit_action polkit-action
index 743d4ed..d89feb0 100644 (file)
 static void
 usage (int argc, char *argv[])
 {
-       fprintf (stderr,
-                 "\n"
-                 "usage : polkit-policy-file-validate [/path/to/config/file] [--version] [--help]\n");
-       fprintf (stderr,
-                 "\n"
-                 "        --version        Show version and exit\n"
-                 "        --help           Show this information and exit\n"
-                 "\n"
-                 "Validates if given file is a valid PolicyKit configuration file.\n"
-                 "If no file is given, then /etc/PolicyKit/PolicyKit.conf is validated.\n"
-                 "Returns 0 if the file is valid, otherwise a non-zero exit code is returned.\n");
+        execlp ("man", "man", "polkit-config-file-validate", NULL);
+        fprintf (stderr, "Cannot show man page: %m\n");
+        exit (1);
 }
 
 int
diff --git a/tools/polkit-grant.c b/tools/polkit-grant.c
deleted file mode 100644 (file)
index ff9d73c..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
-/***************************************************************************
- *
- * polkit-grant.c : grant privileges to a user through authentication
- *
- * Copyright (C) 2007 David Zeuthen, <david@fubar.dk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307         USA
- *
- **************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-#include <unistd.h>
-#include <errno.h>
-#include <termios.h>
-
-#include <polkit-dbus/polkit-dbus.h>
-#include <polkit-grant/polkit-grant.h>
-#include <polkit/polkit-grant-database.h>
-
-#include <glib.h>
-
-static void
-usage (int argc, char *argv[])
-{
-       fprintf (stderr,
-                 "\n"
-                 "usage : polkit-grant [--gain <action>] [--list] [--delete <user>]\n"
-                 "          [--version] [--help]\n");
-       fprintf (stderr,
-                 "\n"
-                 "        --gain       Attempt to gain the privilege to do an action\n"
-                 "        --list       List all grants\n"
-                 "        --delete     Delete all grants for a given user\n"
-                 "        --version    Show version and exit\n"
-                 "        --help       Show this information and exit\n"
-                 "\n");
-}
-
-typedef struct {
-        gboolean gained_privilege;
-        GMainLoop *loop;
-} UserData;
-
-static void
-conversation_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
-{
-        switch (auth_type) {
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
-                printf ("Authentication as an administrative user is required.\n");
-                break;
-
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
-                printf ("Authentication is required.\n");
-                break;
-
-        default:
-                /* should never happen */
-                exit (1);
-        }
-}
-
-static char *
-conversation_select_admin_user (PolKitGrant *polkit_grant, char **admin_users, void *user_data)
-{
-        int n;
-        char *user;
-        char *lineptr = NULL;
-        size_t linelen = 0;
-
-        printf ("The following users qualify as administrative users:\n");
-        for (n = 0; admin_users[n] != NULL; n++) {
-                printf ("%s\n", admin_users[n]);
-        }
-        printf ("Select user: ");
-        getline (&lineptr, &linelen, stdin);
-        user = strdup (lineptr);
-        free (lineptr);
-        return user;
-}
-
-static char *
-conversation_pam_prompt_echo_off (PolKitGrant *polkit_grant, const char *request, void *user_data)
-{
-        char *lineptr = NULL;
-        size_t linelen = 0;
-        struct termios old, new;
-        char *result;
-
-        printf ("%s", request);
-
-        /* Turn echo off */
-        if (tcgetattr (fileno (stdout), &old) != 0) {
-                exit (1);
-        }
-        new = old;
-        new.c_lflag &= ~ECHO;
-        if (tcsetattr (fileno (stdout), TCSAFLUSH, &new) != 0) {
-                exit (1);
-        }
-
-        getline (&lineptr, &linelen, stdin);
-  
-        /* Restore terminal. */
-        tcsetattr (fileno (stdout), TCSAFLUSH, &old);
-
-        result = strdup (lineptr);
-        free (lineptr);
-        printf ("\n");
-        return result;
-}
-
-static char *
-conversation_pam_prompt_echo_on (PolKitGrant *polkit_grant, const char *request, void *user_data)
-{
-        char *lineptr = NULL;
-        size_t linelen = 0;
-        char *result;
-        printf ("%s", request);
-        getline (&lineptr, &linelen, stdin);
-        result = strdup (lineptr);
-        free (lineptr);
-        printf ("\n");
-        return result;
-}
-
-static void
-conversation_pam_error_msg (PolKitGrant *polkit_grant, const char *msg, void *user_data)
-{
-        printf ("error_msg='%s'\n", msg);
-}
-
-static void
-conversation_pam_text_info (PolKitGrant *polkit_grant, const char *msg, void *user_data)
-{
-        printf ("text_info='%s'\n", msg);
-}
-
-static PolKitResult
-conversation_override_grant_type (PolKitGrant *polkit_grant, PolKitResult auth_type, void *user_data)
-{
-        char *lineptr = NULL;
-        size_t linelen = 0;
-        polkit_bool_t keep_session = FALSE;
-        polkit_bool_t keep_always = FALSE;
-        PolKitResult overridden_auth_type;
-
-        switch (auth_type) {
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
-                break;
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
-                printf ("Keep this privilege for the session? [no/session]?\n");
-                getline (&lineptr, &linelen, stdin);
-                if (g_str_has_prefix (lineptr, "no")) {
-                        ;
-                } else if (g_str_has_prefix (lineptr, "session")) {
-                        keep_session = TRUE;
-                } else {
-                        printf ("Valid responses are 'no' and 'session'. Exiting.\n");
-                        exit (1);
-                }
-                free (lineptr);
-                break;
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
-                printf ("Keep this privilege for the session or always? [no/session/always]?\n");
-                getline (&lineptr, &linelen, stdin);
-                if (g_str_has_prefix (lineptr, "no")) {
-                        ;
-                } else if (g_str_has_prefix (lineptr, "session")) {
-                        keep_session = TRUE;
-                } else if (g_str_has_prefix (lineptr, "always")) {
-                        keep_always = TRUE;
-                } else {
-                        printf ("Valid responses are 'no', 'session' and 'always'. Exiting.\n");
-                        exit (1);
-                }
-                free (lineptr);
-                break;
-        default:
-                /* should never happen */
-                exit (1);
-        }
-
-        switch (auth_type) {
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH:
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION:
-        case POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS:
-                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH;
-                if (keep_session)
-                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION;
-                else if (keep_always)
-                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS;
-                break;
-
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION:
-        case POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS:
-                overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH;
-                if (keep_session)
-                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION;
-                else if (keep_always)
-                        overridden_auth_type = POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS;
-                break;
-
-        default:
-                /* should never happen */
-                exit (1);
-        }
-
-        return overridden_auth_type;
-}
-
-static void 
-conversation_done (PolKitGrant *polkit_grant, polkit_bool_t gained_privilege, polkit_bool_t invalid_data, void *user_data)
-{
-        UserData *ud = user_data;
-        ud->gained_privilege = gained_privilege;
-        g_main_loop_quit (ud->loop);
-}
-
-
-
-
-static void
-child_watch_func (GPid pid,
-                  gint status,
-                  gpointer user_data)
-{
-        PolKitGrant *polkit_grant = user_data;
-        polkit_grant_child_func (polkit_grant, pid, WEXITSTATUS (status));
-}
-
-static int
-add_child_watch (PolKitGrant *polkit_grant, pid_t pid)
-{
-        return g_child_watch_add (pid, child_watch_func, polkit_grant);
-}
-
-static gboolean
-io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
-{
-        int fd;
-        PolKitGrant *polkit_grant = user_data;
-        fd = g_io_channel_unix_get_fd (channel);
-        polkit_grant_io_func (polkit_grant, fd);
-        return TRUE;
-}
-
-static int
-add_io_watch (PolKitGrant *polkit_grant, int fd)
-{
-        guint id = 0;
-        GIOChannel *channel;
-        channel = g_io_channel_unix_new (fd);
-        if (channel == NULL)
-                goto out;
-        id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, polkit_grant);
-        if (id == 0) {
-                g_io_channel_unref (channel);
-                goto out;
-        }
-        g_io_channel_unref (channel);
-out:
-        return id;
-}
-
-static void 
-remove_watch (PolKitGrant *polkit_auth, int watch_id)
-{
-        g_source_remove (watch_id);
-}
-
-static void
-_print_grants (const char *action_id, 
-               uid_t uid,
-               time_t when, 
-               PolKitGrantDbGrantType grant_type,
-               pid_t pid,
-               polkit_uint64_t pid_time,
-               const char *session_id,
-               void *user_data)
-{
-        char *user;
-        char *when_str;
-        struct passwd *passwd;
-
-        passwd = getpwuid (uid);
-        if (passwd != NULL)
-                user = passwd->pw_name;
-        else
-                user = "NON_EXISTING_USER";
-
-        when_str = ctime (&when);
-
-        switch (grant_type) {
-        case POLKIT_GRANTDB_GRANT_TYPE_PROCESS:
-                printf ("process:\n"
-                        "  user:    %s (uid %d)\n"
-                        "  pid:     %d@%lld\n"
-                        "  action:  %s\n"
-                        "  granted: %s\n", 
-                        user, uid, pid, pid_time, action_id, when_str);
-                break;
-        case POLKIT_GRANTDB_GRANT_TYPE_SESSION:
-                printf ("session:\n"
-                        "  user:    %s (uid %d)\n"
-                        "  session: %s\n"
-                        "  action:  %s\n"
-                        "  granted: %s\n", 
-                        user, uid, session_id, action_id, when_str);
-                break;
-        case POLKIT_GRANTDB_GRANT_TYPE_ALWAYS:
-                printf ("always:\n"
-                        "  user:    %s (uid %d)\n"
-                        "  action:  %s\n"
-                        "  granted: %s\n", 
-                        user, uid, action_id, when_str);
-                break;
-        default:
-                break;
-        }
-}
-
-
-int
-main (int argc, char *argv[])
-{
-        char *gain_action_id;
-        gboolean is_version;
-        DBusConnection *bus;
-       DBusError error;
-        PolKitContext *pol_ctx;
-        PolKitCaller *caller;
-        PolKitAction *action;
-        PolKitError *p_error;
-        PolKitGrant *polkit_grant;
-        int ret;
-        UserData ud;
-        polkit_bool_t list_grants;
-        char *delete_for_user;
-
-        ret = 1;
-
-       if (argc <= 1) {
-               usage (argc, argv);
-                goto out;
-       }
-
-        list_grants = FALSE;
-        delete_for_user = NULL;
-        is_version = FALSE;
-        gain_action_id = NULL;
-       while (1) {
-               int c;
-               int option_index = 0;
-               const char *opt;
-               static struct option long_options[] = {
-                        {"list", 0, NULL, 0},
-                        {"delete", 1, NULL, 0},
-                       {"gain", 1, NULL, 0},
-                       {"version", 0, NULL, 0},
-                       {"help", 0, NULL, 0},
-                       {NULL, 0, NULL, 0}
-               };
-
-               c = getopt_long (argc, argv, "", long_options, &option_index);
-               if (c == -1)
-                       break;
-
-               switch (c) {
-               case 0:
-                       opt = long_options[option_index].name;
-
-                       if (strcmp (opt, "help") == 0) {
-                               usage (argc, argv);
-                               return 0;
-                       } else if (strcmp (opt, "version") == 0) {
-                               is_version = TRUE;
-                       } else if (strcmp (opt, "gain") == 0) {
-                               gain_action_id = strdup (optarg);
-                       } else if (strcmp (opt, "list") == 0) {
-                                list_grants = TRUE;
-                       } else if (strcmp (opt, "delete") == 0) {
-                                delete_for_user = strdup (optarg);
-                       }
-                       break;
-
-               default:
-                       usage (argc, argv);
-                        goto out;
-               }
-       }
-
-       if (is_version) {
-               printf ("polkit-grant " PACKAGE_VERSION "\n");
-                ret = 0;
-                goto out;
-       }
-
-        if (gain_action_id != NULL) {
-                printf ("Attempting to gain the privilege for %s.\n", gain_action_id);
-                
-                ud.loop = g_main_loop_new (NULL, TRUE);
-                
-                dbus_error_init (&error);
-                bus = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
-                if (bus == NULL) {
-                        fprintf (stderr, "error: dbus_bus_get(): %s: %s\n", error.name, error.message);
-                        goto out;
-                }
-                
-                p_error = NULL;
-                pol_ctx = polkit_context_new ();
-                if (!polkit_context_init (pol_ctx, &p_error)) {
-                        fprintf (stderr, "error: polkit_context_init: %s\n", polkit_error_get_error_message (p_error));
-                        polkit_error_free (p_error);
-                        goto out;
-                }
-                
-                action = polkit_action_new ();
-                polkit_action_set_action_id (action, gain_action_id);
-                
-                caller = polkit_caller_new_from_dbus_name (bus, dbus_bus_get_unique_name (bus), &error);
-                if (caller == NULL) {
-                        if (dbus_error_is_set (&error)) {
-                                fprintf (stderr, "error: polkit_caller_new_from_dbus_name(): %s: %s\n", 
-                                         error.name, error.message);
-                                goto out;
-                        }
-                }
-                
-                polkit_grant = polkit_grant_new ();
-                polkit_grant_set_functions (polkit_grant,
-                                            add_io_watch,
-                                            add_child_watch,
-                                            remove_watch,
-                                            conversation_type,
-                                            conversation_select_admin_user,
-                                            conversation_pam_prompt_echo_off,
-                                            conversation_pam_prompt_echo_on,
-                                            conversation_pam_error_msg,
-                                            conversation_pam_text_info,
-                                            conversation_override_grant_type,
-                                            conversation_done,
-                                            &ud);
-                
-                if (!polkit_grant_initiate_auth (polkit_grant,
-                                                 action,
-                                                 caller)) {
-                        printf ("Failed to initiate privilege grant.\n");
-                        ret = 1;
-                        goto out;
-                }
-                g_main_loop_run (ud.loop);
-                polkit_grant_unref (polkit_grant);
-                
-                if (ud.gained_privilege)
-                        printf ("Successfully gained the privilege for %s.\n", gain_action_id);
-                else
-                        printf ("Failed to gain the privilege for %s.\n", gain_action_id);
-                
-                ret = ud.gained_privilege ? 0 : 1;
-        } else if (list_grants) {
-                _polkit_grantdb_foreach (_print_grants, NULL);
-                ret = 0;
-        } else if (delete_for_user != NULL) {
-                struct passwd *passwd;
-                passwd = getpwnam (delete_for_user);
-                if (passwd == NULL) {
-                        printf ("No such user '%s'.\n", delete_for_user);
-                        goto out;
-                }
-                if (!_polkit_grantdb_delete_for_user (passwd->pw_uid)) {
-                        printf ("Error deleting grants for user '%s'. Got root?\n", delete_for_user);
-                }
-        } else {
-               usage (argc, argv);
-        }
-
-out:
-        return ret;
-}
index 1ad5035..ef3182e 100644 (file)
 static void
 usage (int argc, char *argv[])
 {
-       fprintf (stderr,
-                 "\n"
-                 "usage : polkit-policy-file-validate <policy-files>\n"
-                 "        [--version] [--help]\n");
-       fprintf (stderr,
-                 "\n"
-                 "        --version        Show version and exit\n"
-                 "        --help           Show this information and exit\n"
-                 "\n"
-                 "Validates one or more PolicyKit policy file. Returns 0 if it validates.\n"
-                 "If not, the program exits with a non-zero exit code.\n");
+        execlp ("man", "man", "polkit-policy-file-validate", NULL);
+        fprintf (stderr, "Cannot show man page: %m\n");
+        exit (1);
 }
 
 static bool