Commit 21e21e97 authored by David Zeuthen's avatar David Zeuthen

load and choose what backend to use; also write a simple null backend

The thinking is that if someone wants to turn off PolicyKit, they
simply drop a file /etc/polkit-1/nullbackend.conf.d/99-i-hate-polkit.conf
with the contents

[Configuration]
priority=1000

This also provides a good cut-n-paste template / example etc. of how
to implement a PolicyKit backend.
parent bc150368
......@@ -416,6 +416,7 @@ src/polkitagent/Makefile
src/polkitd/Makefile
src/programs/Makefile
src/examples/Makefile
src/nullbackend/Makefile
docs/version.xml
docs/Makefile
docs/polkit/Makefile
......
<SECTION>
<FILE>polkitbackendauthority</FILE>
<TITLE>PolkitBackendAuthority</TITLE>
POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME
PolkitBackendAuthority
PolkitBackendAuthorityClass
polkit_backend_authority_check_authorization
......@@ -15,6 +16,7 @@ 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
<SUBSECTION Standard>
POLKIT_BACKEND_AUTHORITY
......
SUBDIRS = polkit polkitbackend polkitagent polkitd programs examples
SUBDIRS = polkit polkitbackend polkitagent polkitd nullbackend programs examples
clean-local :
rm -f *~
#
# Configuration file for the PolicyKit null backend.
#
# Do not edit this file, it will be overwritten on update.
#
# To change configuration, create another file in this directory with
# a filename that is sorted after the 50-nullback.conf.
#
# Only a single configuration item is supported now. The priority of
# the null backend. It defaults to -10. See the PolicyKit documentation
# for more information about PolicyKit backends.
#
[Configuration]
priority=-10
NULL =
module_flags = -export_dynamic -avoid-version -module -no-undefined -export-symbols-regex '^g_io_module_(load|unload)'
INCLUDES = \
-I$(top_builddir)/src \
-I$(top_srcdir)/src \
-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
-DPACKAGE_LIB_DIR=\""$(libdir)"\" \
-D_POSIX_PTHREAD_SEMANTICS \
-D_REENTRANT \
$(NULL)
polkitmodulesdir = $(libdir)/polkit-1/backends
polkitmodules_LTLIBRARIES = libpolkit-nullbackend.la
libpolkit_nullbackend_la_SOURCES = \
nullbackend.c \
polkitbackendnullauthority.c polkitbackendnullauthority.h \
$(NULL)
libpolkit_nullbackend_la_CFLAGS = \
-DG_LOG_DOMAIN=\"PolkitNullBackend\" \
$(GLIB_CFLAGS) \
$(NULL)
libpolkit_nullbackend_la_LDFLAGS = \
$(module_flags) \
$(GLIB_LDADD) \
$(top_builddir)/src/polkitbackend/libpolkit-backend-1.la \
$(NULL)
libpolkit_nullbackend_la_LIBADD = \
$(NULL)
nullconfigdir = $(sysconfdir)/polkit-1/nullbackend.conf.d
nullconfig_DATA = 50-nullbackend.conf
clean-local :
rm -f *~
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
#include "polkitbackendnullauthority.h"
void
g_io_module_load (GIOModule *module)
{
polkit_backend_null_authority_register (module);
}
void
g_io_module_unload (GIOModule *module)
{
}
/*
* Copyright (C) 2008 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
#include "config.h"
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <string.h>
#include <glib/gstdio.h>
#include "polkitbackendnullauthority.h"
struct _PolkitBackendNullAuthorityPrivate
{
gint foo;
};
static GList *authority_enumerate_actions (PolkitBackendAuthority *authority,
PolkitSubject *caller,
const gchar *locale,
GError **error);
static void authority_check_authorization (PolkitBackendAuthority *authority,
PolkitSubject *caller,
PolkitSubject *subject,
const gchar *action_id,
PolkitCheckAuthorizationFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
static PolkitAuthorizationResult authority_check_authorization_finish (PolkitBackendAuthority *authority,
GAsyncResult *res,
GError **error);
G_DEFINE_DYNAMIC_TYPE (PolkitBackendNullAuthority, polkit_backend_null_authority,POLKIT_BACKEND_TYPE_AUTHORITY);
static void
polkit_backend_null_authority_init (PolkitBackendNullAuthority *authority)
{
authority->priv = G_TYPE_INSTANCE_GET_PRIVATE (authority,
POLKIT_BACKEND_TYPE_NULL_AUTHORITY,
PolkitBackendNullAuthorityPrivate);
}
static void
polkit_backend_null_authority_finalize (GObject *object)
{
PolkitBackendNullAuthority *authority;
authority = POLKIT_BACKEND_NULL_AUTHORITY (object);
G_OBJECT_CLASS (polkit_backend_null_authority_parent_class)->finalize (object);
}
static void
polkit_backend_null_authority_class_init (PolkitBackendNullAuthorityClass *klass)
{
GObjectClass *gobject_class;
PolkitBackendAuthorityClass *authority_class;
gobject_class = G_OBJECT_CLASS (klass);
authority_class = POLKIT_BACKEND_AUTHORITY_CLASS (klass);
gobject_class->finalize = polkit_backend_null_authority_finalize;
authority_class->enumerate_actions = authority_enumerate_actions;
authority_class->check_authorization = authority_check_authorization;
authority_class->check_authorization_finish = authority_check_authorization_finish;
g_type_class_add_private (klass, sizeof (PolkitBackendNullAuthorityPrivate));
}
static void
polkit_backend_null_authority_class_finalize (PolkitBackendNullAuthorityClass *klass)
{
}
static gint
compare_filename (GFile *a, GFile *b)
{
gchar *a_uri;
gchar *b_uri;
gint ret;
a_uri = g_file_get_uri (a);
b_uri = g_file_get_uri (b);
ret = g_strcmp0 (a_uri, b_uri);
return ret;
}
/* Loads and process all .conf files in /etc/polkit-1/nullbackend.conf.d/ in order */
static void
load_config (gint *out_priority)
{
GFileEnumerator *enumerator;
GFile *directory;
GFileInfo *file_info;
GError *error;
GList *files;
GList *l;
directory = g_file_new_for_path (PACKAGE_SYSCONF_DIR "/polkit-1/nullbackend.conf.d");
files = NULL;
error = NULL;
enumerator = g_file_enumerate_children (directory,
"standard::*",
G_FILE_QUERY_INFO_NONE,
NULL,
&error);
if (error != NULL)
{
g_warning ("Error enumerating files: %s", error->message);
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 ending in .conf */
if (g_str_has_suffix (name, ".conf"))
files = g_list_prepend (files, g_file_get_child (directory, name));
g_object_unref (file_info);
}
if (error != NULL)
{
g_warning ("Error enumerating files: %s", error->message);
goto out;
}
g_object_unref (enumerator);
files = g_list_sort (files, (GCompareFunc) compare_filename);
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 file %s: %s", filename, error->message);
g_error_free (error);
error = NULL;
}
else
{
gint priority;
priority = g_key_file_get_integer (key_file,
"Configuration",
"priority",
&error);
if (error != NULL)
{
/* don't warn, not all config files may have this key */
g_error_free (error);
}
else
{
*out_priority = priority;
}
g_key_file_free (key_file);
}
g_free (filename);
}
out:
g_object_unref (directory);
g_list_foreach (files, (GFunc) g_object_unref, NULL);
g_list_free (files);
}
void
polkit_backend_null_authority_register (GIOModule *module)
{
gint priority;
priority = -1;
load_config (&priority);
polkit_backend_null_authority_register_type (G_TYPE_MODULE (module));
g_print ("Registering null backend at priority %d\n", priority);
g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
POLKIT_BACKEND_TYPE_NULL_AUTHORITY,
"null backend " PACKAGE_VERSION,
priority);
}
/* ---------------------------------------------------------------------------------------------------- */
static GList *
authority_enumerate_actions (PolkitBackendAuthority *authority,
PolkitSubject *caller,
const gchar *locale,
GError **error)
{
/* We don't know any actions */
return NULL;
}
static void
authority_check_authorization (PolkitBackendAuthority *authority,
PolkitSubject *caller,
PolkitSubject *subject,
const gchar *action_id,
PolkitCheckAuthorizationFlags flags,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *simple;
/* complete immediately */
simple = g_simple_async_result_new (G_OBJECT (authority),
callback,
user_data,
authority_check_authorization);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
static PolkitAuthorizationResult
authority_check_authorization_finish (PolkitBackendAuthority *authority,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple;
PolkitAuthorizationResult result;
simple = G_SIMPLE_ASYNC_RESULT (res);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == authority_check_authorization);
/* we always return NOT_AUTHORIZED, never an error */
result = POLKIT_AUTHORIZATION_RESULT_NOT_AUTHORIZED;
if (g_simple_async_result_propagate_error (simple, error))
goto out;
out:
return result;
}
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Author: David Zeuthen <davidz@redhat.com>
*/
#ifndef __POLKIT_BACKEND_NULL_AUTHORITY_H
#define __POLKIT_BACKEND_NULL_AUTHORITY_H
#include <polkitbackend/polkitbackend.h>
G_BEGIN_DECLS
#define POLKIT_BACKEND_TYPE_NULL_AUTHORITY (polkit_backend_null_authority_get_type ())
#define POLKIT_BACKEND_NULL_AUTHORITY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY, PolkitBackendNullAuthority))
#define POLKIT_BACKEND_NULL_AUTHORITY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_BACKEND_TYPE_NULL_AUTHORITY, PolkitBackendNullAuthorityClass))
#define POLKIT_BACKEND_NULL_AUTHORITY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY,PolkitBackendNullAuthorityClass))
#define POLKIT_BACKEND_IS_NULL_AUTHORITY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_BACKEND_TYPE_NULL_AUTHORITY))
#define POLKIT_BACKEND_IS_NULL_AUTHORITY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_BACKEND_TYPE_NULL_AUTHORITY))
typedef struct _PolkitBackendNullAuthority PolkitBackendNullAuthority;
typedef struct _PolkitBackendNullAuthorityClass PolkitBackendNullAuthorityClass;
typedef struct _PolkitBackendNullAuthorityPrivate PolkitBackendNullAuthorityPrivate;
struct _PolkitBackendNullAuthority
{
PolkitBackendAuthority parent_instance;
PolkitBackendNullAuthorityPrivate *priv;
};
struct _PolkitBackendNullAuthorityClass
{
PolkitBackendAuthorityClass parent_class;
};
GType polkit_backend_null_authority_get_type (void) G_GNUC_CONST;
void polkit_backend_null_authority_register (GIOModule *module);
G_END_DECLS
#endif /* __POLKIT_BACKEND_NULL_AUTHORITY_H */
......@@ -84,3 +84,4 @@ clean-local :
install-exec-hook:
mkdir -p $(DESTDIR)$(localstatedir)/lib/polkit-1
-chmod 600 $(DESTDIR)$(localstatedir)/lib/polkit-1
mkdir -p $(DESTDIR)$(libdir)/polkit-1/backends
......@@ -22,6 +22,8 @@
#ifndef __POLKIT_BACKEND_H
#define __POLKIT_BACKEND_H
#include <polkit/polkit.h>
#define _POLKIT_BACKEND_INSIDE_POLKIT_BACKEND_H 1
#include <polkitbackend/polkitbackendtypes.h>
#include <polkitbackend/polkitbackendauthority.h>
......
......@@ -26,6 +26,7 @@
#include <polkit/polkit.h>
#include <polkit/polkitprivate.h>
#include "polkitbackendauthority.h"
#include "polkitbackendlocalauthority.h"
#include "polkitbackendprivate.h"
......@@ -85,6 +86,7 @@ polkit_backend_authority_system_bus_name_owner_changed (PolkitBackendAuthority
klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority);
if (klass->system_bus_name_owner_changed != NULL)
klass->system_bus_name_owner_changed (authority, name, old_owner, new_owner);
}
......@@ -1261,3 +1263,55 @@ polkit_backend_register_authority (PolkitBackendAuthority *authority,
g_object_unref (server);
return FALSE;
}
/**
* polkit_backend_authority_get:
*
* Loads all #GIOModule<!-- -->s from <literal>$(libdir)/polkit-1/backends</literal> to determine
* what implementation of #PolkitBackendAuthority to use. Then instantiates an object of the
* implementation with the highest priority and unloads all other modules.
*
* Returns: A #PolkitBackendAuthority. Free with g_object_unref().
**/
PolkitBackendAuthority *
polkit_backend_authority_get (void)
{
static GIOExtensionPoint *ep = NULL;
static volatile GType local_authority_type = G_TYPE_INVALID;
GList *modules;
GList *authority_implementations;
GType authority_type;
PolkitBackendAuthority *authority;
/* define the extension point */
if (ep == NULL)
{
ep = g_io_extension_point_register (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME);
g_io_extension_point_set_required_type (ep, POLKIT_BACKEND_TYPE_AUTHORITY);
}
/* make sure local types are registered */
if (local_authority_type == G_TYPE_INVALID)
{
local_authority_type = POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY;
}
/* load all modules */
modules = g_io_modules_load_all_in_directory (PACKAGE_LIB_DIR "/polkit-1/backends");
/* find all extensions; we have at least one here since we've registered the local backend */
authority_implementations = g_io_extension_point_get_extensions (ep);
/* the returned list is sorted according to priority so just take the highest one */
authority_type = g_io_extension_get_type ((GIOExtension*) authority_implementations->data);
authority = POLKIT_BACKEND_AUTHORITY (g_object_new (authority_type, NULL));
/* unload all modules; the module our instantiated authority is in won't be unloaded because
* we've instantiated a reference to a type in this module
*/
g_list_foreach (modules, (GFunc) g_type_module_unuse, NULL);
g_list_free (modules);
return authority;
}
......@@ -40,6 +40,13 @@ G_BEGIN_DECLS
typedef struct _PolkitBackendAuthorityClass PolkitBackendAuthorityClass;
/**
* POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME:
*
* Extension point name for authority backend implementations.
*/
#define POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME "polkit-backend-authority-1"
/**
* PolkitBackendAuthority:
*
......@@ -258,6 +265,8 @@ gboolean polkit_backend_authority_authentication_agent_response (PolkitBackendAu
/* --- */
PolkitBackendAuthority *polkit_backend_authority_get (void);
gboolean polkit_backend_register_authority (PolkitBackendAuthority *authority,
const gchar *well_known_name,
const gchar *object_path,
......
......@@ -220,7 +220,11 @@ action_pool_changed (PolkitBackendActionPool *action_pool,
/* ---------------------------------------------------------------------------------------------------- */
G_DEFINE_TYPE (PolkitBackendLocalAuthority, polkit_backend_local_authority, POLKIT_BACKEND_TYPE_AUTHORITY);
G_DEFINE_TYPE_WITH_CODE (PolkitBackendLocalAuthority, polkit_backend_local_authority,POLKIT_BACKEND_TYPE_AUTHORITY,
g_io_extension_point_implement (POLKIT_BACKEND_AUTHORITY_EXTENSION_POINT_NAME,
g_define_type_id,
"local-files " PACKAGE_VERSION,
0));
#define POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_BACKEND_TYPE_LOCAL_AUTHORITY, PolkitBackendLocalAuthorityPrivate))
......
......@@ -26,17 +26,6 @@
#include <polkit/polkit.h>
#include <polkitbackend/polkitbackend.h>
static PolkitBackendAuthority *
get_authority_backend (void)
{
PolkitBackendAuthority *authority;
/* TODO: use extension points etc. */
authority = polkit_backend_local_authority_new ();
return authority;
}
int
main (int argc, char **argv)
{
......@@ -53,7 +42,9 @@ main (int argc, char **argv)
loop = g_main_loop_new (NULL, FALSE);
authority = get_authority_backend ();
authority = polkit_backend_authority_get ();
g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
if (!polkit_backend_register_authority (authority,
"org.freedesktop.PolicyKit1",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment