From 9b4d319e9bb89116ee883381912f53823d5b2234 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 30 Oct 2013 13:30:40 -0400 Subject: [PATCH 1/5] slave: don't run initial-setup on remote displays GDM will run initial-setup if there are no configured user accounts on the system. We correctly skip checking if there are configured user accounts on remote XDMCP displays, but incorrectly, still run initial-setup. This commit makes sure we only every do any of the initial-setup logic in the local display code paths. --- daemon/gdm-simple-slave.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 217c33b..bee6c37 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -1285,60 +1285,71 @@ start_greeter (GdmSimpleSlave *slave) { start_launch_environment (slave, GDM_USERNAME, NULL); } static void start_initial_setup (GdmSimpleSlave *slave) { slave->priv->doing_initial_setup = TRUE; start_launch_environment (slave, INITIAL_SETUP_USERNAME, "gnome-initial-setup"); } static gboolean wants_autologin (GdmSimpleSlave *slave) { gboolean enabled = FALSE; int delay = 0; /* FIXME: handle wait-for-go */ if (g_file_test (GDM_RAN_ONCE_MARKER_FILE, G_FILE_TEST_EXISTS)) { return FALSE; } gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, NULL, &delay); return enabled && delay == 0; } static gboolean wants_initial_setup (GdmSimpleSlave *slave) { gboolean enabled = FALSE; + gboolean display_is_local = FALSE; + + g_object_get (G_OBJECT (slave), + "display-is-local", &display_is_local, + NULL); + + /* don't run initial-setup on remote displays + */ + if (!display_is_local) { + return FALSE; + } /* don't run if the system has existing users */ if (slave->priv->have_existing_user_accounts) { return FALSE; } /* don't run if initial-setup is unavailable */ if (!can_create_environment ("gnome-initial-setup")) { return FALSE; } if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) { return FALSE; } return enabled; } static void setup_session (GdmSimpleSlave *slave) { if (wants_initial_setup (slave)) { start_initial_setup (slave); } else if (wants_autologin (slave)) { /* Run the init script. gdmslave suspends until script has terminated */ gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/Init", GDM_USERNAME); } else { start_greeter (slave); } create_new_session (slave); -- 1.8.3.1 From 29b3f4ea9c69deb3bac2edf76489fa42755d7cd2 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 31 Oct 2013 14:57:04 -0400 Subject: [PATCH 2/5] slave: don't kill slave when client disconnects Right now we stop the slave if a greeter running on a remote X server exits. This is wrong, since the greeter will exit as part of the login screen process. We already have mechanisms in place to reap the slave at the appropriate time, so stopping the slave on disconnection is totally unneeded and actively harmful. This commit drops that code. --- daemon/gdm-simple-slave.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index bee6c37..35951c7 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -816,71 +816,61 @@ on_session_client_connected (GdmSession *session, (GDestroyNotify) g_object_unref); g_cancellable_connect (cancellable, G_CALLBACK (g_source_remove), GINT_TO_POINTER (timeout_id), NULL); g_object_weak_ref (G_OBJECT (session), (GWeakNotify) g_cancellable_cancel, cancellable); g_object_weak_ref (G_OBJECT (session), (GWeakNotify) g_object_unref, cancellable); g_object_weak_ref (G_OBJECT (session), (GWeakNotify) g_free, source_tag); } g_free (username); } static void on_session_client_disconnected (GdmSession *session, GCredentials *credentials, GPid pid_of_client, GdmSimpleSlave *slave) { - gboolean display_is_local; - g_debug ("GdmSimpleSlave: client disconnected"); - - g_object_get (slave, - "display-is-local", &display_is_local, - NULL); - - if ( ! display_is_local && !slave->priv->session_is_running) { - gdm_slave_stop (GDM_SLAVE (slave)); - } } static void on_session_cancelled (GdmSession *session, GdmSimpleSlave *slave) { g_debug ("GdmSimpleSlave: Session was cancelled"); queue_greeter_reset (slave); } static void touch_marker_file (GdmSimpleSlave *slave) { int fd; fd = g_creat (GDM_RAN_ONCE_MARKER_FILE, 0644); if (fd < 0 && errno != EEXIST) { g_warning ("could not create %s to mark run, this may cause auto login " "to repeat: %m", GDM_RAN_ONCE_MARKER_FILE); return; } fsync (fd); close (fd); } static void create_new_session (GdmSimpleSlave *slave) { -- 1.8.3.1 From 0c6811cc358fa1e5ff22fe3ec656c351ab94a899 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 31 Oct 2013 15:00:26 -0400 Subject: [PATCH 3/5] manager: return ACCESS DENIED for most open-reauth-channel failures gnome-shell only falls back to opening a new session if the reauth channel fails to open because of denied access. For XDMCP we currently fail for other reasons. This commit returns ACCESS DENIED for those cases as well, so the intended fallback happens. --- daemon/gdm-manager.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 74c6888..eef7233 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -698,90 +698,112 @@ gdm_manager_handle_open_session (GdmDBusManager *manager, address); g_free (address); return TRUE; } static gboolean gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager, GDBusMethodInvocation *invocation, const char *username) { GdmManager *self = GDM_MANAGER (manager); GDBusConnection *connection; GdmDisplay *display; const char *sender; char *seat_id; char *session_id = NULL; GError *error; char *address; int ret; GPid pid; uid_t caller_uid; g_debug ("GdmManager: trying to open reauthentication channel for user %s", username); sender = g_dbus_method_invocation_get_sender (invocation); error = NULL; ret = gdm_dbus_get_pid_for_name (sender, &pid, &error); if (!ret) { - g_prefix_error (&error, "Error while retrieving caller session id: "); - g_dbus_method_invocation_return_gerror (invocation, error); + g_debug ("GdmManager: could not get pid of caller: %s", + error->message); g_error_free (error); + + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Error getting process id of caller"); return TRUE; } ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error); if (!ret) { - g_prefix_error (&error, "Error while retrieving caller session id: "); - g_dbus_method_invocation_return_gerror (invocation, error); + g_debug ("GdmManager: could not get uid of caller: %s", + error->message); g_error_free (error); + + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Error getting user id of caller"); return TRUE; } connection = g_dbus_method_invocation_get_connection (invocation); seat_id = get_seat_id_for_pid (connection, pid, &error); if (seat_id == NULL) { - g_dbus_method_invocation_return_gerror (invocation, error); + g_debug ("GdmManager: could not get seat id of caller: %s", + error->message); g_error_free (error); + + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Error getting seat id of caller"); return TRUE; } session_id = get_session_id_for_user_on_seat (connection, username, seat_id, &error); if (session_id == NULL) { - g_dbus_method_invocation_return_gerror (invocation, error); + g_debug ("GdmManager: could not get session id for caller: %s", + error->message); g_error_free (error); + + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, + "Error getting session id for caller"); return TRUE; } display = gdm_display_store_find (self->priv->display_store, lookup_by_session_id, (gpointer) session_id); g_free (session_id); if (display == NULL) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, _("No session available")); return TRUE; } address = gdm_display_open_reauthentication_channel_sync (display, username, pid, caller_uid, NULL, &error); if (address == NULL) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return TRUE; } -- 1.8.3.1 From c4472c5e07b5d4e35a7a0c797ba96c882d97feb7 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 1 Nov 2013 12:40:10 -0400 Subject: [PATCH 4/5] daemon: don't require seat to locate reauth channel With systemd, XDMCP sessions don't have associated seats. Currently, reauth channels find the session by first looking up the seat, which means unlocking fails for XDMCP. This commit changes the code to determine session strictly from pid. --- daemon/gdm-manager.c | 503 +++++++-------------------------------------------- 1 file changed, 61 insertions(+), 442 deletions(-) diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index eef7233..6c0fe1d 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -226,605 +226,224 @@ get_uid_for_consolekit_session_id (GDBusConnection *connection, } g_variant_get (reply, "(u)", &uid); g_variant_unref (reply); *out_uid = (uid_t) uid; return TRUE; } #endif static gboolean get_uid_for_session_id (GDBusConnection *connection, const char *session_id, uid_t *uid, GError **error) { #ifdef WITH_SYSTEMD if (LOGIND_RUNNING()) { return get_uid_for_systemd_session_id (session_id, uid, error); } #endif #ifdef WITH_CONSOLE_KIT return get_uid_for_consolekit_session_id (connection, session_id, uid, error); #endif return FALSE; } -#ifdef WITH_SYSTEMD -static char * -get_session_id_for_user_on_seat_systemd (const char *username, - const char *seat, - GError **error) -{ - struct passwd *pwent; - uid_t uid; - int i; - char **sessions; - char *session = NULL; - int ret; - - pwent = NULL; - gdm_get_pwent_for_name (username, &pwent); - - if (pwent == NULL) { - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("Unable to look up UID of user %s"), - username); - return NULL; - } - - uid = pwent->pw_uid; - - session = NULL; - ret = sd_seat_get_sessions (seat, &sessions, NULL, NULL); - if (ret < 0 || sessions == NULL) { - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Error getting session ids from systemd: %s", - ret < 0? g_strerror (-ret) : _("no sessions available")); - return NULL; - } - - for (i = 0; sessions[i] != NULL; i++) { - char *type; - char *state; - gboolean is_closing; - gboolean is_x11; - uid_t session_uid; - - ret = sd_session_get_uid (sessions[i], &session_uid); - - if (ret < 0) { - g_warning ("GdmManager: could not fetch uid of session '%s': %s", - sessions[i], strerror (-ret)); - continue; - } - - if (uid != session_uid) { - continue; - } - - ret = sd_session_get_type (sessions[i], &type); - - if (ret < 0) { - g_warning ("GdmManager: could not fetch type of session '%s': %s", - sessions[i], strerror (-ret)); - continue; - } - - is_x11 = g_strcmp0 (type, "x11") == 0; - free (type); - - if (!is_x11) { - continue; - } - - ret = sd_session_get_state (sessions[i], &state); - if (ret < 0) { - g_warning ("GdmManager: could not fetch state of session '%s': %s", - sessions[i], strerror (-ret)); - continue; - } - - is_closing = g_strcmp0 (state, "closing") == 0; - - if (is_closing) { - continue; - } - - session = g_strdup (sessions[i]); - break; - - } - - if (session == NULL) { - g_debug ("GdmManager: There are no applicable sessions (%d looked at)", i); - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("No sessions for %s available for reauthentication"), - username); - return NULL; - } - - g_debug ("GdmManager: session %s is available for reauthentication", session); - - return session; -} -#endif - -#ifdef WITH_CONSOLE_KIT -static char * -get_session_id_for_user_on_seat_consolekit (GDBusConnection *connection, - const char *username, - const char *seat, - GError **error) -{ - GVariant *reply; - const gchar **sessions; - char *session = NULL; - struct passwd *pwent; - uid_t uid; - int i; - - pwent = NULL; - gdm_get_pwent_for_name (username, &pwent); - - if (pwent == NULL) { - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("Unable to look up UID of user %s"), - username); - return NULL; - } - - uid = pwent->pw_uid; - - reply = g_dbus_connection_call_sync (connection, - "org.freedesktop.ConsoleKit", - "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager", - "GetSessionsForUnixUser", - g_variant_new ("(u)", (guint32) uid), - G_VARIANT_TYPE ("(ao)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - if (reply == NULL) { - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("Unable to find session for user %s"), - username); - return NULL; - } - - g_variant_get_child (reply, 0, "^a&o", &sessions); - for (i = 0; sessions[i] != NULL; i++) { - GVariant *reply2; - GError *error2 = NULL; - gchar *display; - gchar *session_seat_id; - - reply2 = g_dbus_connection_call_sync (connection, - "org.freedesktop.ConsoleKit", - sessions[i], - "org.freedesktop.ConsoleKit.Session", - "GetSeatId", - NULL, - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error2); - if (reply2 == NULL) { - continue; - } - - g_variant_get (reply2, "(o)", &session_seat_id); - g_variant_unref (reply2); - - if (g_strcmp0 (seat, session_seat_id) != 0) { - g_free (session_seat_id); - continue; - } - g_free (session_seat_id); - - reply2 = g_dbus_connection_call_sync (connection, - "org.freedesktop.ConsoleKit", - sessions[i], - "org.freedesktop.ConsoleKit.Session", - "GetX11DisplayDevice", - NULL, - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - &error2); - if (reply2 == NULL) { - continue; - } - - g_variant_get (reply2, "(s)", &display); - g_variant_unref (reply2); - - if (display[0] == '\0') { - g_free (display); - continue; - } - - session = g_strdup (sessions[i]); - break; - - } - g_free (sessions); - g_variant_unref (reply); - - if (session == NULL) { - g_set_error (error, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("Unable to find appropriate session for user %s"), - username); - } - return session; -} -#endif - -static char * -get_session_id_for_user_on_seat (GDBusConnection *connection, - const char *username, - const char *seat, - GError **error) -{ -#ifdef WITH_SYSTEMD - if (LOGIND_RUNNING()) { - return get_session_id_for_user_on_seat_systemd (username, seat, error); - } -#endif - -#ifdef WITH_CONSOLE_KIT - return get_session_id_for_user_on_seat_consolekit (connection, username, seat, error); -#endif - - return NULL; -} - static gboolean lookup_by_session_id (const char *id, GdmDisplay *display, gpointer user_data) { const char *looking_for = user_data; char *current; gboolean res; current = gdm_display_get_session_id (display); res = g_strcmp0 (current, looking_for) == 0; g_free (current); return res; } -#ifdef WITH_SYSTEMD -static char * -get_seat_id_for_pid_systemd (pid_t pid, - GError **error) +static GdmDisplay * +get_display_and_details_for_bus_sender (GdmManager *self, + GDBusConnection *connection, + const char *sender, + GPid *out_pid, + uid_t *out_uid) { - char *session; - char *seat, *gseat; - int ret; + GdmDisplay *display = NULL; + char *session_id = NULL; + GError *error = NULL; + int ret; + GPid pid; + uid_t caller_uid, session_uid; - session = get_session_id_for_pid_systemd (pid, error); + ret = gdm_dbus_get_pid_for_name (sender, &pid, &error); - if (session == NULL) { - return NULL; + if (!ret) { + g_debug ("GdmManager: Error while retrieving pid for sender: %s", + error->message); + g_error_free (error); + goto out; } - seat = NULL; - ret = sd_session_get_seat (session, &seat); - free (session); + ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error); - if (ret < 0) { - g_set_error (error, - GDM_DISPLAY_ERROR, - GDM_DISPLAY_ERROR_GETTING_SESSION_INFO, - "Error getting seat id from systemd: %s", - g_strerror (-ret)); - return NULL; + if (!ret) { + g_debug ("GdmManager: Error while retrieving uid for sender: %s", + error->message); + g_error_free (error); + goto out; } - if (seat != NULL) { - gseat = g_strdup (seat); - free (seat); + session_id = get_session_id_for_pid (connection, pid, &error); - return gseat; - } else { - return NULL; + if (session_id == NULL) { + g_debug ("GdmManager: Error while retrieving session id for sender: %s", + error->message); + g_error_free (error); + goto out; } -} -#endif - -#ifdef WITH_CONSOLE_KIT -static char * -get_seat_id_for_pid_consolekit (GDBusConnection *connection, - pid_t pid, - GError **error) -{ - char *session; - GVariant *reply; - char *retval; - session = get_session_id_for_pid_consolekit (connection, pid, error); - - if (session == NULL) { - return NULL; + if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) { + g_debug ("GdmManager: Error while retrieving uid for session: %s", + error->message); + g_error_free (error); + goto out; } - reply = g_dbus_connection_call_sync (connection, - "org.freedesktop.ConsoleKit", - session, - "org.freedesktop.ConsoleKit.Session", - "GetSeatId", - NULL, - G_VARIANT_TYPE ("(o)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, error); - g_free (session); - - if (reply == NULL) { - return NULL; + if (caller_uid != session_uid) { + g_debug ("GdmManager: uid for sender and uid for session don't match"); + goto out; } - g_variant_get (reply, "(o)", &retval); - g_variant_unref (reply); + display = gdm_display_store_find (self->priv->display_store, + lookup_by_session_id, + (gpointer) session_id); +out: + g_free (session_id); - return retval; -} -#endif + if (display != NULL) { + if (out_pid != NULL) + *out_pid = pid; -static char * -get_seat_id_for_pid (GDBusConnection *connection, - pid_t pid, - GError **error) -{ -#ifdef WITH_SYSTEMD - if (LOGIND_RUNNING()) { - return get_seat_id_for_pid_systemd (pid, error); + if (out_uid != NULL) + *out_uid = session_uid; } -#endif - -#ifdef WITH_CONSOLE_KIT - return get_seat_id_for_pid_consolekit (connection, pid, error); -#endif - - return NULL; + return display; } static gboolean gdm_manager_handle_open_session (GdmDBusManager *manager, GDBusMethodInvocation *invocation) { GdmManager *self = GDM_MANAGER (manager); + const char *sender = NULL; + GError *error = NULL; GDBusConnection *connection; GdmDisplay *display; - const char *sender; - char *session_id; - GError *error; char *address; - int ret; GPid pid; - uid_t caller_uid, session_uid; + uid_t uid; - sender = g_dbus_method_invocation_get_sender (invocation); - error = NULL; - ret = gdm_dbus_get_pid_for_name (sender, &pid, &error); - - if (!ret) { - g_prefix_error (&error, "Error while retrieving caller session id: "); - g_dbus_method_invocation_return_gerror (invocation, error); - g_error_free (error); - return TRUE; - } - - ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error); - - if (!ret) { - g_prefix_error (&error, "Error while retrieving caller session id: "); - g_dbus_method_invocation_return_gerror (invocation, error); - g_error_free (error); - return TRUE; - } + g_debug ("GdmManager: trying to open new session"); + sender = g_dbus_method_invocation_get_sender (invocation); connection = g_dbus_method_invocation_get_connection (invocation); - session_id = get_session_id_for_pid (connection, pid, &error); - - if (session_id == NULL) { - g_dbus_method_invocation_return_gerror (invocation, error); - g_error_free (error); - return TRUE; - } - - if (!get_uid_for_session_id (connection, session_id, &session_uid, &error)) { - g_prefix_error (&error, "Error while retrieving caller session id: "); - g_dbus_method_invocation_return_gerror (invocation, error); - g_error_free (error); - return TRUE; - } - - if (caller_uid != session_uid) { - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - _("User doesn't own session")); - return TRUE; - } - - display = gdm_display_store_find (self->priv->display_store, - lookup_by_session_id, - (gpointer) session_id); - g_free (session_id); + display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid); if (display == NULL) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, _("No session available")); return TRUE; } - address = gdm_display_open_session_sync (display, pid, session_uid, NULL, &error); + address = gdm_display_open_session_sync (display, pid, uid, NULL, &error); if (address == NULL) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return TRUE; } gdm_dbus_manager_complete_open_session (GDM_DBUS_MANAGER (manager), invocation, address); g_free (address); return TRUE; } static gboolean gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager, GDBusMethodInvocation *invocation, const char *username) { GdmManager *self = GDM_MANAGER (manager); + const char *sender = NULL; + GError *error = NULL; GDBusConnection *connection; GdmDisplay *display; - const char *sender; - char *seat_id; - char *session_id = NULL; - GError *error; char *address; - int ret; GPid pid; - uid_t caller_uid; + uid_t uid; g_debug ("GdmManager: trying to open reauthentication channel for user %s", username); sender = g_dbus_method_invocation_get_sender (invocation); - error = NULL; - ret = gdm_dbus_get_pid_for_name (sender, &pid, &error); - - if (!ret) { - g_debug ("GdmManager: could not get pid of caller: %s", - error->message); - g_error_free (error); - - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Error getting process id of caller"); - return TRUE; - - } - - ret = gdm_dbus_get_uid_for_name (sender, &caller_uid, &error); - - if (!ret) { - g_debug ("GdmManager: could not get uid of caller: %s", - error->message); - g_error_free (error); - - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Error getting user id of caller"); - return TRUE; - } - connection = g_dbus_method_invocation_get_connection (invocation); - - seat_id = get_seat_id_for_pid (connection, pid, &error); - - if (seat_id == NULL) { - g_debug ("GdmManager: could not get seat id of caller: %s", - error->message); - g_error_free (error); - - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Error getting seat id of caller"); - return TRUE; - } - - session_id = get_session_id_for_user_on_seat (connection, username, seat_id, &error); - if (session_id == NULL) { - g_debug ("GdmManager: could not get session id for caller: %s", - error->message); - g_error_free (error); - - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Error getting session id for caller"); - return TRUE; - } - - display = gdm_display_store_find (self->priv->display_store, - lookup_by_session_id, - (gpointer) session_id); - g_free (session_id); + display = get_display_and_details_for_bus_sender (self, connection, sender, &pid, &uid); if (display == NULL) { g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, _("No session available")); return TRUE; } address = gdm_display_open_reauthentication_channel_sync (display, username, pid, - caller_uid, + uid, NULL, &error); if (address == NULL) { g_dbus_method_invocation_return_gerror (invocation, error); g_error_free (error); return TRUE; } gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager), invocation, address); g_free (address); return TRUE; } static void manager_interface_init (GdmDBusManagerIface *interface) { interface->handle_open_session = gdm_manager_handle_open_session; interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel; } static void on_display_removed (GdmDisplayStore *display_store, const char *id, GdmManager *manager) { GdmDisplay *display; -- 1.8.3.1 From d70697ff1b6e987c7437fb1a9a8459626bc5358d Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 1 Nov 2013 15:27:14 -0400 Subject: [PATCH 5/5] slave: Pass session id to unlocking code if we know it We currently figure out which session to unlock on-the-fly based on the username that was just reauthenticated. This doesn't work, for XDMCP sessions, under logind, since they don't have a seat. There's no reason to try to deduce the session, though. We already know it, so we might as well pass it down. This fixes unlocking for XDMCP. --- daemon/gdm-simple-slave.c | 5 ++++- daemon/gdm-slave.c | 13 +++++++++---- daemon/gdm-slave.h | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c index 35951c7..1fe58bc 100644 --- a/daemon/gdm-simple-slave.c +++ b/daemon/gdm-simple-slave.c @@ -410,69 +410,72 @@ greeter_reset_timeout (GdmSimpleSlave *slave) return FALSE; } static void queue_greeter_reset (GdmSimpleSlave *slave) { if (slave->priv->greeter_reset_id > 0) { return; } slave->priv->greeter_reset_id = g_idle_add ((GSourceFunc)greeter_reset_timeout, slave); } static void gdm_simple_slave_start_session_when_ready (GdmSimpleSlave *slave, const char *service_name) { if (slave->priv->start_session_when_ready) { slave->priv->waiting_to_start_session = FALSE; queue_start_session (slave, service_name); } else { slave->priv->waiting_to_start_session = TRUE; } } static gboolean switch_to_and_unlock_session (GdmSimpleSlave *slave, gboolean fail_if_already_switched) { char *username; + char *session_id; gboolean res; username = gdm_session_get_username (slave->priv->session); + session_id = gdm_session_get_session_id (slave->priv->session); g_debug ("GdmSimpleSlave: trying to switch to session for user %s", username); /* try to switch to an existing session */ - res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username, fail_if_already_switched); + res = gdm_slave_switch_to_user_session (GDM_SLAVE (slave), username, session_id, fail_if_already_switched); g_free (username); + g_free (session_id); return res; } static void stop_greeter (GdmSimpleSlave *slave) { char *username; gboolean script_successful; g_debug ("GdmSimpleSlave: Stopping greeter"); if (slave->priv->greeter_environment == NULL) { g_debug ("GdmSimpleSlave: No greeter running"); return; } /* Run the PostLogin script. gdmslave suspends until script has terminated */ username = NULL; if (slave->priv->session != NULL) { username = gdm_session_get_username (slave->priv->session); } if (username != NULL) { script_successful = gdm_slave_run_script (GDM_SLAVE (slave), GDMCONFDIR "/PostLogin", username); } else { script_successful = TRUE; } g_free (username); diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c index ba292a3..e5c8be7 100644 --- a/daemon/gdm-slave.c +++ b/daemon/gdm-slave.c @@ -1620,73 +1620,78 @@ session_unlock_for_ck (GdmSlave *slave, g_variant_unref (reply); return TRUE; } #endif static gboolean session_unlock (GdmSlave *slave, const char *ssid) { g_debug ("Unlocking session %s", ssid); #ifdef WITH_SYSTEMD if (LOGIND_RUNNING()) { return session_unlock_for_systemd (slave, ssid); } #endif #ifdef WITH_CONSOLE_KIT return session_unlock_for_ck (slave, ssid); #else return TRUE; #endif } gboolean gdm_slave_switch_to_user_session (GdmSlave *slave, const char *username, + const char *session_id, gboolean fail_if_already_switched) { gboolean res; gboolean ret; gboolean session_already_switched; char *ssid_to_activate; ret = FALSE; - ssid_to_activate = gdm_slave_get_primary_session_id_for_user (slave, username); - if (ssid_to_activate == NULL) { - g_debug ("GdmSlave: unable to determine session to activate"); - goto out; + if (session_id != NULL) { + ssid_to_activate = g_strdup (session_id); + } else { + ssid_to_activate = gdm_slave_get_primary_session_id_for_user (slave, username); + if (ssid_to_activate == NULL) { + g_debug ("GdmSlave: unable to determine session to activate"); + goto out; + } } session_already_switched = session_is_active (slave, slave->priv->display_seat_id, ssid_to_activate); g_debug ("GdmSlave: Activating session: '%s'", ssid_to_activate); if (session_already_switched && fail_if_already_switched) { g_debug ("GdmSlave: unable to activate session since it's already active: %s", ssid_to_activate); goto out; } if (!session_already_switched) { res = activate_session_id (slave, slave->priv->display_seat_id, ssid_to_activate); if (! res) { g_debug ("GdmSlave: unable to activate session: %s", ssid_to_activate); goto out; } } res = session_unlock (slave, ssid_to_activate); if (!res) { /* this isn't fatal */ g_debug ("GdmSlave: unable to unlock session: %s", ssid_to_activate); } ret = TRUE; out: g_free (ssid_to_activate); diff --git a/daemon/gdm-slave.h b/daemon/gdm-slave.h index 902de21..9808433 100644 --- a/daemon/gdm-slave.h +++ b/daemon/gdm-slave.h @@ -73,44 +73,45 @@ typedef struct typedef enum { GDM_SLAVE_ERROR_GENERIC, GDM_SLAVE_ERROR_UNSUPPORTED, GDM_SLAVE_ERROR_NOT_OPENED, GDM_SLAVE_ERROR_WRONG_SESSION, } GdmSlaveError; #define GDM_SLAVE_ERROR (gdm_slave_error_quark ()) GQuark gdm_slave_error_quark (void); GType gdm_slave_get_type (void); gboolean gdm_slave_start (GdmSlave *slave); gboolean gdm_slave_stop (GdmSlave *slave); char * gdm_slave_get_primary_session_id_for_user (GdmSlave *slave, const char *username); gboolean gdm_slave_get_timed_login_details (GdmSlave *slave, gboolean *enabled, char **username, int *delay); gboolean gdm_slave_add_user_authorization (GdmSlave *slave, const char *username, char **filename); gboolean gdm_slave_switch_to_user_session (GdmSlave *slave, const char *username, + const char *session_id, gboolean fail_if_already_switched); gboolean gdm_slave_connect_to_x11_display (GdmSlave *slave); void gdm_slave_set_initial_cursor_position (GdmSlave *slave); gboolean gdm_slave_run_script (GdmSlave *slave, const char *dir, const char *username); void gdm_slave_export_interface (GdmSlave *slave, GDBusInterfaceSkeleton *interface); G_END_DECLS #endif /* __GDM_SLAVE_H */ -- 1.8.3.1