diff options
-rw-r--r-- | .bzrignore | 3 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | src/gtk-dialog/Makefile.am | 2 | ||||
-rw-r--r-- | src/gtk-dialog/ck-pk-helper.c | 214 | ||||
-rw-r--r-- | src/gtk-dialog/ck-pk-helper.h | 6 | ||||
-rw-r--r-- | src/gtk-dialog/logout-dialog.c | 4 |
6 files changed, 228 insertions, 4 deletions
@@ -25,3 +25,6 @@ indicator-status.service indicator-users.service status-service-client.h status-service-server.h +gtk-logout-helper +.deps +.libs diff --git a/configure.ac b/configure.ac index 9d64f40..1e65958 100644 --- a/configure.ac +++ b/configure.ac @@ -48,7 +48,8 @@ PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib >= $DBUSMENUGLIB_REQUIRED_VERSIO AC_SUBST(SESSIONERVICE_CFLAGS) AC_SUBST(SESSIONERVICE_LIBS) -PKG_CHECK_MODULES(GTKLOGOUTHELPER, gtk+-2.0 >= $GTK_REQUIRED_VERSION) +PKG_CHECK_MODULES(GTKLOGOUTHELPER, gtk+-2.0 >= $GTK_REQUIRED_VERSION + polkit-gnome) AC_SUBST(GTKLOGOUTHELPER_CFLAGS) AC_SUBST(GTKLOGOUTHELPER_LIBS) diff --git a/src/gtk-dialog/Makefile.am b/src/gtk-dialog/Makefile.am index 07b0915..9aa0097 100644 --- a/src/gtk-dialog/Makefile.am +++ b/src/gtk-dialog/Makefile.am @@ -3,6 +3,8 @@ libexec_PROGRAMS = gtk-logout-helper gtk_logout_helper_SOURCES = \ gtk-logout-helper.c \ + ck-pk-helper.c \ + ck-pk-helper.h \ logout-dialog.c \ logout-dialog.h diff --git a/src/gtk-dialog/ck-pk-helper.c b/src/gtk-dialog/ck-pk-helper.c new file mode 100644 index 0000000..9278905 --- /dev/null +++ b/src/gtk-dialog/ck-pk-helper.c @@ -0,0 +1,214 @@ + +#include <unistd.h> +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <polkit-gnome/polkit-gnome.h> + +#include "logout-dialog.h" +#include "ck-pk-helper.h" + +static gboolean +ck_multiple_users (void) +{ + DBusGConnection * sbus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + g_return_val_if_fail(sbus != NULL, TRUE); /* worst case */ + DBusGProxy * proxy = dbus_g_proxy_new_for_name(sbus, "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager"); + + if (proxy == NULL) { + return TRUE; + } + + gboolean result; + GPtrArray * seats = NULL; + + result = dbus_g_proxy_call(proxy, "GetSeats", NULL, G_TYPE_INVALID, + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &seats, G_TYPE_INVALID); + + if (!result) { + g_warning("Unable to get the seats for ConsoleKit"); + g_object_unref(proxy); + return TRUE; + } + + gchar * this_session_id = NULL; + + result = dbus_g_proxy_call(proxy, "GetCurrentSession", NULL, G_TYPE_INVALID, + DBUS_TYPE_G_OBJECT_PATH, &this_session_id, G_TYPE_INVALID); + + g_object_unref(proxy); + + if (!result) { + g_warning("Unable to get current session from ConsoleKit"); + return TRUE; + } + + proxy = dbus_g_proxy_new_for_name(sbus, "org.freedesktop.ConsoleKit", + this_session_id, "org.freedesktop.ConsoleKit.Session"); + + if (proxy == NULL) { + return TRUE; + } + + guint this_session_uid; + + result = dbus_g_proxy_call(proxy, "GetUnixUser", NULL, G_TYPE_INVALID, + G_TYPE_UINT, &this_session_uid, G_TYPE_INVALID); + + if (!result) { + g_warning("Unable to get UID from ConsoleKit"); + return TRUE; + } + + guint seat; + gboolean multiple_users = FALSE; + for (seat = 0; seat < seats->len; seat++) { + gchar * seat_id = g_ptr_array_index(seats, seat); + DBusGProxy * seat_proxy = dbus_g_proxy_new_for_name(sbus, "org.freedesktop.ConsoleKit", + seat_id, "org.freedesktop.ConsoleKit.Seat"); + g_free(seat_id); + + if (seat_proxy == NULL) { + continue; + } + + GPtrArray * sessions = NULL; + + gboolean result = dbus_g_proxy_call(seat_proxy, + "GetSessions", NULL, G_TYPE_INVALID, + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, G_TYPE_INVALID); + + g_object_unref(seat_proxy); + if (!result) { + continue; + } + + guint session; + for (session = 0; session < sessions->len; session++) { + gchar * session_id = g_ptr_array_index(sessions, session); + if (g_strcmp0(this_session_id, session_id) == 0) { + continue; + } + DBusGProxy * session_proxy = dbus_g_proxy_new_for_name(sbus, "org.freedesktop.ConsoleKit", + session_id, "org.freedesktop.ConsoleKit.Session"); + g_free(session_id); + + if (session_proxy == NULL) { + continue; + } + + guint session_uid; + result = dbus_g_proxy_call(session_proxy, "GetUnixUser", NULL, G_TYPE_INVALID, + G_TYPE_UINT, &session_uid, G_TYPE_INVALID); + g_object_unref(session_proxy); + + if (!result) { + continue; + } + + if (session_uid != this_session_uid) { + multiple_users = TRUE; + break; + } + } + + g_ptr_array_free(sessions, TRUE); + + if (multiple_users) { + break; + } + } + + g_ptr_array_free(seats, TRUE); + g_object_unref(proxy); + g_free(this_session_id); + + return multiple_users; +} + +gboolean +pk_require_auth (LogoutDialogAction action) { + if (action == LOGOUT_DIALOG_LOGOUT) { + return FALSE; + } + + gchar * pk_action; + if (ck_multiple_users()) { + if (action == LOGOUT_DIALOG_RESTART) { + pk_action = "org.freedesktop.consolekit.system.restart-multiple-users"; + } else { + pk_action = "org.freedesktop.consolekit.system.stop-multiple-users"; + } + } else { + if (action == LOGOUT_DIALOG_RESTART) { + pk_action = "org.freedesktop.consolekit.system.restart"; + } else { + pk_action = "org.freedesktop.consolekit.system.stop"; + } + } + + PolKitResult polres; + if (pk_can_do_action(pk_action, &polres)) { + if (polres == POLKIT_RESULT_YES) { + return FALSE; + } + return TRUE; + } + return FALSE; +} + +gboolean +pk_can_do_action (const gchar *action_id, PolKitResult * pol_result) +{ + PolKitGnomeContext *gnome_context; + PolKitAction *action; + PolKitCaller *caller; + DBusError dbus_error; + PolKitError *error; + PolKitResult result; + + gnome_context = polkit_gnome_context_get (NULL); + + if (gnome_context == NULL) { + return FALSE; + } + + if (gnome_context->pk_tracker == NULL) { + return FALSE; + } + + dbus_error_init (&dbus_error); + caller = polkit_tracker_get_caller_from_pid (gnome_context->pk_tracker, + getpid (), + &dbus_error); + dbus_error_free (&dbus_error); + + if (caller == NULL) { + return FALSE; + } + + action = polkit_action_new (); + if (!polkit_action_set_action_id (action, action_id)) { + polkit_action_unref (action); + polkit_caller_unref (caller); + return FALSE; + } + + result = POLKIT_RESULT_UNKNOWN; + error = NULL; + result = polkit_context_is_caller_authorized (gnome_context->pk_context, + action, caller, FALSE, + &error); + if (polkit_error_is_set (error)) { + polkit_error_free (error); + } + polkit_action_unref (action); + polkit_caller_unref (caller); + + if (pol_result != NULL) { + *pol_result = result; + } + + return result != POLKIT_RESULT_NO && result != POLKIT_RESULT_UNKNOWN; +} diff --git a/src/gtk-dialog/ck-pk-helper.h b/src/gtk-dialog/ck-pk-helper.h new file mode 100644 index 0000000..6a3aa5a --- /dev/null +++ b/src/gtk-dialog/ck-pk-helper.h @@ -0,0 +1,6 @@ + +#include <polkit-gnome/polkit-gnome.h> + +gboolean pk_require_auth (LogoutDialogAction action); +gboolean pk_can_do_action (const gchar *action_id, PolKitResult * pol_result); + diff --git a/src/gtk-dialog/logout-dialog.c b/src/gtk-dialog/logout-dialog.c index 0cd0f7a..cd49b00 100644 --- a/src/gtk-dialog/logout-dialog.c +++ b/src/gtk-dialog/logout-dialog.c @@ -26,10 +26,8 @@ #include <glib/gi18n.h> #include <X11/XKBlib.h> -#include "../config.h" - #include "logout-dialog.h" -#include "applet.h" +#include "ck-pk-helper.h" enum { PROP_ZERO, |