From 600bca82cfeebdcde832d330a2c896c18026bf89 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 23 Jul 2007 22:22:38 -0400 Subject: [PATCH] add support for an /etc/PolicyKit/PolicyKit.conf config file With this, system administrators can override policy. Partial support, more to come (including manual pages and documentation) later. --- data/Makefile.am | 19 +- polkit-dbus/Makefile.am | 2 +- polkit-grant/Makefile.am | 7 +- polkit-grant/polkit-grant-helper.c | 2 +- polkit/Makefile.am | 15 +- polkit/polkit-config.c | 536 +++++++++++++++++++++++ polkit/polkit-config.h | 60 +++ polkit/polkit-context.c | 200 +++------ {polkit-grant => polkit}/polkit-grant-database.c | 6 +- {polkit-grant => polkit}/polkit-grant-database.h | 0 10 files changed, 694 insertions(+), 153 deletions(-) create mode 100644 polkit/polkit-config.c create mode 100644 polkit/polkit-config.h rename {polkit-grant => polkit}/polkit-grant-database.c (98%) rename {polkit-grant => polkit}/polkit-grant-database.h (100%) diff --git a/data/Makefile.am b/data/Makefile.am index 0de382e..8ff233c 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -6,9 +6,24 @@ pam_DATA = polkit pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = polkit.pc polkit-dbus.pc polkit-grant.pc -DISTCLEANFILES = polkit.pc polkit-dbus.pc polkit-grant.pc +confdir = $(sysconfdir)/PolicyKit +conf_DATA = PolicyKit.conf -EXTRA_DIST = polkit.in polkit.pc.in polkit-dbus.pc.in polkit-grant.pc.in +dtddir = $(datadir)/PolicyKit +dtd_DATA = config.dtd + +DISTCLEANFILES = polkit.pc polkit-dbus.pc polkit-grant.pc PolicyKit.conf + +EXTRA_DIST = polkit.in polkit.pc.in polkit-dbus.pc.in polkit-grant.pc.in PolicyKit.conf.in clean-local : rm -f *~ + +PolicyKit.conf: PolicyKit.conf.in Makefile + $(edit) $< >$@ + +edit = sed \ + -e 's|@docdir[@]|$(docdir)|g' \ + -e 's|@sbindir[@]|$(sbindir)|g' \ + -e 's|@sysconfdir[@]|$(sysconfdir)|g' \ + -e 's|@datadir[@]|$(datadir)|g' diff --git a/polkit-dbus/Makefile.am b/polkit-dbus/Makefile.am index 0cee725..3b16b60 100644 --- a/polkit-dbus/Makefile.am +++ b/polkit-dbus/Makefile.am @@ -22,7 +22,7 @@ libpolkit_dbusinclude_HEADERS = \ libpolkit_dbus_la_SOURCES = \ polkit-dbus.h polkit-dbus.c -libpolkit_dbus_la_LIBADD = @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la +libpolkit_dbus_la_LIBADD = @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(SELINUX_LIBS) libpolkit_dbus_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) diff --git a/polkit-grant/Makefile.am b/polkit-grant/Makefile.am index 4e1bc1c..9dc626c 100644 --- a/polkit-grant/Makefile.am +++ b/polkit-grant/Makefile.am @@ -12,11 +12,6 @@ INCLUDES = \ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ @GLIB_CFLAGS@ @DBUS_CFLAGS@ -noinst_LTLIBRARIES=libpolkit-grant-private.la - -libpolkit_grant_private_la_SOURCES = \ - polkit-grant-database.h polkit-grant-database.c - lib_LTLIBRARIES=libpolkit-grant.la libpolkit_grantincludedir=$(includedir)/PolicyKit/polkit-grant @@ -34,7 +29,7 @@ libpolkit_grant_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE libexec_PROGRAMS = polkit-grant-helper polkit_grant_helper_SOURCES = polkit-grant-helper.c -polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @AUTH_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit-grant/libpolkit-grant-private.la +polkit_grant_helper_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @AUTH_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit/libpolkit-grant-private.la polkit_grant_alwaysdir = $(localstatedir)/lib/PolicyKit dist_polkit_grant_always_DATA = diff --git a/polkit-grant/polkit-grant-helper.c b/polkit-grant/polkit-grant-helper.c index 8d12f40..f428dab 100644 --- a/polkit-grant/polkit-grant-helper.c +++ b/polkit-grant/polkit-grant-helper.c @@ -41,7 +41,7 @@ #include -#include "polkit-grant-database.h" +#include static int conversation_function (int n, diff --git a/polkit/Makefile.am b/polkit/Makefile.am index 36fae4c..d0bbd1f 100644 --- a/polkit/Makefile.am +++ b/polkit/Makefile.am @@ -6,13 +6,19 @@ INCLUDES = \ -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ - -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT \ -DPOLKIT_COMPILATION \ @GLIB_CFLAGS@ + +noinst_LTLIBRARIES=libpolkit-grant-private.la + +libpolkit_grant_private_la_SOURCES = \ + polkit-grant-database.h polkit-grant-database.c + lib_LTLIBRARIES=libpolkit.la libpolkitincludedir=$(includedir)/PolicyKit/polkit @@ -47,9 +53,10 @@ libpolkit_la_SOURCES = \ polkit-policy-cache.h polkit-policy-cache.c \ polkit-policy-default.h polkit-policy-default.c \ polkit-debug.h polkit-debug.c \ - polkit-utils.h polkit-utils.c + polkit-utils.h polkit-utils.c \ + polkit-config.h polkit-config.c -libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@ -ldl +libpolkit_la_LIBADD = @GLIB_LIBS@ @EXPAT_LIBS@ libpolkit-grant-private.la libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) @@ -60,5 +67,5 @@ clean-local : # for config file changes. install-data-local: touch $(DESTDIR)$(localstatedir)/lib/PolicyKit/reload - -chmod 700 $(DESTDIR)$(localstatedir)/lib/PolicyKit/reload + -chmod 755 $(DESTDIR)$(localstatedir)/lib/PolicyKit/reload diff --git a/polkit/polkit-config.c b/polkit/polkit-config.c new file mode 100644 index 0000000..aff9fb4 --- /dev/null +++ b/polkit/polkit-config.c @@ -0,0 +1,536 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-config.h : Configuration file + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "polkit-config.h" +#include "polkit-debug.h" +#include "polkit-error.h" + +enum { + STATE_NONE, + STATE_IN_CONFIG, + STATE_IN_MATCH, + STATE_IN_RETURN, +}; + +struct ConfigNode; +typedef struct ConfigNode ConfigNode; + +struct PolKitConfig +{ + int refcount; + ConfigNode *top_config_node; +}; + +#define PARSER_MAX_DEPTH 32 + +typedef struct { + XML_Parser parser; + int state; + PolKitConfig *pk_config; + + int state_stack[PARSER_MAX_DEPTH]; + ConfigNode *node_stack[PARSER_MAX_DEPTH]; + + int stack_depth; +} ParserData; + +enum { + NODE_TYPE_TOP, + NODE_TYPE_MATCH, + NODE_TYPE_RETURN, +}; + +enum { + MATCH_TYPE_ACTION, + MATCH_TYPE_USER, +}; + +static const char * const match_names[] = +{ + "action", + "user", +}; + +struct ConfigNode +{ + int node_type; + + union { + + struct { + int match_type; + char *data; + regex_t preq; + } node_match; + + struct { + PolKitResult result; + } node_return; + + } data; + + GSList *children; +}; + +static ConfigNode * +config_node_new (void) +{ + ConfigNode *node; + node = g_new0 (ConfigNode, 1); + return node; +} + +static void +config_node_dump_real (ConfigNode *node, unsigned int indent) +{ + GSList *i; + unsigned int n; + char buf[128]; + + for (n = 0; n < indent && n < sizeof (buf) - 1; n++) + buf[n] = ' '; + buf[n] = '\0'; + + switch (node->node_type) { + case NODE_TYPE_TOP: + _pk_debug ("%sTOP", buf); + break; + case NODE_TYPE_MATCH: + _pk_debug ("%sMATCH %s (%d) with '%s'", + buf, + match_names[node->data.node_match.match_type], + node->data.node_match.match_type, + node->data.node_match.data); + break; + case NODE_TYPE_RETURN: + _pk_debug ("%sRETURN %s (%d)", + buf, + polkit_result_to_string_representation (node->data.node_return.result), + node->data.node_return.result); + break; + } + + for (i = node->children; i != NULL; i = g_slist_next (i)) { + ConfigNode *child = i->data; + config_node_dump_real (child, indent + 2); + } +} + +static void +config_node_dump (ConfigNode *node) +{ + + config_node_dump_real (node, 0); +} + +static void +config_node_unref (ConfigNode *node) +{ + GSList *i; + + switch (node->node_type) { + case NODE_TYPE_TOP: + break; + case NODE_TYPE_MATCH: + g_free (node->data.node_match.data); + regfree (&(node->data.node_match.preq)); + break; + case NODE_TYPE_RETURN: + break; + } + + for (i = node->children; i != NULL; i = g_slist_next (i)) { + ConfigNode *child = i->data; + config_node_unref (child); + } + g_slist_free (node->children); + g_free (node); +} + +static void +_start (void *data, const char *el, const char **attr) +{ + int state; + int num_attr; + ParserData *pd = data; + ConfigNode *node; + + _pk_debug ("_start for node '%s'", el); + + for (num_attr = 0; attr[num_attr] != NULL; num_attr++) + ; + + state = STATE_NONE; + node = NULL; + + switch (pd->state) { + case STATE_NONE: + if (strcmp (el, "config") == 0) { + state = STATE_IN_CONFIG; + _pk_debug ("parsed config node"); + + if (pd->pk_config->top_config_node != NULL) { + _pk_debug ("Multiple config nodes?"); + goto error; + } + + node = config_node_new (); + node->node_type = NODE_TYPE_TOP; + pd->pk_config->top_config_node = node; + } + break; + case STATE_IN_CONFIG: /* explicit fallthrough */ + case STATE_IN_MATCH: + if ((strcmp (el, "match") == 0) && (num_attr == 2)) { + + node = config_node_new (); + node->node_type = NODE_TYPE_MATCH; + if (strcmp (attr[0], "action") == 0) { + node->data.node_match.match_type = MATCH_TYPE_ACTION; + } else if (strcmp (attr[0], "user") == 0) { + node->data.node_match.match_type = MATCH_TYPE_USER; + } else { + _pk_debug ("Unknown match rule '%s'", attr[0]); + goto error; + } + + node->data.node_match.data = g_strdup (attr[1]); + if (regcomp (&(node->data.node_match.preq), node->data.node_match.data, REG_NOSUB|REG_EXTENDED) != 0) { + _pk_debug ("Invalid expression '%s'", node->data.node_match.data); + goto error; + } + + state = STATE_IN_MATCH; + _pk_debug ("parsed match node ('%s' (%d) -> '%s')", + attr[0], + node->data.node_match.match_type, + node->data.node_match.data); + + } else if ((strcmp (el, "return") == 0) && (num_attr == 2)) { + + node = config_node_new (); + node->node_type = NODE_TYPE_RETURN; + + if (strcmp (attr[0], "result") == 0) { + PolKitResult r; + if (!polkit_result_from_string_representation (attr[1], &r)) { + _pk_debug ("Unknown return result '%s'", attr[1]); + goto error; + } + node->data.node_return.result = r; + } else { + _pk_debug ("Unknown return rule '%s'", attr[0]); + goto error; + } + + state = STATE_IN_RETURN; + _pk_debug ("parsed return node ('%s' (%d))", + attr[1], + node->data.node_return.result); + } + break; + } + + if (state == STATE_NONE || node == NULL) + goto error; + + if (pd->stack_depth < 0 || pd->stack_depth >= PARSER_MAX_DEPTH) { + _pk_debug ("reached max depth?"); + goto error; + } + pd->state = state; + pd->state_stack[pd->stack_depth] = pd->state; + pd->node_stack[pd->stack_depth] = node; + + if (pd->stack_depth > 0) { + pd->node_stack[pd->stack_depth - 1]->children = + g_slist_append (pd->node_stack[pd->stack_depth - 1]->children, node); + } + + pd->stack_depth++; + _pk_debug ("state = %d", pd->state); + return; + +error: + if (node != NULL) { + config_node_unref (node); + } + XML_StopParser (pd->parser, FALSE); +} + +static void +_cdata (void *data, const char *s, int len) +{ +} + +static void +_end (void *data, const char *el) +{ + ParserData *pd = data; + + _pk_debug ("_end for node '%s'", el); + + --pd->stack_depth; + if (pd->stack_depth < 0 || pd->stack_depth >= PARSER_MAX_DEPTH) { + _pk_debug ("reached max depth?"); + goto error; + } + pd->state = pd->state_stack[pd->stack_depth]; + _pk_debug ("state = %d", pd->state); + return; +error: + XML_StopParser (pd->parser, FALSE); +} + +PolKitConfig * +polkit_config_new (PolKitError **error) +{ + ParserData pd; + int xml_res; + PolKitConfig *pk_config; + char *buf; + gsize buflen; + GError *g_error; + const char *path; + + /* load and parse the configuration file */ + pk_config = NULL; + + path = PACKAGE_SYSCONF_DIR "/PolicyKit/PolicyKit.conf"; + + g_error = NULL; + if (!g_file_get_contents (path, &buf, &buflen, &g_error)) { + polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID, + "Cannot load PolicyKit policy file at '%s': %s", + path, + g_error->message); + g_error_free (g_error); + goto error; + } + + pd.parser = XML_ParserCreate (NULL); + if (pd.parser == NULL) { + polkit_error_set_error (error, POLKIT_ERROR_OUT_OF_MEMORY, + "Cannot load PolicyKit policy file at '%s': %s", + path, + "No memory for parser"); + goto error; + } + XML_SetUserData (pd.parser, &pd); + XML_SetElementHandler (pd.parser, _start, _end); + XML_SetCharacterDataHandler (pd.parser, _cdata); + + pk_config = g_new0 (PolKitConfig, 1); + pk_config->refcount = 1; + + pd.state = STATE_NONE; + pd.pk_config = pk_config; + pd.node_stack[0] = NULL; + pd.stack_depth = 0; + + xml_res = XML_Parse (pd.parser, buf, buflen, 1); + + if (xml_res == 0) { + polkit_error_set_error (error, POLKIT_ERROR_POLICY_FILE_INVALID, + "%s:%d: parse error: %s", + path, + (int) XML_GetCurrentLineNumber (pd.parser), + XML_ErrorString (XML_GetErrorCode (pd.parser))); + + XML_ParserFree (pd.parser); + g_free (buf); + goto error; + } + XML_ParserFree (pd.parser); + g_free (buf); + + _pk_debug ("Loaded configuration file %s", path); + + if (pk_config->top_config_node != NULL) + config_node_dump (pk_config->top_config_node); + + return pk_config; + +error: + if (pk_config != NULL) + polkit_config_unref (pk_config); + return NULL; +} + +PolKitConfig * +polkit_config_ref (PolKitConfig *pk_config) +{ + g_return_val_if_fail (pk_config != NULL, pk_config); + pk_config->refcount++; + return pk_config; +} + +void +polkit_config_unref (PolKitConfig *pk_config) +{ + g_return_if_fail (pk_config != NULL); + pk_config->refcount--; + if (pk_config->refcount > 0) + return; + + if (pk_config->top_config_node != NULL) + config_node_unref (pk_config->top_config_node); + + g_free (pk_config); +} + +/* exactly one of the parameters caller and session must be NULL */ +static PolKitResult +config_node_test (ConfigNode *node, PolKitAction *action, PolKitCaller *caller, PolKitSession *session) +{ + gboolean match; + gboolean recurse; + PolKitResult result; + char *str; + char *str1; + char *str2; + uid_t uid; + + result = POLKIT_RESULT_UNKNOWN_ACTION; + recurse = FALSE; + + switch (node->node_type) { + case NODE_TYPE_TOP: + recurse = TRUE; + break; + case NODE_TYPE_MATCH: + match = FALSE; + str1 = NULL; + str2 = NULL; + switch (node->data.node_match.match_type) { + case MATCH_TYPE_ACTION: + if (!polkit_action_get_action_id (action, &str)) + goto out; + str1 = g_strdup (str); + break; + case MATCH_TYPE_USER: + if (caller != NULL) { + if (!polkit_caller_get_uid (caller, &uid)) + goto out; + } else if (session != NULL) { + if (!polkit_session_get_uid (session, &uid)) + goto out; + } else + goto out; + + str1 = g_strdup_printf ("%d", uid); + { + struct passwd pd; + struct passwd* pwdptr=&pd; + struct passwd* tempPwdPtr; + char pwdbuffer[256]; + int pwdlinelen = sizeof(pwdbuffer); + + if ((getpwuid_r (uid, pwdptr, pwdbuffer, pwdlinelen, &tempPwdPtr)) !=0 ) + goto out; + str2 = g_strdup (pd.pw_name); + } + break; + } + + if (str1 != NULL) { + if (regexec (&(node->data.node_match.preq), str1, 0, NULL, 0) == 0) + match = TRUE; + } + if (!match && str2 != NULL) { + if (regexec (&(node->data.node_match.preq), str2, 0, NULL, 0) == 0) + match = TRUE; + } + + + if (match) + recurse = TRUE; + + g_free (str1); + g_free (str2); + break; + case NODE_TYPE_RETURN: + result = node->data.node_return.result; + break; + } + + if (recurse) { + GSList *i; + for (i = node->children; i != NULL; i = g_slist_next (i)) { + ConfigNode *child_node = i->data; + result = config_node_test (child_node, action, caller, session); + if (result != POLKIT_RESULT_UNKNOWN_ACTION) { + goto out; + } + } + } + +out: + return result; +} + +PolKitResult +polkit_config_can_session_do_action (PolKitConfig *pk_config, + PolKitAction *action, + PolKitSession *session) +{ + PolKitResult result; + if (pk_config->top_config_node != NULL) + result = config_node_test (pk_config->top_config_node, action, NULL, session); + else + result = POLKIT_RESULT_UNKNOWN_ACTION; + return result; +} + +PolKitResult +polkit_config_can_caller_do_action (PolKitConfig *pk_config, + PolKitAction *action, + PolKitCaller *caller) +{ + PolKitResult result; + if (pk_config->top_config_node != NULL) + result = config_node_test (pk_config->top_config_node, action, caller, NULL); + else + result = POLKIT_RESULT_UNKNOWN_ACTION; + return result; +} diff --git a/polkit/polkit-config.h b/polkit/polkit-config.h new file mode 100644 index 0000000..24f5658 --- /dev/null +++ b/polkit/polkit-config.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ +/*************************************************************************** + * + * polkit-config.h : Configuration file + * + * Copyright (C) 2007 David Zeuthen, + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#if !defined (POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only can be included directly, this file may disappear or change contents." +#endif + +#ifndef POLKIT_CONFIG_H +#define POLKIT_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include + +struct PolKitConfig; +typedef struct PolKitConfig PolKitConfig; + +PolKitConfig *polkit_config_new (PolKitError **error); +PolKitConfig *polkit_config_ref (PolKitConfig *pk_config); +void polkit_config_unref (PolKitConfig *pk_config); + +PolKitResult +polkit_config_can_session_do_action (PolKitConfig *pk_config, + PolKitAction *action, + PolKitSession *session); + +PolKitResult +polkit_config_can_caller_do_action (PolKitConfig *pk_config, + PolKitAction *action, + PolKitCaller *caller); + +#endif /* POLKIT_CONFIG_H */ + + diff --git a/polkit/polkit-context.c b/polkit/polkit-context.c index 19ba81d..7224b76 100644 --- a/polkit/polkit-context.c +++ b/polkit/polkit-context.c @@ -38,9 +38,11 @@ #include #include +#include "polkit-config.h" #include "polkit-debug.h" #include "polkit-context.h" #include "polkit-policy-cache.h" +#include "polkit-grant-database.h" /** * SECTION:polkit @@ -75,11 +77,12 @@ struct PolKitContext PolKitPolicyCache *priv_cache; + PolKitConfig *config; + polkit_bool_t load_descriptions; int inotify_fd; int inotify_fd_watch_id; - int inotify_reload_wd; }; @@ -122,7 +125,17 @@ polkit_context_init (PolKitContext *pk_context, PolKitError **error) } _pk_debug ("Using policy files from directory %s", pk_context->policy_dir); - /* we don't populate the cache until it's needed.. */ + /* NOTE: we don't populate the cache until it's needed.. */ + + /* Load configuration file */ + pk_context->config = polkit_config_new (error); + if (pk_context->config == NULL) { + _pk_debug ("failed to load configuration file: %s", strerror (errno)); + /* TODO: set error. TODO: should we error out if the config file is bad?!? Or recover and go without a config file? */ + goto error; + } + + /* if the client provided watch functions, use inotify to create a watch on /var/lib/PolicyKit/reload */ if (pk_context->io_add_watch_func != NULL) { pk_context->inotify_fd = inotify_init (); if (pk_context->inotify_fd < 0) { @@ -131,12 +144,11 @@ polkit_context_init (PolKitContext *pk_context, PolKitError **error) goto error; } - /* create a watch on /var/lib/PolicyKit/reload */ pk_context->inotify_reload_wd = inotify_add_watch (pk_context->inotify_fd, - PACKAGE_LOCALSTATEDIR "/lib/PolicyKit/reload", + PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/reload", IN_MODIFY | IN_CREATE | IN_ATTRIB); if (pk_context->inotify_reload_wd < 0) { - _pk_debug ("failed to add watch on file '" PACKAGE_LOCALSTATEDIR "/lib/PolicyKit/reload': %s", + _pk_debug ("failed to add watch on file '" PACKAGE_LOCALSTATE_DIR "/lib/PolicyKit/reload': %s", strerror (errno)); /* TODO: set error */ goto error; @@ -371,10 +383,11 @@ polkit_context_can_session_do_action (PolKitContext *pk_context, { PolKitPolicyCache *cache; PolKitPolicyFileEntry *pfe; - PolKitResult current_result; + PolKitPolicyDefault *policy_default; + PolKitResult result; - current_result = POLKIT_RESULT_NO; - g_return_val_if_fail (pk_context != NULL, current_result); + result = POLKIT_RESULT_NO; + g_return_val_if_fail (pk_context != NULL, result); if (action == NULL || session == NULL) goto out; @@ -401,81 +414,33 @@ polkit_context_can_session_do_action (PolKitContext *pk_context, } else { g_warning ("no action with name '%s'", action_name); } - current_result = POLKIT_RESULT_UNKNOWN_ACTION; + result = POLKIT_RESULT_UNKNOWN_ACTION; goto out; } polkit_policy_file_entry_debug (pfe); - current_result = POLKIT_RESULT_UNKNOWN_ACTION; - -#if 0 - /* visit modules */ - for (i = pk_context->modules; i != NULL; i = g_slist_next (i)) { - PolKitModuleInterface *module_interface = i->data; - PolKitModuleCanSessionDoAction func; - - func = polkit_module_get_func_can_session_do_action (module_interface); - if (func != NULL) { - PolKitModuleControl module_control; - PolKitResult module_result; - - _pk_debug ("Asking module '%s'", polkit_module_get_name (module_interface)); + /* check if the config file specifies a result */ + result = polkit_config_can_session_do_action (pk_context->config, action, session); + if (result != POLKIT_RESULT_UNKNOWN_ACTION) + goto found; - module_control = polkit_module_interface_get_control (module_interface); - - if (polkit_module_interface_check_builtin_confinement_for_session ( - module_interface, - pk_context, - action, - session)) { - /* module is confined by built-in options */ - module_result = POLKIT_RESULT_UNKNOWN_ACTION; - _pk_debug ("Module '%s' confined by built-in's", - polkit_module_get_name (module_interface)); - } else { - module_result = func (module_interface, - pk_context, - action, - session); - } - - /* if a module returns _UNKNOWN_ACTION, it means that it doesn't - * have an opinion about the query; e.g. polkit-module-allow-all(8) - * will return this if it's confined to only consider certain actions - * or certain users. - */ - if (module_result != POLKIT_RESULT_UNKNOWN_ACTION) { - - if (current_control == POLKIT_MODULE_CONTROL_ADVISE && - module_control == POLKIT_MODULE_CONTROL_ADVISE) { - - /* take the less strict result */ - if (current_result < module_result) { - current_result = module_result; - } - - } else if (current_control == POLKIT_MODULE_CONTROL_ADVISE && - module_control == POLKIT_MODULE_CONTROL_MANDATORY) { - - /* here we just override */ - current_result = module_result; - - /* we are now in mandatory mode */ - current_control = POLKIT_MODULE_CONTROL_MANDATORY; - } - } - } + /* if no, just use the defaults */ + policy_default = polkit_policy_file_entry_get_default (pfe); + if (policy_default == NULL) { + g_warning ("no default policy for action!"); + goto out; } -#endif + result = polkit_policy_default_can_session_do_action (policy_default, action, session); +found: /* Never return UNKNOWN_ACTION to user */ - if (current_result == POLKIT_RESULT_UNKNOWN_ACTION) - current_result = POLKIT_RESULT_NO; + if (result == POLKIT_RESULT_UNKNOWN_ACTION) + result = POLKIT_RESULT_NO; out: - _pk_debug ("... result was %s", polkit_result_to_string_representation (current_result)); - return current_result; + _pk_debug ("... result was %s", polkit_result_to_string_representation (result)); + return result; } /** @@ -496,10 +461,11 @@ polkit_context_can_caller_do_action (PolKitContext *pk_context, { PolKitPolicyCache *cache; PolKitPolicyFileEntry *pfe; - PolKitResult current_result; + PolKitResult result; + PolKitPolicyDefault *policy_default; - current_result = POLKIT_RESULT_NO; - g_return_val_if_fail (pk_context != NULL, current_result); + result = POLKIT_RESULT_NO; + g_return_val_if_fail (pk_context != NULL, result); if (action == NULL || caller == NULL) goto out; @@ -526,78 +492,36 @@ polkit_context_can_caller_do_action (PolKitContext *pk_context, } else { g_warning ("no action with name '%s'", action_name); } - current_result = POLKIT_RESULT_UNKNOWN_ACTION; + result = POLKIT_RESULT_UNKNOWN_ACTION; goto out; } polkit_policy_file_entry_debug (pfe); - current_result = POLKIT_RESULT_UNKNOWN_ACTION; - -#if 0 - /* visit modules */ - for (i = pk_context->modules; i != NULL; i = g_slist_next (i)) { - PolKitModuleInterface *module_interface = i->data; - PolKitModuleCanCallerDoAction func; - - func = polkit_module_get_func_can_caller_do_action (module_interface); - if (func != NULL) { - PolKitModuleControl module_control; - PolKitResult module_result; + /* first, check if the grant database specifies a result */ + result = _polkit_grantdb_check_can_caller_do_action (pk_context, action, caller); + if (result != POLKIT_RESULT_UNKNOWN_ACTION) + goto found; - _pk_debug ("Asking module '%s'", polkit_module_get_name (module_interface)); - - module_control = polkit_module_interface_get_control (module_interface); - - if (polkit_module_interface_check_builtin_confinement_for_caller ( - module_interface, - pk_context, - action, - caller)) { - /* module is confined by built-in options */ - module_result = POLKIT_RESULT_UNKNOWN_ACTION; - _pk_debug ("Module '%s' confined by built-in's", - polkit_module_get_name (module_interface)); - } else { - module_result = func (module_interface, - pk_context, - action, - caller); - } + /* second, check if the config file specifies a result */ + result = polkit_config_can_caller_do_action (pk_context->config, action, caller); + if (result != POLKIT_RESULT_UNKNOWN_ACTION) + goto found; - /* if a module returns _UNKNOWN_ACTION, it means that it doesn't - * have an opinion about the query; e.g. polkit-module-allow-all(8) - * will return this if it's confined to only consider certain actions - * or certain users. - */ - if (module_result != POLKIT_RESULT_UNKNOWN_ACTION) { - - if (current_control == POLKIT_MODULE_CONTROL_ADVISE && - module_control == POLKIT_MODULE_CONTROL_ADVISE) { - - /* take the less strict result */ - if (current_result < module_result) { - current_result = module_result; - } - - } else if (current_control == POLKIT_MODULE_CONTROL_ADVISE && - module_control == POLKIT_MODULE_CONTROL_MANDATORY) { - - /* here we just override */ - current_result = module_result; - - /* we are now in mandatory mode */ - current_control = POLKIT_MODULE_CONTROL_MANDATORY; - } - } - } + /* if no, just use the defaults */ + policy_default = polkit_policy_file_entry_get_default (pfe); + if (policy_default == NULL) { + g_warning ("no default policy for action!"); + goto out; } -#endif + result = polkit_policy_default_can_caller_do_action (policy_default, action, caller); + +found: /* Never return UNKNOWN_ACTION to user */ - if (current_result == POLKIT_RESULT_UNKNOWN_ACTION) - current_result = POLKIT_RESULT_NO; + if (result == POLKIT_RESULT_UNKNOWN_ACTION) + result = POLKIT_RESULT_NO; out: - _pk_debug ("... result was %s", polkit_result_to_string_representation (current_result)); - return current_result; + _pk_debug ("... result was %s", polkit_result_to_string_representation (result)); + return result; } diff --git a/polkit-grant/polkit-grant-database.c b/polkit/polkit-grant-database.c similarity index 98% rename from polkit-grant/polkit-grant-database.c rename to polkit/polkit-grant-database.c index 71feea7..c936e98 100644 --- a/polkit-grant/polkit-grant-database.c +++ b/polkit/polkit-grant-database.c @@ -23,6 +23,10 @@ * **************************************************************************/ +#ifdef HAVE_CONFIG_H +# include +#endif + #include #include #include @@ -34,7 +38,7 @@ #include -#include +#include /* TODO FIXME: this is Linux specific */ static unsigned long long diff --git a/polkit-grant/polkit-grant-database.h b/polkit/polkit-grant-database.h similarity index 100% rename from polkit-grant/polkit-grant-database.h rename to polkit/polkit-grant-database.h -- 2.7.4