By Tim Schürmann
By default, Linux delegates responsibilities: The only user permitted to modify system settings is the omnipotent root
; normal users are restricted to their desktops.
In daily use, this restriction can be a nuisance, especially if you just want to mount a USB stick or set the system clock. If several users share a PC, the root user has to be sitting in front of the keyboard to make the changes.
A young project called PolicyKit [1] provides a more refined solution to the problem of setting access privileges. PolicyKit supports independent privilege management reminiscent of telephone directory assistance: Linux programs can "call" to ask whether a user is allowed to execute a specific system function.
On Ubuntu, when you try to set the system clock, before the window hidden behind System | Administration | Time and Date lets you make any changes, you first have to click the padlock or shield icon. After doing so, the Time and Date Settings ask PolicyKit whether you are authorized to set the clock.
To answer this question, PolicyKit checks the ruleset, which says you are only allowed to change the time if you are a member of the Administrator group and can supply a matching password. PolicyKit then asks the Gnome desktop manager to prompt you for your password.
Gnome immediately does so and pops up the windows shown in Figure 1. Once PolicyKit has all the information it needs, it gives the thumbs up to the Time and Date Settings, which in turn unblock the full functionality of the dialog.
By using this approach, PolicyKit can grant or revoke privileges in a targeted manner. For example, you could allow a user, who I will call carlo, to set the clock but not give him access to any other system functions. In contrast to su
or sudo
, the applications involved here are not given root privileges; that is, carlo would not be allowed to use the time and date window to set the time zone or access any other part of the system.
This brave new PolicyKit world has a couple of blemishes. For example, both the applications and the distribution need to support PolicyKit - at least on Ubuntu right now. OpenSUSE 11.2 and Fedora 12 still require the root password for most system settings. OpenSUSE uses PolicyKit to allow software updates by any user, but for nothing else.
On top of this, version 0.9.1 of the system was completely reworked; recent PolicyKit versions are no longer downwardly compatible. Therefore, developers have to modify or rework any applications that support PolicyKit, prompting distributors to take a fairly blunt approach of providing both the legacy and the latest versions. The latest version is often unofficially dubbed PolicyKit-1, or polkit-1 for short, to distinguish between the two.
The latest version doesn't support the graphical privilege manager, which will only work with legacy PolicyKit versions up to 0.9.0. For privilege management tasks, you have no alternative but to use your favorite editor, but this is actually less daunting than you might expect.
PolicyKit-1 distinguishes between normal users and administrators. Administrators can tweak system settings by default just like root. The configuration files in the /etc/polkit-1/localauthority.conf.d
define the members. Out of the box, PolicyKit has a single file, 50-localauthority.conf
, with the entry
[Configuration] AdminIdentities=unix-user:0
that tells PolicyKit to require the (unix-user
) password for the user with ID 0
for all (AdminIdentities
) that require administrative privileges. Of course, ID 0
designates the root user. In other words, installing PolicyKit doesn't change anything. On Ubuntu, a second configuration file, called 51-ubuntu-admin.conf
, overwrites this rule with the following content:
[Configuration] AdminIdentities=unix-group:admin
In line with this, all members of the admin
user group are automatically privileged administrators. Although you can easily modify the defaults to suit your own needs, the next time you update your system, the file will revert to its original state and all your work will be lost. Fortunately, PolicyKit evaluates its configuration files in lexicographic order, so creating your own configuration file will override any other configuration files whose file names start with a smaller number.
To give the users adam and bonny administrative privileges, you would create a 60-myconfig.conf
file in the /etc/polkit-1/localauthority.conf.d
directory and add the following lines:
[Configuration] AdminIdentities=unix-group:admin;unix-user:adam;unix-user:bonny
It doesn't really matter how you name the file, it just has to start with a higher number (60
in this example) than the others. The future admins are separated by colons and follow AdminIdentities=
. Individuals adam and bonny thus need the unix-user:
prefix. User groups are indicated by unix-group:
.
Under the Hood |
PolicyKit comprises a number of modules, and a request to it always triggers a kind of chain reaction. Initially, a non-privileged program, known as a client, triggers a function in a privileged program, or "mechanism." For example, a desktop applet (the client) could try to switch the computer to sleep mode with the use of DeviceKit (mechanism). The mechanism checks with PolicyKit to determine whether the client is allowed to trigger this action. To do so, it sends a request to the If the mechanism finally receives a positive response via D-Bus from PolicyKit, it will execute the requested function; otherwise, it cancels the action and issues an error message. Figure 2 illustrates the whole process. |
Rules define who is permitted to call system functions. PolicyKit calls them "Authorization Entries" and groups them in the /etc/polkit-1/localauthority
directory in its subfolders. Some rules belong in 50-local.d
; Table 1 lists the others.
To allow the non-privileged user carlo to set the clock, you would create a new configuration file with the extension .pkla
(PolicyKit Local Authority). Again, the file name doesn't really matter: PolicyKit simply evaluates all the .pkla
files in this directory in ascending lexicographic order. However, it makes sense to choose an intuitive name. For clock-setter carlo, the file would look like Listing 1.
Listing 1: Set the Clock |
01 [Carlo allowed to set the clock] 02 Identity=unix-user:carlo 03 Action=org.gnome.clockapplet.mechanism.settime 04 ResultActive=yes 05 ResultInactive=no 06 ResultAny=no |
A free-text description in square brackets opens the file. It is followed by the Identity=
keyword and the user or users to whom the following privilege changes apply. Multiple users and groups need to be comma separated (as mentioned earlier) and follow the familiar unix-users:
or unix-group:
keywords.
The next line contains the name of the system function or action in question, org.clockapplet.mechanism.settime
, which refers to setting the clock in Gnome. Typing pkaction --verbose
at the command line will tell you what other actions PolicyKit supports. The list can be fairly long depending on your distribution; the following command redirects output into the text file list.txt
for easier inspection:
$ pkaction --verbose > list.txt
The password prompt dialog in Gnome shown in Figure 3 provides another useful piece of information. The Details section reveals the Action the user tried to perform.
In the .pkla
file, you can use a wildcard (*
) to group multiple actions. For example,
Action=org.gnome.clockapplet.mechanism.*
modifies all actions that start with org.gnome.clockapplet.mechanism.
at the same time. These privileges mean that carlo can set the time and change the time zone.
The last three lines in the rule in Listing 1 define the privileges. When carlo attempts to perform an action in the current session, PolicyKit references the ResultActive=
setting: yes
lets carlo change the time without a prompt; auth_self
forces him to enter his own password, and auth_self_keep
tells PolicyKit to remember the password for a couple of seconds. If carlo needs to change the time again during this period, he doesn't have to retype his password.
apt-get
with root privileges.Finally, auth_admin
prompts the user to enter the administrative password. This can be any user listed after AdminIdentities=
in the /etc/polkit-1/localauthority.conf.d/60-myconfig.conf
file - in this example, adam and bonny. Table 2 shows the other supported values for ResultActive
. Following the same pattern, ResultInactive
handles queries originating from inactive sessions; ResultAny
doesn't distinguish between active and inactive sessions.
On the basis of the pattern shown earlier, you can now add more sections to your .pkla
file and thus tweak your privilege assignments. In a production environment, rules for a single action normally will be grouped in a file, which is then named for the action. The changes for carlo would thus be saved in org.gnome.clockapplet.mechanism.pkla
.
PolicyKit applies new rules immediately without a reboot. On Ubuntu, however, the modifications don't change the user's ability to set the clock: Canonical seems to have redirected the system settings so that clicking on the padlock icon queries org.freedesktop.systemtoolsbackends.set
. To allow bonny to set the clock, I need to modify line 3 in Listing 1 as follows:
Action=org.freedesktop.systemtoolsbackends.set
As the action name suggests, this would give bonny access to all other system settings. She would not just be able to set the time but to tamper with user management. On Ubuntu, it would thus be easier to add bonny to the Administrator group.
With PolicyKit, you can let normal users launch system programs. To allow this to happen, pkexec
replaces the familiar sudo
tool. For example, the command
$ pkexec --user bonny /usr/bin/apt-get
launches the package manager in the context of the bonny user account (see also the "Password Pitfalls" box). The application is executed in a minimal and secure environment. Although this makes it impossible to inject malicious code, it also makes it impossible to launch X11 programs with another user's account.
By default, only administrators - that is, the users listed in the /etc/polkit-1/localauthority.conf.d/60-myconfig.conf
configuration file - are allowed to use pkexec
to launch a program. To allow non-privileged user carlo to launch programs, you simply create a new rule. The action for this is org.freedesktop.policykit.exec
(Listing 2).
Listing 2: Non-Privileged Users Launch Programs |
01 [Allow program execution via pkexec] 02 Identity=unix-user:carlo 03 Action=org.freedesktop.policykit.exec 04 ResultActive=yes 05 ResultInactive=no 06 ResultAny=no |
The code in Listing 2 would allow carlo to launch any program he likes via pkexec
. If you only want to let carlo launch apt-get after entering his password, another special configuration file is needed.
Password Pitfalls |
Pkexec's behavior with password prompts is logical but confusing at first glance. If you enter the command $ pkexec --user bonny apt-get install gnuchess you launch pkexec apt-get install gnuchess PolicyKit will now prompt for Bonny's password, launch apt-get with root privileges, and install |
PolicyKit can only respond to a request if it knows the action in question. Applications thus first have to tell PolicyKit the system functions they offer. For this to happen, you package the required information in one or multiple XML files that reside in the /usr/share/polkit-1/actions
subdirectory, which is also where you will find org.gnome.clockapplet.mechanism.policy
with the actions for the Gnome clock applet that require authentication via PolicyKit.
Launching the /usr/bin/apt-get
program is just another action. To apply access controls, you need to add another XML file (see Listing 3).
Listing 3: Applying Access Controls |
01 <?xml version="1.0" encoding="UTF-8"?> 02 <!DOCTYPE policyconfig PUBLIC 03 "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" 04 "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd"> 05 <policyconfig> 06 07 <vendor>Linux New Media AG</vendor> 08 <vendor_url>http://www.linuxnewmedia.de</vendor_url> 09 10 <action id="de.linuxnewmedia.example.run-apt-get"> 11 <description>run apt-get</description> 12 <description xml:lang="en">run apt-get</description> 13 <message>You need to authenticate to modify the system configuration</message> 14 <message xml:lang="en">You must identify yourself to run the program apt-get</message> 15 <defaults> 16 <allow_any>no</allow_any> 17 <allow_inactive>no</allow_inactive> 18 <allow_active>auth_self_keep</allow_active> 19 </defaults> 20 <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/apt-get</annotate> 21 </action> 22 23 </policyconfig> |
The structure is more complex than the configuration files we have looked at thus far. The cryptic characters at the start are a must for any XML file. The publisher or developer is revealed between the <vendor>
and </vendor>
tags, and the address is shown in <vendor_url>
. The definition of the action to be executed, which starts with <action id=
, and a unique name, which PolicyKit also refers to as an Action ID, follows. Any name is fair game, as long as it is made up of numbers, lowercase letters, dots, and dashes. The convention is to use the vendor's URL back-to-front and append the action name.
A description of the action is given between the <description>
and </description>
tags; <description xml:lang="en">
is used for the English translation. You can add descriptions for other languages in the same way; the org.gnome.clockapplet.mechanism.policy
gives you a good example. The password prompt window displays the message
text, and <message xml:lang="en">
provides the English version. The defaults
section defines the default privileges. The command
<allow_active>auth_admin</allow_active>
tells pkexec
not to run the program until the user in the active session (allow_active
) has entered an administrative password (auth_admin
). Later on, you can overwrite these settings individually with a .pkla
file in /etc/polkit-1/localauthority/50-local.d
.
All values from Table 2 are permitted between allow_active
tags. allow_inactive
handles requests from inactive sessions in a similar way (and corresponds to ResultInactive
), whereas allow_any
(as a counterpart to ResultAny
) does not worry about origins.
Finally, the path to the program is specified in <annotate key="org.freedesktop.policykit.exec.path">
, which is the Apt package manager in this example.
Although you need to save the action description with a .policy
extension, the file name itself is again unimportant; the convention is to follow the action ID.
Now you need to set up a special (exception) rule for user carlo in the /etc/polkit-1/localauthority/50-local.d
(Listing 4) that allows carlo to launch the apt-get program via pkexec
without entering a password. Unfortunately, pkexec
doesn't check the parameters that a user passes in with the program. In the example here, carlo could install an arbitrary (malicious) package.
Listing 4: Launching Without a Password |
01 [Release apt-get program for Carlo] 02 Identity=unix-user:carlo 03 Action=de.linuxnewmedia.example.run-apt-get 04 ResultActive=yes 05 ResultInactive=no 06 ResultAny=no |
PolicyKit gives administrators an extremely flexible tool for tailoring access profiles. In contrast to su
and sudo
, PolicyKit doesn't just give the user a "get out of jail free" card for the whole application; rather, it restricts the user to individual system functions. Additionally, users don't need to detour to the command line; at most, they will be prompted to enter their password.
In more complex scenarios, the rules can easily become cluttered, and using a text editor to create and maintain them isn't exactly convenient. Additionally, PolicyKit drops another privilege management system on top of Linux's own system.
Even if you use PolicyKit to keep carlo from running a program, he might still be able to run the program directly or by using sudo
. This means that you need to keep an eye on both your PolicyKit settings and legacy privileges.
For PolicyKit to succeed, developers must support it explicitly in their applications; desktop systems have to provide a password dialog, and distributions have to be more consistent in their use of PolicyKit. The current versions of openSUSE, Fedora, and Ubuntu show that there is still much ground to cover.
INFO |
[1] PolicyKit: http://www.freedesktop.org/wiki/Software/PolicyKit
|