summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <david@fubar.dk>2006-06-05 23:39:00 +0000
committerDavid Zeuthen <david@fubar.dk>2006-06-05 23:39:00 +0000
commit1c3d5691ad444ae2849d079e3745d6b476614623 (patch)
tree0692c2f1eb10b1ea952449d09782cccb826588a6
parent12d20fc8a71b59584f5636ac4dc85c36e45c0157 (diff)
downloadpolkit-1c3d5691ad444ae2849d079e3745d6b476614623.tar.gz
Lots of changes! Almost ready for 0.2 release.
-rw-r--r--ChangeLog73
-rw-r--r--Makefile.am2
-rw-r--r--README1
-rw-r--r--configure.in9
-rw-r--r--doc/TODO37
-rw-r--r--doc/api/polkit-docs.xml3
-rw-r--r--doc/spec/Makefile.am2
-rw-r--r--doc/spec/polkit-spec.html1165
-rw-r--r--doc/spec/polkit-spec.xml.in259
-rw-r--r--libpolkit/Makefile.am27
-rw-r--r--libpolkit/libpolkit-grant.c407
-rw-r--r--libpolkit/libpolkit-grant.h125
-rw-r--r--libpolkit/libpolkit.c60
-rw-r--r--libpolkit/libpolkit.h10
-rw-r--r--pam-polkit-console/Makefile.am18
-rw-r--r--pam-polkit-console/pam-polkit-console.c255
-rw-r--r--polkit-interface-manager.xml22
-rw-r--r--polkit-interface-session.xml3
-rw-r--r--polkit.pc.in4
-rwxr-xr-xpolkitd/PolicyKit.in10
-rw-r--r--polkitd/main.c102
-rw-r--r--polkitd/policy.c480
-rw-r--r--polkitd/policy.h97
-rw-r--r--polkitd/polkit-manager.c375
-rw-r--r--polkitd/polkit-manager.h11
-rw-r--r--polkitd/polkit-session.c61
-rw-r--r--polkitd/polkit-session.h7
-rw-r--r--privileges/desktop-console.privilege12
-rw-r--r--tools/Makefile.am18
-rw-r--r--tools/polkit-grant-privilege.c248
-rw-r--r--tools/polkit-is-privileged.c31
-rw-r--r--tools/polkit-list-privileges.c27
-rw-r--r--tools/polkit-revoke-privilege.c22
33 files changed, 2673 insertions, 1310 deletions
diff --git a/ChangeLog b/ChangeLog
index 48add59..8c14219 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,76 @@
+2006-06-05 David Zeuthen <davidz@redhat.com>
+
+ Lots of changes! Almost ready for 0.2 release.
+
+ * Makefile.am:
+ * README:
+ * configure.in:
+ * doc/TODO:
+ * doc/api/polkit-docs.xml:
+ * doc/spec/Makefile.am:
+ * doc/spec/polkit-spec.html:
+ * doc/spec/polkit-spec.xml.in:
+ * libpolkit/Makefile.am:
+ * libpolkit/libpolkit-grant.c: (have_questions_handler),
+ (libpolkit_grant_provide_answers), (auth_done_handler),
+ (libpolkit_grant_new_context),
+ (libpolkit_grant_get_libpolkit_context),
+ (libpolkit_grant_set_questions_handler),
+ (libpolkit_grant_set_grant_complete_handler),
+ (libpolkit_grant_initiate_temporary_grant),
+ (libpolkit_grant_get_user_for_auth),
+ (libpolkit_grant_get_pam_service_for_auth),
+ (libpolkit_grant_close), (libpolkit_grant_free_context),
+ (libpolkit_grant_get_user), (libpolkit_grant_get_privilege),
+ (libpolkit_grant_get_resource):
+ * libpolkit/libpolkit-grant.h:
+ * libpolkit/libpolkit.c:
+ (libpolkit_get_allowed_resources_for_privilege_for_uid),
+ (libpolkit_is_uid_allowed_for_privilege):
+ * libpolkit/libpolkit.h:
+ * pam-polkit-console/Makefile.am:
+ * pam-polkit-console/pam-polkit-console.c: (_pam_log),
+ (_parse_module_args), (_is_local_xconsole), (_poke_polkitd),
+ (pam_sm_authenticate), (pam_sm_setcred), (pam_sm_open_session),
+ (pam_sm_close_session):
+ * polkit-interface-manager.xml:
+ * polkit-interface-session.xml:
+ * polkit.pc.in:
+ * polkitd/PolicyKit.in:
+ * polkitd/main.c: (handle_sigusr1), (sigusr1_iochn_data), (main):
+ * polkitd/policy.c: (txt_backend_read_policy),
+ (txt_backend_read_list), (txt_backend_read_word),
+ (policy_get_sufficient_privileges),
+ (policy_get_required_privileges),
+ (policy_get_auth_details_for_policy),
+ (_policy_is_uid_gid_allowed_for_policy),
+ (policy_is_uid_gid_allowed_for_policy),
+ (policy_is_uid_allowed_for_policy):
+ * polkitd/policy.h:
+ * polkitd/polkit-manager.c: (_granting_temp_priv),
+ (_revoking_temp_priv), (polkit_manager_error_get_type),
+ (bus_name_owner_changed), (polkit_manager_get_caller_info),
+ (_check_for_temp_privilege),
+ (polkit_manager_initiate_temporary_privilege_grant),
+ (polkit_manager_is_user_privileged),
+ (polkit_manager_get_allowed_resources_for_privilege),
+ (polkit_manager_revoke_temporary_privilege),
+ (polkit_manager_add_temporary_privilege),
+ (polkit_manager_remove_temporary_privilege),
+ (polkit_manager_update_desktop_console_privileges):
+ * polkitd/polkit-manager.h:
+ * polkitd/polkit-session.c: (polkit_session_close),
+ (polkit_session_grant_privilege_temporarily), (polkit_session_new),
+ (polkit_session_initiator_disconnected):
+ * polkitd/polkit-session.h:
+ * privileges/desktop-console.privilege:
+ * tools/Makefile.am:
+ * tools/polkit-grant-privilege.c: (questions_cb),
+ (grant_complete_cb), (main):
+ * tools/polkit-is-privileged.c: (usage), (main):
+ * tools/polkit-list-privileges.c: (main):
+ * tools/polkit-revoke-privilege.c: (main):
+
2006-04-22 David Zeuthen <davidz@redhat.com>
* tools/polkit-list-privileges.c (main): Update to new D-BUS API;
diff --git a/Makefile.am b/Makefile.am
index 3252cdd..414fc91 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = libpolkit polkitd doc tools privileges
+SUBDIRS = libpolkit pam-polkit-console polkitd doc tools privileges
pamdir = $(sysconfdir)/pam.d
pam_DATA = policy-kit
diff --git a/README b/README
index 3c03364..2de5278 100644
--- a/README
+++ b/README
@@ -2,7 +2,6 @@
PolicyKit is a framework for defining policy for system-wide components and
for desktop pieces to configure it. It is used by HAL.
-
See also the file HACKING for notes of interest to developers working
on PolicyKit.
diff --git a/configure.in b/configure.in
index 17e4080..557aa59 100644
--- a/configure.in
+++ b/configure.in
@@ -1,8 +1,8 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
-AC_INIT(PolicyKit, 0.1, david@fubar.dk)
-AM_INIT_AUTOMAKE(PolicyKit, 0.1)
+AC_INIT(PolicyKit, 0.2, david@fubar.dk)
+AM_INIT_AUTOMAKE(PolicyKit, 0.2)
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
@@ -48,7 +48,7 @@ AC_DEFINE_UNQUOTED(POLKIT_GROUP,"$POLKIT_GROUP", [Group for PolicyKit])
# Taken from dbus
AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
-AC_ARG_ENABLE(docbook-docs, [ --enable-docbook-docs build documentation (requires docbook2html)],enable_docbook_docs=$enableval,enable_docbook_docs=auto)
+AC_ARG_ENABLE(docbook-docs, [ --enable-docbook-docs build documentation (requires xmlto)],enable_docbook_docs=$enableval,enable_docbook_docs=auto)
GTK_DOC_CHECK([1.3])
@@ -150,7 +150,7 @@ AC_CHECK_FUNCS(getgrouplist)
# DocBook Documentation
-AC_PATH_PROG(DOCBOOK, docbook2html, no)
+AC_PATH_PROG(XMLTO, xmlto, no)
AC_MSG_CHECKING([whether to build DocBook documentation])
@@ -347,6 +347,7 @@ AC_OUTPUT([
policy-kit
polkit.pc
Makefile
+pam-polkit-console/Makefile
polkitd/Makefile
polkitd/PolicyKit
polkitd/PolicyKit.conf
diff --git a/doc/TODO b/doc/TODO
index 6921cea..ceeab48 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,2 +1,37 @@
-TODO
+DONE
+
+ - Write up a nice spec about how all this works since it can be a bit
+ confusing
+
+ - Refine the .privilege file format so e.g. user 'foo' is always
+ allowed to grant privilege 'bar' to other users. Also other stuff.
+
+ - write polkit-revoke-privilege
+
+ - make polkit-list-privileges and polkit-is-privileged display if a
+ privilege is granted permanently or temporary. Also display if it's
+ confined to a certain D-BUS connection.
+
+ - Factor out auth code in polkit-is-privileged into a GObject and put
+ it in a libpolkit-gobject library (since the interaction is pretty
+ hairy (see interaction diagram in polkitd/polkit-session.c) I will
+ not put this in libpolkit as I want to use the glib bindings and
+ these require the glib main loop => not suitable for Qt etc.)
+
+PENDING
+
+ - Make polkitd emit signals on an interface such that privileged apps
+ can be notified when privileges are granted and revoked. Also
+ export other useful query operations.
+
+ - make D-BUS interface in general and polkit-grant-privilege in
+ particular capable of granting privs permanently
+
+ - write some man pages
+
+ - write libpolkit-gnome that GNOME apps can consume
+
+ - implement D-BUS interfaces suitable for a GUI privilege editor
+
+ - write more tests; audit code
diff --git a/doc/api/polkit-docs.xml b/doc/api/polkit-docs.xml
index 8fceb3b..6d2245b 100644
--- a/doc/api/polkit-docs.xml
+++ b/doc/api/polkit-docs.xml
@@ -7,8 +7,9 @@
</bookinfo>
<chapter>
- <title>Client library</title>
+ <title>Client libraries</title>
<xi:include href="xml/libpolkit.xml"/>
+ <xi:include href="xml/libpolkit-grant.xml"/>
</chapter>
</book>
diff --git a/doc/spec/Makefile.am b/doc/spec/Makefile.am
index dc08beb..e64c56d 100644
--- a/doc/spec/Makefile.am
+++ b/doc/spec/Makefile.am
@@ -9,7 +9,7 @@ htmldocdir = $(DOCDIR)/spec
htmldoc_DATA = polkit-spec.html $(FIGURE_FILES)
polkit-spec.html : polkit-spec.xml $(FIGURE_FILES)
- $(DOCBOOK) --nochunks polkit-spec.xml -o .
+ $(XMLTO) html-nochunks polkit-spec.xml
clean-local:
rm -f *~
diff --git a/doc/spec/polkit-spec.html b/doc/spec/polkit-spec.html
index efcaf12..71d0776 100644
--- a/doc/spec/polkit-spec.html
+++ b/doc/spec/polkit-spec.html
@@ -1,235 +1,14 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<HTML
-><HEAD
-><TITLE
->PolicyKit 0.1 Specification</TITLE
-><META
-NAME="GENERATOR"
-CONTENT="Modular DocBook HTML Stylesheet Version 1.79"></HEAD
-><BODY
-CLASS="book"
-BGCOLOR="#FFFFFF"
-TEXT="#000000"
-LINK="#0000FF"
-VLINK="#840084"
-ALINK="#0000FF"
-><DIV
-CLASS="BOOK"
-><A
-NAME="index"
-></A
-><DIV
-CLASS="TITLEPAGE"
-><H1
-CLASS="title"
-><A
-NAME="AEN2"
->PolicyKit 0.1 Specification</A
-></H1
-><H3
-CLASS="author"
-><A
-NAME="AEN7"
-></A
->David Zeuthen</H3
-><DIV
-CLASS="affiliation"
-><DIV
-CLASS="address"
-><P
-CLASS="address"
-><br>
- &nbsp;&nbsp;&nbsp;&nbsp;<CODE
-CLASS="email"
->&#60;<A
-HREF="mailto:david@fubar.dk"
->david@fubar.dk</A
->&#62;</CODE
-><br>
- &nbsp;&nbsp;</P
-></DIV
-></DIV
-><SPAN
-CLASS="releaseinfo"
->Version 0.1<BR></SPAN
-><HR></DIV
-><DIV
-CLASS="TOC"
-><DL
-><DT
-><B
->Table of Contents</B
-></DT
-><DT
-><A
-HREF="#introduction"
->Introduction</A
-></DT
-><DD
-><DL
-><DT
-><A
-HREF="#AEN15"
->About</A
-></DT
-></DL
-></DD
-><DT
-><A
-HREF="#operation"
->Theory of operation</A
-></DT
-><DD
-><DL
-><DT
-><A
-HREF="#AEN20"
->Privileges</A
-></DT
-><DT
-><A
-HREF="#AEN26"
->Architecture</A
-></DT
-><DT
-><A
-HREF="#AEN37"
->Example</A
-></DT
-></DL
-></DD
-><DT
-><A
-HREF="#resources"
->Resources</A
-></DT
-><DD
-><DL
-><DT
-><A
-HREF="#AEN78"
->Resource Identifiers</A
-></DT
-></DL
-></DD
-><DT
-><A
-HREF="#privileges"
->Privileges</A
-></DT
-><DD
-><DL
-><DT
-><A
-HREF="#AEN88"
->Privilege Descriptors</A
-></DT
-><DT
-><A
-HREF="#AEN102"
->File Format</A
-></DT
-><DD
-><DL
-><DT
-><A
-HREF="#AEN107"
-><TT
-CLASS="literal"
->RequiredPrivileges</TT
->: Required Privileges</A
-></DT
-><DT
-><A
-HREF="#AEN111"
-><TT
-CLASS="literal"
->Allow, Deny</TT
->: Criteria for Possesing a Privilege</A
-></DT
-><DT
-><A
-HREF="#AEN155"
-><TT
-CLASS="literal"
->CanObtain</TT
->: Obtaining Privileges</A
-></DT
-><DT
-><A
-HREF="#AEN165"
-><TT
-CLASS="literal"
->CanGrant</TT
->: Granting Privileges</A
-></DT
-><DT
-><A
-HREF="#AEN177"
-><TT
-CLASS="literal"
->ObtainRequireRoot, ObtainPAMService</TT
->: Authentication Requirements</A
-></DT
-></DL
-></DD
-><DT
-><A
-HREF="#AEN190"
->Privileges defined by PolicyKit</A
-></DT
-></DL
-></DD
-></DL
-></DIV
-><DIV
-CLASS="chapter"
-><HR><H1
-><A
-NAME="introduction"
-></A
->Introduction</H1
-><DIV
-CLASS="sect1"
-><H2
-CLASS="sect1"
-><A
-NAME="AEN15"
->About</A
-></H2
-><P
->&#13; PolicyKit is a system for enabling unprivileged desktop
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>PolicyKit 0.2 Specification</title><meta name="generator" content="DocBook XSL Stylesheets V1.69.1"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="book" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="index"></a>PolicyKit 0.2 Specification</h1></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">David</span> <span class="surname">Zeuthen</span></h3><div class="affiliation"><div class="address"><p><br>
+     <code class="email">&lt;<a href="mailto:david@fubar.dk">david@fubar.dk</a>&gt;</code><br>
+   </p></div></div></div></div></div><div><p class="releaseinfo">Version 0.2</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="chapter"><a href="#introduction">1. Introduction</a></span></dt><dd><dl><dt><span class="sect1"><a href="#id2789999">About</a></span></dt></dl></dd><dt><span class="chapter"><a href="#operation">2. Theory of operation</a></span></dt><dd><dl><dt><span class="sect1"><a href="#id2790022">Privileges</a></span></dt><dt><span class="sect1"><a href="#id2820713">Architecture</a></span></dt><dt><span class="sect1"><a href="#id2785230">Example</a></span></dt></dl></dd><dt><span class="chapter"><a href="#resources">3. Resources</a></span></dt><dd><dl><dt><span class="sect1"><a href="#id2785455">Resource Identifiers</a></span></dt></dl></dd><dt><span class="chapter"><a href="#privileges">4. Privileges</a></span></dt><dd><dl><dt><span class="sect1"><a href="#id2789259">Privilege Descriptors</a></span></dt><dt><span class="sect1"><a href="#id2789336">File Format</a></span></dt><dd><dl><dt><span class="sect2"><a href="#id2789361"><code class="literal">RequiredPrivileges</code>: Required Privileges</a></span></dt><dt><span class="sect2"><a href="#id2789390"><code class="literal">SufficientPrivileges</code>: Sufficient Privileges</a></span></dt><dt><span class="sect2"><a href="#id2789423"><code class="literal">Allow, Deny</code>: Criteria for Possesing a Privilege</a></span></dt><dt><span class="sect2"><a href="#can-obtain"><code class="literal">CanObtain</code>: Obtaining Privileges</a></span></dt><dt><span class="sect2"><a href="#id2785054"><code class="literal">CanGrant</code>: Granting Privileges</a></span></dt><dt><span class="sect2"><a href="#id2829707"><code class="literal">ObtainRequireRoot</code>: Authentication Requirements</a></span></dt></dl></dd><dt><span class="sect1"><a href="#privs-by-polkit">Privileges defined by PolicyKit</a></span></dt><dd><dl><dt><span class="sect2"><a href="#priv-desktop-console"><code class="literal">desktop-console</code> : Users at a local console</a></span></dt></dl></dd></dl></dd></dl></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="introduction"></a>Chapter 1. Introduction</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#id2789999">About</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2789999"></a>About</h2></div></div></div><p>
+ PolicyKit is a system for enabling unprivileged desktop
applications to invoke privileged methods on system-wide
components in a controlled manner.
- </P
-></DIV
-></DIV
-><DIV
-CLASS="chapter"
-><HR><H1
-><A
-NAME="operation"
-></A
->Theory of operation</H1
-><DIV
-CLASS="sect1"
-><H2
-CLASS="sect1"
-><A
-NAME="AEN20"
->Privileges</A
-></H2
-><P
->&#13; One major concept of the PolicyKit system is the notion of
- privileges; a <I
-CLASS="emphasis"
->PolicyKit privilege</I
->
+ </p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="operation"></a>Chapter 2. Theory of operation</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#id2790022">Privileges</a></span></dt><dt><span class="sect1"><a href="#id2820713">Architecture</a></span></dt><dt><span class="sect1"><a href="#id2785230">Example</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2790022"></a>Privileges</h2></div></div></div><p>
+ One major concept of the PolicyKit system is the notion of
+ privileges; a <span class="emphasis"><em>PolicyKit privilege</em></span>
(referred to simply as
- <I
-CLASS="emphasis"
->privilege</I
-> in the following) is something
+ <span class="emphasis"><em>privilege</em></span> in the following) is something
that a given user may or may not possess. The thinking behind
PolicyKit is that privileged system level components offer
functionality to unprivileged desktop applications as D-BUS
@@ -237,693 +16,369 @@ CLASS="emphasis"
a flexible security policy defining the set of users that are
allowed to invoke a method, the system level component defines
a set of
- <I
-CLASS="emphasis"
->privileges</I
->.
- </P
-></DIV
-><DIV
-CLASS="sect1"
-><HR><H2
-CLASS="sect1"
-><A
-NAME="AEN26"
->Architecture</A
-></H2
-><P
->&#13; The PolicyKit system is basically client/server and is
+ <span class="emphasis"><em>privileges</em></span>.
+ </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2820713"></a>Architecture</h2></div></div></div><p>
+ The PolicyKit system is basically client/server and is
implemented as the
- system-wide <TT
-CLASS="literal"
->org.freedesktop.PolicyKit</TT
-> D-BUS
+ system-wide <code class="literal">org.freedesktop.PolicyKit</code> D-BUS
service. This D-BUS service serves two purposes
- </P
-><P
-></P
-><UL
-><LI
-><P
->&#13; System-level components may used D-BUS methods on this
+ </p><div class="itemizedlist"><ul type="disc"><li><p>
+ System-level components may used D-BUS methods on this
service to determine if a given caller of their methods
are privileged.
- </P
-></LI
-><LI
-><P
->&#13; Desktop level applications may initiate a dialogue with
+ </p></li><li><p>
+ Desktop level applications may initiate a dialogue with
this service to (temporarily) obtain a privilege through
authorization.
- </P
-></LI
-></UL
-><P
->&#13; In addition, the PolicyKit system includes client side
+ </p></li></ul></div><p>
+ In addition, the PolicyKit system includes client side
libraries and command-line utilities wrapping the D-BUS API of
- the <TT
-CLASS="literal"
->org.freedesktop.PolicyKit</TT
-> service.
- </P
-></DIV
-><DIV
-CLASS="sect1"
-><HR><H2
-CLASS="sect1"
-><A
-NAME="AEN37"
->Example</A
-></H2
-><P
->&#13; As an example, HAL exports the method <TT
-CLASS="literal"
->Mount</TT
->
+ the <code class="literal">org.freedesktop.PolicyKit</code> service.
+ </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2785230"></a>Example</h2></div></div></div><p>
+ As an example, HAL exports the method <code class="literal">Mount</code>
on the
- <TT
-CLASS="literal"
->org.freedesktop.Hal.Device.Volume</TT
-> interface
+ <code class="literal">org.freedesktop.Hal.Device.Volume</code> interface
for each hal device object of
- capability <I
-CLASS="emphasis"
->volume</I
->. HAL defines a number
+ capability <span class="emphasis"><em>volume</em></span>. HAL defines a number
of privileges for mounting
- including <I
-CLASS="emphasis"
->hal-storage-fixed-mount</I
->
- and <I
-CLASS="emphasis"
->hal-storage-removable-mount</I
->. Depending
+ including <span class="emphasis"><em>hal-storage-fixed-mount</em></span>
+ and <span class="emphasis"><em>hal-storage-removable-mount</em></span>. Depending
on the whether the volume stems from a fixed hard disk or a
hotpluggable/removable drive, HAL requires the calling user to
possess either
- the <I
-CLASS="emphasis"
->hal-storage-fixed-mount</I
->
- or <I
-CLASS="emphasis"
->hal-storage-removable-mount</I
-> privilege
- in order to carry out the <TT
-CLASS="literal"
->Mount</TT
-> method.
- </P
-><P
->&#13; Upon a user invoking the <TT
-CLASS="literal"
->Mount</TT
-> method, HAL
- simply asks the <TT
-CLASS="literal"
->org.freedesktop.PolicyKit</TT
->
- D-BUS service if the calling user posses this privilege and if
- this is not the case the <TT
-CLASS="literal"
->Mount</TT
-> method
+ the <span class="emphasis"><em>hal-storage-fixed-mount</em></span>
+ or <span class="emphasis"><em>hal-storage-removable-mount</em></span> privilege
+ in order to carry out the <code class="literal">Mount</code> method.
+ </p><p>
+ Upon a user invoking the <code class="literal">Mount</code> method, HAL
+ simply asks the <code class="literal">org.freedesktop.PolicyKit</code>
+ D-BUS service if the calling user possess this privilege and if
+ this is not the case the <code class="literal">Mount</code> method
throws
- the <TT
-CLASS="literal"
->org.freedesktop.Hal.Device.PermissionDeniedByPolicy</TT
->
+ the <code class="literal">org.freedesktop.Hal.Device.PermissionDeniedByPolicy</code>
exception. Notably, this exception will tell the caller what
privilege the calling user needs to possess,
- e.g. either <I
-CLASS="emphasis"
->hal-storage-fixed-mount</I
->
- or <I
-CLASS="emphasis"
->hal-storage-removable-mount</I
->.
- </P
-><P
->&#13; Should the <TT
-CLASS="literal"
->Mount</TT
-> method fail with the
- exception <TT
-CLASS="literal"
->PermissionDeniedByPolicy</TT
-> the
+ e.g. either <span class="emphasis"><em>hal-storage-fixed-mount</em></span>
+ or <span class="emphasis"><em>hal-storage-removable-mount</em></span>.
+ </p><p>
+ Should the <code class="literal">Mount</code> method fail with the
+ exception <code class="literal">PermissionDeniedByPolicy</code> the
caller now knows what privilege is required. The caller can
- now initiate a dialogue with the <TT
-CLASS="literal"
->PolicyKit</TT
->
+ now initiate a dialogue with the <code class="literal">PolicyKit</code>
service to obtain this privilege. This conversation is
basically equivalent to a PAM authentication; in fact the
- <TT
-CLASS="literal"
->PolicyKit</TT
-> service uses PAM under the hood
+ <code class="literal">PolicyKit</code> service uses PAM under the hood
and wraps it in D-BUS calls. For details (like what user to
authenticate as) see XXX. When the caller obtains the
privilege (after successful authentication) he can now
- invoke <TT
-CLASS="literal"
->Mount</TT
-> and after this succeeds he may
- tell the <TT
-CLASS="literal"
->PolicyKit</TT
-> service to release the
+ invoke <code class="literal">Mount</code> and after this succeeds he may
+ tell the <code class="literal">PolicyKit</code> service to release the
privilege for the user as it is no longer needed. Should the
process crash while holding a privilege,
- the <TT
-CLASS="literal"
->PolicyKit</TT
-> service will be notifed and
+ the <code class="literal">PolicyKit</code> service will be notifed and
the privilege will automatically be revoked.
- </P
-><P
->&#13; Hence, <TT
-CLASS="literal"
->PolicyKit</TT
-> has the notion of
- both <I
-CLASS="emphasis"
->permament</I
->
- and <I
-CLASS="emphasis"
->temporary</I
-> privileges. The latter may
+ </p><p>
+ Hence, <code class="literal">PolicyKit</code> has the notion of
+ both <span class="emphasis"><em>permament</em></span>
+ and <span class="emphasis"><em>temporary</em></span> privileges. The latter may
even be restricted such that only callers from the D-BUS
connection (remember, D-BUS connections has unique names)
- obtaining the privilege may use the obtained privilege.
- </P
-><P
->&#13; In addition, privileges may be restricted to
- certain <I
-CLASS="emphasis"
->resources</I
->; this is discussed in
+ obtaining the privilege may use the obtained
+ privilege. Consequently, if a temporary privilege is
+ restricted to a certain D-BUS connection, it is revoked when
+ the owner of this connection disconnects from the system
+ message bus.
+ </p><p>
+ In addition, privileges may be restricted to
+ certain <span class="emphasis"><em>resources</em></span>; this is discussed in
more detail in XXX.
- </P
-><P
->&#13; <IMG
-SRC="polkit-arch.png">
- </P
-><P
->&#13; The whole example is outlined in the diagram above.
- </P
-></DIV
-></DIV
-><DIV
-CLASS="chapter"
-><HR><H1
-><A
-NAME="resources"
-></A
->Resources</H1
-><P
->&#13; PolicyKit allows granting privileges only on
- certain <I
-CLASS="emphasis"
->resources</I
->. For example, for HAL, it
+ </p><p>
+ <img src="polkit-arch.png">
+ </p><p>
+ The whole example is outlined in the diagram above.
+ </p></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="resources"></a>Chapter 3. Resources</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#id2785455">Resource Identifiers</a></span></dt></dl></div><p>
+ PolicyKit allows granting privileges only on
+ certain <span class="emphasis"><em>resources</em></span>. For example, for HAL, it
is possible to grant the
- privilege <I
-CLASS="emphasis"
->hal-storage-fixed-mount</I
-> to the
+ privilege <span class="emphasis"><em>hal-storage-fixed-mount</em></span> to the
user with uid 500 but only for the HAL device object
- representing e.g. the <TT
-CLASS="literal"
->/dev/hda3</TT
-> partition.
- </P
-><DIV
-CLASS="sect1"
-><HR><H2
-CLASS="sect1"
-><A
-NAME="AEN78"
->Resource Identifiers</A
-></H2
-><P
-> Resource identifers are prefixed with a name identifying
+ representing e.g. the <code class="literal">/dev/hda3</code> partition.
+ </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2785455"></a>Resource Identifiers</h2></div></div></div><p> Resource identifers are prefixed with a name identifying
what service they belong to. The following resource
identifiers are defined
- </P
-><P
-></P
-><UL
-><LI
-><P
->&#13; <TT
-CLASS="literal"
->hal://</TT
->
- HAL Unique Device Identifiers also known as HAL UID's. Example: <TT
-CLASS="literal"
->hal:///org/freedesktop/Hal/devices/volume_uuid_1a28b356_9955_44f9_b268_6ed6639978f5</TT
->
- </P
-></LI
-></UL
-></DIV
-></DIV
-><DIV
-CLASS="chapter"
-><HR><H1
-><A
-NAME="privileges"
-></A
->Privileges</H1
-><DIV
-CLASS="sect1"
-><H2
-CLASS="sect1"
-><A
-NAME="AEN88"
->Privilege Descriptors</A
-></H2
-><P
->
- Applications, such as HAL, installs <I
-CLASS="emphasis"
->privilege descriptors</I
-> using the <TT
-CLASS="literal"
->polkit-policy-descriptor-install</TT
-> commandline utility. The descriptor contains the following information
- </P
-><P
-></P
-><UL
-><LI
-><P
->&#13; Criteria for determining if a given user possess the privilege on a given resource.
- </P
-></LI
-><LI
-><P
->&#13; What other privileges a given user must also possess.
- </P
-></LI
-><LI
-><P
->&#13; Information on whether the user can obtain the privilege, and if he can, whether only temporarily or permanently.
- </P
-></LI
-><LI
-><P
->&#13; Whether a user with the privilege may permanently grant it to other users.
- </P
-></LI
-></UL
-></DIV
-><DIV
-CLASS="sect1"
-><HR><H2
-CLASS="sect1"
-><A
-NAME="AEN102"
->File Format</A
-></H2
-><P
->&#13; A developer of a system-wide application wanting to define a
+ </p><div class="itemizedlist"><ul type="disc"><li><p>
+ <code class="literal">hal://</code>
+ HAL Unique Device Identifiers also known as HAL UID's. Example: <code class="literal">hal:///org/freedesktop/Hal/devices/volume_uuid_1a28b356_9955_44f9_b268_6ed6639978f5</code>
+ </p></li></ul></div></div></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="privileges"></a>Chapter 4. Privileges</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#id2789259">Privilege Descriptors</a></span></dt><dt><span class="sect1"><a href="#id2789336">File Format</a></span></dt><dd><dl><dt><span class="sect2"><a href="#id2789361"><code class="literal">RequiredPrivileges</code>: Required Privileges</a></span></dt><dt><span class="sect2"><a href="#id2789390"><code class="literal">SufficientPrivileges</code>: Sufficient Privileges</a></span></dt><dt><span class="sect2"><a href="#id2789423"><code class="literal">Allow, Deny</code>: Criteria for Possesing a Privilege</a></span></dt><dt><span class="sect2"><a href="#can-obtain"><code class="literal">CanObtain</code>: Obtaining Privileges</a></span></dt><dt><span class="sect2"><a href="#id2785054"><code class="literal">CanGrant</code>: Granting Privileges</a></span></dt><dt><span class="sect2"><a href="#id2829707"><code class="literal">ObtainRequireRoot</code>: Authentication Requirements</a></span></dt></dl></dd><dt><span class="sect1"><a href="#privs-by-polkit">Privileges defined by PolicyKit</a></span></dt><dd><dl><dt><span class="sect2"><a href="#priv-desktop-console"><code class="literal">desktop-console</code> : Users at a local console</a></span></dt></dl></dd></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2789259"></a>Privilege Descriptors</h2></div></div></div><p>
+ Applications, such as HAL, installs <span class="emphasis"><em>privilege
+ descriptors</em></span> into
+ the <code class="literal">/etc/PolicyKit/privilege.d</code> directory
+ (or more correct, into
+ the <code class="literal">$sysconfdir/PolicyKit/privilege.d</code>
+ directory depending on where PolicyKit is built).
+ </p><p>
+ A policy descriptor contains the following information:
+ </p><div class="itemizedlist"><ul type="disc"><li><p>
+ Criteria for determining if a given user possess the privilege on a given resource.
+ </p></li><li><p>
+ What privileges are required to possess a given privilege.
+ </p></li><li><p>
+ What privileges are sufficient to possess to automatically possess a given privilege.
+ </p></li><li><p>
+ Information on whether the user can obtain the privilege, and if he can, whether only temporarily or permanently.
+ </p></li><li><p>
+ Whether a user with the privilege may permanently grant it to other users.
+ </p></li></ul></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id2789336"></a>File Format</h2></div></div></div><p>
+ A developer of a system-wide application wanting to define a
privilege must create a privilege descriptor. This is a a
- simple <TT
-CLASS="literal"
->.ini</TT
->-like config file. Here is what
+ simple <code class="literal">.ini</code>-like config file. Here is what
the skeleton looks like:
- </P
-><TABLE
-BORDER="0"
-BGCOLOR="#E0E0E0"
-WIDTH="100%"
-><TR
-><TD
-><PRE
-CLASS="programlisting"
->&#13; [Policy]
+ </p><pre class="programlisting">
+ [Policy]
RequiredPrivileges=
+ SufficientPrivileges=
Allow=
Deny=
CanObtain=
CanGrant=
ObtainRequireRoot=
- ObtainPAMService=
- </PRE
-></TD
-></TR
-></TABLE
-><DIV
-CLASS="sect2"
-><HR><H3
-CLASS="sect2"
-><A
-NAME="AEN107"
-><TT
-CLASS="literal"
->RequiredPrivileges</TT
->: Required Privileges</A
-></H3
-><P
->&#13; This is a list of privileges the user must possess in order
+ </pre><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2789361"></a><code class="literal">RequiredPrivileges</code>: Required Privileges</h3></div></div></div><p>
+ This is a list of privileges the user must possess in order
to possess the given privilege. If the user doesn't possess
all of these privileges he is not considered to possess the
- given privilege. The list may be empty.
- </P
-></DIV
-><DIV
-CLASS="sect2"
-><HR><H3
-CLASS="sect2"
-><A
-NAME="AEN111"
-><TT
-CLASS="literal"
->Allow, Deny</TT
->: Criteria for Possesing a Privilege</A
-></H3
-><P
->&#13; Both <TT
-CLASS="literal"
->Allow</TT
-> and <TT
-CLASS="literal"
->Deny</TT
->
+ given privilege. The list may be empty. A privilege in this
+ list is considered being possessed if the user is privileged
+ for one or more resources. E.g., if <code class="literal">foo</code>
+ is a required privilege then just having this privilege on
+ one resource is sufficient.
+ </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2789390"></a><code class="literal">SufficientPrivileges</code>: Sufficient Privileges</h3></div></div></div><p>
+ This is a list of privileges that, if a user possess any of
+ these, he is consider to possess the given privilege. The
+ list may be empty. A privilege in this list is considered
+ being possessed if the user is privileged for one or more
+ resources. As with <code class="literal">RequiredPrivileges</code>,
+ if <code class="literal">foo</code> is a sufficient privilege then
+ just having this privilege on one resource is sufficient.
+ </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2789423"></a><code class="literal">Allow, Deny</code>: Criteria for Possesing a Privilege</h3></div></div></div><p>
+ Both <code class="literal">Allow</code> and <code class="literal">Deny</code>
contains lists describing what users are allowed
respectively denied the privilege. The elements of in each
list are of the form
- <TT
-CLASS="literal"
->type:value[:resource]</TT
->. where the last
+ <code class="literal">type:value[:resource]</code>. where the last
part, resource, may be omitted. The following types are
supported:
- </P
-><P
-></P
-><UL
-><LI
-><P
-><TT
-CLASS="literal"
->uid</TT
->: Unix user identifer; either
+ </p><div class="itemizedlist"><ul type="disc"><li><p><code class="literal">uid</code>: Unix user identifer; either
a positive integer or Unix username. Special values
- include <TT
-CLASS="literal"
->__all__</TT
-> (for denoting all
- users) and <TT
-CLASS="literal"
->__none__</TT
-> (for denoting no
- users).</P
-></LI
-><LI
-><P
-><TT
-CLASS="literal"
->gid</TT
->: Unix group identifier,
+ include <code class="literal">__all__</code> (for denoting all
+ users) and <code class="literal">__none__</code> (for denoting no
+ users).</p></li><li><p><code class="literal">gid</code>: Unix group identifier,
either a positive integer or Unix groupname. Special
- values include <TT
-CLASS="literal"
->__all__</TT
-> (for denoting
- all groups) and <TT
-CLASS="literal"
->__none__</TT
-> (for denoting
- no groups).</P
-></LI
-></UL
-><P
->&#13; To determine if a given user is allowed for a given
+ values include <code class="literal">__all__</code> (for denoting
+ all groups) and <code class="literal">__none__</code> (for denoting
+ no groups).</p></li></ul></div><p>
+ To determine if a given user is allowed for a given
privilege (for a given resource), first
- the <TT
-CLASS="literal"
->RequiredPrivileges</TT
-> list is consulted
- as described above. If the user possess all of the listed
- privileges, the <TT
-CLASS="literal"
->Allow</TT
-> list is now
- consulted. For each element we it is tested whether the user
- matches. If there are no elements for which the user is
+ the <code class="literal">SufficientPrivileges</code> list is
+ consulted as described above. If the user possesses one or
+ more of the listed privileges we're done; the user is
+ automatically allowed for the given privilege. If this is
+ not the case, the <code class="literal">RequiredPrivileges</code> list
+ is consulted as described above. If the user possess all of
+ the listed privileges, the <code class="literal">Allow</code> list is
+ now consulted. For each element it is tested whether the
+ user matches. If there are no elements for which the user is
matches, the user is said not to possess the given privilege
(for the given resource).
- </P
-><P
->&#13; If there is a match in the <TT
-CLASS="literal"
->Allow</TT
-> list,
- the <TT
-CLASS="literal"
->Deny</TT
-> list is now consulted. If the
+ </p><p>
+ If there is a match in the <code class="literal">Allow</code> list,
+ the <code class="literal">Deny</code> list is now consulted. If the
user matches any of the elements we know he doesn't possess
the given privilege. If no elements match we can conclude
that the user indeed possesses the given privilege (for the
given resource).
- </P
-><P
->&#13; This logic is best described by a few examples
- </P
-><P
-></P
-><UL
-><LI
-><P
->&#13; <TT
-CLASS="literal"
->&#13; Allow="uid:davidz uid:501:hal:///deviceFoo gid:admins
+ </p><p>
+ This logic is best described by a few examples
+ </p><div class="itemizedlist"><ul type="disc"><li><p>
+ <code class="literal">
+ Allow="uid:davidz uid:501:hal:///deviceFoo gid:admins
uid:502"
- </TT
->
- </P
-><P
->&#13; <TT
-CLASS="literal"
->&#13; Deny="gid:dooders uid:502:hal:///deviceBar"
- </TT
->
- </P
-><P
->&#13; User <TT
-CLASS="literal"
->davidz</TT
-> possess this
+ </code>
+ </p><p>
+ <code class="literal">
+ Deny="gid:dooders uid:502:hal:///deviceBar"
+ </code>
+ </p><p>
+ User <code class="literal">davidz</code> possess this
privilege. All members of
- the <TT
-CLASS="literal"
->dooders</TT
-> group is denied this
+ the <code class="literal">dooders</code> group is denied this
privilege. User 501 is allowed this privilege but only
- on the <TT
-CLASS="literal"
->hal:///deviceFoo</TT
->
- resource. All users in the <TT
-CLASS="literal"
->admin</TT
->
+ on the <code class="literal">hal:///deviceFoo</code>
+ resource. All users in the <code class="literal">admin</code>
group posseses the privilege. User 502 is allowed this
privilege but not on
- the <TT
-CLASS="literal"
->hal:///deviceBar</TT
->
+ the <code class="literal">hal:///deviceBar</code>
resource.
- </P
-></LI
-><LI
-><P
->&#13; <TT
-CLASS="literal"
->&#13; Allow="uid:__all__"
- </TT
->
- </P
-><P
->&#13; <TT
-CLASS="literal"
->&#13; Deny="gid:normalstaff"
- </TT
->
- </P
-><P
->&#13; All users expect those in
- the <TT
-CLASS="literal"
->normalstaff</TT
-> group posseses this
+ </p></li><li><p>
+ <code class="literal">
+ Allow="uid:__all__"
+ </code>
+ </p><p>
+ <code class="literal">
+ Deny="gid:normalstaff"
+ </code>
+ </p><p>
+ All users expect those in
+ the <code class="literal">normalstaff</code> group posseses this
privilege.
- </P
-></LI
-></UL
-></DIV
-><DIV
-CLASS="sect2"
-><HR><H3
-CLASS="sect2"
-><A
-NAME="AEN155"
-><TT
-CLASS="literal"
->CanObtain</TT
->: Obtaining Privileges</A
-></H3
-><P
->&#13; This property denotes whether an user can obtain the
- privilege by authentication. It can assume the values
- <TT
-CLASS="literal"
->True</TT
-> (the user can obtain the privilege
- permanently), <TT
-CLASS="literal"
->Temporary</TT
-> (the user can
+ </p></li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="can-obtain"></a><code class="literal">CanObtain</code>: Obtaining Privileges</h3></div></div></div><p>
+ This property denotes whether an user can obtain the
+ privilege by authentication. This is useful when either
+ either the privilege in question or one of the privileges
+ listed in <code class="literal">RequiredPrivileges</code> is not
+ possessed.
+ </p><p>
+ The property can assume the values
+ <code class="literal">True</code> (the user can obtain the privilege
+ permanently), <code class="literal">Temporary</code> (the user can
only obtain the privilege temporarily) and
- <TT
-CLASS="literal"
->False</TT
-> (the user can never obtain the
- privilege through authentication).
- </P
-><P
->&#13; The authentication required are specified in
- the <TT
-CLASS="literal"
->ObtainRequireRoot</TT
->
- and <TT
-CLASS="literal"
->ObtainPAMService</TT
-> properties.
- </P
-></DIV
-><DIV
-CLASS="sect2"
-><HR><H3
-CLASS="sect2"
-><A
-NAME="AEN165"
-><TT
-CLASS="literal"
->CanGrant</TT
->: Granting Privileges</A
-></H3
-><P
->&#13; This property (it can assume the
- values <TT
-CLASS="literal"
->True</TT
-> and <TT
-CLASS="literal"
->False</TT
->)
- describes whether an user with the given privilege can grant
- it to other users, e.g. modify the <TT
-CLASS="literal"
->Allow</TT
->
- and <TT
-CLASS="literal"
->Deny</TT
-> properties.
- </P
-><P
->&#13; The property <TT
-CLASS="literal"
->CanObtain</TT
-> needs to have the
- value <TT
-CLASS="literal"
->True</TT
-> if this property assumes the
- value <TT
-CLASS="literal"
->True</TT
->.
- </P
-></DIV
-><DIV
-CLASS="sect2"
-><HR><H3
-CLASS="sect2"
-><A
-NAME="AEN177"
-><TT
-CLASS="literal"
->ObtainRequireRoot, ObtainPAMService</TT
->: Authentication Requirements</A
-></H3
-><P
->&#13; If the property <TT
-CLASS="literal"
->CanObtain</TT
-> assumes the
- value <TT
-CLASS="literal"
->True</TT
->
- or <TT
-CLASS="literal"
->Temporary</TT
-> it means the user can
- authenticate to gain a privilege.
- </P
-><P
->&#13; The <TT
-CLASS="literal"
->ObtainRequireRoot</TT
-> property specifies
- whether authentication requires the super user password
- (<TT
-CLASS="literal"
->True</TT
->) or the users own password
- (<TT
-CLASS="literal"
->False</TT
->). In addition, it can be specified
- what PAM service (for example <TT
-CLASS="literal"
->pam_rps</TT
->) is
- to be used for authentication through the
- property <TT
-CLASS="literal"
->ObtainPAMService</TT
->.
- </P
-></DIV
-></DIV
-><DIV
-CLASS="sect1"
-><HR><H2
-CLASS="sect1"
-><A
-NAME="AEN190"
->Privileges defined by PolicyKit</A
-></H2
-><P
->&#13; baz
- </P
-></DIV
-></DIV
-></DIV
-></BODY
-></HTML
-> \ No newline at end of file
+ <code class="literal">False</code> (the user can never obtain the
+ privilege through authentication).
+ </p><p>
+ Whether the user needs to autenticate as himself or the
+ super user is specified in
+ the <code class="literal">ObtainRequireRoot</code> property. Note that
+ if the user is lacking one or more of the privileges listed
+ in <code class="literal">RequiredPrivileges</code> and one of these
+ has <code class="literal">ObtainRequireRoot=True</code> the user will
+ have to authenticate as the super user nonwithstanding that
+ the privilege he attempts to obtain
+ has <code class="literal">ObtainRequireRoot=False</code>. Moreover, if
+ any of the lacking privileges
+ in <code class="literal">RequiredPrivileges</code>
+ has <code class="literal">CanObtain</code> set
+ to <code class="literal">False</code>, the user will always have to
+ authenticate as the super user.
+ </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2785054"></a><code class="literal">CanGrant</code>: Granting Privileges</h3></div></div></div><p>
+ This property (it can assume the
+ values <code class="literal">True</code> and <code class="literal">False</code>)
+ describes whether an user with the given privilege can
+ permanently grant it to himself and/or other users,.
+ </p><p>
+ Typically, the construct is used in the following kind of UI
+ dialogs:
+ </p><pre class="programlisting">
+ +----------------------------------------------------+
+ | You are not privileged to access the volume |
+ | 'Dave's USB key'. You need to authenticate as the |
+ | system administrator |
+ | |
+ | Super user password: [_______________] |
+ | |
+ | Would you also like to automatically allow |
+ | |
+ | (*) This user to mount 'Dave's USB key' |
+ | ( ) Any user to mount 'Dave's USB key' |
+ | ( ) This user to mount a removable storage device |
+ | ( ) Any user to mount a removable storage device |
+ | |
+ | [Cancel] [Mount] |
+ +----------------------------------------------------+
+ (TODO: replace with screenshot from gnome-mount)
+ </pre><p>
+ The property <code class="literal">CanObtain</code> needs to assume
+ the value <code class="literal">True</code> if this property assumes
+ the value <code class="literal">True</code>. Otherwise this property
+ effectively assumes the value <code class="literal">False</code>.
+ </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2829707"></a><code class="literal">ObtainRequireRoot</code>: Authentication Requirements</h3></div></div></div><p>
+ If the property <code class="literal">CanObtain</code> assumes the
+ value <code class="literal">True</code>
+ or <code class="literal">Temporary</code> it means the user can
+ authenticate to gain a
+ privilege. The <code class="literal">ObtainRequireRoot</code> property
+ specifies whether authentication requires the super user
+ password (<code class="literal">True</code>) or the users own password
+ (<code class="literal">False</code>).
+ </p><p>
+ See <a href="#can-obtain" title="CanObtain: Obtaining Privileges">the section called &#8220;<code class="literal">CanObtain</code>: Obtaining Privileges&#8221;</a> for discussion on how
+ the <code class="literal">RequiredPrivileges</code> property affects
+ the effective value of this property.
+ </p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="privs-by-polkit"></a>Privileges defined by PolicyKit</h2></div></div></div><p>
+ This section describe privileges defined by PolicyKit and how
+ they can be used by other pieces of software. Some privileges
+ have special meaning and affects how PolicyKit works.
+ </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="priv-desktop-console"></a><code class="literal">desktop-console</code> : Users at a local console</h3></div></div></div><pre class="programlisting">
+desktop-console.privilege:
+
+# This privilege signfies that users holding it are logged into a
+# physical console attached to the system. Thus, it is useful for
+# other privileges for manipulating local devices to simply require
+# this privilege.
+
+[Privilege]
+RequiredPrivileges=
+SufficientPrivileges=
+Allow=
+Deny=
+CanObtain=Temporary
+CanGrant=False
+ObtainRequireRoot=True
+ </pre><p>
+ This privilege signifies that the user holding it is logged
+ in at a local console. In this context, "local console"
+ means that the display / keyboard / pointing device is local
+ to the system which implies the user got physical access to
+ the box.
+ </p><p>
+ The PAM module <code class="literal">pam-polkit-console</code> shipped
+ with PolicyKit is used to maintain files
+ in <code class="literal">/var/run/polkit-console</code> for users
+ logging in and out, and signal the PolicyKit daemon to
+ reread these files and dynamically grant / revoke
+ the <code class="literal">desktop-console</code> privilege. Typically,
+ graphical login managers such as the GNOME Display Manager
+ (gdm) will want include this in it's stack of PAM modules.
+ </p><p>
+ Remote users (e.g. those not at a local console) can obtain
+ the <code class="literal">desktop-console</code> only by
+ authenticating as the super user.
+ </p><p>
+ The <code class="literal">desktop-console</code> privilege can be used
+ in conjunction with
+ the <code class="literal">RequiredPrivileges</code> property in a
+ privilege descriptor to ensure only users at a local console
+ is entitled to a privilege for putting a system to sleep
+ without having to autenticate. This is achieved by e.g. this
+ privilege descriptor:
+ </p><pre class="programlisting">
+hal-system-suspend.privilege:
+
+# This privilege specifies who is allowed to suspend the system.
+
+[Privilege]
+RequiredPrivileges=desktop-console
+SufficientPrivileges=
+Allow=uid:__all__
+Deny=
+CanObtain=True
+CanGrant=True
+ObtainRequireRoot=False
+ </pre><p>
+ For a remote user with the
+ privilege <code class="literal">hal-system-suspend</code> it means
+ that authentication as the super user is required
+ as <code class="literal">desktop-console</code>
+ has <code class="literal">ObtainRequireRoot=True</code> and this
+ trumps the <code class="literal">ObtainRequireRoot=False</code>
+ property that is in
+ the <code class="literal">hal-system-suspend</code> privilege (see
+ <a href="#can-obtain" title="CanObtain: Obtaining Privileges">the section called &#8220;<code class="literal">CanObtain</code>: Obtaining Privileges&#8221;</a>). Of course, if the user is
+ logged in at a local console no authentication is required.
+ </p><p>
+ Typically, the <code class="literal">desktop-console</code> privilege
+ is granted on a specific resource, namely what console the
+ user is logged into. At the time of writing, this resource
+ can only be consider an opaque identifier (such
+ as <code class="literal">console://:0</code> which refers to X11
+ display ":0") and one cannot assign meaning to it. In the
+ future, it may be possible to assign meaning to it.
+ </p></div></div></div></div></body></html>
diff --git a/doc/spec/polkit-spec.xml.in b/doc/spec/polkit-spec.xml.in
index 3111c91..ddc4277 100644
--- a/doc/spec/polkit-spec.xml.in
+++ b/doc/spec/polkit-spec.xml.in
@@ -6,9 +6,9 @@
<book id="index">
<bookinfo>
- <title>PolicyKit 0.1 Specification</title>
- <releaseinfo>Version 0.1</releaseinfo>
- <date>March 28th, 2006</date> <!-- Update this manually -->
+ <title>PolicyKit 0.2 Specification</title>
+ <releaseinfo>Version 0.2</releaseinfo>
+ <date>May 12th, 2006</date> <!-- Update this manually -->
<authorgroup>
<author>
<firstname>David</firstname>
@@ -120,7 +120,7 @@
<para>
Upon a user invoking the <literal>Mount</literal> method, HAL
simply asks the <literal>org.freedesktop.PolicyKit</literal>
- D-BUS service if the calling user posses this privilege and if
+ D-BUS service if the calling user possess this privilege and if
this is not the case the <literal>Mount</literal> method
throws
the <literal>org.freedesktop.Hal.Device.PermissionDeniedByPolicy</literal>
@@ -155,7 +155,11 @@
and <emphasis>temporary</emphasis> privileges. The latter may
even be restricted such that only callers from the D-BUS
connection (remember, D-BUS connections has unique names)
- obtaining the privilege may use the obtained privilege.
+ obtaining the privilege may use the obtained
+ privilege. Consequently, if a temporary privilege is
+ restricted to a certain D-BUS connection, it is revoked when
+ the owner of this connection disconnects from the system
+ message bus.
</para>
<para>
@@ -215,8 +219,17 @@
<sect1>
<title>Privilege Descriptors</title>
- <para>
- Applications, such as HAL, installs <emphasis>privilege descriptors</emphasis> using the <literal>polkit-policy-descriptor-install</literal> commandline utility. The descriptor contains the following information
+ <para>
+ Applications, such as HAL, installs <emphasis>privilege
+ descriptors</emphasis> into
+ the <literal>/etc/PolicyKit/privilege.d</literal> directory
+ (or more correct, into
+ the <literal>$sysconfdir/PolicyKit/privilege.d</literal>
+ directory depending on where PolicyKit is built).
+ </para>
+
+ <para>
+ A policy descriptor contains the following information:
</para>
<itemizedlist>
@@ -228,7 +241,13 @@
<listitem>
<para>
- What other privileges a given user must also possess.
+ What privileges are required to possess a given privilege.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ What privileges are sufficient to possess to automatically possess a given privilege.
</para>
</listitem>
@@ -259,12 +278,12 @@
<programlisting>
[Policy]
RequiredPrivileges=
+ SufficientPrivileges=
Allow=
Deny=
CanObtain=
CanGrant=
ObtainRequireRoot=
- ObtainPAMService=
</programlisting>
<sect2>
@@ -273,7 +292,24 @@
This is a list of privileges the user must possess in order
to possess the given privilege. If the user doesn't possess
all of these privileges he is not considered to possess the
- given privilege. The list may be empty.
+ given privilege. The list may be empty. A privilege in this
+ list is considered being possessed if the user is privileged
+ for one or more resources. E.g., if <literal>foo</literal>
+ is a required privilege then just having this privilege on
+ one resource is sufficient.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><literal>SufficientPrivileges</literal>: Sufficient Privileges</title>
+ <para>
+ This is a list of privileges that, if a user possess any of
+ these, he is consider to possess the given privilege. The
+ list may be empty. A privilege in this list is considered
+ being possessed if the user is privileged for one or more
+ resources. As with <literal>RequiredPrivileges</literal>,
+ if <literal>foo</literal> is a sufficient privilege then
+ just having this privilege on one resource is sufficient.
</para>
</sect2>
@@ -308,11 +344,15 @@
<para>
To determine if a given user is allowed for a given
privilege (for a given resource), first
- the <literal>RequiredPrivileges</literal> list is consulted
- as described above. If the user possess all of the listed
- privileges, the <literal>Allow</literal> list is now
- consulted. For each element we it is tested whether the user
- matches. If there are no elements for which the user is
+ the <literal>SufficientPrivileges</literal> list is
+ consulted as described above. If the user possesses one or
+ more of the listed privileges we're done; the user is
+ automatically allowed for the given privilege. If this is
+ not the case, the <literal>RequiredPrivileges</literal> list
+ is consulted as described above. If the user possess all of
+ the listed privileges, the <literal>Allow</literal> list is
+ now consulted. For each element it is tested whether the
+ user matches. If there are no elements for which the user is
matches, the user is said not to possess the given privilege
(for the given resource).
</para>
@@ -378,22 +418,42 @@
</sect2>
- <sect2>
+ <sect2 id="can-obtain">
<title><literal>CanObtain</literal>: Obtaining Privileges</title>
<para>
This property denotes whether an user can obtain the
- privilege by authentication. It can assume the values
+ privilege by authentication. This is useful when either
+ either the privilege in question or one of the privileges
+ listed in <literal>RequiredPrivileges</literal> is not
+ possessed.
+ </para>
+
+ <para>
+ The property can assume the values
<literal>True</literal> (the user can obtain the privilege
permanently), <literal>Temporary</literal> (the user can
only obtain the privilege temporarily) and
<literal>False</literal> (the user can never obtain the
- privilege through authentication).
+ privilege through authentication).
</para>
+
<para>
- The authentication required are specified in
- the <literal>ObtainRequireRoot</literal>
- and <literal>ObtainPAMService</literal> properties.
+ Whether the user needs to autenticate as himself or the
+ super user is specified in
+ the <literal>ObtainRequireRoot</literal> property. Note that
+ if the user is lacking one or more of the privileges listed
+ in <literal>RequiredPrivileges</literal> and one of these
+ has <literal>ObtainRequireRoot=True</literal> the user will
+ have to authenticate as the super user nonwithstanding that
+ the privilege he attempts to obtain
+ has <literal>ObtainRequireRoot=False</literal>. Moreover, if
+ any of the lacking privileges
+ in <literal>RequiredPrivileges</literal>
+ has <literal>CanObtain</literal> set
+ to <literal>False</literal>, the user will always have to
+ authenticate as the super user.
</para>
+
</sect2>
<sect2>
@@ -401,43 +461,166 @@
<para>
This property (it can assume the
values <literal>True</literal> and <literal>False</literal>)
- describes whether an user with the given privilege can grant
- it to other users, e.g. modify the <literal>Allow</literal>
- and <literal>Deny</literal> properties.
+ describes whether an user with the given privilege can
+ permanently grant it to himself and/or other users,.
+ </para>
+ <para>
+ Typically, the construct is used in the following kind of UI
+ dialogs:
</para>
+
+ <programlisting>
+ +----------------------------------------------------+
+ | You are not privileged to access the volume |
+ | 'Dave's USB key'. You need to authenticate as the |
+ | system administrator |
+ | |
+ | Super user password: [_______________] |
+ | |
+ | Would you also like to automatically allow |
+ | |
+ | (*) This user to mount 'Dave's USB key' |
+ | ( ) Any user to mount 'Dave's USB key' |
+ | ( ) This user to mount a removable storage device |
+ | ( ) Any user to mount a removable storage device |
+ | |
+ | [Cancel] [Mount] |
+ +----------------------------------------------------+
+ (TODO: replace with screenshot from gnome-mount)
+ </programlisting>
+
<para>
- The property <literal>CanObtain</literal> needs to have the
- value <literal>True</literal> if this property assumes the
- value <literal>True</literal>.
+ The property <literal>CanObtain</literal> needs to assume
+ the value <literal>True</literal> if this property assumes
+ the value <literal>True</literal>. Otherwise this property
+ effectively assumes the value <literal>False</literal>.
</para>
</sect2>
<sect2>
- <title><literal>ObtainRequireRoot, ObtainPAMService</literal>: Authentication Requirements</title>
+ <title><literal>ObtainRequireRoot</literal>: Authentication Requirements</title>
<para>
If the property <literal>CanObtain</literal> assumes the
value <literal>True</literal>
or <literal>Temporary</literal> it means the user can
- authenticate to gain a privilege.
+ authenticate to gain a
+ privilege. The <literal>ObtainRequireRoot</literal> property
+ specifies whether authentication requires the super user
+ password (<literal>True</literal>) or the users own password
+ (<literal>False</literal>).
</para>
<para>
- The <literal>ObtainRequireRoot</literal> property specifies
- whether authentication requires the super user password
- (<literal>True</literal>) or the users own password
- (<literal>False</literal>). In addition, it can be specified
- what PAM service (for example <literal>pam_rps</literal>) is
- to be used for authentication through the
- property <literal>ObtainPAMService</literal>.
+ See <xref linkend="can-obtain"/> for discussion on how
+ the <literal>RequiredPrivileges</literal> property affects
+ the effective value of this property.
</para>
</sect2>
</sect1>
- <sect1>
+ <sect1 id="privs-by-polkit">
<title>Privileges defined by PolicyKit</title>
<para>
- baz
+ This section describe privileges defined by PolicyKit and how
+ they can be used by other pieces of software. Some privileges
+ have special meaning and affects how PolicyKit works.
</para>
+
+ <sect2 id="priv-desktop-console">
+ <title><literal>desktop-console</literal> : Users at a local console</title>
+
+ <programlisting>
+desktop-console.privilege:
+
+# This privilege signfies that users holding it are logged into a
+# physical console attached to the system. Thus, it is useful for
+# other privileges for manipulating local devices to simply require
+# this privilege.
+
+[Privilege]
+RequiredPrivileges=
+SufficientPrivileges=
+Allow=
+Deny=
+CanObtain=Temporary
+CanGrant=False
+ObtainRequireRoot=True
+ </programlisting>
+
+ <para>
+ This privilege signifies that the user holding it is logged
+ in at a local console. In this context, "local console"
+ means that the display / keyboard / pointing device is local
+ to the system which implies the user got physical access to
+ the box.
+ </para>
+
+ <para>
+ The PAM module <literal>pam-polkit-console</literal> shipped
+ with PolicyKit is used to maintain files
+ in <literal>/var/run/polkit-console</literal> for users
+ logging in and out, and signal the PolicyKit daemon to
+ reread these files and dynamically grant / revoke
+ the <literal>desktop-console</literal> privilege. Typically,
+ graphical login managers such as the GNOME Display Manager
+ (gdm) will want include this in it's stack of PAM modules.
+ </para>
+
+ <para>
+ Remote users (e.g. those not at a local console) can obtain
+ the <literal>desktop-console</literal> only by
+ authenticating as the super user.
+ </para>
+
+ <para>
+ The <literal>desktop-console</literal> privilege can be used
+ in conjunction with
+ the <literal>RequiredPrivileges</literal> property in a
+ privilege descriptor to ensure only users at a local console
+ is entitled to a privilege for putting a system to sleep
+ without having to autenticate. This is achieved by e.g. this
+ privilege descriptor:
+ </para>
+
+ <programlisting>
+hal-system-suspend.privilege:
+
+# This privilege specifies who is allowed to suspend the system.
+
+[Privilege]
+RequiredPrivileges=desktop-console
+SufficientPrivileges=
+Allow=uid:__all__
+Deny=
+CanObtain=True
+CanGrant=True
+ObtainRequireRoot=False
+ </programlisting>
+
+ <para>
+ For a remote user with the
+ privilege <literal>hal-system-suspend</literal> it means
+ that authentication as the super user is required
+ as <literal>desktop-console</literal>
+ has <literal>ObtainRequireRoot=True</literal> and this
+ trumps the <literal>ObtainRequireRoot=False</literal>
+ property that is in
+ the <literal>hal-system-suspend</literal> privilege (see
+ <xref linkend="can-obtain"/>). Of course, if the user is
+ logged in at a local console no authentication is required.
+ </para>
+
+ <para>
+ Typically, the <literal>desktop-console</literal> privilege
+ is granted on a specific resource, namely what console the
+ user is logged into. At the time of writing, this resource
+ can only be consider an opaque identifier (such
+ as <literal>console://:0</literal> which refers to X11
+ display ":0") and one cannot assign meaning to it. In the
+ future, it may be possible to assign meaning to it.
+ </para>
+ </sect2>
+
</sect1>
</chapter>
diff --git a/libpolkit/Makefile.am b/libpolkit/Makefile.am
index a64391f..a533e86 100644
--- a/libpolkit/Makefile.am
+++ b/libpolkit/Makefile.am
@@ -12,7 +12,7 @@ INCLUDES = \
@GLIB_CFLAGS@ \
@DBUS_GLIB_CFLAGS@
-lib_LTLIBRARIES=libpolkit.la
+lib_LTLIBRARIES=libpolkit.la libpolkit-grant.la
libpolkitincludedir=$(includedir)/libpolkit
@@ -26,6 +26,29 @@ libpolkit_la_LIBADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@
libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+
+libpolkit_grantincludedir=$(includedir)/libpolkit
+
+libpolkit_grantinclude_HEADERS = \
+ libpolkit-grant.h
+
+libpolkit_grant_la_SOURCES = \
+ libpolkit-grant.c libpolkit-grant.h \
+ polkit-interface-manager-glue.h \
+ polkit-interface-session-glue.h
+
+libpolkit_grant_la_LIBADD = @DBUS_GLIB_LIBS@ @GLIB_LIBS@
+
+libpolkit_grant_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+
+polkit-interface-manager-glue.h: ../polkit-interface-manager.xml Makefile.am
+ dbus-binding-tool --prefix=polkit_manager --mode=glib-client --output=polkit-interface-manager-glue.h ../polkit-interface-manager.xml
+
+polkit-interface-session-glue.h: ../polkit-interface-session.xml Makefile.am
+ dbus-binding-tool --prefix=polkit_session --mode=glib-client --output=polkit-interface-session-glue.h ../polkit-interface-session.xml
+
+BUILT_SOURCES = polkit-interface-manager-glue.h polkit-interface-session-glue.h
+
clean-local :
- rm -f *~
+ rm -f *~ $(BUILT_SOURCES)
diff --git a/libpolkit/libpolkit-grant.c b/libpolkit/libpolkit-grant.c
new file mode 100644
index 0000000..4e9e7d1
--- /dev/null
+++ b/libpolkit/libpolkit-grant.c
@@ -0,0 +1,407 @@
+/***************************************************************************
+ *
+ * libpolkit-grant.c : Wraps temporary grant methods on the PolicyKit daemon
+ *
+ * Copyright (C) 2006 David Zeuthen, <david@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
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+
+#include <glib/gstdio.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <libpolkit/libpolkit.h>
+#include "libpolkit-grant.h"
+
+#include "polkit-interface-manager-glue.h"
+#include "polkit-interface-session-glue.h"
+
+struct LibPolKitGrantContext_s
+{
+ DBusGConnection *dbus_g_connection;
+ char *user;
+ char *privilege;
+ char *resource;
+ gboolean restrict_to_dbus_connection;
+
+ LibPolKitGrantQuestions questions_handler;
+ LibPolKitGrantComplete grant_complete_handler;
+
+ char *auth_user;
+ char *auth_service_name;
+
+ DBusGProxy *manager;
+ DBusGProxy *session;
+
+ LibPolKitContext *polkit_ctx;
+
+ gpointer user_data;
+};
+
+
+static void
+have_questions_handler (DBusGProxy *session, gpointer user_data)
+{
+ char **questions;
+ GError *error = NULL;
+ LibPolKitGrantContext *ctx = (LibPolKitGrantContext *) user_data;
+ gboolean should_continue;
+
+ should_continue = FALSE;
+
+ if (!org_freedesktop_PolicyKit_Session_get_questions (ctx->session,
+ &questions,
+ &error)) {
+ g_warning ("GetQuestions: %s", error->message);
+
+ /* we're done */
+ ctx->grant_complete_handler (ctx, FALSE, error->message, ctx->user_data);
+
+ g_error_free (error);
+
+ } else {
+ ctx->questions_handler (ctx, (const char **) questions, ctx->user_data);
+ g_strfreev (questions);
+ }
+}
+
+void
+libpolkit_grant_provide_answers (LibPolKitGrantContext *ctx, const char **answers)
+{
+ GError *error = NULL;
+
+ if (!org_freedesktop_PolicyKit_Session_provide_answers (ctx->session,
+ (const char **) answers,
+ &error)) {
+ g_warning ("ProvideAnswers: %s", error->message);
+
+ /* we're done */
+ ctx->grant_complete_handler (ctx, FALSE, error->message, ctx->user_data);
+
+ g_error_free (error);
+ }
+}
+
+
+static void
+auth_done_handler (DBusGProxy *session, gpointer user_data)
+{
+ gboolean auth_result;
+ //gboolean was_revoked;
+ GError *error = NULL;
+ LibPolKitGrantContext *ctx = (LibPolKitGrantContext *) user_data;
+
+ /*g_debug ("in %s", __FUNCTION__);*/
+
+ if (!org_freedesktop_PolicyKit_Session_is_authenticated (session,
+ &auth_result,
+ &error)) {
+ g_warning ("IsAuthenticated: %s", error->message);
+
+ /* we're done */
+ ctx->grant_complete_handler (ctx, FALSE, error->message, ctx->user_data);
+
+ g_error_free (error);
+ goto out;
+ }
+
+ /*g_message ("Authentication done. %s", auth_result);*/
+
+ if (!auth_result) {
+ char *auth_denied_reason;
+
+ if (!org_freedesktop_PolicyKit_Session_get_auth_denied_reason (session,
+ &auth_denied_reason,
+ &error)) {
+ g_warning ("GetAuthDeniedReason: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /*g_print ("\n"
+ "Authentication failed (reason: '%s').\n", auth_denied_reason);*/
+
+ /* we're done */
+ ctx->grant_complete_handler (ctx, FALSE, auth_denied_reason, ctx->user_data);
+
+ g_free (auth_denied_reason);
+
+ } else {
+ /*g_print ("\n"
+ "Authentication succeeded.\n");*/
+
+ /* don't restrict privilege to callers unique system bus connection name */
+ if (!org_freedesktop_PolicyKit_Session_grant_privilege_temporarily (session,
+ ctx->restrict_to_dbus_connection,
+ &error)) {
+ g_warning ("GrantPrivilegeTemporarily: %s", error->message);
+
+ /* we're done */
+ ctx->grant_complete_handler (ctx, FALSE, error->message, ctx->user_data);
+
+ g_error_free (error);
+
+
+ } else {
+ /* we're done */
+ ctx->grant_complete_handler (ctx, TRUE, NULL, ctx->user_data);
+
+ }
+
+ }
+
+
+ //sleep (20);
+
+ //libpolkit_revoke_temporary_privilege (ctx, grant_user, grant_privilege, grant_resource, &was_revoked);
+ //g_debug ("was revoked = %d", was_revoked);
+ //sleep (10000);
+
+out:
+ ;
+}
+
+
+/**
+ * libpolkit_grant_new_context:
+ * @user: User to request privilege for
+ * @privilege: Privilege to ask for
+ * @resource: Resource to ask for. May be NULL.
+ * @restrict_to_dbus_connection: Whether the privilege should be restricted to a particular D-BUS connection on the
+ * system message bus.
+ * @user_data: User data to be passed to callbacks
+ *
+ * Create a new context for obtaining a privilege.
+ *
+ * Returns: The context. It is an opaque data structure. Free with libpolkit_grant_free_context.
+ */
+
+LibPolKitGrantContext*
+libpolkit_grant_new_context (DBusGConnection *dbus_g_connection,
+ const char *user,
+ const char *privilege,
+ const char *resource,
+ gboolean restrict_to_dbus_connection,
+ gpointer user_data)
+{
+ LibPolKitGrantContext* ctx;
+
+ ctx = g_new (LibPolKitGrantContext, 1);
+ ctx->dbus_g_connection = dbus_g_connection;
+ ctx->user = g_strdup (user);
+ ctx->privilege = g_strdup (privilege);
+ ctx->resource = g_strdup (resource);
+ ctx->restrict_to_dbus_connection = restrict_to_dbus_connection;
+ ctx->questions_handler = NULL;
+ ctx->grant_complete_handler = NULL;
+ ctx->user_data = user_data;
+
+ ctx->auth_user = NULL;
+ ctx->auth_service_name = NULL;
+
+ ctx->polkit_ctx = libpolkit_new_context (dbus_g_connection_get_connection (dbus_g_connection));
+
+ return ctx;
+}
+
+LibPolKitContext*
+libpolkit_grant_get_libpolkit_context (LibPolKitGrantContext *ctx)
+{
+ return ctx->polkit_ctx;
+}
+
+void
+libpolkit_grant_set_questions_handler (LibPolKitGrantContext *ctx,
+ LibPolKitGrantQuestions questions_handler)
+{
+ ctx->questions_handler = questions_handler;
+}
+
+void
+libpolkit_grant_set_grant_complete_handler (LibPolKitGrantContext *ctx,
+ LibPolKitGrantComplete grant_complete_handler)
+{
+ ctx->grant_complete_handler = grant_complete_handler;
+}
+
+gboolean
+libpolkit_grant_initiate_temporary_grant (LibPolKitGrantContext *ctx)
+{
+ GError *error = NULL;
+ char *session_objpath;
+ gboolean rc;
+
+ rc = FALSE;
+ if (ctx->questions_handler == NULL ||
+ ctx->grant_complete_handler == NULL)
+ goto out;
+
+ ctx->manager = dbus_g_proxy_new_for_name (ctx->dbus_g_connection,
+ "org.freedesktop.PolicyKit",
+ "/org/freedesktop/PolicyKit/Manager",
+ "org.freedesktop.PolicyKit.Manager");
+ if (ctx->manager == NULL)
+ goto out;
+
+ if (!org_freedesktop_PolicyKit_Manager_initiate_temporary_privilege_grant (ctx->manager,
+ ctx->user,
+ ctx->privilege,
+ ctx->resource,
+ &session_objpath,
+ &error)) {
+ g_warning ("GrantPrivilege: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ /*g_debug ("session_objpath = %s", session_objpath);*/
+
+ ctx->session = dbus_g_proxy_new_for_name (ctx->dbus_g_connection,
+ "org.freedesktop.PolicyKit",
+ session_objpath,
+ "org.freedesktop.PolicyKit.Session");
+ if (ctx->session == NULL)
+ goto out;
+
+ dbus_g_proxy_add_signal (ctx->session, "HaveQuestions", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (ctx->session, "HaveQuestions", G_CALLBACK (have_questions_handler),
+ (void *) ctx, NULL);
+
+ dbus_g_proxy_add_signal (ctx->session, "AuthenticationDone", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (ctx->session, "AuthenticationDone", G_CALLBACK (auth_done_handler),
+ (void *) ctx, NULL);
+
+ if (!org_freedesktop_PolicyKit_Session_get_auth_details (ctx->session,
+ &ctx->auth_user,
+ &ctx->auth_service_name,
+ &error)) {
+ g_warning ("GetAuthDetails: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (!org_freedesktop_PolicyKit_Session_initiate_auth (ctx->session,
+ &error)) {
+ g_warning ("InitiateAuth: %s", error->message);
+ g_error_free (error);
+ /* TODO: LIBPOLKIT_GRANT_RESULT_NO_SUCH_PRIVILEGE, LIBPOLKIT_GRANT_RESULT_CANNOT_AUTH_FOR_PRIVILEGE */
+ goto out;
+ }
+
+
+ g_free (session_objpath);
+
+ rc = TRUE;
+out:
+
+ return rc;
+}
+
+
+const char*
+libpolkit_grant_get_user_for_auth (LibPolKitGrantContext *ctx)
+{
+ return ctx->auth_user;
+}
+
+const char*
+libpolkit_grant_get_pam_service_for_auth (LibPolKitGrantContext *ctx)
+{
+ return ctx->auth_service_name;
+}
+
+gboolean
+libpolkit_grant_close (LibPolKitGrantContext *ctx,
+ gboolean revoke_privilege)
+{
+ GError *error = NULL;
+
+ /* got the privilege; now close the session.. */
+ if (!org_freedesktop_PolicyKit_Session_close (ctx->session,
+ &error)) {
+ g_warning ("Close: %s", error->message);
+ g_error_free (error);
+ }
+
+ if (revoke_privilege) {
+ gboolean was_revoked;
+
+ libpolkit_revoke_temporary_privilege (ctx->polkit_ctx,
+ ctx->user,
+ ctx->privilege,
+ ctx->resource,
+ &was_revoked);
+
+ if (!was_revoked) {
+ g_warning ("Couldn't revoke privilege");
+ }
+
+ }
+
+ return TRUE;
+}
+
+void
+libpolkit_grant_free_context (LibPolKitGrantContext *ctx)
+{
+ g_free (ctx->user);
+ g_free (ctx->privilege);
+ g_free (ctx->resource);
+ g_free (ctx->auth_user);
+ g_free (ctx->auth_service_name);
+ libpolkit_free_context (ctx->polkit_ctx);
+ g_free (ctx);
+}
+
+const char*
+libpolkit_grant_get_user (LibPolKitGrantContext *ctx)
+{
+ return ctx->user;
+}
+
+const char*
+libpolkit_grant_get_privilege (LibPolKitGrantContext *ctx)
+{
+ return ctx->privilege;
+}
+
+/**
+ * libpolkit_grant_get_resource:
+ * @ctx: Context
+ *
+ * Get the resource as passed in from libpolkit_grant_new_context.
+ *
+ * Returns: The resource. May be NULL.
+ */
+const char*
+libpolkit_grant_get_resource (LibPolKitGrantContext *ctx)
+{
+ return ctx->resource;
+}
+
diff --git a/libpolkit/libpolkit-grant.h b/libpolkit/libpolkit-grant.h
new file mode 100644
index 0000000..156aac1
--- /dev/null
+++ b/libpolkit/libpolkit-grant.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ *
+ * libpolkit-grant.h : Wraps temporary grant methods on the PolicyKit daemon
+ *
+ * Copyright (C) 2006 David Zeuthen, <david@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_GRANT_H
+#define LIBPOLKIT_GRANT_H
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <libpolkit/libpolkit.h>
+
+
+struct LibPolKitGrantContext_s;
+typedef struct LibPolKitGrantContext_s LibPolKitGrantContext;
+
+/**
+ * LibPolKitGrantQuestions:
+ * @ctx: Context
+ * @questions: NULL terminated series of pairs. Each pair represent one question.
+ * @user_data: User data
+ *
+ * Callback when information is needed from the user in order to
+ * authenticate.
+ *
+ * The first component of the each pair in the questions array denote
+ * the question type. It can assume the values "PamPromptEchoOff"
+ * (meaning prompt for answer but don't echo it on the screen as the
+ * user types it), "PamPromptEchoOn" (meaning prompt for answer and
+ * echo the answer on the screen as the user types it), "PamErrorMsg"
+ * (display the message as an error message to the user) and
+ * "PamTextInfo" (textual information to the user). The second
+ * component in the pair is the actual question or information
+ * (e.g. "Password:") and it should be shown to the user next to the
+ * text input box.
+ *
+ * The callee should call libpolkit_grant_provide_answers with a
+ * string array once it the answers have been obtained from the user.
+ *
+ */
+typedef void (*LibPolKitGrantQuestions) (LibPolKitGrantContext *ctx,
+ const char **questions,
+ gpointer user_data);
+
+/**
+ * LibPolKitGrantComplete:
+ * @obtained_privilege: Whether the user sucessfully authenticated
+ * and was granted the privilege.
+ * @reason_not_obtained: If the user did not obtain the privilege
+ * this is the reason. May be NULL.
+ * @user_data: User data
+ *
+ * Callback when authorization was complete or there was an error.
+ *
+ */
+typedef void (*LibPolKitGrantComplete) (LibPolKitGrantContext *ctx,
+ gboolean obtained_privilege,
+ const char *reason_not_obtained,
+ gpointer user_data);
+
+
+LibPolKitGrantContext* libpolkit_grant_new_context (DBusGConnection *dbus_g_connection,
+ const char *user,
+ const char *privilege,
+ const char *resource,
+ gboolean restrict_to_dbus_connection,
+ gpointer user_data);
+
+const char* libpolkit_grant_get_user (LibPolKitGrantContext *ctx);
+
+const char* libpolkit_grant_get_privilege (LibPolKitGrantContext *ctx);
+
+const char* libpolkit_grant_get_resource (LibPolKitGrantContext *ctx);
+
+LibPolKitContext* libpolkit_grant_get_libpolkit_context (LibPolKitGrantContext *ctx);
+
+void libpolkit_grant_set_questions_handler (LibPolKitGrantContext *ctx,
+ LibPolKitGrantQuestions questions_handler);
+
+void libpolkit_grant_set_grant_complete_handler (LibPolKitGrantContext *ctx,
+ LibPolKitGrantComplete grant_complete_handler);
+
+gboolean libpolkit_grant_initiate_temporary_grant (LibPolKitGrantContext *ctx);
+
+const char* libpolkit_grant_get_user_for_auth (LibPolKitGrantContext *ctx);
+
+const char* libpolkit_grant_get_pam_service_for_auth (LibPolKitGrantContext *ctx);
+
+void libpolkit_grant_provide_answers (LibPolKitGrantContext *ctx,
+ const char **answers);
+
+gboolean libpolkit_grant_close (LibPolKitGrantContext *ctx,
+ gboolean revoke_privilege);
+
+void libpolkit_grant_free_context (LibPolKitGrantContext *ctx);
+
+
+#endif /* LIBPOLKIT_GRANT_H */
+
+
diff --git a/libpolkit/libpolkit.c b/libpolkit/libpolkit.c
index b4a78f5..a00283b 100644
--- a/libpolkit/libpolkit.c
+++ b/libpolkit/libpolkit.c
@@ -54,8 +54,8 @@
return _ret_; \
} \
if (_ctx_->magic != LIBPOLKIT_MAGIC) { \
- g_warning ("%s: given LibPolKitContext is invalid", \
- __FUNCTION__); \
+ g_warning ("%s: given LibPolKitContext is invalid (read magic 0x%08x, should be 0x%08x)", \
+ __FUNCTION__, _ctx_->magic, LIBPOLKIT_MAGIC); \
return _ret_; \
} \
} while(0)
@@ -102,7 +102,8 @@ LibPolKitResult
libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx,
const char *user,
const char *privilege,
- GList **result,
+ GList **resources,
+ GList **restrictions,
int *num_non_temporary)
{
LibPolKitResult res;
@@ -111,12 +112,15 @@ libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx,
DBusError error;
char **resource_list;
int num_resources;
+ char **restriction_list;
+ int num_restrictions;
int i;
LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT);
res = LIBPOLKIT_RESULT_ERROR;
- *result = NULL;
+ *resources = NULL;
+ *restrictions = NULL;
message = dbus_message_new_method_call ("org.freedesktop.PolicyKit",
"/org/freedesktop/PolicyKit/Manager",
@@ -149,6 +153,7 @@ libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx,
if (!dbus_message_get_args (reply, &error,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &resource_list, &num_resources,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &restriction_list, &num_restrictions,
DBUS_TYPE_INT32, num_non_temporary,
DBUS_TYPE_INVALID)) {
g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message);
@@ -157,10 +162,15 @@ libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx,
}
for (i = 0; i < num_resources; i++) {
- *result = g_list_append (*result, g_strdup (resource_list[i]));
+ *resources = g_list_append (*resources, g_strdup (resource_list[i]));
}
dbus_free_string_array (resource_list);
+ for (i = 0; i < num_restrictions; i++) {
+ *restrictions = g_list_append (*restrictions, g_strdup (restriction_list[i]));
+ }
+ dbus_free_string_array (restriction_list);
+
res = LIBPOLKIT_RESULT_OK;
out:
@@ -172,25 +182,28 @@ out:
}
LibPolKitResult
-libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
- pid_t pid,
- const char *user,
- const char *privilege,
- const char *resource,
- gboolean *is_allowed,
- gboolean *is_temporary)
+libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
+ const char *system_bus_unique_name,
+ const char *user,
+ const char *privilege,
+ const char *resource,
+ gboolean *out_is_allowed,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted_to_system_bus_unique_name)
{
LibPolKitResult res;
DBusMessage *message = NULL;
DBusMessage *reply = NULL;
DBusError error;
const char *myresource = "";
+ const char *mysystem_bus_unique_name = "";
+ char *but_restricted_to = NULL;
LIBPOLKIT_CHECK_CONTEXT (ctx, LIBPOLKIT_RESULT_INVALID_CONTEXT);
res = LIBPOLKIT_RESULT_ERROR;
- *is_allowed = FALSE;
- *is_temporary = FALSE;
+ *out_is_allowed = FALSE;
+ *out_is_temporary = FALSE;
message = dbus_message_new_method_call ("org.freedesktop.PolicyKit",
"/org/freedesktop/PolicyKit/Manager",
@@ -204,8 +217,11 @@ libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
if (resource != NULL)
myresource = resource;
+ if (system_bus_unique_name != NULL)
+ mysystem_bus_unique_name = system_bus_unique_name;
+
if (!dbus_message_append_args (message,
- DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_STRING, &mysystem_bus_unique_name,
DBUS_TYPE_STRING, &user,
DBUS_TYPE_STRING, &privilege,
DBUS_TYPE_STRING, &myresource,
@@ -232,14 +248,24 @@ libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
if (!dbus_message_get_args (reply, &error,
- DBUS_TYPE_BOOLEAN, is_allowed,
- DBUS_TYPE_BOOLEAN, is_temporary,
+ DBUS_TYPE_BOOLEAN, out_is_allowed,
+ DBUS_TYPE_BOOLEAN, out_is_temporary,
+ DBUS_TYPE_STRING, &but_restricted_to,
DBUS_TYPE_INVALID)) {
g_warning ("Could not extract args from D-BUS message: %s : %s", error.name, error.message);
dbus_error_free (&error);
goto out;
}
+ if (out_is_privileged_but_restricted_to_system_bus_unique_name != NULL) {
+ if (but_restricted_to != NULL && strlen (but_restricted_to) > 0) {
+ *out_is_privileged_but_restricted_to_system_bus_unique_name = strdup (but_restricted_to);
+ } else {
+ *out_is_privileged_but_restricted_to_system_bus_unique_name = NULL;
+ }
+ //dbus_free (but_restricted_to);
+ }
+
res = LIBPOLKIT_RESULT_OK;
out:
diff --git a/libpolkit/libpolkit.h b/libpolkit/libpolkit.h
index 2b19c56..28b4319 100644
--- a/libpolkit/libpolkit.h
+++ b/libpolkit/libpolkit.h
@@ -51,12 +51,13 @@ LibPolKitResult libpolkit_get_privilege_list (LibPolKit
GList **result);
LibPolKitResult libpolkit_is_uid_allowed_for_privilege (LibPolKitContext *ctx,
- pid_t pid,
+ const char *system_bus_unique_name,
const char *user,
const char *privilege,
const char *resource,
- gboolean *is_allowed,
- gboolean *is_temporary);
+ gboolean *out_is_allowed,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted_to_system_bus_unique_name);
LibPolKitResult libpolkit_revoke_temporary_privilege (LibPolKitContext *ctx,
const char *user,
@@ -67,7 +68,8 @@ LibPolKitResult libpolkit_revoke_temporary_privilege (LibPolKit
LibPolKitResult libpolkit_get_allowed_resources_for_privilege_for_uid (LibPolKitContext *ctx,
const char *user,
const char *privilege,
- GList **result,
+ GList **resources,
+ GList **restrictions,
int *num_non_temporary);
#endif /* LIBPOLKIT_H */
diff --git a/pam-polkit-console/Makefile.am b/pam-polkit-console/Makefile.am
new file mode 100644
index 0000000..c0592f9
--- /dev/null
+++ b/pam-polkit-console/Makefile.am
@@ -0,0 +1,18 @@
+
+LOCKDIR = $(localstatedir)/run/polkit-console
+LOCKDIRMODE = 0700
+
+securelibdir = /lib/security
+securelib_LTLIBRARIES = pam_polkit_console.la
+
+pam_polkit_console_la_LDFLAGS = -no-undefined -avoid-version -module
+pam_polkit_console_la_LIBADD = -lpam
+pam_polkit_console_la_CFLAGS = -DLOCKDIR=\"$(LOCKDIR)\"
+
+pam_polkit_console_la_SOURCES = pam-polkit-console.c
+
+clean-local :
+ rm -f *~
+
+install-data-local:
+ mkdir -m $(LOCKDIRMODE) -p $(DESTDIR)$(LOCKDIR)
diff --git a/pam-polkit-console/pam-polkit-console.c b/pam-polkit-console/pam-polkit-console.c
new file mode 100644
index 0000000..353d596
--- /dev/null
+++ b/pam-polkit-console/pam-polkit-console.c
@@ -0,0 +1,255 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * pam-polkit-console.c : Maintain files in /var/run/polkit-console to
+ * maintain a list of what users are logged in at
+ * what console
+ *
+ * Copyright (C) 2006 David Zeuthen, <david@fubar.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ **************************************************************************/
+
+#include <config.h>
+
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+#include <security/pam_modutil.h>
+#include <security/pam_ext.h>
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+
+static int debug = 0;
+
+static void
+_pam_log (pam_handle_t *pamh,
+ int err,
+ int debug_noforce,
+ const char *format, ...)
+{
+ va_list args;
+
+ if (debug_noforce && !debug)
+ return;
+
+ va_start (args, format);
+ pam_vsyslog (pamh, err, format, args);
+ closelog ();
+}
+
+static void
+_parse_module_args (pam_handle_t *pamh,
+ int argc,
+ const char **argv)
+{
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ const char *arg;
+
+ arg = argv[i];
+ if (strcmp (arg,"debug") == 0) {
+ debug = 1;
+ } else {
+ _pam_log(pamh, LOG_ERR, FALSE,
+ "_parse_module_args: unknown option; %s", arg);
+ }
+ }
+}
+
+static int
+_is_local_xconsole (const char *tty)
+{
+ int a, b;
+
+ if (sscanf (tty, ":%d.%d", &a, &b) == 2)
+ return TRUE;
+ else if (sscanf (tty, ":%d", &a) == 1)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+_poke_polkitd (pam_handle_t *pamh)
+{
+ char buf[80];
+
+ /* This is a PAM module so we're loaded into the address space
+ * of some other process (e.g. gdm) - though it's tempting to
+ * use D-BUS to poke the PolicyKit daemon it may, just resort to
+ * using oldskool SIGUSR1 instead.
+ */
+
+ FILE *f;
+ f = fopen (POLKITD_PID_FILE, "r");
+ if (f != NULL) {
+ if (fgets (buf, sizeof (buf), f) != NULL && buf[0] != '\0' && buf[0] != '\n') {
+ pid_t pid;
+ char *p;
+
+ pid = strtol (buf, &p, 10);
+ if ((*p == '\0') || (*p == '\n'))
+ {
+ _pam_log (pamh, LOG_DEBUG, TRUE,
+ "Sending SIGUSR1 to polkitd with pid %d to reload configuration", pid);
+ kill (pid, SIGUSR1);
+ }
+ }
+ fclose (f);
+ }
+}
+
+PAM_EXTERN int
+pam_sm_authenticate (pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return PAM_AUTH_ERR;
+}
+
+PAM_EXTERN int
+pam_sm_setcred (pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN int
+pam_sm_open_session (pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ const char *username = NULL;
+ const char *user_prompt = NULL;
+ const char *tty = NULL;
+ char buf[256];
+
+ _pam_log (pamh, LOG_ERR, TRUE, "pam_polkit_console open_session");
+ _parse_module_args (pamh, argc, argv);
+ if(pam_get_item (pamh, PAM_USER_PROMPT, (const void **) &user_prompt) != PAM_SUCCESS) {
+ user_prompt = "user name: ";
+ }
+ username = NULL;
+ pam_get_user (pamh, &username, user_prompt);
+ if (username == NULL || strlen (username) == 0) {
+ return PAM_SESSION_ERR;
+ }
+
+ pam_get_item(pamh, PAM_TTY, (const void**) &tty);
+ if (tty == NULL || strlen (tty) == 0) {
+ _pam_log(pamh, LOG_ERR, TRUE, "TTY not defined");
+ return PAM_SESSION_ERR;
+ }
+
+ _pam_log (pamh, LOG_DEBUG, TRUE, "open_session for user '%s' @ TTY '%s'", username, tty);
+
+ if (_is_local_xconsole (tty)) {
+ if ((unsigned int) snprintf (buf, sizeof (buf), LOCKDIR "/%s_%s", tty, username) < sizeof (buf)) {
+ int fd;
+
+ fd = open (buf, O_RDWR|O_CREAT|O_EXCL, 0600);
+ if (fd > 0) {
+ _pam_log (pamh, LOG_DEBUG, TRUE, "open_session success; %s %s %s",
+ username, tty, buf);
+ close (fd);
+ _poke_polkitd (pamh);
+ }
+ }
+ }
+
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN int
+pam_sm_close_session (pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ const char *username = NULL;
+ const char *user_prompt = NULL;
+ const char *tty = NULL;
+ char buf[256];
+
+ _pam_log (pamh, LOG_ERR, TRUE, "pam_polkit_console close_session");
+ _parse_module_args (pamh, argc, argv);
+ if (pam_get_item (pamh, PAM_USER_PROMPT, (const void **) &user_prompt) != PAM_SUCCESS) {
+ user_prompt = "user name: ";
+ }
+ username = NULL;
+ pam_get_user (pamh, &username, user_prompt);
+ if (username == NULL || strlen (username) == 0) {
+ return PAM_SESSION_ERR;
+ }
+
+ pam_get_item (pamh, PAM_TTY, (const void**) &tty);
+ if (tty == NULL || strlen (tty) == 0) {
+ _pam_log(pamh, LOG_ERR, TRUE, "TTY not defined");
+ return PAM_SESSION_ERR;
+ }
+
+ _pam_log (pamh, LOG_DEBUG, TRUE, "close_session for user '%s' @ TTY '%s'", username, tty);
+
+ if (_is_local_xconsole (tty)) {
+ if ((unsigned int) snprintf (buf, sizeof (buf), LOCKDIR "/%s_%s", tty, username) < sizeof (buf)) {
+ unlink (buf);
+ _poke_polkitd (pamh);
+ }
+ }
+
+ return PAM_SUCCESS;
+}
+
+#ifdef PAM_STATIC
+
+/* static module data */
+
+struct pam_module _pam_polkit_console_modstruct = {
+ "pam_polkit_console",
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ NULL,
+ pam_sm_open_session,
+ pam_sm_close_session,
+ NULL,
+};
+
+#endif
+
+/* end of module definition */
diff --git a/polkit-interface-manager.xml b/polkit-interface-manager.xml
index 1d050d1..c7c461e 100644
--- a/polkit-interface-manager.xml
+++ b/polkit-interface-manager.xml
@@ -21,20 +21,22 @@
<method name="IsUserPrivileged">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg name="pid" type="i" direction="in"/>
- <arg name="user" type="s" direction="in"/>
- <arg name="privilege" type="s" direction="in"/>
- <arg name="resource" type="s" direction="in"/>
- <arg name="is_privileged" type="b" direction="out"/>
- <arg name="is_temporary" type="b" direction="out"/>
+ <arg name="system_bus_unique_name" type="s" direction="in"/>
+ <arg name="user" type="s" direction="in"/>
+ <arg name="privilege" type="s" direction="in"/>
+ <arg name="resource" type="s" direction="in"/>
+ <arg name="is_privileged" type="b" direction="out"/>
+ <arg name="is_temporary" type="b" direction="out"/>
+ <arg name="is_privileged_but_restricted_to_system_bus_unique_name" type="s" direction="out"/>
</method>
<method name="GetAllowedResourcesForPrivilege">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg name="user" type="s" direction="in"/>
- <arg name="privilege" type="s" direction="in"/>
- <arg name="resource_list" type="as" direction="out"/>
- <arg name="num_non_temp" type="i" direction="out"/>
+ <arg name="user" type="s" direction="in"/>
+ <arg name="privilege" type="s" direction="in"/>
+ <arg name="resource_list" type="as" direction="out"/>
+ <arg name="restriction_list" type="as" direction="out"/>
+ <arg name="num_non_temp" type="i" direction="out"/>
</method>
<method name="ListPrivileges">
diff --git a/polkit-interface-session.xml b/polkit-interface-session.xml
index ff51bff..0549bda 100644
--- a/polkit-interface-session.xml
+++ b/polkit-interface-session.xml
@@ -35,12 +35,11 @@
<method name="Close">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg name="do_not_revoke_privileges" type="b" direction="in"/>
</method>
<method name="GrantPrivilegeTemporarily">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
- <arg name="restrict_to_callers_pid" type="b" direction="in"/>
+ <arg name="restrict_to_callers_system_bus_unique_name" type="b" direction="in"/>
</method>
<signal name="HaveQuestions"/>
diff --git a/polkit.pc.in b/polkit.pc.in
index 8fbc889..55885f5 100644
--- a/polkit.pc.in
+++ b/polkit.pc.in
@@ -3,10 +3,6 @@ exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
-user=@POLKIT_USER@
-group=@POLKIT_GROUP@
-txtsrc=@sysconfdir@/PolicyKit/privilege.d
-
Name: libpolkit
Description: library for querying and setting system-wide policy
Version: @VERSION@
diff --git a/polkitd/PolicyKit.in b/polkitd/PolicyKit.in
index 104386b..023fd7f 100755
--- a/polkitd/PolicyKit.in
+++ b/polkitd/PolicyKit.in
@@ -23,6 +23,13 @@ servicename=PolicyKit
RETVAL=0
+cleanup_state_dir()
+{
+ # Clean out all files in
+ rm -f @LOCALSTATEDIR@/run/polkit-console/*
+ mkdir -p @LOCALSTATEDIR@/run/polkit-console
+}
+
start() {
echo -n $"Starting PolicyKit daemon: "
daemon --check $servicename $processname
@@ -46,6 +53,7 @@ stop() {
# See how we were called.
case "$1" in
start)
+ cleanup_state_dir
start
;;
stop)
@@ -57,13 +65,11 @@ case "$1" in
;;
restart)
stop
- sleep 3
start
;;
condrestart)
if [ -f @LOCALSTATEDIR@/lock/subsys/$servicename ]; then
stop
- sleep 3
start
fi
;;
diff --git a/polkitd/main.c b/polkitd/main.c
index f996540..8286670 100644
--- a/polkitd/main.c
+++ b/polkitd/main.c
@@ -33,6 +33,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <signal.h>
#include <dbus/dbus-glib.h>
@@ -69,18 +70,61 @@ delete_pid (void)
unlink (POLKITD_PID_FILE);
}
+static int sigusr1_unix_signal_pipe_fds[2];
+static GIOChannel *sigusr1_iochn = NULL;
+static PolicyKitManager *manager = NULL;
+
+static void
+handle_sigusr1 (int value)
+{
+ ssize_t written;
+ static char marker[1] = {'S'};
+
+ written = write (sigusr1_unix_signal_pipe_fds[1], marker, 1);
+}
+
+static gboolean
+sigusr1_iochn_data (GIOChannel *source,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ GError *err = NULL;
+ gchar data[1];
+ gsize bytes_read;
+
+ /* Empty the pipe */
+ if (G_IO_STATUS_NORMAL !=
+ g_io_channel_read_chars (source, data, 1, &bytes_read, &err)) {
+ g_warning ("Error emptying sigusr1 pipe: %s", err->message);
+ g_error_free (err);
+ goto out;
+ }
+
+ g_debug ("Caught SIGUSR1");
+ if (manager != NULL) {
+ polkit_manager_update_desktop_console_privileges (manager);
+ }
+
+out:
+ return TRUE;
+}
+
+
int
main (int argc, char *argv[])
{
DBusGConnection *bus;
DBusGProxy *bus_proxy;
GError *error = NULL;
- PolicyKitManager *manager;
GMainLoop *mainloop;
guint request_name_result;
int ret;
gboolean no_daemon = FALSE;
gboolean is_verbose = FALSE;
+ int pf;
+ ssize_t written;
+ char pid[9];
+ guint sigusr1_iochn_listener_source_id;
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"no-daemon", no_argument, NULL, 'n'},
@@ -131,10 +175,6 @@ main (int argc, char *argv[])
if (!no_daemon) {
int child_pid;
int dev_null_fd;
- int pf;
- ssize_t written;
- char pid[9];
-
if (chdir ("/") < 0) {
g_warning ("Could not chdir to /: %s", strerror (errno));
@@ -170,21 +210,21 @@ main (int argc, char *argv[])
/* create session */
setsid ();
-
- /* remove old pid file */
- unlink (POLKITD_PID_FILE);
-
- /* make a new pid file */
- if ((pf = open (POLKITD_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) > 0) {
- snprintf (pid, sizeof(pid), "%lu\n", (long unsigned) getpid ());
- written = write (pf, pid, strlen(pid));
- close (pf);
- g_atexit (delete_pid);
- }
} else {
g_debug (("not becoming a daemon"));
}
+ /* remove old pid file */
+ unlink (POLKITD_PID_FILE);
+
+ /* make a new pid file */
+ if ((pf = open (POLKITD_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644)) > 0) {
+ snprintf (pid, sizeof(pid), "%lu\n", (long unsigned) getpid ());
+ written = write (pf, pid, strlen(pid));
+ close (pf);
+ g_atexit (delete_pid);
+ }
+
g_type_init ();
dbus_g_object_type_install_info (POLKIT_TYPE_MANAGER, &dbus_glib_polkit_manager_object_info);
@@ -194,6 +234,30 @@ main (int argc, char *argv[])
mainloop = g_main_loop_new (NULL, FALSE);
+ /* Listen for SIGUSR1 - UNIX signal handlers are evil though,
+ * so set up a pipe to transmit the signal.
+ */
+
+ /* create pipe */
+ if (pipe (sigusr1_unix_signal_pipe_fds) != 0) {
+ g_warning ("Could not setup pipe, errno=%d", errno);
+ goto out;
+ }
+
+ /* setup glib handler - 0 is for reading, 1 is for writing */
+ sigusr1_iochn = g_io_channel_unix_new (sigusr1_unix_signal_pipe_fds[0]);
+ if (sigusr1_iochn == NULL) {
+ g_warning ("Could not create GIOChannel");
+ goto out;
+ }
+
+ /* get callback when there is data to read */
+ sigusr1_iochn_listener_source_id = g_io_add_watch (
+ sigusr1_iochn, G_IO_IN, sigusr1_iochn_data, NULL);
+
+ /* setup UNIX signal handler for SIGUSR1 */
+ signal (SIGUSR1, handle_sigusr1);
+
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s", error->message);
@@ -222,9 +286,15 @@ main (int argc, char *argv[])
manager = polkit_manager_new (bus, bus_proxy);
+ if (manager == NULL) {
+ g_warning ("Could not construct manager object; bailing out");
+ goto out;
+ }
g_debug ("service running");
+ polkit_manager_update_desktop_console_privileges (manager);
+
g_main_loop_run (mainloop);
ret = 0;
diff --git a/polkitd/policy.c b/polkitd/policy.c
index 95032ec..32c8f78 100644
--- a/polkitd/policy.c
+++ b/polkitd/policy.c
@@ -171,7 +171,7 @@ txt_backend_read_policy (const char *policy,
goto out;
}
- value = g_key_file_get_string (keyfile, "Policy", key, &error);
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
if (value == NULL) {
g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
g_error_free (error);
@@ -295,6 +295,115 @@ out:
return rc;
}
+
+static PolicyResult
+txt_backend_read_list (const char *policy,
+ const char *key,
+ GList **result)
+{
+ int i;
+ GKeyFile *keyfile;
+ GError *error;
+ PolicyResult rc;
+ char *path;
+ char *value = NULL;
+ char **tokens = NULL;
+ GList *res;
+ char *token;
+
+ error = NULL;
+ rc = POLICY_RESULT_ERROR;
+ res = NULL;
+ *result = NULL;
+
+ keyfile = g_key_file_new ();
+ path = g_strdup_printf ("%s/%s.privilege", policy_directory, policy);
+ /*g_message ("Loading %s", path);*/
+ if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) {
+ g_warning ("Couldn't open key-file '%s': %s", path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_NO_SUCH_POLICY;
+ goto out;
+ }
+
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
+ if (value == NULL) {
+ g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_ERROR;
+ goto out;
+ }
+
+ /*g_message ("value = '%s'", value);*/
+ tokens = g_strsplit (value, " ", 0);
+ for (i = 0; tokens[i] != NULL; i++) {
+ token = tokens[i];
+ /*g_message (" token = '%s'", token);*/
+
+ res = g_list_append (res, g_strdup (token));
+ }
+
+ *result = res;
+ rc = POLICY_RESULT_OK;
+
+out:
+ g_strfreev (tokens);
+ g_free (value);
+
+ g_key_file_free (keyfile);
+ g_free (path);
+
+ return rc;
+}
+
+static PolicyResult
+txt_backend_read_word (const char *policy,
+ const char *key,
+ char **result)
+{
+ GKeyFile *keyfile;
+ GError *error;
+ PolicyResult rc;
+ char *path;
+ char *value = NULL;
+
+ error = NULL;
+ rc = POLICY_RESULT_ERROR;
+ *result = NULL;
+
+ keyfile = g_key_file_new ();
+ path = g_strdup_printf ("%s/%s.privilege", policy_directory, policy);
+ /*g_message ("Loading %s", path);*/
+ if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, &error)) {
+ g_warning ("Couldn't open key-file '%s': %s", path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_NO_SUCH_POLICY;
+ goto out;
+ }
+
+ value = g_key_file_get_string (keyfile, "Privilege", key, &error);
+ if (value == NULL) {
+ g_warning ("Cannot get key '%s' in group 'Policy' in file '%s': %s", key, path, error->message);
+ g_error_free (error);
+ rc = POLICY_RESULT_ERROR;
+ goto out;
+ }
+
+ /*g_message ("value = '%s'", value);*/
+
+ *result = g_strdup (value);
+
+ rc = POLICY_RESULT_OK;
+
+out:
+ g_free (value);
+
+ g_key_file_free (keyfile);
+ g_free (path);
+
+ return rc;
+}
+
static PolicyResult
policy_get_whitelist (const char *policy,
GList **result)
@@ -309,6 +418,20 @@ policy_get_blacklist (const char *policy,
return txt_backend_read_policy (policy, "Deny", result);
}
+static PolicyResult
+policy_get_sufficient_privileges (const char *policy,
+ GList **result)
+{
+ return txt_backend_read_list (policy, "SufficientPrivileges", result);
+}
+
+static PolicyResult
+policy_get_required_privileges (const char *policy,
+ GList **result)
+{
+ return txt_backend_read_list (policy, "RequiredPrivileges", result);
+}
+
/** Return all elements in the white-list for a policy
*
* @param result On success set to a list of dynamically allocated strings.
@@ -352,6 +475,177 @@ error:
return POLICY_RESULT_ERROR;
}
+PolicyResult
+policy_get_auth_details_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_auth_can_obtain,
+ gboolean *out_auth_can_obtain_is_temporary,
+ gboolean *out_auth_can_grant,
+ gboolean *out_auth_obtain_requires_root,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
+{
+ PolicyResult res;
+ GList *required_privs;
+ GList *l;
+ char *can_obtain_word;
+ char *can_grant_word;
+ char *obtain_requires_root_word;
+
+ required_privs = NULL;
+ can_obtain_word = NULL;
+ can_grant_word = NULL;
+
+ *out_auth_can_obtain = FALSE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ *out_auth_can_grant = FALSE;
+ *out_auth_obtain_requires_root = TRUE;
+
+ res = POLICY_RESULT_ERROR;
+
+ res = txt_backend_read_word (policy, "CanObtain", &can_obtain_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (policy, "CanGrant", &can_grant_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (policy, "ObtainRequireRoot", &obtain_requires_root_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ if (strcmp (can_obtain_word, "True") == 0) {
+ *out_auth_can_obtain = TRUE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ } else if (strcmp (can_obtain_word, "False") == 0) {
+ *out_auth_can_obtain = FALSE;
+ *out_auth_can_obtain_is_temporary = FALSE;
+ } else if (strcmp (can_obtain_word, "Temporary") == 0) {
+ *out_auth_can_obtain = TRUE;
+ *out_auth_can_obtain_is_temporary = TRUE;
+ } else {
+ g_critical ("CanObtain has bogus value '%s' in privilege '%s'",
+ can_obtain_word, policy);
+ goto out;
+ }
+
+ if (strcmp (can_grant_word, "True") == 0) {
+ *out_auth_can_grant = TRUE;
+ } else if (strcmp (can_grant_word, "False") == 0) {
+ *out_auth_can_grant = FALSE;
+ } else {
+ g_critical ("CanGrant has bogus value '%s' in privilege '%s'",
+ can_grant_word, policy);
+ goto out;
+ }
+
+ if (strcmp (obtain_requires_root_word, "True") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ } else if (strcmp (obtain_requires_root_word, "False") == 0) {
+ *out_auth_obtain_requires_root = FALSE;
+ } else {
+ g_critical ("ObtainRequireRoot has bogus value '%s' in privilege '%s'",
+ obtain_requires_root_word, policy);
+ goto out;
+ }
+
+ /* no need to check RequiredPrivileges if said privilege says we can't obtain it */
+ if ((*out_auth_can_obtain) == FALSE)
+ goto determined;
+
+ /* if privilege already requires super user, no need to check RequiredPrivileges */
+ if ((*out_auth_obtain_requires_root) == TRUE)
+ goto determined;
+
+ /* So now the user can obtain the privilege and doesn't
+ * require root. However, per the spec, if he is lacking any
+ * of the privileges listed and one or more of these have
+ *
+ * - has ObtainRequiresRoot set to TRUE; or
+ *
+ * - has CanObtain set to FALSE
+ *
+ * then effectively ObtainsRequireRoot becomes TRUE.
+ */
+
+ res = policy_get_required_privileges (policy, &required_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ g_message (" * obtain_requires_root = %d", *out_auth_obtain_requires_root);
+
+ for (l = required_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_required_privilege = FALSE;
+ gboolean has_required_privilege_is_temp = FALSE;
+ char *has_required_privilege_is_restricted = NULL;
+ const char *required_privilege = (const char *) l->data;
+ PolicyResult res2;
+
+ g_message (" checking for required privilege '%s'", required_privilege);
+
+ has_required_privilege = FALSE;
+ res2 = policy_is_uid_allowed_for_policy (uid,
+ required_privilege,
+ NULL,
+ &has_required_privilege,
+ &has_required_privilege_is_temp,
+ &has_required_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ g_message (" has_required_privilege = %d", has_required_privilege);
+
+ if (!has_required_privilege ||
+ (has_required_privilege && has_required_privilege_is_restricted != NULL)) {
+
+ g_free (can_obtain_word);
+ g_free (can_grant_word);
+ can_obtain_word = NULL;
+ can_grant_word = NULL;
+
+ res = txt_backend_read_word (required_privilege, "CanObtain",
+ &can_obtain_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ res = txt_backend_read_word (required_privilege, "ObtainRequireRoot",
+ &obtain_requires_root_word);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ if (strcmp (can_obtain_word, "False") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ goto determined;
+ }
+
+ if (strcmp (obtain_requires_root_word, "True") == 0) {
+ *out_auth_obtain_requires_root = TRUE;
+ goto determined;
+ }
+ }
+ }
+
+determined:
+ g_message (" ** obtain_requires_root = %d", *out_auth_obtain_requires_root);
+ res = POLICY_RESULT_OK;
+
+out:
+ if (required_privs != NULL) {
+ g_list_foreach (required_privs, (GFunc) g_free, NULL);
+ g_list_free (required_privs);
+ }
+
+ g_free (can_obtain_word);
+ g_free (can_grant_word);
+
+ return res;
+}
+
+
static void
afp_process_elem(PolicyElement *elem, gboolean *flag, uid_t uid, guint num_gids, gid_t *gid_list)
@@ -467,25 +761,143 @@ out:
return res;
}
-PolicyResult
-policy_is_uid_gid_allowed_for_policy (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- const char *resource,
- gboolean *result)
+static PolicyResult
+_policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege,
+ int recursion_counter)
{
gboolean is_in_whitelist;
gboolean is_in_blacklist;
GList *l;
GList *whitelist;
GList *blacklist;
+ GList *sufficient_privs;
+ GList *required_privs;
PolicyResult res;
+ PolicyResult res2;
whitelist = NULL;
blacklist = NULL;
+ sufficient_privs = NULL;
+ required_privs = NULL;
res = POLICY_RESULT_ERROR;
+ *out_is_privileged = FALSE;
+ *out_is_temporary = FALSE;
+ *out_is_privileged_but_restricted = NULL;
+
+ if (recursion_counter > 8) {
+ g_critical ("Maximal (8) recursion depth detected checking privilege '%s'", policy);
+ goto out;
+ }
+
+ res = policy_get_sufficient_privileges (policy, &sufficient_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ /* first check SufficientPrivileges.. if we have one of those, then return TRUE */
+ for (l = sufficient_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_sufficient_privilege = FALSE;
+ gboolean has_sufficient_privilege_is_temp = FALSE;
+ char *has_sufficient_privilege_is_restricted = NULL;
+ const char *sufficient_privilege = (const char *) l->data;
+
+ g_message (" checking for sufficient privilege '%s'", sufficient_privilege);
+
+ has_sufficient_privilege = FALSE;
+ res2 = _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list,
+ sufficient_privilege, NULL,
+ &has_sufficient_privilege,
+ &has_sufficient_privilege_is_temp,
+ &has_sufficient_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, recursion_counter + 1);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ if (has_sufficient_privilege && has_sufficient_privilege_is_restricted == NULL) {
+ g_message ("Returned TRUE because we have the sufficient privilege '%s' for privilege '%s'",
+ sufficient_privilege, policy);
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = TRUE;
+ *out_is_temporary = has_sufficient_privilege_is_temp;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+ /* then check temporary privileges as it's OK to have a
+ * privilege temporarily without having the all the
+ * RequiredPrivileges.
+ */
+
+ if ((*out_is_privileged == FALSE) && have_temp_privilege != NULL) {
+ gboolean ignore_resource;
+
+ if (recursion_counter == 0)
+ ignore_resource = FALSE;
+ else
+ ignore_resource = TRUE;
+
+ /* TODO: ask for restriction */
+ if (have_temp_privilege (uid, policy, resource, ignore_resource, have_temp_privilege_userdata)) {
+
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = TRUE;
+ *out_is_temporary = TRUE;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+
+ /* now check RequiredPrivileges.. if we have don't have all of those, then return FALSE */
+
+ res = policy_get_required_privileges (policy, &required_privs);
+ if (res != POLICY_RESULT_OK)
+ goto out;
+
+ for (l = required_privs; l != NULL; l = g_list_next (l)) {
+ gboolean has_required_privilege = FALSE;
+ gboolean has_required_privilege_is_temp = FALSE;
+ char *has_required_privilege_is_restricted = NULL;
+ const char *required_privilege = (const char *) l->data;
+
+ g_message (" checking for required privilege '%s'", required_privilege);
+
+ has_required_privilege = FALSE;
+ res2 = _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list,
+ required_privilege, NULL,
+ &has_required_privilege,
+ &has_required_privilege_is_temp,
+ &has_required_privilege_is_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, recursion_counter + 1);
+ if (res2 != POLICY_RESULT_OK)
+ goto out;
+
+ if (!has_required_privilege ||
+ (has_required_privilege && has_required_privilege_is_restricted != NULL)) {
+ g_message ("Returned FALSE because we don't have the required privilege '%s' for privilege '%s'",
+ required_privilege, policy);
+ res = POLICY_RESULT_OK;
+ *out_is_privileged = FALSE;
+ *out_is_temporary = TRUE;
+ *out_is_privileged_but_restricted = NULL;
+ goto out;
+ }
+ }
+
+ /* Check against whitelist and blacklist */
+
res = policy_get_whitelist (policy, &whitelist);
if (res != POLICY_RESULT_OK)
goto out;
@@ -517,11 +929,21 @@ policy_is_uid_gid_allowed_for_policy (uid_t uid,
}
}
- *result = is_in_whitelist && (!is_in_blacklist);
+ *out_is_privileged = is_in_whitelist && (!is_in_blacklist);
+ *out_is_temporary = FALSE;
+ *out_is_privileged_but_restricted = NULL;
res = POLICY_RESULT_OK;
out:
+ if (required_privs != NULL) {
+ g_list_foreach (required_privs, (GFunc) g_free, NULL);
+ g_list_free (required_privs);
+ }
+ if (sufficient_privs != NULL) {
+ g_list_foreach (sufficient_privs, (GFunc) g_free, NULL);
+ g_list_free (sufficient_privs);
+ }
if (whitelist != NULL)
policy_element_free_list (whitelist);
if (blacklist != NULL)
@@ -530,6 +952,28 @@ out:
return res;
}
+
+PolicyResult
+policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
+{
+ return _policy_is_uid_gid_allowed_for_policy (uid, num_gids, gid_list, policy,
+ resource,
+ out_is_privileged,
+ out_is_temporary,
+ out_is_privileged_but_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege, 0);
+}
+
char *
policy_util_uid_to_name (uid_t uid,
gid_t *default_gid)
@@ -686,10 +1130,14 @@ out:
}
PolicyResult
-policy_is_uid_allowed_for_policy (uid_t uid,
- const char *policy,
- const char *resource,
- gboolean *result)
+policy_is_uid_allowed_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege)
{
int num_groups = 0;
gid_t *groups = NULL;
@@ -715,7 +1163,11 @@ policy_is_uid_allowed_for_policy (uid_t uid,
groups,
policy,
resource,
- result);
+ out_is_privileged,
+ out_is_temporary,
+ out_is_privileged_but_restricted,
+ have_temp_privilege_userdata,
+ have_temp_privilege);
out:
g_free (username);
diff --git a/polkitd/policy.h b/polkitd/policy.h
index 11865ea..94a2fd3 100644
--- a/polkitd/policy.h
+++ b/polkitd/policy.h
@@ -35,41 +35,68 @@ typedef enum {
POLICY_RESULT_NO_SUCH_POLICY
} PolicyResult;
-PolicyResult policy_get_policies (GList **result);
-
-PolicyResult policy_is_uid_allowed_for_policy (uid_t uid,
- const char *policy,
- const char *resource,
- gboolean *result);
-
-PolicyResult policy_get_allowed_resources_for_policy_for_uid (uid_t uid,
- const char *policy,
- GList **result);
-
-PolicyResult policy_get_allowed_resources_for_policy_for_uid_gid (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- GList **result);
-
-PolicyResult policy_is_uid_gid_allowed_for_policy (uid_t uid,
- guint num_gids,
- gid_t *gid_list,
- const char *policy,
- const char *resource,
- gboolean *result);
-
-char *policy_util_uid_to_name (uid_t uid,
- gid_t *default_gid);
-
-char *policy_util_gid_to_name (gid_t gid);
-
-uid_t policy_util_name_to_uid (const char *username,
- gid_t *default_gid);
-
-gid_t policy_util_name_to_gid (const char *groupname);
-
-void policy_util_set_policy_directory (const char *directory);
+typedef gboolean (*HaveTempPrivCB) (uid_t user,
+ const char *privilege,
+ const char *resource,
+ gboolean ignore_resource,
+ gpointer userdata);
+
+
+PolicyResult policy_get_policies (GList **result);
+
+PolicyResult policy_is_uid_allowed_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+
+PolicyResult policy_get_auth_details_for_policy (uid_t uid,
+ const char *policy,
+ const char *resource,
+ gboolean *out_auth_can_obtain,
+ gboolean *out_auth_can_obtain_is_temporary,
+ gboolean *out_auth_can_grant,
+ gboolean *out_auth_obtain_requires_root,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+
+PolicyResult policy_get_allowed_resources_for_policy_for_uid (uid_t uid,
+ const char *policy,
+ GList **result);
+
+PolicyResult policy_get_allowed_resources_for_policy_for_uid_gid (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ GList **result);
+
+PolicyResult policy_is_uid_gid_allowed_for_policy (uid_t uid,
+ guint num_gids,
+ gid_t *gid_list,
+ const char *policy,
+ const char *resource,
+ gboolean *out_is_privileged,
+ gboolean *out_is_temporary,
+ char **out_is_privileged_but_restricted,
+ gpointer have_temp_privilege_userdata,
+ HaveTempPrivCB have_temp_privilege);
+
+char *policy_util_uid_to_name (uid_t uid,
+ gid_t *default_gid);
+
+char *policy_util_gid_to_name (gid_t gid);
+
+uid_t policy_util_name_to_uid (const char *username,
+ gid_t *default_gid);
+
+gid_t policy_util_name_to_gid (const char *groupname);
+
+void policy_util_set_policy_directory (const char *directory);
#endif /* POLICY_H */
diff --git a/polkitd/polkit-manager.c b/polkitd/polkit-manager.c
index 52c59d9..947d333 100644
--- a/polkitd/polkit-manager.c
+++ b/polkitd/polkit-manager.c
@@ -38,7 +38,7 @@ typedef struct
uid_t user;
char *privilege;
char *resource;
- pid_t pid_restriction;
+ char *system_bus_unique_name; /* whether the tmp priv is restricted to e.g. :1.43 */
} TemporaryPrivilege;
struct PolicyKitManagerPrivate
@@ -58,6 +58,26 @@ G_DEFINE_TYPE(PolicyKitManager, polkit_manager, G_TYPE_OBJECT)
static GObjectClass *parent_class = NULL;
+
+static void
+_granting_temp_priv (PolicyKitManager *manager,
+ TemporaryPrivilege *p)
+{
+ g_debug ("Granting temporary privilege '%s' to uid %d on resource '%s'",
+ p->privilege, p->user, p->resource != NULL ? p->resource : "(none)");
+ /* TODO: send out D-BUS signal */
+}
+
+static void
+_revoking_temp_priv (PolicyKitManager *manager,
+ TemporaryPrivilege *p)
+{
+ g_debug ("Revoking temporary privilege '%s' to uid %d on resource '%s'",
+ p->privilege, p->user, p->resource != NULL ? p->resource : "(none)");
+ /* TODO: send out D-BUS signal */
+}
+
+
typedef struct {
uid_t uid;
pid_t pid;
@@ -130,6 +150,7 @@ polkit_manager_error_get_type (void)
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_USER, "NoSuchUser"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE, "NoSuchPrivilege"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_NOT_PRIVILEGED, "NotPrivileged"),
+ ENUM_ENTRY (POLKIT_MANAGER_ERROR_CANNOT_OBTAIN_PRIVILEGE, "CannotObtainPrivilege"),
ENUM_ENTRY (POLKIT_MANAGER_ERROR_ERROR, "Error"),
{ 0, 0, 0 }
};
@@ -157,6 +178,8 @@ bus_name_owner_changed (DBusGProxy *bus_proxy,
if (strlen (new_service_name) == 0) {
CallerInfo *caller_info;
PolicyKitSession *session;
+ GList *i;
+ TemporaryPrivilege *p;
/* evict CallerInfo from cache */
caller_info = (CallerInfo *) g_hash_table_lookup (manager->priv->connection_name_to_caller_info,
@@ -177,6 +200,29 @@ bus_name_owner_changed (DBusGProxy *bus_proxy,
g_hash_table_remove (manager->priv->connection_name_to_session_object, old_service_name);
}
+
+ /* revoke any temporary privileges that is restricted to this name */
+ for (i = manager->priv->temporary_privileges; i != NULL; ) {
+ p = (TemporaryPrivilege *) i->data;
+
+ i = g_list_next (i);
+
+ if (p->system_bus_unique_name != NULL &&
+ strcmp (p->system_bus_unique_name, old_service_name) == 0) {
+
+ /* da, revoke this privilege */
+ _revoking_temp_priv (manager, p);
+
+ g_free (p->privilege);
+ g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
+
+ manager->priv->temporary_privileges = g_list_remove (
+ manager->priv->temporary_privileges, p);
+ }
+ }
+
}
/*g_message ("NameOwnerChanged: service_name='%s', old_service_name='%s' new_service_name='%s'",
@@ -269,6 +315,7 @@ polkit_manager_get_caller_info (PolicyKitManager *manager,
gboolean res;
CallerInfo *caller_info;
GError *error = NULL;
+ GArray *calling_selinux_context;
res = FALSE;
@@ -307,6 +354,22 @@ polkit_manager_get_caller_info (PolicyKitManager *manager,
goto out;
}
+ if (!dbus_g_proxy_call (manager->priv->bus_proxy, "GetConnectionSELinuxSecurityContext", &error,
+ G_TYPE_STRING, sender,
+ G_TYPE_INVALID,
+ dbus_g_type_get_collection ("GArray", G_TYPE_UCHAR), &calling_selinux_context,
+ G_TYPE_INVALID)) {
+ g_warning ("GetConnectionSELinuxSecurityContext() failed: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ char *selinux_context_string;
+ g_array_append_val (calling_selinux_context, "\0");
+ selinux_context_string = (char *) g_array_free (calling_selinux_context, FALSE);
+ g_message ("selinux context = '%s' for sender '%s'", selinux_context_string, sender);
+ g_free (selinux_context_string);
+
caller_info = g_new0 (CallerInfo, 1);
caller_info->uid = *calling_uid;
caller_info->pid = *calling_pid;
@@ -324,6 +387,68 @@ out:
return res;
}
+
+typedef struct
+{
+ PolicyKitManager *manager;
+ char *system_bus_unique_name;
+ char *privileged_but_restricted_to;
+ gboolean is_temporary;
+} TempPrivCheckUserData;
+
+static gboolean
+_check_for_temp_privilege (uid_t user,
+ const char *privilege,
+ const char *resource,
+ gboolean ignore_resource,
+ gpointer userdata)
+{
+ GList *i;
+ TempPrivCheckUserData *tpcud = (TempPrivCheckUserData *) userdata;
+ gboolean is_privileged;
+
+ is_privileged = FALSE;
+
+ g_message ("in _check_for_temp_privilege for user=%d priv=%s resource=%s sbun=%s",
+ user, privilege, resource, tpcud->system_bus_unique_name);
+
+ for (i = tpcud->manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
+ TemporaryPrivilege *p;
+ gboolean res_match;
+
+ p = (TemporaryPrivilege *) i->data;
+
+ if (ignore_resource) {
+ res_match = TRUE;
+ } else {
+ if (resource == NULL || strlen (resource) == 0)
+ res_match = (p->resource == NULL);
+ else
+ res_match = (safe_strcmp (p->resource, resource) == 0);
+ }
+
+ if ((strcmp (p->privilege, privilege) == 0) &&
+ res_match &&
+ (p->user == user)) {
+
+ if (p->system_bus_unique_name == NULL) {
+ is_privileged = TRUE;
+ tpcud->is_temporary = TRUE;
+ break;
+ } else if (strcmp (p->system_bus_unique_name, tpcud->system_bus_unique_name) == 0) {
+ is_privileged = TRUE;
+ tpcud->is_temporary = TRUE;
+ break;
+ } else {
+ tpcud->privileged_but_restricted_to = p->system_bus_unique_name;
+ }
+
+ }
+ }
+
+ return is_privileged;
+}
+
gboolean
polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manager,
char *user,
@@ -365,14 +490,45 @@ polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manag
return FALSE;
}
+
+ gboolean auth_can_obtain;
+ gboolean auth_can_obtain_is_temporary;
+ gboolean auth_can_grant;
+ gboolean auth_obtain_requires_root;
+ PolicyResult res;
+ TempPrivCheckUserData tpcud;
+
+ tpcud.manager = manager;
+ tpcud.system_bus_unique_name = NULL;
+ tpcud.privileged_but_restricted_to = "";
+ tpcud.is_temporary = FALSE;
+
+ res = policy_get_auth_details_for_policy (uid,
+ privilege,
+ resource,
+ &auth_can_obtain,
+ &auth_can_obtain_is_temporary,
+ &auth_can_grant,
+ &auth_obtain_requires_root,
+ &tpcud,
+ _check_for_temp_privilege);
+
+ if (!auth_can_obtain) {
+ dbus_g_method_return_error (context,
+ g_error_new (POLKIT_MANAGER_ERROR,
+ POLKIT_MANAGER_ERROR_ERROR,
+ "The privilege %s cannot be obtained.", privilege));
+ return FALSE;
+ }
+
session = polkit_session_new (manager->priv->connection,
manager,
calling_uid,
- calling_pid,
sender,
uid,
privilege,
- strlen (resource) > 0 ? resource : NULL);
+ strlen (resource) > 0 ? resource : NULL,
+ auth_obtain_requires_root);
g_object_weak_ref (G_OBJECT (session),
session_finalized,
@@ -391,7 +547,7 @@ polkit_manager_initiate_temporary_privilege_grant (PolicyKitManager *manag
gboolean
polkit_manager_is_user_privileged (PolicyKitManager *manager,
- int pid,
+ char *system_bus_unique_name,
char *user,
char *privilege,
char *resource,
@@ -403,7 +559,8 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
PolicyResult res;
gboolean is_privileged;
gboolean is_temporary;
-
+ char *is_privileged_but_restricted_to = NULL;
+ TempPrivCheckUserData tpcud;
if (!polkit_manager_get_caller_info (manager,
dbus_g_method_get_sender (context),
@@ -438,10 +595,18 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
return FALSE;
}
+ tpcud.manager = manager;
+ tpcud.system_bus_unique_name = system_bus_unique_name;
+ tpcud.privileged_but_restricted_to = "";
+ tpcud.is_temporary = FALSE;
res = policy_is_uid_allowed_for_policy (uid,
privilege,
strlen (resource) > 0 ? resource : NULL,
- &is_privileged);
+ &is_privileged,
+ &is_temporary,
+ &is_privileged_but_restricted_to,
+ &tpcud,
+ _check_for_temp_privilege);
switch (res) {
case POLICY_RESULT_OK:
break;
@@ -463,35 +628,16 @@ polkit_manager_is_user_privileged (PolicyKitManager *manager,
return FALSE;
}
- is_temporary = FALSE;
-
- /* check temporary lists */
- if (!is_privileged) {
- GList *i;
- TemporaryPrivilege *p;
-
- for (i = manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
- p = (TemporaryPrivilege *) i->data;
- gboolean res_match;
- if (strlen (resource) == 0)
- res_match = (p->resource == NULL);
- else
- res_match = (safe_strcmp (p->resource, resource) == 0);
-
- if ((strcmp (p->privilege, privilege) == 0) &&
- res_match &&
- (p->user == uid) &&
- ((p->pid_restriction == -1) || (p->pid_restriction == pid))) {
-
- is_privileged = TRUE;
- is_temporary = TRUE;
- break;
- }
- }
+ /* if we ended up being privileged, then don't fill in the _but_restricted_to */
+ if (is_privileged) {
+ g_free (is_privileged_but_restricted_to);
+ is_privileged_but_restricted_to = g_strdup ("");
}
- dbus_g_method_return (context, is_privileged, is_temporary);
+ dbus_g_method_return (context, is_privileged, is_temporary, is_privileged_but_restricted_to);
+
+ g_free (is_privileged_but_restricted_to);
return TRUE;
}
@@ -508,10 +654,12 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
int n;
GList *i;
GList *resources;
+ GList *restrictions;
uid_t uid;
PolicyResult res;
TemporaryPrivilege *p;
char **resource_list;
+ char **restriction_list;
int num_non_temporary;
if (!polkit_manager_get_caller_info (manager,
@@ -572,15 +720,19 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
num_non_temporary = g_list_length (resources);
+ restrictions = NULL;
+
/* check temporary list */
for (i = manager->priv->temporary_privileges; i != NULL; i = g_list_next (i)) {
p = (TemporaryPrivilege *) i->data;
if ((strcmp (p->privilege, privilege) == 0) &&
(p->resource != NULL) &&
- (p->user == uid) &&
- (p->pid_restriction == -1)) {
+ (p->user == uid)) {
+
resources = g_list_append (resources, g_strdup (p->resource));
+ restrictions = g_list_append (restrictions, p->system_bus_unique_name != NULL ?
+ p->system_bus_unique_name : "");
}
}
@@ -595,7 +747,18 @@ polkit_manager_get_allowed_resources_for_privilege (PolicyKitManager *manag
g_list_foreach (resources, (GFunc) g_free, NULL);
g_list_free (resources);
- dbus_g_method_return (context, resource_list, num_non_temporary);
+ restriction_list = g_new0 (char *, g_list_length (resources) + 1);
+ for (n = 0; n < num_non_temporary; n++) {
+ restriction_list[n] = "";
+ }
+ for (i = restrictions; i != NULL; i = g_list_next (i)) {
+ char *restriction = (char *) i->data;
+ restriction_list[n] = g_strdup (restriction);
+ n++;
+ }
+ restriction_list[n] = NULL;
+
+ dbus_g_method_return (context, resource_list, restriction_list, num_non_temporary);
return TRUE;
}
@@ -713,7 +876,8 @@ polkit_manager_revoke_temporary_privilege (PolicyKitManager *manager,
uid,
privilege,
resource,
- -1)) {
+ NULL,
+ TRUE)) {
dbus_g_method_return_error (context,
g_error_new (POLKIT_MANAGER_ERROR,
POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE,
@@ -730,13 +894,12 @@ polkit_manager_revoke_temporary_privilege (PolicyKitManager *manager,
/* local methods */
-
gboolean
polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction)
+ const char *system_bus_unique_name)
{
GList *i;
TemporaryPrivilege *p;
@@ -747,7 +910,7 @@ polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
if ((strcmp (p->privilege, privilege) == 0) &&
((resource != NULL) && (safe_strcmp (p->resource, resource)) == 0) &&
(p->user == user) &&
- (p->pid_restriction == pid_restriction))
+ (p->system_bus_unique_name == system_bus_unique_name))
return FALSE;
}
@@ -755,8 +918,9 @@ polkit_manager_add_temporary_privilege (PolicyKitManager *manager,
p->user = user;
p->privilege = g_strdup (privilege);
p->resource = g_strdup (resource);
- p->pid_restriction = pid_restriction;
+ p->system_bus_unique_name = g_strdup (system_bus_unique_name);
+ _granting_temp_priv (manager, p);
manager->priv->temporary_privileges = g_list_append (manager->priv->temporary_privileges, p);
return TRUE;
@@ -767,7 +931,8 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction)
+ const char *system_bus_unique_name,
+ gboolean remove_even_if_system_bus_unique_name_does_not_match)
{
GList *i;
TemporaryPrivilege *p;
@@ -776,13 +941,25 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
p = (TemporaryPrivilege *) i->data;
if ((strcmp (p->privilege, privilege) == 0) &&
+
((resource == NULL) ? (p->resource == NULL)
: ((p->resource != NULL) ? (strcmp (p->resource, resource) == 0) : FALSE)) &&
+
(p->user == user) &&
- (p->pid_restriction == pid_restriction)) {
+
+ (remove_even_if_system_bus_unique_name_does_not_match ||
+ ((system_bus_unique_name == NULL) ? (p->system_bus_unique_name == NULL)
+ : ((p->system_bus_unique_name != NULL) ?
+ (strcmp (p->system_bus_unique_name, system_bus_unique_name) == 0) :
+ FALSE)))
+ ) {
+
+ _revoking_temp_priv (manager, p);
g_free (p->privilege);
g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
manager->priv->temporary_privileges = g_list_remove (
manager->priv->temporary_privileges, p);
@@ -793,3 +970,117 @@ polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
return FALSE;
}
+
+void
+polkit_manager_update_desktop_console_privileges (PolicyKitManager *manager)
+{
+ GDir *dir;
+ GError *err = NULL;
+ const char *f;
+ GSList *list;
+ GSList *j;
+ GList *i;
+ TemporaryPrivilege *p;
+
+ g_debug ("Entering polkit_manager_update_desktop_console_privileges");
+
+ /* Build a list of what /var/run/polkit-console contains;
+ * e.g. {":0", "davidz", ":1", "bateman", ..}
+ *
+ * This is essentially a list of pairs <consoleId, userId>
+ * denoting what users are logged in at the consoles attached
+ * to the system.
+ */
+ list = NULL;
+ if ((dir = g_dir_open (PACKAGE_LOCALSTATEDIR "/run/polkit-console", 0, &err)) == NULL) {
+ g_warning ("Unable to open " PACKAGE_LOCALSTATEDIR "/run/polkit-console : %s", err->message);
+ g_error_free (err);
+ goto out;
+ }
+ while ((f = g_dir_read_name (dir)) != NULL) {
+ char **tokens;
+
+ tokens = g_strsplit (f, "_", 2);
+ if (tokens != NULL && g_strv_length (tokens) == 2) {
+ char *console;
+ char *user;
+
+ console = g_strdup_printf ("console://%s", tokens[0]);
+ user = g_strdup (tokens[1]);
+ list = g_slist_append (list, console);
+ list = g_slist_append (list, user);
+ }
+ g_strfreev (tokens);
+ }
+ g_dir_close (dir);
+
+ /* now revoke the temporary desktop-console privilege for
+ * users no longer at the console; go through all tempoary
+ * desktop-console privileges and check that each one is still
+ * in the list above...
+ */
+ for (i = manager->priv->temporary_privileges; i != NULL; ) {
+ p = (TemporaryPrivilege *) i->data;
+ gboolean found;
+
+ i = g_list_next (i);
+
+ found = FALSE;
+
+ if ((strcmp (p->privilege, "desktop-console") == 0) && p->resource != NULL) {
+
+ for (j = list; j != NULL; j = g_slist_next (j)) {
+ char *console;
+ char *user;
+ uid_t uid;
+
+ console = (char *) j->data;
+ j = g_slist_next (j);
+ user = (char *) j->data;
+ uid = policy_util_name_to_uid (user, NULL);
+ if (uid != (uid_t) -1 && strcmp (p->resource, console) == 0 &&
+ p->user == uid &&
+ p->system_bus_unique_name == NULL) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ /* revoke this privilege */
+ _revoking_temp_priv (manager, p);
+
+ g_free (p->privilege);
+ g_free (p->resource);
+ g_free (p->system_bus_unique_name);
+ g_free (p);
+
+ manager->priv->temporary_privileges = g_list_remove (
+ manager->priv->temporary_privileges, p);
+ }
+ }
+
+ /* finally grant temporary desktop-console privilege for users
+ * now at the console
+ */
+ for (j = list; j != NULL; j = g_slist_next (j)) {
+ char *console;
+ char *user;
+ uid_t uid;
+
+ console = (char *) j->data;
+ j = g_slist_next (j);
+ user = (char *) j->data;
+ uid = policy_util_name_to_uid (user, NULL);
+ if (uid != (uid_t) -1) {
+ polkit_manager_add_temporary_privilege (manager, uid, "desktop-console", console, NULL);
+ }
+ }
+
+ g_slist_foreach (list, (GFunc) g_free, NULL);
+ g_slist_free (list);
+
+out:
+ ;
+}
diff --git a/polkitd/polkit-manager.h b/polkitd/polkit-manager.h
index f59e2dd..9d7b802 100644
--- a/polkitd/polkit-manager.h
+++ b/polkitd/polkit-manager.h
@@ -40,6 +40,7 @@ typedef enum
POLKIT_MANAGER_ERROR_NO_SUCH_PRIVILEGE = 1,
POLKIT_MANAGER_ERROR_NOT_PRIVILEGED = 2,
POLKIT_MANAGER_ERROR_ERROR = 3,
+ POLKIT_MANAGER_ERROR_CANNOT_OBTAIN_PRIVILEGE = 4,
POLKIT_MANAGER_NUM_ERRORS
} PolkitManagerError;
@@ -90,7 +91,7 @@ gboolean polkit_manager_revoke_temporary_privilege (PolicyKitM
DBusGMethodInvocation *context);
gboolean polkit_manager_is_user_privileged (PolicyKitManager *manager,
- int pid,
+ char *system_bus_unique_name,
char *user,
char *privilege,
char *resource,
@@ -116,12 +117,16 @@ gboolean polkit_manager_add_temporary_privilege (PolicyKitM
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction);
+ const char *system_bus_unique_name);
gboolean polkit_manager_remove_temporary_privilege (PolicyKitManager *manager,
uid_t user,
const char *privilege,
const char *resource,
- pid_t pid_restriction);
+ const char *system_bus_unique_name,
+ gboolean remove_even_if_system_bus_unique_name_does_not_match);
+
+void polkit_manager_update_desktop_console_privileges (PolicyKitManager *manager);
+
#endif /* _POLKIT_MANAGER_H */
diff --git a/polkitd/polkit-session.c b/polkitd/polkit-session.c
index 458e854..cbc2fb5 100644
--- a/polkitd/polkit-session.c
+++ b/polkitd/polkit-session.c
@@ -36,6 +36,7 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <security/pam_appl.h>
+#include "policy.h"
#include "polkit-session.h"
enum
@@ -58,13 +59,12 @@ struct PolicyKitSessionPrivate
char *auth_with_pam_service;
uid_t calling_uid;
- pid_t calling_pid;
char *calling_dbus_name;
uid_t grant_to_uid;
char *grant_privilege;
char *grant_resource;
- pid_t grant_pid_restriction;
+ char *grant_system_bus_name_unique_name_restriction;
gboolean have_granted_temp_privileges;
@@ -879,10 +879,9 @@ polkit_session_provide_answers (PolicyKitSession *session,
gboolean
polkit_session_close (PolicyKitSession *session,
- gboolean do_not_revoke_privilege,
DBusGMethodInvocation *context)
{
- /*g_debug ("in %s", __FUNCTION__);*/
+ g_debug ("In polkit_session_close for session %d", session->priv->session_number);
if (!polkit_session_check_caller (session, context))
return FALSE;
@@ -891,21 +890,6 @@ polkit_session_close (PolicyKitSession *session,
if (session->priv->child_pid != 0)
kill (session->priv->child_pid, SIGTERM);
- if (!do_not_revoke_privilege && session->priv->have_granted_temp_privileges) {
-
- if (!polkit_manager_remove_temporary_privilege (session->priv->manager,
- session->priv->grant_to_uid,
- session->priv->grant_privilege,
- session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on pid %d",
- session->priv->grant_privilege,
- session->priv->grant_to_uid,
- session->priv->grant_resource,
- session->priv->grant_pid_restriction);
- }
- }
-
g_object_unref (session);
dbus_g_method_return (context);
@@ -914,7 +898,7 @@ polkit_session_close (PolicyKitSession *session,
gboolean
polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
- gboolean restrict_to_callers_pid,
+ gboolean restrict_to_callers_system_bus_unique_name,
DBusGMethodInvocation *context)
{
if (!polkit_session_check_caller (session, context))
@@ -936,17 +920,18 @@ polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
return FALSE;
}
- session->priv->grant_pid_restriction = restrict_to_callers_pid ? session->priv->calling_pid : (pid_t) -1;
+ session->priv->grant_system_bus_name_unique_name_restriction = restrict_to_callers_system_bus_unique_name ?
+ g_strdup (session->priv->calling_dbus_name) : NULL;
if (!polkit_manager_add_temporary_privilege (session->priv->manager,
session->priv->grant_to_uid,
session->priv->grant_privilege,
session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not add tmp priv '%s' to uid %d for resource '%s' on pid %d",
+ session->priv->grant_system_bus_name_unique_name_restriction)) {
+ g_warning ("Could not add tmp priv '%s' to uid %d for resource '%s' on connection '%s'",
session->priv->grant_privilege,
session->priv->grant_to_uid,
session->priv->grant_resource,
- session->priv->grant_pid_restriction);
+ session->priv->grant_system_bus_name_unique_name_restriction);
}
session->priv->have_granted_temp_privileges = TRUE;
@@ -959,11 +944,11 @@ PolicyKitSession *
polkit_session_new (DBusGConnection *connection,
PolicyKitManager *manager,
uid_t calling_uid,
- pid_t calling_pid,
const char *calling_dbus_name,
uid_t uid,
const char *privilege,
- const char *resource)
+ const char *resource,
+ gboolean auth_as_root)
{
char *objpath;
PolicyKitSession *session;
@@ -978,17 +963,21 @@ polkit_session_new (DBusGConnection *connection,
g_free (objpath);
session->priv->calling_uid = calling_uid;
- session->priv->calling_pid = calling_pid;
session->priv->calling_dbus_name = g_strdup (calling_dbus_name);
session->priv->grant_to_uid = uid;
session->priv->grant_privilege = g_strdup (privilege);
session->priv->grant_resource = g_strdup (resource);
- /* TODO: look up auth_as_user, auth_with_pam_service from privilege configuration files */
- session->priv->auth_as_user = g_strdup ("root");
+ /* TODO: look up auth_as_user from privilege configuration files */
+ if (auth_as_root)
+ session->priv->auth_as_user = g_strdup ("root");
+ else
+ session->priv->auth_as_user = policy_util_uid_to_name (uid, NULL);
session->priv->auth_with_pam_service = g_strdup ("policy-kit");
+ g_debug ("In polkit_session_new ; established session %d", session->priv->session_number);
+
return session;
}
@@ -996,23 +985,29 @@ polkit_session_new (DBusGConnection *connection,
void
polkit_session_initiator_disconnected (PolicyKitSession *session)
{
- /*g_debug ("initiator disconnected");*/
+ g_debug ("Initiator for session %d disconnected", session->priv->session_number);
/* if we have a child... kill it */
if (session->priv->child_pid != 0)
kill (session->priv->child_pid, SIGTERM);
if (session->priv->have_granted_temp_privileges) {
+ g_debug (" Revoking temporary privilege %s on %s for uid %d on connection %s",
+ session->priv->grant_privilege,
+ session->priv->grant_resource,
+ session->priv->grant_to_uid,
+ session->priv->grant_system_bus_name_unique_name_restriction);
if (!polkit_manager_remove_temporary_privilege (session->priv->manager,
session->priv->grant_to_uid,
session->priv->grant_privilege,
session->priv->grant_resource,
- session->priv->grant_pid_restriction)) {
- g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on pid %d",
+ session->priv->grant_system_bus_name_unique_name_restriction,
+ FALSE)) {
+ g_warning ("Could not remove tmp priv '%s' to uid %d for resource '%s' on connection '%s'",
session->priv->grant_privilege,
session->priv->grant_to_uid,
session->priv->grant_resource,
- session->priv->grant_pid_restriction);
+ session->priv->grant_system_bus_name_unique_name_restriction);
}
}
}
diff --git a/polkitd/polkit-session.h b/polkitd/polkit-session.h
index c02bd22..19fac2f 100644
--- a/polkitd/polkit-session.h
+++ b/polkitd/polkit-session.h
@@ -80,11 +80,11 @@ struct PolicyKitSessionClass
PolicyKitSession *polkit_session_new (DBusGConnection *connection,
PolicyKitManager *manager,
uid_t calling_uid,
- pid_t calling_pid,
const char *calling_dbus_name,
uid_t uid,
const char *privilege,
- const char *resource);
+ const char *resource,
+ gboolean auth_as_root);
/* remote methods */
@@ -102,7 +102,6 @@ gboolean polkit_session_provide_answers (PolicyKitSession
DBusGMethodInvocation *context);
gboolean polkit_session_close (PolicyKitSession *session,
- gboolean do_not_revoke_privilege,
DBusGMethodInvocation *context);
gboolean polkit_session_get_auth_details (PolicyKitSession *session,
@@ -112,7 +111,7 @@ gboolean polkit_session_get_auth_denied_reason (PolicyKitSession
DBusGMethodInvocation *context);
gboolean polkit_session_grant_privilege_temporarily (PolicyKitSession *session,
- gboolean restrict_to_callers_pid,
+ gboolean restrict_to_callers_system_bus_unique_name,
DBusGMethodInvocation *context);
/* local methods */
diff --git a/privileges/desktop-console.privilege b/privileges/desktop-console.privilege
index 112951b..dbd4712 100644
--- a/privileges/desktop-console.privilege
+++ b/privileges/desktop-console.privilege
@@ -1,4 +1,14 @@
-[Policy]
+# This privilege signfies that users holding it are logged into a
+# physical console attached to the system. Thus, it is useful for
+# other privileges for manipulating local devices to simply require
+# this privilege.
+
+[Privilege]
+RequiredPrivileges=
+SufficientPrivileges=
Allow=
Deny=
+CanObtain=False
+CanGrant=False
+ObtainRequireRoot=True
diff --git a/tools/Makefile.am b/tools/Makefile.am
index a8d2a54..a16814b 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -24,27 +24,15 @@ polkit_is_privileged_LDADD = @DBUS_CFLAGS@ @GLIB_LIBS@ $(top_builddir)/libpolkit
polkit_list_privileges_SOURCES = polkit-list-privileges.c
polkit_list_privileges_LDADD = @DBUS_CFLAGS@ @GLIB_LIBS@ $(top_builddir)/libpolkit/libpolkit.la
-polkit-interface-manager-glue.h: ../polkit-interface-manager.xml Makefile.am
- dbus-binding-tool --prefix=polkit_manager --mode=glib-client --output=polkit-interface-manager-glue.h ../polkit-interface-manager.xml
-
-polkit-interface-session-glue.h: ../polkit-interface-session.xml Makefile.am
- dbus-binding-tool --prefix=polkit_session --mode=glib-client --output=polkit-interface-session-glue.h ../polkit-interface-session.xml
-
-
polkit_grant_privilege_SOURCES= \
- polkit-grant-privilege.c \
- polkit-interface-manager-glue.h \
- polkit-interface-session-glue.h
-polkit_grant_privilege_LDADD= @DBUS_GLIB_LIBS@ @GLIB_LIBS@ $(top_builddir)/libpolkit/libpolkit.la
+ polkit-grant-privilege.c
+polkit_grant_privilege_LDADD= @DBUS_GLIB_LIBS@ @GLIB_LIBS@ $(top_builddir)/libpolkit/libpolkit.la $(top_builddir)/libpolkit/libpolkit-grant.la
polkit_revoke_privilege_SOURCES= \
polkit-revoke-privilege.c
polkit_revoke_privilege_LDADD= @DBUS_GLIB_LIBS@ @GLIB_LIBS@ $(top_builddir)/libpolkit/libpolkit.la
-
-BUILT_SOURCES = polkit-interface-manager-glue.h polkit-interface-session-glue.h
-
clean-local :
- rm -f *~ $(BUILT_SOURCES)
+ rm -f *~
diff --git a/tools/polkit-grant-privilege.c b/tools/polkit-grant-privilege.c
index 87054a5..b13f34f 100644
--- a/tools/polkit-grant-privilege.c
+++ b/tools/polkit-grant-privilege.c
@@ -36,27 +36,34 @@
#include <dbus/dbus-glib-lowlevel.h>
#include <libpolkit/libpolkit.h>
+#include <libpolkit/libpolkit-grant.h>
-#include "polkit-interface-manager-glue.h"
-#include "polkit-interface-session-glue.h"
-static char *grant_user = NULL;
-static char *grant_privilege = NULL;
-static char *grant_resource = NULL;
-static char *auth_user = NULL;
-static char *auth_pam_service_name = NULL;
+static gboolean is_verbose = FALSE;
+
static void
-have_questions_handler (DBusGProxy *session, gpointer user_data)
+questions_cb (LibPolKitGrantContext *ctx,
+ const char **questions,
+ gpointer user_data)
{
int i;
- char **questions;
- char **answers;
int num_a;
- GError *error = NULL;
+ char **answers;
+ static gboolean showed_user = FALSE;
+
- if (auth_user != NULL) {
- if (grant_resource != NULL)
+ /* print banner for user if we are going to ask questions */
+ if (!showed_user) {
+ const char *auth_user;
+ const char *auth_pam_svc;
+
+ showed_user = TRUE;
+
+ auth_user = libpolkit_grant_get_user_for_auth (ctx);
+ auth_pam_svc = libpolkit_grant_get_pam_service_for_auth (ctx);
+
+ if (libpolkit_grant_get_resource (ctx) != NULL) {
g_print ("\n"
"Authentication needed for user '%s' in order to grant the\n"
"privilege '%s' to user '%s' for the \n"
@@ -65,10 +72,11 @@ have_questions_handler (DBusGProxy *session, gpointer user_data)
"The privilege is configured to use PAM service '%s'.\n"
"\n",
auth_user,
- grant_privilege, grant_user,
- grant_resource,
- auth_pam_service_name);
- else
+ libpolkit_grant_get_privilege (ctx),
+ libpolkit_grant_get_user (ctx),
+ libpolkit_grant_get_resource (ctx),
+ auth_pam_svc);
+ } else {
g_print ("\n"
"Authentication needed for user '%s' in order to grant the\n"
"privilege '%s' to user '%s'.\n"
@@ -76,29 +84,20 @@ have_questions_handler (DBusGProxy *session, gpointer user_data)
"The privilege is configured to use PAM service '%s'.\n"
"\n",
auth_user,
- grant_privilege, grant_user,
- auth_pam_service_name);
- g_free (auth_user);
- g_free (auth_pam_service_name);
- auth_user = NULL;
- auth_pam_service_name = NULL;
+ libpolkit_grant_get_privilege (ctx),
+ libpolkit_grant_get_user (ctx),
+ auth_pam_svc);
+ }
}
- if (!org_freedesktop_PolicyKit_Session_get_questions (session,
- &questions,
- &error)) {
- g_warning ("GetQuestions: %s", error->message);
- g_error_free (error);
- goto out;
- }
- answers = g_new0 (char *, g_strv_length (questions) + 1);
+ answers = g_new0 (char *, g_strv_length ((char **) questions) + 1);
num_a = 0;
for (i = 0; questions[i] != NULL && questions[i+1] != NULL; i++) {
char *answer;
- char *question = questions[i+1];
- char *qtype = questions[i];
+ const char *question = questions[i+1];
+ const char *qtype = questions[i];
/*g_debug ("Question 1: '%s' (pamtype %s)\n(warning; secret will be echoed to stdout)", question, qtype);*/
@@ -112,7 +111,7 @@ have_questions_handler (DBusGProxy *session, gpointer user_data)
char buf[1024];
fputs (question, stderr);
- answer = fgets (question, sizeof (buf), stdin);
+ answer = fgets ((char *) question, sizeof (buf), stdin);
answers[num_a++] = g_strdup (answer);
/*g_debug ("Provding answer: '%s'", answer);*/
@@ -127,156 +126,31 @@ have_questions_handler (DBusGProxy *session, gpointer user_data)
}
answers[num_a] = NULL;
- g_strfreev (questions);
-
- if (!org_freedesktop_PolicyKit_Session_provide_answers (session,
- (const char **) answers,
- &error)) {
- g_warning ("ProvideAnswers: %s", error->message);
- g_error_free (error);
- goto out;
- }
+ libpolkit_grant_provide_answers (ctx, (const char **) answers);
g_strfreev (answers);
-
-out:
- ;
}
static void
-auth_done_handler (DBusGProxy *session, gpointer user_data)
+grant_complete_cb (LibPolKitGrantContext *ctx,
+ gboolean obtained_privilege,
+ const char *reason_not_obtained,
+ gpointer user_data)
{
- gboolean auth_result;
- GError *error = NULL;
-
- /*g_debug ("in %s", __FUNCTION__);*/
-
- if (!org_freedesktop_PolicyKit_Session_is_authenticated (session,
- &auth_result,
- &error)) {
- g_warning ("IsAuthenticated: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- /*g_message ("Authentication done. %s", auth_result);*/
-
- if (!auth_result) {
- char *auth_denied_reason;
-
- if (!org_freedesktop_PolicyKit_Session_get_auth_denied_reason (session,
- &auth_denied_reason,
- &error)) {
- g_warning ("GetAuthDeniedReason: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- g_print ("\n"
- "Authentication failed (reason: '%s').\n", auth_denied_reason);
- g_free (auth_denied_reason);
+ if (!obtained_privilege) {
+ g_print ("Privilege not granted: %s\n", reason_not_obtained != NULL ? reason_not_obtained : "(null)");
} else {
- g_print ("\n"
- "Authentication succeeded.\n");
-
- /* don't restrict privilege to callers PID */
- if (!org_freedesktop_PolicyKit_Session_grant_privilege_temporarily (session,
- FALSE,
- &error)) {
- g_warning ("GrantPrivilegeTemporarily: %s", error->message);
- g_error_free (error);
- }
+ /* keep the privilege */
+ libpolkit_grant_close (ctx, FALSE);
}
-out:
-
- /* don't revoke privilege when we close the session */
- if (!org_freedesktop_PolicyKit_Session_close (session,
- TRUE,
- &error)) {
- g_warning ("Close: %s", error->message);
- g_error_free (error);
- }
+ libpolkit_free_context (ctx);
exit (0);
}
-static void
-do_grant_privilege (DBusGConnection *conn, const char *user, const char *privilege, const char *resource)
-{
- GError *error = NULL;
- DBusGProxy *manager;
- DBusGProxy *session;
- char *session_objpath;
- GMainLoop *mainloop;
-
- grant_user = g_strdup (user);
- grant_privilege = g_strdup (privilege);
- grant_resource = g_strdup (resource);
-
- mainloop = g_main_loop_new (NULL, FALSE);
-
- manager = dbus_g_proxy_new_for_name (conn,
- "org.freedesktop.PolicyKit",
- "/org/freedesktop/PolicyKit/Manager",
- "org.freedesktop.PolicyKit.Manager");
- if (manager == NULL) {
- goto out;
- }
-
- if (!org_freedesktop_PolicyKit_Manager_initiate_temporary_privilege_grant (manager,
- user,
- privilege,
- resource,
- &session_objpath,
- &error)) {
- g_warning ("GrantPrivilege: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- /*g_debug ("session_objpath = %s", session_objpath);*/
-
- session = dbus_g_proxy_new_for_name (conn,
- "org.freedesktop.PolicyKit",
- session_objpath,
- "org.freedesktop.PolicyKit.Session");
- if (session == NULL) {
- goto out;
- }
-
- dbus_g_proxy_add_signal (session, "HaveQuestions", G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (session, "HaveQuestions", G_CALLBACK (have_questions_handler),
- NULL, NULL);
-
- dbus_g_proxy_add_signal (session, "AuthenticationDone", G_TYPE_INVALID);
- dbus_g_proxy_connect_signal (session, "AuthenticationDone", G_CALLBACK (auth_done_handler),
- NULL, NULL);
-
- if (!org_freedesktop_PolicyKit_Session_get_auth_details (session,
- &auth_user,
- &auth_pam_service_name,
- &error)) {
- g_warning ("GetAuthDetails: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- if (!org_freedesktop_PolicyKit_Session_initiate_auth (session,
- &error)) {
- g_warning ("InitiateAuth: %s", error->message);
- g_error_free (error);
- goto out;
- }
-
- g_main_loop_run (mainloop);
- g_free (session_objpath);
-out:
- ;
-}
-
static void
usage (int argc, char *argv[])
{
@@ -297,15 +171,12 @@ usage (int argc, char *argv[])
"be omitted.\n");
}
-static gboolean is_verbose = FALSE;
-
int
main (int argc, char **argv)
{
int rc;
GError *error = NULL;
DBusGConnection *bus;
- LibPolKitContext *ctx;
char *user = NULL;
char *resource = NULL;
char *privilege = NULL;
@@ -321,9 +192,15 @@ main (int argc, char **argv)
gboolean is_privileged = FALSE;
gboolean is_temporary = FALSE;
LibPolKitResult result;
+ LibPolKitGrantContext *gctx;
+ LibPolKitContext *ctx;
+ GMainLoop *mainloop;
g_type_init ();
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+
rc = 1;
while (TRUE) {
@@ -383,15 +260,26 @@ main (int argc, char **argv)
return 1;
}
- ctx = libpolkit_new_context (dbus_g_connection_get_connection (bus));
+ gctx = libpolkit_grant_new_context (bus,
+ user,
+ privilege,
+ resource,
+ FALSE,
+ NULL);
+ if (gctx == NULL) {
+ g_warning ("Cannot initialize new grant context");
+ goto out;
+ }
+ ctx = libpolkit_grant_get_libpolkit_context (gctx);
result = libpolkit_is_uid_allowed_for_privilege (ctx,
- -1,
+ NULL,
user,
privilege,
resource,
&is_privileged,
- &is_temporary);
+ &is_temporary,
+ NULL);
switch (result) {
case LIBPOLKIT_RESULT_OK:
if (is_privileged) {
@@ -428,7 +316,15 @@ main (int argc, char **argv)
goto out;
}
- do_grant_privilege (bus, user, privilege, resource);
+ libpolkit_grant_set_questions_handler (gctx, questions_cb);
+ libpolkit_grant_set_grant_complete_handler (gctx, grant_complete_cb);
+
+ if (!libpolkit_grant_initiate_temporary_grant (gctx)) {
+ g_warning ("Cannot initiate temporary grant; bailing out");
+ goto out;
+ }
+
+ g_main_loop_run (mainloop);
out:
return rc;
diff --git a/tools/polkit-is-privileged.c b/tools/polkit-is-privileged.c
index 594902e..e6e0cf6 100644
--- a/tools/polkit-is-privileged.c
+++ b/tools/polkit-is-privileged.c
@@ -41,17 +41,17 @@ usage (int argc, char *argv[])
fprintf (stderr,
"\n"
"usage : %s -u <uid> -p <privilege> [-r <resource>]\n"
- " [-i <pid>]", argv[0]);
+ " [-s <system-bus-connection-name>]", argv[0]);
fprintf (stderr,
"\n"
"Options:\n"
- " -u, --user Username or user id\n"
- " -i, --pid Pid of process privilege may be restricted to\n"
- " -r, --resource Resource\n"
- " -p, --privilege Privilege to test for\n"
- " -h, --help Show this information and exit\n"
- " -v, --verbose Verbose operation\n"
- " -V, --version Print version number\n"
+ " -u, --user Username or user id\n"
+ " -s, --system-bus-unique-name Unique system bus connection name\n"
+ " -r, --resource Resource\n"
+ " -p, --privilege Privilege to test for\n"
+ " -h, --help Show this information and exit\n"
+ " -v, --verbose Verbose operation\n"
+ " -V, --version Print version number\n"
"\n"
"Queries system policy whether a given user is allowed for a given\n"
"privilege for a given resource. The resource may be omitted.\n"
@@ -65,10 +65,10 @@ main (int argc, char *argv[])
char *user = NULL;
char *privilege = NULL;
char *resource = NULL;
- pid_t pid = (pid_t) -1;
+ char *system_bus_unique_name = NULL;
static const struct option long_options[] = {
{"user", required_argument, NULL, 'u'},
- {"pid", required_argument, NULL, 'i'},
+ {"system-bus-unique-name", required_argument, NULL, 's'},
{"resource", required_argument, NULL, 'r'},
{"privilege", required_argument, NULL, 'p'},
{"help", no_argument, NULL, 'h'},
@@ -89,14 +89,14 @@ main (int argc, char *argv[])
while (TRUE) {
int c;
- c = getopt_long (argc, argv, "u:r:p:i:hVv", long_options, NULL);
+ c = getopt_long (argc, argv, "u:r:p:s:hVv", long_options, NULL);
if (c == -1)
break;
switch (c) {
- case 'i':
- pid = atoi (optarg);
+ case 's':
+ system_bus_unique_name = g_strdup (optarg);
break;
case 'u':
@@ -157,12 +157,13 @@ main (int argc, char *argv[])
}
result = libpolkit_is_uid_allowed_for_privilege (ctx,
- pid,
+ system_bus_unique_name,
user,
privilege,
resource,
&is_allowed,
- &is_temporary);
+ &is_temporary,
+ NULL);
switch (result) {
case LIBPOLKIT_RESULT_OK:
rc = is_allowed ? 0 : 1;
diff --git a/tools/polkit-list-privileges.c b/tools/polkit-list-privileges.c
index d466805..bd7e941 100644
--- a/tools/polkit-list-privileges.c
+++ b/tools/polkit-list-privileges.c
@@ -27,6 +27,7 @@
#endif
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <dbus/dbus.h>
@@ -136,8 +137,11 @@ main (int argc, char *argv[])
const char *privilege;
gboolean is_allowed;
gboolean is_temporary;
+ char *is_privileged_but_restricted_to;
GList *j;
+ GList *k;
GList *resources;
+ GList *restrictions;
int num_non_temporary;
privilege = (const char *) l->data;
@@ -146,33 +150,46 @@ main (int argc, char *argv[])
}
if (libpolkit_is_uid_allowed_for_privilege (ctx,
- -1,
+ NULL,
user,
privilege,
NULL,
&is_allowed,
- &is_temporary) == LIBPOLKIT_RESULT_OK) {
+ &is_temporary,
+ &is_privileged_but_restricted_to) == LIBPOLKIT_RESULT_OK) {
if (is_allowed) {
g_print ("privilege %s%s\n", privilege, is_temporary ? " (temporary)" : "");
- }
+ } else if (is_privileged_but_restricted_to != NULL) {
+ g_print ("privilege %s (temporary) (restricted to %s)\n",
+ privilege, is_privileged_but_restricted_to);
+ }
if (libpolkit_get_allowed_resources_for_privilege_for_uid (
ctx,
user,
privilege,
&resources,
+ &restrictions,
&num_non_temporary) == LIBPOLKIT_RESULT_OK) {
int n;
- for (j = resources, n = 0; j != NULL; j = g_list_next (j), n++) {
+ for (j = resources, k = restrictions, n = 0; j != NULL; j = g_list_next (j), k = g_list_next (k), n++) {
const char *resource;
+ const char *restriction;
resource = (const char *) j->data;
- g_print ("resource %s privilege %s%s\n",
+ restriction = (const char *) k->data;
+ g_print ("resource %s privilege %s%s",
resource, privilege,
n >= num_non_temporary ? " (temporary)" : "");
+ if (strlen (restriction) > 0)
+ g_print (" (restricted to %s)\n", restriction);
+ else
+ g_print ("\n");
}
g_list_foreach (resources, (GFunc) g_free, NULL);
g_list_free (resources);
+ g_list_foreach (restrictions, (GFunc) g_free, NULL);
+ g_list_free (restrictions);
}
}
diff --git a/tools/polkit-revoke-privilege.c b/tools/polkit-revoke-privilege.c
index e0109be..2e75b8b 100644
--- a/tools/polkit-revoke-privilege.c
+++ b/tools/polkit-revoke-privilege.c
@@ -154,11 +154,11 @@ main (int argc, char **argv)
case LIBPOLKIT_RESULT_OK:
if (was_revoked) {
if (resource == NULL) {
- g_print ("User '%s' no longer has privilege '%s'.\n", user, privilege);
+ g_print ("Privilege '%s' succesfully revoked from user '%s'.\n", privilege, user);
} else {
- g_print ("User '%s' no longer has privilege '%s' for accessing\n"
+ g_print ("Privilege '%s' succesfully revoked from user '%s' on\n"
"resource '%s'.\n",
- user, privilege, resource);
+ privilege, user, resource);
}
rc = 0;
goto out;
@@ -166,23 +166,29 @@ main (int argc, char **argv)
break;
case LIBPOLKIT_RESULT_ERROR:
- g_print ("Error granting resource.\n");
+ g_print ("Error: There was an error granting the privilege.\n");
goto out;
case LIBPOLKIT_RESULT_INVALID_CONTEXT:
- g_print ("Invalid context.\n");
+ g_print ("Error: Invalid context.\n");
goto out;
case LIBPOLKIT_RESULT_NOT_PRIVILEGED:
- g_print ("Not privileged.\n");
+ g_print ("Error: Not privileged to perform this operation.\n");
goto out;
case LIBPOLKIT_RESULT_NO_SUCH_PRIVILEGE:
- g_print ("No such privilege '%s'.\n", privilege);
+ if (resource == NULL) {
+ g_print ("Error: User '%s' does not have privilege '%s'.\n", user, privilege);
+ } else {
+ g_print ("Error: User '%s' does not have privilege '%s' for accessing\n"
+ "resource '%s'.\n",
+ user, privilege, resource);
+ }
goto out;
case LIBPOLKIT_RESULT_NO_SUCH_USER:
- g_print ("No such user '%s'.\n", user);
+ g_print ("Error: No such user '%s'.\n", user);
goto out;
}