From 00f63d1f9b1517a8643467647d21e8ac71f992be Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Sat, 13 Apr 2013 19:19:14 +0100 Subject: [PATCH] Detect logind at runtime. if polkit is compiled with libsystemd-login support, logind availability is now detected at runtime. If logind is not running, the code will fall back to ConsoleKit. --- configure.ac | 2 +- src/polkit/Makefile.am | 7 +- src/polkit/polkitunixsession-systemd.c | 490 --------------------- src/polkit/polkitunixsession.c | 55 ++- src/polkit/polkitunixsession.h | 5 + src/polkitbackend/Makefile.am | 5 - .../polkitbackendsessionmonitor-systemd.c | 414 ----------------- src/polkitbackend/polkitbackendsessionmonitor.c | 204 ++++++++- src/polkitbackend/polkitbackendsessionmonitor.h | 6 + 9 files changed, 259 insertions(+), 929 deletions(-) delete mode 100644 src/polkit/polkitunixsession-systemd.c delete mode 100644 src/polkitbackend/polkitbackendsessionmonitor-systemd.c diff --git a/configure.ac b/configure.ac index a9c24c4..b4d5df0 100644 --- a/configure.ac +++ b/configure.ac @@ -166,7 +166,7 @@ if test "$enable_libsystemd_login" != "no"; then have_libsystemd_login=yes, have_libsystemd_login=no) if test "$have_libsystemd_login" = "yes"; then - SESSION_TRACKING=libsystemd-login + SESSION_TRACKING="$SESSION_TRACKING libsystemd-login" AC_DEFINE([HAVE_LIBSYSTEMD_LOGIN], 1, [Define to 1 if libsystemd-login is available]) else if test "$enable_libsystemd_login" = "yes"; then diff --git a/src/polkit/Makefile.am b/src/polkit/Makefile.am index d648d29..3692e95 100644 --- a/src/polkit/Makefile.am +++ b/src/polkit/Makefile.am @@ -81,13 +81,8 @@ libpolkit_gobject_1_la_SOURCES = \ polkitpermission.c polkitpermission.h \ $(NULL) -if HAVE_LIBSYSTEMD_LOGIN libpolkit_gobject_1_la_SOURCES += \ - polkitunixsession-systemd.c polkitunixsession.h -else -libpolkit_gobject_1_la_SOURCES += \ - polkitunixsession.c polkitunixsession.h -endif + polkitunixsession.c polkitunixsession.h libpolkit_gobject_1_la_CFLAGS = \ -D_POLKIT_COMPILATION \ diff --git a/src/polkit/polkitunixsession-systemd.c b/src/polkit/polkitunixsession-systemd.c deleted file mode 100644 index 8a8bf65..0000000 --- a/src/polkit/polkitunixsession-systemd.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (C) 2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Matthias Clasen - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include "polkitunixsession.h" -#include "polkitsubject.h" -#include "polkiterror.h" -#include "polkitprivate.h" - -#include - -/** - * SECTION:polkitunixsession - * @title: PolkitUnixSession - * @short_description: Unix sessions - * - * An object that represents an user session. - * - * The session id is an opaque string obtained from ConsoleKit. - */ - -/** - * PolkitUnixSession: - * - * The #PolkitUnixSession struct should not be accessed directly. - */ -struct _PolkitUnixSession -{ - GObject parent_instance; - - gchar *session_id; - - gint pid; -}; - -struct _PolkitUnixSessionClass -{ - GObjectClass parent_class; -}; - -enum -{ - PROP_0, - PROP_SESSION_ID, - PROP_PID, -}; - -static void subject_iface_init (PolkitSubjectIface *subject_iface); -static void initable_iface_init (GInitableIface *initable_iface); -static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface); - -G_DEFINE_TYPE_WITH_CODE (PolkitUnixSession, polkit_unix_session, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) - ); - -static void -polkit_unix_session_init (PolkitUnixSession *session) -{ -} - -static void -polkit_unix_session_finalize (GObject *object) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); - - g_free (session->session_id); - - if (G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize != NULL) - G_OBJECT_CLASS (polkit_unix_session_parent_class)->finalize (object); -} - -static void -polkit_unix_session_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); - - switch (prop_id) - { - case PROP_SESSION_ID: - g_value_set_string (value, session->session_id); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -polkit_unix_session_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (object); - - switch (prop_id) - { - case PROP_SESSION_ID: - polkit_unix_session_set_session_id (session, g_value_get_string (value)); - break; - - case PROP_PID: - session->pid = g_value_get_int (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -polkit_unix_session_class_init (PolkitUnixSessionClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = polkit_unix_session_finalize; - gobject_class->get_property = polkit_unix_session_get_property; - gobject_class->set_property = polkit_unix_session_set_property; - - /** - * PolkitUnixSession:session-id: - * - * The UNIX session id. - */ - g_object_class_install_property (gobject_class, - PROP_SESSION_ID, - g_param_spec_string ("session-id", - "Session ID", - "The UNIX session ID", - NULL, - G_PARAM_CONSTRUCT | - G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_BLURB | - G_PARAM_STATIC_NICK)); - - - /** - * PolkitUnixSession:pid: - * - * The UNIX process id to look up the session. - */ - g_object_class_install_property (gobject_class, - PROP_PID, - g_param_spec_int ("pid", - "Process ID", - "Process ID to use for looking up the session", - 0, - G_MAXINT, - 0, - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_WRITABLE | - G_PARAM_STATIC_NAME | - G_PARAM_STATIC_BLURB | - G_PARAM_STATIC_NICK)); - -} - -/** - * polkit_unix_session_get_session_id: - * @session: A #PolkitUnixSession. - * - * Gets the session id for @session. - * - * Returns: The session id for @session. Do not free this string, it - * is owned by @session. - **/ -const gchar * -polkit_unix_session_get_session_id (PolkitUnixSession *session) -{ - g_return_val_if_fail (POLKIT_IS_UNIX_SESSION (session), NULL); - return session->session_id; -} - -/** - * polkit_unix_session_set_session_id: - * @session: A #PolkitUnixSession. - * @session_id: The session id. - * - * Sets the session id for @session to @session_id. - **/ -void -polkit_unix_session_set_session_id (PolkitUnixSession *session, - const gchar *session_id) -{ - g_return_if_fail (POLKIT_IS_UNIX_SESSION (session)); - /*g_return_if_fail (session_id != NULL);*/ - g_free (session->session_id); - session->session_id = g_strdup (session_id); -} - -/** - * polkit_unix_session_new: - * @session_id: The session id. - * - * Creates a new #PolkitUnixSession for @session_id. - * - * Returns: (transfer full): A #PolkitUnixSession. Free with g_object_unref(). - **/ -PolkitSubject * -polkit_unix_session_new (const gchar *session_id) -{ - return POLKIT_SUBJECT (g_object_new (POLKIT_TYPE_UNIX_SESSION, - "session-id", session_id, - NULL)); -} - -/** - * polkit_unix_session_new_for_process: - * @pid: The process id of the process to get the session for. - * @cancellable: (allow-none): A #GCancellable or %NULL. - * @callback: A #GAsyncReadyCallback to call when the request is satisfied - * @user_data: The data to pass to @callback. - * - * Asynchronously creates a new #PolkitUnixSession object for the - * process with process id @pid. - * - * When the operation is finished, @callback will be invoked in the - * thread-default - * main loop of the thread you are calling this method - * from. You can then call - * polkit_unix_session_new_for_process_finish() to get the result of - * the operation. - * - * This method constructs the object asynchronously, for the synchronous and blocking version - * use polkit_unix_session_new_for_process_sync(). - **/ -void -polkit_unix_session_new_for_process (gint pid, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_async_initable_new_async (POLKIT_TYPE_UNIX_SESSION, - G_PRIORITY_DEFAULT, - cancellable, - callback, - user_data, - "pid", pid, - NULL); -} - -/** - * polkit_unix_session_new_for_process_finish: - * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_unix_session_new_for_process(). - * @error: (allow-none): Return location for error. - * - * Finishes constructing a #PolkitSubject for a process id. - * - * Returns: (transfer full) (allow-none): A #PolkitUnixSession for the @pid passed to - * polkit_unix_session_new_for_process() or %NULL if @error is - * set. Free with g_object_unref(). - **/ -PolkitSubject * -polkit_unix_session_new_for_process_finish (GAsyncResult *res, - GError **error) -{ - GObject *object; - GObject *source_object; - - source_object = g_async_result_get_source_object (res); - g_assert (source_object != NULL); - - object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), - res, - error); - g_object_unref (source_object); - - if (object != NULL) - return POLKIT_SUBJECT (object); - else - return NULL; -} - - -/** - * polkit_unix_session_new_for_process_sync: - * @pid: The process id of the process to get the session for. - * @cancellable: (allow-none): A #GCancellable or %NULL. - * @error: (allow-none): Return location for error. - * - * Creates a new #PolkitUnixSession for the process with process id @pid. - * - * This is a synchronous call - the calling thread is blocked until a - * reply is received. For the asynchronous version, see - * polkit_unix_session_new_for_process(). - * - * Returns: (allow-none) (transfer full): A #PolkitUnixSession for - * @pid or %NULL if @error is set. Free with g_object_unref(). - **/ -PolkitSubject * -polkit_unix_session_new_for_process_sync (gint pid, - GCancellable *cancellable, - GError **error) -{ - return POLKIT_SUBJECT (g_initable_new (POLKIT_TYPE_UNIX_SESSION, - cancellable, - error, - "pid", pid, - NULL)); -} - -static guint -polkit_unix_session_hash (PolkitSubject *subject) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); - - return g_str_hash (session->session_id); -} - -static gboolean -polkit_unix_session_equal (PolkitSubject *a, - PolkitSubject *b) -{ - PolkitUnixSession *session_a; - PolkitUnixSession *session_b; - - session_a = POLKIT_UNIX_SESSION (a); - session_b = POLKIT_UNIX_SESSION (b); - - return g_strcmp0 (session_a->session_id, session_b->session_id) == 0; -} - -static gchar * -polkit_unix_session_to_string (PolkitSubject *subject) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); - - return g_strdup_printf ("unix-session:%s", session->session_id); -} - -static gboolean -polkit_unix_session_exists_sync (PolkitSubject *subject, - GCancellable *cancellable, - GError **error) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); - gboolean ret = FALSE; - uid_t uid; - - if (sd_session_get_uid (session->session_id, &uid) == 0) - ret = TRUE; - - return ret; -} - -static void -exists_in_thread_func (GSimpleAsyncResult *res, - GObject *object, - GCancellable *cancellable) -{ - GError *error; - error = NULL; - if (!polkit_unix_session_exists_sync (POLKIT_SUBJECT (object), - cancellable, - &error)) - { - g_simple_async_result_set_from_error (res, error); - g_error_free (error); - } -} - -static void -polkit_unix_session_exists (PolkitSubject *subject, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GSimpleAsyncResult *simple; - - g_return_if_fail (POLKIT_IS_UNIX_SESSION (subject)); - - simple = g_simple_async_result_new (G_OBJECT (subject), - callback, - user_data, - polkit_unix_session_exists); - g_simple_async_result_run_in_thread (simple, - exists_in_thread_func, - G_PRIORITY_DEFAULT, - cancellable); - g_object_unref (simple); -} - -static gboolean -polkit_unix_session_exists_finish (PolkitSubject *subject, - GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); - gboolean ret; - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_session_exists); - - ret = FALSE; - - if (g_simple_async_result_propagate_error (simple, error)) - goto out; - - ret = g_simple_async_result_get_op_res_gboolean (simple); - - out: - return ret; -} - -static void -subject_iface_init (PolkitSubjectIface *subject_iface) -{ - subject_iface->hash = polkit_unix_session_hash; - subject_iface->equal = polkit_unix_session_equal; - subject_iface->to_string = polkit_unix_session_to_string; - subject_iface->exists = polkit_unix_session_exists; - subject_iface->exists_finish = polkit_unix_session_exists_finish; - subject_iface->exists_sync = polkit_unix_session_exists_sync; -} - -static gboolean -polkit_unix_session_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); - gboolean ret = FALSE; - char *s; - - if (session->session_id != NULL) - { - /* already set, nothing to do */ - ret = TRUE; - goto out; - } - - if (sd_pid_get_session (session->pid, &s) == 0) - { - session->session_id = g_strdup (s); - free (s); - ret = TRUE; - goto out; - } - - g_set_error (error, - POLKIT_ERROR, - POLKIT_ERROR_FAILED, - "No session for pid %d", - (gint) session->pid); - -out: - return ret; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = polkit_unix_session_initable_init; -} - -static void -async_initable_iface_init (GAsyncInitableIface *async_initable_iface) -{ - /* use default implementation to run GInitable code in a thread */ -} diff --git a/src/polkit/polkitunixsession.c b/src/polkit/polkitunixsession.c index 40817de..14c1392 100644 --- a/src/polkit/polkitunixsession.c +++ b/src/polkit/polkitunixsession.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2013 Fabio Erculiani * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,18 +18,26 @@ * Boston, MA 02111-1307, USA. * * Author: David Zeuthen + * Author: Fabio Erculiani */ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include #include + #include "polkitunixsession.h" #include "polkitsubject.h" #include "polkiterror.h" #include "polkitprivate.h" +#ifdef HAVE_LIBSYSTEMD_LOGIN +#include +#endif /* HAVE_LIBSYSTEMD_LOGIN */ + + /** * SECTION:polkitunixsession * @title: PolkitUnixSession @@ -36,7 +45,8 @@ * * An object that represents an user session. * - * The session id is an opaque string obtained from ConsoleKit. + * The session id is an opaque string obtained from either ConsoleKit or + * systemd-logind. */ /** @@ -358,16 +368,30 @@ polkit_unix_session_to_string (PolkitSubject *subject) static gboolean polkit_unix_session_exists_sync (PolkitSubject *subject, - GCancellable *cancellable, - GError **error) + GCancellable *cancellable, + GError **error) { PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); GDBusConnection *connection; GVariant *result; gboolean ret; + connection = NULL; ret = FALSE; +#ifdef HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + uid_t uid; + if (sd_session_get_uid (session->session_id, &uid) == 0) + { + ret = TRUE; + goto out; + } + goto out; + } +#endif + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); if (connection == NULL) goto out; @@ -434,8 +458,8 @@ polkit_unix_session_exists (PolkitSubject *subject, static gboolean polkit_unix_session_exists_finish (PolkitSubject *subject, - GAsyncResult *res, - GError **error) + GAsyncResult *res, + GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); gboolean ret; @@ -473,6 +497,7 @@ polkit_unix_session_initable_init (GInitable *initable, GDBusConnection *connection; GVariant *result; gboolean ret; + char *s; connection = NULL; ret = FALSE; @@ -484,6 +509,26 @@ polkit_unix_session_initable_init (GInitable *initable, goto out; } +#ifdef HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + if (sd_pid_get_session (session->pid, &s) == 0) + { + session->session_id = g_strdup (s); + free (s); + ret = TRUE; + goto out; + } + + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "No session for pid %d", + (gint) session->pid); + goto out; + } +#endif + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error); if (connection == NULL) goto out; diff --git a/src/polkit/polkitunixsession.h b/src/polkit/polkitunixsession.h index 2674abe..313e153 100644 --- a/src/polkit/polkitunixsession.h +++ b/src/polkit/polkitunixsession.h @@ -30,6 +30,11 @@ #include #include +/* check if logind is running + * thanks to: https://bugzilla.gnome.org/show_bug.cgi?id=696266 + */ +#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0) + G_BEGIN_DECLS #define POLKIT_TYPE_UNIX_SESSION (polkit_unix_session_get_type()) diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am index aa57a97..ae8af19 100644 --- a/src/polkitbackend/Makefile.am +++ b/src/polkitbackend/Makefile.am @@ -38,13 +38,8 @@ libpolkit_backend_1_la_SOURCES = \ polkitbackendactionlookup.h polkitbackendactionlookup.c \ $(NULL) -if HAVE_LIBSYSTEMD_LOGIN -libpolkit_backend_1_la_SOURCES += \ - polkitbackendsessionmonitor.h polkitbackendsessionmonitor-systemd.c -else libpolkit_backend_1_la_SOURCES += \ polkitbackendsessionmonitor.h polkitbackendsessionmonitor.c -endif libpolkit_backend_1_la_CFLAGS = \ -D_POLKIT_COMPILATION \ diff --git a/src/polkitbackend/polkitbackendsessionmonitor-systemd.c b/src/polkitbackend/polkitbackendsessionmonitor-systemd.c deleted file mode 100644 index 58593c3..0000000 --- a/src/polkitbackend/polkitbackendsessionmonitor-systemd.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - * - * Author: Matthias Clasen - */ - -#include "config.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include "polkitbackendsessionmonitor.h" - -/* - * SECTION:polkitbackendsessionmonitor - * @title: PolkitBackendSessionMonitor - * @short_description: Monitor sessions - * - * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. - */ - -typedef struct -{ - GSource source; - GPollFD pollfd; - sd_login_monitor *monitor; -} SdSource; - -static gboolean -sd_source_prepare (GSource *source, - gint *timeout) -{ - *timeout = -1; - return FALSE; -} - -static gboolean -sd_source_check (GSource *source) -{ - SdSource *sd_source = (SdSource *)source; - - return sd_source->pollfd.revents != 0; -} - -static gboolean -sd_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) - -{ - SdSource *sd_source = (SdSource *)source; - gboolean ret; - - g_warn_if_fail (callback != NULL); - - ret = (*callback) (user_data); - - sd_login_monitor_flush (sd_source->monitor); - - return ret; -} - -static void -sd_source_finalize (GSource *source) -{ - SdSource *sd_source = (SdSource*)source; - - sd_login_monitor_unref (sd_source->monitor); -} - -static GSourceFuncs sd_source_funcs = { - sd_source_prepare, - sd_source_check, - sd_source_dispatch, - sd_source_finalize -}; - -static GSource * -sd_source_new (void) -{ - GSource *source; - SdSource *sd_source; - int ret; - - source = g_source_new (&sd_source_funcs, sizeof (SdSource)); - sd_source = (SdSource *)source; - - if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) - { - g_printerr ("Error getting login monitor: %d", ret); - } - else - { - sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); - sd_source->pollfd.events = G_IO_IN; - g_source_add_poll (source, &sd_source->pollfd); - } - - return source; -} - -struct _PolkitBackendSessionMonitor -{ - GObject parent_instance; - - GDBusConnection *system_bus; - - GSource *sd_source; -}; - -struct _PolkitBackendSessionMonitorClass -{ - GObjectClass parent_class; - - void (*changed) (PolkitBackendSessionMonitor *monitor); -}; - - -enum -{ - CHANGED_SIGNAL, - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT); - -/* ---------------------------------------------------------------------------------------------------- */ - -static gboolean -sessions_changed (gpointer user_data) -{ - PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); - - g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); - - return TRUE; -} - - -static void -polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) -{ - GError *error; - - error = NULL; - monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); - if (monitor->system_bus == NULL) - { - g_printerr ("Error getting system bus: %s", error->message); - g_error_free (error); - } - - monitor->sd_source = sd_source_new (); - g_source_set_callback (monitor->sd_source, sessions_changed, monitor, NULL); - g_source_attach (monitor->sd_source, NULL); -} - -static void -polkit_backend_session_monitor_finalize (GObject *object) -{ - PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (object); - - if (monitor->system_bus != NULL) - g_object_unref (monitor->system_bus); - - if (monitor->sd_source != NULL) - { - g_source_destroy (monitor->sd_source); - g_source_unref (monitor->sd_source); - } - - if (G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize != NULL) - G_OBJECT_CLASS (polkit_backend_session_monitor_parent_class)->finalize (object); -} - -static void -polkit_backend_session_monitor_class_init (PolkitBackendSessionMonitorClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = polkit_backend_session_monitor_finalize; - - /** - * PolkitBackendSessionMonitor::changed: - * @monitor: A #PolkitBackendSessionMonitor - * - * Emitted when something changes. - */ - signals[CHANGED_SIGNAL] = g_signal_new ("changed", - POLKIT_BACKEND_TYPE_SESSION_MONITOR, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (PolkitBackendSessionMonitorClass, changed), - NULL, /* accumulator */ - NULL, /* accumulator data */ - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -} - -PolkitBackendSessionMonitor * -polkit_backend_session_monitor_new (void) -{ - PolkitBackendSessionMonitor *monitor; - - monitor = POLKIT_BACKEND_SESSION_MONITOR (g_object_new (POLKIT_BACKEND_TYPE_SESSION_MONITOR, NULL)); - - return monitor; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -GList * -polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor) -{ - /* TODO */ - return NULL; -} - -/* ---------------------------------------------------------------------------------------------------- */ - -/** - * polkit_backend_session_monitor_get_user: - * @monitor: A #PolkitBackendSessionMonitor. - * @subject: A #PolkitSubject. - * @error: Return location for error. - * - * Gets the user corresponding to @subject or %NULL if no user exists. - * - * Returns: %NULL if @error is set otherwise a #PolkitUnixUser that should be freed with g_object_unref(). - */ -PolkitIdentity * -polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor *monitor, - PolkitSubject *subject, - GError **error) -{ - PolkitIdentity *ret; - guint32 uid; - - ret = NULL; - - if (POLKIT_IS_UNIX_PROCESS (subject)) - { - uid = polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)); - if ((gint) uid == -1) - { - g_set_error (error, - POLKIT_ERROR, - POLKIT_ERROR_FAILED, - "Unix process subject does not have uid set"); - goto out; - } - ret = polkit_unix_user_new (uid); - } - else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) - { - GVariant *result; - - result = g_dbus_connection_call_sync (monitor->system_bus, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetConnectionUnixUser", - g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), - G_VARIANT_TYPE ("(u)"), - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout_msec */ - NULL, /* GCancellable */ - error); - if (result == NULL) - goto out; - g_variant_get (result, "(u)", &uid); - g_variant_unref (result); - - ret = polkit_unix_user_new (uid); - } - else if (POLKIT_IS_UNIX_SESSION (subject)) - { - - if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) - { - g_set_error (error, - POLKIT_ERROR, - POLKIT_ERROR_FAILED, - "Error getting uid for session"); - goto out; - } - - ret = polkit_unix_user_new (uid); - } - - out: - return ret; -} - -/** - * polkit_backend_session_monitor_get_session_for_subject: - * @monitor: A #PolkitBackendSessionMonitor. - * @subject: A #PolkitSubject. - * @error: Return location for error. - * - * Gets the session corresponding to @subject or %NULL if no session exists. - * - * Returns: %NULL if @error is set otherwise a #PolkitUnixSession that should be freed with g_object_unref(). - */ -PolkitSubject * -polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMonitor *monitor, - PolkitSubject *subject, - GError **error) -{ - PolkitSubject *session; - - session = NULL; - - if (POLKIT_IS_UNIX_PROCESS (subject)) - { - gchar *session_id; - pid_t pid; - - pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); - if (sd_pid_get_session (pid, &session_id) < 0) - goto out; - - session = polkit_unix_session_new (session_id); - free (session_id); - } - else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) - { - guint32 pid; - gchar *session_id; - GVariant *result; - - result = g_dbus_connection_call_sync (monitor->system_bus, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetConnectionUnixProcessID", - g_variant_new ("(s)", polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (subject))), - G_VARIANT_TYPE ("(u)"), - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout_msec */ - NULL, /* GCancellable */ - error); - if (result == NULL) - goto out; - g_variant_get (result, "(u)", &pid); - g_variant_unref (result); - - if (sd_pid_get_session (pid, &session_id) < 0) - goto out; - - session = polkit_unix_session_new (session_id); - free (session_id); - } - else - { - g_set_error (error, - POLKIT_ERROR, - POLKIT_ERROR_NOT_SUPPORTED, - "Cannot get user for subject of type %s", - g_type_name (G_TYPE_FROM_INSTANCE (subject))); - } - - out: - - return session; -} - -gboolean -polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor, - PolkitSubject *session) -{ - char *seat; - - if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) - { - free (seat); - return TRUE; - } - - return FALSE; -} - - -gboolean -polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, - PolkitSubject *session) -{ - return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); -} - diff --git a/src/polkitbackend/polkitbackendsessionmonitor.c b/src/polkitbackend/polkitbackendsessionmonitor.c index 9c331b6..27b7910 100644 --- a/src/polkitbackend/polkitbackendsessionmonitor.c +++ b/src/polkitbackend/polkitbackendsessionmonitor.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Red Hat, Inc. + * Copyright (C) 2013 Fabio Erculiani * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,16 +18,22 @@ * Boston, MA 02111-1307, USA. * * Author: David Zeuthen + * Author: Fabio Erculiani */ #include "config.h" #include #include #include +#include #include #include #include +#ifdef HAVE_LIBSYSTEMD_LOGIN +#include +#endif + #include "polkitbackendsessionmonitor.h" #define CKDB_PATH "/var/run/ConsoleKit/database" @@ -36,9 +43,92 @@ * @title: PolkitBackendSessionMonitor * @short_description: Monitor sessions * - * The #PolkitBackendSessionMonitor class is a utility class to track and monitor sessions. + * The #PolkitBackendSessionMonitor class is a utility class to track and monitor + * ConsoleKit sessions. */ +#ifdef HAVE_LIBSYSTEMD_LOGIN +typedef struct +{ + GSource source; + GPollFD pollfd; + sd_login_monitor *monitor; +} SdSource; + +static gboolean +sd_source_prepare (GSource *source, + gint *timeout) +{ + *timeout = -1; + return FALSE; +} + +static gboolean +sd_source_check (GSource *source) +{ + SdSource *sd_source = (SdSource *)source; + + return sd_source->pollfd.revents != 0; +} + +static gboolean +sd_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) + +{ + SdSource *sd_source = (SdSource *)source; + gboolean ret; + + g_warn_if_fail (callback != NULL); + + ret = (*callback) (user_data); + + sd_login_monitor_flush (sd_source->monitor); + + return ret; +} + +static void +sd_source_finalize (GSource *source) +{ + SdSource *sd_source = (SdSource*)source; + + sd_login_monitor_unref (sd_source->monitor); +} + +static GSourceFuncs sd_source_funcs = { + sd_source_prepare, + sd_source_check, + sd_source_dispatch, + sd_source_finalize +}; + +static GSource * +sd_source_new (void) +{ + GSource *source; + SdSource *sd_source; + int ret; + + source = g_source_new (&sd_source_funcs, sizeof (SdSource)); + sd_source = (SdSource *)source; + + if ((ret = sd_login_monitor_new (NULL, &sd_source->monitor)) < 0) + { + g_printerr ("Error getting login monitor: %d", ret); + } + else + { + sd_source->pollfd.fd = sd_login_monitor_get_fd (sd_source->monitor); + sd_source->pollfd.events = G_IO_IN; + g_source_add_poll (source, &sd_source->pollfd); + } + + return source; +} +#endif + struct _PolkitBackendSessionMonitor { GObject parent_instance; @@ -48,6 +138,8 @@ struct _PolkitBackendSessionMonitor GKeyFile *database; GFileMonitor *database_monitor; time_t database_mtime; + + GSource *sd_source; }; struct _PolkitBackendSessionMonitorClass @@ -68,7 +160,6 @@ static guint signals[LAST_SIGNAL] = {0}; G_DEFINE_TYPE (PolkitBackendSessionMonitor, polkit_backend_session_monitor, G_TYPE_OBJECT); -/* ---------------------------------------------------------------------------------------------------- */ static gboolean reload_database (PolkitBackendSessionMonitor *monitor, @@ -162,6 +253,18 @@ on_file_monitor_changed (GFileMonitor *file_monitor, g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); } +#ifdef HAVE_LIBSYSTEMD_LOGIN +static gboolean +systemd_sessions_changed (gpointer user_data) +{ + PolkitBackendSessionMonitor *monitor = POLKIT_BACKEND_SESSION_MONITOR (user_data); + + g_signal_emit (monitor, signals[CHANGED_SIGNAL], 0); + + return TRUE; +} +#endif + static void polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) { @@ -169,6 +272,9 @@ polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) GFile *file; error = NULL; + monitor->sd_source = NULL; + monitor->database_monitor = NULL; + monitor->system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (monitor->system_bus == NULL) { @@ -176,6 +282,15 @@ polkit_backend_session_monitor_init (PolkitBackendSessionMonitor *monitor) g_error_free (error); } +#ifdef HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) { + monitor->sd_source = sd_source_new (); + g_source_set_callback (monitor->sd_source, systemd_sessions_changed, monitor, NULL); + g_source_attach (monitor->sd_source, NULL); + return; + } +#endif + error = NULL; if (!ensure_database (monitor, &error)) { @@ -212,6 +327,12 @@ polkit_backend_session_monitor_finalize (GObject *object) if (monitor->system_bus != NULL) g_object_unref (monitor->system_bus); + if (monitor->sd_source != NULL) + { + g_source_destroy (monitor->sd_source); + g_source_unref (monitor->sd_source); + } + if (monitor->database_monitor != NULL) g_object_unref (monitor->database_monitor); @@ -258,8 +379,6 @@ polkit_backend_session_monitor_new (void) return monitor; } -/* ---------------------------------------------------------------------------------------------------- */ - GList * polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monitor) { @@ -267,8 +386,6 @@ polkit_backend_session_monitor_get_sessions (PolkitBackendSessionMonitor *monito return NULL; } -/* ---------------------------------------------------------------------------------------------------- */ - /** * polkit_backend_session_monitor_get_user: * @monitor: A #PolkitBackendSessionMonitor. @@ -328,6 +445,24 @@ polkit_backend_session_monitor_get_user_for_subject (PolkitBackendSessionMonitor } else if (POLKIT_IS_UNIX_SESSION (subject)) { + +#ifdef HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + if (sd_session_get_uid (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (subject)), &uid) < 0) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Error getting uid for session"); + goto out; + } + ret = polkit_unix_user_new (uid); + goto out; + } + /* fall through */ +#endif + if (!ensure_database (monitor, error)) { g_prefix_error (error, "Error getting user for session: Error ensuring CK database at " CKDB_PATH ": "); @@ -373,7 +508,23 @@ polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMoni if (POLKIT_IS_UNIX_PROCESS (subject)) { - const gchar *session_id; + gchar *session_id; + +#ifdef HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + pid_t pid; + + pid = polkit_unix_process_get_pid (POLKIT_UNIX_PROCESS (subject)); + if (sd_pid_get_session (pid, &session_id) < 0) + goto out; + + session = polkit_unix_session_new (session_id); + free (session_id); + goto out; + } + /* fall through */ +#endif GVariant *result; result = g_dbus_connection_call_sync (monitor->system_bus, "org.freedesktop.ConsoleKit", @@ -395,7 +546,6 @@ polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMoni else if (POLKIT_IS_SYSTEM_BUS_NAME (subject)) { guint32 pid; - const gchar *session_id; GVariant *result; result = g_dbus_connection_call_sync (monitor->system_bus, @@ -414,6 +564,22 @@ polkit_backend_session_monitor_get_session_for_subject (PolkitBackendSessionMoni g_variant_get (result, "(u)", &pid); g_variant_unref (result); +#ifdef HAVE_LIBSYSTEMD_LOGIN + gchar *sd_session_id; + + if (LOGIND_RUNNING()) + { + if (sd_pid_get_session (pid, &sd_session_id) < 0) + goto out; + + session = polkit_unix_session_new (sd_session_id); + free (sd_session_id); + goto out; + } + /* fall through */ +#endif + + const gchar *session_id; result = g_dbus_connection_call_sync (monitor->system_bus, "org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", @@ -490,6 +656,21 @@ gboolean polkit_backend_session_monitor_is_session_local (PolkitBackendSessionMonitor *monitor, PolkitSubject *session) { +#if HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + char *seat; + + if (!sd_session_get_seat (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session)), &seat)) + { + free (seat); + return TRUE; + } + + return FALSE; + } + /* fall through */ +#endif return get_boolean (monitor, session, "is_local"); } @@ -498,6 +679,13 @@ gboolean polkit_backend_session_monitor_is_session_active (PolkitBackendSessionMonitor *monitor, PolkitSubject *session) { +#if HAVE_LIBSYSTEMD_LOGIN + if (LOGIND_RUNNING()) + { + return sd_session_is_active (polkit_unix_session_get_session_id (POLKIT_UNIX_SESSION (session))); + } + /* fall through */ +#endif return get_boolean (monitor, session, "is_active"); } diff --git a/src/polkitbackend/polkitbackendsessionmonitor.h b/src/polkitbackend/polkitbackendsessionmonitor.h index 8f8a2ca..2d608dc 100644 --- a/src/polkitbackend/polkitbackendsessionmonitor.h +++ b/src/polkitbackend/polkitbackendsessionmonitor.h @@ -29,6 +29,12 @@ #include #include +/* check if logind is running + * thanks to: https://bugzilla.gnome.org/show_bug.cgi?id=696266 + */ +#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0) + + G_BEGIN_DECLS #define POLKIT_BACKEND_TYPE_SESSION_MONITOR (polkit_backend_session_monitor_get_type ()) -- 1.8.1.5