PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Wed Jul 15 12:25:03 PDT 2009


 docs/polkit/polkit-1-docs.xml                            |    1 
 docs/polkit/polkit-1-sections.txt                        |   22 
 docs/polkit/polkit-1.types                               |    1 
 src/polkitbackend/Makefile.am                            |    3 
 src/polkitbackend/polkitbackend.h                        |    1 
 src/polkitbackend/polkitbackendlocalauthority.c          |  100 ++
 src/polkitbackend/polkitbackendlocalauthorizationstore.c |  616 +++++++++++++++
 src/polkitbackend/polkitbackendlocalauthorizationstore.h |   83 ++
 src/polkitbackend/polkitbackendtypes.h                   |    3 
 9 files changed, 810 insertions(+), 20 deletions(-)

New commits:
commit 5bf2c57b424b0ee85f42082ed684df5acec46e45
Author: David Zeuthen <davidz at redhat.com>
Date:   Wed Jul 15 15:21:35 2009 -0400

    Actually make the local authority look up authorization files
    
    Still need to add test cases / docs but this seems to work great.

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 at 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 at redhat.com>
+ */
+
+#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H)
+#error "Only <polkitbackend/polkitbackend.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef __POLKIT_BACKEND_LOCAL_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 */
 


More information about the hal-commit mailing list