575 lines
20 KiB
Plaintext
575 lines
20 KiB
Plaintext
$OpenBSD: patch-common_gdm-common_c,v 1.9 2021/05/15 15:49:02 ajacoutot Exp $
|
|
|
|
REVERT - OpenBSD does not have a systemd implementation (we need ConsoleKit)
|
|
From fcba1e1a5d556ce7b52101dbd2d1ba4a19469161 Mon Sep 17 00:00:00 2001
|
|
From: Iain Lane <iain@orangesquash.org.uk>
|
|
Date: Fri, 5 Jan 2018 11:53:34 +0000
|
|
Subject: [PATCH] manager: Find user's current graphical session, not session of caller
|
|
|
|
REVERT - OpenBSD does not have a systemd implementation (we need ConsoleKit)
|
|
From 9be58c9ec9a3a411492a5182ac4b0d51fdc3a323 Mon Sep 17 00:00:00 2001
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
Date: Fri, 12 Jun 2015 13:48:52 -0400
|
|
Subject: require logind support
|
|
|
|
REVERT - OpenBSD does not have a systemd implementation (we need ConsoleKit)
|
|
From 1ac67f522f5690c27023d98096ca817f12f7eb88 Mon Sep 17 00:00:00 2001
|
|
From: Ray Strode <rstrode@redhat.com>
|
|
Date: Fri, 12 Jun 2015 13:28:01 -0400
|
|
Subject: drop consolekit support
|
|
|
|
Index: common/gdm-common.c
|
|
--- common/gdm-common.c.orig
|
|
+++ common/gdm-common.c
|
|
@@ -36,12 +36,25 @@
|
|
|
|
#include "gdm-common.h"
|
|
|
|
+#ifdef WITH_SYSTEMD
|
|
#include <systemd/sd-login.h>
|
|
+#endif
|
|
|
|
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
|
|
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH "/org/gnome/DisplayManager/LocalDisplayFactory"
|
|
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
|
|
|
|
+#ifdef WITH_CONSOLE_KIT
|
|
+#define CK_NAME "org.freedesktop.ConsoleKit"
|
|
+#define CK_PATH "/org/freedesktop/ConsoleKit"
|
|
+#define CK_INTERFACE "org.freedesktop.ConsoleKit"
|
|
+
|
|
+#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
|
|
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
|
|
+#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
|
|
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
|
|
+#endif
|
|
+
|
|
G_DEFINE_QUARK (gdm-common-error, gdm_common_error);
|
|
|
|
gboolean
|
|
@@ -352,8 +365,87 @@ create_transient_display (GDBusConnection *connection,
|
|
return TRUE;
|
|
}
|
|
|
|
+#ifdef WITH_CONSOLE_KIT
|
|
gboolean
|
|
-gdm_activate_session_by_id (GDBusConnection *connection,
|
|
+get_current_session_id (GDBusConnection *connection,
|
|
+ char **session_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ CK_MANAGER_PATH,
|
|
+ CK_MANAGER_INTERFACE,
|
|
+ "GetCurrentSession",
|
|
+ NULL, /* parameters */
|
|
+ G_VARIANT_TYPE ("(o)"),
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to determine session: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_get (reply, "(o)", session_id);
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+get_seat_id_for_session (GDBusConnection *connection,
|
|
+ const char *session_id,
|
|
+ char **seat_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ session_id,
|
|
+ CK_SESSION_INTERFACE,
|
|
+ "GetSeatId",
|
|
+ NULL, /* parameters */
|
|
+ G_VARIANT_TYPE ("(o)"),
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to determine seat: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_get (reply, "(o)", seat_id);
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static char *
|
|
+get_current_seat_id (GDBusConnection *connection)
|
|
+{
|
|
+ gboolean res;
|
|
+ char *session_id;
|
|
+ char *seat_id;
|
|
+
|
|
+ session_id = NULL;
|
|
+ seat_id = NULL;
|
|
+
|
|
+ res = get_current_session_id (connection, &session_id);
|
|
+ if (res) {
|
|
+ res = get_seat_id_for_session (connection, session_id, &seat_id);
|
|
+ }
|
|
+ g_free (session_id);
|
|
+
|
|
+ return seat_id;
|
|
+}
|
|
+
|
|
+gboolean
|
|
+activate_session_id_for_ck (GDBusConnection *connection,
|
|
const char *seat_id,
|
|
const char *session_id)
|
|
{
|
|
@@ -361,6 +453,217 @@ gdm_activate_session_by_id (GDBusConnection *connectio
|
|
GVariant *reply;
|
|
|
|
reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ seat_id,
|
|
+ CK_SEAT_INTERFACE,
|
|
+ "ActivateSession",
|
|
+ g_variant_new ("(o)", session_id),
|
|
+ NULL,
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to activate session: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+session_is_login_window (GDBusConnection *connection,
|
|
+ const char *session_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+ const char *value;
|
|
+ gboolean ret;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ session_id,
|
|
+ CK_SESSION_INTERFACE,
|
|
+ "GetSessionType",
|
|
+ NULL,
|
|
+ G_VARIANT_TYPE ("(s)"),
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to determine session type: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_get (reply, "(&s)", &value);
|
|
+
|
|
+ if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
|
|
+ ret = FALSE;
|
|
+ } else {
|
|
+ ret = TRUE;
|
|
+ }
|
|
+
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+seat_can_activate_sessions (GDBusConnection *connection,
|
|
+ const char *seat_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+ gboolean ret;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ seat_id,
|
|
+ CK_SEAT_INTERFACE,
|
|
+ "CanActivateSessions",
|
|
+ NULL,
|
|
+ G_VARIANT_TYPE ("(b)"),
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to determine if can activate sessions: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_get (reply, "(b)", &ret);
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const char **
|
|
+seat_get_sessions (GDBusConnection *connection,
|
|
+ const char *seat_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+ const char **value;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
+ CK_NAME,
|
|
+ seat_id,
|
|
+ CK_SEAT_INTERFACE,
|
|
+ "GetSessions",
|
|
+ NULL,
|
|
+ G_VARIANT_TYPE ("(ao)"),
|
|
+ G_DBUS_CALL_FLAGS_NONE,
|
|
+ -1,
|
|
+ NULL, &local_error);
|
|
+ if (reply == NULL) {
|
|
+ g_warning ("Unable to list sessions: %s", local_error->message);
|
|
+ g_error_free (local_error);
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ g_variant_get (reply, "(^ao)", &value);
|
|
+ g_variant_unref (reply);
|
|
+
|
|
+ return value;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+get_login_window_session_id_for_ck (GDBusConnection *connection,
|
|
+ const char *seat_id,
|
|
+ char **session_id)
|
|
+{
|
|
+ gboolean can_activate_sessions;
|
|
+ const char **sessions;
|
|
+ int i;
|
|
+
|
|
+ *session_id = NULL;
|
|
+ sessions = NULL;
|
|
+
|
|
+ g_debug ("checking if seat can activate sessions");
|
|
+
|
|
+ can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
|
|
+ if (! can_activate_sessions) {
|
|
+ g_debug ("seat is unable to activate sessions");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ sessions = seat_get_sessions (connection, seat_id);
|
|
+ for (i = 0; sessions [i] != NULL; i++) {
|
|
+ const char *ssid;
|
|
+
|
|
+ ssid = sessions [i];
|
|
+
|
|
+ if (session_is_login_window (connection, ssid)) {
|
|
+ *session_id = g_strdup (ssid);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ g_free (sessions);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static gboolean
|
|
+goto_login_session_for_ck (GDBusConnection *connection,
|
|
+ GError **error)
|
|
+{
|
|
+ gboolean ret;
|
|
+ gboolean res;
|
|
+ char *session_id;
|
|
+ char *seat_id;
|
|
+
|
|
+ ret = FALSE;
|
|
+
|
|
+ /* First look for any existing LoginWindow sessions on the seat.
|
|
+ If none are found, create a new one. */
|
|
+
|
|
+ seat_id = get_current_seat_id (connection);
|
|
+ if (seat_id == NULL || seat_id[0] == '\0') {
|
|
+ g_debug ("seat id is not set; can't switch sessions");
|
|
+ g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
|
|
+
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ res = get_login_window_session_id_for_ck (connection, seat_id, &session_id);
|
|
+ if (! res) {
|
|
+ g_set_error (error, GDM_COMMON_ERROR, 1, _("User unable to switch sessions."));
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ if (session_id != NULL) {
|
|
+ res = activate_session_id_for_ck (connection, seat_id, session_id);
|
|
+ if (res) {
|
|
+ ret = TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (! ret && g_strcmp0 (seat_id, "/org/freedesktop/ConsoleKit/Seat1") == 0) {
|
|
+ res = create_transient_display (connection, error);
|
|
+ if (res) {
|
|
+ ret = TRUE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef WITH_SYSTEMD
|
|
+
|
|
+gboolean
|
|
+activate_session_id_for_systemd (GDBusConnection *connection,
|
|
+ const char *seat_id,
|
|
+ const char *session_id)
|
|
+{
|
|
+ GError *local_error = NULL;
|
|
+ GVariant *reply;
|
|
+
|
|
+ reply = g_dbus_connection_call_sync (connection,
|
|
"org.freedesktop.login1",
|
|
"/org/freedesktop/login1",
|
|
"org.freedesktop.login1.Manager",
|
|
@@ -382,8 +685,8 @@ gdm_activate_session_by_id (GDBusConnection *connectio
|
|
}
|
|
|
|
gboolean
|
|
-gdm_get_login_window_session_id (const char *seat_id,
|
|
- char **session_id)
|
|
+get_login_window_session_id_for_systemd (const char *seat_id,
|
|
+ char **session_id)
|
|
{
|
|
gboolean ret;
|
|
int res, i;
|
|
@@ -476,15 +779,14 @@ out:
|
|
}
|
|
|
|
static gboolean
|
|
-goto_login_session (GDBusConnection *connection,
|
|
- GError **error)
|
|
+goto_login_session_for_systemd (GDBusConnection *connection,
|
|
+ GError **error)
|
|
{
|
|
gboolean ret;
|
|
int res;
|
|
char *our_session;
|
|
char *session_id;
|
|
char *seat_id;
|
|
- GError *local_error = NULL;
|
|
|
|
ret = FALSE;
|
|
session_id = NULL;
|
|
@@ -497,8 +799,10 @@ goto_login_session (GDBusConnection *connection,
|
|
* since the data allocated is from libsystemd-logind, which
|
|
* does not use GLib's g_malloc (). */
|
|
|
|
- if (!gdm_find_display_session (0, getuid (), &our_session, &local_error)) {
|
|
- g_propagate_prefixed_error (error, local_error, _("Could not identify the current session: "));
|
|
+ res = sd_pid_get_session (0, &our_session);
|
|
+ if (res < 0) {
|
|
+ g_debug ("failed to determine own session: %s", strerror (-res));
|
|
+ g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
|
|
|
|
return FALSE;
|
|
}
|
|
@@ -512,9 +816,9 @@ goto_login_session (GDBusConnection *connection,
|
|
return FALSE;
|
|
}
|
|
|
|
- res = gdm_get_login_window_session_id (seat_id, &session_id);
|
|
+ res = get_login_window_session_id_for_systemd (seat_id, &session_id);
|
|
if (res && session_id != NULL) {
|
|
- res = gdm_activate_session_by_id (connection, seat_id, session_id);
|
|
+ res = activate_session_id_for_systemd (connection, seat_id, session_id);
|
|
|
|
if (res) {
|
|
ret = TRUE;
|
|
@@ -533,6 +837,7 @@ goto_login_session (GDBusConnection *connection,
|
|
|
|
return ret;
|
|
}
|
|
+#endif
|
|
|
|
gboolean
|
|
gdm_goto_login_session (GError **error)
|
|
@@ -548,7 +853,17 @@ gdm_goto_login_session (GError **error)
|
|
return FALSE;
|
|
}
|
|
|
|
- return goto_login_session (connection, error);
|
|
+#ifdef WITH_SYSTEMD
|
|
+ if (LOGIND_RUNNING()) {
|
|
+ return goto_login_session_for_systemd (connection, error);
|
|
+ }
|
|
+#endif
|
|
+
|
|
+#ifdef WITH_CONSOLE_KIT
|
|
+ return goto_login_session_for_ck (connection, error);
|
|
+#else
|
|
+ return FALSE;
|
|
+#endif
|
|
}
|
|
|
|
static void
|
|
@@ -823,136 +1138,4 @@ gdm_shell_expand (const char *str,
|
|
}
|
|
}
|
|
return g_string_free (s, FALSE);
|
|
-}
|
|
-
|
|
-static gboolean
|
|
-_systemd_session_is_graphical (const char *session_id)
|
|
-{
|
|
- const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL };
|
|
- int saved_errno;
|
|
- g_autofree gchar *type = NULL;
|
|
-
|
|
- saved_errno = sd_session_get_type (session_id, &type);
|
|
- if (saved_errno < 0) {
|
|
- g_warning ("Couldn't get type for session '%s': %s",
|
|
- session_id,
|
|
- g_strerror (-saved_errno));
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (!g_strv_contains (graphical_session_types, type)) {
|
|
- g_debug ("Session '%s' is not a graphical session (type: '%s')",
|
|
- session_id,
|
|
- type);
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-static gboolean
|
|
-_systemd_session_is_active (const char *session_id)
|
|
-{
|
|
- const gchar * const active_states[] = { "active", "online", NULL };
|
|
- int saved_errno;
|
|
- g_autofree gchar *state = NULL;
|
|
-
|
|
- /*
|
|
- * display sessions can be 'closing' if they are logged out but some
|
|
- * processes are lingering; we shouldn't consider these (this is
|
|
- * checking for a race condition since we specified
|
|
- * GDM_SYSTEMD_SESSION_REQUIRE_ONLINE)
|
|
- */
|
|
- saved_errno = sd_session_get_state (session_id, &state);
|
|
- if (saved_errno < 0) {
|
|
- g_warning ("Couldn't get state for session '%s': %s",
|
|
- session_id,
|
|
- g_strerror (-saved_errno));
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- if (!g_strv_contains (active_states, state)) {
|
|
- g_debug ("Session '%s' is not active or online", session_id);
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-gboolean
|
|
-gdm_find_display_session (GPid pid,
|
|
- const uid_t uid,
|
|
- char **out_session_id,
|
|
- GError **error)
|
|
-{
|
|
- char *local_session_id = NULL;
|
|
- g_auto(GStrv) sessions = NULL;
|
|
- int n_sessions;
|
|
- int res;
|
|
-
|
|
- g_return_val_if_fail (out_session_id != NULL, FALSE);
|
|
-
|
|
- /* First try to look up the session using the pid. We need this
|
|
- * at least for the greeter, because it currently runs multiple
|
|
- * sessions under the same user.
|
|
- * See also commit 2b52d8933c8ab38e7ee83318da2363d00d8c5581
|
|
- * which added an explicit dbus-run-session for all but seat0.
|
|
- */
|
|
- res = sd_pid_get_session (pid, &local_session_id);
|
|
- if (res >= 0) {
|
|
- g_debug ("GdmCommon: Found session %s for PID %d, using", local_session_id, pid);
|
|
-
|
|
- *out_session_id = g_strdup (local_session_id);
|
|
- free (local_session_id);
|
|
-
|
|
- return TRUE;
|
|
- } else {
|
|
- if (res != -ENODATA)
|
|
- g_warning ("GdmCommon: Failed to retrieve session information for pid %d: %s",
|
|
- pid, strerror (-res));
|
|
- }
|
|
-
|
|
- g_debug ("Finding a graphical session for user %d", uid);
|
|
-
|
|
- n_sessions = sd_uid_get_sessions (uid,
|
|
- GDM_SYSTEMD_SESSION_REQUIRE_ONLINE,
|
|
- &sessions);
|
|
-
|
|
- if (n_sessions < 0) {
|
|
- g_set_error (error,
|
|
- GDM_COMMON_ERROR,
|
|
- 0,
|
|
- "Failed to get sessions for user %d",
|
|
- uid);
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- for (int i = 0; i < n_sessions; ++i) {
|
|
- g_debug ("Considering session '%s'", sessions[i]);
|
|
-
|
|
- if (!_systemd_session_is_graphical (sessions[i]))
|
|
- continue;
|
|
-
|
|
- if (!_systemd_session_is_active (sessions[i]))
|
|
- continue;
|
|
-
|
|
- /*
|
|
- * We get the sessions from newest to oldest, so take the last
|
|
- * one we find that's good
|
|
- */
|
|
- local_session_id = sessions[i];
|
|
- }
|
|
-
|
|
- if (local_session_id == NULL) {
|
|
- g_set_error (error,
|
|
- GDM_COMMON_ERROR,
|
|
- 0,
|
|
- "Could not find a graphical session for user %d",
|
|
- uid);
|
|
- return FALSE;
|
|
- }
|
|
-
|
|
- *out_session_id = g_strdup (local_session_id);
|
|
-
|
|
- return TRUE;
|
|
}
|