gnome-lirc-properties, which I just mentioned needs to edit /etc/lirc/lircd.conf, which requires sudo/root access. Various APIs exist to get temporary sudo/root access but everyone now seems to agree that the new PolicyKit system is the way to go. I’d like to link to a website for it. All the system administration control panels in Ubuntu Hardy Heron seem to use PolicyKit already.
But I can’t get the thing to work, maybe because I’m using Python, and I haven’t found any help so far. I have defined the PolicyKit mechanism, but I can’t get even a simple test of the ObtainAuthorization() method to do anything interesting. This python code does not return anything other than None from ObtainAuthorization() and none of the callbacks are called:
#!/usr/bin/python
import pygtk
pygtk.require('2.0')
import gtk
import dbus
import os
class TestWindow:
def on_button_clicked(self, widget, data=None):
#Call the D-Bus method to request PolicyKit authorization:
session_bus = dbus.SessionBus()
policykit = session_bus.get_object('org.freedesktop.PolicyKit.AuthenticationAgent', '/', "org.gnome.PolicyKit.AuthorizationManager.SingleInstance")
if(policykit == None):
print("Error: Could not get PolicyKit D-Bus Interface\n")
gdkwindow = self.window.window
xid = gdkwindow.xid
print "Calling ObtainAuthorization..."
#This complains that no ObtainAuthorization(ssi) exists:
#granted = policykit.ObtainAuthorization("test_action_id", xid, os.getpid())
#TODO: Neither of the async callbacks are called, and how could the return value be useful if it is async?
# Note: Other code (such as gnome-panel) seems to use ShowDialog instead of ObtainAuthorization, though
# ShowDialog is apparently deprecated (I don't know when), but that also has no effect.
granted = policykit.ObtainAuthorization("test_action_id", xid, os.getpid(), reply_handler=self.__handleAuthReply, error_handler=self.__handleAuthError)
print "...Finished."
print "granted=", granted
def __handleAuthReply(self, granted):
print "handleAuthReply: granted\n"
def __handleAuthError(self, exception):
print "handleAuthError: not granted: %s\n" % exception
def on_delete_event(self, widget, event, data=None):
# Close the window:
return False
def on_destroy(self, widget, data=None):
gtk.main_quit()
def show(self):
self.window.show()
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", self.on_delete_event)
self.window.connect("destroy", self.on_destroy)
self.button = gtk.Button("Obtain Authorization")
self.button.connect("clicked", self.on_button_clicked, None)
self.window.add(self.button)
self.button.show()
window = TestWindow()
window.show()
gtk.main()
gnome-lirc-properties has a real mechanism and tries to use ObtainAuthorization() for real, if someone wants to look at it properly. Here is the gnome-lirc-properties svn, and a tarball (it doesn’t do much yet).
In return for asking the lazy web, I’ll try to describe how I think it should work, based mostly on David Zeuthen’s description. There are many opportunities to get something wrong:
February 7th, 2008 at 3:30 pm
Btw, try
org.freedesktop.PolicyKit.AuthenticationAgent
instead of
org.gnome.PolicyKit.AuthorizationManager.SingleInstance
And note that the type signature for ObtainAuthorization() on the fd.o interface is in fact (string, uint32, uint32) which I think is “suu”, not “ssi”. So you may need to do some type casting as weel.
Btw,
dbus-send –session –print-reply –dest=org.freedesktop.PolicyKit.AuthenticationAgent / org.freedesktop.DBus.Introspectable.Introspect
will tell you the whole signature for the service.
Hope this helps.
February 7th, 2008 at 5:57 pm
davidz wrote:
> try
> org.freedesktop.PolicyKit.AuthenticationAgent
> instead of
> org.gnome.PolicyKit.AuthorizationManager.SingleInstance
Thanks for the suggestion. So this is what I had:
policykit = session_bus.get_object(‘org.freedesktop.PolicyKit.AuthenticationAgent’, ‘/’, “org.gnome.PolicyKit.AuthorizationManager.SingleInstance”)
I copy/pasted that from somewhere or other and I actually have no idea what that (optional) third argument is for. I can’t find any DBus-Python reference documentation to tell me.
I tried this:
policykit = session_bus.get_object(‘org.freedesktop.PolicyKit.AuthenticationAgent’, ‘/’, “org.gnome.PolicyKit.AuthorizationManager.SingleInstance”)
and this:
policykit = session_bus.get_object(‘org.freedesktop.PolicyKit.AuthenticationAgent’, ‘/’)
with no change.
> And note that the type signature for ObtainAuthorization() on the fd.o interface is in fact (string, uint32, uint32) which I think is “suu”, not “ssi”.
Yes, I did change this
granted = policykit.ObtainAuthorization(“test_action_id”, xid, os.getpid(), reply_handler=self.__handleAuthReply, error_handler=self.__handleAuthError)
(also copy pasted from somewhere)
to this
granted = policykit.ObtainAuthorization(“test_action_id”, (dbus.UInt32)(xid), (dbus.UInt32)(os.getpid()))
and now I get 0 instead of None, which suggests it is now working, though I’d expect some kind of exception saying that the action doesn’t exist.
I wonder how it is even possible to call ObtainAuthorization() with those 5 wrong arguments. If I call it with just the 3 arguments without casting then Python complains. I’m also surprised that a cast is necessary in python.
February 7th, 2008 at 6:00 pm
OOh, and now I see the dialog when I use my real action ID. Result!
February 8th, 2008 at 2:08 am
Cool, glad that it works.
Not a Python expert myself, bu am pretty sure the third argument is the D-Bus interface name for the Python proxy object; remember an object may implement more than one interface (and it’s not even uncommon; several objects from the org.fd.Hal service implement multiple interfaces).
February 8th, 2008 at 11:10 am
Bizarrely, ObtainAuthorization() also returns 0 if I have already authenticated (confirmed by removing my previous authentication via the Authentications control panel). I don’t see any other way to see if I already have authentication.
June 16th, 2008 at 2:15 pm
Thanks for the post, I really found it helpful as I was trying to do the same thing.
You can use the org.freedesktop.PolicyKit.IsProcessAuthorized() method to check if the process is authorized and then call ObtainAuthorization() if needed
June 16th, 2008 at 2:22 pm
Yes, omajid, that’s what we do. It doesn’t seem like an ideal API.
December 31st, 2008 at 1:05 am
How about posting the final solution? :)
December 15th, 2009 at 4:11 pm
I’ve tracked it down and it now resides in live.gnome.org’s git repo
http://git.gnome.org/cgit/gnome-lirc-properties/
and here is the newest file at time of theis post which appears to have been ported to policykit-1.0
http://git.gnome.org/cgit/gnome-lirc-properties/tree/gnome_lirc_properties/policykit.py
December 17th, 2009 at 4:34 pm
I used this post and comments to guide my own usage of policykit and authentication agent. My question is what action-id should I use? I am writing a graphical installer for a game so I will need write access to /usr or /opt. Is there a policykit action-id that is highly likely to be available under common linux distros (ubuntu, fedora, suse) ?
December 19th, 2009 at 7:48 pm
Thanks to this post (in part) I finally managed to get a working example of PolicyKit in action under Python.
(In case the link gets parsed out, here it again)
http://ubuntuforums.org/showthread.php?p=8527327