summaryrefslogtreecommitdiff
path: root/docs/polkit/overview.xml
blob: 19834d21365a56d74eb3bec3a4fd5c8db6c3bf33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY version SYSTEM "../version.xml">
<!ENTITY extensiondir SYSTEM "../extensiondir.xml">
]>
<part id="overview">
  <title>polkit Overview</title>
  <chapter id="polkit-intro">
    <title>Introduction</title>
    <para>
      polkit provides an authorization API intended to be used by
      privileged programs (<quote>MECHANISMS</quote>) offering service
      to unprivileged programs (<quote>CLIENTS</quote>). See the
      <link linkend="polkit.8">polkit</link> manual page for
      the system architecture and big picture.
    </para>
  </chapter>

  <chapter id="polkit-apps">
    <title>Writing polkit applications</title>
    <para>
      polkit applications are privileged mechanisms (typically) using
      the polkit authority as a decider component. They do this by
      installing a <filename class='extension'>.policy</filename> file
      into the
      <filename class='directory'>/usr/share/polkit-1/actions</filename>
      directory and communicating with the polkit authority at runtime
      (either via the
      <link linkend="ref-dbus-api">D-Bus API</link> or indirectly
      via the
      <link linkend="ref-api">libpolkit-gobject-1</link> library or the
      <link linkend="pkcheck.1">pkcheck</link> command).
    </para>

    <simplesect id="polkit-apps-best-practices">
      <title>Best practices</title>
      <itemizedlist mark='opencircle' spacing='compact'>

        <listitem><para>
          <emphasis role='bold'>DO</emphasis> use polkit if you are writing a mechanism that is intended to be used by unprivileged programs.
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DO</emphasis> carefully consider what actions to define. In many cases there is not a 1:1 mapping between operations and polkit actions (often a polkit action has more to do with the object the operation is acting on than the operation itself). It is important to strike the right balance between too fine-grained and too coarse-grained.
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DO</emphasis> try to pick actions and implicit authorizations so applications using your mechanism will work out-of-the box for users logged in at the console (e.g. without interrupting the user with authentication dialogs).
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DO</emphasis> pass polkit variables along with
        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
requests so it's possible to write <emphasis>authorization rules</emphasis> matching on these. Also document these variables in your documentation (for example, see the
<ulink url="http://udisks.freedesktop.org/docs/latest/udisks-polkit-actions.html">udisks2 actions and variables</ulink>).
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DO</emphasis> pass a customized authentication message (using the <literal>polkit.message</literal> and <literal>polkit.gettext_domain</literal> variables) that includes more detailed information about the request than whatever is declared in the <filename class='extension'>.policy</filename> file's <literal>message</literal> element. For example, it's better to show <quote>Authentication is needed to format INTEL SSDSA2MH080G1GC (/dev/sda)</quote> than just <quote>Authentication is needed to format the device</quote>.
        </para></listitem>


        <listitem><para>
          <emphasis role='bold'>DON'T</emphasis> use polkit if your program isn't intended to be used by unprivileged programs. For example, if you are writing developer tools or low-level core OS command it's fine to just require the user to be root. Users can always run your tool through e.g.
<citerefentry><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<link linkend="pkexec.1"><citerefentry><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry></link>
or write a simple polkit-using mechanism that allows access to a (safe) subset of your tool.
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DON'T</emphasis> use polkit unless you actually have to. In other words, not every single privileged program providing a service to an unprivileged programs has to use polkit. For example, if you have a small well-written <ulink url="http://en.wikipedia.org/wiki/Setuid">setuid</ulink> helper to help deal with some implementation-detail of the OS (such as elevating the priority of the sound server process to real-time for sessions on local seats) it's not really helpful to define a polkit action for this since no-one is going to choose to not grant the privilige (in the example, no-one is going run the sound server process without real-time priority).
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DON'T</emphasis> call
        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
        for all your actions every time the authority emits the
        <link linkend="eggdbus-signal-org.freedesktop.PolicyKit1.Authority::Changed">Changed</link> signal. Not only is this a waste of resources, the result may also be inaccurate as authorization rules can return whatever they want, whenever they want.
        </para></listitem>

        <listitem><para>
          <emphasis role='bold'>DON'T</emphasis> block the main thread in your mechanism (e.g. the one used to service IPC requests from unprivileged programs) while waiting for the authority to reply - calls to
        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
        may take a very long time (seconds, even minutes) to complete as user interaction may be involved.
        Instead, use either the <link linkend="polkit-authority-check-authorization">asynchronous API</link> or
        a dedicated thread with the <link linkend="polkit-authority-check-authorization-sync">synchronous API</link>.
        </para></listitem>

      </itemizedlist>
    </simplesect>

    <simplesect id="polkit-apps-unprivileged">
      <title>Usage in unprivileged programs</title>

      <para>
        Unprivileged programs consuming privileged mechanisms normally
        does use polkit directly - they simply call into the mechanism
        and the mechanism either renders service (or refuses the
        request) after checking with polkit (which may include
        presenting an authentication dialog). In either case, the
        unprivileged program in question is oblivious to the fact that
        polkit is being used - it simply just waits for the privileged
        mechanism to carry out the request (which, if authentication
        dialogs are involved may take many seconds).
      </para>
      <para>
        Note that unprivileged programs often need to disable, modify
        or remove UI elements to e.g. convey to the user that a certain
        action cannot be carried out (because e.g. the user is not
        authorized) or authentication is needed (by e.g. displaying a
        padlock icon in the UI).
        In this case, the best approach is
        usually to have the unprivileged program get this information
        from the privileged mechanism - especially because there often
        is no reliable way that the unprivileged program can know what
        polkit action is going to be used.  In general, there is no
        guarantee that operations (such as D-Bus methods) map 1:1: to
        polkit action - for example, a disk manager service's
        <literal>Format()</literal> method may check for the action
        <literal>net.company.diskmanager.format-removable</literal> if
        the disk is removable and
        <literal>net.company.diskmanager.format-fixed</literal>
        otherwise.
      </para>
      <para>
        However, in certain cases, for example when using the
        <emphasis>org.freedesktop.policykit.imply</emphasis> annotation
        (see the
        <link linkend="polkit.8"><citerefentry><refentrytitle>polkit</refentrytitle><manvolnum>8</manvolnum></citerefentry></link> man page),
        it does make sense for an unprivileged program to query the
        polkit authority (to e.g. update UI elements) and it is
        in fact allowed to do so as long as the unprivileged program doesn't pass any variables along with the
        <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.CheckAuthorization">CheckAuthorization()</link>
        call (otherwise it would be easy to spoof authentication dialogs and bypass authorization rules).
        In fact, since this use-case is so common,
        <link linkend="ref-api">libpolkit-gobject-1</link> provides the
        <link linkend="PolkitPermission"><type>PolkitPermission</type></link> type (which is derived from
        <ulink url="http://developer.gnome.org/gio/unstable/GPermission.html"><type>GPermission</type></ulink>)
        that can be used together with
        <ulink url="http://developer.gnome.org/gtk3/unstable/GtkLockButton.html"><type>GtkLockButton</type></ulink>
        (often used to implement an
        <ulink url="http://developer.gnome.org/hig-book/3.2/hig-book.html#windows-instant-apply">instant apply</ulink>
        paradigm).
        Note that for <type>GtkLockButton</type> to work well, the
        polkit action backing it should use <literal>auth_self_keep</literal> or
        <literal>auth_admin_keep</literal> for its implicit authorizations.
      </para>
    </simplesect>

    <simplesect id="polkit-apps-no-auth-agent">
      <title>No authentication agent</title>
      <para>
        If a polkit application wants to handle the case where no
        authentication agent exists (for example if the app is launched
        via a
        <citerefentry><refentrytitle>ssh</refentrytitle><manvolnum>1</manvolnum></citerefentry>
        login), the application can use the <link
        linkend="PolkitAgentTextListener">PolkitAgentTextListener</link>
        type to spawn its own authentication agent as
        needed. Alternatively, the <xref linkend="pkttyagent.1"/>
        helper can be used to do this.
      </para>
    </simplesect>

  </chapter>

  <chapter id="polkit-agents">
    <title>Writing polkit Authentication Agents</title>
    <para>
      Authentication agents are provided by desktop environments. When
      an user session starts, the agent registers with the polkit
      Authority using
      the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent">RegisterAuthenticationAgent()</link>
      method. When services are needed, the authority will invoke
      methods on
      the <link linkend="eggdbus-interface-org.freedesktop.PolicyKit1.AuthenticationAgent">org.freedesktop.PolicyKit1.AuthenticationAgent</link>
      D-Bus interface. Once the user is authenticated, (a privileged
      part of) the agent invokes
      the <link linkend="eggdbus-method-org.freedesktop.PolicyKit1.Authority.AuthenticationAgentResponse">AuthenticationAgentResponse()</link>
      method.  Note that the polkit Authority itself does not care
      how the agent authenticates the user.
    </para>
    <para>
      The <link linkend="ref-authentication-agent-api">libpolkit-agent-1</link>
      library provides helpers to make it easy to build authentication
      agents that use the native authentication system
      e.g. pam<literal>(8)</literal>.
    </para>
    <para>
      If the environment variable <literal>POLKIT_DEBUG</literal> is
      set, the libpolkit-agent-1 library prints out diagnostic
      information on standard output.
    </para>
  </chapter>

</part>