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:
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.
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.
OOh, and now I see the dialog when I use my real action ID. Result!
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).
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.
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
Yes, omajid, that’s what we do. It doesn’t seem like an ideal API.
How about posting the final solution? :)
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
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) ?
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