Table of Contents
Table of Contents
Table of Contents
One major concept of the PolicyKit system is the notion of privileges; a PolicyKit privilege (referred to simply as privilege 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 method calls through the system message bus. In order to have a flexible security policy defining the set of users that are allowed to invoke a method, the system level component defines a set of privileges.
The PolicyKit system is basically client/server and is
implemented as the
system-wide org.freedesktop.PolicyKit
D-BUS
service. This D-BUS service serves two purposes
System-level components may used D-BUS methods on this service to determine if a given caller of their methods are privileged.
Desktop level applications may initiate a dialogue with this service to (temporarily) obtain a privilege through authorization.
In addition, the PolicyKit system includes client side
libraries and command-line utilities wrapping the D-BUS API of
the org.freedesktop.PolicyKit
service.
As an example, HAL exports the method Mount
on the
org.freedesktop.Hal.Device.Volume
interface
for each hal device object of
capability volume. HAL defines a number
of privileges for mounting
including hal-storage-fixed-mount
and hal-storage-removable-mount. 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 hal-storage-fixed-mount
or hal-storage-removable-mount privilege
in order to carry out the Mount
method.
Upon a user invoking the Mount
method, HAL
simply asks the org.freedesktop.PolicyKit
D-BUS service if the calling user possess this privilege and if
this is not the case the Mount
method
throws
the org.freedesktop.Hal.Device.PermissionDeniedByPolicy
exception. Notably, this exception will tell the caller what
privilege the calling user needs to possess,
e.g. either hal-storage-fixed-mount
or hal-storage-removable-mount.
Should the Mount
method fail with the
exception PermissionDeniedByPolicy
the
caller now knows what privilege is required. The caller can
now initiate a dialogue with the PolicyKit
service to obtain this privilege. This conversation is
basically equivalent to a PAM authentication; in fact the
PolicyKit
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 Mount
and after this succeeds he may
tell the PolicyKit
service to release the
privilege for the user as it is no longer needed. Should the
process crash while holding a privilege,
the PolicyKit
service will be notifed and
the privilege will automatically be revoked.
Hence, PolicyKit
has the notion of
both permament
and temporary 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. 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.
In addition, privileges may be restricted to certain resources; this is discussed in more detail in XXX.
The whole example is outlined in the diagram above.
Table of Contents
PolicyKit allows granting privileges only on
certain resources. For example, for HAL, it
is possible to grant the
privilege hal-storage-fixed-mount to the
user with uid 500 but only for the HAL device object
representing e.g. the /dev/hda3
partition.
Resource identifers are prefixed with a name identifying what service they belong to. The following resource identifiers are defined
hal://
HAL Unique Device Identifiers also known as HAL UID's. Example: hal:///org/freedesktop/Hal/devices/volume_uuid_1a28b356_9955_44f9_b268_6ed6639978f5
Table of Contents
Applications, such as HAL, installs privilege
descriptors into
the /etc/PolicyKit/privilege.d
directory
(or more correct, into
the $sysconfdir/PolicyKit/privilege.d
directory depending on where PolicyKit is built).
A policy descriptor contains the following information:
Criteria for determining if a given user possess the privilege on a given resource.
What privileges are required to possess a given privilege.
What privileges are sufficient to possess to automatically possess a given privilege.
Information on whether the user can obtain the privilege, and if he can, whether only temporarily or permanently.
Whether a user with the privilege may permanently grant it to other users.
A developer of a system-wide application wanting to define a
privilege must create a privilege descriptor. This is a a
simple .ini
-like config file. Here is what
the skeleton looks like:
[Policy] RequiredPrivileges= SufficientPrivileges= Allow= Deny= CanObtain= CanGrant= ObtainRequireRoot=
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. A privilege in this
list is considered being possessed if the user is privileged
for one or more resources. E.g., if foo
is a required privilege then just having this privilege on
one resource is sufficient.
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 RequiredPrivileges
,
if foo
is a sufficient privilege then
just having this privilege on one resource is sufficient.
Both Allow
and Deny
contains lists describing what users are allowed
respectively denied the privilege. The elements of in each
list are of the form
type:value[:resource]
. where the last
part, resource, may be omitted. The following types are
supported:
uid
: Unix user identifer; either
a positive integer or Unix username. Special values
include __all__
(for denoting all
users) and __none__
(for denoting no
users).
gid
: Unix group identifier,
either a positive integer or Unix groupname. Special
values include __all__
(for denoting
all groups) and __none__
(for denoting
no groups).
To determine if a given user is allowed for a given
privilege (for a given resource), first
the SufficientPrivileges
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 RequiredPrivileges
list
is consulted as described above. If the user possess all of
the listed privileges, the Allow
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).
If there is a match in the Allow
list,
the Deny
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).
This logic is best described by a few examples
Allow="uid:davidz uid:501:hal:///deviceFoo gid:admins
uid:502"
Deny="gid:dooders uid:502:hal:///deviceBar"
User davidz
possess this
privilege. All members of
the dooders
group is denied this
privilege. User 501 is allowed this privilege but only
on the hal:///deviceFoo
resource. All users in the admin
group posseses the privilege. User 502 is allowed this
privilege but not on
the hal:///deviceBar
resource.
Allow="uid:__all__"
Deny="gid:normalstaff"
All users expect those in
the normalstaff
group posseses this
privilege.
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 RequiredPrivileges
is not
possessed.
The property can assume the values
True
(the user can obtain the privilege
permanently), Temporary
(the user can
only obtain the privilege temporarily) and
False
(the user can never obtain the
privilege through authentication).
Whether the user needs to autenticate as himself or the
super user is specified in
the ObtainRequireRoot
property. Note that
if the user is lacking one or more of the privileges listed
in RequiredPrivileges
and one of these
has ObtainRequireRoot=True
the user will
have to authenticate as the super user nonwithstanding that
the privilege he attempts to obtain
has ObtainRequireRoot=False
. Moreover, if
any of the lacking privileges
in RequiredPrivileges
has CanObtain
set
to False
, the user will always have to
authenticate as the super user.
This property (it can assume the
values True
and False
)
describes whether an user with the given privilege can
permanently grant it to himself and/or other users,.
Typically, the construct is used in the following kind of UI dialogs:
+----------------------------------------------------+ | 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)
The property CanObtain
needs to assume
the value True
if this property assumes
the value True
. Otherwise this property
effectively assumes the value False
.
If the property CanObtain
assumes the
value True
or Temporary
it means the user can
authenticate to gain a
privilege. The ObtainRequireRoot
property
specifies whether authentication requires the super user
password (True
) or the users own password
(False
).
See the section called “CanObtain
: Obtaining Privileges” for discussion on how
the RequiredPrivileges
property affects
the effective value of this property.
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.
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
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.
The PAM module pam-polkit-console
shipped
with PolicyKit is used to maintain files
in /var/run/polkit-console
for users
logging in and out, and signal the PolicyKit daemon to
reread these files and dynamically grant / revoke
the desktop-console
privilege. Typically,
graphical login managers such as the GNOME Display Manager
(gdm) will want include this in it's stack of PAM modules.
Remote users (e.g. those not at a local console) can obtain
the desktop-console
only by
authenticating as the super user.
The desktop-console
privilege can be used
in conjunction with
the RequiredPrivileges
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:
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
For a remote user with the
privilege hal-system-suspend
it means
that authentication as the super user is required
as desktop-console
has ObtainRequireRoot=True
and this
trumps the ObtainRequireRoot=False
property that is in
the hal-system-suspend
privilege (see
the section called “CanObtain
: Obtaining Privileges”). Of course, if the user is
logged in at a local console no authentication is required.
Typically, the desktop-console
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 console://:0
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.