PolicyKit: Branch 'master'

David Zeuthen david at kemper.freedesktop.org
Fri Apr 6 11:09:15 PDT 2007


 Makefile.am                                 |    2 
 configure.in                                |    1 
 doc/api/libpolkit/libpolkit-docs.xml        |    3 
 doc/man/Makefile.am                         |    2 
 doc/man/polkit-privilege-file-validate.1.in |   55 ++++
 doc/spec/Makefile.am                        |    2 
 examples/polkit-example-privilege.priv      |   12 -
 libpolkit/Makefile.am                       |   30 +-
 libpolkit/libpolkit-caller.c                |   15 +
 libpolkit/libpolkit-caller.h                |    2 
 libpolkit/libpolkit-context.c               |   40 +++
 libpolkit/libpolkit-context.h               |    5 
 libpolkit/libpolkit-error.h                 |    4 
 libpolkit/libpolkit-privilege-cache.c       |  241 ++++++++++++++++++++
 libpolkit/libpolkit-privilege-cache.h       |   50 ++++
 libpolkit/libpolkit-privilege-default.c     |  324 ++++++++++++++++++++++++++++
 libpolkit/libpolkit-privilege-default.h     |   61 +++++
 libpolkit/libpolkit-privilege-file-entry.c  |  177 +++++++++++++++
 libpolkit/libpolkit-privilege-file-entry.h  |   51 ++++
 libpolkit/libpolkit-privilege-file.c        |  147 +++++-------
 libpolkit/libpolkit-privilege-file.h        |    9 
 libpolkit/libpolkit-privilege.c             |   13 +
 libpolkit/libpolkit-privilege.h             |    2 
 libpolkit/libpolkit-resource.c              |   13 +
 libpolkit/libpolkit-resource.h              |    2 
 libpolkit/libpolkit-result.c                |    2 
 libpolkit/libpolkit-result.h                |    2 
 libpolkit/libpolkit-seat.c                  |   13 +
 libpolkit/libpolkit-seat.h                  |    2 
 libpolkit/libpolkit-session.c               |   15 +
 libpolkit/libpolkit-session.h               |    2 
 libpolkit/libpolkit.c                       |   79 ++++++
 privileges/Makefile.am                      |   17 +
 privileges/polkit-example-privilege.priv    |   15 +
 tools/Makefile.am                           |    1 
 tools/polkit-check-caller.c                 |    9 
 tools/polkit-check-session.c                |    9 
 37 files changed, 1309 insertions(+), 120 deletions(-)

New commits:
diff-tree b18bb2d892fc073528552d1094659a0d1902ef18 (from 5a74d9b7a123f0bed10c857863e81bc88c402d8e)
Author: David Zeuthen <davidz at redhat.com>
Date:   Fri Apr 6 14:09:02 2007 -0400

    read privilege files and actually use the policy described in those

diff --git a/Makefile.am b/Makefile.am
index 422aece..6e481ed 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = libpolkit doc tools
+SUBDIRS = libpolkit doc tools privileges
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libpolkit.pc
diff --git a/configure.in b/configure.in
index 17cee01..7af5deb 100644
--- a/configure.in
+++ b/configure.in
@@ -173,6 +173,7 @@ doc/api/libpolkit/version.xml
 doc/spec/Makefile
 doc/spec/polkit-spec.xml.in
 doc/man/Makefile
+privileges/Makefile
 ])
 
 dnl ==========================================================================
diff --git a/doc/api/libpolkit/libpolkit-docs.xml b/doc/api/libpolkit/libpolkit-docs.xml
index 6b7ac6b..1c9d355 100644
--- a/doc/api/libpolkit/libpolkit-docs.xml
+++ b/doc/api/libpolkit/libpolkit-docs.xml
@@ -70,6 +70,9 @@
     <xi:include href="xml/libpolkit-context.xml"/>
     <xi:include href="xml/libpolkit-privilege.xml"/>
     <xi:include href="xml/libpolkit-privilege-file.xml"/>
+    <xi:include href="xml/libpolkit-privilege-file-entry.xml"/>
+    <xi:include href="xml/libpolkit-privilege-cache.xml"/>
+    <xi:include href="xml/libpolkit-privilege-default.xml"/>
     <xi:include href="xml/libpolkit-resource.xml"/>
     <xi:include href="xml/libpolkit-seat.xml"/>
     <xi:include href="xml/libpolkit-session.xml"/>
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 0582021..5b99a1f 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
+MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in polkit-privilege-file-validate.1.in
 
 man_MANS = $(MAN_IN_FILES:.in=)
 
diff --git a/doc/man/polkit-privilege-file-validate.1.in b/doc/man/polkit-privilege-file-validate.1.in
new file mode 100644
index 0000000..9c7ecc3
--- /dev/null
+++ b/doc/man/polkit-privilege-file-validate.1.in
@@ -0,0 +1,55 @@
+.\" 
+.\" polkit-privilege-file-validate manual page.
+.\" Copyright (C) 2007 David Zeuthen <david at fubar.dk>
+.\"
+.TH POLKIT-PRIVILEGE-FILE-VALIDATE 1
+.SH NAME
+polkit-privilege-file-validate \- check access
+.SH SYNOPSIS
+.PP
+.B polkit-privilege-file-validate
+[options]
+
+.SH DESCRIPTION
+
+\fIpolkit-privilege-file-validate\fP is used to validate PolicyKit
+privilege definition files. These are normally stored in the
+.I "@sysconfdir@/PolicyKit/privileges"
+directory. 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
+The following options are supported:
+.TP
+.I "--file"
+File to validate.
+.TP
+.I "--help"
+Print out usage.
+.TP
+.I "--version"
+Print the version.
+
+.SH RETURN VALUE
+.PP
+If the file validates, this program exits with exit code 0. Otherwise
+the program exits with a non-zero exit code.
+
+.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-check-caller\fR\|(1),
+\&\fIpolkit-check-session\fR\|(1)
+
+.SH AUTHOR
+Written by David Zeuthen <david at fubar.dk> with a lot of help from many
+others.
+
diff --git a/doc/spec/Makefile.am b/doc/spec/Makefile.am
index 8abc430..5d885de 100644
--- a/doc/spec/Makefile.am
+++ b/doc/spec/Makefile.am
@@ -6,7 +6,7 @@ SPEC_XML_EXTRA_FILES =			\
 
 if DOCBOOK_DOCS_ENABLED
 
-htmldocdir = $(DOCDIR)/spec
+htmldocdir = $(docdir)/spec
 htmldoc_DATA = polkit-spec.html $(FIGURE_FILES) docbook.css
 
 polkit-spec.html : polkit-spec.xml.in $(FIGURE_FILES) $(SPEC_XML_EXTRA_FILES)
diff --git a/examples/polkit-example-privilege.priv b/examples/polkit-example-privilege.priv
deleted file mode 100644
index 206eb32..0000000
--- a/examples/polkit-example-privilege.priv
+++ /dev/null
@@ -1,12 +0,0 @@
-
-[Privilege]
-Group=PolicyKit Example
-Identifier=polkit-example-privileges
-Description=Example Privilege
-
-[Defaults]
-AllowRemoteInactive=no
-AllowRemoteActive=auth_root_keep_session
-AllowLocalInactive=auth_self_keep_always
-AllowLocalActive=yes
-
diff --git a/libpolkit/Makefile.am b/libpolkit/Makefile.am
index b65a9fd..90e9695 100644
--- a/libpolkit/Makefile.am
+++ b/libpolkit/Makefile.am
@@ -25,19 +25,25 @@ libpolkitinclude_HEADERS =              
 	libpolkit-seat.h				\
 	libpolkit-session.h				\
 	libpolkit-caller.h				\
-	libpolkit-privilege-file.h
+	libpolkit-privilege-file-entry.h		\
+	libpolkit-privilege-file.h			\
+	libpolkit-privilege-cache.h			\
+	libpolkit-privilege-default.h
 
-libpolkit_la_SOURCES =                  	              		\
-	libpolkit.h			libpolkit.c			\
-	libpolkit-error.h		libpolkit-error.c		\
-	libpolkit-result.h		libpolkit-result.c		\
-	libpolkit-context.h		libpolkit-context.c		\
-	libpolkit-privilege.h		libpolkit-privilege.c		\
-	libpolkit-resource.h		libpolkit-resource.c		\
-	libpolkit-seat.h		libpolkit-seat.c		\
-	libpolkit-session.h		libpolkit-session.c		\
-	libpolkit-caller.h		libpolkit-caller.c		\
-	libpolkit-privilege-file.h	libpolkit-privilege-file.c
+libpolkit_la_SOURCES =                  	              				\
+	libpolkit.h				libpolkit.c				\
+	libpolkit-error.h			libpolkit-error.c			\
+	libpolkit-result.h			libpolkit-result.c			\
+	libpolkit-context.h			libpolkit-context.c			\
+	libpolkit-privilege.h			libpolkit-privilege.c			\
+	libpolkit-resource.h			libpolkit-resource.c			\
+	libpolkit-seat.h			libpolkit-seat.c			\
+	libpolkit-session.h			libpolkit-session.c			\
+	libpolkit-caller.h			libpolkit-caller.c			\
+	libpolkit-privilege-file-entry.h	libpolkit-privilege-file-entry.c	\
+	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_la_LIBADD = @GLIB_LIBS@ @DBUS_LIBS@
 
diff --git a/libpolkit/libpolkit-caller.c b/libpolkit/libpolkit-caller.c
index 2982508..a325256 100644
--- a/libpolkit/libpolkit-caller.c
+++ b/libpolkit/libpolkit-caller.c
@@ -435,3 +435,18 @@ out:
         return caller;
 }
 
+/**
+ * libpolkit_caller_debug:
+ * @caller: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_caller_debug (PolKitCaller *caller)
+{
+        g_return_if_fail (caller != NULL);
+        g_debug ("PolKitCaller: refcount=%d dbus_name=%s uid=%d pid=%d selinux_context=%s", 
+                 caller->refcount, caller->dbus_name, caller->uid, caller->pid, caller->selinux_context);
+        if (caller->session != NULL)
+                libpolkit_session_debug (caller->session);
+}
diff --git a/libpolkit/libpolkit-caller.h b/libpolkit/libpolkit-caller.h
index b2cfd11..7e8bb3a 100644
--- a/libpolkit/libpolkit-caller.h
+++ b/libpolkit/libpolkit-caller.h
@@ -52,6 +52,8 @@ gboolean          libpolkit_caller_get_p
 gboolean          libpolkit_caller_get_selinux_context (PolKitCaller   *caller, char          **out_selinux_context);
 gboolean          libpolkit_caller_get_ck_session      (PolKitCaller   *caller, PolKitSession **out_session);
 
+void              libpolkit_caller_debug               (PolKitCaller   *caller);
+
 #endif /* LIBPOLKIT_H */
 
 
diff --git a/libpolkit/libpolkit-context.c b/libpolkit/libpolkit-context.c
index 2243af3..3a6fc32 100644
--- a/libpolkit/libpolkit-context.c
+++ b/libpolkit/libpolkit-context.c
@@ -38,6 +38,7 @@
 
 #include <glib.h>
 #include "libpolkit-context.h"
+#include "libpolkit-privilege-cache.h"
 
 /**
  * SECTION:libpolkit-context
@@ -56,22 +57,42 @@ struct PolKitContext
         int refcount;
         PolKitContextConfigChangedCB config_changed_cb;
         gpointer config_changed_user_data;
+
+        PolKitPrivilegeCache *priv_cache;
 };
 
 /**
  * libpolkit_context_new:
+ * @error: return location for error
  * 
  * Create a new context.
  * 
- * Returns: the new context object
+ * Returns: #NULL if @error was set, otherwise the #PolKitPrivilegeCache object
  **/
 PolKitContext *
-libpolkit_context_new (void)
+libpolkit_context_new (GError **error)
 {
+        const char *dirname;
         PolKitContext *pk_context;
         pk_context = g_new0 (PolKitContext, 1);
         pk_context->refcount = 1;
+
+        dirname = getenv ("POLKIT_PRIV_DIR");
+        if (dirname != NULL) {
+                g_debug ("Using directory %s", dirname);
+        } else {
+                dirname = PACKAGE_SYSCONF_DIR "/PolicyKit/privileges";
+        }
+
+        pk_context->priv_cache = libpolkit_privilege_cache_new (dirname, error);
+        if (pk_context->priv_cache == NULL)
+                goto error;
+        libpolkit_privilege_cache_debug (pk_context->priv_cache);
+
         return pk_context;
+error:
+        libpolkit_context_unref (pk_context);
+        return NULL;
 }
 
 /**
@@ -128,3 +149,18 @@ libpolkit_context_set_config_changed (Po
         pk_context->config_changed_cb = cb;
         pk_context->config_changed_user_data = user_data;
 }
+
+/**
+ * libpolkit_context_get_privilege_cache:
+ * @pk_context: the context
+ * 
+ * Get the #PolKitPrivilegeCache object that holds all the defined privileges as well as their defaults.
+ * 
+ * Returns: the #PolKitPrivilegeCache object. Caller shall not unref it.
+ **/
+PolKitPrivilegeCache *
+libpolkit_context_get_privilege_cache (PolKitContext *pk_context)
+{
+        g_return_val_if_fail (pk_context != NULL, NULL);
+        return pk_context->priv_cache;
+}
diff --git a/libpolkit/libpolkit-context.h b/libpolkit/libpolkit-context.h
index dffb5f5..bf34c40 100644
--- a/libpolkit/libpolkit-context.h
+++ b/libpolkit/libpolkit-context.h
@@ -31,6 +31,8 @@
 #include <sys/types.h>
 #include <glib.h>
 
+#include <libpolkit/libpolkit-privilege-cache.h>
+
 struct PolKitContext;
 typedef struct PolKitContext PolKitContext;
 
@@ -44,13 +46,14 @@ typedef struct PolKitContext PolKitConte
 typedef void (*PolKitContextConfigChangedCB) (PolKitContext  *pk_context,
                                               gpointer        user_data);
 
-PolKitContext *libpolkit_context_new                (void);
+PolKitContext *libpolkit_context_new                (GError                      **error);
 PolKitContext *libpolkit_context_ref                (PolKitContext                *pk_context);
 void           libpolkit_context_set_config_changed (PolKitContext                *pk_context, 
                                                      PolKitContextConfigChangedCB  cb, 
                                                      gpointer                      user_data);
 void           libpolkit_context_unref              (PolKitContext                *pk_context);
 
+PolKitPrivilegeCache *libpolkit_context_get_privilege_cache (PolKitContext *pk_context);
 
 #endif /* LIBPOLKIT_CONTEXT_H */
 
diff --git a/libpolkit/libpolkit-error.h b/libpolkit/libpolkit-error.h
index 53d5be9..b587ee0 100644
--- a/libpolkit/libpolkit-error.h
+++ b/libpolkit/libpolkit-error.h
@@ -30,13 +30,13 @@
 
 /**
  * PolKitError:
- * @POLKIT_ERROR_PRIVILEGE_FILE_INVALID_VALUE: There was an error parsing the given privilege file
+ * @POLKIT_ERROR_PRIVILEGE_FILE_INVALID: There was an error parsing the given privilege file
  *
  * Error codes returned by PolicyKit
  */
 typedef enum
 {      
-        POLKIT_ERROR_PRIVILEGE_FILE_INVALID_VALUE
+        POLKIT_ERROR_PRIVILEGE_FILE_INVALID
 } PolKitError;
 
 /**
diff --git a/libpolkit/libpolkit-privilege-cache.c b/libpolkit/libpolkit-privilege-cache.c
new file mode 100644
index 0000000..51c3a26
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-cache.c
@@ -0,0 +1,241 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-cache.c : privilege cache
+ *
+ * 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 <glib.h>
+#include "libpolkit-privilege-file.h"
+#include "libpolkit-privilege-cache.h"
+
+/**
+ * SECTION:libpolkit-privilege-cache
+ * @short_description: System privilege queries.
+ *
+ * This class is used to query all system-defined privileges,
+ * e.g. privilege files installed in /etc/PolicyKit/privileges.
+ **/
+
+/**
+ * PolKitPrivilegeCache:
+ *
+ * Instances of this class is used to query all system-defined
+ * privileges, e.g. privilege files installed in
+ * /etc/PolicyKit/privileges.
+ **/
+struct PolKitPrivilegeCache
+{
+        int refcount;
+
+        GSList *priv_entries;
+};
+
+
+static void
+add_entries_from_file (PolKitPrivilegeCache *privilege_cache,
+                       PolKitPrivilegeFile  *privilege_file)
+{
+        GSList *i;
+
+        g_return_if_fail (privilege_cache != NULL);
+        g_return_if_fail (privilege_file != NULL);
+
+        for (i = libpolkit_privilege_file_get_entries (privilege_file); i != NULL; i = g_slist_next (i)) {
+                PolKitPrivilegeFileEntry  *privilege_file_entry = i->data;
+                libpolkit_privilege_file_entry_ref (privilege_file_entry);
+                privilege_cache->priv_entries = g_slist_append (privilege_cache->priv_entries, 
+                                                                privilege_file_entry);
+        }
+}
+
+/**
+ * libpolkit_privilege_cache_new:
+ * @dirname: directory containing privilege files
+ * @error: location to return error
+ * 
+ * Create a new #PolKitPrivilegeCache object and load information from privilege files.
+ * 
+ * Returns: #NULL if @error was set, otherwise the #PolKitPrivilegeCache object
+ **/
+PolKitPrivilegeCache *
+libpolkit_privilege_cache_new (const char *dirname, GError **error)
+{
+        const char *file;
+        GDir *dir;
+        PolKitPrivilegeCache *pc;
+
+        pc = g_new0 (PolKitPrivilegeCache, 1);
+        pc->refcount = 1;
+
+        dir = g_dir_open (dirname, 0, error);
+        if (dir == NULL) {
+                goto out;
+        }
+        while ((file = g_dir_read_name (dir)) != NULL) {
+                char *path;
+                PolKitPrivilegeFile *pf;
+
+                if (!g_str_has_suffix (file, ".priv"))
+                        continue;
+
+                path = g_strdup_printf ("%s/%s", dirname, file);
+
+                g_debug ("Loading %s", path);
+                pf = libpolkit_privilege_file_new (path, error);
+                g_free (path);
+
+                if (pf == NULL) {
+                        goto out;
+                }
+
+                add_entries_from_file (pc, pf);
+                libpolkit_privilege_file_unref (pf);
+        }
+        g_dir_close (dir);
+
+        return pc;
+out:
+        if (pc != NULL)
+                libpolkit_privilege_cache_ref (pc);
+        return NULL;
+}
+
+/**
+ * libpolkit_privilege_cache_ref:
+ * @privilege_cache: the privilege cache object
+ * 
+ * Increase reference count.
+ * 
+ * Returns: the object
+ **/
+PolKitPrivilegeCache *
+libpolkit_privilege_cache_ref (PolKitPrivilegeCache *privilege_cache)
+{
+        g_return_val_if_fail (privilege_cache != NULL, privilege_cache);
+        privilege_cache->refcount++;
+        return privilege_cache;
+}
+
+/**
+ * libpolkit_privilege_cache_unref:
+ * @privilege_cache: the privilege cache 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_privilege_cache_unref (PolKitPrivilegeCache *privilege_cache)
+{
+        GSList *i;
+
+        g_return_if_fail (privilege_cache != NULL);
+        privilege_cache->refcount--;
+        if (privilege_cache->refcount > 0) 
+                return;
+
+        for (i = privilege_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
+                PolKitPrivilegeFileEntry *pfe = i->data;
+                libpolkit_privilege_file_entry_unref (pfe);
+        }
+        if (privilege_cache->priv_entries != NULL)
+                g_slist_free (privilege_cache->priv_entries);
+
+        g_free (privilege_cache);
+}
+
+/**
+ * libpolkit_privilege_cache_debug:
+ * @privilege_cache: the cache
+ * 
+ * Print debug information about object
+ **/
+void
+libpolkit_privilege_cache_debug (PolKitPrivilegeCache *privilege_cache)
+{
+        GSList *i;
+        g_return_if_fail (privilege_cache != NULL);
+
+        g_debug ("PolKitPrivilegeCache: refcount=%d num_entries=%d ...", 
+                 privilege_cache->refcount,
+                 privilege_cache->priv_entries == NULL ? 0 : g_slist_length (privilege_cache->priv_entries));
+
+        for (i = privilege_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
+                PolKitPrivilegeFileEntry *pfe = i->data;
+                libpolkit_privilege_file_entry_debug (pfe);
+        }
+}
+
+/**
+ * libpolkit_privilege_cache_get_entry:
+ * @privilege_cache: the cache
+ * @privilege: the privilege
+ * 
+ * Given a privilege, find the object describing the definition of the
+ * privilege; e.g. data stemming from files in
+ * /etc/PolicyKit/privileges.
+ * 
+ * Returns: A #PolKitPrivilegeFileEntry entry on sucess; otherwise
+ * #NULL if the privilege wasn't identified. Caller shall not unref
+ * this object.
+ **/
+PolKitPrivilegeFileEntry* 
+libpolkit_privilege_cache_get_entry (PolKitPrivilegeCache *privilege_cache,
+                                     PolKitPrivilege      *privilege)
+{
+        char *priv_id;
+        GSList *i;
+        PolKitPrivilegeFileEntry *pfe;
+
+        pfe = NULL;
+
+        g_return_val_if_fail (privilege_cache != NULL, NULL);
+        g_return_val_if_fail (privilege != NULL, NULL);
+
+        if (!libpolkit_privilege_get_privilege_id (privilege, &priv_id))
+                goto out;
+
+        for (i = privilege_cache->priv_entries; i != NULL; i = g_slist_next (i)) {
+                pfe = i->data;
+                if (strcmp (libpolkit_privilege_file_entry_get_id (pfe), priv_id) == 0) {
+                        goto out;
+                }
+        }
+
+        pfe = NULL;
+
+out:
+        return pfe;
+}
diff --git a/libpolkit/libpolkit-privilege-cache.h b/libpolkit/libpolkit-privilege-cache.h
new file mode 100644
index 0000000..0b3932b
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-cache.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-cache.h : privilege cache
+ *
+ * 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_PRIVILEGE_CACHE_H
+#define LIBPOLKIT_PRIVILEGE_CACHE_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+
+#include <libpolkit/libpolkit-privilege.h>
+#include <libpolkit/libpolkit-privilege-file-entry.h>
+
+struct PolKitPrivilegeCache;
+typedef struct PolKitPrivilegeCache PolKitPrivilegeCache;
+
+PolKitPrivilegeCache *libpolkit_privilege_cache_new                   (const char *dirname, GError **error);
+PolKitPrivilegeCache *libpolkit_privilege_cache_ref                   (PolKitPrivilegeCache *privilege_cache);
+void                  libpolkit_privilege_cache_unref                 (PolKitPrivilegeCache *privilege_cache);
+void                  libpolkit_privilege_cache_debug                 (PolKitPrivilegeCache *privilege_cache);
+
+PolKitPrivilegeFileEntry* libpolkit_privilege_cache_get_entry (PolKitPrivilegeCache *privilege_cache,
+                                                               PolKitPrivilege      *privilege);
+
+#endif /* LIBPOLKIT_PRIVILEGE_CACHE_H */
+
+
diff --git a/libpolkit/libpolkit-privilege-default.c b/libpolkit/libpolkit-privilege-default.c
new file mode 100644
index 0000000..3a2eb99
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-default.c
@@ -0,0 +1,324 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-default.c : privilege definition for the defaults
+ *
+ * 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 <glib.h>
+#include "libpolkit-error.h"
+#include "libpolkit-privilege-default.h"
+
+/**
+ * SECTION:libpolkit-privilege-default
+ * @short_description: Defaults for privileges.
+ *
+ * This class records the default policy of a privilege as defined by
+ * the, privilege files installed in /etc/PolicyKit/privileges.
+ * 
+ **/
+
+/**
+ * PolKitPrivilegeDefault:
+ *
+ * Objects of this class are used to record information about a
+ * default policy for privilege.
+ **/
+struct PolKitPrivilegeDefault
+{
+        int refcount;
+        PolKitResult default_remote_inactive;
+        PolKitResult default_remote_active;
+        PolKitResult default_local_inactive;
+        PolKitResult default_local_active;
+};
+
+static gboolean
+parse_default (const char *key, char *s, const char *group, PolKitResult* target, GError **error)
+{
+        gboolean ret;
+
+        ret = libpolkit_result_from_string_representation (s, target);
+        if (!ret) {
+                int n;
+                char *s2;
+                GString *str;
+
+                str = g_string_new (NULL);
+                for (n = 0; n < LIBPOLKIT_RESULT_N_RESULTS; n++) {
+                        if (n == LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW)
+                                continue;
+
+                        if (str->len > 0) {
+                                g_string_append (str, ", ");
+                        }
+                        g_string_append (str, libpolkit_result_to_string_representation (n));
+                }
+                s2 = g_string_free (str, FALSE);
+
+                g_set_error (error, 
+                             POLKIT_ERROR, 
+                             POLKIT_ERROR_PRIVILEGE_FILE_INVALID,
+                             "Value '%s' is not allowed for key '%s' in group '%s' - supported values are: %s", 
+                             s, 
+                             key,
+                             group,
+                             s2);
+                g_free (s2);
+        }
+        
+        g_free (s);
+        return ret;
+}
+
+/**
+ * libpolkit_privilege_default_new:
+ * @key_file: a #GKeyFile object
+ * @privilege: privilege to look up defaults for in key_file
+ * @error: return location for error
+ * 
+ * Create a new #PolKitPrivilegeDefault object.
+ * 
+ * Returns: the new object or #NULL if error is set
+ **/
+PolKitPrivilegeDefault *
+libpolkit_privilege_default_new (GKeyFile *key_file, const char *privilege, GError **error)
+{
+        const char *key;
+        const char *group;
+        char *s;
+        char buf[256];
+        PolKitPrivilegeDefault *pd;
+
+        pd = g_new0 (PolKitPrivilegeDefault, 1);
+        pd->refcount = 1;
+
+        g_snprintf (buf, sizeof (buf), "Privilege %s", privilege);
+        group = buf;
+
+        key = "AllowRemoteInactive";
+        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
+                goto error;
+        if (!parse_default (key, s, group, &pd->default_remote_inactive, error))
+                goto error;
+        key = "AllowRemoteActive";
+        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
+                goto error;
+        if (!parse_default (key, s, group, &pd->default_remote_active, error))
+                goto error;
+        key = "AllowLocalInactive";
+        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
+                goto error;
+        if (!parse_default (key, s, group, &pd->default_local_inactive, error))
+                goto error;
+        key = "AllowLocalActive";
+        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
+                goto error;
+        if (!parse_default (key, s, group, &pd->default_local_active, error))
+                goto error;
+
+        return pd;
+error:
+        if (pd != NULL)
+                libpolkit_privilege_default_ref (pd);
+        return NULL;
+}
+
+/**
+ * libpolkit_privilege_default_ref:
+ * @privilege_default: the privilege object
+ * 
+ * Increase reference count.
+ * 
+ * Returns: the object
+ **/
+PolKitPrivilegeDefault *
+libpolkit_privilege_default_ref (PolKitPrivilegeDefault *privilege_default)
+{
+        g_return_val_if_fail (privilege_default != NULL, privilege_default);
+        privilege_default->refcount++;
+        return privilege_default;
+}
+
+/**
+ * libpolkit_privilege_default_unref:
+ * @privilege_default: the 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_privilege_default_unref (PolKitPrivilegeDefault *privilege_default)
+{
+        g_return_if_fail (privilege_default != NULL);
+        privilege_default->refcount--;
+        if (privilege_default->refcount > 0) 
+                return;
+        g_free (privilege_default);
+}
+
+/**
+ * libpolkit_privilege_default_debug:
+ * @privilege_default: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_privilege_default_debug (PolKitPrivilegeDefault *privilege_default)
+{
+        g_return_if_fail (privilege_default != NULL);
+        g_debug ("PolKitPrivilegeDefault: refcount=%d\n"
+                 "  default_remote_inactive=%s\n"
+                 "    default_remote_active=%s\n"
+                 "   default_local_inactive=%s\n"
+                 "     default_local_active=%s", 
+                 privilege_default->refcount,
+                 libpolkit_result_to_string_representation (privilege_default->default_remote_inactive),
+                 libpolkit_result_to_string_representation (privilege_default->default_remote_active),
+                 libpolkit_result_to_string_representation (privilege_default->default_local_inactive),
+                 libpolkit_result_to_string_representation (privilege_default->default_local_active));
+}
+
+
+/**
+ * libpolkit_privilege_default_can_session_access_resource:
+ * @privilege_default: the object
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @session: the session in question
+ * 
+ * Using the default policy for a privilege, 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_privilege_default_can_session_access_resource (PolKitPrivilegeDefault *privilege_default,
+                                                         PolKitPrivilege        *privilege,
+                                                         PolKitResource         *resource,
+                                                         PolKitSession          *session)
+{
+        gboolean is_local;
+        gboolean is_active;
+        PolKitResult ret;
+
+        ret = LIBPOLKIT_RESULT_NO;
+
+        g_return_val_if_fail (privilege_default != NULL, ret);
+        g_return_val_if_fail (privilege != NULL, ret);
+        g_return_val_if_fail (resource != NULL, ret);
+        g_return_val_if_fail (session != NULL, ret);
+
+        if (!libpolkit_session_get_ck_is_local (session, &is_local))
+                goto out;
+        if (!libpolkit_session_get_ck_is_active (session, &is_active))
+                goto out;
+
+        if (is_local) {
+                if (is_active) {
+                        ret = privilege_default->default_local_active;
+                } else {
+                        ret = privilege_default->default_local_inactive;
+                }
+        } else {
+                if (is_active) {
+                        ret = privilege_default->default_remote_active;
+                } else {
+                        ret = privilege_default->default_remote_inactive;
+                }
+        }
+out:
+        return ret;
+}
+
+/**
+ * libpolkit_privilege_default_can_caller_access_resource:
+ * @privilege_default: the object
+ * @privilege: the type of access to check for
+ * @resource: the resource in question
+ * @caller: the resource in question
+ * 
+ * Using the default policy for a privilege, 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_privilege_default_can_caller_access_resource (PolKitPrivilegeDefault *privilege_default,
+                                                        PolKitPrivilege        *privilege,
+                                                        PolKitResource         *resource,
+                                                        PolKitCaller           *caller)
+{
+        gboolean is_local;
+        gboolean is_active;
+        PolKitSession *session;
+        PolKitResult ret;
+
+        ret = LIBPOLKIT_RESULT_NO;
+
+        g_return_val_if_fail (privilege_default != NULL, ret);
+        g_return_val_if_fail (privilege != NULL, ret);
+        g_return_val_if_fail (resource != NULL, ret);
+        g_return_val_if_fail (caller != NULL, ret);
+
+        if (!libpolkit_caller_get_ck_session (caller, &session))
+                goto out;
+        if (session == NULL)
+                goto out;
+
+        if (!libpolkit_session_get_ck_is_local (session, &is_local))
+                goto out;
+        if (!libpolkit_session_get_ck_is_active (session, &is_active))
+                goto out;
+
+        if (is_local) {
+                if (is_active) {
+                        ret = privilege_default->default_local_active;
+                } else {
+                        ret = privilege_default->default_local_inactive;
+                }
+        } else {
+                if (is_active) {
+                        ret = privilege_default->default_remote_active;
+                } else {
+                        ret = privilege_default->default_remote_inactive;
+                }
+        }
+out:
+        return ret;
+}
diff --git a/libpolkit/libpolkit-privilege-default.h b/libpolkit/libpolkit-privilege-default.h
new file mode 100644
index 0000000..ac84a8a
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-default.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-default.h : privilege definition for the defaults
+ *
+ * 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_PRIVILEGE_DEFAULT_H
+#define LIBPOLKIT_PRIVILEGE_DEFAULT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+
+#include <libpolkit/libpolkit-result.h>
+#include <libpolkit/libpolkit-privilege.h>
+#include <libpolkit/libpolkit-resource.h>
+#include <libpolkit/libpolkit-session.h>
+#include <libpolkit/libpolkit-caller.h>
+
+struct PolKitPrivilegeDefault;
+typedef struct PolKitPrivilegeDefault PolKitPrivilegeDefault;
+
+PolKitPrivilegeDefault *libpolkit_privilege_default_new   (GKeyFile *key_file, const char *privilege, GError **error);
+PolKitPrivilegeDefault *libpolkit_privilege_default_ref   (PolKitPrivilegeDefault *privilege_default);
+void                    libpolkit_privilege_default_unref (PolKitPrivilegeDefault *privilege_default);
+void                    libpolkit_privilege_default_debug (PolKitPrivilegeDefault *privilege_default);
+
+PolKitResult libpolkit_privilege_default_can_session_access_resource (PolKitPrivilegeDefault *privilege_default,
+                                                                      PolKitPrivilege        *privilege,
+                                                                      PolKitResource         *resource,
+                                                                      PolKitSession          *session);
+PolKitResult libpolkit_privilege_default_can_caller_access_resource (PolKitPrivilegeDefault *privilege_default,
+                                                                     PolKitPrivilege        *privilege,
+                                                                     PolKitResource         *resource,
+                                                                     PolKitCaller           *caller);
+
+/* TODO: export knobs for "default policy" */
+
+#endif /* LIBPOLKIT_PRIVILEGE_DEFAULT_H */
+
+
diff --git a/libpolkit/libpolkit-privilege-file-entry.c b/libpolkit/libpolkit-privilege-file-entry.c
new file mode 100644
index 0000000..bd9c034
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-file-entry.c
@@ -0,0 +1,177 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-file-entry.c : entries in privilege files
+ *
+ * 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 <glib.h>
+#include "libpolkit-error.h"
+#include "libpolkit-result.h"
+#include "libpolkit-privilege-file-entry.h"
+
+/**
+ * SECTION:libpolkit-privilege-file-entry
+ * @short_description: Privileges files.
+ *
+ * This class is used to represent a entries in privilege files.
+ **/
+
+/**
+ * PolKitPrivilegeFileEntry:
+ *
+ * Objects of this class are used to record information about a
+ * privilege.
+ **/
+struct PolKitPrivilegeFileEntry
+{
+        int refcount;
+        char *privilege;
+        PolKitPrivilegeDefault *defaults;
+};
+
+/**
+ * libpolkit_privilege_file_entry_new:
+ * @key_file: a #GKeyFile object
+ * @privilege: privilege to look for in key_file
+ * @error: return location for error
+ * 
+ * Create a new #PolKitPrivilegeFileEntry object. If the given
+ * @key_file object does not contain the requisite sections, a human
+ * readable explanation of why will be set in @error.
+ * 
+ * Returns: the new object or #NULL if error is set
+ **/
+PolKitPrivilegeFileEntry *
+libpolkit_privilege_file_entry_new (GKeyFile *key_file, const char *privilege, GError **error)
+{
+        PolKitPrivilegeFileEntry *pfe;
+
+        pfe = g_new0 (PolKitPrivilegeFileEntry, 1);
+        pfe->refcount = 1;
+        pfe->privilege = g_strdup (privilege);
+
+        pfe->defaults = libpolkit_privilege_default_new (key_file, privilege, error);
+        if (pfe->defaults == NULL)
+                goto error;
+
+        return pfe;
+error:
+        if (pfe != NULL)
+                libpolkit_privilege_file_entry_unref (pfe);
+        return NULL;
+}
+
+/**
+ * libpolkit_privilege_file_entry_ref:
+ * @privilege_file_entry: the privilege file object
+ * 
+ * Increase reference count.
+ * 
+ * Returns: the object
+ **/
+PolKitPrivilegeFileEntry *
+libpolkit_privilege_file_entry_ref (PolKitPrivilegeFileEntry *privilege_file_entry)
+{
+        g_return_val_if_fail (privilege_file_entry != NULL, privilege_file_entry);
+        privilege_file_entry->refcount++;
+        return privilege_file_entry;
+}
+
+/**
+ * libpolkit_privilege_file_entry_unref:
+ * @privilege_file_entry: the privilege file 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_privilege_file_entry_unref (PolKitPrivilegeFileEntry *privilege_file_entry)
+{
+        g_return_if_fail (privilege_file_entry != NULL);
+        privilege_file_entry->refcount--;
+        if (privilege_file_entry->refcount > 0) 
+                return;
+        g_free (privilege_file_entry->privilege);
+        if (privilege_file_entry->defaults != NULL)
+                libpolkit_privilege_default_unref (privilege_file_entry->defaults);
+        g_free (privilege_file_entry);
+}
+
+/**
+ * libpolkit_privilege_file_entry_debug:
+ * @privilege_file_entry: the entry
+ * 
+ * Print debug information about object
+ **/
+void
+libpolkit_privilege_file_entry_debug (PolKitPrivilegeFileEntry *privilege_file_entry)
+{
+        g_return_if_fail (privilege_file_entry != NULL);
+        g_debug ("PolKitPrivilegeFileEntry: refcount=%d privilege=%s",
+                 privilege_file_entry->refcount,
+                 privilege_file_entry->privilege);
+        libpolkit_privilege_default_debug (privilege_file_entry->defaults);
+}
+
+/**
+ * libpolkit_privilege_file_entry_get_id:
+ * @privilege_file_entry: the file entry
+ * 
+ * Get the privilege identifier.
+ * 
+ * Returns: A string - caller shall not free this string.
+ **/
+const char *
+libpolkit_privilege_file_entry_get_id (PolKitPrivilegeFileEntry *privilege_file_entry)
+{
+        g_return_val_if_fail (privilege_file_entry != NULL, NULL);
+        return privilege_file_entry->privilege;
+}
+
+/**
+ * libpolkit_privilege_file_entry_get_default:
+ * @privilege_file_entry: the file entry
+ * 
+ * Get the the default policy for this privilege.
+ * 
+ * Returns: A #PolKitPrivilegeDefault object - caller shall not unref this object.
+ **/
+PolKitPrivilegeDefault *
+libpolkit_privilege_file_entry_get_default (PolKitPrivilegeFileEntry *privilege_file_entry)
+{
+        g_return_val_if_fail (privilege_file_entry != NULL, NULL);
+        return privilege_file_entry->defaults;
+}
diff --git a/libpolkit/libpolkit-privilege-file-entry.h b/libpolkit/libpolkit-privilege-file-entry.h
new file mode 100644
index 0000000..0d2b32c
--- /dev/null
+++ b/libpolkit/libpolkit-privilege-file-entry.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/***************************************************************************
+ *
+ * libpolkit-privilege-file-entry.h : entries in privilege files
+ *
+ * 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_PRIVILEGE_FILE_ENTRY_H
+#define LIBPOLKIT_PRIVILEGE_FILE_ENTRY_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+
+#include <libpolkit/libpolkit-result.h>
+#include <libpolkit/libpolkit-privilege-default.h>
+
+struct PolKitPrivilegeFileEntry;
+typedef struct PolKitPrivilegeFileEntry PolKitPrivilegeFileEntry;
+
+PolKitPrivilegeFileEntry *libpolkit_privilege_file_entry_new   (GKeyFile *key_file, const char *privilege, GError **error);
+PolKitPrivilegeFileEntry *libpolkit_privilege_file_entry_ref   (PolKitPrivilegeFileEntry *privilege_file_entry);
+void                      libpolkit_privilege_file_entry_unref (PolKitPrivilegeFileEntry *privilege_file_entry);
+void                      libpolkit_privilege_file_entry_debug (PolKitPrivilegeFileEntry *privilege_file_entry);
+
+const char             *libpolkit_privilege_file_entry_get_id      (PolKitPrivilegeFileEntry *privilege_file_entry);
+PolKitPrivilegeDefault *libpolkit_privilege_file_entry_get_default (PolKitPrivilegeFileEntry *privilege_file_entry);
+
+
+#endif /* LIBPOLKIT_PRIVILEGE_FILE_ENTRY_H */
+
+
diff --git a/libpolkit/libpolkit-privilege-file.c b/libpolkit/libpolkit-privilege-file.c
index f414c48..ae119b8 100644
--- a/libpolkit/libpolkit-privilege-file.c
+++ b/libpolkit/libpolkit-privilege-file.c
@@ -57,53 +57,9 @@
 struct PolKitPrivilegeFile
 {
         int refcount;
-        char *group;
-        char *identifier;
-        char *description;
-
-        PolKitResult default_remote_inactive;
-        PolKitResult default_remote_active;
-        PolKitResult default_local_inactive;
-        PolKitResult default_local_active;
+        GSList *entries;
 };
 
-static gboolean
-parse_default (const char *key, char *s, PolKitResult* target, GError **error)
-{
-        gboolean ret;
-
-        ret = libpolkit_result_from_string_representation (s, target);
-        if (!ret) {
-                int n;
-                char *s2;
-                GString *str;
-
-                str = g_string_new (NULL);
-                for (n = 0; n < LIBPOLKIT_RESULT_N_RESULTS; n++) {
-                        if (n == LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW)
-                                continue;
-
-                        if (str->len > 0) {
-                                g_string_append (str, ", ");
-                        }
-                        g_string_append (str, libpolkit_result_to_string_representation (n));
-                }
-                s2 = g_string_free (str, FALSE);
-
-                g_set_error (error, 
-                             POLKIT_ERROR, 
-                             POLKIT_ERROR_PRIVILEGE_FILE_INVALID_VALUE,
-                             "Value %s is not allowed for key %s - supported values are: %s", 
-                             s, 
-                             key,
-                             s2);
-                g_free (s2);
-        }
-        
-        g_free (s);
-        return ret;
-}
-
 /**
  * libpolkit_privilege_file_new:
  * @path: path to privilege file
@@ -120,11 +76,21 @@ libpolkit_privilege_file_new (const char
 {
         GKeyFile *key_file;
         PolKitPrivilegeFile *pf;
-        char *s;
-        const char *key;
-        const char *group;
+        char **groups;
+        gsize groups_len;
+        int n;
 
         pf = NULL;
+        key_file = NULL;
+        groups = NULL;
+
+        if (!g_str_has_suffix (path, ".priv")) {
+                g_set_error (error, 
+                             POLKIT_ERROR, 
+                             POLKIT_ERROR_PRIVILEGE_FILE_INVALID,
+                             "Privilege files must have extension .priv");
+                goto error;
+        }
 
         key_file = g_key_file_new ();
         if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, error))
@@ -133,40 +99,45 @@ libpolkit_privilege_file_new (const char
         pf = g_new0 (PolKitPrivilegeFile, 1);
         pf->refcount = 1;
 
-        group = "Privilege";
-        if ((pf->group = g_key_file_get_string (key_file, group, "Group", error)) == NULL)
-                goto error;
-        if ((pf->identifier = g_key_file_get_string (key_file, group, "Identifier", error)) == NULL)
-                goto error;
-        if ((pf->description = g_key_file_get_string (key_file, group, "Description", error)) == NULL)
+        groups = g_key_file_get_groups(key_file, &groups_len);
+        if (groups == NULL)
                 goto error;
 
-        group = "Defaults";
-        key = "AllowRemoteInactive";
-        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, &pf->default_remote_inactive, error))
-                goto error;
-        key = "AllowRemoteActive";
-        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, &pf->default_remote_active, error))
-                goto error;
-        key = "AllowLocalInactive";
-        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, &pf->default_local_inactive, error))
-                goto error;
-        key = "AllowLocalActive";
-        if ((s = g_key_file_get_string (key_file, group, key, error)) == NULL)
-                goto error;
-        if (!parse_default (key, s, &pf->default_local_active, error))
-                goto error;
+        for (n = 0; groups[n] != NULL; n++) {
+                const char *privilege;
+                PolKitPrivilegeFileEntry *pfe;
+
+                if (!g_str_has_prefix (groups[n], "Privilege ")) {
+                        g_set_error (error, 
+                                     POLKIT_ERROR, 
+                                     POLKIT_ERROR_PRIVILEGE_FILE_INVALID,
+                                     "Unknown group of name '%s'", groups[n]);
+                        goto error;
+                }
 
+                privilege = groups[n] + 10; /* strlen ("Privilege ") */
+                if (strlen (privilege) == 0) {
+                        g_set_error (error, 
+                                     POLKIT_ERROR, 
+                                     POLKIT_ERROR_PRIVILEGE_FILE_INVALID,
+                                     "Zero-length privilege name");
+                        goto error;
+                }
+
+                pfe = libpolkit_privilege_file_entry_new (key_file, privilege, error);
+                if (pfe == NULL)
+                        goto error;
+                pf->entries = g_slist_prepend (pf->entries, pfe);
+        }
+
+        g_strfreev (groups);
         g_key_file_free (key_file);
         return pf;
 error:
-        g_key_file_free (key_file);
+        if (groups != NULL)
+                g_strfreev (groups);
+        if (key_file != NULL)
+                g_key_file_free (key_file);
         if (pf != NULL)
                 libpolkit_privilege_file_unref (pf);
         return NULL;
@@ -199,13 +170,31 @@ libpolkit_privilege_file_ref (PolKitPriv
 void
 libpolkit_privilege_file_unref (PolKitPrivilegeFile *privilege_file)
 {
+        GSList *i;
         g_return_if_fail (privilege_file != NULL);
         privilege_file->refcount--;
         if (privilege_file->refcount > 0) 
                 return;
-        g_free (privilege_file->group);
-        g_free (privilege_file->identifier);
-        g_free (privilege_file->description);
+        for (i = privilege_file->entries; i != NULL; i = g_slist_next (i)) {
+                libpolkit_privilege_file_entry_unref (i->data);
+        }
+        if (privilege_file->entries != NULL)
+                g_slist_free (privilege_file->entries);
         g_free (privilege_file);
 }
 
+/**
+ * libpolkit_privilege_file_get_entries:
+ * @privilege_file: the privilege file object
+ * 
+ * Get the entries stemming from the given file.
+ * 
+ * Returns: A #GSList of the entries.
+ **/
+GSList *
+libpolkit_privilege_file_get_entries (PolKitPrivilegeFile *privilege_file)
+{
+        g_return_val_if_fail (privilege_file != NULL, NULL);
+        return privilege_file->entries;
+}
+
diff --git a/libpolkit/libpolkit-privilege-file.h b/libpolkit/libpolkit-privilege-file.h
index b536915..8b4b3fa 100644
--- a/libpolkit/libpolkit-privilege-file.h
+++ b/libpolkit/libpolkit-privilege-file.h
@@ -31,12 +31,15 @@
 #include <sys/types.h>
 #include <glib.h>
 
+#include <libpolkit/libpolkit-privilege-file-entry.h>
+
 struct PolKitPrivilegeFile;
 typedef struct PolKitPrivilegeFile PolKitPrivilegeFile;
 
-PolKitPrivilegeFile *libpolkit_privilege_file_new   (const char          *path, GError **error);
-PolKitPrivilegeFile *libpolkit_privilege_file_ref   (PolKitPrivilegeFile *privilege_file);
-void                 libpolkit_privilege_file_unref (PolKitPrivilegeFile *privilege_file);
+PolKitPrivilegeFile *libpolkit_privilege_file_new         (const char          *path, GError **error);
+PolKitPrivilegeFile *libpolkit_privilege_file_ref         (PolKitPrivilegeFile *privilege_file);
+GSList              *libpolkit_privilege_file_get_entries (PolKitPrivilegeFile *privilege_file);
+void                 libpolkit_privilege_file_unref       (PolKitPrivilegeFile *privilege_file);
 
 #endif /* LIBPOLKIT_PRIVILEGE_FILE_H */
 
diff --git a/libpolkit/libpolkit-privilege.c b/libpolkit/libpolkit-privilege.c
index bc18b55..faf9747 100644
--- a/libpolkit/libpolkit-privilege.c
+++ b/libpolkit/libpolkit-privilege.c
@@ -144,3 +144,16 @@ libpolkit_privilege_get_privilege_id (Po
         *out_privilege_id = privilege->id;
         return TRUE;
 }
+
+/**
+ * libpolkit_privilege_debug:
+ * @privilege: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_privilege_debug (PolKitPrivilege *privilege)
+{
+        g_return_if_fail (privilege != NULL);
+        g_debug ("PolKitPrivilege: refcount=%d id=%s", privilege->refcount, privilege->id);
+}
diff --git a/libpolkit/libpolkit-privilege.h b/libpolkit/libpolkit-privilege.h
index 092f565..bfc4d14 100644
--- a/libpolkit/libpolkit-privilege.h
+++ b/libpolkit/libpolkit-privilege.h
@@ -40,6 +40,8 @@ void             libpolkit_privilege_unr
 void             libpolkit_privilege_set_privilege_id (PolKitPrivilege *privilege, const char  *privilege_id);
 gboolean         libpolkit_privilege_get_privilege_id (PolKitPrivilege *privilege, char       **out_privilege_id);
 
+void             libpolkit_privilege_debug            (PolKitPrivilege *privilege);
+
 #endif /* LIBPOLKIT_PRIVILEGE_H */
 
 
diff --git a/libpolkit/libpolkit-resource.c b/libpolkit/libpolkit-resource.c
index 44f6fa2..1ed4bae 100644
--- a/libpolkit/libpolkit-resource.c
+++ b/libpolkit/libpolkit-resource.c
@@ -192,3 +192,16 @@ libpolkit_resource_get_resource_id (PolK
         *out_resource_id = resource->id;
         return TRUE;
 }
+
+/**
+ * libpolkit_resource_debug:
+ * @resource: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_resource_debug (PolKitResource *resource)
+{
+        g_return_if_fail (resource != NULL);
+        g_debug ("PolKitResource: refcount=%d type=%s id=%s", resource->refcount, resource->type, resource->id);
+}
diff --git a/libpolkit/libpolkit-resource.h b/libpolkit/libpolkit-resource.h
index 91e0a7e..f50b7db 100644
--- a/libpolkit/libpolkit-resource.h
+++ b/libpolkit/libpolkit-resource.h
@@ -42,6 +42,8 @@ void            libpolkit_resource_set_r
 gboolean        libpolkit_resource_get_resource_type (PolKitResource *resource, char       **out_resource_type);
 gboolean        libpolkit_resource_get_resource_id   (PolKitResource *resource, char       **out_resource_id);
 
+void            libpolkit_resource_debug             (PolKitResource *resource);
+
 #endif /* LIBPOLKIT_RESOURCE_H */
 
 
diff --git a/libpolkit/libpolkit-result.c b/libpolkit/libpolkit-result.c
index b04dc10..8d23dd5 100644
--- a/libpolkit/libpolkit-result.c
+++ b/libpolkit/libpolkit-result.c
@@ -52,6 +52,7 @@ static const struct {
         const char *str;
 } mapping[] = 
 {
+        {LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE, "unknown"},
         {LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW, "not_authorized"},
         {LIBPOLKIT_RESULT_YES, "yes"},
         {LIBPOLKIT_RESULT_NO, "no"},
@@ -109,7 +110,6 @@ libpolkit_result_from_string_representat
                 }
         }
 
-        /* don't print a warning; this is used by polkit-privilege-file-validate */
         return FALSE;
 
 found:
diff --git a/libpolkit/libpolkit-result.h b/libpolkit/libpolkit-result.h
index b5b7ed6..7d9ea6f 100644
--- a/libpolkit/libpolkit-result.h
+++ b/libpolkit/libpolkit-result.h
@@ -30,6 +30,7 @@
 
 /**
  * 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.
@@ -51,6 +52,7 @@
  */
 typedef enum
 {
+        LIBPOLKIT_RESULT_UNKNOWN_PRIVILEGE,
         LIBPOLKIT_RESULT_NOT_AUTHORIZED_TO_KNOW,
         LIBPOLKIT_RESULT_YES,
         LIBPOLKIT_RESULT_NO,
diff --git a/libpolkit/libpolkit-seat.c b/libpolkit/libpolkit-seat.c
index 4bbadf9..64e7997 100644
--- a/libpolkit/libpolkit-seat.c
+++ b/libpolkit/libpolkit-seat.c
@@ -142,3 +142,16 @@ libpolkit_seat_get_ck_objref (PolKitSeat
         *out_ck_objref = seat->ck_objref;
         return TRUE;
 }
+
+/**
+ * libpolkit_seat_debug:
+ * @seat: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_seat_debug (PolKitSeat *seat)
+{
+        g_return_if_fail (seat != NULL);
+        g_debug ("PolKitSeat: refcount=%d objpath=%s", seat->refcount, seat->ck_objref);
+}
diff --git a/libpolkit/libpolkit-seat.h b/libpolkit/libpolkit-seat.h
index 27be25b..86f1bc7 100644
--- a/libpolkit/libpolkit-seat.h
+++ b/libpolkit/libpolkit-seat.h
@@ -40,6 +40,8 @@ void        libpolkit_seat_unref        
 void        libpolkit_seat_set_ck_objref (PolKitSeat *seat, const char  *ck_objref);
 gboolean    libpolkit_seat_get_ck_objref (PolKitSeat *seat, char       **out_ck_objref);
 
+void        libpolkit_seat_debug         (PolKitSeat *seat);
+
 #endif /* LIBPOLKIT_SEAT_H */
 
 
diff --git a/libpolkit/libpolkit-session.c b/libpolkit/libpolkit-session.c
index 268faf1..8aa526a 100644
--- a/libpolkit/libpolkit-session.c
+++ b/libpolkit/libpolkit-session.c
@@ -563,3 +563,18 @@ out:
         return session;
 }
 
+/**
+ * libpolkit_session_debug:
+ * @session: the object
+ * 
+ * Print debug details
+ **/
+void
+libpolkit_session_debug (PolKitSession *session)
+{
+        g_return_if_fail (session != NULL);
+        g_debug ("PolKitSession: refcount=%d objpath=%s is_active=%d is_local=%d remote_host=%s", 
+                 session->refcount, session->ck_objref, session->is_active, session->is_local, session->remote_host);
+        if (session->seat != NULL)
+                libpolkit_seat_debug (session->seat);
+}
diff --git a/libpolkit/libpolkit-session.h b/libpolkit/libpolkit-session.h
index 08000bd..1cbafec 100644
--- a/libpolkit/libpolkit-session.h
+++ b/libpolkit/libpolkit-session.h
@@ -55,4 +55,6 @@ gboolean       libpolkit_session_get_ck_
 gboolean       libpolkit_session_get_ck_is_local    (PolKitSession *session, gboolean       *out_is_local);
 gboolean       libpolkit_session_get_ck_remote_host (PolKitSession *session, char          **out_remote_host);
 
+void           libpolkit_session_debug              (PolKitSession *session);
+
 #endif /* LIBPOLKIT_SESSION_H */
diff --git a/libpolkit/libpolkit.c b/libpolkit/libpolkit.c
index 9b03ba5..e12ed96 100644
--- a/libpolkit/libpolkit.c
+++ b/libpolkit/libpolkit.c
@@ -118,7 +118,44 @@ libpolkit_can_session_access_resource (P
                                        PolKitResource  *resource,
                                        PolKitSession   *session)
 {
-        return LIBPOLKIT_RESULT_NO;
+        PolKitPrivilegeCache *cache;
+        PolKitResult result;
+        PolKitPrivilegeFileEntry *pfe;
+
+        result = LIBPOLKIT_RESULT_NO;
+
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        if (cache == NULL)
+                goto out;
+
+        g_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:
+        g_debug ("... result was %s", libpolkit_result_to_string_representation (result));
+        return result;
 }
 
 /**
@@ -139,5 +176,43 @@ libpolkit_can_caller_access_resource (Po
                                       PolKitResource  *resource,
                                       PolKitCaller    *caller)
 {
-        return LIBPOLKIT_RESULT_NO;
+        PolKitPrivilegeCache *cache;
+        PolKitResult result;
+        PolKitPrivilegeFileEntry *pfe;
+
+        result = LIBPOLKIT_RESULT_NO;
+
+        cache = libpolkit_context_get_privilege_cache (pk_context);
+        if (cache == NULL)
+                goto out;
+
+        g_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:
+        g_debug ("... result was %s", libpolkit_result_to_string_representation (result));
+        return result;
 }
diff --git a/privileges/Makefile.am b/privileges/Makefile.am
new file mode 100644
index 0000000..356ed5f
--- /dev/null
+++ b/privileges/Makefile.am
@@ -0,0 +1,17 @@
+
+polkit_privilegedir = $(sysconfdir)/PolicyKit/privileges
+
+dist_polkit_privilege_DATA =
+
+check:
+	for f in $(dist_polkit_privilege_DATA); do \
+          echo "Validating privilege file: $$f"; \
+          $(top_builddir)/tools/polkit-privilege-file-validate --file $(srcdir)/$$f; \
+          if [ "$$?" != "0" ]; then \
+            echo "failed"; \
+            exit 1; \
+          fi; \
+        done
+
+clean-local :
+	rm -f *~
diff --git a/privileges/polkit-example-privilege.priv b/privileges/polkit-example-privilege.priv
new file mode 100644
index 0000000..fb4032c
--- /dev/null
+++ b/privileges/polkit-example-privilege.priv
@@ -0,0 +1,15 @@
+# -*- Conf -*-
+#
+# Example privilege definitions...
+
+[Privilege polkit-example-privilege]
+AllowRemoteInactive=no
+AllowRemoteActive=auth_root_keep_session
+AllowLocalInactive=auth_self_keep_always
+AllowLocalActive=yes
+
+[Privilege polkit-example-privilege2]
+AllowRemoteInactive=no
+AllowRemoteActive=auth_root_keep_session
+AllowLocalInactive=auth_self_keep_always
+AllowLocalActive=yes
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 07c542d..0f7b6c6 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -22,7 +22,6 @@ polkit_check_session_LDADD = @GLIB_LIBS@
 polkit_privilege_file_validate_SOURCES = polkit-privilege-file-validate.c
 polkit_privilege_file_validate_LDADD = @GLIB_LIBS@ $(top_builddir)/libpolkit/libpolkit.la
 
-
 clean-local :
 	rm -f *~
 
diff --git a/tools/polkit-check-caller.c b/tools/polkit-check-caller.c
index abaa53c..e9e7715 100644
--- a/tools/polkit-check-caller.c
+++ b/tools/polkit-check-caller.c
@@ -76,6 +76,7 @@ main (int argc, char *argv[])
         PolKitResource *resource;
         PolKitPrivilege *privilege;
         gboolean allowed;
+        GError *g_error;
 
 	if (argc <= 1) {
 		usage (argc, argv);
@@ -145,7 +146,13 @@ main (int argc, char *argv[])
 		return 1;
 	}
 
-        pol_ctx = libpolkit_context_new ();
+        g_error = NULL;
+        pol_ctx = libpolkit_context_new (&g_error);
+        if (pol_ctx == NULL) {
+		fprintf (stderr, "error: libpolkit_context_new: %s\n", g_error->message);
+                g_error_free (g_error);
+                return 1;
+        }
 
         privilege = libpolkit_privilege_new ();
         libpolkit_privilege_set_privilege_id (privilege, privilege_id);
diff --git a/tools/polkit-check-session.c b/tools/polkit-check-session.c
index 81b2b24..8ee2932 100644
--- a/tools/polkit-check-session.c
+++ b/tools/polkit-check-session.c
@@ -77,6 +77,7 @@ main (int argc, char *argv[])
         PolKitResource *resource;
         PolKitPrivilege *privilege;
         gboolean allowed;
+        GError *g_error;
 
 	if (argc <= 1) {
 		usage (argc, argv);
@@ -148,7 +149,13 @@ main (int argc, char *argv[])
 		return 1;
 	}
 
-        pol_ctx = libpolkit_context_new ();
+        g_error = NULL;
+        pol_ctx = libpolkit_context_new (&g_error);
+        if (pol_ctx == NULL) {
+		fprintf (stderr, "error: libpolkit_context_new: %s\n", g_error->message);
+                g_error_free (g_error);
+                return 1;
+        }
 
         if (session_id != NULL) {
                 session = libpolkit_session_new_from_objpath (bus, session_id, -1, &error);


More information about the hal-commit mailing list