diff --git a/common/gdm-common.c b/common/gdm-common.c index 654b84e0a..4f56a05d4 100644 --- a/common/gdm-common.c +++ b/common/gdm-common.c @@ -88,42 +88,6 @@ gdm_get_pwent_for_name (const char *name, return (pwent != NULL); } -gboolean -gdm_get_pwent_for_uid (uid_t uid, - struct passwd **pwentp) -{ - struct passwd *pwent; - - do { - errno = 0; - pwent = getpwuid (uid); - } while (pwent == NULL && errno == EINTR); - - if (pwentp != NULL) { - *pwentp = pwent; - } - - return (pwent != NULL); -} - -gboolean -gdm_get_grent_for_name (const char *name, - struct group **grentp) -{ - struct group *grent; - - do { - errno = 0; - grent = getgrnam (name); - } while (grent == NULL && errno == EINTR); - - if (grentp != NULL) { - *grentp = grent; - } - - return (grent != NULL); -} - static gboolean gdm_get_grent_for_gid (gint gid, struct group **grentp) diff --git a/common/gdm-common.h b/common/gdm-common.h index 3e210b87b..cffefe1e4 100644 --- a/common/gdm-common.h +++ b/common/gdm-common.h @@ -24,7 +24,6 @@ #include #include -#include #include #include @@ -64,12 +63,6 @@ gboolean gdm_find_display_session (GPid pid, gboolean gdm_get_pwent_for_name (const char *name, struct passwd **pwentp); -gboolean gdm_get_pwent_for_uid (uid_t uid, - struct passwd **pwentp); - -gboolean gdm_get_grent_for_name (const char *name, - struct group **grentp); - gboolean gdm_clear_close_on_exec_flag (int fd); char *gdm_generate_random_bytes (gsize size, diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c index 54e054808..5a5096aa1 100644 --- a/daemon/gdm-display.c +++ b/daemon/gdm-display.c @@ -1678,32 +1678,6 @@ wants_initial_setup (GdmDisplay *self) return enabled; } -gboolean -gdm_display_prepare_greeter_session (GdmDisplay *self, - GdmDynamicUserStore *dyn_user_store, - uid_t *ret_uid) -{ - g_autoptr (GError) error = NULL; - GdmDisplayPrivate *priv; - uid_t uid; - - g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); - priv = gdm_display_get_instance_private (self); - g_return_val_if_fail (g_strcmp0 (priv->session_class, "greeter") == 0, FALSE); - - if (!gdm_launch_environment_ensure_uid (priv->launch_environment, - dyn_user_store, &uid, &error)) { - g_warning ("GdmDisplay: Failed to allocate UID for greeter: %s", - error->message); - return FALSE; - } - - if (ret_uid != NULL) - *ret_uid = uid; - - return TRUE; -} - void gdm_display_start_greeter_session (GdmDisplay *self) { diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h index c91c44995..1575faac2 100644 --- a/daemon/gdm-display.h +++ b/daemon/gdm-display.h @@ -25,8 +25,6 @@ #include #include -#include "gdm-dynamic-user-store.h" - G_BEGIN_DECLS #define GDM_TYPE_DISPLAY (gdm_display_get_type ()) @@ -109,9 +107,6 @@ gboolean gdm_display_add_user_authorization (GdmDisplay *disp gboolean gdm_display_remove_user_authorization (GdmDisplay *display, const char *username, GError **error); -gboolean gdm_display_prepare_greeter_session (GdmDisplay *display, - GdmDynamicUserStore *dyn_user_store, - uid_t *ret_uid); void gdm_display_start_greeter_session (GdmDisplay *display); void gdm_display_stop_greeter_session (GdmDisplay *display); diff --git a/daemon/gdm-dynamic-user-store.h b/daemon/gdm-dynamic-user-store.h deleted file mode 100644 index 848f00525..000000000 --- a/daemon/gdm-dynamic-user-store.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright Red Hat - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - */ - -#pragma once - -#include - -#include -#include - -G_BEGIN_DECLS - -#define GDM_TYPE_DYNAMIC_USER_STORE (gdm_dynamic_user_store_get_type ()) -G_DECLARE_FINAL_TYPE (GdmDynamicUserStore, gdm_dynamic_user_store, GDM, DYNAMIC_USER_STORE, GObject) - -typedef enum -{ - GDM_DYNAMIC_USER_STORE_ERROR_NO_FREE_UID, - GDM_DYNAMIC_USER_STORE_ERROR_NO_SUCH_GROUP, -} GdmDynamicUserStoreError; - -#define GDM_DYNAMIC_USER_STORE_ERROR (gdm_dynamic_user_store_error_quark ()) - -GQuark gdm_dynamic_user_store_error_quark (void); - -GdmDynamicUserStore *gdm_dynamic_user_store_new (void); - -gboolean gdm_dynamic_user_store_create (GdmDynamicUserStore *store, - const char *preferred_username, - const char *display_name, - const char *member_of, - char **ret_username, - uid_t *ret_uid, - char **ret_home, - GError **error); - -void gdm_dynamic_user_store_remove (GdmDynamicUserStore *store, - uid_t uid); - -G_END_DECLS diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c index 67f6c29..29cbc14 100644 --- a/daemon/gdm-launch-environment.c +++ b/daemon/gdm-launch-environment.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #ifdef HAVE_SYS_PRCTL_H #include @@ -49,19 +51,9 @@ #include "gdm-settings-direct.h" #include "gdm-settings-keys.h" -#define GDM_GREETER_USERNAME "gdm-greeter" -#define GDM_GREETER_DISP_NAME "GDM Greeter" -#define GDM_SESSION_MODE "gdm" - -#define INITIAL_SETUP_SESSION "gnome-initial-setup" #define INITIAL_SETUP_USERNAME "gnome-initial-setup" -#define INITIAL_SETUP_DISP_NAME "GNOME Initial Setup" +#define GDM_SESSION_MODE "gdm" #define INITIAL_SETUP_SESSION_MODE "initial-setup" -#define INITIAL_SETUP_GROUPNAME "gnome-initial-setup" -#define INITIAL_SETUP_DCONF_PROFILE "gnome-initial-setup" - -#define GDM_CHOOSER_USERNAME "gdm-chooser" -#define GDM_CHOOSER_DISP_NAME "GDM XDMCP Chooser" extern char **environ; @@ -74,15 +66,9 @@ struct _GdmLaunchEnvironment GdmSessionVerificationMode verification_mode; - GdmDynamicUserStore *dyn_user_store; - char *preferred_user_name; - char *user_disp_name; - char *user_member_of; - char *dyn_user_name; - uid_t dyn_uid; - char *dyn_user_home; + char *user_name; + char *runtime_dir; - char *dconf_profile; char *session_id; char *session_type; char *session_mode; @@ -105,10 +91,8 @@ enum { PROP_X11_DISPLAY_HOSTNAME, PROP_X11_AUTHORITY_FILE, PROP_X11_DISPLAY_IS_LOCAL, - PROP_PREFERRED_USER_NAME, - PROP_USER_DISP_NAME, - PROP_USER_MEMBER_OF, - PROP_DCONF_PROFILE, + PROP_USER_NAME, + PROP_RUNTIME_DIR, PROP_COMMAND, }; @@ -270,8 +254,8 @@ static GHashTable * build_launch_environment (GdmLaunchEnvironment *launch_environment, gboolean start_session) { - gboolean is_initial_setup = FALSE; GHashTable *hash; + struct passwd *pwent; static const char *const optional_environment[] = { "GI_TYPELIB_PATH", "LANG", @@ -318,11 +302,9 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment, if (launch_environment->session_mode != NULL) { g_hash_table_insert (hash, g_strdup ("GNOME_SHELL_SESSION_MODE"), g_strdup (launch_environment->session_mode)); - g_hash_table_insert (hash, g_strdup ("DCONF_PROFILE"), g_strdup (launch_environment->dconf_profile)); + g_hash_table_insert (hash, g_strdup ("DCONF_PROFILE"), g_strdup (launch_environment->user_name)); - is_initial_setup = strcmp (launch_environment->session_mode, INITIAL_SETUP_SESSION_MODE) == 0; - - if (!is_initial_setup) { + if (strcmp (launch_environment->session_mode, INITIAL_SETUP_SESSION_MODE) != 0) { /* gvfs is needed for fetching remote avatars in the initial setup. Disable it otherwise. */ g_hash_table_insert (hash, g_strdup ("GVFS_DISABLE_FUSE"), g_strdup ("1")); g_hash_table_insert (hash, g_strdup ("GIO_USE_VFS"), g_strdup ("local")); @@ -330,16 +312,26 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment, } } - g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (launch_environment->dyn_user_name)); - g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (launch_environment->dyn_user_name)); - g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (launch_environment->dyn_user_name)); + g_hash_table_insert (hash, g_strdup ("LOGNAME"), g_strdup (launch_environment->user_name)); + g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (launch_environment->user_name)); + g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (launch_environment->user_name)); g_hash_table_insert (hash, g_strdup ("GDM_VERSION"), g_strdup (VERSION)); g_hash_table_remove (hash, "MAIL"); - g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (launch_environment->dyn_user_home)); - g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup (launch_environment->dyn_user_home)); - g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (NOLOGIN_PATH)); + g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/")); + g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/")); + g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh")); + + gdm_get_pwent_for_name (launch_environment->user_name, &pwent); + if (pwent != NULL) { + if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') { + g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir)); + g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup (pwent->pw_dir)); + } + + g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (pwent->pw_shell)); + } if (start_session && launch_environment->x11_display_seat_id != NULL) { char *seat_id; @@ -350,8 +342,7 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment, g_hash_table_insert (hash, g_strdup ("GDM_SEAT_ID"), g_strdup (seat_id)); - if (!is_initial_setup && - setup_seat_persist_dirs(seat_id, launch_environment->dyn_uid, &config_dir, &state_dir)) { + if (setup_seat_persist_dirs(seat_id, pwent->pw_uid, &config_dir, &state_dir)) { g_hash_table_insert (hash, g_strdup ("XDG_CONFIG_HOME"), config_dir); g_hash_table_insert (hash, g_strdup ("XDG_STATE_HOME"), state_dir); } @@ -473,7 +464,7 @@ on_conversation_started (GdmSession *session, gdm_session_setup_for_program (launch_environment->session, "gdm-launch-environment", - launch_environment->dyn_user_name, + launch_environment->user_name, log_path); } @@ -498,31 +489,24 @@ on_conversation_stopped (GdmSession *session, } } -gboolean -gdm_launch_environment_ensure_uid (GdmLaunchEnvironment *launch_environment, - GdmDynamicUserStore *dyn_user_store, - uid_t *uid, - GError **error) +static gboolean +ensure_directory_with_uid_gid (const char *path, + uid_t uid, + gid_t gid, + GError **error) { - if (launch_environment->dyn_uid != 0) { - *uid = launch_environment->dyn_uid; - return TRUE; + if (mkdir (path, 0700) == -1 && errno != EEXIST) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to create directory %s: %s", path, + g_strerror (errno)); + return FALSE; } - - if (!gdm_dynamic_user_store_create (dyn_user_store, - launch_environment->preferred_user_name, - launch_environment->user_disp_name, - launch_environment->user_member_of, - &launch_environment->dyn_user_name, - &launch_environment->dyn_uid, - &launch_environment->dyn_user_home, - error)) + if (chown (path, uid, gid) == -1) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to set owner of %s: %s", path, + g_strerror (errno)); return FALSE; - - /* We've allocated the UID, so let's make sure we can deallocate later */ - g_set_object (&launch_environment->dyn_user_store, dyn_user_store); - - *uid = launch_environment->dyn_uid; + } return TRUE; } @@ -536,14 +520,37 @@ gboolean gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment) { g_autoptr(GError) error = NULL; + struct passwd *passwd_entry; + uid_t uid; + gid_t gid; g_return_val_if_fail (GDM_IS_LAUNCH_ENVIRONMENT (launch_environment), FALSE); - g_return_val_if_fail (launch_environment->dyn_uid != 0, FALSE); g_debug ("GdmLaunchEnvironment: Starting..."); + if (!gdm_get_pwent_for_name (launch_environment->user_name, &passwd_entry)) { + g_critical ("GdmLaunchEnvironment: Unknown user %s", launch_environment->user_name); + return FALSE; + } + + uid = passwd_entry->pw_uid; + gid = passwd_entry->pw_gid; + + g_debug ("GdmLaunchEnvironment: Setting up run time dir %s", + launch_environment->runtime_dir); + if (!ensure_directory_with_uid_gid (launch_environment->runtime_dir, uid, gid, &error)) { + g_critical ("GdmLaunchEnvironment: %s", error->message); + return FALSE; + } + + /* Create the home directory too */ + if (!ensure_directory_with_uid_gid (passwd_entry->pw_dir, uid, gid, &error)) { + g_critical ("GdmLaunchEnvironment: %s", error->message); + return FALSE; + } + launch_environment->session = gdm_session_new (launch_environment->verification_mode, - launch_environment->dyn_uid, + uid, launch_environment->x11_display_name, launch_environment->x11_display_hostname, launch_environment->x11_display_device, @@ -621,12 +628,6 @@ gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment) g_clear_object (&launch_environment->session); } - if (launch_environment->dyn_uid != 0) { - gdm_dynamic_user_store_remove (launch_environment->dyn_user_store, - launch_environment->dyn_uid); - launch_environment->dyn_uid = 0; - } - g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0); return TRUE; @@ -719,35 +720,19 @@ _gdm_launch_environment_set_x11_authority_file (GdmLaunchEnvironment *launch_env } static void -_gdm_launch_environment_set_preferred_user_name (GdmLaunchEnvironment *launch_environment, - const char *name) +_gdm_launch_environment_set_user_name (GdmLaunchEnvironment *launch_environment, + const char *name) { - g_free (launch_environment->preferred_user_name); - launch_environment->preferred_user_name = g_strdup (name); + g_free (launch_environment->user_name); + launch_environment->user_name = g_strdup (name); } static void -_gdm_launch_environment_set_user_disp_name (GdmLaunchEnvironment *launch_environment, - const char *disp_name) +_gdm_launch_environment_set_runtime_dir (GdmLaunchEnvironment *launch_environment, + const char *dir) { - g_free (launch_environment->user_disp_name); - launch_environment->user_disp_name = g_strdup (disp_name); -} - -static void -_gdm_launch_environment_set_user_member_of (GdmLaunchEnvironment *launch_environment, - const char *member_of) -{ - g_free (launch_environment->user_member_of); - launch_environment->user_member_of = g_strdup (member_of); -} - -static void -_gdm_launch_environment_set_dconf_profile (GdmLaunchEnvironment *launch_environment, - const char *profile) -{ - g_free (launch_environment->dconf_profile); - launch_environment->dconf_profile = g_strdup (profile); + g_free (launch_environment->runtime_dir); + launch_environment->runtime_dir = g_strdup (dir); } static void @@ -796,17 +781,11 @@ gdm_launch_environment_set_property (GObject *object, case PROP_X11_AUTHORITY_FILE: _gdm_launch_environment_set_x11_authority_file (self, g_value_get_string (value)); break; - case PROP_PREFERRED_USER_NAME: - _gdm_launch_environment_set_preferred_user_name (self, g_value_get_string (value)); - break; - case PROP_USER_DISP_NAME: - _gdm_launch_environment_set_user_disp_name (self, g_value_get_string (value)); + case PROP_USER_NAME: + _gdm_launch_environment_set_user_name (self, g_value_get_string (value)); break; - case PROP_USER_MEMBER_OF: - _gdm_launch_environment_set_user_member_of (self, g_value_get_string (value)); - break; - case PROP_DCONF_PROFILE: - _gdm_launch_environment_set_dconf_profile (self, g_value_get_string (value)); + case PROP_RUNTIME_DIR: + _gdm_launch_environment_set_runtime_dir (self, g_value_get_string (value)); break; case PROP_COMMAND: _gdm_launch_environment_set_command (self, g_value_get_string (value)); @@ -855,17 +834,11 @@ gdm_launch_environment_get_property (GObject *object, case PROP_X11_AUTHORITY_FILE: g_value_set_string (value, self->x11_authority_file); break; - case PROP_PREFERRED_USER_NAME: - g_value_set_string (value, self->preferred_user_name); - break; - case PROP_USER_DISP_NAME: - g_value_set_string (value, self->user_disp_name); - break; - case PROP_USER_MEMBER_OF: - g_value_set_string (value, self->user_member_of); + case PROP_USER_NAME: + g_value_set_string (value, self->user_name); break; - case PROP_DCONF_PROFILE: - g_value_set_string (value, self->dconf_profile); + case PROP_RUNTIME_DIR: + g_value_set_string (value, self->runtime_dir); break; case PROP_COMMAND: g_value_set_string (value, self->command); @@ -950,31 +923,17 @@ gdm_launch_environment_class_init (GdmLaunchEnvironmentClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, - PROP_PREFERRED_USER_NAME, - g_param_spec_string ("preferred-user-name", - "preferred user name", - "preferred user name", + PROP_USER_NAME, + g_param_spec_string ("user-name", + "user name", + "user name", GDM_USERNAME, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, - PROP_USER_DISP_NAME, - g_param_spec_string ("user-display-name", - "user display name", - "user display name", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_USER_MEMBER_OF, - g_param_spec_string ("user-member-of", - "user member of", - "user member of", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, - PROP_DCONF_PROFILE, - g_param_spec_string ("dconf-profile", - "dconf profile", - "dconf profile", + PROP_RUNTIME_DIR, + g_param_spec_string ("runtime-dir", + "runtime dir", + "runtime dir", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, @@ -1074,12 +1033,8 @@ gdm_launch_environment_finalize (GObject *object) } g_free (launch_environment->command); - g_free (launch_environment->preferred_user_name); - g_free (launch_environment->dyn_user_name); - g_free (launch_environment->dyn_user_home); - g_free (launch_environment->user_disp_name); - g_free (launch_environment->user_member_of); - g_free (launch_environment->dconf_profile); + g_free (launch_environment->user_name); + g_free (launch_environment->runtime_dir); g_free (launch_environment->x11_display_name); g_free (launch_environment->x11_display_seat_id); g_free (launch_environment->x11_display_device); @@ -1088,17 +1043,12 @@ gdm_launch_environment_finalize (GObject *object) g_free (launch_environment->session_id); g_free (launch_environment->session_type); - g_clear_object (&launch_environment->dyn_user_store); - G_OBJECT_CLASS (gdm_launch_environment_parent_class)->finalize (object); } static GdmLaunchEnvironment * create_gnome_session_environment (const char *session_id, - const char *preferred_user_name, - const char *user_display_name, - const char *user_member_of, - const char *dconf_profile, + const char *user_name, const char *display_name, const char *seat_id, const char *session_type, @@ -1117,6 +1067,9 @@ create_gnome_session_environment (const char *session_id, args = g_ptr_array_new (); g_ptr_array_add (args, "gnome-session"); + g_ptr_array_add (args, "--autostart"); + g_ptr_array_add (args, DATADIR "/gdm/greeter/autostart"); + if (debug) { g_ptr_array_add (args, "--debug"); } @@ -1133,16 +1086,14 @@ create_gnome_session_environment (const char *session_id, launch_environment = g_object_new (GDM_TYPE_LAUNCH_ENVIRONMENT, "command", command, - "preferred-user-name", preferred_user_name, - "user-display-name", user_display_name, - "user-member-of", user_member_of, - "dconf-profile", dconf_profile, + "user-name", user_name, "session-type", session_type, "session-mode", session_mode, "x11-display-name", display_name, "x11-display-seat-id", seat_id, "x11-display-hostname", display_hostname, "x11-display-is-local", display_is_local, + "runtime-dir", GDM_SCREENSHOT_DIR, NULL); return launch_environment; @@ -1155,11 +1106,10 @@ gdm_create_greeter_launch_environment (const char *display_name, const char *display_hostname, gboolean display_is_local) { - return create_gnome_session_environment (NULL, - GDM_GREETER_USERNAME, - GDM_GREETER_DISP_NAME, - GDM_GROUPNAME, - GDM_DCONF_PROFILE, + const char *session_name = NULL; + + return create_gnome_session_environment (session_name, + GDM_USERNAME, display_name, seat_id, session_type, @@ -1175,11 +1125,8 @@ gdm_create_initial_setup_launch_environment (const char *display_name, const char *display_hostname, gboolean display_is_local) { - return create_gnome_session_environment (INITIAL_SETUP_SESSION, + return create_gnome_session_environment ("gnome-initial-setup", INITIAL_SETUP_USERNAME, - INITIAL_SETUP_DISP_NAME, - INITIAL_SETUP_GROUPNAME, - INITIAL_SETUP_DCONF_PROFILE, display_name, seat_id, session_type, @@ -1199,14 +1146,12 @@ gdm_create_chooser_launch_environment (const char *display_name, launch_environment = g_object_new (GDM_TYPE_LAUNCH_ENVIRONMENT, "command", LIBEXECDIR "/gdm-simple-chooser", "verification-mode", GDM_SESSION_VERIFICATION_MODE_CHOOSER, - "preferred-user-name", GDM_CHOOSER_USERNAME, - "user-display-name", GDM_CHOOSER_DISP_NAME, - "user-member-of", GDM_GROUPNAME, - "dconf-profile", GDM_DCONF_PROFILE, + "user-name", GDM_USERNAME, "x11-display-name", display_name, "x11-display-seat-id", seat_id, "x11-display-hostname", display_hostname, "x11-display-is-local", FALSE, + "runtime-dir", GDM_SCREENSHOT_DIR, NULL); return launch_environment; diff --git a/daemon/gdm-launch-environment.h b/daemon/gdm-launch-environment.h index f0102ef..354cf49 100644 --- a/daemon/gdm-launch-environment.h +++ b/daemon/gdm-launch-environment.h @@ -25,17 +25,12 @@ #include #include "gdm-session.h" -#include "gdm-dynamic-user-store.h" G_BEGIN_DECLS #define GDM_TYPE_LAUNCH_ENVIRONMENT (gdm_launch_environment_get_type ()) G_DECLARE_FINAL_TYPE (GdmLaunchEnvironment, gdm_launch_environment, GDM, LAUNCH_ENVIRONMENT, GObject) -gboolean gdm_launch_environment_ensure_uid (GdmLaunchEnvironment *launch_environment, - GdmDynamicUserStore *dyn_user_store, - uid_t *uid, - GError **error); gboolean gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment); gboolean gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment); GdmSession * gdm_launch_environment_get_session (GdmLaunchEnvironment *launch_environment); diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index f73bccf61..10a5475f2 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -46,7 +46,6 @@ #include "gdm-manager-glue.h" #include "gdm-display-store.h" #include "gdm-display-factory.h" -#include "gdm-dynamic-user-store.h" #include "gdm-launch-environment.h" #include "gdm-local-display.h" #include "gdm-local-display-factory.h" @@ -63,8 +62,8 @@ #define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager" #define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays" +#define INITIAL_SETUP_USERNAME "gnome-initial-setup" #define ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT GDM_RUN_DIR "/gdm.ran-initial-setup" -#define INITIAL_SETUP_EXPORT_DIR GDM_RUN_DIR "/gnome-initial-setup" typedef struct { @@ -77,7 +76,6 @@ struct _GdmManager { GdmDBusManagerSkeleton parent; - GdmDynamicUserStore *dyn_user_store; GdmDisplayStore *display_store; GdmLocalDisplayFactory *local_factory; #ifdef HAVE_LIBXDMCP @@ -903,7 +901,6 @@ allowed_user = gdm_session_get_allowed_user (session); if (uid != allowed_user) { - g_debug("GdmSession: Denying access to %d, only %d is allowed", uid, allowed_user); g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED, @@ -1369,6 +1366,23 @@ return enabled; } +static const char * +get_username_for_greeter_display (GdmManager *manager, + GdmDisplay *display) +{ + gboolean doing_initial_setup = FALSE; + + g_object_get (G_OBJECT (display), + "doing-initial-setup", &doing_initial_setup, + NULL); + + if (doing_initial_setup) { + return INITIAL_SETUP_USERNAME; + } else { + return GDM_USERNAME; + } +} + static void set_up_automatic_login_session (GdmManager *manager, GdmDisplay *display) @@ -1400,7 +1414,14 @@ set_up_chooser_session (GdmManager *manager, GdmDisplay *display) { - if (!gdm_display_prepare_greeter_session (display, manager->dyn_user_store, NULL)) { + 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; @@ -1414,15 +1435,20 @@ set_up_greeter_session (GdmManager *manager, GdmDisplay *display) { - uid_t greeter_uid; + const char *allowed_user; + struct passwd *passwd_entry; - if (!gdm_display_prepare_greeter_session (display, manager->dyn_user_store, &greeter_uid)) { + 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_user_session_for_display (manager, display, greeter_uid); + create_user_session_for_display (manager, display, passwd_entry->pw_uid); gdm_display_start_greeter_session (display); } @@ -1703,60 +1729,53 @@ clean_user_session); } -static gboolean -export_initial_setup_home_dir (GdmSession *initial_setup_session) +static void +chown_initial_setup_home_dir (void) { - uid_t gis_uid; + GFile *dir; + GError *error; + char *gis_dir_path; + char *gis_uid_path; + char *gis_uid_contents; struct passwd *pwe; - g_autoptr (GFile) gis_home = NULL; - g_autoptr (GError) error = NULL; - g_autofree char *user_uid_path = NULL; - g_autofree char *user_uid_contents = NULL; - uid_t user_uid; - g_autoptr (GFile) gis_export = NULL; - - gis_uid = gdm_session_get_allowed_user (initial_setup_session); + uid_t uid; - if (!gdm_get_pwent_for_uid (gis_uid, &pwe)) { - g_warning ("Failed to resolve gnome-initial-setup UID: %d", gis_uid); - return FALSE; + if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) { + g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME); + return; } - gis_home = g_file_new_for_path (pwe->pw_dir); - - user_uid_path = g_build_filename (pwe->pw_dir, "gnome-initial-setup-uid", NULL); - if (!g_file_get_contents (user_uid_path, &user_uid_contents, NULL, &error)) { - g_warning ("Unable to read %s: %s", user_uid_path, error->message); - return FALSE; - } - user_uid = (uid_t) atoi (user_uid_contents); + gis_dir_path = g_strdup (pwe->pw_dir); - if (!gdm_get_pwent_for_uid (user_uid, &pwe)) { - g_warning ("UID '%s' in %s is not valid", user_uid_contents, user_uid_path); - return FALSE; + gis_uid_path = g_build_filename (gis_dir_path, + "gnome-initial-setup-uid", + NULL); + if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) { + g_warning ("Unable to read %s", gis_uid_path); + goto out; } - g_debug ("Moving %s to " INITIAL_SETUP_EXPORT_DIR, - g_file_peek_path (gis_home)); - - gis_export = g_file_new_for_path (INITIAL_SETUP_EXPORT_DIR); - if (!g_file_move (gis_home, gis_export, G_FILE_COPY_OVERWRITE, NULL, - NULL, NULL, &error)) { - g_warning ("Failed to move %s to " INITIAL_SETUP_EXPORT_DIR ": %s", - g_file_peek_path (gis_home), error->message); - return FALSE; + uid = (uid_t) atoi (gis_uid_contents); + pwe = getpwuid (uid); + if (uid == 0 || pwe == NULL) { + g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path); + goto out; } - g_debug ("Changing ownership of " INITIAL_SETUP_EXPORT_DIR " to %u:%u", - pwe->pw_uid, pwe->pw_gid); + g_debug ("Changing ownership of %s to %u:%u", gis_dir_path, pwe->pw_uid, pwe->pw_gid); - if (!gdm_chown_recursively (gis_export, pwe->pw_uid, pwe->pw_gid, &error)) { - g_warning ("Failed to change ownership of " INITIAL_SETUP_EXPORT_DIR ": %s", - error->message); - return FALSE; - } + error = NULL; + dir = g_file_new_for_path (gis_dir_path); + if (!gdm_chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) { + g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message); + g_error_free (error); + } - return TRUE; + g_object_unref (dir); +out: + g_free (gis_uid_contents); + g_free (gis_uid_path); + g_free (gis_dir_path); } static gboolean @@ -1922,7 +1941,7 @@ "doing-initial-setup", &doing_initial_setup, NULL); if (doing_initial_setup) - export_initial_setup_home_dir (session); + chown_initial_setup_home_dir (); } static void @@ -2854,7 +2873,6 @@ static void gdm_manager_init (GdmManager *manager) { - manager->dyn_user_store = gdm_dynamic_user_store_new (); manager->display_store = gdm_display_store_new (); manager->user_sessions = NULL; manager->open_reauthentication_requests = g_hash_table_new_full (NULL, @@ -2957,7 +2975,6 @@ g_clear_object (&manager->connection); g_clear_object (&manager->object_manager); g_clear_object (&manager->display_store); - g_clear_object (&manager->dyn_user_store); G_OBJECT_CLASS (gdm_manager_parent_class)->dispose (object); } diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c index b78068d42..08ba39cf6 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -3184,18 +3184,33 @@ gdm_session_start_session (GdmSession *self, g_free (command); } else { + /* FIXME: + * Always use a separate DBus bus for each greeter session. + * Firstly, this means that if we run multiple greeter session + * (which we really should not do, but have to currently), then + * each one will get its own DBus session bus. + * But, we also explicitly do this for seat0, because that way + * it cannot make use of systemd to run the GNOME session. This + * prevents the session lookup logic from getting confused. + * This has a similar effect as passing --builtin to gnome-session. + * + * We really should not be doing this. But the fix is to use + * separate dynamically created users and that requires some + * major refactorings. + */ if (run_launcher) { if (is_x11) { - program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"%s\"", + program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"dbus-run-session -- %s\"", register_session ? "--register-session " : "", self->selected_program); } else { - program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"", + program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"dbus-run-session -- %s\"", register_session ? "--register-session " : "", self->selected_program); } } else { - program = g_strdup (self->selected_program); + program = g_strdup_printf ("dbus-run-session -- %s", + self->selected_program); } } diff --git a/daemon/meson.build b/daemon/meson.build index 26fe79bfc..aaf990e25 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -188,7 +188,6 @@ gdm_daemon_sources = files( 'gdm-display-factory.c', 'gdm-display-store.c', 'gdm-display.c', - 'gdm-dynamic-user-store.c', 'gdm-launch-environment.c', 'gdm-legacy-display.c', 'gdm-local-display-factory.c', diff --git a/data/autostart/meson.build b/data/autostart/meson.build new file mode 100644 index 000000000..11ea694ec --- /dev/null +++ b/data/autostart/meson.build @@ -0,0 +1,12 @@ +autostart_files_conf = { + 'LIBEXECDIR': gdm_prefix / get_option('libexecdir'), +} + +foreach autostart_file : [ 'orca-autostart.desktop' ] + configure_file( + input: autostart_file, + output: autostart_file, + configuration: autostart_files_conf, + install_dir: gdm_datadir / 'greeter' / 'autostart', + ) +endforeach diff --git a/data/autostart/orca-autostart.desktop b/data/autostart/orca-autostart.desktop new file mode 100644 index 000000000..944cfd78f --- /dev/null +++ b/data/autostart/orca-autostart.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +Name=Orca screen reader +Exec=orca --disable main-window,splash-window --enable speech,braille +NoDisplay=true +AutostartCondition=GSettings org.gnome.desktop.a11y.applications screen-reader-enabled +X-GNOME-AutoRestart=true diff --git a/data/gdm.conf.in b/data/gdm.conf.in index eda131e02..fcc2bd2b1 100644 --- a/data/gdm.conf.in +++ b/data/gdm.conf.in @@ -71,7 +71,7 @@ send_member="CreateTransientDisplay"/> - + = 257') - - # Our range is documented at https://systemd.io/UIDS-GIDS/ - greeter_uid_min = systemd_dep.get_variable('greeter_uid_min', default_value: '60578') - greeter_uid_max = systemd_dep.get_variable('greeter_uid_max', default_value: '60705') else elogind_dep = dependency('libelogind') logind_dep = elogind_dep systemd_x_server = 'disabled' - have_userdb = false - greeter_uid_min = 0 - greeter_uid_max = 0 endif -nologin_program = find_program('nologin', required: false) -nologin_path = nologin_program.found()? nologin_program.path() : '/sbin/nologin' - # Plymouth plymouth_dep = dependency('ply-boot-client', required: get_option('plymouth')) # Check for Solaris auditing API (ADT) @@ -250,6 +238,7 @@ conf.set_quoted('PACKAGE_VERSION', meson.project_version()) conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) conf.set_quoted('DATADIR', gdm_prefix / get_option('datadir')) +conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir) conf.set_quoted('SYSCONFDIR', gdm_prefix / get_option('sysconfdir')) conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir')) conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir')) @@ -263,9 +252,11 @@ conf.set_quoted('GDM_DATADIR', gdm_prefix / gdm_datadir) conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir) conf.set_quoted('GDM_PRIVATE_DBUS_DIR', gdm_private_dbus_dir) +conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir) conf.set_quoted('GDM_RUN_DIR', gdm_run_dir) conf.set_quoted('GDM_DCONF_PROFILE', 'gdm') conf.set_quoted('GDM_WORKING_DIR', working_dir) +conf.set_quoted('GDM_WORKING_DIR', working_dir) conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('localedir')) conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir) conf.set_quoted('GDM_PID_FILE', gdm_pid_file) @@ -303,11 +294,6 @@ conf.set_quoted('GDM_GROUPNAME', get_option('group')) conf.set('HAVE_LIBXDMCP', have_xdmcp) conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server) -conf.set('HAVE_USERDB', have_userdb) -conf.set('GREETER_UID_MIN', greeter_uid_min) -conf.set('GREETER_UID_MAX', greeter_uid_max) -conf.set_quoted('GDM_DYN_HOME_DIR', gdm_dyn_home_dir) -conf.set_quoted('NOLOGIN_PATH', nologin_path) conf.set('WITH_PLYMOUTH', plymouth_dep.found()) conf.set_quoted('X_SERVER', x_bin) conf.set_quoted('X_PATH', x_path) @@ -359,9 +345,10 @@ 'System DBus': dbus_sys_dir, 'DM conf': dmconfdir, 'GDM conf': gdmconfdir, + 'GDM Screenshot ': gdm_screenshot_dir, 'GDM Xauth': gdm_xauth_dir, + 'GDM RanOnceMarker': ran_once_marker_dir, 'GDM Run': gdm_run_dir, - 'GDM Dynamic Homes': gdm_dyn_home_dir, 'GDM PID file': gdm_pid_file, 'GDM Defaults config': gdm_defaults_conf, 'GDM Custom config': gdm_custom_conf, diff --git a/meson_options.txt b/meson_options.txt index 3f3865c7a..18f223ddf 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -21,8 +21,10 @@ option('plymouth', type: 'feature', value: 'auto', description: 'Add plymouth support.') option('private-dbus-dir', type: 'string', value: '', description: 'Directory for private D-Bus server sockets') option('profiling', type: 'boolean', value: false, description: 'Enable profiling.') +option('ran-once-marker-dir', type: 'string', value: '', description: 'Ran once marker directory.') option('run-dir', type: 'string', value: '', description: 'Runtime directory.') option('runtime-conf', type: 'string', value: '', description: 'Filename to give to runtime configuration file.') +option('screenshot-dir', type: 'string', value: '', description: 'Directory to store greeter screenshot.') option('selinux', type: 'feature', value: 'auto', description: 'Add SELinux support.') option('solaris', type: 'boolean', value: false, description: 'Build for Solaris') option('split-authentication', type: 'boolean', value: true, description: 'Enable multiple simultaneous PAM conversations during login.') @@ -38,5 +40,4 @@ option('x11-support', type: 'boolean', value: true, description: 'Enable support for x11 sessions.') option('working-dir', type: 'string', value: '', description: 'Working directory.') option('xauth-dir', type: 'string', value: '', description: 'XAuth cookie directory.') -option('xdmcp', type: 'feature', value: 'auto', description: 'Add XDMCP (remote login) support.') -option('dyn-home-dir', type: 'string', value: '', description: 'Parent directory for dynamic user home directories') \ No newline at end of file +option('xdmcp', type: 'feature', value: 'auto', description: 'Add XDMCP (remote login) support.') \ No newline at end of file diff --git a/utils/gdm-config.c b/utils/gdm-config.c index f468312c0..82051a1b1 100644 --- a/utils/gdm-config.c +++ b/utils/gdm-config.c @@ -482,6 +482,53 @@ config_command_handler_add_to_group (GdmConfigCommandHandler *command_handler, command_handler->post_parse_func); } +static gboolean +switch_to_gdm_user (GError **error) { + struct passwd *pwent; + + /* We don't care about forking here, as we need to do just one action + * so, once we switch, there's no point of return */ + + gdm_get_pwent_for_name (GDM_USERNAME, &pwent); + + if (pwent == NULL) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + _("Failed to switch to %s user"), GDM_USERNAME); + return FALSE; + } + + g_debug ("Switching to %s user (uid:gid) %d:%d", + GDM_USERNAME, pwent->pw_uid, pwent->pw_gid); + + if (setgid (pwent->pw_gid) < 0) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn’t set groupid to %d"), pwent->pw_gid); + return FALSE; + } + + if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("initgroups () failed for %s"), pwent->pw_name); + return FALSE; + } + + if (setuid (pwent->pw_uid) < 0) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Couldn’t set userid to %u"), pwent->pw_uid); + return FALSE; + } + + g_unsetenv ("XDG_RUNTIME_DIR"); + g_unsetenv ("DISPLAY"); + + if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') { + g_setenv ("HOME", pwent->pw_dir, TRUE); + g_setenv ("PWD", GDM_WORKING_DIR, TRUE); + } + + return TRUE; +} + static GPtrArray * read_file_contents_to_array (const char *file_path, GError **error) @@ -1852,6 +1899,15 @@ handle_show (GdmConfigCommand config_command, removal_setting = get_smartcard_option (GSD_SC_REMOVAL_ACTION_KEY); + /* While this may be not super-needed it ensures that we act as if we + * were gdm itself */ + if (!g_getenv ("UNDER_JHBUILD") && !switch_to_gdm_user (&local_error)) { + g_critical ("Impossible to switch to GDM user %s: %s", + GDM_USERNAME, local_error->message); + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + g_print(_("GDM Authorization configuration\n" "\n" " Password authentication: %s\n"