PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Sat Apr 7 23:07:49 PDT 2007


 Makefile.am                                 |    2 
 configure.in                                |    4 
 doc/api/libpolkit/libpolkit-docs.xml        |    2 
 doc/man/Makefile.am                         |    4 
 doc/man/PolicyKit.8.in                      |   38 ++
 doc/man/polkit-check-caller.1.in            |    1 
 doc/man/polkit-check-session.1.in           |    1 
 doc/man/polkit-module-allow-all.8.in        |   61 +++
 doc/man/polkit-module-default.8.in          |   39 ++
 doc/man/polkit-module-deny-all.8.in         |   60 +++
 doc/man/polkit-privilege-file-validate.1.in |    1 
 libpolkit/Makefile.am                       |   11 
 libpolkit/libpolkit-context.c               |  443 ++++++++++++++++++++++++-
 libpolkit/libpolkit-context.h               |   50 ++
 libpolkit/libpolkit-debug.c                 |   10 
 libpolkit/libpolkit-module.c                |  490 ++++++++++++++++++++++++++++
 libpolkit/libpolkit-module.h                |  192 ++++++++++
 libpolkit/libpolkit-result.c                |    4 
 libpolkit/libpolkit-result.h                |    9 
 libpolkit/libpolkit.c                       |  219 ------------
 libpolkit/libpolkit.h                       |   46 --
 modules/Makefile.am                         |    5 
 modules/PolicyKit.conf                      |    5 
 modules/allow-all/Makefile.am               |   25 +
 modules/allow-all/polkit-module-allow-all.c |  241 +++++++++++++
 modules/default/Makefile.am                 |   25 +
 modules/default/polkit-module-default.c     |  116 ++++++
 modules/deny-all/Makefile.am                |   25 +
 tools/polkit-check-caller.c                 |    2 
 tools/polkit-check-session.c                |    2 
 30 files changed, 1842 insertions(+), 291 deletions(-)

New commits:
diff-tree 3638c6c15eb33ec64559dc9f075c3f82f9cbcb66 (from a1b5a12bd768c2d34d33c24af1853a424b875527)
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Apr 8 02:07:42 2007 -0400

    add module loading to PolicyKit
    
    This paves the way for writing
    
     1. A module that tracks temporary (look in /var/run) and permanent (look
        in /var/lib) privilege grants
     2. A D-Bus service to authenticate a client to obtain to a privilege
        grant and then writing the grant in temporary or permanent storage
    
    Also, this feature lets people very easily lock down the system; just
    edit /etc/PolicyKit/PolicyKit.conf; add pam-module-deny-all / -allow-all
    stanzas with various privilege=<regexp> and user=<username> options.

diff --git a/Makefile.am b/Makefile.am
index 6e481ed..9c313f1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = libpolkit doc tools privileges
+SUBDIRS = libpolkit modules doc tools privileges
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libpolkit.pc
diff --git a/configure.in b/configure.in
index 7af5deb..25fc9af 100644
--- a/configure.in
+++ b/configure.in
@@ -174,6 +174,10 @@ doc/spec/Makefile
 doc/spec/polkit-spec.xml.in
 doc/man/Makefile
 privileges/Makefile
+modules/Makefile
+modules/default/Makefile
+modules/allow-all/Makefile
+modules/deny-all/Makefile
 ])
 
 dnl ==========================================================================
diff --git a/doc/api/libpolkit/libpolkit-docs.xml b/doc/api/libpolkit/libpolkit-docs.xml
index 1c9d355..7909e91 100644
--- a/doc/api/libpolkit/libpolkit-docs.xml
+++ b/doc/api/libpolkit/libpolkit-docs.xml
@@ -64,7 +64,6 @@
 	PolicyKit library.
       </para>
     </partintro>
-    <xi:include href="xml/libpolkit.xml"/>
     <xi:include href="xml/libpolkit-error.xml"/>
     <xi:include href="xml/libpolkit-result.xml"/>
     <xi:include href="xml/libpolkit-context.xml"/>
@@ -77,6 +76,7 @@
     <xi:include href="xml/libpolkit-seat.xml"/>
     <xi:include href="xml/libpolkit-session.xml"/>
     <xi:include href="xml/libpolkit-caller.xml"/>
+    <xi:include href="xml/libpolkit-module.xml"/>
   </reference>
 
   <index>
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 5b99a1f..93de521 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -1,7 +1,7 @@
 
 if MAN_PAGES_ENABLED
 
-MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in polkit-privilege-file-validate.1.in
+MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in polkit-privilege-file-validate.1.in PolicyKit.8.in polkit-module-default.8.in polkit-module-allow-all.8.in polkit-module-deny-all.8.in
 
 man_MANS = $(MAN_IN_FILES:.in=)
 
@@ -10,7 +10,7 @@ endif # MAN_PAGES_ENABLED
 EXTRA_DIST=$(man_MANS) $(MAN_IN_FILES)
 
 clean-local:
-	rm -f *~ *.1
+	rm -f *~ *.1 *.8
 
 %: %.in Makefile
 	$(edit) $< >$@
diff --git a/doc/man/PolicyKit.8.in b/doc/man/PolicyKit.8.in
new file mode 100644
index 0000000..ca427e3
--- /dev/null
+++ b/doc/man/PolicyKit.8.in
@@ -0,0 +1,38 @@
+.\" 
+.\" PolicyKit manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLICYKIT 8
+.SH NAME
+PolicyKit \- centralized policy management
+.SH DESCRIPTION
+.PP
+
+For more information about the big picture refer to the \fIPolicyKit
+spec\fP which can be found in
+.I "@docdir@/spec/polkit-spec.html"
+depending on the distribution.
+
+.SH BUGS
+.PP
+Please send bug reports to either the distribution or the HAL
+mailing list, see 
+.I "http://lists.freedesktop.org/mailman/listinfo/hal"
+on how to subscribe.
+
+.SH SEE ALSO
+.PP
+\&\fIpolkit-module-default\fR\|(8),
+\&\fIpolkit-module-allow-all\fR\|(8),
+\&\fIpolkit-module-deny-all\fR\|(8),
+\&\fIpolkit-check-caller\fR\|(1),
+\&\fIpolkit-check-session\fR\|(1),
+\&\fIpolkit-privilege-file-validate\fR\|(1),
+\&\fIdbus-daemon\fR\|(1),
+\&\fIhald\fR\|(8)
+
+
+.SH AUTHOR
+Written by David Zeuthen <david at fubar.dk> with a lot of help from many
+others.
+
diff --git a/doc/man/polkit-check-caller.1.in b/doc/man/polkit-check-caller.1.in
index 0992d9b..fe67d4d 100644
--- a/doc/man/polkit-check-caller.1.in
+++ b/doc/man/polkit-check-caller.1.in
@@ -56,6 +56,7 @@ on how to subscribe.
 
 .SH SEE ALSO
 .PP
+\&\fIPolicyKit\fR\|(8),
 \&\fIdbus-daemon\fR\|(1),
 \&\fIpolkit-check-session\fR\|(1)
 
diff --git a/doc/man/polkit-check-session.1.in b/doc/man/polkit-check-session.1.in
index b364104..cab454c 100644
--- a/doc/man/polkit-check-session.1.in
+++ b/doc/man/polkit-check-session.1.in
@@ -56,6 +56,7 @@ on how to subscribe.
 
 .SH SEE ALSO
 .PP
+\&\fIPolicyKit\fR\|(8),
 \&\fIdbus-daemon\fR\|(1),
 \&\fIpolkit-check-caller\fR\|(1)
 
diff --git a/doc/man/polkit-module-allow-all.8.in b/doc/man/polkit-module-allow-all.8.in
new file mode 100644
index 0000000..decd097
--- /dev/null
+++ b/doc/man/polkit-module-allow-all.8.in
@@ -0,0 +1,61 @@
+.\" 
+.\" polkit-module-allow-all manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-MODULE-ALLOW-ALL 8
+.SH NAME
+polkit-module-allow-all \- grant access to all privileges
+.SH SYNOPSIS
+.PP
+.B polkit-module-allow-all.so [privilege=<regexp>] [user=<username>]
+.SH DESCRIPTION
+.PP
+This PolicyKit module will allow access to any privilege regardless of
+the entity requesting it, what the requested privilege is and what
+resource is involved.
+
+For more information about the big picture refer to the \fIPolicyKit
+spec\fP which can be found in
+.I "@docdir@/spec/polkit-spec.html"
+depending on the distribution.
+
+.SH OPTIONS
+
+.TP 3n
+.B privilege=<regexp>
+Only consider requests where the privilege name matches the given
+regular expression. Example:
+.B privilege=hal-storage-mount*
+
+.TP 3n
+.B user=<username>
+Only consider requests matching the given username. May be both a
+numerical
+.B uid
+value or a username. Example:
+.B user=davidz
+
+.SH NOTES
+.PP
+Never use this module unless you
+.B COMPLETELY
+trust anyone with either remote or local access to the system.
+
+.SH BUGS
+.PP
+Please send bug reports to either the distribution or the HAL
+mailing list, see 
+.I "http://lists.freedesktop.org/mailman/listinfo/hal"
+on how to subscribe.
+
+.SH SEE ALSO
+.PP
+\&\fIPolicyKit\fR\|(8),
+\&\fIpolkit-module-default\fR\|(8),
+\&\fIpolkit-module-deny-all\fR\|(8),
+\&\fI at sysconfdir@/PolicyKit/privileges\fR\|,
+\&\fI at sysconfdir@/PolicyKit/PolicyKit.conf\fR\|
+
+.SH AUTHOR
+Written by David Zeuthen <david at fubar.dk> with a lot of help from many
+others.
diff --git a/doc/man/polkit-module-default.8.in b/doc/man/polkit-module-default.8.in
new file mode 100644
index 0000000..379d332
--- /dev/null
+++ b/doc/man/polkit-module-default.8.in
@@ -0,0 +1,39 @@
+.\" 
+.\" polkit-module-default manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-MODULE-DEFAULT 8
+.SH NAME
+polkit-module-default \- use default policy for privileges
+.SH SYNOPSIS
+.PP
+.B standard   polkit-module-default.so
+.SH DESCRIPTION
+.PP
+This PolicyKit module uses the default policy as specified (and
+required) for by the privilege definition file for a given privilege.
+
+For more information about the big picture refer to the \fIPolicyKit
+spec\fP which can be found in
+.I "@docdir@/spec/polkit-spec.html"
+depending on the distribution.
+
+.SH BUGS
+.PP
+Please send bug reports to either the distribution or the HAL
+mailing list, see 
+.I "http://lists.freedesktop.org/mailman/listinfo/hal"
+on how to subscribe.
+
+.SH SEE ALSO
+.PP
+\&\fIPolicyKit\fR\|(8),
+\&\fIpolkit-module-allow-all\fR\|(8),
+\&\fIpolkit-module-deny-all\fR\|(8),
+\&\fI at sysconfdir@/PolicyKit/privileges\fR\|,
+\&\fI at sysconfdir@/PolicyKit/PolicyKit.conf\fR\|
+
+.SH AUTHOR
+Written by David Zeuthen <david at fubar.dk> with a lot of help from many
+others.
+
diff --git a/doc/man/polkit-module-deny-all.8.in b/doc/man/polkit-module-deny-all.8.in
new file mode 100644
index 0000000..feee066
--- /dev/null
+++ b/doc/man/polkit-module-deny-all.8.in
@@ -0,0 +1,60 @@
+.\" 
+.\" polkit-module-deny-all manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-MODULE-DENY-ALL 8
+.SH NAME
+polkit-module-deny-all \- grant access to all privileges
+.SH SYNOPSIS
+.PP
+.B polkit-module-deny-all.so [privilege=<regexp>] [user=<username>]
+.SH DESCRIPTION
+.PP
+This PolicyKit module will deny access to any privilege regardless of
+the entity requesting it, what the requested privilege is and what
+resource is involved.
+
+For more information about the big picture refer to the \fIPolicyKit
+spec\fP which can be found in
+.I "@docdir@/spec/polkit-spec.html"
+depending on the distribution.
+
+.SH OPTIONS
+
+.TP 3n
+.B privilege=<regexp>
+Only consider requests where the privilege name matches the given
+regular expression. Example:
+.B privilege=hal-storage-mount*
+
+.TP 3n
+.B user=<username>
+Only consider requests matching the given username. May be both a
+numerical
+.B uid
+value or a username. Example:
+.B user=davidz
+
+.SH NOTES
+.PP
+This module is mostly useful in situations where it's desirable to
+lock down the system so it's unusable by normal unprivileged users.
+
+.SH BUGS
+.PP
+Please send bug reports to either the distribution or the HAL
+mailing list, see 
+.I "http://lists.freedesktop.org/mailman/listinfo/hal"
+on how to subscribe.
+
+.SH SEE ALSO
+.PP
+\&\fIPolicyKit\fR\|(8),
+\&\fIpolkit-module-default\fR\|(8),
+\&\fIpolkit-module-allow-all\fR\|(8),
+\&\fI at sysconfdir@/PolicyKit/privileges\fR\|,
+\&\fI at sysconfdir@/PolicyKit/PolicyKit.conf\fR\|
+
+.SH AUTHOR
+Written by David Zeuthen <david at fubar.dk> with a lot of help from many
+others.
diff --git a/doc/man/polkit-privilege-file-validate.1.in b/doc/man/polkit-privilege-file-validate.1.in
index 035f881..8a02f66 100644
--- a/doc/man/polkit-privilege-file-validate.1.in
+++ b/doc/man/polkit-privilege-file-validate.1.in
@@ -43,6 +43,7 @@ on how to subscribe.
 
 .SH SEE ALSO
 .PP
+\&\fIPolicyKit\fR\|(8),
 \&\fIpolkit-check-caller\fR\|(1),
 \&\fIpolkit-check-session\fR\|(1)
 
diff --git a/libpolkit/Makefile.am b/libpolkit/Makefile.am
index 244e21e..5961d9b 100644
--- a/libpolkit/Makefile.am
+++ b/libpolkit/Makefile.am
@@ -8,6 +8,7 @@ INCLUDES = \
 	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
 	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
 	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-DPACKAGE_LIB_DIR=\""$(libdir)"\" \
 	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
 	@GLIB_CFLAGS@ @DBUS_CFLAGS@
 
@@ -28,10 +29,11 @@ libpolkitinclude_HEADERS =              
 	libpolkit-privilege-file-entry.h		\
 	libpolkit-privilege-file.h			\
 	libpolkit-privilege-cache.h			\
-	libpolkit-privilege-default.h
+	libpolkit-privilege-default.h			\
+	libpolkit-module.h
 
 libpolkit_la_SOURCES =                  	              				\
-	libpolkit.h				libpolkit.c				\
+	libpolkit.h									\
 	libpolkit-error.h			libpolkit-error.c			\
 	libpolkit-result.h			libpolkit-result.c			\
 	libpolkit-context.h			libpolkit-context.c			\
@@ -44,9 +46,10 @@ libpolkit_la_SOURCES =                  
 	libpolkit-privilege-file.h		libpolkit-privilege-file.c		\
 	libpolkit-privilege-cache.h		libpolkit-privilege-cache.c		\
 	libpolkit-privilege-default.h		libpolkit-privilege-default.c		\
-	libpolkit-debug.h			libpolkit-debug.c
+	libpolkit-debug.h			libpolkit-debug.c			\
+	libpolkit-module.h			libpolkit-module.c
 
-libpolkit_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@
+libpolkit_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 
 libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
 
diff --git a/libpolkit/libpolkit-context.c b/libpolkit/libpolkit-context.c
index 2a05fbe..5dcc5b2 100644
--- a/libpolkit/libpolkit-context.c
+++ b/libpolkit/libpolkit-context.c
@@ -40,6 +40,7 @@
 #include "libpolkit-debug.h"
 #include "libpolkit-context.h"
 #include "libpolkit-privilege-cache.h"
+#include "libpolkit-module.h"
 
 /**
  * SECTION:libpolkit-context
@@ -66,6 +67,8 @@ struct PolKitContext
         char *priv_dir;
 
         PolKitPrivilegeCache *priv_cache;
+
+        GSList *modules;
 };
 
 /**
@@ -84,6 +87,147 @@ libpolkit_context_new (void)
         return pk_context;
 }
 
+static gboolean
+unload_modules (PolKitContext *pk_context)
+{
+        GSList *i;
+        for (i = pk_context->modules; i != NULL; i = g_slist_next (i)) {
+                PolKitModuleInterface *module_interface = i->data;
+                libpolkit_module_interface_unref (module_interface);
+        }
+        g_slist_free (pk_context->modules);
+        pk_context->modules = NULL;
+        _pk_debug ("Unloaded modules");
+
+        return TRUE;
+}
+
+static gboolean
+load_modules (PolKitContext *pk_context, GError **error)
+{
+        const char *config_file;
+        gboolean ret;
+        char *buf;
+        char *end;
+        char line[256];
+        char *p;
+        char *q;
+        gsize len;
+        int line_number;
+        int mod_number;
+
+        ret = FALSE;
+        buf = NULL;
+        mod_number = 0;
+
+        config_file = PACKAGE_SYSCONF_DIR "/PolicyKit/PolicyKit.conf";
+        if (!g_file_get_contents (config_file,
+                                  &buf,
+                                  &len,
+                                  error)) {
+                _pk_debug ("Cannot load PolicyKit configuration file at '%s'", config_file);
+                goto out;
+        }
+
+        end = buf + len;
+
+        /* parse the config file; one line at a time (yes, this is super ugly code) */
+        p = buf;
+        line_number = -1;
+        while (TRUE) {
+                int argc;
+                char **tokens;
+                char *module_name;
+                char *module_path;
+                PolKitModuleControl module_control;
+                PolKitModuleInterface *module_interface;
+
+                line_number++;
+
+                q = p;
+                while (*q != '\n' && q != '\0' && q < end)
+                        q++;
+                if (*q == '\0' || q >= end) {
+                        /* skip last line if it's not terminated by whitespace */
+                        break;
+                }
+                if ((unsigned int) (q - p) > sizeof(line) - 1) {
+                        _pk_debug ("Line is too long; skipping it");
+                        continue;
+                }
+                strncpy (line, p, q - p);
+                line[q - p] = '\0';
+                p = q + 1;
+
+                /* remove leading and trailing white space */
+                g_strstrip (line);
+
+                /* comments, blank lines are fine; just skip them */
+                if (line[0] == '#' || strlen (line) == 0) {
+                        continue;
+                }
+
+                /*_pk_debug ("Looking at line: '%s'", line);*/
+
+                if (!g_shell_parse_argv (line, &argc, &tokens, NULL)) {
+                        _pk_debug ("Cannot parse line %d - skipping", line_number);
+                        continue;
+                }
+                if (argc < 2) {
+                        _pk_debug ("Line %d is malformed - skipping line", line_number);
+                        g_strfreev (tokens);
+                        continue;
+                }
+                if (!libpolkit_module_control_from_string_representation (tokens[0], &module_control)) {
+                        _pk_debug ("Unknown module_control '%s' at line %d - skipping line", tokens[0], line_number);
+                        g_strfreev (tokens);
+                        continue;
+                }
+                module_name = tokens[1];
+
+                module_path = g_strdup_printf (PACKAGE_LIB_DIR "/PolicyKit/modules/%s", module_name);
+                _pk_debug ("MODULE: number=%d control=%d name=%s argc=%d", 
+                           mod_number, module_control, module_name, argc - 1);
+                module_interface = libpolkit_module_interface_load_module (module_path, 
+                                                                           module_control, 
+                                                                           argc - 1, 
+                                                                           tokens + 1);
+                g_free (module_path);
+
+                if (module_interface != NULL) {
+                        pk_context->modules = g_slist_append (pk_context->modules, module_interface);
+                        mod_number++;
+                }
+                g_strfreev (tokens);
+
+        }
+
+        ret = TRUE;
+
+out:
+        if (buf != NULL)
+                g_free (buf);
+
+        _pk_debug ("Loaded %d modules in total", mod_number);
+        return ret;
+}
+
+static void
+_config_file_events (PolKitContext                 *pk_context,
+                     PolKitContextFileMonitorEvent  event_mask,
+                     const char                    *path,
+                     gpointer                       user_data)
+{
+        _pk_debug ("Config file changed");
+        unload_modules (pk_context);
+        load_modules (pk_context, NULL);
+
+        /* signal that our configuration (may have) changed */
+        if (pk_context->config_changed_cb) {
+                pk_context->config_changed_cb (pk_context, pk_context->config_changed_user_data);
+        }
+}
+
 static void
 _privilege_dir_events (PolKitContext                 *pk_context,
                        PolKitContextFileMonitorEvent  event_mask,
@@ -117,11 +261,8 @@ _privilege_dir_events (PolKitContext    
 gboolean
 libpolkit_context_init (PolKitContext *pk_context, GError **error)
 {
-        gboolean ret;
         const char *dirname;
 
-        ret = FALSE;
-
         dirname = getenv ("POLKIT_PRIVILEGE_DIR");
         if (dirname != NULL) {
                 pk_context->priv_dir = g_strdup (dirname);
@@ -130,11 +271,16 @@ libpolkit_context_init (PolKitContext *p
         }
         _pk_debug ("Using privilege files from directory %s", pk_context->priv_dir);
 
+        /* Load modules */
+        if (!load_modules (pk_context, error))
+                goto error;
+
         /* don't populate the cache until it's needed.. */
 
         if (pk_context->file_monitor_add_watch_func == NULL) {
                 _pk_debug ("No file monitor; cannot monitor '%s' for .priv file changes", dirname);
         } else {
+                /* Watch when privilege definitions file change */
                 pk_context->file_monitor_add_watch_func (pk_context, 
                                                          pk_context->priv_dir,
                                                          POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE|
@@ -142,12 +288,23 @@ libpolkit_context_init (PolKitContext *p
                                                          POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE,
                                                          _privilege_dir_events,
                                                          NULL);
+
+                /* Config file changes */
+                pk_context->file_monitor_add_watch_func (pk_context, 
+                                                         PACKAGE_SYSCONF_DIR "/PolicyKit",
+                                                         POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE|
+                                                         POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE|
+                                                         POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE,
+                                                         _config_file_events,
+                                                         NULL);
         }
 
-        /* right now we can't fail - but in the future modules we load may */
+        return TRUE;
+error:
+        if (pk_context != NULL)
+                libpolkit_context_unref (pk_context);
 
-        ret = TRUE;
-        return ret;
+        return FALSE;
 }
 
 /**
@@ -177,10 +334,14 @@ libpolkit_context_ref (PolKitContext *pk
 void
 libpolkit_context_unref (PolKitContext *pk_context)
 {
+
         g_return_if_fail (pk_context != NULL);
         pk_context->refcount--;
         if (pk_context->refcount > 0) 
                 return;
+
+        unload_modules (pk_context);
+
         g_free (pk_context);
 }
 
@@ -263,3 +424,273 @@ libpolkit_context_get_privilege_cache (P
 
         return pk_context->priv_cache;
 }
+
+
+/**
+ * libpolkit_context_get_seat_resource_association:
+ * @pk_context: the PolicyKit context
+ * @visitor: visitor function
+ * @user_data: user data
+ *
+ * Retrieve information about what resources are associated to what
+ * seats. Note that a resource may be associated to more than one
+ * seat. This information stems from user configuration and consumers
+ * of this information that know better (e.g. HAL) may choose to
+ * override it. 
+ *
+ * Typically, this information is used to e.g. bootstrap the system
+ * insofar that it can be used to start login greeters on the given
+ * video hardware (e.g. resources) on the given user-configured seats.
+ *
+ * If a resource is not associated with any seat, it is assumed to be
+ * available to any local seat.
+ *
+ * Returns: A #PolKitResult - can only be one of
+ * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW or
+ * #LIBPOLKIT_RESULT_YES (if the callback was invoked)
+ */
+PolKitResult
+libpolkit_context_get_seat_resource_association (PolKitContext       *pk_context,
+                                                 PolKitSeatVisitorCB  visitor,
+                                                 gpointer            *user_data)
+{
+        return LIBPOLKIT_RESULT_YES;
+}
+
+/**
+ * libpolkit_context_is_resource_associated_with_seat:
+ * @pk_context: the PolicyKit context
+ * @resource: the resource in question
+ * @seat: the seat
+ *
+ * Determine if a given resource is associated with a given seat. The
+ * same comments noted in libpolkit_get_seat_resource_association() about the
+ * source purely being user configuration applies here as well.
+ *
+ * Returns: A #PolKitResult - can only be one of
+ * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
+ * #LIBPOLKIT_RESULT_YES, #LIBPOLKIT_RESULT_NO.
+ */
+PolKitResult
+libpolkit_context_is_resource_associated_with_seat (PolKitContext   *pk_context,
+                                                    PolKitResource  *resource,
+                                                    PolKitSeat      *seat)
+{
+        return LIBPOLKIT_RESULT_NO;
+}
+
+/**
+ * libpolkit_context_can_session_access_resource:
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @session: the session in question
+ *
+ * Determine if a given session can access a given resource in a given way.
+ *
+ * Returns: A #PolKitResult - can only be one of
+ * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
+ * #LIBPOLKIT_RESULT_YES, #LIBPOLKIT_RESULT_NO.
+ */
+PolKitResult
+libpolkit_context_can_session_access_resource (PolKitContext   *pk_context,
+                                               PolKitPrivilege *privilege,
+                                               PolKitResource  *resource,
+                                               PolKitSession   *session)
+{
+        PolKitPrivilegeCache *cache;
+        PolKitPrivilegeFileEntry *pfe;
+        PolKitResult current_result;
+        PolKitModuleControl current_control;
+        GSList *i;
+
+        current_result = LIBPOLKIT_RESULT_NO;
+
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        if (cache == NULL)
+                goto out;
+
+        _pk_debug ("entering libpolkit_can_session_access_resource()");
+        libpolkit_privilege_debug (privilege);
+        libpolkit_resource_debug (resource);
+        libpolkit_session_debug (session);
+
+        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
+        if (pfe == NULL) {
+                char *privilege_name;
+                if (!libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
+                        g_warning ("given privilege has no name");
+                } else {
+                        g_warning ("no privilege with name '%s'", privilege_name);
+                }
+                current_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+                goto out;
+        }
+
+        libpolkit_privilege_file_entry_debug (pfe);
+
+        current_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+        current_control = LIBPOLKIT_MODULE_CONTROL_ADVISE; /* start with advise */
+
+        /* visit modules */
+        for (i = pk_context->modules; i != NULL; i = g_slist_next (i)) {
+                PolKitModuleInterface *module_interface = i->data;
+                PolKitModuleCanSessionAccessResource func;
+
+                func = libpolkit_module_get_func_can_session_access_resource (module_interface);
+                if (func != NULL) {
+                        PolKitModuleControl module_control;
+                        PolKitResult module_result;
+
+                        _pk_debug ("Asking module '%s'", libpolkit_module_get_name (module_interface));
+
+                        module_control = libpolkit_module_interface_get_control (module_interface);
+                        module_result = func (module_interface,
+                                              pk_context,
+                                              privilege, 
+                                              resource, 
+                                              session);
+
+                        /* if a module returns _UNKNOWN_PRIVILEGE, 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 privileges
+                         * or certain users.
+                         */
+                        if (module_result != LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE) {
+
+                                if (current_control == LIBPOLKIT_MODULE_CONTROL_ADVISE &&
+                                    module_control == LIBPOLKIT_MODULE_CONTROL_ADVISE) {
+
+                                        /* take the less strict result */
+                                        if (current_result < module_result) {
+                                                current_result = module_result;
+                                        }
+
+                                } else if (current_control == LIBPOLKIT_MODULE_CONTROL_ADVISE &&
+                                           module_control == LIBPOLKIT_MODULE_CONTROL_MANDATORY) {
+                                        
+                                        /* here we just override */
+                                        current_result = module_result;
+
+                                        /* we are now in mandatory mode */
+                                        current_control = LIBPOLKIT_MODULE_CONTROL_MANDATORY;
+                                }
+                        }
+                }
+        }
+
+        /* Never return UNKNOWN_PRIVILEGE to user */
+        if (current_result == LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE)
+                current_result = LIBPOLKIT_RESULT_NO;
+
+out:
+        _pk_debug ("... result was %s", libpolkit_result_to_string_representation (current_result));
+        return current_result;
+}
+
+/**
+ * libpolkit_context_can_caller_access_resource:
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @caller: the resource in question
+ *
+ * Determine if a given caller can access a given resource in a given way.
+ *
+ * Returns: A #PolKitResult specifying if, and how, the caller can
+ * access the resource in the given way
+ */
+PolKitResult
+libpolkit_context_can_caller_access_resource (PolKitContext   *pk_context,
+                                              PolKitPrivilege *privilege,
+                                              PolKitResource  *resource,
+                                              PolKitCaller    *caller)
+{
+        PolKitPrivilegeCache *cache;
+        PolKitPrivilegeFileEntry *pfe;
+        PolKitResult current_result;
+        PolKitModuleControl current_control;
+        GSList *i;
+
+        current_result = LIBPOLKIT_RESULT_NO;
+
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        if (cache == NULL)
+                goto out;
+
+        _pk_debug ("entering libpolkit_can_caller_access_resource()");
+        libpolkit_privilege_debug (privilege);
+        libpolkit_resource_debug (resource);
+        libpolkit_caller_debug (caller);
+
+        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
+        if (pfe == NULL) {
+                char *privilege_name;
+                if (!libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
+                        g_warning ("given privilege has no name");
+                } else {
+                        g_warning ("no privilege with name '%s'", privilege_name);
+                }
+                current_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+                goto out;
+        }
+
+        libpolkit_privilege_file_entry_debug (pfe);
+
+        current_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+        current_control = LIBPOLKIT_MODULE_CONTROL_ADVISE; /* start with advise */
+
+        /* visit modules */
+        for (i = pk_context->modules; i != NULL; i = g_slist_next (i)) {
+                PolKitModuleInterface *module_interface = i->data;
+                PolKitModuleCanCallerAccessResource func;
+
+                func = libpolkit_module_get_func_can_caller_access_resource (module_interface);
+                if (func != NULL) {
+                        PolKitModuleControl module_control;
+                        PolKitResult module_result;
+
+                        _pk_debug ("Asking module '%s'", libpolkit_module_get_name (module_interface));
+
+                        module_control = libpolkit_module_interface_get_control (module_interface);
+                        module_result = func (module_interface,
+                                              pk_context,
+                                              privilege, 
+                                              resource, 
+                                              caller);
+
+                        /* if a module returns _UNKNOWN_PRIVILEGE, 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 privileges
+                         * or certain users.
+                         */
+                        if (module_result != LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE) {
+
+                                if (current_control == LIBPOLKIT_MODULE_CONTROL_ADVISE &&
+                                    module_control == LIBPOLKIT_MODULE_CONTROL_ADVISE) {
+
+                                        /* take the less strict result */
+                                        if (current_result < module_result) {
+                                                current_result = module_result;
+                                        }
+
+                                } else if (current_control == LIBPOLKIT_MODULE_CONTROL_ADVISE &&
+                                           module_control == LIBPOLKIT_MODULE_CONTROL_MANDATORY) {
+                                        
+                                        /* here we just override */
+                                        current_result = module_result;
+
+                                        /* we are now in mandatory mode */
+                                        current_control = LIBPOLKIT_MODULE_CONTROL_MANDATORY;
+                                }
+                        }
+                }
+        }
+
+        /* Never return UNKNOWN_PRIVILEGE to user */
+        if (current_result == LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE)
+                current_result = LIBPOLKIT_RESULT_NO;
+out:
+        _pk_debug ("... result was %s", libpolkit_result_to_string_representation (current_result));
+        return current_result;
+}
diff --git a/libpolkit/libpolkit-context.h b/libpolkit/libpolkit-context.h
index 33705ff..31fd1da 100644
--- a/libpolkit/libpolkit-context.h
+++ b/libpolkit/libpolkit-context.h
@@ -31,6 +31,14 @@
 #include <sys/types.h>
 #include <glib.h>
 
+#include <libpolkit/libpolkit-error.h>
+#include <libpolkit/libpolkit-result.h>
+#include <libpolkit/libpolkit-context.h>
+#include <libpolkit/libpolkit-privilege.h>
+#include <libpolkit/libpolkit-resource.h>
+#include <libpolkit/libpolkit-seat.h>
+#include <libpolkit/libpolkit-session.h>
+#include <libpolkit/libpolkit-caller.h>
 #include <libpolkit/libpolkit-privilege-cache.h>
 
 struct PolKitContext;
@@ -126,19 +134,53 @@ typedef void (*PolKitContextFileMonitorR
 
 
 PolKitContext *libpolkit_context_new                (void);
-gboolean       libpolkit_context_init               (PolKitContext                       *pk_context, 
-                                                     GError                             **error);
-PolKitContext *libpolkit_context_ref                (PolKitContext                        *pk_context);
-void           libpolkit_context_unref              (PolKitContext                        *pk_context);
 void           libpolkit_context_set_config_changed (PolKitContext                        *pk_context, 
                                                      PolKitContextConfigChangedCB          cb, 
                                                      gpointer                              user_data);
 void           libpolkit_context_set_file_monitor   (PolKitContext                        *pk_context, 
                                                      PolKitContextFileMonitorAddWatch      add_watch_func,
                                                      PolKitContextFileMonitorRemoveWatch   remove_watch_func);
+gboolean       libpolkit_context_init               (PolKitContext                        *pk_context, 
+                                                     GError                              **error);
+PolKitContext *libpolkit_context_ref                (PolKitContext                        *pk_context);
+void           libpolkit_context_unref              (PolKitContext                        *pk_context);
 
 PolKitPrivilegeCache *libpolkit_context_get_privilege_cache (PolKitContext *pk_context);
 
+/**
+ * PolKitSeatVisitorCB:
+ * @seat: the seat
+ * @resources_associated_with_seat: A NULL terminated array of resources associated with the seat
+ * @user_data: user data
+ *
+ * Visitor function for libpolkit_get_seat_resource_association(). The caller should _not_ unref the passed objects.
+ */
+typedef void (*PolKitSeatVisitorCB) (PolKitSeat      *seat,
+                                     PolKitResource **resources_associated_with_seat,
+                                     gpointer         user_data);
+
+PolKitResult
+libpolkit_context_get_seat_resource_association (PolKitContext       *pk_context,
+                                                 PolKitSeatVisitorCB  visitor,
+                                                 gpointer            *user_data);
+
+PolKitResult
+libpolkit_context_is_resource_associated_with_seat (PolKitContext   *pk_context,
+                                                    PolKitResource  *resource,
+                                                    PolKitSeat      *seat);
+
+PolKitResult
+libpolkit_context_can_session_access_resource (PolKitContext   *pk_context,
+                                               PolKitPrivilege *privilege,
+                                               PolKitResource  *resource,
+                                               PolKitSession   *session);
+
+PolKitResult
+libpolkit_context_can_caller_access_resource (PolKitContext   *pk_context,
+                                              PolKitPrivilege *privilege,
+                                              PolKitResource  *resource,
+                                              PolKitCaller    *caller);
+
 #endif /* LIBPOLKIT_CONTEXT_H */
 
 
diff --git a/libpolkit/libpolkit-debug.c b/libpolkit/libpolkit-debug.c
index 1a07435..b4987a5 100644
--- a/libpolkit/libpolkit-debug.c
+++ b/libpolkit/libpolkit-debug.c
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <sys/time.h>
 
 #include "libpolkit-debug.h"
 
@@ -61,6 +62,15 @@ _pk_debug (const char *format, ...)
         }
 
         if (show_debug) {
+                struct timeval tnow;
+                struct tm *tlocaltime;
+                struct timezone tzone;
+                char tbuf[256];
+                gettimeofday (&tnow, &tzone);
+                tlocaltime = localtime ((time_t *) &tnow.tv_sec);
+                strftime (tbuf, sizeof (tbuf), "%H:%M:%S", tlocaltime);
+		fprintf (stdout, "%s.%03d: ", tbuf, (int)(tnow.tv_usec/1000));
+
                 va_start (args, format);
                 vfprintf (stdout, format, args);
                 va_end (args);
diff --git a/libpolkit/libpolkit-module.c b/libpolkit/libpolkit-module.c
new file mode 100644
index 0000000..562e90c
--- /dev/null
+++ b/libpolkit/libpolkit-module.c
@@ -0,0 +1,490 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-module.c : PolicyKit loadable module interface
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+/**
+ * SECTION:libpolkit-module
+ * @short_description: PolicyKit loadable module interface
+ *
+ * These functions are used by loadable PolicyKit modules.
+ **/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+#include <dlfcn.h>
+
+#include "libpolkit-debug.h"
+#include "libpolkit-module.h"
+
+/**
+ * PolKitModuleInterface:
+ *
+ * Objects of this class are used to interface with PolicyKit modules
+ **/
+struct PolKitModuleInterface
+{
+        int refcount;
+        void *dlopen_handle;
+        char *name;
+
+        gpointer module_user_data;
+        PolKitModuleControl module_control;
+
+        PolKitModuleInitialize                     func_initialize;
+        PolKitModuleShutdown                       func_shutdown;
+        PolKitModuleGetSeatResourceAssociation     func_get_seat_resource_association;
+        PolKitModuleIsResourceAssociatedWithSeat   func_is_resource_associated_with_seat;
+        PolKitModuleCanSessionAccessResource       func_can_session_access_resource;
+        PolKitModuleCanCallerAccessResource        func_can_caller_access_resource;
+};
+
+/**
+ * libpolkit_module_interface_load_module:
+ * @name: name of module, e.g. "polkit-module-default.so"
+ * @module_control: the module control; from the configuration file
+ * @argc: number arguments to pass
+ * @argv: argument vector, the first argument must be the filename/path to the module
+ * 
+ * Load and initialize a PolicyKit module
+ * 
+ * Returns: A #PolKitModuleInterface object on success; #NULL on failure.
+ **/
+PolKitModuleInterface *
+libpolkit_module_interface_load_module (const char *name, PolKitModuleControl module_control, int argc, char *argv[])
+{
+        void *handle;
+        PolKitModuleInterface *mi;
+        gboolean (*func) (PolKitModuleInterface *);
+
+        mi = NULL;
+
+        _pk_debug ("loading %s", name);
+
+        handle = dlopen (name, RTLD_NOW | RTLD_LOCAL);
+        if (handle == NULL) {
+                _pk_debug ("Cannot load module '%s'", name);
+                goto error;
+        }
+
+        func = dlsym (handle, "libpolkit_module_set_functions");
+        if (func == NULL) {
+                _pk_debug ("Cannot get symbol 'libpolkit_module_set_functions' in module '%s'", name);
+                goto error;
+        }
+
+        _pk_debug ("func = %p", func);
+
+        mi = libpolkit_module_interface_new ();
+        if (!func (mi)) {
+                _pk_debug ("Module '%s' returned FALSE when asked to set functions", name);
+                goto error;
+        }
+
+        if (mi->func_initialize == NULL) {
+                _pk_debug ("Module '%s' didn't set initialize function", name);
+                goto error;
+        }
+        
+        if (mi->func_shutdown == NULL) {
+                _pk_debug ("Module '%s' didn't set shutdown function", name);
+                goto error;
+        }
+
+        if (!mi->func_initialize (mi, argc, argv)) {
+                _pk_debug ("Module '%s' returned FALSE in initialization function", name);
+                goto error;
+        }
+
+        mi->dlopen_handle = handle;
+        mi->name = g_strdup (name);
+        mi->module_control = module_control;
+        return mi;
+error:
+        if (mi != NULL)
+                libpolkit_module_interface_unref (mi);
+        if (handle != NULL)
+                dlclose (handle);
+        return NULL;
+}
+
+/**
+ * libpolkit_module_get_name:
+ * @module_interface: the module interface
+ * 
+ * Get the name of the module
+ * 
+ * Returns: name or #NULL if an error occured
+ **/
+const char *
+libpolkit_module_get_name (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->name;
+}
+
+
+/**
+ * libpolkit_module_interface_new:
+ * 
+ * Create a new #PolKitModuleInterface object.
+ * 
+ * Returns: the new object
+ **/
+PolKitModuleInterface *
+libpolkit_module_interface_new (void)
+{
+        PolKitModuleInterface *module_interface;
+        module_interface = g_new0 (PolKitModuleInterface, 1);
+        module_interface->refcount = 1;
+        return module_interface;
+}
+
+/**
+ * libpolkit_module_interface_ref:
+ * @module_interface: the module_interface object
+ * 
+ * Increase reference count.
+ * 
+ * Returns: the object
+ **/
+PolKitModuleInterface *
+libpolkit_module_interface_ref (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, module_interface);
+        module_interface->refcount++;
+        return module_interface;
+}
+
+/**
+ * libpolkit_module_interface_unref:
+ * @module_interface: the module_interface object
+ * 
+ * Decreases the reference count of the object. If it becomes zero,
+ * the object is freed. Before freeing, reference counts on embedded
+ * objects are decresed by one.
+ **/
+void
+libpolkit_module_interface_unref (PolKitModuleInterface *module_interface)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->refcount--;
+        if (module_interface->refcount > 0) 
+                return;
+
+        /* shutdown the module and unload it */
+        if (module_interface->func_shutdown != NULL)
+                module_interface->func_shutdown (module_interface);
+        if (module_interface->dlopen_handle != NULL)
+                dlclose (module_interface->dlopen_handle);
+
+        g_free (module_interface->name);
+        g_free (module_interface);
+}
+
+/**
+ * libpolkit_module_set_func_initialize:
+ * @module_interface: the module interface
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void
+libpolkit_module_set_func_initialize (PolKitModuleInterface  *module_interface, 
+                                      PolKitModuleInitialize  func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_initialize = func;
+}
+
+/**
+ * libpolkit_module_set_func_shutdown:
+ * @module_interface: the module interface 
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void 
+libpolkit_module_set_func_shutdown (PolKitModuleInterface *module_interface, 
+                                    PolKitModuleShutdown   func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_shutdown = func;
+}
+
+/**
+ * libpolkit_module_set_func_get_seat_resource_association:
+ * @module_interface: the module interface 
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void 
+libpolkit_module_set_func_get_seat_resource_association (PolKitModuleInterface                   *module_interface,
+                                                         PolKitModuleGetSeatResourceAssociation  func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_get_seat_resource_association = func;
+}
+
+/**
+ * libpolkit_module_set_func_is_resource_associated_with_seat:
+ * @module_interface: the module interface 
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void libpolkit_module_set_func_is_resource_associated_with_seat (PolKitModuleInterface               *module_interface,
+                                                                 PolKitModuleIsResourceAssociatedWithSeat func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_is_resource_associated_with_seat = func;
+}
+
+/**
+ * libpolkit_module_set_func_can_session_access_resource:
+ * @module_interface: the module interface 
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void libpolkit_module_set_func_can_session_access_resource (PolKitModuleInterface                *module_interface,
+                                                            PolKitModuleCanSessionAccessResource  func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_can_session_access_resource = func;
+}
+
+/**
+ * libpolkit_module_set_func_can_caller_access_resource:
+ * @module_interface: the module interface 
+ * @func: the function pointer
+ * 
+ * Set the function pointer.
+ **/
+void libpolkit_module_set_func_can_caller_access_resource (PolKitModuleInterface               *module_interface,
+                                                           PolKitModuleCanCallerAccessResource  func)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->func_can_caller_access_resource = func;
+}
+
+/**
+ * libpolkit_module_get_func_initialize:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured 
+ **/
+PolKitModuleInitialize 
+libpolkit_module_get_func_initialize (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_initialize;
+}
+
+/**
+ * libpolkit_module_get_func_shutdown:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured 
+ **/
+PolKitModuleShutdown
+libpolkit_module_get_func_shutdown (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_shutdown;
+}
+
+/**
+ * libpolkit_module_get_func_get_seat_resource_association:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured 
+ **/
+PolKitModuleGetSeatResourceAssociation
+libpolkit_module_get_func_get_seat_resource_association (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_get_seat_resource_association;
+}
+
+/**
+ * libpolkit_module_get_func_is_resource_associated_with_seat:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured 
+ **/
+PolKitModuleIsResourceAssociatedWithSeat
+libpolkit_module_get_func_is_resource_associated_with_seat (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_is_resource_associated_with_seat;
+}
+
+/**
+ * libpolkit_module_get_func_can_session_access_resource:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured 
+ **/
+PolKitModuleCanSessionAccessResource
+libpolkit_module_get_func_can_session_access_resource (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_can_session_access_resource;
+}
+
+/**
+ * libpolkit_module_get_func_can_caller_access_resource:
+ * @module_interface: the module interface 
+ * 
+ * Get the function pointer.
+ * 
+ * Returns: Function pointer or #NULL if it's unavailable or an error occured
+ **/
+PolKitModuleCanCallerAccessResource
+libpolkit_module_get_func_can_caller_access_resource (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->func_can_caller_access_resource;
+}
+
+
+/**
+ * libpolkit_module_interface_get_control:
+ * @module_interface: the module interface
+ * 
+ * Get the control for this module.
+ * 
+ * Returns: A #PolKitModuleControl value.
+ **/
+PolKitModuleControl 
+libpolkit_module_interface_get_control (PolKitModuleInterface *module_interface)
+{
+        /* hmm, should we have UNKNOWN? */
+        g_return_val_if_fail (module_interface != NULL, LIBPOLKIT_MODULE_CONTROL_MANDATORY);
+        return module_interface->module_control;
+}
+
+static const struct {
+        PolKitModuleControl module_control;
+        const char *str;
+} mapping[] = 
+{
+        {LIBPOLKIT_MODULE_CONTROL_ADVISE, "advise"},
+        {LIBPOLKIT_MODULE_CONTROL_MANDATORY, "mandatory"},
+        {0, NULL}
+};
+
+/**
+ * libpolkit_module_control_to_string_representation:
+ * @module_control: the given value
+ * 
+ * Gives a textual representation of a #PolKitModuleControl object.
+ * 
+ * Returns: The textual representation or #NULL if the value passed is invalid
+ **/
+const char *
+libpolkit_module_control_to_string_representation (PolKitModuleControl module_control)
+{
+        if (module_control < 0 || module_control >= LIBPOLKIT_MODULE_CONTROL_N_CONTROLS) {
+                g_warning ("The passed module control identifier, %d, is not valid", module_control);
+                return NULL;
+        }
+
+        return mapping[module_control].str;
+}
+
+/**
+ * libpolkit_module_control_from_string_representation:
+ * @string: the textual representation
+ * @out_module_control: return location for the value
+ * 
+ * Given a textual representation of a #PolKitModuleControl object, find the #PolKitModuleControl value.
+ * 
+ * Returns: TRUE if the textual representation was valid, otherwise FALSE
+ **/
+gboolean
+libpolkit_module_control_from_string_representation (const char *string, PolKitModuleControl *out_module_control)
+{
+        int n;
+
+        g_return_val_if_fail (out_module_control != NULL, FALSE);
+
+        for (n = 0; n < LIBPOLKIT_MODULE_CONTROL_N_CONTROLS; n++) {
+                if (mapping[n].str == NULL)
+                        break;
+                if (g_ascii_strcasecmp (mapping[n].str, string) == 0) {
+                        *out_module_control = mapping[n].module_control;
+                        goto found;
+                }
+        }
+
+        return FALSE;
+found:
+        return TRUE;
+}
+
+
+/**
+ * libpolkit_module_set_user_data:
+ * @module_interface: module interface
+ * @user_data: user data to set
+ * 
+ * Set user data. A PolicyKit module should use these instead of
+ * global variables as multiple instances of the module may be
+ * instantiated at the same time.
+ **/
+void
+libpolkit_module_set_user_data (PolKitModuleInterface *module_interface, gpointer user_data)
+{
+        g_return_if_fail (module_interface != NULL);
+        module_interface->module_user_data = user_data;
+}
+
+/**
+ * libpolkit_module_get_user_data:
+ * @module_interface: module interface
+ * 
+ * Get user data.
+ * 
+ * Returns: The user data set with libpolkit_module_set_user_data()
+ **/
+gpointer
+libpolkit_module_get_user_data   (PolKitModuleInterface *module_interface)
+{
+        g_return_val_if_fail (module_interface != NULL, NULL);
+        return module_interface->module_user_data;
+}
+
diff --git a/libpolkit/libpolkit-module.h b/libpolkit/libpolkit-module.h
new file mode 100644
index 0000000..9f325e3
--- /dev/null
+++ b/libpolkit/libpolkit-module.h
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-module.h : PolicyKit loadable module interface
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef LIBPOLKIT_MODULE_H
+#define LIBPOLKIT_MODULE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+
+#include <libpolkit/libpolkit.h>
+
+struct PolKitModuleInterface;
+typedef struct PolKitModuleInterface PolKitModuleInterface;
+
+/**
+ * PolKitModuleInitialize:
+ * @module_interface: the module interface
+ * @argc: number of arguments to pass to module
+ * @argv: arguments passed to module; the first argument is the filename/path to the module
+ *
+ * Type of PolicyKit module function to initialize the module.
+ *
+ * Returns: Whether the module was initialized.
+ **/
+typedef gboolean (*PolKitModuleInitialize) (PolKitModuleInterface *module_interface, 
+                                            int                    argc, 
+                                            char                  *argv[]);
+
+/**
+ * PolKitModuleShutdown:
+ * @module_interface: the module interface
+ *
+ * Type of PolicyKit module function to shutdown the module.
+ **/
+typedef void (*PolKitModuleShutdown) (PolKitModuleInterface *module_interface);
+
+/**
+ * PolKitModuleGetSeatResourceAssociation:
+ * @module_interface: the module interface
+ * @pk_context: the PolicyKit context
+ * @visitor: visitor function
+ * @user_data: user data
+ *
+ * Type of PolicyKit module function to implement libpolkit_get_seat_resource_association().
+ *
+ * Returns: the #PolKitResult
+ **/
+typedef PolKitResult (*PolKitModuleGetSeatResourceAssociation) (PolKitModuleInterface *module_interface,
+                                                                PolKitContext         *pk_context,
+                                                                PolKitSeatVisitorCB    visitor,
+                                                                gpointer              *user_data);
+
+/**
+ * PolKitModuleIsResourceAssociatedWithSeat:
+ * @module_interface: the module interface
+ * @pk_context: the PolicyKit context
+ * @resource: the resource in question
+ * @seat: the seat
+ *
+ * Type of PolicyKit module function to implement libpolkit_is_resource_associated_with_seat().
+ *
+ * Returns: the #PolKitResult
+ **/
+typedef PolKitResult (*PolKitModuleIsResourceAssociatedWithSeat) (PolKitModuleInterface *module_interface,
+                                                                  PolKitContext         *pk_context,
+                                                                  PolKitResource        *resource,
+                                                                  PolKitSeat            *seat);
+
+/**
+ * PolKitModuleCanSessionAccessResource:
+ * @module_interface: the module interface
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @session: the session in question
+ *
+ * Type of PolicyKit module function to implement libpolkit_can_session_access_resource().
+ *
+ * Returns: the #PolKitResult
+ **/
+typedef PolKitResult (*PolKitModuleCanSessionAccessResource) (PolKitModuleInterface *module_interface,
+                                                              PolKitContext         *pk_context,
+                                                              PolKitPrivilege       *privilege,
+                                                              PolKitResource        *resource,
+                                                              PolKitSession         *session);
+
+/**
+ * PolKitModuleCanCallerAccessResource:
+ * @module_interface: the module interface
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @caller: the resource in question
+ *
+ * Type of PolicyKit module function to implement libpolkit_can_caller_access_resource().
+ *
+ * Returns: the #PolKitResult
+ **/
+typedef PolKitResult (*PolKitModuleCanCallerAccessResource) (PolKitModuleInterface *module_interface,
+                                                             PolKitContext         *pk_context,
+                                                             PolKitPrivilege       *privilege,
+                                                             PolKitResource        *resource,
+                                                             PolKitCaller          *caller);
+
+PolKitModuleInterface *libpolkit_module_interface_new   (void);
+PolKitModuleInterface *libpolkit_module_interface_ref   (PolKitModuleInterface *module_interface);
+void                   libpolkit_module_interface_unref (PolKitModuleInterface *module_interface);
+const char            *libpolkit_module_get_name        (PolKitModuleInterface *module_interface);
+
+void                   libpolkit_module_set_user_data   (PolKitModuleInterface *module_interface, gpointer user_data);
+gpointer               libpolkit_module_get_user_data   (PolKitModuleInterface *module_interface);
+
+void libpolkit_module_set_func_initialize                       (PolKitModuleInterface               *module_interface, 
+                                                                 PolKitModuleInitialize               func);
+void libpolkit_module_set_func_shutdown                         (PolKitModuleInterface               *module_interface, 
+                                                                 PolKitModuleShutdown                 func);
+void libpolkit_module_set_func_get_seat_resource_association    (PolKitModuleInterface               *module_interface,
+                                                                 PolKitModuleGetSeatResourceAssociation func);
+void libpolkit_module_set_func_is_resource_associated_with_seat (PolKitModuleInterface               *module_interface,
+                                                                 PolKitModuleIsResourceAssociatedWithSeat func);
+void libpolkit_module_set_func_can_session_access_resource      (PolKitModuleInterface               *module_interface,
+                                                                 PolKitModuleCanSessionAccessResource func);
+void libpolkit_module_set_func_can_caller_access_resource       (PolKitModuleInterface               *module_interface,
+                                                                 PolKitModuleCanCallerAccessResource  func);
+
+PolKitModuleInitialize libpolkit_module_get_func_initialize (PolKitModuleInterface *module_interface);
+PolKitModuleShutdown libpolkit_module_get_func_shutdown (PolKitModuleInterface *module_interface);
+PolKitModuleGetSeatResourceAssociation libpolkit_module_get_func_get_seat_resource_association (PolKitModuleInterface *module_interface);
+PolKitModuleIsResourceAssociatedWithSeat libpolkit_module_get_func_is_resource_associated_with_seat (PolKitModuleInterface *module_interface);
+PolKitModuleCanSessionAccessResource libpolkit_module_get_func_can_session_access_resource (PolKitModuleInterface *module_interface);
+PolKitModuleCanCallerAccessResource libpolkit_module_get_func_can_caller_access_resource (PolKitModuleInterface *module_interface);
+
+/**
+ * PolKitModuleControl:
+ * @LIBPOLKIT_MODULE_CONTROL_ADVISE: Allow modules, marked with #LIBPOLKIT_MODULE_CONTROL_MANDATORY, down the
+ * stack to override results from this module. Modules down the stack that are also marked with 
+ * the #LIBPOLKIT_MODULE_CONTROL_ADVISE control will only take effect it they change the result to be "less strict".
+ * @LIBPOLKIT_MODULE_CONTROL_MANDATORY: Always use results (unless it returns 
+ * #LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE for a given request) from this module, even if it changes whether the
+ * result to be "more strict". . If a later module also uses this control, results from that module will override it.
+ * @LIBPOLKIT_MODULE_CONTROL_N_CONTROLS: Number of control stanzas
+ *
+ * The control stanza for a PolicyKit module. This is read from the
+ * PolicyKit configuration file (/etc/PolicyKit/PolicyKit.conf) that
+ * defines the stacked order of the modules and is chosen by the
+ * system administrator. See the definition of #PolKitResult for
+ * the definition of "strict" with respect to result values.
+ **/
+typedef enum
+{
+        LIBPOLKIT_MODULE_CONTROL_ADVISE,
+        LIBPOLKIT_MODULE_CONTROL_MANDATORY,
+        LIBPOLKIT_MODULE_CONTROL_N_CONTROLS
+} PolKitModuleControl;
+
+const char *
+libpolkit_module_control_to_string_representation (PolKitModuleControl module_control);
+
+gboolean
+libpolkit_module_control_from_string_representation (const char *string, PolKitModuleControl *out_module_control);
+
+PolKitModuleInterface *libpolkit_module_interface_load_module (const char *name, 
+                                                               PolKitModuleControl module_control, 
+                                                               int argc, char *argv[]);
+
+PolKitModuleControl libpolkit_module_interface_get_control (PolKitModuleInterface *module_interface);
+
+#endif /* LIBPOLKIT_MODULE_H */
diff --git a/libpolkit/libpolkit-result.c b/libpolkit/libpolkit-result.c
index 8d23dd5..f19b710 100644
--- a/libpolkit/libpolkit-result.c
+++ b/libpolkit/libpolkit-result.c
@@ -54,7 +54,6 @@ static const struct {
 {
         {LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE, "unknown"},
         {LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW, "not_authorized"},
-        {LIBPOLKIT_RESULT_YES, "yes"},
         {LIBPOLKIT_RESULT_NO, "no"},
         {LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH, "auth_root"},
         {LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION, "auth_root_keep_session"},
@@ -62,6 +61,7 @@ static const struct {
         {LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH, "auth_self"},
         {LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION, "auth_self_keep_session"},
         {LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS, "auth_self_keep_always"},
+        {LIBPOLKIT_RESULT_YES, "yes"},
         {0, NULL}
 };
 
@@ -111,8 +111,6 @@ libpolkit_result_from_string_representat
         }
 
         return FALSE;
-
 found:
         return TRUE;
-
 }
diff --git a/libpolkit/libpolkit-result.h b/libpolkit/libpolkit-result.h
index 7d9ea6f..6573f59 100644
--- a/libpolkit/libpolkit-result.h
+++ b/libpolkit/libpolkit-result.h
@@ -32,7 +32,6 @@
  * PolKitResult:
  * @LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE: The passed privilege is unknown.
  * @LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW: The caller of libpolkit is not sufficiently privilege to know the answer.
- * @LIBPOLKIT_RESULT_YES: Access granted.
  * @LIBPOLKIT_RESULT_NO: Access denied.
  * @LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH: Access denied, but authentication of the caller as 
  * root will grant access to only that caller.
@@ -46,15 +45,18 @@
  * his user will grant access for the remainder of the session the caller stems from.
  * @LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS: Access denied, but authentication of the caller as
  * his user will grant access to the user of the caller in the future.
+ * @LIBPOLKIT_RESULT_YES: Access granted.
  * @LIBPOLKIT_RESULT_N_RESULTS: Number of result codes
  *
- * Result codes from queries to PolicyKit.
+ * Result codes from queries to PolicyKit. These are ordered and we
+ * say that a result A is "more strict" than a result B, if A has a
+ * lower numerical value. (e.g. #LIBPOLKIT_RESULT_NO is more strict
+ * than #LIBPOLKIT_RESULT_YES).
  */
 typedef enum
 {
         LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE,
         LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
-        LIBPOLKIT_RESULT_YES,
         LIBPOLKIT_RESULT_NO,
         LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH,
         LIBPOLKIT_RESULT_ONLY_VIA_ROOT_AUTH_KEEP_SESSION,
@@ -62,6 +64,7 @@ typedef enum
         LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH,
         LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION,
         LIBPOLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS,
+        LIBPOLKIT_RESULT_YES,
         LIBPOLKIT_RESULT_N_RESULTS
 } PolKitResult;
 
diff --git a/libpolkit/libpolkit.c b/libpolkit/libpolkit.c
deleted file mode 100644
index 651e54c..0000000
--- a/libpolkit/libpolkit.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
-/***************************************************************************
- *
- * libpolkit.c : library for querying system-wide policy
- *
- * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-/**
- * SECTION:libpolkit
- * @short_description: Policy functions.
- *
- * These functions are used to query system policy.
- **/
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <glib.h>
-#include "libpolkit.h"
-#include "libpolkit-debug.h"
-
-/**
- * libpolkit_get_seat_resource_association:
- * @pk_context: the PolicyKit context
- * @visitor: visitor function
- * @user_data: user data
- *
- * Retrieve information about what resources are associated to what
- * seats. Note that a resource may be associated to more than one
- * seat. This information stems from user configuration and consumers
- * of this information that know better (e.g. HAL) may choose to
- * override it. 
- *
- * Typically, this information is used to e.g. bootstrap the system
- * insofar that it can be used to start login greeters on the given
- * video hardware (e.g. resources) on the given user-configured seats.
- *
- * If a resource is not associated with any seat, it is assumed to be
- * available to any local seat.
- *
- * Returns: A #PolKitResult - can only be one of
- * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW or
- * #LIBPOLKIT_RESULT_YES (if the callback was invoked)
- */
-PolKitResult
-libpolkit_get_seat_resource_association (PolKitContext       *pk_context,
-                                         PolKitSeatVisitorCB  visitor,
-                                         gpointer            *user_data)
-{
-        return LIBPOLKIT_RESULT_YES;
-}
-
-/**
- * libpolkit_is_resource_associated_with_seat:
- * @pk_context: the PolicyKit context
- * @resource: the resource in question
- * @seat: the seat
- *
- * Determine if a given resource is associated with a given seat. The
- * same comments noted in libpolkit_get_seat_resource_association() about the
- * source purely being user configuration applies here as well.
- *
- * Returns: A #PolKitResult - can only be one of
- * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
- * #LIBPOLKIT_RESULT_YES, #LIBPOLKIT_RESULT_NO.
- */
-PolKitResult
-libpolkit_is_resource_associated_with_seat (PolKitContext   *pk_context,
-                                            PolKitResource  *resource,
-                                            PolKitSeat      *seat)
-{
-        return LIBPOLKIT_RESULT_NO;
-}
-
-/**
- * libpolkit_can_session_access_resource:
- * @pk_context: the PolicyKit context
- * @privilege: the type of access to check for
- * @resource: the resource in question
- * @session: the session in question
- *
- * Determine if a given session can access a given resource in a given way.
- *
- * Returns: A #PolKitResult - can only be one of
- * #LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
- * #LIBPOLKIT_RESULT_YES, #LIBPOLKIT_RESULT_NO.
- */
-PolKitResult
-libpolkit_can_session_access_resource (PolKitContext   *pk_context,
-                                       PolKitPrivilege *privilege,
-                                       PolKitResource  *resource,
-                                       PolKitSession   *session)
-{
-        PolKitPrivilegeCache *cache;
-        PolKitResult result;
-        PolKitPrivilegeFileEntry *pfe;
-
-        result = LIBPOLKIT_RESULT_NO;
-
-        cache = libpolkit_context_get_privilege_cache (pk_context);
-        if (cache == NULL)
-                goto out;
-
-        _pk_debug ("entering libpolkit_can_session_access_resource()");
-        libpolkit_privilege_debug (privilege);
-        libpolkit_resource_debug (resource);
-        libpolkit_session_debug (session);
-
-        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
-        if (pfe == NULL) {
-                char *privilege_name;
-                if (!libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
-                        g_warning ("given privilege has no name");
-                } else {
-                        g_warning ("no privilege with name '%s'", privilege_name);
-                }
-                result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
-                goto out;
-        }
-
-        libpolkit_privilege_file_entry_debug (pfe);
-        
-        /* for now, hardcode to defaults */
-        result = libpolkit_privilege_default_can_session_access_resource (
-                libpolkit_privilege_file_entry_get_default (pfe), 
-                privilege, 
-                resource, 
-                session);
-out:
-        _pk_debug ("... result was %s", libpolkit_result_to_string_representation (result));
-        return result;
-}
-
-/**
- * libpolkit_can_caller_access_resource:
- * @pk_context: the PolicyKit context
- * @privilege: the type of access to check for
- * @resource: the resource in question
- * @caller: the resource in question
- *
- * Determine if a given caller can access a given resource in a given way.
- *
- * Returns: A #PolKitResult specifying if, and how, the caller can
- * access the resource in the given way
- */
-PolKitResult
-libpolkit_can_caller_access_resource (PolKitContext   *pk_context,
-                                      PolKitPrivilege *privilege,
-                                      PolKitResource  *resource,
-                                      PolKitCaller    *caller)
-{
-        PolKitPrivilegeCache *cache;
-        PolKitResult result;
-        PolKitPrivilegeFileEntry *pfe;
-
-        result = LIBPOLKIT_RESULT_NO;
-
-        cache = libpolkit_context_get_privilege_cache (pk_context);
-        if (cache == NULL)
-                goto out;
-
-        _pk_debug ("entering libpolkit_can_caller_access_resource()");
-        libpolkit_privilege_debug (privilege);
-        libpolkit_resource_debug (resource);
-        libpolkit_caller_debug (caller);
-
-        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
-        if (pfe == NULL) {
-                char *privilege_name;
-                if (!libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
-                        g_warning ("given privilege has no name");
-                } else {
-                        g_warning ("no privilege with name '%s'", privilege_name);
-                }
-                result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
-                goto out;
-        }
-
-        libpolkit_privilege_file_entry_debug (pfe);
-
-        /* for now, hardcode to defaults */
-        result = libpolkit_privilege_default_can_caller_access_resource (
-                libpolkit_privilege_file_entry_get_default (pfe), 
-                privilege, 
-                resource, 
-                caller);
-
-out:
-        _pk_debug ("... result was %s", libpolkit_result_to_string_representation (result));
-        return result;
-}
diff --git a/libpolkit/libpolkit.h b/libpolkit/libpolkit.h
index 1fed4f1..4088a8e 100644
--- a/libpolkit/libpolkit.h
+++ b/libpolkit/libpolkit.h
@@ -26,53 +26,7 @@
 #ifndef LIBPOLKIT_H
 #define LIBPOLKIT_H
 
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <glib.h>
-
-#include <libpolkit/libpolkit-error.h>
-#include <libpolkit/libpolkit-result.h>
 #include <libpolkit/libpolkit-context.h>
-#include <libpolkit/libpolkit-privilege.h>
-#include <libpolkit/libpolkit-resource.h>
-#include <libpolkit/libpolkit-seat.h>
-#include <libpolkit/libpolkit-session.h>
-#include <libpolkit/libpolkit-caller.h>
-
-/**
- * PolKitSeatVisitorCB:
- * @seat: the seat
- * @resources_associated_with_seat: A NULL terminated array of resources associated with the seat
- * @user_data: user data
- *
- * Visitor function for libpolkit_get_seat_resource_association(). The caller should _not_ unref the passed objects.
- */
-typedef void (*PolKitSeatVisitorCB) (PolKitSeat      *seat,
-                                     PolKitResource **resources_associated_with_seat,
-                                     gpointer         user_data);
-
-PolKitResult
-libpolkit_get_seat_resource_association (PolKitContext       *pk_context,
-                                         PolKitSeatVisitorCB  visitor,
-                                         gpointer            *user_data);
-
-PolKitResult
-libpolkit_is_resource_associated_with_seat (PolKitContext   *pk_context,
-                                            PolKitResource  *resource,
-                                            PolKitSeat      *seat);
-
-PolKitResult
-libpolkit_can_session_access_resource (PolKitContext   *pk_context,
-                                       PolKitPrivilege *privilege,
-                                       PolKitResource  *resource,
-                                       PolKitSession   *session);
-
-PolKitResult
-libpolkit_can_caller_access_resource (PolKitContext   *pk_context,
-                                      PolKitPrivilege *privilege,
-                                      PolKitResource  *resource,
-                                      PolKitCaller    *caller);
 
 #endif /* LIBPOLKIT_H */
 
diff --git a/modules/Makefile.am b/modules/Makefile.am
new file mode 100644
index 0000000..c2d8d54
--- /dev/null
+++ b/modules/Makefile.am
@@ -0,0 +1,5 @@
+
+SUBDIRS = default allow-all deny-all
+
+polkitconfdir = $(sysconfdir)/PolicyKit
+polkitconf_DATA = PolicyKit.conf
diff --git a/modules/PolicyKit.conf b/modules/PolicyKit.conf
new file mode 100644
index 0000000..ee8120b
--- /dev/null
+++ b/modules/PolicyKit.conf
@@ -0,0 +1,5 @@
+# PolicyKit modules - see PolicyKit(8)
+#
+# NOTE: Changes made to this file may be applied instantly
+
+advise          polkit-module-default.so
diff --git a/modules/allow-all/Makefile.am b/modules/allow-all/Makefile.am
new file mode 100644
index 0000000..8a09890
--- /dev/null
+++ b/modules/allow-all/Makefile.am
@@ -0,0 +1,25 @@
+## 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_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+polkitmoduledir = $(libdir)/PolicyKit/modules
+polkitmodule_LTLIBRARIES = 				\
+	polkit-module-allow-all.la		\
+	$(NULL)
+
+
+polkit_module_allow_all_la_SOURCES = polkit-module-allow-all.c
+polkit_module_allow_all_la_LDFLAGS = -no-undefined -module -avoid-version
+polkit_module_allow_all_la_LIBADD = $(top_builddir)/libpolkit/libpolkit.la @GLIB_LIBS@
+
+clean-local :
+	rm -f *~
diff --git a/modules/allow-all/polkit-module-allow-all.c b/modules/allow-all/polkit-module-allow-all.c
new file mode 100644
index 0000000..82701c2
--- /dev/null
+++ b/modules/allow-all/polkit-module-allow-all.c
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-module-allow-all.c : PolicyKit module that says YES to everything
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <regex.h>
+
+#include <libpolkit/libpolkit-module.h>
+
+/* The symbol that libpolkit looks up when loading this module */
+gboolean libpolkit_module_set_functions (PolKitModuleInterface *module_interface);
+
+typedef struct {
+        regex_t preg;
+        uid_t uid;
+        gboolean have_regex;
+        gboolean have_uid;
+} UserData;
+
+static uid_t
+_util_name_to_uid (const char *username, gid_t *default_gid)
+{
+        int rc;
+        uid_t res;
+        char *buf = NULL;
+        unsigned int bufsize;
+        struct passwd pwd;
+        struct passwd *pwdp;
+
+        res = (uid_t) -1;
+
+        bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
+        buf = g_new0 (char, bufsize);
+                
+        rc = getpwnam_r (username, &pwd, buf, bufsize, &pwdp);
+        if (rc != 0 || pwdp == NULL) {
+                /*g_warning ("getpwnam_r() returned %d", rc);*/
+                goto out;
+        }
+
+        res = pwdp->pw_uid;
+        if (default_gid != NULL)
+                *default_gid = pwdp->pw_gid;
+
+out:
+        g_free (buf);
+        return res;
+}
+
+static gboolean
+_module_init (PolKitModuleInterface *module_interface, int argc, char *argv[])
+{
+        int n;
+        UserData *user_data;
+
+        user_data = g_new0 (UserData, 1);
+        for (n = 1; n < argc; n++) {
+                if (g_str_has_prefix (argv[n], "privilege=")) {
+                        const char *regex;
+                        regex = argv[n] + 10;
+                        if (regcomp (&(user_data->preg), regex, REG_EXTENDED) != 0) {
+                                printf ("Regex '%s' didn't compile\n", regex);
+                                goto error;
+                        }
+                        user_data->have_regex = TRUE;
+                } else if (g_str_has_prefix (argv[n], "user=")) {
+                        const char *user;
+                        user = argv[n] + 5;
+                        user_data->uid = _util_name_to_uid (user, NULL);
+                        if ((int) user_data->uid == -1)
+                                goto error;
+                        user_data->have_uid = TRUE;
+                }
+        }
+
+        libpolkit_module_set_user_data (module_interface, user_data);
+
+        return TRUE;
+error:
+        g_free (user_data);
+        return FALSE;
+}
+
+static void
+_module_shutdown (PolKitModuleInterface *module_interface)
+{
+        UserData *user_data;
+        user_data = libpolkit_module_get_user_data (module_interface);
+        g_free (user_data);
+}
+
+static PolKitResult
+_module_can_session_access_resource (PolKitModuleInterface *module_interface,
+                                     PolKitContext         *pk_context,
+                                     PolKitPrivilege       *privilege,
+                                     PolKitResource        *resource,
+                                     PolKitSession         *session)
+{
+        UserData *user_data;
+        PolKitResult result;
+        gboolean user_check_ok;
+        gboolean regex_check_ok;
+
+        user_check_ok = FALSE;
+        regex_check_ok = FALSE;
+
+        user_data = libpolkit_module_get_user_data (module_interface);
+
+        if (user_data->have_regex) {
+                char *privilege_name;
+                if (libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
+                        if (regexec (&user_data->preg, privilege_name, 0, NULL, 0) == 0) {
+                                regex_check_ok = TRUE;
+                        }
+                }
+        } else {
+                regex_check_ok = TRUE;
+        }
+
+        if (user_data->have_uid) {
+                if (session != NULL) {
+                        uid_t session_uid;
+                        if (libpolkit_session_get_uid (session, &session_uid) && session_uid == user_data->uid) {
+                                user_check_ok = TRUE;
+                        }
+                }
+        } else {
+                user_check_ok = TRUE;
+        }
+
+        if (user_check_ok && regex_check_ok) {
+#ifdef IS_POLKIT_MODULE_DENY_ALL
+                result = LIBPOLKIT_RESULT_NO;
+#else
+                result = LIBPOLKIT_RESULT_YES;
+#endif
+        } else {
+                result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+        }
+        return result;
+}
+
+static PolKitResult
+_module_can_caller_access_resource (PolKitModuleInterface *module_interface,
+                                    PolKitContext         *pk_context,
+                                    PolKitPrivilege       *privilege,
+                                    PolKitResource        *resource,
+                                    PolKitCaller          *caller)
+{
+        UserData *user_data;
+        PolKitResult result;
+        gboolean user_check_ok;
+        gboolean regex_check_ok;
+
+        user_check_ok = FALSE;
+        regex_check_ok = FALSE;
+
+        user_data = libpolkit_module_get_user_data (module_interface);
+
+        if (user_data->have_regex) {
+                char *privilege_name;
+                if (libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
+                        if (regexec (&user_data->preg, privilege_name, 0, NULL, 0) == 0) {
+                                regex_check_ok = TRUE;
+                        }
+                }
+        } else {
+                regex_check_ok = TRUE;
+        }
+
+        if (user_data->have_uid) {
+                uid_t caller_uid;
+                if (libpolkit_caller_get_uid (caller, &caller_uid) && caller_uid == user_data->uid) {
+                        user_check_ok = TRUE;
+                }
+        } else {
+                user_check_ok = TRUE;
+        }
+
+        if (user_check_ok && regex_check_ok) {
+#ifdef IS_POLKIT_MODULE_DENY_ALL
+                result = LIBPOLKIT_RESULT_NO;
+#else
+                result = LIBPOLKIT_RESULT_YES;
+#endif
+        } else {
+                result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+        }
+        return result;
+}
+
+gboolean
+libpolkit_module_set_functions (PolKitModuleInterface *module_interface)
+{
+        gboolean ret;
+
+        ret = FALSE;
+        if (module_interface == NULL)
+                goto out;
+
+        libpolkit_module_set_func_initialize (module_interface, _module_init);
+        libpolkit_module_set_func_shutdown (module_interface, _module_shutdown);
+        libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource);
+        libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource);
+
+        ret = TRUE;
+out:
+        return ret;
+}
diff --git a/modules/default/Makefile.am b/modules/default/Makefile.am
new file mode 100644
index 0000000..6167cc4
--- /dev/null
+++ b/modules/default/Makefile.am
@@ -0,0 +1,25 @@
+## 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_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+polkitmoduledir = $(libdir)/PolicyKit/modules
+polkitmodule_LTLIBRARIES = 				\
+	polkit-module-default.la			\
+	$(NULL)
+
+
+polkit_module_default_la_SOURCES = polkit-module-default.c
+polkit_module_default_la_LDFLAGS = -no-undefined -module -avoid-version
+polkit_module_default_la_LIBADD = $(top_builddir)/libpolkit/libpolkit.la @GLIB_LIBS@
+
+clean-local :
+	rm -f *~
diff --git a/modules/default/polkit-module-default.c b/modules/default/polkit-module-default.c
new file mode 100644
index 0000000..83f1e31
--- /dev/null
+++ b/modules/default/polkit-module-default.c
@@ -0,0 +1,116 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-module-default.c : PolicyKit module for default policy
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <libpolkit/libpolkit-module.h>
+
+/* The symbol that libpolkit looks up when loading this module */
+gboolean libpolkit_module_set_functions (PolKitModuleInterface *module_interface);
+
+static gboolean
+_module_init (PolKitModuleInterface *module_interface, 
+              int argc, 
+              char *argv[])
+{
+        return TRUE;
+}
+
+static void
+_module_shutdown (PolKitModuleInterface *module_interface)
+{
+}
+
+static PolKitResult
+_module_can_session_access_resource (PolKitModuleInterface *module_interface,
+                                     PolKitContext         *pk_context,
+                                     PolKitPrivilege       *privilege,
+                                     PolKitResource        *resource,
+                                     PolKitSession         *session)
+{
+        PolKitResult result;
+        PolKitPrivilegeCache *cache;
+        PolKitPrivilegeFileEntry *pfe;
+
+        result = LIBPOLKIT_RESULT_NO;
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
+        return libpolkit_privilege_default_can_session_access_resource (
+                libpolkit_privilege_file_entry_get_default (pfe), 
+                privilege, 
+                resource, 
+                session);
+}
+
+static PolKitResult
+_module_can_caller_access_resource (PolKitModuleInterface *module_interface,
+                                    PolKitContext         *pk_context,
+                                    PolKitPrivilege       *privilege,
+                                    PolKitResource        *resource,
+                                    PolKitCaller          *caller)
+{
+        PolKitResult result;
+        PolKitPrivilegeCache *cache;
+        PolKitPrivilegeFileEntry *pfe;
+
+        result = LIBPOLKIT_RESULT_NO;
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        pfe = libpolkit_privilege_cache_get_entry (cache, privilege);
+        return libpolkit_privilege_default_can_caller_access_resource (
+                libpolkit_privilege_file_entry_get_default (pfe), 
+                privilege, 
+                resource, 
+                caller);
+}
+
+gboolean
+libpolkit_module_set_functions (PolKitModuleInterface *module_interface)
+{
+        gboolean ret;
+
+        ret = FALSE;
+        if (module_interface == NULL)
+                goto out;
+
+        libpolkit_module_set_func_initialize (module_interface, _module_init);
+        libpolkit_module_set_func_shutdown (module_interface, _module_shutdown);
+        libpolkit_module_set_func_can_session_access_resource (module_interface, _module_can_session_access_resource);
+        libpolkit_module_set_func_can_caller_access_resource (module_interface, _module_can_caller_access_resource);
+
+        ret = TRUE;
+out:
+        return ret;
+}
diff --git a/modules/deny-all/Makefile.am b/modules/deny-all/Makefile.am
new file mode 100644
index 0000000..db5a282
--- /dev/null
+++ b/modules/deny-all/Makefile.am
@@ -0,0 +1,25 @@
+## 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_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
+	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@ -DIS_POLKIT_MODULE_DENY_ALL
+
+polkitmoduledir = $(libdir)/PolicyKit/modules
+polkitmodule_LTLIBRARIES = 				\
+	polkit-module-deny-all.la		\
+	$(NULL)
+
+
+polkit_module_deny_all_la_SOURCES = ../allow-all/polkit-module-allow-all.c
+polkit_module_deny_all_la_LDFLAGS = -no-undefined -module -avoid-version
+polkit_module_deny_all_la_LIBADD = $(top_builddir)/libpolkit/libpolkit.la @GLIB_LIBS@
+
+clean-local :
+	rm -f *~
diff --git a/tools/polkit-check-caller.c b/tools/polkit-check-caller.c
index d1f53aa..1c3b2ca 100644
--- a/tools/polkit-check-caller.c
+++ b/tools/polkit-check-caller.c
@@ -170,7 +170,7 @@ main (int argc, char *argv[])
                 }
         }
 
-        allowed = libpolkit_can_caller_access_resource (pol_ctx, privilege, resource, caller);
+        allowed = libpolkit_context_can_caller_access_resource (pol_ctx, privilege, resource, caller);
 
         if (allowed)
                 return 0;
diff --git a/tools/polkit-check-session.c b/tools/polkit-check-session.c
index d6ee164..7ed3a2f 100644
--- a/tools/polkit-check-session.c
+++ b/tools/polkit-check-session.c
@@ -178,7 +178,7 @@ main (int argc, char *argv[])
         libpolkit_resource_set_resource_type (resource, resource_type);
         libpolkit_resource_set_resource_id (resource, resource_id);
 
-        allowed = libpolkit_can_session_access_resource (pol_ctx, privilege, resource, session);
+        allowed = libpolkit_context_can_session_access_resource (pol_ctx, privilege, resource, session);
 
         if (allowed)
                 return 0;


More information about the hal-commit mailing list