PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Tue Oct 30 18:19:04 PDT 2007
Makefile.am | 2
configure.in | 5
polkit-dbus/polkit-read-auth-helper.c | 13
polkitd/Makefile.am | 61 +++
polkitd/main.c | 193 +++++++++
polkitd/org.freedesktop.PolicyKit.conf.in | 11
polkitd/org.freedesktop.PolicyKit.service.in | 11
polkitd/org.freedesktop.PolicyKit.xml | 27 +
polkitd/polkit-daemon.c | 527 +++++++++++++++++++++++++++
polkitd/polkit-daemon.h | 72 +++
10 files changed, 919 insertions(+), 3 deletions(-)
New commits:
commit 871e4c93e96e5ae9782f1aafddc2f47cc2c34b78
Author: David Zeuthen <davidz at redhat.com>
Date: Tue Oct 30 21:17:08 2007 -0400
provide a polkit D-Bus service that is activated on demand
Right now we provide two methods
IsProcessAuthorized
IsSystemBusNameAuthorized
This is useful for a couple of reasons
- some mechanisms (e.g. Avahi) runs in a chroot and their only
life-line to the world is a system bus connection. If it were to
use libpolkit (and Lennart says he wants it to, yay!) it would need
to bindmount crazy stuff into the chroot.
- languages for which libpolkit bindings not yet exist can use
this interface
Going forward, this service can expose a private interface meaning we
can get rid of (almost) all of our setgid helpers.
diff --git a/Makefile.am b/Makefile.am
index 23d971f..b5d36ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = data polkit polkit-dbus polkit-grant doc tools policy po
+SUBDIRS = data polkit polkit-dbus polkit-grant polkitd doc tools policy po
# Creating ChangeLog from git log (taken from cairo/Makefile.am):
ChangeLog: $(srcdir)/ChangeLog
diff --git a/configure.in b/configure.in
index 9ab5d4b..17694a2 100644
--- a/configure.in
+++ b/configure.in
@@ -136,6 +136,10 @@ PKG_CHECK_MODULES(DBUS, [dbus-1 >= 1.0])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
+PKG_CHECK_MODULES(DBUS_GLIB, [dbus-glib-1 >= 0.73])
+AC_SUBST(DBUS_GLIB_CFLAGS)
+AC_SUBST(DBUS_GLIB_LIBS)
+
AC_CHECK_FUNCS(getgrouplist)
EXPAT_LIB=""
@@ -429,6 +433,7 @@ data/polkit-grant.pc
polkit/Makefile
polkit-dbus/Makefile
polkit-grant/Makefile
+polkitd/Makefile
tools/Makefile
doc/Makefile
doc/version.xml
diff --git a/polkit-dbus/polkit-read-auth-helper.c b/polkit-dbus/polkit-read-auth-helper.c
index 385c75d..2701634 100644
--- a/polkit-dbus/polkit-read-auth-helper.c
+++ b/polkit-dbus/polkit-read-auth-helper.c
@@ -341,6 +341,8 @@ main (int argc, char *argv[])
uid_t caller_uid;
uid_t requesting_info_for_uid;
char *endp;
+ struct passwd *pw;
+ uid_t uid_for_polkit_user;
ret = 1;
/* clear the entire environment to avoid attacks using with libraries honoring environment variables */
@@ -379,6 +381,13 @@ main (int argc, char *argv[])
goto out;
}
+ pw = getpwnam (POLKIT_USER);
+ if (pw == NULL) {
+ fprintf (stderr, "polkit-read-auth-helper: cannot lookup uid for " POLKIT_USER "\n");
+ goto out;
+ }
+ uid_for_polkit_user = pw->pw_uid;
+
/*----------------------------------------------------------------------------------------------------*/
requesting_info_for_uid = strtoul (argv[1], &endp, 10);
@@ -387,8 +396,8 @@ main (int argc, char *argv[])
goto out;
}
- /* uid 0 is allowed to read anything */
- if (caller_uid != 0) {
+ /* uid 0 and user polkituser is allowed to read anything */
+ if (caller_uid != 0 && caller_uid != uid_for_polkit_user) {
if (caller_uid != requesting_info_for_uid) {
/* see if calling user has the
diff --git a/polkitd/Makefile.am b/polkitd/Makefile.am
new file mode 100644
index 0000000..815e72a
--- /dev/null
+++ b/polkitd/Makefile.am
@@ -0,0 +1,61 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = \
+ -I$(top_builddir) -I$(top_srcdir) \
+ -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 \
+ -DPOLKIT_COMPILATION \
+ $(DBUS_GLIB_CFLAGS) \
+ @GLIB_CFLAGS@
+
+BUILT_SOURCES = \
+ polkit-daemon-glue.h
+
+polkit-daemon-glue.h: org.freedesktop.PolicyKit.xml Makefile.am
+ dbus-binding-tool --prefix=polkit_daemon --mode=glib-server --output=polkit-daemon-glue.h org.freedesktop.PolicyKit.xml
+
+libexec_PROGRAMS = polkitd
+
+polkitd_SOURCES = \
+ polkit-daemon.h polkit-daemon.c \
+ main.c \
+ $(BUILT_SOURCES)
+
+polkitd_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -DG_LOG_DOMAIN=\"polkitd\" \
+ -DDATADIR=\""$(pkgdatadir)"\" \
+ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+ $(DISABLE_DEPRECATED) \
+ $(AM_CPPFLAGS)
+
+polkitd_LDADD = \
+ $(DBUS_GLIB_LIBS) $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la $(top_builddir)/polkit-grant/libpolkit-grant.la
+
+
+servicedir = $(datadir)/dbus-1/system-services
+service_in_files = org.freedesktop.PolicyKit.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@polkituser\@|$(POLKIT_USER)|" -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+dbusconfdir = $(sysconfdir)/dbus-1/system.d
+dbusconf_in_files = org.freedesktop.PolicyKit.conf.in
+dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
+
+$(dbusconf_DATA): $(dbusconf_in_files) Makefile
+ @sed -e "s|\@polkituser\@|$(POLKIT_USER)|" $< > $@
+
+CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = org.freedesktop.PolicyKit.xml $(service_in_files) $(dbusconf_in_files)
+
+clean-local :
+ rm -f *~ $(service_DATA) $(dbusconf_DATA)
diff --git a/polkitd/main.c b/polkitd/main.c
new file mode 100644
index 0000000..fe7b626
--- /dev/null
+++ b/polkitd/main.c
@@ -0,0 +1,193 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+ *
+ * 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 "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "polkit-daemon.h"
+
+#define NAME_TO_CLAIM "org.freedesktop.PolicyKit"
+
+static gboolean
+acquire_name_on_proxy (DBusGProxy *bus_proxy)
+{
+ GError *error;
+ guint result;
+ gboolean res;
+ gboolean ret;
+
+ ret = FALSE;
+
+ if (bus_proxy == NULL) {
+ goto out;
+ }
+
+ error = NULL;
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &error,
+ G_TYPE_STRING, NAME_TO_CLAIM,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ if (! res) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
+ }
+ goto out;
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", NAME_TO_CLAIM, error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Failed to acquire %s", NAME_TO_CLAIM);
+ }
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+int
+main (int argc, char **argv)
+{
+ GError *error;
+ GMainLoop *loop;
+ PolKitDaemon *daemon;
+ GOptionContext *context;
+ DBusGProxy *bus_proxy;
+ DBusGConnection *bus;
+ int ret;
+ struct passwd *pw = NULL;
+ struct group *gr = NULL;
+ static gboolean no_exit = FALSE;
+ static GOptionEntry entries [] = {
+ { "no-exit", 0, 0, G_OPTION_ARG_NONE, &no_exit, "Don't exit after 30 seconds of inactivity", NULL },
+ { NULL }
+ };
+
+ ret = 1;
+
+ pw = getpwnam (POLKIT_USER);
+ if (pw == NULL) {
+ g_warning ("polkitd: user " POLKIT_USER " does not exist");
+ goto out;
+ }
+
+ gr = getgrnam (POLKIT_GROUP);
+ if (gr == NULL) {
+ g_warning ("polkitd: group " POLKIT_GROUP " does not exist");
+ goto out;
+ }
+
+ if (initgroups (POLKIT_USER, gr->gr_gid)) {
+ g_warning ("polkitd: could not initialize groups");
+ goto out;
+ }
+
+ if (setgid (gr->gr_gid)) {
+ g_warning ("polkitd: could not set group id");
+ goto out;
+ }
+
+ if (setuid (pw->pw_uid)) {
+ g_warning ("polkitd: could not set user id");
+ goto out;
+ }
+
+
+ g_type_init ();
+
+ context = g_option_context_new ("PolicyKit daemon");
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ error = NULL;
+ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (bus == NULL) {
+ g_warning ("Couldn't connect to session bus: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name (bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (bus_proxy == NULL) {
+ g_warning ("Could not construct bus_proxy object; bailing out");
+ goto out;
+ }
+
+ if (!acquire_name_on_proxy (bus_proxy) ) {
+ g_warning ("Could not acquire name; bailing out");
+ goto out;
+ }
+
+ g_debug ("Starting polkitd version %s", VERSION);
+
+ daemon = polkit_daemon_new (no_exit);
+
+ if (daemon == NULL) {
+ goto out;
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ g_main_loop_run (loop);
+
+ g_object_unref (daemon);
+ g_main_loop_unref (loop);
+ ret = 0;
+
+out:
+ return ret;
+}
diff --git a/polkitd/org.freedesktop.PolicyKit.conf.in b/polkitd/org.freedesktop.PolicyKit.conf.in
new file mode 100644
index 0000000..d7ca4e0
--- /dev/null
+++ b/polkitd/org.freedesktop.PolicyKit.conf.in
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- XML -*- -->
+
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Only @polkituser@ can own the service -->
+ <policy user="@polkituser@">
+ <allow own="org.freedesktop.PolicyKit"/>
+ </policy>
+</busconfig>
diff --git a/polkitd/org.freedesktop.PolicyKit.service.in b/polkitd/org.freedesktop.PolicyKit.service.in
new file mode 100644
index 0000000..ae17b31
--- /dev/null
+++ b/polkitd/org.freedesktop.PolicyKit.service.in
@@ -0,0 +1,11 @@
+[D-BUS Service]
+Name=org.freedesktop.PolicyKit
+Exec=@libexecdir@/polkitd
+User=root
+
+# Hmm when using User=@polkituser@ I get this:
+#
+# Error org.freedesktop.DBus.Error.Spawn.ChildExited: Launch helper exited with unknown return code 1
+#
+# Need to investigate
+
diff --git a/polkitd/org.freedesktop.PolicyKit.xml b/polkitd/org.freedesktop.PolicyKit.xml
new file mode 100644
index 0000000..a342847
--- /dev/null
+++ b/polkitd/org.freedesktop.PolicyKit.xml
@@ -0,0 +1,27 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/">
+
+ <interface name="org.freedesktop.PolicyKit">
+
+ <method name="IsProcessAuthorized">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <!-- IN: PolicyKit action identifier -->
+ <arg name="action_id" direction="in" type="s"/>
+ <!-- IN: process id of caller to check for -->
+ <arg name="pid" direction="in" type="u"/>
+ <!-- OUT: the PolKitResult in textual form -->
+ <arg name="result" direction="out" type="s"/>
+ </method>
+
+ <method name="IsSystemBusNameAuthorized">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <!-- IN: PolicyKit action identifier -->
+ <arg name="action_id" direction="in" type="s"/>
+ <!-- IN: Unique name on the system bus of the caller to check for -->
+ <arg name="system_bus_name" direction="in" type="s"/>
+ <!-- OUT: the PolKitResult in textual form -->
+ <arg name="result" direction="out" type="s"/>
+ </method>
+
+ </interface>
+</node>
diff --git a/polkitd/polkit-daemon.c b/polkitd/polkit-daemon.c
new file mode 100644
index 0000000..48353b5
--- /dev/null
+++ b/polkitd/polkit-daemon.c
@@ -0,0 +1,527 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+ *
+ * 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 "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <polkit/polkit.h>
+#include <polkit/polkit-utils.h>
+#include <polkit-dbus/polkit-dbus.h>
+
+#include "polkit-daemon.h"
+
+static gboolean no_exit = FALSE;
+
+/*--------------------------------------------------------------------------------------------------------------*/
+#include "polkit-daemon-glue.h"
+
+static gboolean
+do_exit (gpointer user_data)
+{
+ g_debug ("Exiting due to inactivity");
+ exit (1);
+ return FALSE;
+}
+
+static void
+reset_killtimer (void)
+{
+ static guint timer_id = 0;
+
+ if (no_exit)
+ return;
+
+ if (timer_id > 0) {
+ g_source_remove (timer_id);
+ }
+ g_debug ("Setting killtimer to 30 seconds...");
+ timer_id = g_timeout_add (30 * 1000, do_exit, NULL);
+}
+
+struct PolKitDaemonPrivate
+{
+ DBusGConnection *system_bus_connection;
+ DBusGProxy *system_bus_proxy;
+ PolKitContext *pk_context;
+ PolKitTracker *pk_tracker;
+};
+
+static void polkit_daemon_class_init (PolKitDaemonClass *klass);
+static void polkit_daemon_init (PolKitDaemon *seat);
+static void polkit_daemon_finalize (GObject *object);
+
+G_DEFINE_TYPE (PolKitDaemon, polkit_daemon, G_TYPE_OBJECT)
+
+#define POLKIT_DAEMON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POLKIT_TYPE_DAEMON, PolKitDaemonPrivate))
+
+GQuark
+polkit_daemon_error_quark (void)
+{
+ static GQuark ret = 0;
+
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("polkit_daemon_error");
+ }
+
+ return ret;
+}
+
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+polkit_daemon_error_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static const GEnumValue values[] =
+ {
+ ENUM_ENTRY (POLKIT_DAEMON_ERROR_GENERAL, "GeneralError"),
+ ENUM_ENTRY (POLKIT_DAEMON_ERROR_NOT_AUTHORIZED, "NotAuthorized"),
+ { 0, 0, 0 }
+ };
+
+ g_assert (POLKIT_DAEMON_NUM_ERRORS == G_N_ELEMENTS (values) - 1);
+
+ etype = g_enum_register_static ("PolKitDaemonError", values);
+ }
+
+ return etype;
+}
+
+
+static GObject *
+polkit_daemon_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ PolKitDaemon *daemon;
+ PolKitDaemonClass *klass;
+
+ klass = POLKIT_DAEMON_CLASS (g_type_class_peek (POLKIT_TYPE_DAEMON));
+
+ daemon = POLKIT_DAEMON (
+ G_OBJECT_CLASS (polkit_daemon_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ return G_OBJECT (daemon);
+}
+
+static void
+polkit_daemon_class_init (PolKitDaemonClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = polkit_daemon_constructor;
+ object_class->finalize = polkit_daemon_finalize;
+
+ g_type_class_add_private (klass, sizeof (PolKitDaemonPrivate));
+
+ dbus_g_object_type_install_info (POLKIT_TYPE_DAEMON, &dbus_glib_polkit_daemon_object_info);
+
+ dbus_g_error_domain_register (POLKIT_DAEMON_ERROR, NULL, POLKIT_DAEMON_TYPE_ERROR);
+
+}
+
+static void
+polkit_daemon_init (PolKitDaemon *daemon)
+{
+ daemon->priv = POLKIT_DAEMON_GET_PRIVATE (daemon);
+
+}
+
+static void
+polkit_daemon_finalize (GObject *object)
+{
+ PolKitDaemon *daemon;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (POLKIT_IS_DAEMON (object));
+
+ daemon = POLKIT_DAEMON (object);
+
+ g_return_if_fail (daemon->priv != NULL);
+
+ g_object_unref (daemon->priv->system_bus_proxy);
+
+ G_OBJECT_CLASS (polkit_daemon_parent_class)->finalize (object);
+}
+
+static gboolean
+pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
+{
+ int fd;
+ PolKitContext *pk_context = user_data;
+ fd = g_io_channel_unix_get_fd (channel);
+ polkit_context_io_func (pk_context, fd);
+ return TRUE;
+}
+
+static int
+pk_io_add_watch (PolKitContext *pk_context, int fd)
+{
+ guint id = 0;
+ GIOChannel *channel;
+ channel = g_io_channel_unix_new (fd);
+ if (channel == NULL)
+ goto out;
+ id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context);
+ if (id == 0) {
+ g_io_channel_unref (channel);
+ goto out;
+ }
+ g_io_channel_unref (channel);
+out:
+ return id;
+}
+
+static void
+pk_io_remove_watch (PolKitContext *pk_context, int watch_id)
+{
+ g_source_remove (watch_id);
+}
+
+static DBusHandlerResult
+_filter (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+ PolKitDaemon *daemon = POLKIT_DAEMON (user_data);
+
+ /* pass NameOwnerChanged signals from the bus and ConsoleKit to PolKitTracker */
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged") ||
+ (dbus_message_get_interface (message) != NULL &&
+ g_str_has_prefix (dbus_message_get_interface (message), "org.freedesktop.ConsoleKit"))) {
+ if (polkit_tracker_dbus_func (daemon->priv->pk_tracker, message)) {
+
+ /* Something has changed! TODO: emit D-Bus signal? */
+ g_debug ("Something has changed!");
+ }
+ }
+
+ /* other filters might want to process this message too */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean
+register_daemon (PolKitDaemon *daemon)
+{
+ DBusConnection *connection;
+ DBusError dbus_error;
+ GError *error = NULL;
+
+ daemon->priv->pk_context = polkit_context_new ();
+ polkit_context_set_io_watch_functions (daemon->priv->pk_context, pk_io_add_watch, pk_io_remove_watch);
+ if (!polkit_context_init (daemon->priv->pk_context, NULL)) {
+ g_critical ("cannot initialize libpolkit");
+ goto error;
+ }
+
+ error = NULL;
+ daemon->priv->system_bus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (daemon->priv->system_bus_connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ goto error;
+ }
+ connection = dbus_g_connection_get_connection (daemon->priv->system_bus_connection);
+
+ daemon->priv->pk_tracker = polkit_tracker_new ();
+ polkit_tracker_set_system_bus_connection (daemon->priv->pk_tracker, connection);
+ polkit_tracker_init (daemon->priv->pk_tracker);
+
+ dbus_g_connection_register_g_object (daemon->priv->system_bus_connection, "/",
+ G_OBJECT (daemon));
+
+ daemon->priv->system_bus_proxy = dbus_g_proxy_new_for_name (daemon->priv->system_bus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
+ * we can't say we're interested in all signals from all
+ * members on all interfaces for a given service... So we do
+ * this..
+ */
+
+ dbus_error_init (&dbus_error);
+
+ /* need to listen to NameOwnerChanged */
+ dbus_bus_add_match (connection,
+ "type='signal'"
+ ",interface='"DBUS_INTERFACE_DBUS"'"
+ ",sender='"DBUS_SERVICE_DBUS"'"
+ ",member='NameOwnerChanged'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto error;
+ }
+
+ /* need to listen to ConsoleKit signals */
+ dbus_bus_add_match (connection,
+ "type='signal',sender='org.freedesktop.ConsoleKit'",
+ &dbus_error);
+
+ if (dbus_error_is_set (&dbus_error)) {
+ g_warning ("Cannot add match rule: %s: %s", dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ goto error;
+ }
+
+ if (!dbus_connection_add_filter (connection,
+ _filter,
+ daemon,
+ NULL)) {
+ g_warning ("Cannot add D-Bus filter: %s: %s", dbus_error.name, dbus_error.message);
+ goto error;
+ }
+
+ reset_killtimer ();
+
+ return TRUE;
+
+error:
+ return FALSE;
+}
+
+
+PolKitDaemon *
+polkit_daemon_new (gboolean _no_exit)
+{
+ GObject *object;
+ gboolean res;
+
+ no_exit = _no_exit;
+
+ object = g_object_new (POLKIT_TYPE_DAEMON, NULL);
+
+ res = register_daemon (POLKIT_DAEMON (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return POLKIT_DAEMON (object);
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+/* exported methods */
+
+static PolKitCaller *
+get_caller_from_context (PolKitDaemon *daemon, DBusGMethodInvocation *context)
+{
+ const char *sender;
+ GError *error;
+ DBusError dbus_error;
+ PolKitCaller *pk_caller;
+
+ sender = dbus_g_method_get_sender (context);
+ dbus_error_init (&dbus_error);
+ pk_caller = polkit_tracker_get_caller_from_dbus_name (daemon->priv->pk_tracker,
+ sender,
+ &dbus_error);
+ if (pk_caller == NULL) {
+ error = g_error_new (POLKIT_DAEMON_ERROR,
+ POLKIT_DAEMON_ERROR_GENERAL,
+ "Error getting information about caller: %s: %s",
+ dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return NULL;
+ }
+
+ return pk_caller;
+}
+
+
+/* takes ownership of pk_caller */
+static gboolean
+is_caller_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ PolKitCaller *pk_caller,
+ DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ GError *error;
+ PolKitCaller *pk_caller_who_wants_to_know;
+ uid_t uid_caller;
+ uid_t uid_caller_who_wants_to_know;
+ PolKitAction *pk_action;
+ PolKitResult pk_result;
+
+ ret = FALSE;
+ pk_caller_who_wants_to_know = NULL;
+
+ pk_caller_who_wants_to_know = get_caller_from_context (daemon, context);
+ if (pk_caller_who_wants_to_know == NULL) {
+ goto out;
+ }
+
+ if (!polkit_caller_get_uid (pk_caller_who_wants_to_know, &uid_caller_who_wants_to_know))
+ goto out;
+
+ if (!polkit_caller_get_uid (pk_caller, &uid_caller))
+ goto out;
+
+ if (uid_caller_who_wants_to_know != uid_caller) {
+ /* if the uid's are different, the caller who wants to know need to posses
+ * the org.freedesktop.policykit.read authorization
+ */
+
+ pk_action = polkit_action_new ();
+ polkit_action_set_action_id (pk_action, "org.freedesktop.policykit.read");
+ pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context,
+ pk_action,
+ pk_caller_who_wants_to_know,
+ FALSE);
+ polkit_action_unref (pk_action);
+ if (pk_result != POLKIT_RESULT_YES) {
+ error = g_error_new (POLKIT_DAEMON_ERROR,
+ POLKIT_DAEMON_ERROR_NOT_AUTHORIZED,
+ "uid %d is not authorized to know authorizations for uid %d "
+ "(requires org.freedesktop.policykit.read)",
+ uid_caller_who_wants_to_know, uid_caller);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+ }
+
+ pk_action = polkit_action_new ();
+ polkit_action_set_action_id (pk_action, action_id);
+ pk_result = polkit_context_is_caller_authorized (daemon->priv->pk_context, pk_action, pk_caller, FALSE);
+ polkit_action_unref (pk_action);
+
+ dbus_g_method_return (context, polkit_result_to_string_representation (pk_result));
+
+out:
+ if (pk_caller_who_wants_to_know != NULL)
+ polkit_caller_unref (pk_caller_who_wants_to_know);
+
+ if (pk_caller != NULL)
+ polkit_caller_unref (pk_caller);
+
+ return ret;
+}
+
+gboolean
+polkit_daemon_is_process_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ guint32 pid,
+ DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ DBusError dbus_error;
+ GError *error;
+ PolKitCaller *pk_caller;
+
+ ret = FALSE;
+ pk_caller = NULL;
+
+ dbus_error_init (&dbus_error);
+ pk_caller = polkit_tracker_get_caller_from_pid (daemon->priv->pk_tracker, (pid_t) pid, &dbus_error);
+ if (pk_caller == NULL) {
+ error = g_error_new (POLKIT_DAEMON_ERROR,
+ POLKIT_DAEMON_ERROR_GENERAL,
+ "Error getting information about pid %d: %s: %s",
+ pid,
+ dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = is_caller_authorized (daemon, action_id, pk_caller, context);
+
+out:
+ return ret;
+}
+
+gboolean
+polkit_daemon_is_system_bus_name_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ const char *system_bus_name,
+ DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ DBusError dbus_error;
+ GError *error;
+ PolKitCaller *pk_caller;
+
+ ret = FALSE;
+ pk_caller = NULL;
+
+ if (!_pk_validate_unique_bus_name (system_bus_name)) {
+ error = g_error_new (POLKIT_DAEMON_ERROR,
+ POLKIT_DAEMON_ERROR_GENERAL,
+ "Given system bus name is not a valid unique system bus name");
+ dbus_error_free (&dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ dbus_error_init (&dbus_error);
+ pk_caller = polkit_tracker_get_caller_from_dbus_name (daemon->priv->pk_tracker, system_bus_name, &dbus_error);
+ if (pk_caller == NULL) {
+ error = g_error_new (POLKIT_DAEMON_ERROR,
+ POLKIT_DAEMON_ERROR_GENERAL,
+ "Error getting information about system bus name %s: %s: %s",
+ system_bus_name,
+ dbus_error.name, dbus_error.message);
+ dbus_error_free (&dbus_error);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ ret = is_caller_authorized (daemon, action_id, pk_caller, context);
+
+out:
+ return ret;
+}
diff --git a/polkitd/polkit-daemon.h b/polkitd/polkit-daemon.h
new file mode 100644
index 0000000..6031bf5
--- /dev/null
+++ b/polkitd/polkit-daemon.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+ *
+ * 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.
+ *
+ */
+
+#define POLKIT_TYPE_DAEMON (polkit_daemon_get_type ())
+#define POLKIT_DAEMON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_TYPE_DAEMON, PolKitDaemon))
+#define POLKIT_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_TYPE_DAEMON, PolKitDaemonClass))
+#define POLKIT_IS_DAEMON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_TYPE_DAEMON))
+#define POLKIT_IS_DAEMON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_TYPE_DAEMON))
+#define POLKIT_DAEMON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_TYPE_DAEMON, PolKitDaemonClass))
+
+typedef struct PolKitDaemonPrivate PolKitDaemonPrivate;
+
+typedef struct
+{
+ GObject parent;
+ PolKitDaemonPrivate *priv;
+} PolKitDaemon;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} PolKitDaemonClass;
+
+typedef enum
+{
+ POLKIT_DAEMON_ERROR_GENERAL,
+ POLKIT_DAEMON_ERROR_NOT_AUTHORIZED,
+ POLKIT_DAEMON_NUM_ERRORS
+} PolKitDaemonError;
+
+#define POLKIT_DAEMON_ERROR polkit_daemon_error_quark ()
+
+GType polkit_daemon_error_get_type (void);
+#define POLKIT_DAEMON_TYPE_ERROR (polkit_daemon_error_get_type ())
+
+GQuark polkit_daemon_error_quark (void);
+GType polkit_daemon_get_type (void);
+PolKitDaemon *polkit_daemon_new (gboolean no_exit);
+
+/* exported methods */
+
+gboolean polkit_daemon_is_session_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ const char *ck_session_id,
+ DBusGMethodInvocation *context);
+
+gboolean polkit_daemon_is_process_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ guint32 pid,
+ DBusGMethodInvocation *context);
+
+gboolean polkit_daemon_is_system_bus_name_authorized (PolKitDaemon *daemon,
+ const char *action_id,
+ const char *system_bus_name,
+ DBusGMethodInvocation *context);
More information about the hal-commit
mailing list