PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Thu Dec 10 11:51:12 PST 2009
configure.ac | 4
docs/man/pklocalauthority.xml | 122 ++++++-
src/polkitbackend/Makefile.am | 3
src/polkitbackend/polkitbackendlocalauthority.c | 240 +++++++++++++--
src/polkitbackend/polkitbackendlocalauthorizationstore.c | 6
5 files changed, 334 insertions(+), 41 deletions(-)
New commits:
commit 8e0b9b47d1fc1a4ab6020770e4b3084ddd45b71d
Author: David Zeuthen <davidz at redhat.com>
Date: Thu Dec 10 14:45:10 2009 -0500
Bug 25367 â Also read local authority configuration data from /etc
Turns out some people would rather edit local files in /etc rather
than shipping them in a package (as e.g. Fedora does with the
polkit-desktop-policy RPM).
This also drops the hard-coded list of directory names such as
10-vendor.d, 20-org.d - we now monitor the
/var/lib/polkit-1/localauthority and /etc/polkit-1/localauthority
directories for changes - whenever we see a subdirectory in any of
these directories, we create an AuthorizationStore object that looks
for .pkla files.
Signed-off-by: David Zeuthen <davidz at redhat.com>
diff --git a/configure.ac b/configure.ac
index 7d42ac0..2605187 100644
--- a/configure.ac
+++ b/configure.ac
@@ -484,6 +484,10 @@ echo "
"
+echo "NOTE: The directory ${sysconfdir}/polkit-1/localauthority must be owned"
+echo " by root and have mode 700"
+echo
+
echo "NOTE: The directory ${localstatedir}/lib/polkit-1 must be owned"
echo " by root and have mode 700"
echo
diff --git a/docs/man/pklocalauthority.xml b/docs/man/pklocalauthority.xml
index 5ba01a6..f0343f3 100644
--- a/docs/man/pklocalauthority.xml
+++ b/docs/man/pklocalauthority.xml
@@ -91,7 +91,22 @@
<title>DIRECTORY STRUCTURE</title>
<para>
The Local Authority reads files with <filename>.pkla</filename>
- extension from the following directories
+ extension from all directories located inside the
+ <filename>/etc/polkit-1/localauthority</filename>
+ and <filename>/var/lib/polkit-1/localauthority</filename>
+ directories. By default, the following sub-directories are installed.
+ </para>
+ <programlisting>
+/etc/polkit-1/
+`-- localauthority
+ |-- 10-vendor.d
+ |-- 20-org.d
+ |-- 30-site.d
+ |-- 50-local.d
+ `-- 90-mandatory.d
+ </programlisting>
+ <para>
+ and
</para>
<programlisting>
/var/lib/polkit-1/
@@ -103,6 +118,12 @@
`-- 90-mandatory.d
</programlisting>
<para>
+ The <filename>/etc/polkit-1/localauthority</filename> hierarchy
+ is inteded for local configuration and
+ the <filename>/var/lib/polkit-1/localauthority</filename> is
+ intended for 3rd party packages.
+ </para>
+ <para>
Each <filename>.pkla</filename> file contains one or more
authorization entries. If the underlying filesystem supports
file monitoring, the Local Authority will reload information
@@ -117,7 +138,7 @@
<term><emphasis>10-vendor.d</emphasis></term>
<listitem>
<para>
- Reserved for the Operating System vendor.
+ Intended for use by the OS vendor.
</para>
</listitem>
</varlistentry>
@@ -125,7 +146,7 @@
<term><emphasis>20-org.d</emphasis></term>
<listitem>
<para>
- Reserved for the organization deploying the system.
+ Intended for the organization deploying the OS.
</para>
</listitem>
</varlistentry>
@@ -133,7 +154,7 @@
<term><emphasis>30-site.d</emphasis></term>
<listitem>
<para>
- Reserved for site deploying the system.
+ Intended for the site deploying the system.
</para>
</listitem>
</varlistentry>
@@ -141,7 +162,7 @@
<term><emphasis>50-local.d</emphasis></term>
<listitem>
<para>
- Reserved for local usage.
+ Intended for local usage.
</para>
</listitem>
</varlistentry>
@@ -149,15 +170,19 @@
<term><emphasis>90-mandatory.d</emphasis></term>
<listitem>
<para>
- Reserved for the organization deploying the system.
+ Intended for the organization deploying the OS.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>
- Each <filename>.pkla</filename> file is a standard <emphasis>key
- file</emphasis> and contains key/value pairs in one or more
- groups with each group representing an authorization entry.
+ and new directories can be added/removed as needed.
+ </para>
+ <para>
+ As to regards to the content, each <filename>.pkla</filename>
+ file is a standard <emphasis>key file</emphasis> and contains
+ key/value pairs in one or more groups with each group
+ representing an authorization entry.
A <filename>.pkla</filename> file MUST be named by using a
scheme to ensure that the name is unique, e.g. reverse DNS
notation or similar. For example, if the organization is
@@ -261,13 +286,78 @@
following algorithm.
</para>
<para>
- First, the user of the Subject is determined and the groups that
- the user belongs are looked up. For each group identity, the
- authorization entries are consulted in the lexigraphical order
- (using standard lexicographical sorting (using the standard C
- locale) of file names and appearance of each group in each
- file). If the authorization check matches the data from the
- authorization check, then the authorization result
+ The authorization entries from all .pkla files are ordered using
+ the following rules. First all the basename of all
+ sub-directories (e.g. <emphasis>30-site.d</emphasis>) from both
+ the <filename>/etc/polkit-1/localauthority</filename>
+ and <filename>/var/lib/polkit-1/localauthority</filename>
+ directories are enumerated and sorted (using the C locale). If a
+ name exists in both <filename>/etc</filename>
+ and <filename>/var</filename>, the one
+ in <filename>/etc</filename> takes precedence. Then
+ all <filename>.pkla</filename> files are read in order from this
+ list of sub-directories. For each <filename>.pkla</filename>
+ file, authorizations from each file are appended in order resulting
+ in an ordered list of authorization entries.
+ </para>
+ <para>
+ For example, given the following files
+ </para>
+ <programlisting>
+/var/lib/polkit-1
+âââ localauthority
+ âââ 10-vendor.d
+ â âââ 10-desktop-policy.pkla
+ âââ 20-org.d
+ âââ 30-site.d
+ âââ 50-local.d
+ âââ 55-org.my.company.d
+ â âââ 10-org.my.company.product.pkla
+ âââ 90-mandatory.d
+
+/etc/polkit-1
+âââ localauthority
+ âââ 10-vendor.d
+ â âââ 01-some-changes-from-a-subvendor.pkla
+ âââ 20-org.d
+ âââ 30-site.d
+ âââ 50-local.d
+ âââ 55-org.my.company.d
+ â âââ 10-org.my.company.product.pkla
+ âââ 90-mandatory.d
+ </programlisting>
+ <para>
+ the evaluation order of the <filename>.pkla</filename> files is:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ <filename>10-desktop-policy.pkla</filename>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>01-some-changes-from-a-subvendor.pkla</filename>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>10-org.my.company.product.pkla</filename> (the <filename>/var</filename> one)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>10-org.my.company.product.pkla</filename> (the <filename>/etc</filename> one)
+ </para>
+ </listitem>
+ </orderedlist>
+ <para>
+ When the list of authorization entries has been calculated, the
+ authorization check can be made. First, the user of the Subject
+ is determined and the groups that the user belongs are looked
+ up. For each group identity, the authorization entries are
+ consulted in order. If the authorization check matches the data
+ from the authorization check, then the authorization result
from <emphasis>RequireAny</emphasis>, <emphasis>RequireInactive</emphasis>
or <emphasis>RequireActive</emphasis> is used
and <emphasis>ReturnValue</emphasis> is added to the
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index 48695d2..4cb7310 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -103,4 +103,7 @@ install-exec-hook:
mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1
mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1/localauthority/{10-vendor.d,20-org.d,30-site.d,50-local.d,90-mandatory.d}
-chmod 700 $(DESTDIR)$(localstatedir)/lib/polkit-1
+ mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1
+ mkdir -p $(DESTDIR)$(sysconfdir)/polkit-1/localauthority/{10-vendor.d,20-org.d,30-site.d,50-local.d,90-mandatory.d}
+ -chmod 700 $(DESTDIR)$(sysconfdir)/polkit-1/localauthority
mkdir -p $(DESTDIR)$(libdir)/polkit-1/extensions
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index 3672f4c..737b7d2 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -66,6 +66,9 @@ typedef struct
GList *authorization_stores;
+ GFileMonitor *sysconf_dir_monitor;
+ GFileMonitor *localstate_dir_monitor;
+
} PolkitBackendLocalAuthorityPrivate;
/* ---------------------------------------------------------------------------------------------------- */
@@ -131,43 +134,226 @@ on_store_changed (PolkitBackendLocalAuthorizationStore *store,
g_signal_emit_by_name (authority, "changed");
}
+/* ---------------------------------------------------------------------------------------------------- */
+
static void
-polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
+purge_all_authorization_stores (PolkitBackendLocalAuthority *authority)
{
PolkitBackendLocalAuthorityPrivate *priv;
- GFile *directory;
+ GList *l;
+
+ priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
+
+ for (l = priv->authorization_stores; l != NULL; l = l->next)
+ {
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
+ g_signal_handlers_disconnect_by_func (store,
+ G_CALLBACK (on_store_changed),
+ authority);
+ g_object_unref (store);
+ }
+ g_list_free (priv->authorization_stores);
+ priv->authorization_stores = NULL;
+
+ g_debug ("Purged all local authorization stores");
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+add_one_authorization_store (PolkitBackendLocalAuthority *authority,
+ GFile *directory)
+{
+ PolkitBackendLocalAuthorizationStore *store;
+ PolkitBackendLocalAuthorityPrivate *priv;
+
+ priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
+
+ store = polkit_backend_local_authorization_store_new (directory, ".pkla");
+ priv->authorization_stores = g_list_append (priv->authorization_stores, store);
+
+ g_signal_connect (store,
+ "changed",
+ G_CALLBACK (on_store_changed),
+ authority);
+}
+
+static gint
+authorization_store_path_compare_func (GFile *file_a,
+ GFile *file_b)
+{
+ const gchar *a;
+ const gchar *b;
+
+ a = g_object_get_data (G_OBJECT (file_a), "sort-key");
+ b = g_object_get_data (G_OBJECT (file_b), "sort-key");
+
+ return g_strcmp0 (a, b);
+}
+
+static void
+add_all_authorization_stores (PolkitBackendLocalAuthority *authority)
+{
guint n;
- const gchar *store_locations[] =
+ GList *directories;
+ GList *l;
+
+ directories = NULL;
+
+ for (n = 0; n < 2; n++)
+ {
+ const gchar *toplevel_path;
+ GFile *toplevel_directory;
+ GFileEnumerator *directory_enumerator;
+ GFileInfo *file_info;
+ GError *error;
+
+ error = NULL;
+
+ if (n == 0)
+ toplevel_path = PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority";
+ else
+ toplevel_path = PACKAGE_SYSCONF_DIR "/polkit-1/localauthority";
+
+ toplevel_directory = g_file_new_for_path (toplevel_path);
+ directory_enumerator = g_file_enumerate_children (toplevel_directory,
+ "standard::*",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (directory_enumerator == NULL)
+ {
+ g_warning ("Error getting enumerator for %s: %s", toplevel_path, error->message);
+ g_error_free (error);
+ g_object_unref (toplevel_directory);
+ continue;
+ }
+
+ while ((file_info = g_file_enumerator_next_file (directory_enumerator, NULL, &error)) != NULL)
+ {
+ /* only consider directories */
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+ {
+ const gchar *name;
+ GFile *directory;
+ gchar *sort_key;
+
+ name = g_file_info_get_name (file_info);
+
+ /* This makes entries in directories in /etc take precedence to entries in directories in /var */
+ sort_key = g_strdup_printf ("%s-%d", name, n);
+
+ directory = g_file_get_child (toplevel_directory, name);
+ g_object_set_data_full (G_OBJECT (directory), "sort-key", sort_key, g_free);
+
+ directories = g_list_prepend (directories, directory);
+ }
+ g_object_unref (file_info);
+ }
+ if (error != NULL)
+ {
+ g_warning ("Error enumerating files in %s: %s", toplevel_path, error->message);
+ g_error_free (error);
+ g_object_unref (toplevel_directory);
+ g_object_unref (directory_enumerator);
+ continue;
+ }
+ g_object_unref (directory_enumerator);
+ g_object_unref (toplevel_directory);
+ }
+
+ /* Sort directories */
+ directories = g_list_sort (directories, (GCompareFunc) authorization_store_path_compare_func);
+
+ /* And now add an authorization store for each one */
+ for (l = directories; l != NULL; l = l->next)
{
- PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority/10-vendor.d",
- PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority/20-org.d",
- PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority/30-site.d",
- PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority/50-local.d",
- PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority/90-mandatory.d",
- NULL
- };
+ GFile *directory = G_FILE (l->data);
+ gchar *name;
+
+ name = g_file_get_path (directory);
+ g_debug ("Added `%s' as a local authorization store", name);
+ g_free (name);
+
+ add_one_authorization_store (authority, directory);
+ }
+
+ g_list_foreach (directories, (GFunc) g_object_unref, NULL);
+ g_list_free (directories);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_toplevel_authority_store_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ PolkitBackendLocalAuthority *authority = POLKIT_BACKEND_LOCAL_AUTHORITY (user_data);
+
+ purge_all_authorization_stores (authority);
+ add_all_authorization_stores (authority);
+}
+
+static void
+polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
+{
+ PolkitBackendLocalAuthorityPrivate *priv;
+ GFile *config_directory;
+ guint n;
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority);
- directory = g_file_new_for_path (PACKAGE_SYSCONF_DIR "/polkit-1/localauthority.conf.d");
- priv->config_source = polkit_backend_config_source_new (directory);
- g_object_unref (directory);
+ config_directory = g_file_new_for_path (PACKAGE_SYSCONF_DIR "/polkit-1/localauthority.conf.d");
+ priv->config_source = polkit_backend_config_source_new (config_directory);
+ g_object_unref (config_directory);
- for (n = 0; store_locations[n] != NULL; n++)
+ add_all_authorization_stores (authority);
+
+ /* Monitor the toplevels */
+ for (n = 0; n < 2; n++)
{
- PolkitBackendLocalAuthorizationStore *store;
+ const gchar *toplevel_path;
+ GFile *toplevel_directory;
+ GFileMonitor *monitor;
+ GError *error;
+
+ if (n == 0)
+ toplevel_path = PACKAGE_LOCALSTATE_DIR "/lib/polkit-1/localauthority";
+ else
+ toplevel_path = PACKAGE_SYSCONF_DIR "/polkit-1/localauthority";
+
+ toplevel_directory = g_file_new_for_path (toplevel_path);
+
+ error = NULL;
+ monitor = g_file_monitor_directory (toplevel_directory,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (monitor == NULL)
+ {
+ g_warning ("Error creating file monitor for %s: %s", toplevel_path, error->message);
+ g_error_free (error);
+ g_object_unref (toplevel_directory);
+ continue;
+ }
- directory = g_file_new_for_path (store_locations[n]);
- store = polkit_backend_local_authorization_store_new (directory, ".pkla");
- priv->authorization_stores = g_list_prepend (priv->authorization_stores, store);
- g_object_unref (directory);
+ g_debug ("Monitoring `%s' for changes", toplevel_path);
- g_signal_connect (store,
+ g_signal_connect (monitor,
"changed",
- G_CALLBACK (on_store_changed),
+ G_CALLBACK (on_toplevel_authority_store_monitor_changed),
authority);
+
+ if (n == 0)
+ priv->sysconf_dir_monitor = monitor;
+ else
+ priv->localstate_dir_monitor = monitor;
+
+ g_object_unref (toplevel_directory);
}
- priv->authorization_stores = g_list_reverse (priv->authorization_stores);
}
static void
@@ -179,12 +365,16 @@ polkit_backend_local_authority_finalize (GObject *object)
local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (object);
priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
+ purge_all_authorization_stores (local_authority);
+
+ if (priv->sysconf_dir_monitor != NULL)
+ g_object_unref (priv->sysconf_dir_monitor);
+ if (priv->localstate_dir_monitor != NULL)
+ g_object_unref (priv->localstate_dir_monitor);
+
if (priv->config_source != NULL)
g_object_unref (priv->config_source);
- g_list_foreach (priv->authorization_stores, (GFunc) g_object_unref, NULL);
- g_list_free (priv->authorization_stores);
-
G_OBJECT_CLASS (polkit_backend_local_authority_parent_class)->finalize (object);
}
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
index bdd0103..5d5dc14 100644
--- a/src/polkitbackend/polkitbackendlocalauthorizationstore.c
+++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
@@ -518,6 +518,12 @@ polkit_backend_local_authorization_store_new (GFile *directory,
static void
polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store)
{
+ gchar *path;
+
+ path = g_file_get_path (store->priv->directory);
+ g_debug ("Dropping all .pkla caches for directory `%s'", path);
+ g_free (path);
+
g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
g_list_free (store->priv->authorizations);
store->priv->authorizations = NULL;
More information about the hal-commit
mailing list