## 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
.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
echo "Running autoconf ..."
autoconf
+intltoolize --copy --force --automake || exit 1
+
conf_flags="--enable-maintainer-mode --enable-gtk-doc"
if test x$NOCONFIGURE = x; then
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)
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
doc/version.xml
doc/man/Makefile
policy/Makefile
+po/Makefile.in
])
dnl ==========================================================================
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."
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 \
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 $<
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:
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>
<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>
-<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>
<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>
<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>
--- /dev/null
+<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>
+++ /dev/null
-<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>
<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>
--- /dev/null
+# please keep this list sorted alphabetically
+#
+
+
--- /dev/null
+# List of source files containing translatable strings.
+# Please keep this file sorted alphabetically.
+[encoding: UTF-8]
+policy/org.freedesktop.policykit.policy.in
-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
--- /dev/null
+<?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>
+++ /dev/null
-<!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>
-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 \
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
#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:
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);
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);
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);
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:
*
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);
/* 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
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:
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);
+}
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;
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 */
--- /dev/null
+/* -*- 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;
+}
+
--- /dev/null
+/* -*- 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;
+}
+
--- /dev/null
+/* -*- 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;
+}
+
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;
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;
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;
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..
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]",
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) {
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]",
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@
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
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+/* -*- 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 */
+
+
#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
* 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:
*
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;
}
authdb->refcount--;
if (authdb->refcount > 0)
return;
+ g_hash_table_destroy (authdb->uid_to_authlist);
g_free (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:
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;
}
/**
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;
}
* @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
* 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
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);
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
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
* 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
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;
+
}
#include <polkit/polkit-result.h>
#include <polkit/polkit-caller.h>
#include <polkit/polkit-session.h>
+#include <polkit/polkit-error.h>
POLKIT_BEGIN_DECLS
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
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.
*
* 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
* 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
*
* 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
*
* 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.
* 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
* 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.
* 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
* 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;
}
#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);
/**
* @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,
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
int inotify_config_wd;
int inotify_policy_wd;
int inotify_grant_perm_wd;
- int inotify_grant_temp_wd;
};
/**
* @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.. */
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;
}
return TRUE;
-
error:
- if (pk_context != NULL)
- polkit_context_unref (pk_context);
-
return FALSE;
}
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
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,
PolKitPolicyCache *cache;
PolKitPolicyFileEntry *pfe;
PolKitPolicyDefault *policy_default;
+ PolKitResult result_from_config;
+ PolKitResult result_from_grantdb;
+ polkit_bool_t from_authdb;
PolKitResult result;
PolKitConfig *config;
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!");
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 ||
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!");
}
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 */
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:
}
}
+
+//static PolKitError _oom_error = {true, POLKIT_ERROR_OUT_OF_MEMORY, "Out of memory"};
+
/**
* polkit_error_set_error:
* @error: the error object
* 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);
}
ret = TRUE;
error:
- return TRUE;
+ return ret;
}
@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
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
/* -*- 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
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) {
--- /dev/null
+/* -*- 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;
+}
--- /dev/null
+
+####################################################################################################
+
+__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
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
+++ /dev/null
-/* -*- 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;
-}
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