From 5afc4cd548f3ae8db9fbaab32fe2189efff37677 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Tue, 12 Jan 2016 21:42:15 -0600 Subject: [PATCH 01/13] manager: be more robust against autologin having an invalid user If the configured autologin user does not exist, fall back to a greeter session. https://bugzilla.gnome.org/show_bug.cgi?id=695250 --- configure.ac | 2 +- daemon/gdm-manager.c | 115 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 31 deletions(-) diff --git a/configure.ac b/configure.ac index 6613097b..119297c5 100644 --- a/configure.ac +++ b/configure.ac @@ -36,61 +36,61 @@ AC_SUBST(LT_AGE) AC_HEADER_STDC AC_SUBST(VERSION) AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) # Documentation enable_documentation=no m4_ifdef([YELP_HELP_INIT],[ YELP_HELP_INIT enable_documentation=yes ]) AM_CONDITIONAL(ENABLE_DOCUMENTATION, test x$enable_documentation = xyes) # i18n stuff IT_PROG_INTLTOOL([0.40.0]) GETTEXT_PACKAGE=gdm AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [gettext package]) dnl --------------------------------------------------------------------------- dnl - Dependencies dnl --------------------------------------------------------------------------- GLIB_REQUIRED_VERSION=2.36.0 GTK_REQUIRED_VERSION=2.91.1 LIBCANBERRA_GTK_REQUIRED_VERSION=0.4 -ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.12 +ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.35 EXTRA_COMPILE_WARNINGS(yes) PKG_CHECK_MODULES(GTHREAD, gthread-2.0) AC_SUBST(GTHREAD_CFLAGS) AC_SUBST(GTHREAD_LIBS) PKG_CHECK_MODULES(COMMON, gobject-2.0 >= $GLIB_REQUIRED_VERSION gio-2.0 >= $GLIB_REQUIRED_VERSION gio-unix-2.0 >= $GLIB_REQUIRED_VERSION ) AC_SUBST(COMMON_CFLAGS) AC_SUBST(COMMON_LIBS) PKG_CHECK_MODULES(DAEMON, gobject-2.0 >= $GLIB_REQUIRED_VERSION gio-2.0 >= $GLIB_REQUIRED_VERSION gio-unix-2.0 >= $GLIB_REQUIRED_VERSION accountsservice >= $ACCOUNTS_SERVICE_REQUIRED_VERSION xcb ) AC_SUBST(DAEMON_CFLAGS) AC_SUBST(DAEMON_LIBS) GLIB_GSETTINGS PKG_CHECK_MODULES(XLIB, x11 xau, , [AC_PATH_XTRA if test "x$no_x" = xyes; then diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 35a7a0fe..e78228b4 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -7,60 +7,62 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include + #include #include "gdm-common.h" #include "gdm-dbus-util.h" #include "gdm-manager.h" #include "gdm-manager-glue.h" #include "gdm-display-store.h" #include "gdm-display-factory.h" #include "gdm-local-display.h" #include "gdm-local-display-factory.h" #include "gdm-session.h" #include "gdm-session-record.h" #include "gdm-settings-direct.h" #include "gdm-settings-keys.h" #include "gdm-xdmcp-display-factory.h" #define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate)) #define GDM_DBUS_PATH "/org/gnome/DisplayManager" #define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager" #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays" #define INITIAL_SETUP_USERNAME "gnome-initial-setup" typedef struct { GdmManager *manager; GdmSession *session; char *service_name; @@ -1227,79 +1229,60 @@ get_automatic_login_details (GdmManager *manager, if (res && enabled) { res = gdm_settings_direct_get_string (GDM_KEY_AUTO_LOGIN_USER, &username); } if (enabled && res && username != NULL && username[0] != '\0') { goto out; } g_free (username); username = NULL; enabled = FALSE; out: if (enabled) { g_debug ("GdmDisplay: Got automatic login details for display: %d %s", enabled, username); } else { g_debug ("GdmDisplay: Got automatic login details for display: 0"); } if (usernamep != NULL) { *usernamep = username; } else { g_free (username); } return enabled; } -static gboolean -display_should_autologin (GdmManager *manager, - GdmDisplay *display) -{ - gboolean enabled = FALSE; - - if (manager->priv->ran_once) { - return FALSE; - } - - if (!display_is_on_seat0 (display)) { - return FALSE; - } - - enabled = get_automatic_login_details (manager, NULL); - - return enabled; -} - static void maybe_start_pending_initial_login (GdmManager *manager, GdmDisplay *greeter_display) { StartUserSessionOperation *operation; char *greeter_seat_id = NULL; char *user_session_seat_id = NULL; /* There may be a user session waiting to be started. * This would happen if we couldn't start it earlier because * the login screen X server was coming up and two X servers * can't be started on the same seat at the same time. */ if (manager->priv->initial_login_operation == NULL) { return; } operation = manager->priv->initial_login_operation; g_object_get (G_OBJECT (greeter_display), "seat-id", &greeter_seat_id, NULL); g_object_get (G_OBJECT (operation->session), "display-seat-id", &user_session_seat_id, NULL); if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) { start_user_session (manager, operation); manager->priv->initial_login_operation = NULL; @@ -1347,114 +1330,186 @@ set_up_automatic_login_session (GdmManager *manager, g_object_set (G_OBJECT (session), "display-is-initial", is_initial, NULL); g_debug ("GdmManager: Starting automatic login conversation"); gdm_session_start_conversation (session, "gdm-autologin"); } static void set_up_greeter_session (GdmManager *manager, GdmDisplay *display) { const char *allowed_user; struct passwd *passwd_entry; allowed_user = get_username_for_greeter_display (manager, display); if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) { g_warning ("GdmManager: couldn't look up username %s", allowed_user); gdm_display_unmanage (display); gdm_display_finish (display); return; } create_embryonic_user_session_for_display (manager, display, passwd_entry->pw_uid); gdm_display_start_greeter_session (display); } static void +set_up_automatic_login_session_if_user_exists (GdmManager *manager, + GdmDisplay *display, + ActUser *user) +{ + if (act_user_is_nonexistent (user)) + set_up_greeter_session (manager, display); + else + set_up_automatic_login_session (manager, display); +} + +typedef struct { + GdmManager *manager; + GdmDisplay *display; + char *username; +} UsernameLookupOperation; + +static void +destroy_username_lookup_operation (UsernameLookupOperation *operation) +{ + g_object_unref (operation->manager); + g_object_unref (operation->display); + g_free (operation->username); + g_free (operation); +} + +static void +on_user_is_loaded_changed (ActUser *user, + GParamSpec *pspec, + UsernameLookupOperation *operation) +{ + if (act_user_is_loaded (user)) { + set_up_automatic_login_session_if_user_exists (operation->manager, operation->display, user); + g_signal_handlers_disconnect_by_func (G_OBJECT (user), + G_CALLBACK (on_user_is_loaded_changed), + operation); + destroy_username_lookup_operation (operation); + } +} + +static void +set_up_session (GdmManager *manager, + GdmDisplay *display) +{ + ActUserManager *user_manager; + ActUser *user; + gboolean loaded; + gboolean autologin_enabled = FALSE; + char *username = NULL; + + if (!manager->priv->ran_once && display_is_on_seat0 (display)) + autologin_enabled = get_automatic_login_details (manager, &username); + + if (!autologin_enabled) { + set_up_greeter_session (manager, display); + g_free (username); + return; + } + + /* Check whether the user really exists before committing to autologin. */ + user_manager = act_user_manager_get_default (); + user = act_user_manager_get_user (user_manager, username); + g_object_get (user_manager, "is-loaded", &loaded, NULL); + + if (loaded) { + set_up_automatic_login_session_if_user_exists (manager, display, user); + } else { + UsernameLookupOperation *operation; + + operation = g_new (UsernameLookupOperation, 1); + operation->manager = g_object_ref (manager); + operation->display = g_object_ref (display); + operation->username = username; + + g_signal_connect (user, + "notify::is-loaded", + G_CALLBACK (on_user_is_loaded_changed), + operation); + } +} + +static void greeter_display_started (GdmManager *manager, GdmDisplay *display) { if (manager->priv->ran_once) { return; } maybe_start_pending_initial_login (manager, display); manager->priv->ran_once = TRUE; } static void on_display_status_changed (GdmDisplay *display, GParamSpec *arg1, GdmManager *manager) { int status; int display_number = -1; #ifdef WITH_PLYMOUTH gboolean display_is_local = FALSE; gboolean quit_plymouth = FALSE; g_object_get (display, "is-local", &display_is_local, NULL); quit_plymouth = display_is_local && manager->priv->plymouth_is_running; #endif g_object_get (display, "x11-display-number", &display_number, NULL); status = gdm_display_get_status (display); switch (status) { case GDM_DISPLAY_PREPARED: case GDM_DISPLAY_MANAGED: if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) || (display_number != -1 && status == GDM_DISPLAY_MANAGED)) { char *session_class; g_object_get (display, "session-class", &session_class, NULL); - if (g_strcmp0 (session_class, "greeter") == 0) { - gboolean will_autologin; - - will_autologin = display_should_autologin (manager, display); - - if (will_autologin) { - set_up_automatic_login_session (manager, display); - } else { - set_up_greeter_session (manager, display); - } - } + if (g_strcmp0 (session_class, "greeter") == 0) + set_up_session (manager, display); g_free (session_class); } if (status == GDM_DISPLAY_MANAGED) { greeter_display_started (manager, display); } break; case GDM_DISPLAY_FAILED: case GDM_DISPLAY_UNMANAGED: case GDM_DISPLAY_FINISHED: #ifdef WITH_PLYMOUTH if (quit_plymouth) { plymouth_quit_without_transition (); manager->priv->plymouth_is_running = FALSE; } #endif maybe_start_pending_initial_login (manager, display); break; default: break; } } static void on_display_removed (GdmDisplayStore *display_store, const char *id, GdmManager *manager) { -- 2.12.0