From 5bf2c57b424b0ee85f42082ed684df5acec46e45 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Wed, 15 Jul 2009 15:21:35 -0400 Subject: [PATCH] Actually make the local authority look up authorization files Still need to add test cases / docs but this seems to work great. --- 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 +++- .../polkitbackendlocalauthorizationstore.c | 616 +++++++++++++++++++++ .../polkitbackendlocalauthorizationstore.h | 83 +++ src/polkitbackend/polkitbackendtypes.h | 3 + 9 files changed, 810 insertions(+), 20 deletions(-) create mode 100644 src/polkitbackend/polkitbackendlocalauthorizationstore.c create mode 100644 src/polkitbackend/polkitbackendlocalauthorizationstore.h 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 @@ + 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
+polkitbackendlocalauthorizationstore +PolkitBackendLocalAuthorizationStore +PolkitBackendLocalAuthorizationStore +PolkitBackendLocalAuthorizationStoreClass +polkit_backend_local_authorization_store_new +polkit_backend_local_authorization_store_lookup + +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 +
+ +
polkitbackendinteractiveauthority PolkitBackendInteractiveAuthority 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 #include #include +#include #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 #include "polkitbackendconfigsource.h" #include "polkitbackendlocalauthority.h" +#include "polkitbackendlocalauthorizationstore.h" #include @@ -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 + */ + +#include "config.h" + +#include +#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. .pkla. + */ + 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. .pkla. + * + * 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 + */ + +#if !defined (_POLKIT_BACKEND_COMPILATION) && !defined(_POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H) +#error "Only 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 +#include +#include + +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 */ -- 2.7.4