openSUSE:Security Documentation

Jump to: navigation, search
Security related documentation for openSUSE distributions.

The permissions Package

Purpose

The permissions package is a SUSE specific package that controls the privilege settings for a number of global system files and security sensitive package files in the distribution. It is concerned with the following kinds of file or directory based privileges:

  • the classical UNIX file owner and group assignment of a file.
  • the classical UNIX user/group/world access bits.
  • special file mode bits like the setuid and setgid bit or the sticky bit.
  • capability bits.

These settings are important for the overall system security. For example a badly configured /tmp directory can cause security issues. Furthermore the setuid, setgid and capability bits on files grant special privileges to programs. The SUSE Security Team attempts to keep the number of such programs as low as possible. Since it is not always possible to combine the user experience with maximum security and vice versa.

Available Profiles

To give system administrators more control over the settings the permissions package provides different profiles that can be configured:

  • the easy profile has a focus on ease of use where more program features work out of the box without the user having to intervene. It also means that there is a larger security attack surface. It can be used for typical single user desktop systems when usability is favored over stricter security.
  • the secure profile is more security oriented and disables certain program privileges. This can result in some program features not being available or behaving less conventiently. It can be used for typical server or multi-user host machines.
  • the paranoid profile is a tightly locked down set of settings that isn't fully usable in production, because a lot of program features will stop working. This should only be used when security is the major requirement and when you are willing to tune the profile into a state where you can perform the task you want to fullfill with the system.

You can look up the different profiles in /etc/permissions.easy, /etc/permissions.secure and /etc/permissions.paranoid respectively.

File Format

The structure of these files is line based and each non-comment line has the format:

/path/to/file    <owner>:<group>    <octal-mode>

Customization of Profiles

The predefined profile settings are not to be edited by the system administrator. For customization of individual file permissions the file /etc/permissions.local can be used. Entries found in this file will override entries defined in the predefined profiles. You should only perform customization if you are aware of the implications, however. Bad permission settings can easily break your system or your system's security.

Customization of the profile won't be effective immediately. You will need to run `ckstat` for this to happen. See below for more information.

Changing the Active Profile

The active permissions profile is configured in the configuration file /etc/sysconfig/security. In it the variable PERMISSIONS_SECURITY determines the active profile. Changing this variable's content doesn't immediately perform changes, however. The current profile is applied implicitly when installing or updating packages that require special permissions. You can also explicitly apply the currently configured profile by calling chkstat:

chkstat --system

The chkstat command has a number of other options that allow you to inspect what *would* be changed without actually touching anything.

Further Resources

  • The permissions configuration file man page: man 5 permissions
  • The ckstat utility man page: man 8 chkstat

The polkit Authentication Framework

What is Polkit?

The polkit authentication framework is a mechanism used on the Linux desktop which is used for fine grained management of access rights in the system.

Traditionally there exists a strong separation of privileges on Linux where the root user is allowed to do anything and regular users only have access to well defined files and interfaces. A regular user can be member of a certain set of groups which extends the respective user's privilege for a certain purpose (for example an audio group that allows access to sound hardware). This kind of privilege is fixed, however, and cannot be granted just in certain situations of for a certain duration of time.

To get higher privileges while being logged in as a regular user the usual approach is to completely switch over to the root user. This can be achieved with tools like su or sudo on the command line or similar graphical tools like kdesu and other wrappers that query the root password from the regular user. There are a couple of problems with this approach:

  • it's an all or nothing approach: the new application completely runs as root, even if only a small operation needs to be carried out as root. Running applications as root without necessity is considered bad practice and may create security issues.
  • it's unflexible: the root password needs to be shared with regular users if they shall be able to perform privileged operations. The same applies to all unprivileged users without considering any context like whether it's a local interactive user or a remote background user etc.

This is where polkit comes in. It allows more fine grain management of granting privileges in a system. For example it allows to configure who is allowed to mount a removable storage device in the system and what kind of authorization he needs. How this works in detail is explained in the following sections.

The Typical Authentication Workflow

To achieve the fine grained Polkit authentication typically a small privileged service runs in the background (a daemon) that a regular user can communicate with. In Polkit different activities called actions are defined that can be individually configured. An action firstly is a unique name and can be something like org.freedesktop.hostname1.set-hostname. So now an unprivileged program can request from a privileged service to perform the action org.freedesktop.hostname1.set-hostname. The unprivileged program can also pass additional parameters like in this case the hostname to set for the system.

It is now the job of the background service to determine whether the unprivileged program is allowed to perform the requested operation. The background service uses the Polkit framework to find an answer to that question. For this the Polkit framework differentiates three different user contexts:

  • allow_active: This refers to a locally logged in user that runs in an active session. An active session simply means that you are logged into the graphical desktop environment, for example. It is the most trustful user context, since it refers to an interactive user that probably sits in front of the machine.
  • allow_inactive: This is basically the same context as allow_active but refers to a user session that is not currently active. It could mean that the terminal has been switched to text mode (via ctrl-alt-f1 for example) and the authentication request is still coming from the graphical user session. Another case could be that the user has been switched in the graphical mode to another user.
  • allow_any: This is weakest user context which refers to any other user for example remotely logged in users (SSH) or otherwise unrelated programs.

For each of these contexts an authorization setting is configured for Polkit. The following settings are available:

  • auth_admin: This means that the requesting user needs to enter the Administrator (i.e. root) password to authenticate the action.
  • auth_admin_keep: This is like auth_admin but if the same user program requests the same action again at a later time then the initial authentication is cached and the password needs not to be entered again.
  • auth_self: This means that the requesting user needs to enter his own password again to authenticate the action.
  • yes: This means that the action is granted without further authentication requirements.
  • no: This means that the action is never granted.

With this information and configuration available Polkit performs the following:

  • it determines from what user context the authentication request is originating from e.g. if you're logged into a regular desktop environment and trigger a Polkit authentication then the user context will be allow_active.
  • it determines the configuration setting for this user context. Depending on its value the privileged operation will either be immediately granted (yes) or a password prompt will appear (auth_self, auth_admin). In the latter case the privileged operation will only be granted if the password was successfully entered. Finally the privileged operation may be denied right away (no).
  • the outcome of this decision finding process is reported back from Polkit to the privileged service and the privileged service will only perform the privileged operation if Polkit says the user is authorized for this.

So as we can see from this Polkit does not act on its own but always on behalf of some other program in the system that supports Polkit. There is a long list of programs that provide Polkit support like systemd, NetworkManager, libvirt and a lot more.

Configuration of Polkit Settings

The configuration of the Polkit framework is not all that easy unfortunately. There are a couple of different mechanisms involved. First of all individual packages that use Polkit ship so called policy files which can be found in the system directory /usr/share/polkit-1/actions. These policy files are XML documents that define the various Polkit actions and their authorization settings. This is a snippet from the org.freedesktop.hostname1.policy file:

<action id="org.freedesktop.hostname1.set-hostname">
    <description gettext-domain="systemd">Set host name</description>
    <message gettext-domain="systemd">Authentication is required to set the local host name.</message>
    <defaults>
        <allow_any>auth_admin_keep</allow_any>
        <allow_inactive>auth_admin_keep</allow_inactive>
        <allow_active>auth_admin_keep</allow_active>
    </defaults>
</action>

This snippet defines the authorization requirements for all three users contexts (any, inactive, active) for the polkit action org.freedesktop.hostname1.set-hostname. These authorization settings are predefined by the package developers and shouldn't be changed directly in the policy files.

On OpenSUSE there is a SUSE specific package called polkit-default-privs that further customizes the Polkit configuration. There exist three predefined profiles easy, standard and restrictive that are defined in the files /etc/polkit-default-privs.easy, /etc/polkit-default-privs.standard and /etc/polkit-default-privs.restrictive respectively. In these files you will find lines of the following form:

<action-id> <ANY-USER-AUTH>:<INACTIVE-USER-AUTH>:<ACTIVE-CONSOLE-AUTH>

For example the line org.freedesktop.hostname1.set-hostname auth_admin:auth_admin:yes expresses that for the set-hostname action the authentication requirements are auth_admin for other user contexts and the inactive user context and yes for the active user context. If all three auth fields should have the same value then the line can also be written as org.freedesktop.hostname1.set-hostname auth_admin, without any colon separators.

The easy profile is, like for the permissions package described above, a profile suitable for single user desktop computers where the only user is always also the Administrator of the system. The standard profile is a mixture of settings suitable for multi user systems. The restrictive profile is the most conservative polkit profile that is mostly useful for security aware people and server systems.

The currently active polkit profile can be configured in /etc/sysconfig/security via the configuration variable POLKIT_DEFAULT_PRIVS="...". Changing this variable doesn't have any immediate effect, however. You will need to run the program set_polkit_default_privs to regenerate the active Polkit configuration.

On top of the baseline Polkit profile you can customize individual Polkit rules by entering lines into the file /etc/polkit-default-privs.local. This file will not be overwritten by updates. Be careful not to relax settings to much in this file, because many Polkit actions that normally require auth_admin authorization often carry a lot of power. Settings in this file also require regeneration of the current Polkit rules by calling set_polkit_default_privs.

Beyond these declarative configuration files for Polkit there exists also the possibility to run more complex scripts to determine Polkit authorization. These scripts are written in Java Script and are located in /usr/share/polkit-1/rules.d and in /etc/polkit-1/rules.d. Whenever an authorization decision needs to be made the Polkit framework processes the scripts found in those two directories in alphabetically sorted order. Whichever script returns an authorization decision first decides the outcome. By way of this mechanism Polkit also allows everything for the root user and the polkit-default-privs implements the profile support this way. Using this approach should only be considered by advanced users, however.

Debugging Polkit

Determining why a certain Polkit action requires an Admin password or where a certain authentication window is suddenly popping up from can be difficult to understand. This is because a lot of different components and configuration items are interacting with each other. Also the end user usability is not always the first priority among developers of applications. This section attempts to give some pointers on how to find out more about what is going on with Polkit.

The Polkit Authentication Agent

Polkit uses a so called agent that helps with acquiring passwords from the user and also displays authentication requests to the user. These agents need to run in the user context. When you are logged into a fully blown desktop environment like Gnome or KDE then such an agent is already available and you don't need to worry about it. When running remotely, on the console or from a lightweight desktop environment then you may need to start such an agent explicitly. For example for the text mode the program pkttyagent is available. It's use is a bit clunky on the console and it also doesn't support all Polkit features but it's a start.

Inspecting Actions and Testing Authorization

You can get more detailed information about a single Polkit action by using the pkaction utility like this:

$ pkaction --action-id org.freedesktop.hostname1.set-hostname --verbose
org.freedesktop.hostname1.set-hostname:
  description:       Set host name
  message:           Authentication is required to set the local host name.
  vendor:            The systemd Project
  vendor_url:        http://www.freedesktop.org/wiki/Software/systemd
  icon:
  implicit any:      auth_admin_keep
  implicit inactive: auth_admin_keep
  implicit active:   auth_admin_keep

The authorization settings displayed here are only the vendor presets as defined in the files in /usr/share/polkit-1/actions, however. This does not take into account the settings that polkit-default-privs performs.

You can also check whether a certain process currently has the privilege to perform a certain Polkit action by using the utility pkcheck:

$ pkcheck --action-id org.freedesktop.hostname1.set-hostname --process $$
[...]
$ [ $? -eq 0 ] && echo "authorized"

The utility returns an exit code of zero if the current process is authorized for the given action. It does not return zero if a password would be to be entered for authorization.

Debugging polkitd

Polkit uses a central daemon running in the background called polkitd. This daemon manages the communication between polkit enabled programs and background service and the polkit agent that queries passwords and displays authorization messages. Therefore polkitd is a good place to look into for debugging.

There doesn't seem to be a configuration file to enable debugging and the default log messages are somewhat sparse. You can restart polkitd in a root shell, however, to get more information:

root # G_MESSAGES_DEBUG=all /usr/lib/polkit-1/polkitd --replace

Running this command will cause a possibly already running polkitd instance to be replaced and runs a new instance in the foreground. Any polkit requests will then cause messages to be printed on the console. Note that this approach may interfere with running applications or other users in the system.

Further Resources