Sunday, November 18, 2007

On Xguest, Access Control and Desktop

Dan, I think the ideas behind Xguest are nice. But your ideas about using SELinux to implement access control for users leaves much to be desired. If you think that a brutal approach of denying individual users to even access services like HAL, NetworkManager and Bluez is good, then please think again. Please realize that if you do this, the desktop experience will suddenly change. Things like networking and bluetooth applets will cease to work. The file manager will fall back to relying on /etc/mtab and /etc/fstab. I’m not sure PulseAudio will start.


The problem is that your approach is not fine grained; it’s all or nothing. And this is not really useful. For example, for NetworkManager what you want is to lock down the machine so the user can only connect to trusted networks. With e.g. trusted networks being defined as something that is defined in a file in /etc that only uid 0 can change.


I’m not sure if it’s a surprise to you, but over the past year or so I’ve been working on and off on an application-level access control mechanism (similar to various RBAC implementations but with a few innovations on top) called PolicyKit that does all this. It’s specifically designed and optimized for desktop applications but can also be useful for legacy UNIX command line apps. It puts the administrator and users back in control since it provides a way for them to gain authorizations by authenticating and also supports systems like Ubuntu that has no root password. It provides a nice user interface for human beings to manage authorizations. There’s GTK+ widgets to make it really simple to integrate into existing applications (and KDE support is underway). The list of applications that are PolicyKit enabled is growing rapidly. It’s in all the major distributions. It encourages least privilege, e.g splitting a program into privileged and non-privileged bits.


It’s not that I hate SELinux because I don’t. I think SELinux is already very useful, just look at how useful SELinux is in confining network-facing and privileged services. I also have SELinux support in PolicyKit already and I plan (with your help) to make gnome-user-share run in a dedicated SELinux context so it is authorized to punch holes in the firewall without any configuration whatsoever (today it’s totally broken since g-u-s picks a random high port number to listen on). But, Dan, frankly, I think your use of SELinux to lock down access on the desktop is misguided. It’s a bit like if all you have is a hammer, then everything looks like a nail. I feel that it’s a bit sad that that two developers, working for the same company, in the same office are trying to solve the same problems. We really ought to do better.


(Disclaimer: this post does not necessarily represent the views of my employer, Red Hat, Inc.)


Update: A few people pointed out that I sounded too confrontational in this post and maybe they’re right. As I tried (and probably failed at) to explain it’s not either/or. Surely, there’s a ton of value in using SELinux to lock down privileged mechanisms like HAL, NM, Bluez and so on. Having PolicyKit and SELinux work well together is in everyone’s best interest.

Monday, November 12, 2007

Coverage

Andy Oram wrote a nice piece on PolicyKit detailing what it is and some of the plans for the future. I also did a short walk-through recently on one of our staff meetings here at Red Hat, there are some pseudo slides here. On the topic of coverage I’ve recently add unit tests to all the library sources and gcov tells me we’re at 59%. Not too shabby.

Thursday, September 20, 2007

Policy, Mechanism and Time zones

In my last post I looked at D-Bus system bus activation and provided a step-by-step guide on how to use this. In this installment we’re going to look at a specific application of system bus activation; namely how it can be used from a desktop application to do a privileged operation: setting the timezone. This example will also feature usage of PolicyKit for lock down.


When dealing with programs that needs to do privileged operations, the first thing that one needs to do is to separate the mechanism (the piece of code actually doing the privileged bits) into a separate process from the rest of the program. The main program will then simply launch a small privileged helper whenever something privileged needs to happen. This is a good idea because it’s a lot easier to review a tiny privileged helper with minimal dependencies rather than a huge program that pulls in things like GTK+, Python, image loaders and what not. Typically, the privileged helper is written in a way such that it trusts no-one; it verifies all the incoming parameters and also checks whether the program that calls it should be allowed to do so. The latter part is where PolicyKit comes in - PolicyKit is an application-level toolkit that allows a mechanism to ask “is $USER allowed to do $ACTION?”. As such, PolicyKit comes with a set of data structures to help model these constructs.


Anyway, enough boring theory; the user experience we want is that the user can click on his predefined list of time zones to set it; something like this

modified intlclock

If the user is not privileged to do this action, we may show a dialog like this

stock PolicyKit-gnome dialog

that may (or may not) feature buttons to make the system remember that setting the time zone is OK. Such that the system won’t ask for authentication in the future. In other words, this is a one-time-pain dialog.


Let’s go through the code and see how all this works. First, we need to write a mechanism. This will need to run as uid 0 (e.g. root) and we choose D-Bus as the interface for using the mechanism. We choose a unique name for the service, org.gnome.ClockApplet.Mechanism and since we’d like to write it in C using dbus-glib, we need to write some XML to define the objects and interfaces that this service will expose. This is defined in this file. As evident, this service exposes a single object, /, that exposes a single interface org.gnome.ClockApplet.Mechanism that currently exposes a single method SetTimezone(string zonefile) where the argument to that function is a path to what time zone we want to use. The mechanism itself consists of two C files, available here and here and a single C header file, available here.


Then, exactly as in the last post we need a D-Bus configuration file and a D-Bus service file. There’s also a cheesy Makefile to tie it all together.


Now, with this mechanism in place, we can poke it via D-Bus

$ dbus-send --system --print-reply --dest=org.gnome.ClockApplet.Mechanism / org.gnome.ClockApplet.Mechanism.SetTimezone string:/usr/share/zoneinfo/Europe/Copenhagen
method return sender=:1.346 -> dest=:1.345 reply_serial=2

The usage of PolicyKit deserves some explanation. First of all, as stated in the docs, we need to declare one or more actions for our mechanism. As we only export a single action right now (setting the time zone), we declare only that one action via the PolicyKit .policy file here. When we extend the mechanism to e.g. provide functionality to set the time as well (via e.g. a SetTime(int64 secs_since_epoch) method) we can declare an action org.gnome.clockapplet.mechanism.settime in addition to our org.gnome.clockapplet.mechanism.settimezone one.


Now, whenever someone calls into the mechanism, we simply use libpolkit to query whether the caller is allowed to do the specific action:

sender = dbus_g_method_get_sender (context);
pk_caller = polkit_caller_new_from_dbus_name (system_bus_connection, sender, &dbus_error);
pk_action = polkit_action_new ();
polkit_action_set_action_id (pk_action, "org.gnome.clockapplet.mechanism.settimezone");
pk_result = polkit_context_can_caller_do_action (pk_context, pk_action, pk_caller);
polkit_caller_unref (pk_caller);
polkit_action_unref (pk_action);
if (pk_result != POLKIT_RESULT_YES) { /* bail out */ }

The system administrator can control, using the /etc/PolicyKit/PolicyKit.conf configuration file, exactly what users are allowed to do this and whether they are allowed to keep the privilege to do the action on a forever- or per-session basis. This shouldn’t be necessary since it’s possible to specify the default result for a given action. Distributors can tweak the .policy as they see fit; for example consumer-oriented distributions might want to patch this to make the defaults always be “yes” (to avoid the auth dialog entirely) and workstation-oriented distributions might want the defaults to be “auth_admin” (to require the system administrator password and not give a chance to remember the privilege). Finally, sites can override this using the system-wide configuration file, e.g. if I’m a huge site I can distribute a PolicyKit.conf file that allows certain users to always do an action, certain other users never to do an action, and finally a third set of users for whom I want them to enter their own (or the root) password. Again, see the /etc/PolicyKit/PolicyKit.conf configuration file for details.


The screenshots above show integration with the intlclock applet; that’s thanks to Matthias Clasen. I simply handed Matthias the mechanism code including a simple GTK demo application available here. This application simply attempts to call into the mechanism and if the mechanism throws the org.gnome.ClockApplet.Mechanism.NotPrivileged exception it uses PolicyKit-gnome (via the session bus) to prompt the user for authentication if applicable.


The PolicyKit stuff is mostly done; at least the plumbing is there. What I like to see is some more GNOME-ish porcelain to make this stuff even easier to use. First, it’s simply way too complicated to write dbus-glib D-Bus servers. There’s just way too much code; compare to the Python server in the last post. Second, I’d like to provide a small library with a subclassed GtkButton, e.g. PolicyKitGtkButton such that all the magic happens there and it shows e.g. a lock only if authentication will be needed. I’m also planning to do a song and dance at the Boston Summit about this. The list of users of PolicyKit right now includes only HAL. However, PackageKit, dconf and virt-manager are all in the process of picking it up. I’m also hoping NetworkManager and things like gnome-system-monitor will pick it up (for the process killing bits instead of falling back to running the entire UI as uid 0 just for this). With time, and not too much time, I’m hoping for PolicyKit to be a blessed dependency in GNOME and banish the idea of su/sudo wrappers to enable running X11 applications as uid 0.

Wednesday, August 1, 2007

System Bus Activation hits Fedora Rawhide

.. well, almost. Anyway, you can get packages here or wait until Rawhide opens again (it’s currently frozen for F8t1). Credit goes to Richard for finishing this work and getting it past Havoc. This is a really huge thing; it opens up a lot of possibilities for better desktop/OS integration.



Lots of pretty colors
Lots of pretty colors


To actually test the packages I wrote a simple test program and thought it might be useful to share it. First, you need a program that claims a name on the system bus. I just copied the one from the dbus-python repository and modified it slightly. You can see it here.


Second, as with any service on the system message bus (as opposed to the session bus which has different security characteristics) you need a file in /etc/dbus-1/system.d. Mine is named dk.fubar.Test.conf (but note that any unique file name ending in .conf will do) and is pretty much run-of-the-mill standard stuff and shouldn’t be a surprise if you’re familiar with services on the system bus. It looks like this.


Finally, for system bus activation to work you simply need to put a service file in /usr/share/dbus-1/system-services. Mine is named dk.fubar.Test.service (again, any unique name ending in .service will do) and looks like this:

[D-BUS Service]
Name=dk.fubar.Test
Exec=/usr/sbin/dbus-sysbus-test.py
User=root

and that’s it! Provided you installed everything correctly (there’s a cheesy Makefile to do this) things should Just Work(tm) and the following command should print

$ dbus-send --system --print-reply --dest=dk.fubar.Test /SomeObject dk.fubar.Test.SampleInterface.HelloWorld string:foo
method return sender=:1.517 -> dest=:1.516 reply_serial=2
array [
string "Hello"
string " from example-service.py"
string "with unique name"
string ":1.517"
]

If your service is capable of operating correctly when running as an unprivileged system user (e.g. ftp or whatever) instead of root (think least privilege), simply change the user mentioned in both the .service and .conf files.

Thursday, July 19, 2007

No more polling

I just committed code to hal to take advantage of asynchronous change notification events originating from SATA AN capable drives. This means we can avoid polling the drive and this should result in fewer wakeups in libata. This also opens the opportunity for the drive itself to go into a deeper sleep state when it’s not used. So all in all this should improve laptop battery life. I haven’t tried this on a laptop just yet, but when I find a suitable one I’m sure PowerTOP will tell me.



Mural at the back of 1369
I took this while testing this GPS receiver. Click to see where to get good coffee.


Credit goes to Kristen Carlson Accardi from Intel. She did the kernel bits, sent me a SATA AN capable drive and pointed me in the right direction. To try this out, you will need a recent kernel and also some patches not yet in Linus’ tree. See RH #204969 for details. I’m hoping this will make it into Fedora 8; the hal bits will for sure; for the kernel bits I suppose asking davej is in order.

Wednesday, June 20, 2007

PolicyKit release

Late last night I finally made a PolicyKit release. It’s almost ready for prime time; wait a month for 0.4 to get out and I should be able to maintain a stable API.



PolicyKit
PolicyKit in action


With Richard’s great work on D-Bus system bus activation it looks like we’re soon going to have nice upstream frameworks for enabling the desktop to do privileged operations in a hopefully sane way. Instead of having each and every distribution on the planet write their own configuration tools. I, for one, really wants to see some effort of merging such things into upstream GNOME and KDE as far as possible.

Tuesday, June 5, 2007

Interwebs

Normally I’m not opposed to what our new web overlords are serving us; you know; social networks and the ability to see what past and present, uh, peers are up to… but sometimes it’s just TMI - Maybe I just need to use the Interwebs less :-)