From f12d17a6f4f76ba037e9126113684777a070a8f4 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 20 Aug 2018 14:30:59 -0400 Subject: [PATCH 3/4] daemon: save os-release in accountsservice It can be useful to know what OS a user was running when they logged in (to detect upgrades). This commit saves that information in accountsservice. --- daemon/Makefile.am | 10 ++ daemon/gdm-session-settings.c | 98 +++++++++++++++++++ data/Makefile.am | 2 + .../com.redhat.AccountsServiceUser.System.xml | 10 ++ 4 files changed, 120 insertions(+) create mode 100644 data/com.redhat.AccountsServiceUser.System.xml diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 3b1b15122..b77c9276e 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -14,137 +14,147 @@ AM_CPPFLAGS = \ -DLIBEXECDIR=\"$(libexecdir)\" \ -DLOCALSTATEDIR=\"$(localstatedir)\" \ -DLOGDIR=\"$(logdir)\" \ -DSBINDIR=\"$(sbindir)\" \ -DSYSCONFDIR=\"$(sysconfdir)\" \ -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ -DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \ -DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \ -DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \ -DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \ -DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \ $(DISABLE_DEPRECATED_CFLAGS) \ $(DAEMON_CFLAGS) \ $(XLIB_CFLAGS) \ $(WARN_CFLAGS) \ $(DEBUG_CFLAGS) \ $(SYSTEMD_CFLAGS) \ $(JOURNALD_CFLAGS) \ $(LIBSELINUX_CFLAGS) \ -DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \ $(NULL) BUILT_SOURCES = \ gdm-display-glue.h \ gdm-manager-glue.h \ gdm-local-display-glue.h \ gdm-local-display-factory-glue.h \ gdm-session-glue.h \ gdm-session-worker-glue.h \ gdm-session-enum-types.h \ + com.redhat.AccountsServiceUser.System.h \ $(NULL) gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h $(AM_V_GEN) glib-mkenums --template $^ > $@ gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h $(AM_V_GEN) glib-mkenums --template $^ > $@ gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-display-glue \ $(srcdir)/gdm-display.xml gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-local-display-glue \ $(srcdir)/gdm-local-display.xml gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-local-display-factory-glue \ $(srcdir)/gdm-local-display-factory.xml gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-manager-glue \ $(srcdir)/gdm-manager.xml gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-session-glue \ $(srcdir)/gdm-session.xml gdm-session-worker-glue.c gdm-session-worker-glue.h : gdm-session-worker.xml Makefile.am $(AM_V_GEN)gdbus-codegen \ --c-namespace=GdmDBus \ --interface-prefix=org.gnome.DisplayManager \ --generate-c-code=gdm-session-worker-glue \ $(srcdir)/gdm-session-worker.xml +com.redhat.AccountsServiceUser.System.c com.redhat.AccountsServiceUser.System.h: $(top_srcdir)/data/com.redhat.AccountsServiceUser.System.xml Makefile.am + $(AM_V_GEN)gdbus-codegen \ + --c-namespace=Gdm \ + --interface-prefix=com.redhat \ + --generate-c-code=com.redhat.AccountsServiceUser.System \ + $(top_srcdir)/data/com.redhat.AccountsServiceUser.System.xml + noinst_PROGRAMS = \ test-session-client \ $(NULL) test_session_client_SOURCES = \ test-session-client.c \ $(NULL) nodist_test_session_client_SOURCES = \ gdm-session-glue.h \ gdm-session-glue.c \ gdm-manager-glue.h \ gdm-manager-glue.c \ $(NULL) test_session_client_LDADD = \ $(DAEMON_LIBS) \ $(NULL) libexec_PROGRAMS = \ gdm-session-worker \ gdm-wayland-session \ gdm-x-session \ $(NULL) gdm_session_worker_SOURCES = \ session-worker-main.c \ + com.redhat.AccountsServiceUser.System.h \ + com.redhat.AccountsServiceUser.System.c \ gdm-session.c \ gdm-session.h \ gdm-session-settings.h \ gdm-session-settings.c \ gdm-session-auditor.h \ gdm-session-auditor.c \ gdm-session-record.c \ gdm-session-record.h \ gdm-session-worker.h \ gdm-session-worker.c \ gdm-session-worker-job.c \ gdm-session-worker-common.c \ gdm-session-worker-common.h \ gdm-dbus-util.c \ gdm-dbus-util.h \ $(NULL) if SUPPORTS_PAM_EXTENSIONS gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h endif nodist_gdm_session_worker_SOURCES = \ gdm-session-glue.h \ gdm-session-glue.c \ gdm-session-worker-glue.c \ gdm-session-worker-glue.h \ gdm-session-enum-types.c \ gdm-session-enum-types.h \ $(NULL) diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c index 8463fad32..921e4d501 100644 --- a/daemon/gdm-session-settings.c +++ b/daemon/gdm-session-settings.c @@ -1,70 +1,77 @@ /* gdm-session-settings.c - Loads session and language from ~/.dmrc * * Copyright (C) 2008 Red Hat, Inc. * * 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, 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. * * Written by: Ray Strode */ #include "config.h" #include "gdm-session-settings.h" +#include "gdm-common.h" + +#include "com.redhat.AccountsServiceUser.System.h" #include #include #include #include #include #include #include #include #include struct _GdmSessionSettingsPrivate { ActUserManager *user_manager; ActUser *user; + + /* used for retrieving the last OS user logged in with */ + GdmAccountsServiceUserSystem *user_system_proxy; + char *session_name; char *session_type; char *language_name; }; static void gdm_session_settings_finalize (GObject *object); static void gdm_session_settings_class_install_properties (GdmSessionSettingsClass * settings_class); static void gdm_session_settings_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void gdm_session_settings_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); enum { PROP_0 = 0, PROP_SESSION_NAME, PROP_SESSION_TYPE, PROP_LANGUAGE_NAME, PROP_IS_LOADED }; G_DEFINE_TYPE (GdmSessionSettings, gdm_session_settings, G_TYPE_OBJECT) static void gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class) @@ -107,60 +114,62 @@ gdm_session_settings_class_install_properties (GdmSessionSettingsClass *settings g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec); param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL, FALSE, G_PARAM_READABLE); g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec); } static void gdm_session_settings_init (GdmSessionSettings *settings) { settings->priv = G_TYPE_INSTANCE_GET_PRIVATE (settings, GDM_TYPE_SESSION_SETTINGS, GdmSessionSettingsPrivate); settings->priv->user_manager = act_user_manager_get_default (); } static void gdm_session_settings_finalize (GObject *object) { GdmSessionSettings *settings; GObjectClass *parent_class; settings = GDM_SESSION_SETTINGS (object); if (settings->priv->user != NULL) { g_object_unref (settings->priv->user); } + g_clear_object (&settings->priv->user_system_proxy); + g_free (settings->priv->session_name); g_free (settings->priv->language_name); parent_class = G_OBJECT_CLASS (gdm_session_settings_parent_class); if (parent_class->finalize != NULL) { parent_class->finalize (object); } } void gdm_session_settings_set_language_name (GdmSessionSettings *settings, const char *language_name) { g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings)); if (settings->priv->language_name == NULL || strcmp (settings->priv->language_name, language_name) != 0) { settings->priv->language_name = g_strdup (language_name); g_object_notify (G_OBJECT (settings), "language-name"); } } void gdm_session_settings_set_session_name (GdmSessionSettings *settings, const char *session_name) { g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings)); if (settings->priv->session_name == NULL || @@ -261,69 +270,86 @@ gdm_session_settings_get_property (GObject *object, default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } GdmSessionSettings * gdm_session_settings_new (void) { GdmSessionSettings *settings; settings = g_object_new (GDM_TYPE_SESSION_SETTINGS, NULL); return settings; } gboolean gdm_session_settings_is_loaded (GdmSessionSettings *settings) { if (settings->priv->user == NULL) { return FALSE; } return act_user_is_loaded (settings->priv->user); } static void load_settings_from_user (GdmSessionSettings *settings) { + const char *object_path; const char *session_name; const char *session_type; const char *language_name; if (!act_user_is_loaded (settings->priv->user)) { g_warning ("GdmSessionSettings: trying to load user settings from unloaded user"); return; } + object_path = act_user_get_object_path (settings->priv->user); + + if (object_path != NULL) { + g_autoptr (GError) error = NULL; + settings->priv->user_system_proxy = gdm_accounts_service_user_system_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + object_path, + NULL, + &error); + if (error != NULL) { + g_debug ("GdmSessionSettings: couldn't retrieve user system proxy from accountsservice: %s", + error->message); + } + } + /* if the user doesn't have saved state, they don't have any settings worth reading */ if (!act_user_get_saved (settings->priv->user)) goto out; session_type = act_user_get_session_type (settings->priv->user); session_name = act_user_get_session (settings->priv->user); g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type); if (session_type != NULL && session_type[0] != '\0') { gdm_session_settings_set_session_type (settings, session_type); } if (session_name != NULL && session_name[0] != '\0') { gdm_session_settings_set_session_name (settings, session_name); } language_name = act_user_get_language (settings->priv->user); g_debug ("GdmSessionSettings: saved language is %s", language_name); if (language_name != NULL && language_name[0] != '\0') { gdm_session_settings_set_language_name (settings, language_name); } out: g_object_notify (G_OBJECT (settings), "is-loaded"); } static void on_user_is_loaded_changed (ActUser *user, @@ -349,64 +375,136 @@ gdm_session_settings_load (GdmSessionSettings *settings, g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE); if (settings->priv->user != NULL) { old_user = settings->priv->user; g_signal_handlers_disconnect_by_func (G_OBJECT (settings->priv->user), G_CALLBACK (on_user_is_loaded_changed), settings); } else { old_user = NULL; } settings->priv->user = act_user_manager_get_user (settings->priv->user_manager, username); g_clear_object (&old_user); if (!act_user_is_loaded (settings->priv->user)) { g_signal_connect (settings->priv->user, "notify::is-loaded", G_CALLBACK (on_user_is_loaded_changed), settings); return FALSE; } load_settings_from_user (settings); return TRUE; } +static void +save_os_release (GdmSessionSettings *settings, + ActUser *user) +{ + g_autoptr(GFile) file = NULL; + g_autoptr(GError) error = NULL; + g_autofree char *contents = NULL; + g_auto(GStrv) lines = NULL; + size_t i; + + if (settings->priv->user_system_proxy == NULL) { + g_debug ("GdmSessionSettings: not saving OS version to user account because accountsservice doesn't support it"); + return; + } + + file = g_file_new_for_path ("/etc/os-release"); + + if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, &error)) { + g_debug ("GdmSessionSettings: couldn't load /etc/os-release: %s", error->message); + return; + } + + lines = g_strsplit (contents, "\n", -1); + for (i = 0; lines[i] != NULL; i++) { + char *p, *name, *name_end, *value, *value_end; + + p = lines[i]; + + while (g_ascii_isspace (*p)) + p++; + + if (*p == '#' || *p == '\0') + continue; + name = p; + while (gdm_shell_var_is_valid_char (*p, p == name)) + p++; + name_end = p; + while (g_ascii_isspace (*p)) + p++; + if (name == name_end || *p != '=') { + continue; + } + *name_end = '\0'; + + p++; + + while (g_ascii_isspace (*p)) + p++; + + value = p; + value_end = value + strlen(value) - 1; + + if (value != value_end && *value == '"' && *value_end == '"') { + value++; + *value_end = '\0'; + } + + if (strcmp (name, "ID") == 0) { + gdm_accounts_service_user_system_set_id (settings->priv->user_system_proxy, + value); + g_debug ("GdmSessionSettings: setting system OS for user to '%s'", value); + } else if (strcmp (name, "VERSION_ID") == 0) { + gdm_accounts_service_user_system_set_version_id (settings->priv->user_system_proxy, + value); + g_debug ("GdmSessionSettings: setting system OS version for user to '%s'", value); + } + } +} + gboolean gdm_session_settings_save (GdmSessionSettings *settings, const char *username) { ActUser *user; g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE); g_return_val_if_fail (username != NULL, FALSE); g_return_val_if_fail (gdm_session_settings_is_loaded (settings), FALSE); user = act_user_manager_get_user (settings->priv->user_manager, username); if (!act_user_is_loaded (user)) { g_object_unref (user); return FALSE; } if (settings->priv->session_name != NULL) { act_user_set_session (user, settings->priv->session_name); } if (settings->priv->session_type != NULL) { act_user_set_session_type (user, settings->priv->session_type); } if (settings->priv->language_name != NULL) { act_user_set_language (user, settings->priv->language_name); } + + save_os_release (settings, user); + g_object_unref (user); return TRUE; } diff --git a/data/Makefile.am b/data/Makefile.am index 192dfa052..d69021985 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -8,60 +8,62 @@ SUBDIRS = \ $(NULL) initdir = $(gdmconfdir)/Init postdir = $(gdmconfdir)/PostSession predir = $(gdmconfdir)/PreSession postlogindir = $(gdmconfdir)/PostLogin workingdir = $(GDM_WORKING_DIR) xauthdir = $(GDM_XAUTH_DIR) screenshotdir = $(GDM_SCREENSHOT_DIR) cachedir = $(localstatedir)/cache/gdm Init: $(srcdir)/Init.in sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ <$(srcdir)/Init.in >Init PreSession: $(srcdir)/PreSession.in sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ <$(srcdir)/PreSession.in >PreSession PostSession: $(srcdir)/PostSession.in sed -e 's,[@]X_PATH[@],$(X_PATH),g' \ <$(srcdir)/PostSession.in >PostSession gdm.conf-custom: $(srcdir)/gdm.conf-custom.in sed -e 's,[@]GDM_DEFAULTS_CONF[@],$(GDM_DEFAULTS_CONF),g' \ <$(srcdir)/gdm.conf-custom.in >gdm.conf-custom dbusconfdir = $(DBUS_SYS_DIR) dbusconf_in_files = gdm.conf.in dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf) +EXTRA_DIST += com.redhat.AccountsServiceUser.System.xml + @INTLTOOL_SCHEMAS_RULE@ @INTLTOOL_XML_NOMERGE_RULE@ # dconf database and profile dconf_db_files = \ dconf/defaults/00-upstream-settings \ dconf/defaults/locks/00-upstream-settings-locks dconfdbdir = $(pkgdatadir) dconfdb_DATA = greeter-dconf-defaults greeter-dconf-defaults: $(dconf_db_files) $(AM_V_GEN) dconf compile $@ $(srcdir)/dconf/defaults dconfprofiledir = $(DATADIR)/dconf/profile dconfprofile_DATA = dconf/gdm gsettings_SCHEMAS = org.gnome.login-screen.gschema.xml @GSETTINGS_RULES@ schemasdir = $(pkgdatadir) schemas_in_files = gdm.schemas.in schemas_DATA = $(schemas_in_files:.schemas.in=.schemas) gdm.schemas.in: $(srcdir)/gdm.schemas.in.in sed -e 's,[@]GDMPREFETCHCMD[@],$(GDMPREFETCHCMD),g' \ -e 's,[@]GDM_CUSTOM_CONF[@],$(GDM_CUSTOM_CONF),g' \ -e 's,[@]GDM_USER_PATH[@],$(GDM_USER_PATH),g' \ -e 's,[@]GDM_USERNAME[@],$(GDM_USERNAME),g' \ -e 's,[@]GDM_GROUPNAME[@],$(GDM_GROUPNAME),g' \ -e 's,[@]HALT_COMMAND[@],$(HALT_COMMAND),g' \ diff --git a/data/com.redhat.AccountsServiceUser.System.xml b/data/com.redhat.AccountsServiceUser.System.xml new file mode 100644 index 000000000..67f5f302c --- /dev/null +++ b/data/com.redhat.AccountsServiceUser.System.xml @@ -0,0 +1,10 @@ + + + + + + + + + + -- 2.17.1