ACC SHELL
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Theory of Operation</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="index.html" title="PolicyKit Library Reference Manual">
<link rel="up" href="model.html" title="PolicyKit Model">
<link rel="prev" href="model-concepts.html" title="Concepts">
<link rel="next" href="model-authentication-agent.html" title="Authentication Agent">
<meta name="generator" content="GTK-Doc V1.14 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle">
<td><a accesskey="p" href="model-concepts.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
<td><a accesskey="u" href="model.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
<th width="100%" align="center">PolicyKit Library Reference Manual</th>
<td><a accesskey="n" href="model-authentication-agent.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
</tr></table>
<div class="sect1" title="Theory of Operation">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="model-theory-of-operation"></a>Theory of Operation</h2></div></div></div>
<p>
The core of PolicyKit is implemented as a shared library that
Mechanisms can link to and use as the decider component. There's
a small set of (extensible) data structures that establish a
vocabulary for <code class="literal">libpolkit</code> and the Mechanism to
describe the Subject and Action in question. The Mechanism
should think about <code class="literal">libpolkit</code> as a black box;
it's sole purpose is to answer whether a given Subject is
permitted to do a specific Action. The answer, obviously, comes
from a configuration source read by the library and maintained
by the system administrator; see <a class="xref" href="polkit-conf.html" title="PolicyKit configuration"><i>PolicyKit configuration</i></a>
for details on PolicyKit configuration.
</p>
<p>
The answer from <code class="literal">libpolkit</code> is not limited to a
boolean value; essentially the following values can be returned
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
<span class="emphasis"><em>Yes:</em></span> It is ok for the Mechanism to
carry out the Action requsted by the given Subject.
</p></li>
<li class="listitem"><p>
<span class="emphasis"><em>No:</em></span> The Mechanism should not carry
out the Action requested by the given Subject.
</p></li>
<li class="listitem"><p>
<span class="emphasis"><em>Require authentication:</em></span> The Subject
(e.g. the UI application) needs to ask the user to
authenticate in order for the Mechanism to carry out this
Action.
</p></li>
</ul></div>
<p>
In addition,
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
Authentication can be specified (in the return value
from <code class="literal">libpolkit</code>) as either user
authentication (user puts in his own password) or super
user authentication (user puts in the root password or a
user in an administrator group authenticates).
</p></li>
<li class="listitem"><p>
The authorization can be kept (this is also specified in
the return value from <code class="literal">libpolkit</code>) either
1) indefinitely (e.g. it persists across reboots and
different desktop sessions); 2) for the remainder of the
desktop session the Subject is part of; or 3) confined to
the process life-time of the Subject.
</p></li>
</ul></div>
<p>
</p>
<p>
To facilitate the authentication step, there's a shared library
called <code class="literal">libpolkit-grant</code>. Given an Action, this
library uses a privileged helper (as in it's a <code class="literal">setgid
polkit</code> application) to authenticate the user (using
PAM) and upon successful authentication leave a cookie
specifying that the given Action can be carried out. It is the
presence and contents of this cookie that will
allow <code class="literal">libpolkit</code> to
return <span class="emphasis"><em>Yes</em></span> when the Subject asks the
Mechanism to carry out the Action again. This whole process is
best explained by a diagram:
</p>
<p>
<img src="diagram-interaction.png">
</p>
<p>
Detail on the diagram:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem"><p>
The user double clicks an icon on the desktop that
resembles a hard drive. As mounting file systems is a
privileged operation, the File Manager calls, via the
system message bus, into the Mechanism (HAL).
</p></li>
<li class="listitem">
<p>
The Mechanism identifies the caller, using ConsoleKit, all
the relevant information about the caller and stores this
information in
a PolKitCaller
object. This information includes
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
UNIX user id (uid)
</p></li>
<li class="listitem"><p>
UNIX process id (pid)
</p></li>
<li class="listitem"><p>
An identifier for the desktop session and whether
the session is active (e.g. currently showing on a
display), whether it's local and if it's remote, the
address of the remote display
</p></li>
<li class="listitem"><p>
Optional OS specific attributes such as the SELinux security context.
</p></li>
</ul></div>
<p>
</p>
<p>
Second, the Mechanism creates
a PolKitAction
object that represents the action that the caller wants
the Mechanism to perform on it's behalf. Specifically, for
HAL, the D-Bus method call <code class="literal">Mount()</code> maps
into two
actions: <code class="literal">org.freedesktop.hal.storage.mount-fixed</code>
and <code class="literal">org.freedesktop.hal.storage.mount-removable</code>. As
the device the user wants to mount is an internal hard
disk, HAL
picks <code class="literal">org.freedesktop.hal.storage.mount-fixed</code>
and constructs
the PolKitAction
object.
</p>
<p>
Third, HAL now calls
the <a class="link" href="polkit-Context.html#polkit-context-can-caller-do-action" title="polkit_context_can_caller_do_action ()">polkit_context_can_caller_do_action()</a>
function in <code class="literal">libpolkit</code> and passes
the PolKitAction
and PolKitCaller
objects as parameters. Armed with all this
information, <code class="literal">libpolkit</code> is now in a
position to make a decision; see
<a class="xref" href="polkit-conf.html" title="PolicyKit configuration"><i>PolicyKit configuration</i></a> for how exactly this is
done.
</p>
<p>
The result
from <code class="literal">libpolkit</code> is of the
type PolKitResult
and tells whether the given caller is allowed to do the
given action. If the result is yes
(e.g. POLKIT_RESULT_YES), the Mechanism carries out the
action on behalf of the caller.
</p>
</li>
<li class="listitem">
<p>
If the result from <code class="literal">libpolkit</code> is not
yes, the Mechanism sends a reply back to the caller with
two pieces of information:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
The result from <code class="literal">libpolkit</code> itself.
</p></li>
<li class="listitem"><p>
The action that the caller needs to be authorized to
do.
</p></li>
</ul></div>
<p>
For this example, HAL returns an exception via D-Bus with
the
name <code class="literal">org.freedesktop.Hal.Device.PermissionDeniedByPolicy</code>
and the detail text
string <code class="literal">"org.freedesktop.hal.storage.mount-fixed
auth_admin_keep_always"</code> (assuming the return code
was POLKIT_RESULT_AUTH_ADMIN_KEEP_ALWAYS). This enables
the caller to take action and acquire authorization to do
this action.
</p>
</li>
<li class="listitem">
<p>
The File Manager receives the exception from the Mechanism
and since the exception
name <code class="literal">org.freedesktop.Hal.Device.PermissionDeniedByPolicy</code>
is well-defined it decodes the exception detail string to
learn that in order to do what the user asked it (by
double clicking an icon resembling a hard drive), it needs
to make the user authenticate as an administrator in order
to be authorized for the
action <code class="literal">org.freedesktop.hal.storage.mount-fixed</code>.
</p>
<p>
The File Manager now proceeds to call into
an <span class="emphasis"><em>Authentication Agent</em></span> and passes
two items of information
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
The PolKitResult
that <code class="literal">libpolkit</code> returned to the
Mechanism and passed on to the File Manager.
</p></li>
<li class="listitem"><p>
The PolKitAction
that <code class="literal">libpolkit</code> returned to the
Mechanism and passed on to the File Manager.
</p></li>
</ul></div>
<p>
In fact, the File Manager could implement an
Authentication Agent by itself but for both practical
reasons (implementing an Authentication Agent is not
trivial) and security reasons (it is typically a good idea
to have password handling in as few processes as possible)
it is preferable to have this done in a separate
process. PolicyKit defines an abstract interface to
interact with the an Authentication Agent, see the
<a class="link" href="model-authentication-agent.html" title="Authentication Agent">Authentication
Agent section</a> for details. For details on the
Authentication Agent for the GNOME desktop, please see
the <a class="ulink" href="http://hal.freedesktop.org/docs/PolicyKit-gnome/ref-auth-daemon.html" target="_top">PolicyKit-gnome</a>
documentation.
</p>
</li>
<li class="listitem">
<p>
The first thing that the Authentication Agent does when it
receives a request from an application is to validate the
incoming parameters to see if they are correct;
essentially it's doing exactly the same check as the
Mechanism was doing in step 2;
e.g. constructing PolKitCaller
and PolKitAction
objects, calling
into <a class="link" href="polkit-Context.html#polkit-context-can-caller-do-action" title="polkit_context_can_caller_do_action ()">polkit_context_can_caller_do_action()</a>
and examining the
returned PolKitResult.
</p>
<p>
If the parameters check out, the Authentication Agent now
pops up a window to explain the user than authentication
is required to perform the desired action. Note that the
text to put in the dialog stems from files that are not
under the users control (see
<a class="xref" href="polkit-conf.html#conf-declaring-actions" title="Declaring Actions">the section called “Declaring Actions”</a> for details) so
there is no chance for any application to spoof the dialog
to trick the user into agreeing to authenticate for
something while in fact the authentication is about
something else.
</p>
<p>
Internally the Authentication Agent uses services provided
by the
PolKitGrant
class and is little more than a thin layer above the PAM
user API. The authentication itself is performed in a
privileged helper program (e.g. running
with <a class="ulink" href="http://en.wikipedia.org/wiki/Setgid" target="_top">setgid</a>
privileges) that communicates with the (graphical)
Authentication Agent through pipes. As such, if the user
successfully authenticates, the privileged helper program
writes an entry into the Authorization Database (it can do
so only because it is privileged). When the user is done
with the dialog (either through successful authentication
or by cancelling) a reply including whether the
authorization was gained is sent back to the File Manager
</p>
<p>
As mentioned, an authorization has a notion of scope which
is indicated in
the PolKitResult
value from <code class="literal">libpolkit</code>. The user, when
authenticating, can also opt to lessen the scope
(e.g. keep the authorization only for the remainder of his
desktop session instead of forever)
(see <a class="link" href="polkit-Authorizations-and-Authentication.html#PolKitGrantOverrideGrantType" title="PolKitGrantOverrideGrantType ()">this
section</a> for details) but he can never widen it -
this is checked and enforced by the privileged helper
program. The way the authorization is stored is as
follows:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>
For POLKIT_RESULT_AUTH_[SELF|ADMIN] the
authorization is limited to the requesting process;
in this example it would be the File Manager. Thus,
the UNIX process id (and start time of the process
to avoid clashes caused by pid recycling) is used as
the primary key in the Authorization
Database. Entries like these are flushed when the
system is restarted.
</p></li>
<li class="listitem"><p>
For POLKIT_RESULT_AUTH_[SELF|ADMIN]_KEEP_SESSION the
authorization is limited to processes in the same
desktop session as the calling process (e.g. the
File Manager). The ConsoleKit session identifier is
used as the the primary key in the Authorization
Database. Entries like these are also flushed when
the system is restarted.
</p></li>
<li class="listitem"><p>
For POLKIT_RESULT_AUTH_[SELF|ADMIN]_KEEP_ALWAYS the
authorization is limited to processes owned by the
same user as the calling process (e.g. the File
Manager). The UNIX uid of the user is used as the
the primary key in the Authorization Database. These
entries are not flushed when the system is
restarted.
</p></li>
</ul></div>
<p>
</p>
</li>
<li class="listitem"><p>
If the File Manager is told by the Authentication Agent
that the authorization for it to do the
action <code class="literal">org.freedesktop.hal.storage.mount-fixed</code>
was obtained (because the user successfully
authenticated), it asks the Mechanism (HAL to perform the
action again. This time, because an entry now exists in
the Authorization Database, the Mechanism (HAL) will
receive the answer POLKIT_RESULT_YES
from <code class="literal">libpolkit</code> and carry out the action
on behalf of the File Manager.
</p></li>
</ol></div>
<p>
</p>
<p>
Furthermore, as hinted above, any program can check,
using <code class="literal">libpolkit</code>, whether a given caller is
authorized to do a specific Action (though users may be limited
to asking questions only about themselves; not about other
users). This is a feature, not a bug, as it allows to build user
interfaces where it's possible to use this information to aid
the user in carrying out work.
</p>
<p>
For example, the UI configuration dialog for the desktop clock
may provide a button for reconfiguring the system time (which is
a privileged operation). Using <code class="literal">libpolkit</code>, the
desktop code can determine, in advance, if the user is
authorized to do the
Action <code class="literal">org.gnome.clockapplet.mechanism.settime</code>. If
the user is authorized, the desktop will paint an ordinary
button <code class="literal">"Set System Time"</code>, if authentication
is required, it can paint another button <code class="literal">"[L] Set
System Time..."</code> where the L is an icon depicting a
closed padlock and if the answer is POLKIT_RESULT_NO it can make
the button insensitive so it can't be clicked. In fact, the
aforementioned PolicyKit-gnome library, provides
exactly <a class="ulink" href="http://hal.freedesktop.org/docs/PolicyKit-gnome/PolKitGnomeAction.html" target="_top">such
services</a> for GTK+ applications.
</p>
<p>
In order to keep the PolicyKit model reasonably simple, there is
no representation of the Object. Instead, a Mechanism that cares
about Objects (and many don't; for example, Mechanisms to change
the timezone, punch a hole in the firewall or add a user all
operate on a singleton Object: the system as a whole) must
instead divide a given Action into multiple sub-Actions
depending on the nature of the Object.
</p>
<p>
For example, consider a Mechanism for dial-up networking. Here,
the Subject is a UI applet running in a desktop session, the
Object is the phone number to dial and the Action is to
establish the connection (another Action could be to hang-up an
existing connection). Suppose that the Mechanism has a
white-list of phone numbers that are trusted; this could simply
be a
directory <code class="literal">/var/lib/dialup-helper/trusted-dialup.d</code>
where the system administrator can drop simple text or XML files
with phone numbers that are considered safe to dial. If the
phone number given by the client matches this white-list, the
Mechanism chooses the Action to
be <code class="literal">dialup-connect-trusted</code>. If it's not in the
white-list, the Action will be
<code class="literal">dialup-connect-untrusted</code>. Hence, depending
on how PolicyKit is configured it may return different answers
since these are different Actions; one sensible thing in a
default desktop rollout would be to always allow the
Action <code class="literal">dialup-connect-trusted</code> for local
active sessions and always require authentication for the Action
<code class="literal">dialup-connect-untrusted</code>.
</p>
</div>
<div class="footer">
<hr>
Generated by GTK-Doc V1.14</div>
</body>
</html>
ACC SHELL 2018