summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2009-07-15 15:21:35 -0400
committerDavid Zeuthen <davidz@redhat.com>2009-07-15 15:21:35 -0400
commit5bf2c57b424b0ee85f42082ed684df5acec46e45 (patch)
tree573bb75fe7786a3d90b62bb11764ab48dd59a3a7
parent38f472c1c8c3868bab9950403272060b20ead0e2 (diff)
downloadpolkit-5bf2c57b424b0ee85f42082ed684df5acec46e45.tar.gz
Actually make the local authority look up authorization files
Still need to add test cases / docs but this seems to work great.
-rw-r--r--docs/polkit/polkit-1-docs.xml1
-rw-r--r--docs/polkit/polkit-1-sections.txt22
-rw-r--r--docs/polkit/polkit-1.types1
-rw-r--r--src/polkitbackend/Makefile.am3
-rw-r--r--src/polkitbackend/polkitbackend.h1
-rw-r--r--src/polkitbackend/polkitbackendlocalauthority.c100
-rw-r--r--src/polkitbackend/polkitbackendlocalauthorizationstore.c616
-rw-r--r--src/polkitbackend/polkitbackendlocalauthorizationstore.h83
-rw-r--r--src/polkitbackend/polkitbackendtypes.h3
9 files changed, 810 insertions, 20 deletions
diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml
index 4744e58..0e4f70e 100644
--- a/docs/polkit/polkit-1-docs.xml
+++ b/docs/polkit/polkit-1-docs.xml
@@ -92,6 +92,7 @@
<xi:include href="xml/polkitbackendauthority.xml"/>
<xi:include href="xml/polkitbackendinteractiveauthority.xml"/>
<xi:include href="xml/polkitbackendlocalauthority.xml"/>
+ <xi:include href="xml/polkitbackendlocalauthorizationstore.xml"/>
<xi:include href="xml/polkitbackendactionpool.xml"/>
<xi:include href="xml/polkitbackendsessionmonitor.xml"/>
<xi:include href="xml/polkitbackendconfigsource.xml"/>
diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt
index a5a03c8..1e3bd8c 100644
--- a/docs/polkit/polkit-1-sections.txt
+++ b/docs/polkit/polkit-1-sections.txt
@@ -251,11 +251,6 @@ polkit_backend_authority_register_authentication_agent
polkit_backend_authority_unregister_authentication_agent
polkit_backend_authority_authentication_agent_response
polkit_backend_authority_enumerate_actions
-polkit_backend_authority_enumerate_users
-polkit_backend_authority_enumerate_groups
-polkit_backend_authority_enumerate_authorizations
-polkit_backend_authority_add_authorization
-polkit_backend_authority_remove_authorization
polkit_backend_authority_system_bus_name_owner_changed
polkit_backend_authority_get
polkit_backend_register_authority
@@ -302,6 +297,23 @@ POLKIT_BACKEND_LOCAL_AUTHORITY_GET_CLASS
</SECTION>
<SECTION>
+<FILE>polkitbackendlocalauthorizationstore</FILE>
+<TITLE>PolkitBackendLocalAuthorizationStore</TITLE>
+PolkitBackendLocalAuthorizationStore
+PolkitBackendLocalAuthorizationStoreClass
+polkit_backend_local_authorization_store_new
+polkit_backend_local_authorization_store_lookup
+<SUBSECTION Standard>
+POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE
+POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE
+POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE
+polkit_backend_local_authorization_store_get_type
+POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_CLASS
+POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE_CLASS
+POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_GET_CLASS
+</SECTION>
+
+<SECTION>
<FILE>polkitbackendinteractiveauthority</FILE>
<TITLE>PolkitBackendInteractiveAuthority</TITLE>
PolkitBackendInteractiveAuthority
diff --git a/docs/polkit/polkit-1.types b/docs/polkit/polkit-1.types
index fd9fe53..c212fd2 100644
--- a/docs/polkit/polkit-1.types
+++ b/docs/polkit/polkit-1.types
@@ -20,6 +20,7 @@ polkit_backend_action_lookup_get_type
polkit_backend_action_pool_get_type
polkit_backend_session_monitor_get_type
polkit_backend_config_source_get_type
+polkit_backend_local_authorization_store_get_type
polkit_agent_session_get_type
polkit_agent_listener_get_type
diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am
index a41201f..6854609 100644
--- a/src/polkitbackend/Makefile.am
+++ b/src/polkitbackend/Makefile.am
@@ -47,6 +47,7 @@ libpolkit_backend_1include_HEADERS = \
polkitbackendsessionmonitor.h \
polkitbackendconfigsource.h \
polkitbackendactionlookup.h \
+ polkitbackendlocalauthorizationstore.h \
$(NULL)
libpolkit_backend_1_la_SOURCES = \
@@ -62,6 +63,7 @@ libpolkit_backend_1_la_SOURCES = \
polkitbackendsessionmonitor.h polkitbackendsessionmonitor.c \
polkitbackendconfigsource.h polkitbackendconfigsource.c \
polkitbackendactionlookup.h polkitbackendactionlookup.c \
+ polkitbackendlocalauthorizationstore.h polkitbackendlocalauthorizationstore.c \
$(NULL)
libpolkit_backend_1_la_CFLAGS = \
@@ -97,4 +99,5 @@ clean-local :
install-exec-hook:
mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1
-chmod 600 $(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}
mkdir -p $(DESTDIR)$(libdir)/polkit-1/extensions
diff --git a/src/polkitbackend/polkitbackend.h b/src/polkitbackend/polkitbackend.h
index c734945..44b5176 100644
--- a/src/polkitbackend/polkitbackend.h
+++ b/src/polkitbackend/polkitbackend.h
@@ -37,6 +37,7 @@
#include <polkitbackend/polkitbackendsessionmonitor.h>
#include <polkitbackend/polkitbackendconfigsource.h>
#include <polkitbackend/polkitbackendactionlookup.h>
+#include <polkitbackend/polkitbackendlocalauthorizationstore.h>
#undef _POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H
#endif /* __POLKIT_BACKEND_H */
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index d18108e..ce3a7d3 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -30,6 +30,7 @@
#include <polkit/polkit.h>
#include "polkitbackendconfigsource.h"
#include "polkitbackendlocalauthority.h"
+#include "polkitbackendlocalauthorizationstore.h"
#include <polkit/polkitprivate.h>
@@ -45,14 +46,10 @@
/* ---------------------------------------------------------------------------------------------------- */
-static GList *get_users_in_group (PolkitBackendInteractiveAuthority *authority,
- PolkitIdentity *group,
+static GList *get_users_in_group (PolkitIdentity *group,
gboolean include_root);
-#if 0
-static GList *get_groups_for_user (PolkitBackendInteractiveAuthority *authority,
- PolkitIdentity *user);
-#endif
+static GList *get_groups_for_user (PolkitIdentity *user);
/* ---------------------------------------------------------------------------------------------------- */
@@ -60,6 +57,8 @@ typedef struct
{
PolkitBackendConfigSource *config_source;
+ GList *authorization_stores;
+
} PolkitBackendLocalAuthorityPrivate;
/* ---------------------------------------------------------------------------------------------------- */
@@ -98,12 +97,33 @@ polkit_backend_local_authority_init (PolkitBackendLocalAuthority *authority)
{
PolkitBackendLocalAuthorityPrivate *priv;
GFile *directory;
+ guint n;
+ const gchar *store_locations[] =
+ {
+ 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
+ };
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);
+
+ for (n = 0; store_locations[n] != NULL; n++)
+ {
+ PolkitBackendLocalAuthorizationStore *store;
+
+ 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);
+ }
+ priv->authorization_stores = g_list_reverse (priv->authorization_stores);
}
static void
@@ -118,6 +138,9 @@ polkit_backend_local_authority_finalize (GObject *object)
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);
}
@@ -188,7 +211,7 @@ polkit_backend_local_authority_get_admin_auth_identities (PolkitBackendInteracti
}
else if (POLKIT_IS_UNIX_GROUP (identity))
{
- ret = g_list_concat (ret, get_users_in_group (authority, identity, FALSE));
+ ret = g_list_concat (ret, get_users_in_group (identity, FALSE));
}
else
{
@@ -218,20 +241,70 @@ polkit_backend_local_authority_check_authorization_sync (PolkitBackendInteractiv
PolkitDetails *details,
PolkitImplicitAuthorization implicit)
{
+ PolkitBackendLocalAuthority *local_authority;
+ PolkitBackendLocalAuthorityPrivate *priv;
+ PolkitImplicitAuthorization ret;
+ GList *groups;
+ GList *l, *ll;
+
+ ret = implicit;
+
+ local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority);
+ priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority);
+
+#if 0
g_debug ("local: checking `%s' for subject `%s' (user `%s')",
action_id,
polkit_subject_to_string (subject),
polkit_identity_to_string (user_for_subject));
+#endif
- return implicit;
+ /* First lookup for all groups the user belong to */
+ groups = get_groups_for_user (user_for_subject);
+ for (ll = groups; ll != NULL; ll = ll->next)
+ {
+ PolkitIdentity *group = POLKIT_IDENTITY (ll->data);
+
+ for (l = priv->authorization_stores; l != NULL; l = l->next)
+ {
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
+
+ if (polkit_backend_local_authorization_store_lookup (store,
+ group,
+ action_id,
+ details,
+ &ret))
+ {
+ ; /* do nothing */
+ }
+ }
+ }
+ g_list_foreach (groups, (GFunc) g_object_unref, NULL);
+ g_list_free (groups);
+
+ /* Then do it for the user */
+ for (l = priv->authorization_stores; l != NULL; l = l->next)
+ {
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (l->data);
+
+ if (polkit_backend_local_authorization_store_lookup (store,
+ user_for_subject,
+ action_id,
+ details,
+ &ret))
+ {
+ ; /* do nothing */
+ }
+ }
+
+ return ret;
}
/* ---------------------------------------------------------------------------------------------------- */
static GList *
-get_users_in_group (PolkitBackendInteractiveAuthority *authority,
- PolkitIdentity *group,
- gboolean include_root)
+get_users_in_group (PolkitIdentity *group,
+ gboolean include_root)
{
gid_t gid;
struct group *grp;
@@ -275,10 +348,8 @@ get_users_in_group (PolkitBackendInteractiveAuthority *authority,
return ret;
}
-#if 0
static GList *
-get_groups_for_user (PolkitBackendInteractiveAuthority *authority,
- PolkitIdentity *user)
+get_groups_for_user (PolkitIdentity *user)
{
uid_t uid;
struct passwd *passwd;
@@ -317,6 +388,5 @@ get_groups_for_user (PolkitBackendInteractiveAuthority *authority,
return result;
}
-#endif
/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.c b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
new file mode 100644
index 0000000..a183351
--- /dev/null
+++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#include "config.h"
+
+#include <polkit/polkit.h>
+#include "polkitbackendlocalauthorizationstore.h"
+
+/**
+ * SECTION:polkitbackendlocalauthorizationstore
+ * @title: PolkitBackendLocalAuthorizationStore
+ * @short_description: Watches a directory for authorization files
+ *
+ * #PolkitBackendLocalAuthorizationStore is a utility class to watch
+ * and read authorization files from a directory.
+ */
+
+struct _PolkitBackendLocalAuthorizationStorePrivate
+{
+ GFile *directory;
+ gchar *extension;
+
+ GFileMonitor *directory_monitor;
+
+ /* List of LocalAuthorization objects */
+ GList *authorizations;
+
+ gboolean has_data;
+};
+
+enum
+{
+ PROP_0,
+ PROP_DIRECTORY,
+ PROP_EXTENSION,
+};
+
+enum
+{
+ CHANGED_SIGNAL,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+static void polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store);
+
+static void polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store);
+
+G_DEFINE_TYPE (PolkitBackendLocalAuthorizationStore, polkit_backend_local_authorization_store, G_TYPE_OBJECT);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+ gchar *id;
+
+ GList *identity_specs;
+ GList *action_specs;
+
+ PolkitImplicitAuthorization result;
+} LocalAuthorization;
+
+static void
+local_authorization_free (LocalAuthorization *authorization)
+{
+ g_free (authorization->id);
+ g_list_foreach (authorization->identity_specs, (GFunc) g_pattern_spec_free, NULL);
+ g_list_free (authorization->identity_specs);
+ g_list_foreach (authorization->action_specs, (GFunc) g_pattern_spec_free, NULL);
+ g_list_free (authorization->action_specs);
+ g_free (authorization);
+}
+
+
+static LocalAuthorization *
+local_authorization_new (GKeyFile *key_file,
+ const gchar *filename,
+ const gchar *group,
+ GError **error)
+{
+ LocalAuthorization *authorization;
+ gchar **identity_strings;
+ gchar **action_strings;
+ gchar *result_string;
+ guint n;
+
+ identity_strings = NULL;
+ action_strings = NULL;
+ result_string = NULL;
+
+ authorization = g_new0 (LocalAuthorization, 1);
+
+ identity_strings = g_key_file_get_string_list (key_file,
+ group,
+ "Identity",
+ NULL,
+ error);
+ if (identity_strings == NULL)
+ {
+ local_authorization_free (authorization);
+ authorization = NULL;
+ goto out;
+ }
+ for (n = 0; identity_strings[n] != NULL; n++)
+ {
+ authorization->identity_specs = g_list_prepend (authorization->identity_specs,
+ g_pattern_spec_new (identity_strings[n]));
+ }
+
+ action_strings = g_key_file_get_string_list (key_file,
+ group,
+ "Action",
+ NULL,
+ error);
+ if (action_strings == NULL)
+ {
+ local_authorization_free (authorization);
+ authorization = NULL;
+ goto out;
+ }
+ for (n = 0; action_strings[n] != NULL; n++)
+ {
+ authorization->action_specs = g_list_prepend (authorization->action_specs,
+ g_pattern_spec_new (action_strings[n]));
+ }
+
+ result_string = g_key_file_get_string (key_file,
+ group,
+ "Result",
+ error);
+ if (result_string == NULL)
+ {
+ local_authorization_free (authorization);
+ authorization = NULL;
+ goto out;
+ }
+
+ if (!polkit_implicit_authorization_from_string (result_string,
+ &authorization->result))
+ {
+ g_set_error (error,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "Cannot parse Result string `%s'", result_string);
+ local_authorization_free (authorization);
+ authorization = NULL;
+ goto out;
+ }
+
+ authorization->id = g_strdup_printf ("%s::%s", filename, group);
+
+ out:
+ g_strfreev (identity_strings);
+ g_free (action_strings);
+ g_free (result_string);
+ return authorization;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+polkit_backend_local_authorization_store_init (PolkitBackendLocalAuthorizationStore *store)
+{
+ store->priv = G_TYPE_INSTANCE_GET_PRIVATE (store,
+ POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
+ PolkitBackendLocalAuthorizationStorePrivate);
+}
+
+static void
+polkit_backend_local_authorization_store_finalize (GObject *object)
+{
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
+
+ if (store->priv->directory != NULL)
+ g_object_unref (store->priv->directory);
+ g_free (store->priv->extension);
+
+ if (store->priv->directory_monitor != NULL)
+ g_object_unref (store->priv->directory_monitor);
+
+ g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
+ g_list_free (store->priv->authorizations);
+
+ if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->finalize (object);
+}
+
+
+static void
+polkit_backend_local_authorization_store_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ g_value_set_object (value, store->priv->directory);
+ break;
+
+ case PROP_EXTENSION:
+ g_value_set_string (value, store->priv->extension);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+polkit_backend_local_authorization_store_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
+
+ switch (prop_id)
+ {
+ case PROP_DIRECTORY:
+ store->priv->directory = g_value_dup_object (value);
+ break;
+
+ case PROP_EXTENSION:
+ store->priv->extension = g_value_dup_string (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+directory_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ gpointer user_data)
+{
+ PolkitBackendLocalAuthorizationStore *store;
+
+ store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (user_data);
+
+ if (file != NULL)
+ {
+ gchar *name;
+
+ name = g_file_get_basename (file);
+
+ //g_debug ("event_type=%d file=%p name=%s", event_type, file, name);
+
+ if (!g_str_has_prefix (name, ".") &&
+ !g_str_has_prefix (name, "#") &&
+ g_str_has_suffix (name, store->priv->extension) &&
+ (event_type == G_FILE_MONITOR_EVENT_CREATED ||
+ event_type == G_FILE_MONITOR_EVENT_DELETED ||
+ event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT))
+ {
+
+ //g_debug ("match");
+
+ /* now throw away all caches */
+ polkit_backend_local_authorization_store_purge (store);
+ g_signal_emit_by_name (store, "changed");
+ }
+
+ g_free (name);
+ }
+}
+
+static void
+polkit_backend_local_authorization_store_constructed (GObject *object)
+{
+ PolkitBackendLocalAuthorizationStore *store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (object);
+ GError *error;
+
+ error = NULL;
+ store->priv->directory_monitor = g_file_monitor_directory (store->priv->directory,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (store->priv->directory_monitor == NULL)
+ {
+ gchar *dir_name;
+ dir_name = g_file_get_uri (store->priv->directory);
+ g_warning ("Error monitoring directory %s: %s", dir_name, error->message);
+ g_free (dir_name);
+ g_error_free (error);
+ }
+ else
+ {
+ g_signal_connect (store->priv->directory_monitor,
+ "changed",
+ (GCallback) directory_monitor_changed,
+ store);
+ }
+
+ if (G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed != NULL)
+ G_OBJECT_CLASS (polkit_backend_local_authorization_store_parent_class)->constructed (object);
+}
+
+static void
+polkit_backend_local_authorization_store_class_init (PolkitBackendLocalAuthorizationStoreClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = polkit_backend_local_authorization_store_get_property;
+ gobject_class->set_property = polkit_backend_local_authorization_store_set_property;
+ gobject_class->constructed = polkit_backend_local_authorization_store_constructed;
+ gobject_class->finalize = polkit_backend_local_authorization_store_finalize;
+
+ g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorizationStorePrivate));
+
+ /**
+ * PolkitBackendLocalAuthorizationStore:directory:
+ *
+ * The directory to watch for authorization files.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_DIRECTORY,
+ g_param_spec_object ("directory",
+ "Directory",
+ "The directory to watch for configuration files",
+ G_TYPE_FILE,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * PolkitBackendLocalAuthorizationStore:extension:
+ *
+ * The file extension for files to consider, e.g. <quote>.pkla</quote>.
+ */
+ g_object_class_install_property (gobject_class,
+ PROP_EXTENSION,
+ g_param_spec_string ("extension",
+ "Extension",
+ "The extension of files to consider",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_NAME |
+ G_PARAM_STATIC_BLURB |
+ G_PARAM_STATIC_NICK));
+
+ /**
+ * PolkitBackendConfiguStore::changed:
+ * @store: A #PolkitBackendLocalAuthorizationStore.
+ *
+ * Emitted when configuration files in #PolkitBackendConfiguStore:directory changes.
+ */
+ signals[CHANGED_SIGNAL] = g_signal_new ("changed",
+ POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (PolkitBackendLocalAuthorizationStoreClass, changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+/**
+ * polkit_backend_local_authorization_store_new:
+ * @directory: The directory to watch.
+ * @extension: The extension of files to consider e.g. <quote>.pkla</quote>.
+ *
+ * Creates a new #PolkitBackendLocalAuthorizationStore object that
+ * reads authorizations from @directory with file extension
+ * @extension. To watch for configuration changes, connect to the
+ * #PolkitBackendLocalAuthorizationStore::changed signal.
+ *
+ * Returns: A #PolkitBackendLocalAuthorizationStore. Free with
+ * g_object_unref().
+ **/
+PolkitBackendLocalAuthorizationStore *
+polkit_backend_local_authorization_store_new (GFile *directory,
+ const gchar *extension)
+{
+ PolkitBackendLocalAuthorizationStore *store;
+
+ store = POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE (g_object_new (POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,
+ "directory", directory,
+ "extension", extension,
+ NULL));
+
+ return store;
+}
+
+static void
+polkit_backend_local_authorization_store_purge (PolkitBackendLocalAuthorizationStore *store)
+{
+ g_list_foreach (store->priv->authorizations, (GFunc) local_authorization_free, NULL);
+ g_list_free (store->priv->authorizations);
+ store->priv->authorizations = NULL;
+
+ store->priv->has_data = FALSE;
+}
+
+static void
+polkit_backend_local_authorization_store_ensure (PolkitBackendLocalAuthorizationStore *store)
+{
+ GFileEnumerator *enumerator;
+ GFileInfo *file_info;
+ GError *error;
+ GList *files;
+ GList *l;
+
+ files = NULL;
+
+ if (store->priv->has_data)
+ goto out;
+
+ polkit_backend_local_authorization_store_purge (store);
+
+ error = NULL;
+ enumerator = g_file_enumerate_children (store->priv->directory,
+ "standard::*",
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ &error);
+ if (enumerator == NULL)
+ {
+ gchar *dir_name;
+ dir_name = g_file_get_uri (store->priv->directory);
+ g_warning ("Error enumerating files in %s: %s", dir_name, error->message);
+ g_free (dir_name);
+ g_error_free (error);
+ goto out;
+ }
+
+ while ((file_info = g_file_enumerator_next_file (enumerator, NULL, &error)) != NULL)
+ {
+ const gchar *name;
+
+ name = g_file_info_get_name (file_info);
+
+ /* only consider files with the appropriate extension */
+ if (g_str_has_suffix (name, store->priv->extension))
+ files = g_list_prepend (files, g_file_get_child (store->priv->directory, name));
+
+ g_object_unref (file_info);
+ }
+ g_object_unref (enumerator);
+ if (error != NULL)
+ {
+ g_warning ("Error enumerating files: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /* process files; highest priority comes first */
+ for (l = files; l != NULL; l = l->next)
+ {
+ GFile *file = G_FILE (l->data);
+ gchar *filename;
+ GKeyFile *key_file;
+
+ filename = g_file_get_path (file);
+
+ key_file = g_key_file_new ();
+
+ error = NULL;
+ if (!g_key_file_load_from_file (key_file,
+ filename,
+ G_KEY_FILE_NONE,
+ NULL))
+ {
+ g_warning ("Error loading key-file %s: %s", filename, error->message);
+ g_error_free (error);
+ error = NULL;
+ g_key_file_free (key_file);
+ }
+ else
+ {
+ gchar **groups;
+ guint n;
+
+ groups = g_key_file_get_groups (key_file, NULL);
+ for (n = 0; groups[n] != NULL; n++)
+ {
+ LocalAuthorization *authorization;
+
+ error = NULL;
+ authorization = local_authorization_new (key_file, filename, groups[n], &error);
+ if (authorization == NULL)
+ {
+ g_warning ("Error parsing group `%s' in file `%s': %s",
+ groups[n],
+ filename,
+ error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ store->priv->authorizations = g_list_prepend (store->priv->authorizations,
+ authorization);
+ }
+ }
+ g_strfreev (groups);
+
+ store->priv->authorizations = g_list_reverse (store->priv->authorizations);
+
+ g_key_file_free (key_file);
+ }
+
+ g_free (filename);
+ }
+
+ out:
+ g_list_foreach (files, (GFunc) g_object_unref, NULL);
+ g_list_free (files);
+}
+
+/**
+ * polkit_backend_local_authorization_store_lookup:
+ * @store: A #PolkitBackendLocalAuthorizationStore.
+ * @identity: The identity to check for.
+ * @action_id: The action id to check for.
+ * @details: Details for @action.
+ * @out_result: Return location for the result if the look up matched.
+ *
+ * Checks if an authorization entry from @store matches @identity, @action_id and @details.
+ *
+ * Returns: %TRUE if @store has an authorization entry that matches
+ * @identity, @action_id and @details. Otherwise %FALSE.
+ */
+gboolean
+polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorizationStore *store,
+ PolkitIdentity *identity,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitImplicitAuthorization *out_result)
+{
+ GList *l, *ll;
+ gboolean ret;
+ gchar *identity_string;
+
+ g_return_val_if_fail (POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE (store), FALSE);
+ g_return_val_if_fail (POLKIT_IS_IDENTITY (identity), FALSE);
+ g_return_val_if_fail (action_id != NULL, FALSE);
+ g_return_val_if_fail (POLKIT_IS_DETAILS (details), FALSE);
+ g_return_val_if_fail (out_result != NULL, FALSE);
+
+ ret = FALSE;
+ identity_string = NULL;
+
+ polkit_backend_local_authorization_store_ensure (store);
+
+ for (l = store->priv->authorizations; l != NULL; l = l->next)
+ {
+ LocalAuthorization *authorization = l->data;
+
+ /* first match the action */
+ for (ll = authorization->action_specs; ll != NULL; ll = ll->next)
+ {
+ if (g_pattern_match_string ((GPatternSpec *) ll->data, action_id))
+ break;
+ }
+ if (ll == NULL)
+ continue;
+
+ /* then match the identity */
+ if (identity_string == NULL)
+ identity_string = polkit_identity_to_string (identity);
+ for (ll = authorization->identity_specs; ll != NULL; ll = ll->next)
+ {
+ if (g_pattern_match_string ((GPatternSpec *) ll->data, identity_string))
+ break;
+ }
+ if (ll == NULL)
+ continue;
+
+ /* Yay, a match! However, keep going since subsequent authorization entries may modify the result */
+ *out_result = authorization->result;
+ ret = TRUE;
+
+#if 0
+ g_debug ("authorization with id `%s' matched action_id `%s' for identity `%s'",
+ authorization->id,
+ action_id,
+ polkit_identity_to_string (identity));
+#endif
+ }
+
+ g_free (identity_string);
+
+ return ret;
+}
diff --git a/src/polkitbackend/polkitbackendlocalauthorizationstore.h b/src/polkitbackend/polkitbackendlocalauthorizationstore.h
new file mode 100644
index 0000000..426ea69
--- /dev/null
+++ b/src/polkitbackend/polkitbackendlocalauthorizationstore.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz@redhat.com>
+ */
+
+#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
+#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H
+#define __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <polkitbackend/polkitbackendtypes.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE (polkit_backend_local_authorization_store_get_type ())
+#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE, PolkitBackendLocalAuthorizationStore))
+#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE, PolkitBackendLocalAuthorizationStoreClass))
+#define POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE,PolkitBackendLocalAuthorizationStoreClass))
+#define POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE))
+#define POLKIT_BACKEND_IS_LOCAL_AUTHORIZATION_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_LOCAL_AUTHORIZATION_STORE))
+
+typedef struct _PolkitBackendLocalAuthorizationStoreClass PolkitBackendLocalAuthorizationStoreClass;
+typedef struct _PolkitBackendLocalAuthorizationStorePrivate PolkitBackendLocalAuthorizationStorePrivate;
+
+struct _PolkitBackendLocalAuthorizationStore
+{
+ GObject parent_instance;
+ PolkitBackendLocalAuthorizationStorePrivate *priv;
+};
+
+struct _PolkitBackendLocalAuthorizationStoreClass
+{
+ /*< public >*/
+ GObjectClass parent_class;
+
+ /* Signals */
+ void (*changed) (PolkitBackendLocalAuthorizationStore *store);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_polkit_reserved1) (void);
+ void (*_polkit_reserved2) (void);
+ void (*_polkit_reserved3) (void);
+ void (*_polkit_reserved4) (void);
+ void (*_polkit_reserved5) (void);
+ void (*_polkit_reserved6) (void);
+ void (*_polkit_reserved7) (void);
+ void (*_polkit_reserved8) (void);
+};
+
+GType polkit_backend_local_authorization_store_get_type (void) G_GNUC_CONST;
+PolkitBackendLocalAuthorizationStore *polkit_backend_local_authorization_store_new (GFile *directory,
+ const gchar *extension);
+gboolean polkit_backend_local_authorization_store_lookup (PolkitBackendLocalAuthorizationStore *store,
+ PolkitIdentity *identity,
+ const gchar *action_id,
+ PolkitDetails *details,
+ PolkitImplicitAuthorization *out_result);
+
+G_END_DECLS
+
+#endif /* __POLKIT_BACKEND_LOCAL_AUTHORIZATION_STORE_H */
+
diff --git a/src/polkitbackend/polkitbackendtypes.h b/src/polkitbackend/polkitbackendtypes.h
index e130d16..6ebc881 100644
--- a/src/polkitbackend/polkitbackendtypes.h
+++ b/src/polkitbackend/polkitbackendtypes.h
@@ -42,5 +42,8 @@ typedef struct _PolkitBackendInteractiveAuthority PolkitBackendInteractiveAuthor
struct _PolkitBackendLocalAuthority;
typedef struct _PolkitBackendLocalAuthority PolkitBackendLocalAuthority;
+struct _PolkitBackendLocalAuthorizationStore;
+typedef struct _PolkitBackendLocalAuthorizationStore PolkitBackendLocalAuthorizationStore;
+
#endif /* __POLKIT_BACKEND_TYPES_H */