Robert Ancell
Fri, 24 Jul 2009 00:40:35 -0700
Hi, I'm trying to learn how to use PolicyKit for configuration of a server. Find attached a demo program (which I plan to post as a a tutorial) which does the following: - Has a server providing a method "Reflect" which reverses a string - Has a client with a text entry that uses that uses the server to reflect entered text - The client has an "unlock" button that should authorize with the PolKit once
Note I've tried to make the simplest example not the most efficient. I've been stumbling along for a while and am in need of some help: - I've used POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION in polkit_authority_check_authorization_sync to prompt the user for authentication but sometimes it just blocks for ages instead of popping up the dialog. When should I use this flag and when let the client do the authorization? - I haven't been able to get the client to manually authorize or have persistent authorization, how do I do this? - Any pointers? The documentation I have been working from: http://dbus.freedesktop.org/doc/dbus-specification.html http://hal.freedesktop.org/docs/PolicyKit/ http://people.freedesktop.org/~david/polkit-0.92-newdocs/ http://cgit.freedesktop.org/PolicyKit/tree/docs/PORTING-GUIDE Thanks, --Robert
#include <stdio.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <polkit/polkit.h>
#include "mirror.h"
#include "mirror-server-glue.h"
/* Boilerplate for Mirror object */
G_DEFINE_TYPE(Mirror, mirror, G_TYPE_OBJECT)
Mirror *mirror_new() { return g_object_new(TYPE_MIRROR, NULL); }
static void mirror_init(Mirror *mirror) {}
static void
mirror_class_init(MirrorClass *klass)
{
/* Add D-Bus metadata */
dbus_g_object_type_install_info(TYPE_MIRROR, &dbus_glib_mirror_object_info);
}
/* Method expored over D-Bus and uses PolKit for authorization */
gboolean
mirror_reflect(Mirror *mirror, const gchar *name, DBusGMethodInvocation *context)
{
gchar *value;
GError *error = NULL;
PolkitAuthorizationResult *result;
printf("reflect '%s' by %s\n", name, dbus_g_method_get_sender(context));
result = polkit_authority_check_authorization_sync(polkit_authority_get(),
polkit_system_bus_name_new(dbus_g_method_get_sender(context)),
"com.example.mirror.use",
NULL,
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
NULL,
&error);
if (error) {
printf("Failed to check authorization: %s\n", error->message);
dbus_g_method_return_error(context, error);
return FALSE;
}
if (!polkit_authorization_result_get_is_authorized(result)) {
printf("Not authorized\n");
error = g_error_new(DBUS_GERROR_REMOTE_EXCEPTION, 0, "Not authorized");
dbus_g_method_return_error(context, error);
return FALSE;
}
value = g_strdup(name);
g_strreverse(value);
dbus_g_method_return(context, value);
return TRUE;
}
int main(int argc, char **argv)
{
GError *error = NULL;
DBusGConnection *connection;
DBusError dbus_error;
Mirror *mirror;
GMainLoop *loop;
int result;
/* Initialise GLib */
g_type_init();
/* Connect to the system D-Bus */
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
if (error) {
printf("Failed to get bus: %s\n", error->message);
return 1;
}
/* Register this services name on the bus */
dbus_error_init(&dbus_error);
result = dbus_bus_request_name(dbus_g_connection_get_connection(connection),
"com.example.Mirror", DBUS_NAME_FLAG_DO_NOT_QUEUE, &dbus_error);
if (dbus_error_is_set(&dbus_error)) {
printf("Failed to register name: %s\n", dbus_error.message);
return 1;
}
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
printf("Unable to get bus name\n");
return 1;
}
/* Make a new object and connect it to the bus */
mirror = mirror_new();
dbus_g_connection_register_g_object(connection, "/com/example/Mirror", G_OBJECT(mirror));
/* Loop, processing requests */
loop = g_main_loop_new(g_main_context_default(), TRUE);
g_main_loop_run(loop);
return 0;
}
#include <sys/types.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <dbus/dbus.h>
#include <polkit-dbus/polkit-dbus.h>
#include "mirror-client-glue.h"
GtkWidget *error_label;
DBusGProxy *proxy = NULL;
static void
mirror_cb(GtkWidget *entry)
{
char *result;
GError *error = NULL;
com_example_Mirror_reflect(proxy,
gtk_entry_get_text(GTK_ENTRY(entry)),
&result,
&error);
if (error != NULL) {
gtk_label_set(GTK_LABEL(error_label), error->message);
return;
}
gtk_label_set(GTK_LABEL(error_label), "");
gtk_entry_set_text(GTK_ENTRY(entry), result);
}
static void
authorize_cb(GtkWidget *button)
{
DBusConnection *bus;
DBusError dbus_error;
PolKitContext *context;
PolKitAction *action;
PolKitCaller *caller;
PolKitResult result;
polkit_bool_t authorized;
PolKitError *polkit_error = NULL;
//const gchar *action_name = "com.example.mirror.use";
const gchar *action_name = "org.gnome.clockapplet.mechanism.settimezone";
dbus_error_init(&dbus_error);
bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error);
context = polkit_context_new();
polkit_context_init(context, &polkit_error);
action = polkit_action_new();
polkit_action_set_action_id(action, action_name);
result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error);
printf("%s\n", polkit_result_to_string_representation(result));
authorized = polkit_auth_obtain(action_name, 0, getpid(), &dbus_error);
if (dbus_error_is_set(&dbus_error)) {
printf("Error authorizing: %s\n", dbus_error.message);
return;
}
printf("authorized = %s\n", authorized ? "yes" : "no");
/* Disable button once authorized */
if(authorized)
gtk_widget_set_sensitive(button, FALSE);
}
int main(int argc, char **argv)
{
DBusGConnection *connection;
GtkWidget *window, *vbox, *entry, *label, *button;
GError *error = NULL;
gtk_init(&argc, &argv);
connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
if (error) {
printf("Failed to get bus: %s\n", error->message);
return 1;
}
proxy = dbus_g_proxy_new_for_name(connection,
"com.example.Mirror",
"/com/example/Mirror",
"com.example.Mirror");
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(gtk_main_quit), NULL);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
label = gtk_label_new("Text to send:");
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 3);
entry = gtk_entry_new();
g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(mirror_cb), NULL);
gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, TRUE, 3);
error_label = gtk_label_new("");
gtk_label_set_line_wrap(GTK_LABEL(error_label), TRUE);
gtk_box_pack_start(GTK_BOX(vbox), error_label, FALSE, TRUE, 3);
button = gtk_button_new_with_label("Unlock");
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(authorize_cb), NULL);
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, TRUE, 3);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Makefile
Description: Binary data
mirror.policy
Description: Binary data
mirror.conf
Description: Binary data
<?xml version="1.0" encoding="UTF-8" ?> <node name="/com/example/Mirror"> <interface name="com.example.Mirror"> <method name="Reflect"> <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <arg type="s" name="in" direction="in" /> <arg type="s" name="out" direction="out" /> </method> </interface> </node>
_______________________________________________ polkit-devel mailing list polkit-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/polkit-devel