Difference between revisions of "Development/Tutorials/PolicyKit/Helper HowTo"

Jump to: navigation, search
Line 45: Line 45:
  
 
We already know how create Policy files, let's get deeper on the other points and let's try to understand what we need to do, how and why.
 
We already know how create Policy files, let's get deeper on the other points and let's try to understand what we need to do, how and why.
 +
 +
=== The DBus interface ===
 +
We suppose you already know how to create DBus interfaces from XML files. In our interface we need to specify the means of communication between the helper and the main application. Consider that the only way we have to talk to our helper is DBus, so we need to rely on signals and slots streamed through the Bus. In our foo application, we have a signal that tells us when the helper has completed the action. So:
 +
 +
<code xml>
 +
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
 +
<node>
 +
  <interface name="org.kde.foohelper">
 +
      <method name="action2" >
 +
      </method>
 +
      <signal name="action2completed">
 +
      </signal>
 +
  </interface>
 +
</node>
 +
</code>
 +
 +
And that's enough. Remember to specify in the interface any needed signal/slot to communicate with the main application or library.
 +
 +
=== The DBus policy file ===
 +
Our helper will register itself on the system bus, as the session bus is reserved for the current user. DBus by default does not allow to register names on the System Bus, so we need a policy file for it. That's how it looks:
 +
 +
<code xml>
 +
<!DOCTYPE busconfig PUBLIC
 +
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 +
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
 +
<busconfig>
 +
 +
  <!-- Only user root can own the foo helper -->
 +
  <policy user="root">
 +
    <allow own="org.kde.foohelper"/>
 +
  </policy>
 +
 +
  <!-- Allow anyone to call into the service - we'll reject callers using PolicyKit -->
 +
  <policy context="default">
 +
    <allow send_interface="org.kde.foohelper"/>
 +
    <allow receive_sender="org.kde.foohelper"/>
 +
    <allow receive_interface="org.kde.foohelper"/>
 +
  </policy>
 +
 +
</busconfig>
 +
</code>
 +
 +
What does this file implies? It tells DBus that only root can register the name org.kde.foohelper on the System Bus (so that we avoid misusage), and anyone is allowed to call or receive signals from it. Don't worry about security: this will come later.

Revision as of 18:43, 11 March 2009


Contents

Development/Tutorials/PolicyKit/Introduction


Using the caller-helper model to perform actions as root
Tutorial Series   PolicyKit Tutorial
Previous   Development/Tutorials/PolicyKit/Introduction
What's Next   None

reading=None

Further Reading   n/a

Before you start

Applications running under root privileges has always been a major problem in Linux, and PolicyKit was created exactly to make the whole process easier and more secure. Though, running applications as root, even if small and controlled, can be still a major issue. So there are a few things you should take in account that will help you minimize possible issues:

  • Include in the helper just the strictly needed code. The fact itself that is a helper delegated to run just small parts of code implies that only the few lines of code you need to run as root should go in
  • Link against and use the minor number of libraries possible. The helper itself requires only QtCore and QtDBus. In particular, try not to use KDELibs as possible, as they were not designed to be used as root.
  • DO NOT USE SETUID IN HELPER. We'll see in this tutorial how to get root privileges without messing with the setuid bit.

If you are aware of this, and you're also sure that your application actually needs root privileges, you can go on reading.

What we need to do

What is cool about PolicyKit and this approach is that we need to write a minimum portion of code, don't need hacks or executon bits, and we actually get root privileges for a minimum portion of code. Suppose we still have our foo application we saw in the precedent Tutorial. From our .policy file, we know action2 actually does something that requires authentication as root. In fact, the following lines of code in action2 definitely require root privileges:

eraseHardDrive(); killUser(); detonatePC(); runAsFastAsYouCan();

But foo is a huge program that runs as standard user apart from those lines. So the option is to make it run as root as a whole, or split those 4 lines in a different program running as root. That is the approach that we will take in this tutorial.

Creating the Helper

Our helper will be a standard QCoreApplication. We need to create the following stuff:

  • A .policy file defining the various actions, that we should have already done
  • A DBus interface for our Helper
  • A DBus policy file
  • A file for DBus Activation
  • The main class

We already know how create Policy files, let's get deeper on the other points and let's try to understand what we need to do, how and why.

The DBus interface

We suppose you already know how to create DBus interfaces from XML files. In our interface we need to specify the means of communication between the helper and the main application. Consider that the only way we have to talk to our helper is DBus, so we need to rely on signals and slots streamed through the Bus. In our foo application, we have a signal that tells us when the helper has completed the action. So:

<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node>

  <interface name="org.kde.foohelper">
      <method name="action2" >
      </method>
      <signal name="action2completed">
      </signal>
  </interface>

</node>

And that's enough. Remember to specify in the interface any needed signal/slot to communicate with the main application or library.

The DBus policy file

Our helper will register itself on the system bus, as the session bus is reserved for the current user. DBus by default does not allow to register names on the System Bus, so we need a policy file for it. That's how it looks:

<!DOCTYPE busconfig PUBLIC

"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">

<busconfig>

 <policy user="root">
   <allow own="org.kde.foohelper"/>
 </policy>
 <policy context="default">
   <allow send_interface="org.kde.foohelper"/>
   <allow receive_sender="org.kde.foohelper"/>
   <allow receive_interface="org.kde.foohelper"/>
 </policy>

</busconfig>

What does this file implies? It tells DBus that only root can register the name org.kde.foohelper on the System Bus (so that we avoid misusage), and anyone is allowed to call or receive signals from it. Don't worry about security: this will come later.


KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal