PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Sun Apr 8 13:49:44 PDT 2007


 configure.in                                    |    1 
 doc/man/Makefile.am                             |    2 
 doc/man/polkit-module-allow-all.8.in            |   22 -
 doc/man/polkit-module-builtins.8.in             |   55 +++
 doc/man/polkit-module-deny-all.8.in             |   24 -
 doc/man/polkit-module-run-program.8.in          |  198 +++++++++++++
 libpolkit/libpolkit-context.c                   |   53 ++-
 libpolkit/libpolkit-module.c                    |  256 +++++++++++++++++
 libpolkit/libpolkit-module.h                    |   15 +
 modules/Makefile.am                             |    2 
 modules/allow-all/polkit-module-allow-all.c     |  153 ----------
 modules/deny-all/Makefile.am                    |    4 
 modules/deny-all/polkit-module-deny-all.c       |   92 ++++++
 modules/run-program/Makefile.am                 |   25 +
 modules/run-program/polkit-module-run-program.c |  359 ++++++++++++++++++++++++
 15 files changed, 1063 insertions(+), 198 deletions(-)

New commits:
diff-tree e2a465d0f9a16b501754b03267d743ac20135973 (from 0973db30eaab0e12d48b1e1f8386960fb32e2343)
Author: David Zeuthen <davidz at redhat.com>
Date:   Sun Apr 8 16:49:27 2007 -0400

    add built-in options and a new module pam-polkit-run-program.so

diff --git a/configure.in b/configure.in
index 25fc9af..97d0aa0 100644
--- a/configure.in
+++ b/configure.in
@@ -178,6 +178,7 @@ modules/Makefile
 modules/default/Makefile
 modules/allow-all/Makefile
 modules/deny-all/Makefile
+modules/run-program/Makefile
 ])
 
 dnl ==========================================================================
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 93de521..7e9464c 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 PolicyKit.8.in polkit-module-default.8.in polkit-module-allow-all.8.in polkit-module-deny-all.8.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 polkit-module-run-program.8.in polkit-module-builtins.8.in
 
 man_MANS = $(MAN_IN_FILES:.in=)
 
diff --git a/doc/man/polkit-module-allow-all.8.in b/doc/man/polkit-module-allow-all.8.in
index decd097..17de422 100644
--- a/doc/man/polkit-module-allow-all.8.in
+++ b/doc/man/polkit-module-allow-all.8.in
@@ -7,7 +7,7 @@
 polkit-module-allow-all \- grant access to all privileges
 .SH SYNOPSIS
 .PP
-.B polkit-module-allow-all.so [privilege=<regexp>] [user=<username>]
+.B polkit-module-allow-all.so
 .SH DESCRIPTION
 .PP
 This PolicyKit module will allow access to any privilege regardless of
@@ -20,26 +20,14 @@ spec\fP which can be found in
 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
+This module does not require nor recognize any options.
 
 .SH NOTES
 .PP
 Never use this module unless you
 .B COMPLETELY
-trust anyone with either remote or local access to the system.
+trust anyone with either remote or local access to the system, or you
+have confined the module using built-in options.
 
 .SH BUGS
 .PP
@@ -51,8 +39,10 @@ on how to subscribe.
 .SH SEE ALSO
 .PP
 \&\fIPolicyKit\fR\|(8),
+\&\fIpolkit-module-builtins\fR\|(8),
 \&\fIpolkit-module-default\fR\|(8),
 \&\fIpolkit-module-deny-all\fR\|(8),
+\&\fIpolkit-module-run-program\fR\|(8),
 \&\fI at sysconfdir@/PolicyKit/privileges\fR\|,
 \&\fI at sysconfdir@/PolicyKit/PolicyKit.conf\fR\|
 
diff --git a/doc/man/polkit-module-builtins.8.in b/doc/man/polkit-module-builtins.8.in
new file mode 100644
index 0000000..333076b
--- /dev/null
+++ b/doc/man/polkit-module-builtins.8.in
@@ -0,0 +1,55 @@
+.\" 
+.\" polkit-module-builtins manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-MODULE-BUILTINS 8
+.SH NAME
+polkit-module-builtins \- options that apply to any PolicyKit module
+.SH SYNOPSIS
+.PP
+.B any-module.so [privilege=<regexp>] [user=<username> ...]
+.SH DESCRIPTION
+.PP
+This manual page describes options that can be used for any PolicyKit
+module to confine what requests it should deal with.
+
+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. This option can be used multiple times to specify
+multiple users. Example:
+.B user=davidz user=bateman
+
+.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-deny-all.8.in b/doc/man/polkit-module-deny-all.8.in
index feee066..f2648c5 100644
--- a/doc/man/polkit-module-deny-all.8.in
+++ b/doc/man/polkit-module-deny-all.8.in
@@ -7,7 +7,7 @@
 polkit-module-deny-all \- grant access to all privileges
 .SH SYNOPSIS
 .PP
-.B polkit-module-deny-all.so [privilege=<regexp>] [user=<username>]
+.B polkit-module-deny-all.so
 .SH DESCRIPTION
 .PP
 This PolicyKit module will deny access to any privilege regardless of
@@ -20,25 +20,13 @@ spec\fP which can be found in
 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
+This module does not require nor recognize any options.
 
 .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.
+Unless confined using built-in options, this module is only useful
+in situations where it's desirable to lock down the system so it's
+unusable by normal unprivileged users.
 
 .SH BUGS
 .PP
@@ -50,8 +38,10 @@ on how to subscribe.
 .SH SEE ALSO
 .PP
 \&\fIPolicyKit\fR\|(8),
+\&\fIpolkit-module-builtins\fR\|(8),
 \&\fIpolkit-module-default\fR\|(8),
 \&\fIpolkit-module-allow-all\fR\|(8),
+\&\fIpolkit-module-run-program\fR\|(8),
 \&\fI at sysconfdir@/PolicyKit/privileges\fR\|,
 \&\fI at sysconfdir@/PolicyKit/PolicyKit.conf\fR\|
 
diff --git a/doc/man/polkit-module-run-program.8.in b/doc/man/polkit-module-run-program.8.in
new file mode 100644
index 0000000..96f0868
--- /dev/null
+++ b/doc/man/polkit-module-run-program.8.in
@@ -0,0 +1,198 @@
+.\" 
+.\" polkit-module-run-program manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-MODULE-RUN-PROGRAM 8
+.SH NAME
+polkit-module-run-program \- determine policy by running a program
+.SH SYNOPSIS
+.PP
+.HP 31
+\fBpolkit-module-run-program.so\fR program=\fI<program>\fR
+.SH DESCRIPTION
+.PP
+This PolicyKit module will run a program every time a privilege is
+requested. 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 program=<program>
+Absolute path to program to run; this is a mandatory option. Examples:
+.B privilege=/usr/bin/my-program
+or
+.B privilege="/path/to/program --foo --bar"
+
+.SH DESCRIPTION
+This module will invoke the given program and will export a minimal
+environment with values identifying the request. The program
+.B SHOULD NOT
+have any side effects; it is only invoked to make a decision - not to
+alter state on the system. Further, the program is not guaranteed to
+run as 
+.B uid 0
+(e.g. root); it is effectively invoked by a mechanism (such as
+\fBhald\fR(7)) that may run as an unprivileged system user.
+
+.PP
+If the program fails to run or exits with a non-zero exit code, it
+means that the request is denied (same as returning
+.B no
+- see below). If the program exits with exit code 0,
+.I stdout
+of the program is examined to determine the result of the decision
+(these values map directly to the possible values in the
+.I PolKitResult
+enumeration):
+
+.I
+.TP
+.B unknown
+The passed privilege is unknown.
+.TP
+.B not_authorized
+The mechanism / caller (e.g. the program using
+.I libpolkit 
+that loads this module) is not sufficiently privileged to know the
+answer.
+.TP
+.B no
+Access denied.
+.TP
+.B auth_root
+Access denied, but authentication of the caller as root will grant
+access to only that caller.
+.TP
+.B auth_root_keep_session
+Access denied, but authentication of the caller as root will grant
+access for the remainder of the session the caller stems from.
+.TP
+.B auth_root_keep_always
+Access denied, but authentication of the caller as root will grant
+access to the user of the caller in the future.
+.TP
+.B auth_self
+Access denied, but authentication of the caller as himself will grant
+access to only that caller.
+.TP
+.B auth_self_keep_session
+Access denied, but authentication of the caller as himself will grant
+access for the remainder of the session the caller stems from.
+.TP
+.B auth_self_keep_always
+Access denied, but authentication of the caller as himself will grant
+access to the user of the caller in the future.
+.TP
+.B yes
+Access granted.
+
+.PP
+For a request concerning decisions for calls via the system message
+bus daemon, the environment will contain:
+
+.TP
+.B POLKIT_REQUEST_CALLER=1
+To identify the request to be concerning a decision about a caller on
+the system message bus.
+.TP
+.B POLKIT_PRIVILEGE_ID
+Privilege identifier
+.TP
+.B POLKIT_RESOURCE_ID
+Resource identifier
+.TP
+.B POLKIT_RESOURCE_TYPE
+Resource type
+.TP
+.B POLKIT_CALLER_UID
+UNIX user id of the caller
+.TP
+.B POLKIT_CALLER_DBUS_NAME
+Unique name of the caller on the system message bus
+.TP
+.B POLKIT_CALLER_PID
+UNIX process id of the caller
+.TP
+.B POLKIT_CALLER_SELINUX_CONTEXT
+SELinux security context of the caller (only set if SELinux is enabled)
+.TP
+.B POLKIT_SESSION_CK_IS_ACTIVE
+Whether ConsoleKit regards the session as active (only set if the caller belong to a session)
+.TP
+.B POLKIT_SESSION_CK_IS_LOCAL
+Whether ConsoleKit regards the session as local (only set if the caller belong to a session)
+.TP
+.B POLKIT_SESSION_CK_OBJREF
+ConsoleKit session D-Bus object reference (only set if the caller belong to a session)
+.TP
+.B POLKIT_SESSION_UID
+UNIX user ID of the user owning the session (only set if the caller belong to a session)
+.TP
+.B POLKIT_SEAT_CK_OBJREF
+ConsoleKit seat D-Bus object reference of the seat that the session belongs to (only set if the caller belong to a session)
+
+.PP
+For a request concerning session-wide decisions the environment will
+contain:
+
+.TP
+.B POLKIT_REQUEST_SESSION=1
+To identify the request to be session-wide.
+.TP
+.B POLKIT_PRIVILEGE_ID
+Privilege identifier
+.TP
+.B POLKIT_RESOURCE_ID
+Resource identifier
+.TP
+.B POLKIT_RESOURCE_TYPE
+Resource type
+.TP
+.B POLKIT_SESSION_CK_IS_ACTIVE
+Whether ConsoleKit regards the session as active
+.TP
+.B POLKIT_SESSION_CK_IS_LOCAL
+Whether ConsoleKit regards the session as local
+.TP
+.B POLKIT_SESSION_CK_OBJREF
+ConsoleKit session D-Bus object reference
+.TP
+.B POLKIT_SESSION_UID
+UNIX user ID of the user owning the session
+.TP
+.B POLKIT_SEAT_CK_OBJREF
+ConsoleKit seat D-Bus object reference of the seat that the session belongs to
+
+.SH NOTES
+.PP
+As PolicyKit modules are heavily used to enforce policy, running a
+program on every request may put unneccessary load on the system
+unless judicious use of built-in options to confine the module are
+employed.
+
+.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),
+\&\fIhald\fR\|(8),
+\&\fIdbus-daemon\fR\|(1),
+\&\fIpolkit-module-default\fR\|(8),
+\&\fIpolkit-module-builtins\fR\|(8),
+\&\fIpolkit-module-default\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/libpolkit/libpolkit-context.c b/libpolkit/libpolkit-context.c
index 5dcc5b2..0f71293 100644
--- a/libpolkit/libpolkit-context.c
+++ b/libpolkit/libpolkit-context.c
@@ -43,6 +43,13 @@
 #include "libpolkit-module.h"
 
 /**
+ * SECTION:libpolkit
+ * @short_description: Centralized policy management.
+ *
+ * libpolkit is a C library for centralized policy management.
+ **/
+
+/**
  * SECTION:libpolkit-context
  * @short_description: Context.
  *
@@ -545,11 +552,24 @@ libpolkit_context_can_session_access_res
                         _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 (libpolkit_module_interface_check_builtin_confinement_for_session (
+                                    module_interface,
+                                    pk_context,
+                                    privilege,
+                                    resource,
+                                    session)) {
+                                /* module is confined by built-in options */
+                                module_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+                                _pk_debug ("Module '%s' confined by built-in's", 
+                                           libpolkit_module_get_name (module_interface));
+                        } else {
+                                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)
@@ -653,11 +673,24 @@ libpolkit_context_can_caller_access_reso
                         _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 (libpolkit_module_interface_check_builtin_confinement_for_caller (
+                                    module_interface,
+                                    pk_context,
+                                    privilege,
+                                    resource,
+                                    caller)) {
+                                /* module is confined by built-in options */
+                                module_result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+                                _pk_debug ("Module '%s' confined by built-in's", 
+                                           libpolkit_module_get_name (module_interface));
+                        } else {
+                                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)
diff --git a/libpolkit/libpolkit-module.c b/libpolkit/libpolkit-module.c
index 562e90c..414d2c8 100644
--- a/libpolkit/libpolkit-module.c
+++ b/libpolkit/libpolkit-module.c
@@ -34,6 +34,9 @@
 #  include <config.h>
 #endif
 #include <dlfcn.h>
+#include <regex.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include "libpolkit-debug.h"
 #include "libpolkit-module.h"
@@ -58,8 +61,114 @@ struct PolKitModuleInterface
         PolKitModuleIsResourceAssociatedWithSeat   func_is_resource_associated_with_seat;
         PolKitModuleCanSessionAccessResource       func_can_session_access_resource;
         PolKitModuleCanCallerAccessResource        func_can_caller_access_resource;
+
+        gboolean builtin_have_privilege_regex;
+        regex_t  builtin_privilege_regex_compiled;
+
+        GSList *builtin_users;
 };
 
+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 void
+_parse_builtin_remove_option (int *argc, char *argv[], int position)
+{
+        int n;
+        for (n = position; n < *argc; n++)
+                argv[n] = argv[n+1];
+        (*argc)--;
+}
+
+static gboolean
+_parse_builtin (PolKitModuleInterface *mi, int *argc, char *argv[])
+{
+        int n;
+        gboolean ret;
+
+        ret = FALSE;
+
+        for (n = 1; n < *argc; ) {
+                if (g_str_has_prefix (argv[n], "privilege=")) {
+                        const char *regex;
+
+                        if (mi->builtin_have_privilege_regex) {
+                                _pk_debug ("Already have option 'privilege='");
+                                goto error;
+                        }
+
+                        regex = argv[n] + 10;
+                        if (regcomp (&(mi->builtin_privilege_regex_compiled), regex, REG_EXTENDED) != 0) {
+                                _pk_debug ("Regex '%s' didn't compile", regex);
+                                goto error;
+                        }
+                        mi->builtin_have_privilege_regex = TRUE;
+
+                        _pk_debug ("Compiled regex '%s' for option 'privilege=' OK", regex);
+
+                        _parse_builtin_remove_option (argc, argv, n);
+                } else if (g_str_has_prefix (argv[n], "user=")) {
+                        const char *user;
+                        uid_t uid;
+                        GSList *i;
+
+                        user = argv[n] + 5;
+                        uid = _util_name_to_uid (user, NULL);
+                        if ((int) uid == -1) {
+                                _pk_debug ("Unknown user name '%s'", user);
+                                goto error;
+                        }
+
+                        for (i = mi->builtin_users; i != NULL; i = g_slist_next (i)) {
+                                uid_t uid_in_list = GPOINTER_TO_INT (i->data);
+                                if (uid_in_list == uid) {
+                                        _pk_debug ("Already have user '%s'", user);
+                                        goto error;
+                                }
+                        }                        
+
+                        _pk_debug ("adding uid %d", uid);
+                        mi->builtin_users = g_slist_prepend (mi->builtin_users, GINT_TO_POINTER (uid));
+
+                        _parse_builtin_remove_option (argc, argv, n);
+                } else {
+                        n++;
+                }
+        }
+
+        ret = TRUE;
+
+error:
+        return ret;
+}
+
 /**
  * libpolkit_module_interface_load_module:
  * @name: name of module, e.g. "polkit-module-default.so"
@@ -112,6 +221,11 @@ libpolkit_module_interface_load_module (
                 goto error;
         }
 
+        if (!_parse_builtin (mi, &argc, argv)) {
+                _pk_debug ("Error parsing built-in module options for '%s'", name);
+                goto error;
+        }
+
         if (!mi->func_initialize (mi, argc, argv)) {
                 _pk_debug ("Module '%s' returned FALSE in initialization function", name);
                 goto error;
@@ -193,6 +307,11 @@ libpolkit_module_interface_unref (PolKit
         if (module_interface->refcount > 0) 
                 return;
 
+        /* builtins */
+        if (module_interface->builtin_have_privilege_regex)
+                regfree (&module_interface->builtin_privilege_regex_compiled);
+        g_slist_free (module_interface->builtin_users);
+
         /* shutdown the module and unload it */
         if (module_interface->func_shutdown != NULL)
                 module_interface->func_shutdown (module_interface);
@@ -488,3 +607,140 @@ libpolkit_module_get_user_data   (PolKit
         return module_interface->module_user_data;
 }
 
+static gboolean 
+_check_privilege (PolKitModuleInterface *module_interface, PolKitPrivilege *privilege)
+{
+        gboolean ret;
+
+        ret = FALSE;
+
+        if (module_interface->builtin_have_privilege_regex) {
+                char *privilege_name;
+                if (libpolkit_privilege_get_privilege_id (privilege, &privilege_name)) {
+                        if (regexec (&module_interface->builtin_privilege_regex_compiled, 
+                                     privilege_name, 0, NULL, 0) == 0) {
+                                ret = TRUE;
+                        }
+                }
+        } else {
+                ret = TRUE;
+        }
+
+        return ret;
+}
+
+/*----*/
+
+static gboolean
+_check_uid_in_list (GSList *list, uid_t given_uid)
+{
+        GSList *i;
+
+        for (i = list; i != NULL; i = g_slist_next (i)) {
+                uid_t uid = GPOINTER_TO_INT (i->data);
+                if (given_uid == uid)
+                        return TRUE;                
+        }
+        return FALSE;
+}
+
+static gboolean
+_check_users_for_session (PolKitModuleInterface *module_interface, PolKitSession *session)
+{
+        uid_t uid;
+        GSList *list;
+        if ((list = module_interface->builtin_users) == NULL)
+                return TRUE;
+        if (session == NULL)
+                return FALSE;
+        if (!libpolkit_session_get_uid (session, &uid))
+                return FALSE;
+        return _check_uid_in_list (list, uid);
+}
+
+static gboolean
+_check_users_for_caller (PolKitModuleInterface *module_interface, PolKitCaller *caller)
+{
+        uid_t uid;
+        GSList *list;
+        if ((list = module_interface->builtin_users) == NULL)
+                return TRUE;
+        if (caller == NULL)
+                return FALSE;
+        if (!libpolkit_caller_get_uid (caller, &uid))
+                return FALSE;
+        return _check_uid_in_list (list, uid);
+}
+
+
+/**
+ * libpolkit_module_interface_check_builtin_confinement_for_session:
+ * @module_interface: the given module
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @session: the session in question
+ * 
+ * Check whether some of the built-in module options (e.g. privilege="hal-storage-*", 
+ * user=davidz) confines the given module, e.g. whether it should be skipped.
+ * 
+ * Returns: TRUE if, and only if, the module is confined from handling the request
+ **/
+gboolean
+libpolkit_module_interface_check_builtin_confinement_for_session (PolKitModuleInterface *module_interface,
+                                                                  PolKitContext   *pk_context,
+                                                                  PolKitPrivilege *privilege,
+                                                                  PolKitResource  *resource,
+                                                                  PolKitSession   *session)
+{
+        gboolean ret;
+        ret = TRUE;
+
+        g_return_val_if_fail (module_interface != NULL, ret);
+
+        if (!_check_privilege (module_interface, privilege))
+                goto out;
+        if (!_check_users_for_session (module_interface, session))
+                goto out;
+
+        /* not confined */
+        ret = FALSE;
+out:
+        return ret;
+}
+
+/**
+ * libpolkit_module_interface_check_builtin_confinement_for_caller:
+ * @module_interface: the given module
+ * @pk_context: the PolicyKit context
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @caller: the resource in question
+ * 
+ * Check whether some of the built-in module options (e.g. privilege="hal-storage-*", 
+ * user=davidz) confines the given module, e.g. whether it should be skipped.
+ * 
+ * Returns: TRUE if, and only if, the module is confined from handling the request
+ **/
+gboolean
+libpolkit_module_interface_check_builtin_confinement_for_caller (PolKitModuleInterface *module_interface,
+                                                                 PolKitContext   *pk_context,
+                                                                 PolKitPrivilege *privilege,
+                                                                 PolKitResource  *resource,
+                                                                 PolKitCaller    *caller)
+{
+        gboolean ret;
+        ret = TRUE;
+
+        g_return_val_if_fail (module_interface != NULL, ret);
+
+        if (!_check_privilege (module_interface, privilege))
+                goto out;
+        if (!_check_users_for_caller (module_interface, caller))
+                goto out;
+
+        /* not confined */
+        ret = FALSE;
+out:
+        return ret;
+}
diff --git a/libpolkit/libpolkit-module.h b/libpolkit/libpolkit-module.h
index 9f325e3..bb99383 100644
--- a/libpolkit/libpolkit-module.h
+++ b/libpolkit/libpolkit-module.h
@@ -189,4 +189,19 @@ PolKitModuleInterface *libpolkit_module_
 
 PolKitModuleControl libpolkit_module_interface_get_control (PolKitModuleInterface *module_interface);
 
+
+gboolean
+libpolkit_module_interface_check_builtin_confinement_for_session (PolKitModuleInterface *module_interface,
+                                                                  PolKitContext   *pk_context,
+                                                                  PolKitPrivilege *privilege,
+                                                                  PolKitResource  *resource,
+                                                                  PolKitSession   *session);
+
+gboolean
+libpolkit_module_interface_check_builtin_confinement_for_caller (PolKitModuleInterface *module_interface,
+                                                                 PolKitContext   *pk_context,
+                                                                 PolKitPrivilege *privilege,
+                                                                 PolKitResource  *resource,
+                                                                 PolKitCaller    *caller);
+
 #endif /* LIBPOLKIT_MODULE_H */
diff --git a/modules/Makefile.am b/modules/Makefile.am
index b8c1a0d..b4eee78 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -1,5 +1,5 @@
 
-SUBDIRS = default allow-all deny-all
+SUBDIRS = default allow-all deny-all run-program
 
 polkitconfdir = $(sysconfdir)/PolicyKit
 dist_polkitconf_DATA = PolicyKit.conf
diff --git a/modules/allow-all/polkit-module-allow-all.c b/modules/allow-all/polkit-module-allow-all.c
index 82701c2..507868c 100644
--- a/modules/allow-all/polkit-module-allow-all.c
+++ b/modules/allow-all/polkit-module-allow-all.c
@@ -35,90 +35,21 @@
 #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
@@ -128,48 +59,7 @@ _module_can_session_access_resource (Pol
                                      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;
+        return LIBPOLKIT_RESULT_YES;
 }
 
 static PolKitResult
@@ -179,46 +69,7 @@ _module_can_caller_access_resource (PolK
                                     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;
+        return LIBPOLKIT_RESULT_YES;
 }
 
 gboolean
diff --git a/modules/deny-all/Makefile.am b/modules/deny-all/Makefile.am
index db5a282..d6a134a 100644
--- a/modules/deny-all/Makefile.am
+++ b/modules/deny-all/Makefile.am
@@ -9,7 +9,7 @@ INCLUDES = \
 	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
 	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
 	-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT	\
-	@GLIB_CFLAGS@ @DBUS_CFLAGS@ -DIS_POLKIT_MODULE_DENY_ALL
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
 
 polkitmoduledir = $(libdir)/PolicyKit/modules
 polkitmodule_LTLIBRARIES = 				\
@@ -17,7 +17,7 @@ polkitmodule_LTLIBRARIES = 				\
 	$(NULL)
 
 
-polkit_module_deny_all_la_SOURCES = ../allow-all/polkit-module-allow-all.c
+polkit_module_deny_all_la_SOURCES = polkit-module-deny-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@
 
diff --git a/modules/deny-all/polkit-module-deny-all.c b/modules/deny-all/polkit-module-deny-all.c
new file mode 100644
index 0000000..feece30
--- /dev/null
+++ b/modules/deny-all/polkit-module-deny-all.c
@@ -0,0 +1,92 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-module-allow-all.c : PolicyKit module that says NO 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 <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)
+{
+        return LIBPOLKIT_RESULT_NO;
+}
+
+static PolKitResult
+_module_can_caller_access_resource (PolKitModuleInterface *module_interface,
+                                    PolKitContext         *pk_context,
+                                    PolKitPrivilege       *privilege,
+                                    PolKitResource        *resource,
+                                    PolKitCaller          *caller)
+{
+        return LIBPOLKIT_RESULT_NO;
+}
+
+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/run-program/Makefile.am b/modules/run-program/Makefile.am
new file mode 100644
index 0000000..057c996
--- /dev/null
+++ b/modules/run-program/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-run-program.la		\
+	$(NULL)
+
+
+polkit_module_run_program_la_SOURCES = polkit-module-run-program.c
+polkit_module_run_program_la_LDFLAGS = -no-undefined -module -avoid-version
+polkit_module_run_program_la_LIBADD = $(top_builddir)/libpolkit/libpolkit.la @GLIB_LIBS@
+
+clean-local :
+	rm -f *~
diff --git a/modules/run-program/polkit-module-run-program.c b/modules/run-program/polkit-module-run-program.c
new file mode 100644
index 0000000..af641c6
--- /dev/null
+++ b/modules/run-program/polkit-module-run-program.c
@@ -0,0 +1,359 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * polkit-module-run-program.c : determine policy by running a program
+ *
+ * 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);
+
+typedef struct {
+        int program_argc;
+        char **program_argv;
+} UserData;
+
+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], "program=")) {
+                        const char *program;
+                        program = argv[n] + 8;
+
+                        if (!g_shell_parse_argv (program, 
+                                                 &user_data->program_argc, 
+                                                 &user_data->program_argv, NULL)) {
+                                printf ("Cannot parse '%s' - skipping\n", program);
+                                goto error;
+                        }
+
+                        if (!g_file_test (user_data->program_argv[0], 
+                                          G_FILE_TEST_IS_EXECUTABLE|G_FILE_TEST_IS_REGULAR)) {
+                                printf ("Program '%s' is not an executable file - skipping\n",
+                                        user_data->program_argv[0]);
+                                goto error;
+                        }
+
+                        printf ("program = '%s'\n", user_data->program_argv[0]);
+
+                        /* TODO:
+                         * O_o o_O... we could monitor the executable file :-) and trigger config changes!
+                         */
+                }
+        }
+
+        if (user_data->program_argv == NULL)
+                goto error;
+
+        libpolkit_module_set_user_data (module_interface, user_data);
+
+        return TRUE;
+error:
+        if (user_data->program_argv != NULL)
+                g_strfreev (user_data->program_argv);
+        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);
+        if (user_data != NULL) {
+                if (user_data->program_argv != NULL)
+                        g_strfreev (user_data->program_argv);
+                g_free (user_data);
+        }
+}
+
+static gboolean
+_add_privilege_to_env (PolKitPrivilege *privilege, GPtrArray *envp)
+{
+        char *p_id;
+        if (!libpolkit_privilege_get_privilege_id (privilege, &p_id))
+                goto error;
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_PRIVILEGE_ID=%s", p_id));
+        return TRUE;
+error:
+        return FALSE;
+}
+
+static gboolean
+_add_resource_to_env (PolKitResource *resource, GPtrArray *envp)
+{
+        char *r_type;
+        char *r_id;
+        if (!libpolkit_resource_get_resource_type (resource, &r_type))
+                goto error;
+        if (!libpolkit_resource_get_resource_id (resource, &r_id))
+                goto error;
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_RESOURCE_TYPE=%s", r_type));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_RESOURCE_ID=%s", r_id));
+        return TRUE;
+error:
+        return FALSE;
+}
+
+static gboolean
+_add_seat_to_env (PolKitSeat *seat, GPtrArray *envp)
+{
+        char *s_ck_objref;
+        if (!libpolkit_seat_get_ck_objref (seat, &s_ck_objref))
+                goto error;
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SEAT_CK_OBJREF=%s", s_ck_objref));
+        return TRUE;
+error:
+        return FALSE;
+}
+
+static gboolean
+_add_session_to_env (PolKitSession *session, GPtrArray *envp)
+{
+        uid_t s_uid;
+        char *s_ck_objref;
+        gboolean s_ck_is_active;
+        gboolean s_ck_is_local;
+        char *s_ck_remote_host;
+        PolKitSeat *s_seat;
+
+        if (!libpolkit_session_get_uid (session, &s_uid))
+                goto error;
+        if (!libpolkit_session_get_ck_objref (session, &s_ck_objref))
+                goto error;
+        if (!libpolkit_session_get_ck_is_active (session, &s_ck_is_active))
+                goto error;
+        if (!libpolkit_session_get_ck_is_local (session, &s_ck_is_local))
+                goto error;
+        if (!s_ck_is_local)
+                if (!libpolkit_session_get_ck_remote_host (session, &s_ck_remote_host))
+                        goto error;
+        if (!libpolkit_session_get_seat (session, &s_seat))
+                goto error;
+
+        if (!_add_seat_to_env (s_seat, envp))
+                goto error;
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_UID=%d", (int) s_uid));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_OBJREF=%s", s_ck_objref));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_IS_ACTIVE=%d", s_ck_is_active));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_IS_LOCAL=%d", s_ck_is_local));
+        if (!s_ck_is_local)
+                g_ptr_array_add (envp, g_strdup_printf ("POLKIT_SESSION_CK_REMOTE_HOST=%s", s_ck_remote_host));
+        return TRUE;
+error:
+        return FALSE;
+}
+
+static gboolean
+_add_caller_to_env (PolKitCaller *caller, GPtrArray *envp)
+{
+        uid_t c_uid;
+        pid_t c_pid;
+        char *c_selinux_context;
+        char *c_dbus_name;
+        PolKitSession *c_session;
+
+        if (!libpolkit_caller_get_uid (caller, &c_uid))
+                goto error;
+        if (!libpolkit_caller_get_pid (caller, &c_pid))
+                goto error;
+        if (!libpolkit_caller_get_dbus_name (caller, &c_dbus_name))
+                goto error;
+        if (!libpolkit_caller_get_selinux_context (caller, &c_selinux_context)) /* SELinux may not be available */
+                c_selinux_context = NULL;
+        if (!libpolkit_caller_get_ck_session (caller, &c_session)) /* Caller may not originate from a session */
+                c_session = NULL;
+
+        if (c_session != NULL)
+                if (!_add_session_to_env (c_session, envp))
+                        goto error;
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_UID=%d", (int) c_uid));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_PID=%d", (int) c_pid));
+        g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_DBUS_NAME=%s", c_dbus_name));
+        if (c_selinux_context != NULL)
+                g_ptr_array_add (envp, g_strdup_printf ("POLKIT_CALLER_SELINUX_CONTEXT=%s", c_selinux_context));
+        return TRUE;
+error:
+        return FALSE;
+}
+
+static gboolean
+_run_program (UserData *user_data, char **envp, PolKitResult *result)
+{
+        int n;
+        int exit_status;
+        GError *g_error;
+        char *prog_stdout;
+        gboolean ret;
+
+        g_error = NULL;
+        prog_stdout = NULL;
+        ret = FALSE;
+
+        if (!g_spawn_sync ("/",
+                           user_data->program_argv,
+                           envp,
+                           0,
+                           NULL,
+                           NULL,
+                           &prog_stdout,
+                           NULL,
+                           &exit_status,
+                           &g_error)) {
+                printf ("error spawning '%s': %s\n", user_data->program_argv[0], g_error->message);
+                g_error_free (g_error);
+                goto error;
+        }
+
+        /* only care if the program returned 0 */
+        if (exit_status != 0)
+                goto error;
+
+        /* only care about the first line */
+        for (n = 0; prog_stdout[n] != '\n' && prog_stdout[n] != '\0'; n++)
+                ;
+        prog_stdout[n] = '\0';
+
+        if (!libpolkit_result_from_string_representation (prog_stdout, result)) {
+                printf ("malformed result '%s' from program\n", prog_stdout);
+                goto error;
+        }
+
+        ret = TRUE;
+error:
+        g_free (prog_stdout);
+        return ret;
+}
+
+
+static PolKitResult
+_module_can_session_access_resource (PolKitModuleInterface *module_interface,
+                                     PolKitContext         *pk_context,
+                                     PolKitPrivilege       *privilege,
+                                     PolKitResource        *resource,
+                                     PolKitSession         *session)
+{
+        PolKitResult result;
+        UserData *user_data;
+        GPtrArray *envp;
+
+        envp = NULL;
+        result = LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE;
+
+        user_data = libpolkit_module_get_user_data (module_interface);
+
+        envp = g_ptr_array_new ();
+
+        if (!_add_privilege_to_env (privilege, envp))
+                goto error;
+        if (!_add_resource_to_env (resource, envp))
+                goto error;
+        if (!_add_session_to_env (session, envp))
+                goto error;
+        g_ptr_array_add (envp, g_strdup ("PATH=/usr/bin:/bin"));
+        g_ptr_array_add (envp, g_strdup ("POLKIT_REQUEST_SESSION=1"));
+        g_ptr_array_add (envp, NULL);
+
+        if (!_run_program (user_data, (char **) envp->pdata, &result))
+                goto error;
+        
+error:
+        if (envp != NULL) {
+                g_ptr_array_foreach (envp, (GFunc) g_free, NULL);
+                g_ptr_array_free (envp, TRUE);
+        }
+        return result;
+}
+
+static PolKitResult
+_module_can_caller_access_resource (PolKitModuleInterface *module_interface,
+                                    PolKitContext         *pk_context,
+                                    PolKitPrivilege       *privilege,
+                                    PolKitResource        *resource,
+                                    PolKitCaller          *caller)
+{
+        PolKitResult result;
+        UserData *user_data;
+        GPtrArray *envp;
+
+        envp = NULL;
+        result = LIBPOLKIT_RESULT_NO;
+        user_data = libpolkit_module_get_user_data (module_interface);
+
+        envp = g_ptr_array_new ();
+        if (!_add_privilege_to_env (privilege, envp))
+                goto error;
+        if (!_add_resource_to_env (resource, envp))
+                goto error;
+        if (!_add_caller_to_env (caller, envp))
+                goto error;
+        g_ptr_array_add (envp, g_strdup ("PATH=/usr/bin:/bin"));
+        g_ptr_array_add (envp, g_strdup ("POLKIT_REQUEST_CALLER=1"));
+        g_ptr_array_add (envp, NULL);
+        if(!_run_program (user_data, (char **) envp->pdata, &result))
+                goto error;
+
+error:
+        if (envp != NULL) {
+                g_ptr_array_foreach (envp, (GFunc) g_free, NULL);
+                g_ptr_array_free (envp, TRUE);
+        }
+        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;
+}


More information about the hal-commit mailing list