diff --git a/SOURCES/0001-smartcard-Cancel-cancellable-when-stopping.patch b/SOURCES/0001-smartcard-Cancel-cancellable-when-stopping.patch index 4ddcdef..38c6a13 100644 --- a/SOURCES/0001-smartcard-Cancel-cancellable-when-stopping.patch +++ b/SOURCES/0001-smartcard-Cancel-cancellable-when-stopping.patch @@ -1,7 +1,7 @@ -From a1c2685bc6b255f22b6ce4645c001d428cb67907 Mon Sep 17 00:00:00 2001 +From b0fb67c05e19a1a8715c1045f02657055d9e2578 Mon Sep 17 00:00:00 2001 From: Marek Kasik Date: Wed, 22 May 2019 14:56:42 +0200 -Subject: [PATCH] smartcard: Cancel cancellable when stopping +Subject: [PATCH 1/4] smartcard: Cancel cancellable when stopping self->cancellable in GsdSmartcardManager is not cancelled at gsd_smartcard_manager_stop() and hence some callbacks are @@ -19,13 +19,40 @@ https://bugzilla.redhat.com/show_bug.cgi?id=1688791 and their duplicates for additional info. --- plugins/smartcard/gsd-smartcard-manager.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletion(-) + 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c -index 014c17be..da1e0d6d 100644 +index 94ffdd90..09ccecc0 100644 --- a/plugins/smartcard/gsd-smartcard-manager.c +++ b/plugins/smartcard/gsd-smartcard-manager.c -@@ -184,7 +184,7 @@ +@@ -157,71 +157,72 @@ unload_nss (GsdSmartcardManager *self) + if (self->priv->nss_context != NULL) { + g_clear_pointer (&self->priv->nss_context, + NSS_ShutdownContext); + g_debug ("NSS database '%s' unloaded", GSD_SMARTCARD_MANAGER_NSS_DB); + } else { + g_debug ("NSS database '%s' already not loaded", GSD_SMARTCARD_MANAGER_NSS_DB); + } + } + + typedef struct + { + SECMODModule *driver; + GHashTable *smartcards; + int number_of_consecutive_errors; + } WatchSmartcardsOperation; + + static void + on_watch_cancelled (GCancellable *cancellable, + WatchSmartcardsOperation *operation) + { + SECMOD_CancelWait (operation->driver); + } + + static gboolean + watch_one_event_from_driver (GsdSmartcardManager *self, + WatchSmartcardsOperation *operation, + GCancellable *cancellable, GError **error) { GsdSmartcardManagerPrivate *priv = self->priv; @@ -34,7 +61,9 @@ index 014c17be..da1e0d6d 100644 CK_SLOT_ID slot_id; gulong handler_id; int old_slot_series = -1, slot_series; -@@ -190,7 +190,8 @@ watch_one_event_from_driver (GsdSmartcardManager *self, + + handler_id = g_cancellable_connect (cancellable, + G_CALLBACK (on_watch_cancelled), operation, NULL); @@ -44,7 +73,61 @@ index 014c17be..da1e0d6d 100644 g_cancellable_disconnect (cancellable, handler_id); -@@ -773,6 +774,8 @@ gsd_smartcard_manager_stop (GsdSmartcardManager *self) + if (g_cancellable_set_error_if_cancelled (cancellable, error)) { + g_warning ("smartcard event function cancelled"); + return FALSE; + } + + if (card == NULL) { + int error_code; + + error_code = PORT_GetError (); + + operation->number_of_consecutive_errors++; + if (operation->number_of_consecutive_errors > 10) { + g_warning ("Got %d consecutive smartcard errors, so giving up.", + operation->number_of_consecutive_errors); + + g_set_error (error, + GSD_SMARTCARD_MANAGER_ERROR, + GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, + "encountered unexpected error while " + "waiting for smartcard events (error %x)", + error_code); + return FALSE; + } + + g_warning ("Got potentially spurious smartcard event error: %x.", error_code); + + g_usleep (0.5 * G_USEC_PER_SEC); +@@ -764,60 +765,62 @@ gsd_smartcard_manager_idle_cb (GsdSmartcardManager *self) + + gnome_settings_profile_end (NULL); + + priv->start_idle_id = 0; + return FALSE; + } + + gboolean + gsd_smartcard_manager_start (GsdSmartcardManager *self, + GError **error) + { + GsdSmartcardManagerPrivate *priv = self->priv; + + gnome_settings_profile_start (NULL); + + priv->start_idle_id = g_idle_add ((GSourceFunc) gsd_smartcard_manager_idle_cb, self); + g_source_set_name_by_id (priv->start_idle_id, "[gnome-settings-daemon] gsd_smartcard_manager_idle_cb"); + + gnome_settings_profile_end (NULL); + + return TRUE; + } + + void + gsd_smartcard_manager_stop (GsdSmartcardManager *self) + { + GsdSmartcardManagerPrivate *priv = self->priv; g_debug ("Stopping smartcard manager"); @@ -53,6 +136,33 @@ index 014c17be..da1e0d6d 100644 unload_nss (self); g_clear_object (&priv->settings); + g_clear_object (&priv->cancellable); + g_clear_object (&priv->session_manager); + g_clear_object (&priv->screen_saver); + } + + static void + on_screen_locked (GsdScreenSaver *screen_saver, + GAsyncResult *result, + GsdSmartcardManager *self) + { + gboolean is_locked; + GError *error = NULL; + + is_locked = gsd_screen_saver_call_lock_finish (screen_saver, result, &error); + + if (!is_locked) { + g_warning ("Couldn't lock screen: %s", error->message); + g_error_free (error); + return; + } + } + + static void + lock_screen (GsdSmartcardManager *self) + { + GsdSmartcardManagerPrivate *priv = self->priv; + -- -2.23.0 +2.39.2 diff --git a/SOURCES/0001-subman-Add-a-new-plugin-to-provide-system-subscripti.patch b/SOURCES/0001-subman-Add-a-new-plugin-to-provide-system-subscripti.patch deleted file mode 100644 index bc13b55..0000000 --- a/SOURCES/0001-subman-Add-a-new-plugin-to-provide-system-subscripti.patch +++ /dev/null @@ -1,1871 +0,0 @@ -From bee6d42503ec9b56f6e10704db02bcedb6a4fdf1 Mon Sep 17 00:00:00 2001 -From: Richard Hughes -Date: Thu, 20 Aug 2020 11:16:09 -0400 -Subject: [PATCH 01/15] subman: Add a new plugin to provide system subscription - registration - ---- - meson.build | 1 + - plugins/meson.build | 1 + - plugins/subman/README.md | 56 + - plugins/subman/gsd-subman-common.c | 36 + - plugins/subman/gsd-subman-common.h | 40 + - plugins/subman/gsd-subman-helper.c | 378 +++++++ - plugins/subman/gsd-subscription-manager.c | 982 ++++++++++++++++++ - plugins/subman/gsd-subscription-manager.h | 63 ++ - plugins/subman/main.c | 8 + - plugins/subman/meson.build | 56 + - ...ome.SettingsDaemon.Subscription.desktop.in | 9 + - ...ettings-daemon.plugins.subman.policy.in.in | 27 + - ...gnome.settings-daemon.plugins.subman.rules | 7 + - 13 files changed, 1664 insertions(+) - create mode 100644 plugins/subman/README.md - create mode 100644 plugins/subman/gsd-subman-common.c - create mode 100644 plugins/subman/gsd-subman-common.h - create mode 100644 plugins/subman/gsd-subman-helper.c - create mode 100644 plugins/subman/gsd-subscription-manager.c - create mode 100644 plugins/subman/gsd-subscription-manager.h - create mode 100644 plugins/subman/main.c - create mode 100644 plugins/subman/meson.build - create mode 100644 plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in - create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in - create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.rules - -diff --git a/meson.build b/meson.build -index 1632ea05..27bf8c4c 100644 ---- a/meson.build -+++ b/meson.build -@@ -70,60 +70,61 @@ if gsd_buildtype.contains('debug') - ] - - compiler_flags = cc.get_supported_arguments(test_cflags) - elif gsd_buildtype.contains('release') - common_flags += ['-DG_DISABLE_CAST_CHECKS'] - endif - - # Workaround for meson's bug - # https://github.com/mesonbuild/meson/pull/1896 - if get_option('b_ndebug') == true - common_flags += ['-DG_DISABLE_ASSERT'] - endif - - add_project_arguments(common_flags + compiler_flags, language: 'c') - - glib_dep = dependency('glib-2.0', version: '>= 2.56') - colord_dep = dependency('colord', version: '>= 1.0.2') - geocode_glib_dep = dependency('geocode-glib-1.0', version: '>= 3.10.0') - gio_dep = dependency('gio-2.0', version: '>= 2.53.0') - gio_unix_dep = dependency('gio-unix-2.0') - gnome_desktop_dep = dependency('gnome-desktop-3.0', version: '>= 3.11.1') - gsettings_desktop_dep = dependency('gsettings-desktop-schemas', version: '>= 3.27.90') - gtk_dep = dependency('gtk+-3.0', version: '>= 3.15.3') - gtk_x11_dep = dependency('gtk+-x11-3.0') - gweather_dep = dependency('gweather-3.0', version: '>= 3.9.5') - lcms_dep = dependency('lcms2', version: '>= 2.2') - libcanberra_gtk_dep = dependency('libcanberra-gtk3') - libgeoclue_dep = dependency('libgeoclue-2.0', version: '>= 2.3.1') - libnotify_dep = dependency('libnotify', version: '>= 0.7.3') - libpulse_mainloop_glib_dep = dependency('libpulse-mainloop-glib', version: '>= 2.0') -+jsonglib_dep = dependency('json-glib-1.0', version: '>= 1.1.1') - pango_dep = dependency('pango', version: '>= 1.20.0') - polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.103') - upower_glib_dep = dependency('upower-glib', version: '>= 0.99.0') - x11_dep = dependency('x11') - - m_dep = cc.find_library('m') - dl_dep = cc.find_library('dl') - - # ALSA integration (default enabled) - enable_alsa = get_option('alsa') - assert(enable_alsa or not host_is_linux, 'ALSA is not optional on Linux platforms') - - libgvc = subproject( - 'gvc', - default_options: [ - 'static=true', - 'alsa=' + enable_alsa.to_string() - ] - ) - libgvc_dep = libgvc.get_variable('libgvc_dep') - - # GUdev integration (default enabled) - enable_gudev = get_option('gudev') - if enable_gudev - gudev_dep = dependency('gudev-1.0') - endif - config_h.set10('HAVE_GUDEV', enable_gudev) - if host_is_linux - assert(enable_gudev, 'GUdev is not optional on Linux platforms') - endif -diff --git a/plugins/meson.build b/plugins/meson.build -index 3c4d42ac..4c9caf47 100644 ---- a/plugins/meson.build -+++ b/plugins/meson.build -@@ -1,35 +1,36 @@ - enabled_plugins = [ - ['a11y-settings', 'A11ySettings'], - ['account', 'Account'], - ['clipboard', 'Clipboard'], - ['color', 'Color'], -+ ['subman', 'Subscription'], - ['datetime', 'Datetime'], - ['dummy', ''], - ['power', 'Power'], - ['housekeeping', 'Housekeeping'], - ['keyboard', 'Keyboard'], - ['media-keys', 'MediaKeys'], - ['mouse', 'Mouse'], - ['screensaver-proxy', 'ScreensaverProxy'], - ['sharing', 'Sharing'], - ['sound', 'Sound'], - ['xsettings', 'XSettings'] - ] - - if enable_smartcard - enabled_plugins += [['smartcard', 'Smartcard']] - endif - - if enable_wacom - enabled_plugins += [['wacom', 'Wacom']] - endif - - if enable_cups - enabled_plugins += [['print-notifications', 'PrintNotifications']] - endif - - if enable_rfkill - enabled_plugins += [['rfkill', 'Rfkill']] - endif - - plugins_conf = configuration_data() -diff --git a/plugins/subman/README.md b/plugins/subman/README.md -new file mode 100644 -index 00000000..3e1cc3cd ---- /dev/null -+++ b/plugins/subman/README.md -@@ -0,0 +1,56 @@ -+GNOME Settings Daemon: Subscription Manager Plugin -+================================================== -+ -+Testing: -+ -+To add a test acccount on subscription.rhsm.stage.redhat.com, use Ethel: -+http://account-manager-stage.app.eng.rdu2.redhat.com/#view -+ -+Register with a username and password -+------------------------------------- -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'username'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'username':<'rhughes_test'>,'password':<'barbaz'>}" -+ -+To register with a certificate -+------------------------------ -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'key'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'organisation':<'foo'>,'activation-key':<'barbaz'>}" -+ -+To unregister -+------------- -+ -+ gdbus call \ -+ --session \ -+ --dest org.gnome.SettingsDaemon.Subscription \ -+ --object-path /org/gnome/SettingsDaemon/Subscription \ -+ --method org.gnome.SettingsDaemon.Subscription.Unregister -+ -+Debugging -+--------- -+ -+Get the UNIX socket using `Subscription.Register` then call something like: -+ -+ sudo G_MESSAGES_DEBUG=all ./plugins/subman/gsd-subman-helper \ -+ --address="unix:abstract=/var/run/dbus-ulGB1wfnbn,guid=71e6bf329d861ce366df7a1d5d036a5b" \ -+ --kind="register-with-username" \ -+ --username="rhughes_test" \ -+ --password="barbaz" \ -+ --hostname="subscription.rhsm.stage.redhat.com" \ -+ --organisation="" -+ -+You can all see some basic debugging running `rhsmd` in the foreground: -+ -+ sudo /usr/libexec/rhsmd -d -k -+ -+Known Limitations -+================= -+ -+Proxy servers are not supported, nor are custom host ports or prefixes. -diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c -new file mode 100644 -index 00000000..e515131e ---- /dev/null -+++ b/plugins/subman/gsd-subman-common.c -@@ -0,0 +1,36 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * 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, see . -+ * -+ */ -+ -+#include "config.h" -+ -+#include "gsd-subman-common.h" -+ -+const gchar * -+gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) -+{ -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID) -+ return "valid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) -+ return "invalid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) -+ return "disabled"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) -+ return "partially-valid"; -+ return "unknown"; -+} -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -new file mode 100644 -index 00000000..fccf9f6a ---- /dev/null -+++ b/plugins/subman/gsd-subman-common.h -@@ -0,0 +1,40 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * 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, see . -+ * -+ */ -+ -+#ifndef __GSD_SUBMAN_COMMON_H -+#define __GSD_SUBMAN_COMMON_H -+ -+#include -+ -+G_BEGIN_DECLS -+ -+typedef enum { -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST -+} GsdSubmanSubscriptionStatus; -+ -+const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); -+ -+G_END_DECLS -+ -+#endif /* __GSD_SUBMAN_COMMON_H */ -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -new file mode 100644 -index 00000000..182f7190 ---- /dev/null -+++ b/plugins/subman/gsd-subman-helper.c -@@ -0,0 +1,378 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * Licensed under the GNU General Public License Version 2 -+ * -+ * 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. -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+static void -+_helper_convert_error (const gchar *json_txt, GError **error) -+{ -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *message; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ /* this may be plain text or JSON :| */ -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ json_txt); -+ return; -+ } -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "message")) { -+ g_set_error (error, -+ G_IO_ERROR, -+ G_IO_ERROR_INVALID_DATA, -+ "no message' in %s", json_txt); -+ return; -+ } -+ message = json_object_get_string_member (json_obj, "message"); -+ if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_PERMISSION_DENIED, -+ message); -+ return; -+ } -+ g_set_error_literal (error, -+ G_IO_ERROR, -+ G_IO_ERROR_NOT_SUPPORTED, -+ message); -+} -+ -+static gboolean -+_helper_unregister (GError **error) -+{ -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("unregistering"); -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Unregister", -+ "com.redhat.RHSM1.Unregister", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); -+ res = g_dbus_proxy_call_sync (proxy, -+ "Unregister", -+ g_variant_new ("(a{sv}s)", -+ proxy_options, -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ return res != NULL; -+} -+ -+static gboolean -+_helper_auto_attach (GError **error) -+{ -+ const gchar *str = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("auto-attaching subscriptions"); -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Attach", -+ "com.redhat.RHSM1.Attach", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); -+ res = g_dbus_proxy_call_sync (proxy, -+ "AutoAttach", -+ g_variant_new ("(sa{sv}s)", -+ "", /* now? */ -+ proxy_options, -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (res == NULL) -+ return FALSE; -+ g_variant_get (res, "(&s)", &str); -+ g_debug ("Attach.AutoAttach: %s", str); -+ return TRUE; -+} -+ -+static gboolean -+_helper_save_config (const gchar *key, const gchar *value, GError **error) -+{ -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) res = NULL; -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | -+ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/Config", -+ "com.redhat.RHSM1.Config", -+ NULL, error); -+ if (proxy == NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ res = g_dbus_proxy_call_sync (proxy, "Set", -+ g_variant_new ("(svs)", -+ key, -+ g_variant_new_string (value), -+ ""), /* lang */ -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ return res != NULL; -+} -+ -+int -+main (int argc, char *argv[]) -+{ -+ const gchar *userlang = ""; /* as root, so no translations */ -+ g_autofree gchar *activation_key = NULL; -+ g_autofree gchar *address = NULL; -+ g_autofree gchar *hostname = NULL; -+ g_autofree gchar *kind = NULL; -+ g_autofree gchar *organisation = NULL; -+ g_autofree gchar *password = NULL; -+ g_autofree gchar *port = NULL; -+ g_autofree gchar *prefix = NULL; -+ g_autofree gchar *proxy_server = NULL; -+ g_autofree gchar *username = NULL; -+ g_autoptr(GDBusConnection) conn_private = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GError) error = NULL; -+ g_autoptr(GOptionContext) context = g_option_context_new (NULL); -+ g_autoptr(GVariantBuilder) proxy_options = NULL; -+ g_autoptr(GVariantBuilder) subman_conopts = NULL; -+ g_autoptr(GVariantBuilder) subman_options = NULL; -+ -+ const GOptionEntry options[] = { -+ { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &kind, "Kind, e.g. 'username' or 'key'", NULL }, -+ { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &address, "UNIX address", NULL }, -+ { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &username, "Username", NULL }, -+ { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &password, "Password", NULL }, -+ { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &organisation, "Organisation", NULL }, -+ { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -+ &activation_key, "Activation keys", NULL }, -+ { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &hostname, "Registration server hostname", NULL }, -+ { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &prefix, "Registration server prefix", NULL }, -+ { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &port, "Registration server port", NULL }, -+ { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, -+ &proxy_server, "Proxy settings", NULL }, -+ { NULL} -+ }; -+ -+ /* check calling UID */ -+ if (getuid () != 0 || geteuid () != 0) { -+ g_printerr ("This program can only be used by the root user\n"); -+ return G_IO_ERROR_NOT_SUPPORTED; -+ } -+ g_option_context_add_main_entries (context, options, NULL); -+ if (!g_option_context_parse (context, &argc, &argv, &error)) { -+ g_printerr ("Failed to parse arguments: %s\n", error->message); -+ return G_IO_ERROR_NOT_SUPPORTED; -+ } -+ -+ /* uncommon actions */ -+ if (kind == NULL) { -+ g_printerr ("No --kind specified\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (g_strcmp0 (kind, "unregister") == 0) { -+ if (!_helper_unregister (&error)) { -+ g_printerr ("Failed to Unregister: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ return EXIT_SUCCESS; -+ } -+ if (g_strcmp0 (kind, "auto-attach") == 0) { -+ if (!_helper_auto_attach (&error)) { -+ g_printerr ("Failed to AutoAttach: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ return EXIT_SUCCESS; -+ } -+ -+ /* connect to abstract socket for reasons */ -+ if (address == NULL) { -+ g_printerr ("No --address specified\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ conn_private = g_dbus_connection_new_for_address_sync (address, -+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, -+ NULL, NULL, -+ &error); -+ if (conn_private == NULL) { -+ g_printerr ("Invalid --address specified: %s\n", error->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ proxy = g_dbus_proxy_new_sync (conn_private, -+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, -+ NULL, /* GDBusInterfaceInfo */ -+ NULL, /* name */ -+ "/com/redhat/RHSM1/Register", -+ "com.redhat.RHSM1.Register", -+ NULL, &error); -+ if (proxy == NULL) { -+ g_printerr ("Count not contact RHSM: %s\n", error->message); -+ return G_IO_ERROR_NOT_FOUND; -+ } -+ -+ /* no options */ -+ subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); -+ -+ /* set registration server */ -+ if (hostname == NULL || hostname[0] == '\0') -+ hostname = g_strdup ("subscription.rhsm.redhat.com"); -+ if (prefix == NULL || prefix[0] == '\0') -+ prefix = g_strdup ("/subscription"); -+ if (port == NULL || port[0] == '\0') -+ port = g_strdup ("443"); -+ subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); -+ g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); -+ g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); -+ g_variant_builder_add (subman_conopts, "{ss}", "port", port); -+ -+ /* call into RHSM */ -+ if (g_strcmp0 (kind, "register-with-key") == 0) { -+ g_auto(GStrv) activation_keys = NULL; -+ g_autoptr(GError) error_local = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ if (activation_key == NULL) { -+ g_printerr ("Required --activation-key\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (organisation == NULL) { -+ g_printerr ("Required --organisation\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ -+ g_debug ("registering using activation key"); -+ activation_keys = g_strsplit (activation_key, ",", -1); -+ res = g_dbus_proxy_call_sync (proxy, -+ "RegisterWithActivationKeys", -+ g_variant_new ("(s^asa{ss}a{ss}s)", -+ organisation, -+ activation_keys, -+ subman_options, -+ subman_conopts, -+ userlang), -+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -+ -1, NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, &error); -+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -+ return error->code; -+ } -+ } else if (g_strcmp0 (kind, "register-with-username") == 0) { -+ g_autoptr(GError) error_local = NULL; -+ g_autoptr(GVariant) res = NULL; -+ -+ g_debug ("registering using username and password"); -+ if (username == NULL) { -+ g_printerr ("Required --username\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (password == NULL) { -+ g_printerr ("Required --password\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ if (organisation == NULL) { -+ g_printerr ("Required --organisation\n"); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ res = g_dbus_proxy_call_sync (proxy, -+ "Register", -+ g_variant_new ("(sssa{ss}a{ss}s)", -+ organisation, -+ username, -+ password, -+ subman_options, -+ subman_conopts, -+ userlang), -+ G_DBUS_CALL_FLAGS_NO_AUTO_START, -+ -1, NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, &error); -+ g_printerr ("Failed to Register: %s\n", error->message); -+ return error->code; -+ } -+ } else { -+ g_printerr ("Invalid --kind specified: %s\n", kind); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ -+ /* set the new hostname */ -+ if (!_helper_save_config ("server.hostname", hostname, &error)) { -+ g_printerr ("Failed to save hostname: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ if (!_helper_save_config ("server.prefix", prefix, &error)) { -+ g_printerr ("Failed to save prefix: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ if (!_helper_save_config ("server.port", port, &error)) { -+ g_printerr ("Failed to save port: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ -+ /* wait for rhsmd to notice the new config */ -+ g_usleep (G_USEC_PER_SEC * 5); -+ -+ /* auto-attach */ -+ if (!_helper_auto_attach (&error)) { -+ g_printerr ("Failed to AutoAttach: %s\n", error->message); -+ return G_IO_ERROR_NOT_INITIALIZED; -+ } -+ -+ return EXIT_SUCCESS; -+} -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -new file mode 100644 -index 00000000..08b13fa6 ---- /dev/null -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -0,0 +1,982 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * 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, see . -+ * -+ */ -+ -+#include "config.h" -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "gnome-settings-profile.h" -+#include "gsd-subman-common.h" -+#include "gsd-subscription-manager.h" -+ -+#define GSD_DBUS_NAME "org.gnome.SettingsDaemon" -+#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" -+#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" -+ -+#define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" -+#define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" -+#define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" -+ -+static const gchar introspection_xml[] = -+"" -+" " -+" " -+" " -+" " -+" " -+" " -+" " -+""; -+ -+#define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) -+ -+typedef enum { -+ _RHSM_INTERFACE_CONFIG, -+ _RHSM_INTERFACE_REGISTER_SERVER, -+ _RHSM_INTERFACE_ATTACH, -+ _RHSM_INTERFACE_ENTITLEMENT, -+ _RHSM_INTERFACE_PRODUCTS, -+ _RHSM_INTERFACE_CONSUMER, -+ _RHSM_INTERFACE_SYSPURPOSE, -+ _RHSM_INTERFACE_LAST -+} _RhsmInterface; -+ -+struct GsdSubscriptionManagerPrivate -+{ -+ /* D-Bus */ -+ guint name_id; -+ GDBusNodeInfo *introspection_data; -+ GDBusConnection *connection; -+ GCancellable *bus_cancellable; -+ -+ GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; -+ const gchar *userlang; /* owned by GLib internally */ -+ GHashTable *config; /* str:str */ -+ gchar *address; -+ -+ GTimer *timer_last_notified; -+ NotifyNotification *notification_expired; -+ NotifyNotification *notification_registered; -+ NotifyNotification *notification_registration_required; -+ GsdSubmanSubscriptionStatus subscription_status; -+ GsdSubmanSubscriptionStatus subscription_status_last; -+}; -+ -+enum { -+ PROP_0, -+}; -+ -+static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); -+static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); -+static void gsd_subscription_manager_finalize (GObject *object); -+ -+G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) -+ -+static gpointer manager_object = NULL; -+ -+GQuark -+gsd_subscription_manager_error_quark (void) -+{ -+ static GQuark quark = 0; -+ if (!quark) -+ quark = g_quark_from_static_string ("gsd_subscription_manager_error"); -+ return quark; -+} -+ -+static GsdSubmanSubscriptionStatus -+_client_subscription_status_from_text (const gchar *status_txt) -+{ -+ if (g_strcmp0 (status_txt, "Unknown") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ if (g_strcmp0 (status_txt, "Current") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -+ if (g_strcmp0 (status_txt, "Invalid") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ if (g_strcmp0 (status_txt, "Disabled") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -+ if (g_strcmp0 (status_txt, "Insufficient") == 0) -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -+ g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? -+ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+} -+ -+static void -+_emit_property_changed (GsdSubscriptionManager *manager, -+ const gchar *property_name, -+ GVariant *property_value) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ GVariantBuilder builder; -+ GVariantBuilder invalidated_builder; -+ -+ /* not yet connected */ -+ if (priv->connection == NULL) -+ return; -+ -+ /* build the dict */ -+ g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); -+ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); -+ g_variant_builder_add (&builder, -+ "{sv}", -+ property_name, -+ property_value); -+ g_dbus_connection_emit_signal (priv->connection, -+ NULL, -+ GSD_SUBSCRIPTION_DBUS_PATH, -+ "org.freedesktop.DBus.Properties", -+ "PropertiesChanged", -+ g_variant_new ("(sa{sv}as)", -+ GSD_SUBSCRIPTION_DBUS_INTERFACE, -+ &builder, -+ &invalidated_builder), -+ NULL); -+ g_variant_builder_clear (&builder); -+ g_variant_builder_clear (&invalidated_builder); -+} -+ -+static gboolean -+_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *json_txt = NULL; -+ const gchar *status_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ /* save old value */ -+ priv->subscription_status_last = priv->subscription_status; -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -+ "GetStatus", -+ g_variant_new ("(ss)", -+ "", /* assumed as 'now' */ -+ priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Entitlement.GetStatus JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "status")) { -+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -+ "no Entitlement.GetStatus status in %s", json_txt); -+ return FALSE; -+ } -+ -+ status_txt = json_object_get_string_member (json_obj, "status"); -+ g_debug ("Entitlement.GetStatus: %s", status_txt); -+ priv->subscription_status = _client_subscription_status_from_text (status_txt); -+ -+ /* emit notification for g-c-c */ -+ if (priv->subscription_status != priv->subscription_status_last) { -+ _emit_property_changed (manager, "SubscriptionStatus", -+ g_variant_new_uint32 (priv->subscription_status)); -+ } -+ -+ return TRUE; -+} -+ -+static gboolean -+_client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonObject *json_obj; -+ const gchar *json_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], -+ "GetSyspurpose", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_obj = json_node_get_object (json_root); -+ if (!json_object_has_member (json_obj, "status")) { -+ g_debug ("Syspurpose.GetSyspurpose: Unknown"); -+ return TRUE; -+ } -+ g_debug ("Syspurpose.GetSyspurpose: '%s", json_object_get_string_member (json_obj, "status")); -+ return TRUE; -+} -+ -+static gboolean -+_client_register_start (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ const gchar *address = NULL; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) val = NULL; -+ -+ /* already started */ -+ if (priv->address != NULL) -+ return TRUE; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/RegisterServer", -+ "com.redhat.RHSM1.RegisterServer", -+ NULL, error); -+ if (proxy == NULL) -+ return FALSE; -+ val = g_dbus_proxy_call_sync (proxy, "Start", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &address); -+ g_debug ("RegisterServer.Start: %s", address); -+ priv->address = g_strdup (address); -+ return TRUE; -+} -+ -+static gboolean -+_client_register_stop (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GDBusProxy) proxy = NULL; -+ g_autoptr(GVariant) val = NULL; -+ -+ /* already started */ -+ if (priv->address == NULL) -+ return TRUE; -+ -+ /* stop registration server */ -+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ "/com/redhat/RHSM1/RegisterServer", -+ "com.redhat.RHSM1.RegisterServer", -+ NULL, error); -+ if (proxy == NULL) -+ return FALSE; -+ val = g_dbus_proxy_call_sync (proxy, "Stop", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_clear_pointer (&priv->address, g_free); -+ return TRUE; -+} -+ -+static gboolean -+_client_subprocess_wait_check (GSubprocess *subprocess, GError **error) -+{ -+ gint rc; -+ if (!g_subprocess_wait (subprocess, NULL, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); -+ return FALSE; -+ } -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ GInputStream *istream = g_subprocess_get_stderr_pipe (subprocess); -+ gchar buf[1024] = { 0x0 }; -+ gsize sz = 0; -+ g_input_stream_read_all (istream, buf, sizeof(buf) - 1, &sz, NULL, NULL); -+ if (sz == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ g_set_error_literal (error, G_IO_ERROR, rc, buf); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+typedef enum { -+ _NOTIFY_EXPIRED, -+ _NOTIFY_REGISTRATION_REQUIRED, -+ _NOTIFY_REGISTERED -+} _NotifyKind; -+ -+static void -+_show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ switch (notify_kind) { -+ case _NOTIFY_EXPIRED: -+ notify_notification_close (priv->notification_registered, NULL); -+ notify_notification_close (priv->notification_registration_required, NULL); -+ notify_notification_show (priv->notification_expired, NULL); -+ break; -+ case _NOTIFY_REGISTRATION_REQUIRED: -+ notify_notification_close (priv->notification_registered, NULL); -+ notify_notification_close (priv->notification_expired, NULL); -+ notify_notification_show (priv->notification_registration_required, NULL); -+ break; -+ case _NOTIFY_REGISTERED: -+ notify_notification_close (priv->notification_expired, NULL); -+ notify_notification_close (priv->notification_registration_required, NULL); -+ notify_notification_show (priv->notification_registered, NULL); -+ break; -+ default: -+ break; -+ } -+ g_timer_reset (priv->timer_last_notified); -+} -+ -+static void -+_client_maybe__show_notification (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ /* startup */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* something changed */ -+ if (priv->subscription_status_last != priv->subscription_status) { -+ g_debug ("transisition from subscription status '%s' to '%s'", -+ gsd_subman_subscription_status_to_string (priv->subscription_status_last), -+ gsd_subman_subscription_status_to_string (priv->subscription_status)); -+ -+ /* needs registration */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* was unregistered */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ -+ /* registered */ -+ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ } -+ -+ /* nag again */ -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ return; -+ } -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_EXPIRED); -+ return; -+ } -+ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && -+ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -+ _show_notification (manager, _NOTIFY_EXPIRED); -+ return; -+ } -+} -+ -+static gboolean -+_client_register_with_keys (GsdSubscriptionManager *manager, -+ const gchar *hostname, -+ const gchar *organisation, -+ const gchar *activation_key, -+ GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "register-with-key", -+ "--address", priv->address, -+ "--hostname", hostname, -+ "--organisation", organisation, -+ "--activation-key", activation_key, -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ -+ /* FIXME: also do on error? */ -+ if (!_client_register_stop (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ -+ /* success */ -+ return TRUE; -+} -+ -+static gboolean -+_client_register (GsdSubscriptionManager *manager, -+ const gchar *hostname, -+ const gchar *organisation, -+ const gchar *username, -+ const gchar *password, -+ GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* fallback */ -+ if (organisation == NULL) -+ organisation = ""; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "register-with-username", -+ "--address", priv->address, -+ "--hostname", hostname, -+ "--organisation", organisation, -+ "--username", username, -+ "--password", password, -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ -+ /* FIXME: also do on error? */ -+ if (!_client_register_stop (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ -+static gboolean -+_client_unregister (GsdSubscriptionManager *manager, GError **error) -+{ -+ g_autoptr(GSubprocess) subprocess = NULL; -+ -+ /* apparently: "we can't send registration credentials over the regular -+ * system or session bus since those aren't really locked down..." */ -+ if (!_client_register_start (manager, error)) -+ return FALSE; -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "unregister", -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ if (!_client_subprocess_wait_check (subprocess, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ -+static gboolean -+_client_update_config (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(GVariant) val_server = NULL; -+ g_autoptr(GVariantDict) dict = NULL; -+ GVariantIter iter; -+ gchar *key; -+ gchar *value; -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], -+ "GetAll", -+ g_variant_new ("(s)", priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); -+ val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); -+ if (val_server != NULL) { -+ g_variant_iter_init (&iter, val_server); -+ while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { -+ g_debug ("%s=%s", key, value); -+ g_hash_table_insert (priv->config, -+ g_steal_pointer (&key), -+ g_steal_pointer (&value)); -+ } -+ } -+ return TRUE; -+} -+ -+static void -+_subman_proxy_signal_cb (GDBusProxy *proxy, -+ const gchar *sender_name, -+ const gchar *signal_name, -+ GVariant *parameters, -+ GsdSubscriptionManager *manager) -+{ -+ g_autoptr(GError) error = NULL; -+ if (!_client_syspurpose_update (manager, &error)) { -+ g_warning ("failed to update syspurpose: %s", error->message); -+ g_clear_error (&error); -+ } -+ if (!_client_subscription_status_update (manager, &error)) { -+ g_warning ("failed to update subscription status: %s", error->message); -+ g_clear_error (&error); -+ } -+ _client_maybe__show_notification (manager); -+} -+ -+static void -+_client_unload (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) -+ g_clear_object (&priv->proxies[i]); -+ g_hash_table_unref (priv->config); -+} -+ -+static const gchar * -+_rhsm_interface_to_string (_RhsmInterface kind) -+{ -+ if (kind == _RHSM_INTERFACE_CONFIG) -+ return "Config"; -+ if (kind == _RHSM_INTERFACE_REGISTER_SERVER) -+ return "RegisterServer"; -+ if (kind == _RHSM_INTERFACE_ATTACH) -+ return "Attach"; -+ if (kind == _RHSM_INTERFACE_ENTITLEMENT) -+ return "Entitlement"; -+ if (kind == _RHSM_INTERFACE_PRODUCTS) -+ return "Products"; -+ if (kind == _RHSM_INTERFACE_CONSUMER) -+ return "Consumer"; -+ if (kind == _RHSM_INTERFACE_SYSPURPOSE) -+ return "Syspurpose"; -+ return NULL; -+} -+ -+static gboolean -+_client_load (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); -+ -+ /* connect to all the interfaces on the *different* objects :| */ -+ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { -+ const gchar *kind = _rhsm_interface_to_string (i); -+ g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); -+ g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); -+ priv->proxies[i] = -+ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, -+ G_DBUS_PROXY_FLAGS_NONE, -+ NULL, -+ "com.redhat.RHSM1", -+ opath, iface, -+ NULL, -+ error); -+ if (priv->proxies[i] == NULL) -+ return FALSE; -+ /* we want to get notified if the status of the system changes */ -+ g_signal_connect (priv->proxies[i], "g-signal", -+ G_CALLBACK (_subman_proxy_signal_cb), manager); -+ } -+ -+ /* get initial status */ -+ priv->userlang = ""; -+ if (!_client_update_config (manager, error)) -+ return FALSE; -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ if (!_client_syspurpose_update (manager, error)) -+ return FALSE; -+ -+ /* success */ -+ return TRUE; -+} -+ -+gboolean -+gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) -+{ -+ gboolean ret; -+ g_debug ("Starting subscription manager"); -+ gnome_settings_profile_start (NULL); -+ ret = _client_load (manager, error); -+ _client_maybe__show_notification (manager); -+ gnome_settings_profile_end (NULL); -+ return ret; -+} -+ -+void -+gsd_subscription_manager_stop (GsdSubscriptionManager *manager) -+{ -+ g_debug ("Stopping subscription manager"); -+ _client_unload (manager); -+} -+ -+static void -+gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) -+{ -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); -+ object_class->finalize = gsd_subscription_manager_finalize; -+ notify_init ("gnome-settings-daemon"); -+ g_type_class_add_private (klass, sizeof (GsdSubscriptionManagerPrivate)); -+} -+ -+static void -+_launch_info_overview (void) -+{ -+ const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; -+ g_debug ("Running gnome-control-center info-overview"); -+ g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, -+ NULL, NULL, NULL, NULL); -+} -+ -+static void -+_notify_closed_cb (NotifyNotification *notification, gpointer user_data) -+{ -+ /* FIXME: only launch when clicking on the main body, not the window close */ -+ if (notify_notification_get_closed_reason (notification) == 0x400) -+ _launch_info_overview (); -+} -+ -+static void -+_notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) -+{ -+ _launch_info_overview (); -+} -+ -+static void -+gsd_subscription_manager_init (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); -+ -+ priv->timer_last_notified = g_timer_new (); -+ -+ /* expired */ -+ priv->notification_expired = -+ notify_notification_new (_("Subscription Has Expired"), -+ _("Add or renew a subscription to continue receiving software updates."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_expired, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); -+ notify_notification_add_action (priv->notification_expired, -+ "info-overview", _("Subscribe System…"), -+ _notify_clicked_cb, -+ manager, NULL); -+ g_signal_connect (priv->notification_expired, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+ -+ /* registered */ -+ priv->notification_registered = -+ notify_notification_new (_("Registration Successful"), -+ _("The system has been registered and software updates have been enabled."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_registered, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); -+ g_signal_connect (priv->notification_registered, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+ -+ /* registration required */ -+ priv->notification_registration_required = -+ notify_notification_new (_("System Not Registered"), -+ _("Please register your system to receive software updates."), -+ NULL); -+ notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); -+ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); -+ notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); -+ notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); -+ notify_notification_add_action (priv->notification_registration_required, -+ "info-overview", _("Register System…"), -+ _notify_clicked_cb, -+ manager, NULL); -+ g_signal_connect (priv->notification_registration_required, "closed", -+ G_CALLBACK (_notify_closed_cb), manager); -+} -+ -+static void -+gsd_subscription_manager_finalize (GObject *object) -+{ -+ GsdSubscriptionManager *manager; -+ -+ g_return_if_fail (object != NULL); -+ g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object)); -+ -+ manager = GSD_SUBSCRIPTION_MANAGER (object); -+ -+ gsd_subscription_manager_stop (manager); -+ -+ if (manager->priv->bus_cancellable != NULL) { -+ g_cancellable_cancel (manager->priv->bus_cancellable); -+ g_clear_object (&manager->priv->bus_cancellable); -+ } -+ -+ g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); -+ g_clear_object (&manager->priv->connection); -+ g_clear_object (&manager->priv->notification_expired); -+ g_clear_object (&manager->priv->notification_registered); -+ g_timer_destroy (manager->priv->timer_last_notified); -+ -+ if (manager->priv->name_id != 0) { -+ g_bus_unown_name (manager->priv->name_id); -+ manager->priv->name_id = 0; -+ } -+ -+ G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object); -+} -+ -+static void -+handle_method_call (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *method_name, -+ GVariant *parameters, -+ GDBusMethodInvocation *invocation, -+ gpointer user_data) -+{ -+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); -+ g_autoptr(GError) error = NULL; -+ -+ if (g_strcmp0 (method_name, "Register") == 0) { -+ const gchar *organisation = NULL; -+ const gchar *hostname = NULL; -+ -+ if (FALSE) { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, -+ "Cannot register at this time"); -+ -+ return; -+ } -+ -+ g_autoptr(GVariantDict) dict = g_variant_dict_new (g_variant_get_child_value (parameters, 0)); -+ -+ const gchar *kind = NULL; -+ if (!g_variant_dict_lookup (dict, "kind", "&s", &kind)) { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_FAILED, -+ "No kind specified"); -+ -+ return; -+ } -+ if (g_strcmp0 (kind, "username") == 0) { -+ const gchar *username = NULL; -+ const gchar *password = NULL; -+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); -+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); -+ g_variant_dict_lookup (dict, "username", "&s", &username); -+ g_variant_dict_lookup (dict, "password", "&s", &password); -+ if (!_client_register (manager, -+ hostname, -+ organisation, -+ username, -+ password, -+ &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ } else if (g_strcmp0 (kind, "key") == 0) { -+ const gchar *activation_key = NULL; -+ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); -+ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); -+ g_variant_dict_lookup (dict, "activation-key", "&s", &activation_key); -+ if (!_client_register_with_keys (manager, -+ hostname, -+ organisation, -+ activation_key, -+ &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ } else { -+ g_dbus_method_invocation_return_error_literal (invocation, -+ G_IO_ERROR, G_IO_ERROR_FAILED, -+ "Invalid kind specified"); -+ -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); -+ } else if (g_strcmp0 (method_name, "Unregister") == 0) { -+ if (!_client_unregister (manager, &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); -+ } else { -+ g_assert_not_reached (); -+ } -+} -+ -+static GVariant * -+handle_get_property (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *property_name, -+ GError **error, gpointer user_data) -+{ -+ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such interface: %s", interface_name); -+ return NULL; -+ } -+ -+ if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) -+ return g_variant_new_uint32 (priv->subscription_status); -+ -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "Failed to get property: %s", property_name); -+ return NULL; -+} -+ -+static gboolean -+handle_set_property (GDBusConnection *connection, -+ const gchar *sender, -+ const gchar *object_path, -+ const gchar *interface_name, -+ const gchar *property_name, -+ GVariant *value, -+ GError **error, gpointer user_data) -+{ -+ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such interface: %s", interface_name); -+ return FALSE; -+ } -+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, -+ "No such property: %s", property_name); -+ return FALSE; -+} -+ -+static const GDBusInterfaceVTable interface_vtable = -+{ -+ handle_method_call, -+ handle_get_property, -+ handle_set_property -+}; -+ -+static void -+name_lost_handler_cb (GDBusConnection *connection, const gchar *name, gpointer user_data) -+{ -+ g_debug ("lost name, so exiting"); -+ gtk_main_quit (); -+} -+ -+static void -+on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ GDBusConnection *connection; -+ g_autoptr(GError) error = NULL; -+ -+ connection = g_bus_get_finish (res, &error); -+ if (connection == NULL) { -+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) -+ g_warning ("Could not get session bus: %s", error->message); -+ return; -+ } -+ -+ priv->connection = connection; -+ g_dbus_connection_register_object (connection, -+ GSD_SUBSCRIPTION_DBUS_PATH, -+ priv->introspection_data->interfaces[0], -+ &interface_vtable, -+ manager, -+ NULL, -+ NULL); -+ priv->name_id = g_bus_own_name_on_connection (connection, -+ GSD_SUBSCRIPTION_DBUS_NAME, -+ G_BUS_NAME_OWNER_FLAGS_NONE, -+ NULL, -+ name_lost_handler_cb, -+ manager, -+ NULL); -+} -+ -+static void -+register_manager_dbus (GsdSubscriptionManager *manager) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ -+ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); -+ g_assert (priv->introspection_data != NULL); -+ priv->bus_cancellable = g_cancellable_new (); -+ -+ g_bus_get (G_BUS_TYPE_SESSION, priv->bus_cancellable, -+ (GAsyncReadyCallback) on_bus_gotten, manager); -+} -+ -+GsdSubscriptionManager * -+gsd_subscription_manager_new (void) -+{ -+ if (manager_object != NULL) { -+ g_object_ref (manager_object); -+ } else { -+ manager_object = g_object_new (GSD_TYPE_SUBSCRIPTION_MANAGER, NULL); -+ g_object_add_weak_pointer (manager_object, -+ (gpointer *) &manager_object); -+ register_manager_dbus (manager_object); -+ } -+ -+ return GSD_SUBSCRIPTION_MANAGER (manager_object); -+} -diff --git a/plugins/subman/gsd-subscription-manager.h b/plugins/subman/gsd-subscription-manager.h -new file mode 100644 -index 00000000..6a524b1b ---- /dev/null -+++ b/plugins/subman/gsd-subscription-manager.h -@@ -0,0 +1,63 @@ -+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- -+ * -+ * Copyright (C) 2019 Richard Hughes -+ * -+ * 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, see . -+ * -+ */ -+ -+#ifndef __GSD_SUBSCRIPTION_MANAGER_H -+#define __GSD_SUBSCRIPTION_MANAGER_H -+ -+#include -+ -+G_BEGIN_DECLS -+ -+#define GSD_TYPE_SUBSCRIPTION_MANAGER (gsd_subscription_manager_get_type ()) -+#define GSD_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManager)) -+#define GSD_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) -+#define GSD_IS_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER)) -+#define GSD_IS_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SUBSCRIPTION_MANAGER)) -+#define GSD_SUBSCRIPTION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) -+#define GSD_SUBSCRIPTION_MANAGER_ERROR (gsd_subscription_manager_error_quark ()) -+ -+typedef struct GsdSubscriptionManagerPrivate GsdSubscriptionManagerPrivate; -+ -+typedef struct -+{ -+ GObject parent; -+ GsdSubscriptionManagerPrivate *priv; -+} GsdSubscriptionManager; -+ -+typedef struct -+{ -+ GObjectClass parent_class; -+} GsdSubscriptionManagerClass; -+ -+enum -+{ -+ GSD_SUBSCRIPTION_MANAGER_ERROR_FAILED -+}; -+ -+GType gsd_subscription_manager_get_type (void); -+GQuark gsd_subscription_manager_error_quark (void); -+ -+GsdSubscriptionManager *gsd_subscription_manager_new (void); -+gboolean gsd_subscription_manager_start (GsdSubscriptionManager *manager, -+ GError **error); -+void gsd_subscription_manager_stop (GsdSubscriptionManager *manager); -+ -+G_END_DECLS -+ -+#endif /* __GSD_SUBSCRIPTION_MANAGER_H */ -diff --git a/plugins/subman/main.c b/plugins/subman/main.c -new file mode 100644 -index 00000000..28ac995b ---- /dev/null -+++ b/plugins/subman/main.c -@@ -0,0 +1,8 @@ -+#define NEW gsd_subscription_manager_new -+#define START gsd_subscription_manager_start -+#define STOP gsd_subscription_manager_stop -+#define MANAGER GsdSubscriptionManager -+#define GDK_BACKEND "x11" -+#include "gsd-subscription-manager.h" -+ -+#include "daemon-skeleton-gtk.h" -diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build -new file mode 100644 -index 00000000..bfd073b6 ---- /dev/null -+++ b/plugins/subman/meson.build -@@ -0,0 +1,56 @@ -+sources = files( -+ 'gsd-subscription-manager.c', -+ 'gsd-subman-common.c', -+ 'main.c' -+) -+ -+deps = plugins_deps + [ -+ libnotify_dep, -+ gtk_dep, -+ jsonglib_dep, -+ m_dep, -+] -+ -+cflags += ['-DBINDIR="@0@"'.format(gsd_bindir)] -+cflags += ['-DLIBEXECDIR="@0@"'.format(gsd_libexecdir)] -+ -+executable( -+ 'gsd-' + plugin_name, -+ sources, -+ include_directories: [top_inc, common_inc], -+ dependencies: deps, -+ c_args: cflags, -+ install: true, -+ install_rpath: gsd_pkglibdir, -+ install_dir: gsd_libexecdir -+) -+ -+# .Register needs to be called from root as subman can't do PolicyKit... -+policy = 'org.gnome.settings-daemon.plugins.subman.policy' -+policy_in = configure_file( -+ input: policy + '.in.in', -+ output: policy + '.in', -+ configuration: plugins_conf -+) -+ -+i18n.merge_file( -+ policy, -+ input: policy_in, -+ output: policy, -+ po_dir: po_dir, -+ install: true, -+ install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions') -+) -+ -+install_data('org.gnome.settings-daemon.plugins.subman.rules', -+ install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d')) -+ -+executable( -+ 'gsd-subman-helper', -+ 'gsd-subman-helper.c', -+ include_directories: top_inc, -+ dependencies: [gio_dep, jsonglib_dep], -+ install: true, -+ install_rpath: gsd_pkglibdir, -+ install_dir: gsd_libexecdir -+) -diff --git a/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in -new file mode 100644 -index 00000000..14fe5915 ---- /dev/null -+++ b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in -@@ -0,0 +1,9 @@ -+[Desktop Entry] -+Type=Application -+Name=GNOME Settings Daemon's subscription manager plugin -+Exec=@libexecdir@/gsd-subman -+OnlyShowIn=GNOME; -+NoDisplay=true -+X-GNOME-Autostart-Phase=Initialization -+X-GNOME-Autostart-Notify=true -+X-GNOME-AutoRestart=true -diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in -new file mode 100644 -index 00000000..59e9fdd4 ---- /dev/null -+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in -@@ -0,0 +1,27 @@ -+ -+ -+ -+ -+ -+ -+ GNOME Settings Daemon -+ http://git.gnome.org/browse/gnome-settings-daemon -+ emblem-synchronizing -+ -+ -+ Register the system -+ Authentication is required to register the system -+ -+ no -+ no -+ auth_admin_keep -+ -+ @libexecdir@/gsd-subman-helper -+ -+ -+ -diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules -new file mode 100644 -index 00000000..1ed3a0ea ---- /dev/null -+++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules -@@ -0,0 +1,7 @@ -+polkit.addRule(function(action, subject) { -+ if (action.id == "org.gnome.settings-daemon.plugins.subman.register" && -+ subject.active == true && subject.local == true && -+ subject.isInGroup("wheel")) { -+ return polkit.Result.YES; -+ } -+}); --- -2.30.0 - diff --git a/SOURCES/0002-smartcard-Change-manager-to-non-blocking.patch b/SOURCES/0002-smartcard-Change-manager-to-non-blocking.patch new file mode 100644 index 0000000..f76e9b4 --- /dev/null +++ b/SOURCES/0002-smartcard-Change-manager-to-non-blocking.patch @@ -0,0 +1,124 @@ +From 65d854c690cad1ccef6544a8c571bbb723ff9be0 Mon Sep 17 00:00:00 2001 +From: Jack Massey +Date: Tue, 17 Sep 2019 09:39:56 +1000 +Subject: [PATCH 2/4] smartcard: Change manager to non-blocking + +NSS's SECMOND_WaitForAnyTokenEvent uses the pkcs11 C_WaitForSlotEvent, +and by default NSS will use p11-kit, at least on Fedora and Ubuntu. +p11-kit doesn't support the blocking call for C_WaitForSlotEvent so NSS +falls back to a polling simulation of the C_WaitForSlotEvent. This +causes the LED on the smartcard to blink constantly as the card is +polled. + +If we instead use the non-blocking version of the call, which p11-kit +supports, NSS doesn't poll the card. The downside of this is that the +application will wake up every second to check for events even if there +hasn't been any, plus the fact that there could be up to a second delay +between the event and it being picked up by gsd-smartcard. However, NSS +is polling anyway so this is consistent with existing behaviour. + +The reason a one second delay was chosen was because this is what was +currently used in NSS. nss/lib/dev/devslot.c:17 + + /* measured in seconds */ + #define NSSSLOT_TOKEN_DELAY_TIME 1 +--- + plugins/smartcard/gsd-smartcard-manager.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c +index 09ccecc0..77650643 100644 +--- a/plugins/smartcard/gsd-smartcard-manager.c ++++ b/plugins/smartcard/gsd-smartcard-manager.c +@@ -167,75 +167,86 @@ typedef struct + { + SECMODModule *driver; + GHashTable *smartcards; + int number_of_consecutive_errors; + } WatchSmartcardsOperation; + + static void + on_watch_cancelled (GCancellable *cancellable, + WatchSmartcardsOperation *operation) + { + SECMOD_CancelWait (operation->driver); + } + + static gboolean + watch_one_event_from_driver (GsdSmartcardManager *self, + WatchSmartcardsOperation *operation, + GCancellable *cancellable, + GError **error) + { + GsdSmartcardManagerPrivate *priv = self->priv; + PK11SlotInfo *card = NULL, *old_card; + CK_SLOT_ID slot_id; + gulong handler_id; + int old_slot_series = -1, slot_series; + + handler_id = g_cancellable_connect (cancellable, + G_CALLBACK (on_watch_cancelled), + operation, + NULL); + +- if (handler_id != 0) +- card = SECMOD_WaitForAnyTokenEvent (operation->driver, 0, PR_SecondsToInterval (1)); ++ if (handler_id != 0) { ++ /* Use the non-blocking version of the call as p11-kit, which ++ * is used on both Fedora and Ubuntu, doesn't support the ++ * blocking version of the call. ++ */ ++ card = SECMOD_WaitForAnyTokenEvent (operation->driver, CKF_DONT_BLOCK, PR_SecondsToInterval (1)); ++ } + + g_cancellable_disconnect (cancellable, handler_id); + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) { + g_warning ("smartcard event function cancelled"); + return FALSE; + } + + if (card == NULL) { + int error_code; + + error_code = PORT_GetError (); + ++ if (error_code == SEC_ERROR_NO_EVENT) { ++ g_usleep (1 * G_USEC_PER_SEC); ++ ++ return TRUE; ++ } ++ + operation->number_of_consecutive_errors++; + if (operation->number_of_consecutive_errors > 10) { + g_warning ("Got %d consecutive smartcard errors, so giving up.", + operation->number_of_consecutive_errors); + + g_set_error (error, + GSD_SMARTCARD_MANAGER_ERROR, + GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, + "encountered unexpected error while " + "waiting for smartcard events (error %x)", + error_code); + return FALSE; + } + + g_warning ("Got potentially spurious smartcard event error: %x.", error_code); + + g_usleep (0.5 * G_USEC_PER_SEC); + return TRUE; + } + operation->number_of_consecutive_errors = 0; + + slot_id = PK11_GetSlotID (card); + slot_series = PK11_GetSlotSeries (card); + + old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); + + /* If there is a different card in the slot now than + * there was before, then we need to emit a removed signal + * for the old card + */ +-- +2.39.2 + diff --git a/SOURCES/0002-subman-Add-InstalledProducts-dbus-property-for-g-c-c.patch b/SOURCES/0002-subman-Add-InstalledProducts-dbus-property-for-g-c-c.patch deleted file mode 100644 index c7505ab..0000000 --- a/SOURCES/0002-subman-Add-InstalledProducts-dbus-property-for-g-c-c.patch +++ /dev/null @@ -1,768 +0,0 @@ -From f723ed1078e050c4d966d40b2aea74970c74279c Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Thu, 27 Jun 2019 16:12:00 +0200 -Subject: [PATCH 02/15] subman: Add InstalledProducts dbus property for g-c-c - ---- - plugins/subman/gsd-subscription-manager.c | 135 ++++++++++++++++++++++ - 1 file changed, 135 insertions(+) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 08b13fa6..a8c18a26 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -1,186 +1,304 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes -+ * Copyright (C) 2019 Kalev Lember - * - * 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, see . - * - */ - - #include "config.h" - - #include - #include - #include - #include - #include - - #include "gnome-settings-profile.h" - #include "gsd-subman-common.h" - #include "gsd-subscription-manager.h" - - #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" - #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" - #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" - - #define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" - #define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" - #define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" - - static const gchar introspection_xml[] = - "" - " " - " " - " " - " " - " " -+" " - " " - " " - ""; - - #define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) - - typedef enum { - _RHSM_INTERFACE_CONFIG, - _RHSM_INTERFACE_REGISTER_SERVER, - _RHSM_INTERFACE_ATTACH, - _RHSM_INTERFACE_ENTITLEMENT, - _RHSM_INTERFACE_PRODUCTS, - _RHSM_INTERFACE_CONSUMER, - _RHSM_INTERFACE_SYSPURPOSE, - _RHSM_INTERFACE_LAST - } _RhsmInterface; - - struct GsdSubscriptionManagerPrivate - { - /* D-Bus */ - guint name_id; - GDBusNodeInfo *introspection_data; - GDBusConnection *connection; - GCancellable *bus_cancellable; - - GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; - const gchar *userlang; /* owned by GLib internally */ - GHashTable *config; /* str:str */ -+ GPtrArray *installed_products; - gchar *address; - - GTimer *timer_last_notified; - NotifyNotification *notification_expired; - NotifyNotification *notification_registered; - NotifyNotification *notification_registration_required; - GsdSubmanSubscriptionStatus subscription_status; - GsdSubmanSubscriptionStatus subscription_status_last; - }; - - enum { - PROP_0, - }; - - static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); - static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); - static void gsd_subscription_manager_finalize (GObject *object); - - G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) - -+typedef struct -+{ -+ gchar *product_name; -+ gchar *product_id; -+ gchar *version; -+ gchar *arch; -+ gchar *status; -+ gchar *starts; -+ gchar *ends; -+} ProductData; -+ -+static void -+product_data_free (ProductData *product) -+{ -+ g_free (product->product_name); -+ g_free (product->product_id); -+ g_free (product->version); -+ g_free (product->arch); -+ g_free (product->status); -+ g_free (product->starts); -+ g_free (product->ends); -+ g_free (product); -+} -+ -+G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); -+ - static gpointer manager_object = NULL; - - GQuark - gsd_subscription_manager_error_quark (void) - { - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("gsd_subscription_manager_error"); - return quark; - } - - static GsdSubmanSubscriptionStatus - _client_subscription_status_from_text (const gchar *status_txt) - { - if (g_strcmp0 (status_txt, "Unknown") == 0) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - if (g_strcmp0 (status_txt, "Current") == 0) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; - if (g_strcmp0 (status_txt, "Invalid") == 0) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; - if (g_strcmp0 (status_txt, "Disabled") == 0) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; - if (g_strcmp0 (status_txt, "Insufficient") == 0) - return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; - g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? - return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - } - -+static GVariant * -+_make_installed_products_variant (GPtrArray *installed_products) -+{ -+ GVariantBuilder builder; -+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); -+ -+ for (guint i = 0; i < installed_products->len; i++) { -+ ProductData *product = g_ptr_array_index (installed_products, i); -+ g_auto(GVariantDict) dict; -+ -+ g_variant_dict_init (&dict, NULL); -+ -+ g_variant_dict_insert (&dict, "product-name", "s", product->product_name); -+ g_variant_dict_insert (&dict, "product-id", "s", product->product_id); -+ g_variant_dict_insert (&dict, "version", "s", product->version); -+ g_variant_dict_insert (&dict, "arch", "s", product->arch); -+ g_variant_dict_insert (&dict, "status", "s", product->status); -+ g_variant_dict_insert (&dict, "starts", "s", product->starts); -+ g_variant_dict_insert (&dict, "ends", "s", product->ends); -+ -+ g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); -+ } -+ -+ return g_variant_builder_end (&builder); -+} -+ - static void - _emit_property_changed (GsdSubscriptionManager *manager, - const gchar *property_name, - GVariant *property_value) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - GVariantBuilder builder; - GVariantBuilder invalidated_builder; - - /* not yet connected */ - if (priv->connection == NULL) - return; - - /* build the dict */ - g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); - g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); - g_variant_builder_add (&builder, - "{sv}", - property_name, - property_value); - g_dbus_connection_emit_signal (priv->connection, - NULL, - GSD_SUBSCRIPTION_DBUS_PATH, - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - g_variant_new ("(sa{sv}as)", - GSD_SUBSCRIPTION_DBUS_INTERFACE, - &builder, - &invalidated_builder), - NULL); - g_variant_builder_clear (&builder); - g_variant_builder_clear (&invalidated_builder); - } - -+static gboolean -+_client_installed_products_update (GsdSubscriptionManager *manager, GError **error) -+{ -+ GsdSubscriptionManagerPrivate *priv = manager->priv; -+ JsonNode *json_root; -+ JsonArray *json_products_array; -+ const gchar *json_txt = NULL; -+ g_autoptr(GVariant) val = NULL; -+ g_autoptr(JsonParser) json_parser = json_parser_new (); -+ -+ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS], -+ "ListInstalledProducts", -+ g_variant_new ("(sa{sv}s)", -+ "" /* filter_string */, -+ NULL /* proxy_options */, -+ priv->userlang), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (val == NULL) -+ return FALSE; -+ g_variant_get (val, "(&s)", &json_txt); -+ g_debug ("Products.ListInstalledProducts JSON: %s", json_txt); -+ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) -+ return FALSE; -+ json_root = json_parser_get_root (json_parser); -+ json_products_array = json_node_get_array (json_root); -+ if (json_products_array == NULL) { -+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -+ "no InstalledProducts array in %s", json_txt); -+ return FALSE; -+ } -+ -+ g_ptr_array_set_size (priv->installed_products, 0); -+ -+ for (guint i = 0; i < json_array_get_length (json_products_array); i++) { -+ JsonArray *json_product = json_array_get_array_element (json_products_array, i); -+ g_autoptr(ProductData) product = g_new0 (ProductData, 1); -+ -+ if (json_product == NULL) -+ continue; -+ if (json_array_get_length (json_product) < 8) { -+ g_debug ("Unexpected number of array elements in InstalledProducts JSON"); -+ continue; -+ } -+ -+ product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); -+ product->product_id = g_strdup (json_array_get_string_element (json_product, 1)); -+ product->version = g_strdup (json_array_get_string_element (json_product, 2)); -+ product->arch = g_strdup (json_array_get_string_element (json_product, 3)); -+ product->status = g_strdup (json_array_get_string_element (json_product, 4)); -+ product->starts = g_strdup (json_array_get_string_element (json_product, 6)); -+ product->ends = g_strdup (json_array_get_string_element (json_product, 7)); -+ -+ g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); -+ } -+ -+ /* emit notification for g-c-c */ -+ _emit_property_changed (manager, "InstalledProducts", -+ _make_installed_products_variant (priv->installed_products)); -+ -+ return TRUE; -+} -+ - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - const gchar *status_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ - priv->userlang), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "status")) { -@@ -423,185 +541,195 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-key", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - "--activation-key", activation_key, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - - /* success */ - return TRUE; - } - - static gboolean - _client_register (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *username, - const gchar *password, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; - - /* fallback */ - if (organisation == NULL) - organisation = ""; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-username", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - "--username", username, - "--password", password, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_unregister (GsdSubscriptionManager *manager, GError **error) - { - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_update_config (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) val = NULL; - g_autoptr(GVariant) val_server = NULL; - g_autoptr(GVariantDict) dict = NULL; - GVariantIter iter; - gchar *key; - gchar *value; - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], - "GetAll", - g_variant_new ("(s)", priv->userlang), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); - val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); - if (val_server != NULL) { - g_variant_iter_init (&iter, val_server); - while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { - g_debug ("%s=%s", key, value); - g_hash_table_insert (priv->config, - g_steal_pointer (&key), - g_steal_pointer (&value)); - } - } - return TRUE; - } - - static void - _subman_proxy_signal_cb (GDBusProxy *proxy, - const gchar *sender_name, - const gchar *signal_name, - GVariant *parameters, - GsdSubscriptionManager *manager) - { - g_autoptr(GError) error = NULL; - if (!_client_syspurpose_update (manager, &error)) { - g_warning ("failed to update syspurpose: %s", error->message); - g_clear_error (&error); - } - if (!_client_subscription_status_update (manager, &error)) { - g_warning ("failed to update subscription status: %s", error->message); - g_clear_error (&error); - } -+ if (!_client_installed_products_update (manager, &error)) { -+ g_warning ("failed to update installed products: %s", error->message); -+ g_clear_error (&error); -+ } - _client_maybe__show_notification (manager); - } - - static void - _client_unload (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) - g_clear_object (&priv->proxies[i]); - g_hash_table_unref (priv->config); - } - - static const gchar * - _rhsm_interface_to_string (_RhsmInterface kind) - { - if (kind == _RHSM_INTERFACE_CONFIG) - return "Config"; - if (kind == _RHSM_INTERFACE_REGISTER_SERVER) - return "RegisterServer"; - if (kind == _RHSM_INTERFACE_ATTACH) - return "Attach"; - if (kind == _RHSM_INTERFACE_ENTITLEMENT) - return "Entitlement"; - if (kind == _RHSM_INTERFACE_PRODUCTS) - return "Products"; - if (kind == _RHSM_INTERFACE_CONSUMER) - return "Consumer"; - if (kind == _RHSM_INTERFACE_SYSPURPOSE) - return "Syspurpose"; - return NULL; -@@ -613,60 +741,62 @@ _client_load (GsdSubscriptionManager *manager, GError **error) - GsdSubscriptionManagerPrivate *priv = manager->priv; - - priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* connect to all the interfaces on the *different* objects :| */ - for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { - const gchar *kind = _rhsm_interface_to_string (i); - g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); - g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); - priv->proxies[i] = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "com.redhat.RHSM1", - opath, iface, - NULL, - error); - if (priv->proxies[i] == NULL) - return FALSE; - /* we want to get notified if the status of the system changes */ - g_signal_connect (priv->proxies[i], "g-signal", - G_CALLBACK (_subman_proxy_signal_cb), manager); - } - - /* get initial status */ - priv->userlang = ""; - if (!_client_update_config (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -+ if (!_client_installed_products_update (manager, error)) -+ return FALSE; - if (!_client_syspurpose_update (manager, error)) - return FALSE; - - /* success */ - return TRUE; - } - - gboolean - gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) - { - gboolean ret; - g_debug ("Starting subscription manager"); - gnome_settings_profile_start (NULL); - ret = _client_load (manager, error); - _client_maybe__show_notification (manager); - gnome_settings_profile_end (NULL); - return ret; - } - - void - gsd_subscription_manager_stop (GsdSubscriptionManager *manager) - { - g_debug ("Stopping subscription manager"); - _client_unload (manager); - } - - static void - gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) - { - GObjectClass *object_class = G_OBJECT_CLASS (klass); -@@ -676,60 +806,61 @@ gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) - } - - static void - _launch_info_overview (void) - { - const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; - g_debug ("Running gnome-control-center info-overview"); - g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, - NULL, NULL, NULL, NULL); - } - - static void - _notify_closed_cb (NotifyNotification *notification, gpointer user_data) - { - /* FIXME: only launch when clicking on the main body, not the window close */ - if (notify_notification_get_closed_reason (notification) == 0x400) - _launch_info_overview (); - } - - static void - _notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) - { - _launch_info_overview (); - } - - static void - gsd_subscription_manager_init (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); - -+ priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); - priv->timer_last_notified = g_timer_new (); - - /* expired */ - priv->notification_expired = - notify_notification_new (_("Subscription Has Expired"), - _("Add or renew a subscription to continue receiving software updates."), - NULL); - notify_notification_set_app_name (priv->notification_expired, _("Subscription")); - notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); - notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); - notify_notification_add_action (priv->notification_expired, - "info-overview", _("Subscribe System…"), - _notify_clicked_cb, - manager, NULL); - g_signal_connect (priv->notification_expired, "closed", - G_CALLBACK (_notify_closed_cb), manager); - - /* registered */ - priv->notification_registered = - notify_notification_new (_("Registration Successful"), - _("The system has been registered and software updates have been enabled."), - NULL); - notify_notification_set_app_name (priv->notification_registered, _("Subscription")); - notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); - notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); - g_signal_connect (priv->notification_registered, "closed", - G_CALLBACK (_notify_closed_cb), manager); - -@@ -740,60 +871,61 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) - NULL); - notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); - notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); - notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); - notify_notification_add_action (priv->notification_registration_required, - "info-overview", _("Register System…"), - _notify_clicked_cb, - manager, NULL); - g_signal_connect (priv->notification_registration_required, "closed", - G_CALLBACK (_notify_closed_cb), manager); - } - - static void - gsd_subscription_manager_finalize (GObject *object) - { - GsdSubscriptionManager *manager; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object)); - - manager = GSD_SUBSCRIPTION_MANAGER (object); - - gsd_subscription_manager_stop (manager); - - if (manager->priv->bus_cancellable != NULL) { - g_cancellable_cancel (manager->priv->bus_cancellable); - g_clear_object (&manager->priv->bus_cancellable); - } - -+ g_clear_pointer (&manager->priv->installed_products, g_ptr_array_unref); - g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); - g_clear_object (&manager->priv->connection); - g_clear_object (&manager->priv->notification_expired); - g_clear_object (&manager->priv->notification_registered); - g_timer_destroy (manager->priv->timer_last_notified); - - if (manager->priv->name_id != 0) { - g_bus_unown_name (manager->priv->name_id); - manager->priv->name_id = 0; - } - - G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object); - } - - static void - handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) - { - GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); - g_autoptr(GError) error = NULL; - - if (g_strcmp0 (method_name, "Register") == 0) { - const gchar *organisation = NULL; - const gchar *hostname = NULL; -@@ -857,60 +989,63 @@ handle_method_call (GDBusConnection *connection, - if (!_client_unregister (manager, &error)) { - g_dbus_method_invocation_return_gerror (invocation, error); - return; - } - g_dbus_method_invocation_return_value (invocation, NULL); - } else { - g_assert_not_reached (); - } - } - - static GVariant * - handle_get_property (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GError **error, gpointer user_data) - { - GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); - GsdSubscriptionManagerPrivate *priv = manager->priv; - - if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "No such interface: %s", interface_name); - return NULL; - } - - if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) - return g_variant_new_uint32 (priv->subscription_status); - -+ if (g_strcmp0 (property_name, "InstalledProducts") == 0) -+ return _make_installed_products_variant (priv->installed_products); -+ - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "Failed to get property: %s", property_name); - return NULL; - } - - static gboolean - handle_set_property (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GVariant *value, - GError **error, gpointer user_data) - { - if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "No such interface: %s", interface_name); - return FALSE; - } - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "No such property: %s", property_name); - return FALSE; - } - - static const GDBusInterfaceVTable interface_vtable = - { - handle_method_call, - handle_get_property, - handle_set_property - }; --- -2.30.0 - diff --git a/SOURCES/0003-smartcard-Change-timeout-on-spurious-event-error.patch b/SOURCES/0003-smartcard-Change-timeout-on-spurious-event-error.patch new file mode 100644 index 0000000..6fb84a1 --- /dev/null +++ b/SOURCES/0003-smartcard-Change-timeout-on-spurious-event-error.patch @@ -0,0 +1,83 @@ +From 5da276e4559d5c3b072a9870db6d78a1fe788339 Mon Sep 17 00:00:00 2001 +From: Jack Massey +Date: Tue, 17 Sep 2019 09:39:59 +1000 +Subject: [PATCH 3/4] smartcard: Change timeout on spurious event error + +The 0.5s timeout was probably based on the fact that the +SECMOD_WaitForAnyTokenEvent call was blocking, it doesn't make sense to +have the timeout on the error case less than the timeout on the normal +case. +--- + plugins/smartcard/gsd-smartcard-manager.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c +index 77650643..a29df3e0 100644 +--- a/plugins/smartcard/gsd-smartcard-manager.c ++++ b/plugins/smartcard/gsd-smartcard-manager.c +@@ -209,61 +209,61 @@ watch_one_event_from_driver (GsdSmartcardManager *self, + return FALSE; + } + + if (card == NULL) { + int error_code; + + error_code = PORT_GetError (); + + if (error_code == SEC_ERROR_NO_EVENT) { + g_usleep (1 * G_USEC_PER_SEC); + + return TRUE; + } + + operation->number_of_consecutive_errors++; + if (operation->number_of_consecutive_errors > 10) { + g_warning ("Got %d consecutive smartcard errors, so giving up.", + operation->number_of_consecutive_errors); + + g_set_error (error, + GSD_SMARTCARD_MANAGER_ERROR, + GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, + "encountered unexpected error while " + "waiting for smartcard events (error %x)", + error_code); + return FALSE; + } + + g_warning ("Got potentially spurious smartcard event error: %x.", error_code); + +- g_usleep (0.5 * G_USEC_PER_SEC); ++ g_usleep (1 * G_USEC_PER_SEC); + return TRUE; + } + operation->number_of_consecutive_errors = 0; + + slot_id = PK11_GetSlotID (card); + slot_series = PK11_GetSlotSeries (card); + + old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); + + /* If there is a different card in the slot now than + * there was before, then we need to emit a removed signal + * for the old card + */ + if (old_card != NULL) { + old_slot_series = PK11_GetSlotSeries (old_card); + + if (old_slot_series != slot_series) { + /* Card registered with slot previously is + * different than this card, so update its + * exported state to track the implicit missed + * removal + */ + gsd_smartcard_service_sync_token (priv->service, old_card, cancellable); + } + + g_hash_table_remove (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); + } + + if (PK11_IsPresent (card)) { + g_debug ("Detected smartcard insertion event in slot %d", (int) slot_id); +-- +2.39.2 + diff --git a/SOURCES/0003-subman-Increase-RHSM-dbus-call-timeouts.patch b/SOURCES/0003-subman-Increase-RHSM-dbus-call-timeouts.patch deleted file mode 100644 index b8a4ea4..0000000 --- a/SOURCES/0003-subman-Increase-RHSM-dbus-call-timeouts.patch +++ /dev/null @@ -1,313 +0,0 @@ -From 0d88b2133b20957e00b0eeb0c0f48932485cc73d Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Fri, 28 Jun 2019 18:10:36 +0200 -Subject: [PATCH 03/15] subman: Increase RHSM dbus call timeouts - -Increase the dbus timeouts to 5 minutes as the register/unregister calls -seem to routinely take more than a minute. ---- - plugins/subman/gsd-subman-helper.c | 17 ++++++++++++----- - 1 file changed, 12 insertions(+), 5 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index 182f7190..af7a82e9 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -1,60 +1,62 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes - * - * Licensed under the GNU General Public License Version 2 - * - * 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. - */ - - #include "config.h" - - #include - #include - #include - - #include - #include - -+#define DBUS_TIMEOUT 300000 /* 5 minutes */ -+ - static void - _helper_convert_error (const gchar *json_txt, GError **error) - { - JsonNode *json_root; - JsonObject *json_obj; - const gchar *message; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* this may be plain text or JSON :| */ - if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - json_txt); - return; - } - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "no message' in %s", json_txt); - return; - } - message = json_object_get_string_member (json_obj, "message"); - if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED, -@@ -67,125 +69,128 @@ _helper_convert_error (const gchar *json_txt, GError **error) - message); - } - - static gboolean - _helper_unregister (GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("unregistering"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Unregister", - "com.redhat.RHSM1.Unregister", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "Unregister", - g_variant_new ("(a{sv}s)", - proxy_options, - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - return res != NULL; - } - - static gboolean - _helper_auto_attach (GError **error) - { - const gchar *str = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("auto-attaching subscriptions"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Attach", - "com.redhat.RHSM1.Attach", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "AutoAttach", - g_variant_new ("(sa{sv}s)", - "", /* now? */ - proxy_options, - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - if (res == NULL) - return FALSE; - g_variant_get (res, "(&s)", &str); - g_debug ("Attach.AutoAttach: %s", str); - return TRUE; - } - - static gboolean - _helper_save_config (const gchar *key, const gchar *value, GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) res = NULL; - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Config", - "com.redhat.RHSM1.Config", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - res = g_dbus_proxy_call_sync (proxy, "Set", - g_variant_new ("(svs)", - key, - g_variant_new_string (value), - ""), /* lang */ - G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -+ DBUS_TIMEOUT, -+ NULL, error); - return res != NULL; - } - - int - main (int argc, char *argv[]) - { - const gchar *userlang = ""; /* as root, so no translations */ - g_autofree gchar *activation_key = NULL; - g_autofree gchar *address = NULL; - g_autofree gchar *hostname = NULL; - g_autofree gchar *kind = NULL; - g_autofree gchar *organisation = NULL; - g_autofree gchar *password = NULL; - g_autofree gchar *port = NULL; - g_autofree gchar *prefix = NULL; - g_autofree gchar *proxy_server = NULL; - g_autofree gchar *username = NULL; - g_autoptr(GDBusConnection) conn_private = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GError) error = NULL; - g_autoptr(GOptionContext) context = g_option_context_new (NULL); - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariantBuilder) subman_conopts = NULL; - g_autoptr(GVariantBuilder) subman_options = NULL; - - const GOptionEntry options[] = { - { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &kind, "Kind, e.g. 'username' or 'key'", NULL }, - { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &address, "UNIX address", NULL }, -@@ -278,95 +283,97 @@ main (int argc, char *argv[]) - g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); - g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); - g_variant_builder_add (subman_conopts, "{ss}", "port", port); - - /* call into RHSM */ - if (g_strcmp0 (kind, "register-with-key") == 0) { - g_auto(GStrv) activation_keys = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - - if (activation_key == NULL) { - g_printerr ("Required --activation-key\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, - "RegisterWithActivationKeys", - g_variant_new ("(s^asa{ss}a{ss}s)", - organisation, - activation_keys, - subman_options, - subman_conopts, - userlang), - G_DBUS_CALL_FLAGS_NO_AUTO_START, -- -1, NULL, &error_local); -+ DBUS_TIMEOUT, -+ NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); - return error->code; - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("registering using username and password"); - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (password == NULL) { - g_printerr ("Required --password\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", - organisation, - username, - password, - subman_options, - subman_conopts, - userlang), - G_DBUS_CALL_FLAGS_NO_AUTO_START, -- -1, NULL, &error_local); -+ DBUS_TIMEOUT, -+ NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to Register: %s\n", error->message); - return error->code; - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); - return G_IO_ERROR_INVALID_DATA; - } - - /* set the new hostname */ - if (!_helper_save_config ("server.hostname", hostname, &error)) { - g_printerr ("Failed to save hostname: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.prefix", prefix, &error)) { - g_printerr ("Failed to save prefix: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.port", port, &error)) { - g_printerr ("Failed to save port: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - - /* wait for rhsmd to notice the new config */ - g_usleep (G_USEC_PER_SEC * 5); - - /* auto-attach */ - if (!_helper_auto_attach (&error)) { --- -2.30.0 - diff --git a/SOURCES/0004-smartcard-check-for-the-addition-of-new-smartcard-re.patch b/SOURCES/0004-smartcard-check-for-the-addition-of-new-smartcard-re.patch new file mode 100644 index 0000000..a14e3c8 --- /dev/null +++ b/SOURCES/0004-smartcard-check-for-the-addition-of-new-smartcard-re.patch @@ -0,0 +1,94 @@ +From 2b0b62d8b04a2c3d6e1d4fccacfd29dd3da2d04c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?David=20H=C3=A4rdeman?= +Date: Wed, 12 Apr 2023 22:23:51 +0200 +Subject: [PATCH 4/4] smartcard: check for the addition of new smartcard + readers + +gsd-smartcard currently checks for the insertion/removal of smartcards +in reader devices which where present at the time gsd-smartcard was +started, but does not account for new smartcard readers appearing +after gsd-smartcard was started. + +This patch adds support for checking for the addition of new slots +(i.e. smartcard readers), which is necessary to support devices +like the Yubikey (a "reader" and a smartcard) which may be inserted +after gsd-smartcard was started. +--- + plugins/smartcard/gsd-smartcard-manager.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c +index a29df3e0..fbb9b260 100644 +--- a/plugins/smartcard/gsd-smartcard-manager.c ++++ b/plugins/smartcard/gsd-smartcard-manager.c +@@ -188,61 +188,66 @@ watch_one_event_from_driver (GsdSmartcardManager *self, + CK_SLOT_ID slot_id; + gulong handler_id; + int old_slot_series = -1, slot_series; + + handler_id = g_cancellable_connect (cancellable, + G_CALLBACK (on_watch_cancelled), + operation, + NULL); + + if (handler_id != 0) { + /* Use the non-blocking version of the call as p11-kit, which + * is used on both Fedora and Ubuntu, doesn't support the + * blocking version of the call. + */ + card = SECMOD_WaitForAnyTokenEvent (operation->driver, CKF_DONT_BLOCK, PR_SecondsToInterval (1)); + } + + g_cancellable_disconnect (cancellable, handler_id); + + if (g_cancellable_set_error_if_cancelled (cancellable, error)) { + g_warning ("smartcard event function cancelled"); + return FALSE; + } + + if (card == NULL) { + int error_code; + + error_code = PORT_GetError (); + + if (error_code == SEC_ERROR_NO_EVENT) { +- g_usleep (1 * G_USEC_PER_SEC); ++ int old_slot_count = operation->driver->slotCount; ++ SECMOD_UpdateSlotList (operation->driver); ++ if (operation->driver->slotCount != old_slot_count) ++ g_debug ("Slot count change %i -> %i", old_slot_count, operation->driver->slotCount); ++ else ++ g_usleep (1 * G_USEC_PER_SEC); + + return TRUE; + } + + operation->number_of_consecutive_errors++; + if (operation->number_of_consecutive_errors > 10) { + g_warning ("Got %d consecutive smartcard errors, so giving up.", + operation->number_of_consecutive_errors); + + g_set_error (error, + GSD_SMARTCARD_MANAGER_ERROR, + GSD_SMARTCARD_MANAGER_ERROR_WITH_NSS, + "encountered unexpected error while " + "waiting for smartcard events (error %x)", + error_code); + return FALSE; + } + + g_warning ("Got potentially spurious smartcard event error: %x.", error_code); + + g_usleep (1 * G_USEC_PER_SEC); + return TRUE; + } + operation->number_of_consecutive_errors = 0; + + slot_id = PK11_GetSlotID (card); + slot_series = PK11_GetSlotSeries (card); + + old_card = g_hash_table_lookup (operation->smartcards, GINT_TO_POINTER ((int) slot_id)); + +-- +2.39.2 + diff --git a/SOURCES/0004-subman-Drop-userlang-field.patch b/SOURCES/0004-subman-Drop-userlang-field.patch deleted file mode 100644 index 559be02..0000000 --- a/SOURCES/0004-subman-Drop-userlang-field.patch +++ /dev/null @@ -1,454 +0,0 @@ -From df08a65d86626ff135a12d96cff6f48f3f1864ae Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 20 Aug 2020 11:20:47 -0400 -Subject: [PATCH 04/15] subman: Drop userlang field - -It's currently always erroneously set to empty string. - -This commit drops it, and just uses "C.UTF-8" everywhere, -which is what we actually want. ---- - plugins/subman/gsd-subscription-manager.c | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index a8c18a26..46f051a5 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -45,61 +45,60 @@ static const gchar introspection_xml[] = - " " - " " - " " - " " - " " - " " - ""; - - #define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) - - typedef enum { - _RHSM_INTERFACE_CONFIG, - _RHSM_INTERFACE_REGISTER_SERVER, - _RHSM_INTERFACE_ATTACH, - _RHSM_INTERFACE_ENTITLEMENT, - _RHSM_INTERFACE_PRODUCTS, - _RHSM_INTERFACE_CONSUMER, - _RHSM_INTERFACE_SYSPURPOSE, - _RHSM_INTERFACE_LAST - } _RhsmInterface; - - struct GsdSubscriptionManagerPrivate - { - /* D-Bus */ - guint name_id; - GDBusNodeInfo *introspection_data; - GDBusConnection *connection; - GCancellable *bus_cancellable; - - GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; -- const gchar *userlang; /* owned by GLib internally */ - GHashTable *config; /* str:str */ - GPtrArray *installed_products; - gchar *address; - - GTimer *timer_last_notified; - NotifyNotification *notification_expired; - NotifyNotification *notification_registered; - NotifyNotification *notification_registration_required; - GsdSubmanSubscriptionStatus subscription_status; - GsdSubmanSubscriptionStatus subscription_status_last; - }; - - enum { - PROP_0, - }; - - static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); - static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); - static void gsd_subscription_manager_finalize (GObject *object); - - G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) - - typedef struct - { - gchar *product_name; - gchar *product_id; - gchar *version; - gchar *arch; - gchar *status; - gchar *starts; -@@ -197,61 +196,61 @@ _emit_property_changed (GsdSubscriptionManager *manager, - property_value); - g_dbus_connection_emit_signal (priv->connection, - NULL, - GSD_SUBSCRIPTION_DBUS_PATH, - "org.freedesktop.DBus.Properties", - "PropertiesChanged", - g_variant_new ("(sa{sv}as)", - GSD_SUBSCRIPTION_DBUS_INTERFACE, - &builder, - &invalidated_builder), - NULL); - g_variant_builder_clear (&builder); - g_variant_builder_clear (&invalidated_builder); - } - - static gboolean - _client_installed_products_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonArray *json_products_array; - const gchar *json_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS], - "ListInstalledProducts", - g_variant_new ("(sa{sv}s)", - "" /* filter_string */, - NULL /* proxy_options */, -- priv->userlang), -+ "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Products.ListInstalledProducts JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_products_array = json_node_get_array (json_root); - if (json_products_array == NULL) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "no InstalledProducts array in %s", json_txt); - return FALSE; - } - - g_ptr_array_set_size (priv->installed_products, 0); - - for (guint i = 0; i < json_array_get_length (json_products_array); i++) { - JsonArray *json_product = json_array_get_array_element (json_products_array, i); - g_autoptr(ProductData) product = g_new0 (ProductData, 1); - - if (json_product == NULL) - continue; - if (json_array_get_length (json_product) < 8) { - g_debug ("Unexpected number of array elements in InstalledProducts JSON"); - continue; - } - - product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); -@@ -263,179 +262,179 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err - product->ends = g_strdup (json_array_get_string_element (json_product, 7)); - - g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); - } - - /* emit notification for g-c-c */ - _emit_property_changed (manager, "InstalledProducts", - _make_installed_products_variant (priv->installed_products)); - - return TRUE; - } - - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - const gchar *status_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ -- priv->userlang), -+ "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "status")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "no Entitlement.GetStatus status in %s", json_txt); - return FALSE; - } - - status_txt = json_object_get_string_member (json_obj, "status"); - g_debug ("Entitlement.GetStatus: %s", status_txt); - priv->subscription_status = _client_subscription_status_from_text (status_txt); - - /* emit notification for g-c-c */ - if (priv->subscription_status != priv->subscription_status_last) { - _emit_property_changed (manager, "SubscriptionStatus", - g_variant_new_uint32 (priv->subscription_status)); - } - - return TRUE; - } - - static gboolean - _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], - "GetSyspurpose", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "status")) { - g_debug ("Syspurpose.GetSyspurpose: Unknown"); - return TRUE; - } - g_debug ("Syspurpose.GetSyspurpose: '%s", json_object_get_string_member (json_obj, "status")); - return TRUE; - } - - static gboolean - _client_register_start (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - const gchar *address = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) val = NULL; - - /* already started */ - if (priv->address != NULL) - return TRUE; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/RegisterServer", - "com.redhat.RHSM1.RegisterServer", - NULL, error); - if (proxy == NULL) - return FALSE; - val = g_dbus_proxy_call_sync (proxy, "Start", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &address); - g_debug ("RegisterServer.Start: %s", address); - priv->address = g_strdup (address); - return TRUE; - } - - static gboolean - _client_register_stop (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) val = NULL; - - /* already started */ - if (priv->address == NULL) - return TRUE; - - /* stop registration server */ - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/RegisterServer", - "com.redhat.RHSM1.RegisterServer", - NULL, error); - if (proxy == NULL) - return FALSE; - val = g_dbus_proxy_call_sync (proxy, "Stop", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_clear_pointer (&priv->address, g_free); - return TRUE; - } - - static gboolean - _client_subprocess_wait_check (GSubprocess *subprocess, GError **error) - { - gint rc; - if (!g_subprocess_wait (subprocess, NULL, error)) { - g_prefix_error (error, "failed to run pkexec: "); - return FALSE; - } - rc = g_subprocess_get_exit_status (subprocess); - if (rc != 0) { - GInputStream *istream = g_subprocess_get_stderr_pipe (subprocess); - gchar buf[1024] = { 0x0 }; - gsize sz = 0; - g_input_stream_read_all (istream, buf, sizeof(buf) - 1, &sz, NULL, NULL); - if (sz == 0) { - g_set_error_literal (error, G_IO_ERROR, rc, - "Failed to run helper without stderr"); - return FALSE; - } - g_set_error_literal (error, G_IO_ERROR, rc, buf); - return FALSE; - } -@@ -637,61 +636,61 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_update_config (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) val = NULL; - g_autoptr(GVariant) val_server = NULL; - g_autoptr(GVariantDict) dict = NULL; - GVariantIter iter; - gchar *key; - gchar *value; - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], - "GetAll", -- g_variant_new ("(s)", priv->userlang), -+ g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); - val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); - if (val_server != NULL) { - g_variant_iter_init (&iter, val_server); - while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { - g_debug ("%s=%s", key, value); - g_hash_table_insert (priv->config, - g_steal_pointer (&key), - g_steal_pointer (&value)); - } - } - return TRUE; - } - - static void - _subman_proxy_signal_cb (GDBusProxy *proxy, - const gchar *sender_name, - const gchar *signal_name, - GVariant *parameters, - GsdSubscriptionManager *manager) - { - g_autoptr(GError) error = NULL; - if (!_client_syspurpose_update (manager, &error)) { - g_warning ("failed to update syspurpose: %s", error->message); - g_clear_error (&error); - } -@@ -736,61 +735,60 @@ _rhsm_interface_to_string (_RhsmInterface kind) - } - - static gboolean - _client_load (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - - priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* connect to all the interfaces on the *different* objects :| */ - for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { - const gchar *kind = _rhsm_interface_to_string (i); - g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); - g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); - priv->proxies[i] = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "com.redhat.RHSM1", - opath, iface, - NULL, - error); - if (priv->proxies[i] == NULL) - return FALSE; - /* we want to get notified if the status of the system changes */ - g_signal_connect (priv->proxies[i], "g-signal", - G_CALLBACK (_subman_proxy_signal_cb), manager); - } - - /* get initial status */ -- priv->userlang = ""; - if (!_client_update_config (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - if (!_client_syspurpose_update (manager, error)) - return FALSE; - - /* success */ - return TRUE; - } - - gboolean - gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) - { - gboolean ret; - g_debug ("Starting subscription manager"); - gnome_settings_profile_start (NULL); - ret = _client_load (manager, error); - _client_maybe__show_notification (manager); - gnome_settings_profile_end (NULL); - return ret; - } - - void - gsd_subscription_manager_stop (GsdSubscriptionManager *manager) - { - g_debug ("Stopping subscription manager"); - _client_unload (manager); --- -2.30.0 - diff --git a/SOURCES/0005-subman-Use-user-locale-for-registration-subscription.patch b/SOURCES/0005-subman-Use-user-locale-for-registration-subscription.patch deleted file mode 100644 index fa6973b..0000000 --- a/SOURCES/0005-subman-Use-user-locale-for-registration-subscription.patch +++ /dev/null @@ -1,373 +0,0 @@ -From db73e2211ecc746434d78d23d801c92581fa8824 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 15:04:17 -0500 -Subject: [PATCH 05/15] subman: Use user locale for registration/subscription - operations - -This makes sure that error messages are in the correct locale. ---- - plugins/subman/gsd-subman-helper.c | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index af7a82e9..f84e91bf 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -1,61 +1,63 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes - * - * Licensed under the GNU General Public License Version 2 - * - * 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. - */ - - #include "config.h" - - #include - #include - #include -+#include - - #include - #include - - #define DBUS_TIMEOUT 300000 /* 5 minutes */ -+static const char *locale; - - static void - _helper_convert_error (const gchar *json_txt, GError **error) - { - JsonNode *json_root; - JsonObject *json_obj; - const gchar *message; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* this may be plain text or JSON :| */ - if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - json_txt); - return; - } - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "no message' in %s", json_txt); - return; - } - message = json_object_get_string_member (json_obj, "message"); - if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { - g_set_error_literal (error, - G_IO_ERROR, -@@ -67,184 +69,187 @@ _helper_convert_error (const gchar *json_txt, GError **error) - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - message); - } - - static gboolean - _helper_unregister (GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("unregistering"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Unregister", - "com.redhat.RHSM1.Unregister", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "Unregister", - g_variant_new ("(a{sv}s)", - proxy_options, -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - return res != NULL; - } - - static gboolean - _helper_auto_attach (GError **error) - { - const gchar *str = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("auto-attaching subscriptions"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Attach", - "com.redhat.RHSM1.Attach", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "AutoAttach", - g_variant_new ("(sa{sv}s)", - "", /* now? */ - proxy_options, -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - if (res == NULL) - return FALSE; - g_variant_get (res, "(&s)", &str); - g_debug ("Attach.AutoAttach: %s", str); - return TRUE; - } - - static gboolean - _helper_save_config (const gchar *key, const gchar *value, GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) res = NULL; - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Config", - "com.redhat.RHSM1.Config", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - res = g_dbus_proxy_call_sync (proxy, "Set", - g_variant_new ("(svs)", - key, - g_variant_new_string (value), -- ""), /* lang */ -+ locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - return res != NULL; - } - - int - main (int argc, char *argv[]) - { -- const gchar *userlang = ""; /* as root, so no translations */ - g_autofree gchar *activation_key = NULL; - g_autofree gchar *address = NULL; - g_autofree gchar *hostname = NULL; - g_autofree gchar *kind = NULL; - g_autofree gchar *organisation = NULL; - g_autofree gchar *password = NULL; - g_autofree gchar *port = NULL; - g_autofree gchar *prefix = NULL; - g_autofree gchar *proxy_server = NULL; - g_autofree gchar *username = NULL; - g_autoptr(GDBusConnection) conn_private = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GError) error = NULL; - g_autoptr(GOptionContext) context = g_option_context_new (NULL); - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariantBuilder) subman_conopts = NULL; - g_autoptr(GVariantBuilder) subman_options = NULL; - - const GOptionEntry options[] = { - { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &kind, "Kind, e.g. 'username' or 'key'", NULL }, - { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &address, "UNIX address", NULL }, - { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &username, "Username", NULL }, - { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &password, "Password", NULL }, - { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &organisation, "Organisation", NULL }, - { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &activation_key, "Activation keys", NULL }, - { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &hostname, "Registration server hostname", NULL }, - { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &prefix, "Registration server prefix", NULL }, - { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &port, "Registration server port", NULL }, - { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &proxy_server, "Proxy settings", NULL }, - { NULL} - }; - - /* check calling UID */ - if (getuid () != 0 || geteuid () != 0) { - g_printerr ("This program can only be used by the root user\n"); - return G_IO_ERROR_NOT_SUPPORTED; - } -+ -+ setlocale (LC_ALL, ""); -+ locale = setlocale (LC_MESSAGES, NULL); -+ - g_option_context_add_main_entries (context, options, NULL); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("Failed to parse arguments: %s\n", error->message); - return G_IO_ERROR_NOT_SUPPORTED; - } - - /* uncommon actions */ - if (kind == NULL) { - g_printerr ("No --kind specified\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (g_strcmp0 (kind, "unregister") == 0) { - if (!_helper_unregister (&error)) { - g_printerr ("Failed to Unregister: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - return EXIT_SUCCESS; - } - if (g_strcmp0 (kind, "auto-attach") == 0) { - if (!_helper_auto_attach (&error)) { - g_printerr ("Failed to AutoAttach: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - return EXIT_SUCCESS; - } - - /* connect to abstract socket for reasons */ - if (address == NULL) { - g_printerr ("No --address specified\n"); - return G_IO_ERROR_INVALID_DATA; -@@ -281,96 +286,96 @@ main (int argc, char *argv[]) - port = g_strdup ("443"); - subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); - g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); - g_variant_builder_add (subman_conopts, "{ss}", "port", port); - - /* call into RHSM */ - if (g_strcmp0 (kind, "register-with-key") == 0) { - g_auto(GStrv) activation_keys = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - - if (activation_key == NULL) { - g_printerr ("Required --activation-key\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, - "RegisterWithActivationKeys", - g_variant_new ("(s^asa{ss}a{ss}s)", - organisation, - activation_keys, - subman_options, - subman_conopts, -- userlang), -+ locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); - return error->code; - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("registering using username and password"); - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (password == NULL) { - g_printerr ("Required --password\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", - organisation, - username, - password, - subman_options, - subman_conopts, -- userlang), -+ locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to Register: %s\n", error->message); - return error->code; - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); - return G_IO_ERROR_INVALID_DATA; - } - - /* set the new hostname */ - if (!_helper_save_config ("server.hostname", hostname, &error)) { - g_printerr ("Failed to save hostname: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.prefix", prefix, &error)) { - g_printerr ("Failed to save prefix: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.port", port, &error)) { - g_printerr ("Failed to save port: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - - /* wait for rhsmd to notice the new config */ - g_usleep (G_USEC_PER_SEC * 5); --- -2.30.0 - diff --git a/SOURCES/0006-subman-Handle-subscription-manager-giving-invalid-st.patch b/SOURCES/0006-subman-Handle-subscription-manager-giving-invalid-st.patch deleted file mode 100644 index cfd9b7c..0000000 --- a/SOURCES/0006-subman-Handle-subscription-manager-giving-invalid-st.patch +++ /dev/null @@ -1,236 +0,0 @@ -From f8ddd2c711cd502c74eb9d45360914fe2e6e1b3f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 20 Aug 2020 13:34:19 -0400 -Subject: [PATCH 06/15] subman: Handle subscription-manager giving invalid - status better - -subscription-manager potentially returns status messages that the -subman plugin treats as enum values translated in some unknown -other language. It could be tied to system locale, or due to a -caching bug a previous locale used. - -This commit tries to work around that bug, by instead relying on -the GetUUID() method and valid attribute. If there's no UUID we -know the system is unregistered. If there's a UUID but the valid -attribute is FALSE we know the system is registered, but hasn't -got proper entitlements. ---- - plugins/subman/gsd-subscription-manager.c | 69 ++++++++++++----------- - 1 file changed, 36 insertions(+), 33 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 46f051a5..e2c16056 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -104,77 +104,60 @@ typedef struct - gchar *starts; - gchar *ends; - } ProductData; - - static void - product_data_free (ProductData *product) - { - g_free (product->product_name); - g_free (product->product_id); - g_free (product->version); - g_free (product->arch); - g_free (product->status); - g_free (product->starts); - g_free (product->ends); - g_free (product); - } - - G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); - - static gpointer manager_object = NULL; - - GQuark - gsd_subscription_manager_error_quark (void) - { - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("gsd_subscription_manager_error"); - return quark; - } - --static GsdSubmanSubscriptionStatus --_client_subscription_status_from_text (const gchar *status_txt) --{ -- if (g_strcmp0 (status_txt, "Unknown") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -- if (g_strcmp0 (status_txt, "Current") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -- if (g_strcmp0 (status_txt, "Invalid") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -- if (g_strcmp0 (status_txt, "Disabled") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -- if (g_strcmp0 (status_txt, "Insufficient") == 0) -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -- g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? -- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; --} -- - static GVariant * - _make_installed_products_variant (GPtrArray *installed_products) - { - GVariantBuilder builder; - g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); - - for (guint i = 0; i < installed_products->len; i++) { - ProductData *product = g_ptr_array_index (installed_products, i); - g_auto(GVariantDict) dict; - - g_variant_dict_init (&dict, NULL); - - g_variant_dict_insert (&dict, "product-name", "s", product->product_name); - g_variant_dict_insert (&dict, "product-id", "s", product->product_id); - g_variant_dict_insert (&dict, "version", "s", product->version); - g_variant_dict_insert (&dict, "arch", "s", product->arch); - g_variant_dict_insert (&dict, "status", "s", product->status); - g_variant_dict_insert (&dict, "starts", "s", product->starts); - g_variant_dict_insert (&dict, "ends", "s", product->ends); - - g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); - } - - return g_variant_builder_end (&builder); - } - - static void - _emit_property_changed (GsdSubscriptionManager *manager, - const gchar *property_name, - GVariant *property_value) -@@ -248,94 +231,114 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err - - if (json_product == NULL) - continue; - if (json_array_get_length (json_product) < 8) { - g_debug ("Unexpected number of array elements in InstalledProducts JSON"); - continue; - } - - product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); - product->product_id = g_strdup (json_array_get_string_element (json_product, 1)); - product->version = g_strdup (json_array_get_string_element (json_product, 2)); - product->arch = g_strdup (json_array_get_string_element (json_product, 3)); - product->status = g_strdup (json_array_get_string_element (json_product, 4)); - product->starts = g_strdup (json_array_get_string_element (json_product, 6)); - product->ends = g_strdup (json_array_get_string_element (json_product, 7)); - - g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); - } - - /* emit notification for g-c-c */ - _emit_property_changed (manager, "InstalledProducts", - _make_installed_products_variant (priv->installed_products)); - - return TRUE; - } - - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; -+ g_autoptr(GVariant) uuid = NULL; -+ const gchar *uuid_txt = NULL; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; -- const gchar *status_txt = NULL; -- g_autoptr(GVariant) val = NULL; -+ g_autoptr(GVariant) status = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; - -- val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -- "GetStatus", -- g_variant_new ("(ss)", -- "", /* assumed as 'now' */ -- "C.UTF-8"), -- G_DBUS_CALL_FLAGS_NONE, -- -1, NULL, error); -- if (val == NULL) -+ uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], -+ "GetUuid", -+ g_variant_new ("(s)", -+ "C.UTF-8"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (uuid == NULL) - return FALSE; -- g_variant_get (val, "(&s)", &json_txt); -+ -+ g_variant_get (uuid, "(&s)", &uuid_txt); -+ -+ status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], -+ "GetStatus", -+ g_variant_new ("(ss)", -+ "", /* assumed as 'now' */ -+ "C.UTF-8"), -+ G_DBUS_CALL_FLAGS_NONE, -+ -1, NULL, error); -+ if (status == NULL) -+ return FALSE; -+ g_variant_get (status, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -- if (!json_object_has_member (json_obj, "status")) { -+ if (!json_object_has_member (json_obj, "valid")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, -- "no Entitlement.GetStatus status in %s", json_txt); -+ "no Entitlement.GetStatus valid in %s", json_txt); - return FALSE; - } - -- status_txt = json_object_get_string_member (json_obj, "status"); -- g_debug ("Entitlement.GetStatus: %s", status_txt); -- priv->subscription_status = _client_subscription_status_from_text (status_txt); -+ gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); -+ -+ if (uuid_txt[0] != '\0') { -+ if (is_valid) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; -+ } else { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ } -+ } else { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ } - - /* emit notification for g-c-c */ - if (priv->subscription_status != priv->subscription_status_last) { - _emit_property_changed (manager, "SubscriptionStatus", - g_variant_new_uint32 (priv->subscription_status)); - } - - return TRUE; - } - - static gboolean - _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], - "GetSyspurpose", - g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) --- -2.30.0 - diff --git a/SOURCES/0007-subman-Force-re-subscribe-if-the-admin-already-subsc.patch b/SOURCES/0007-subman-Force-re-subscribe-if-the-admin-already-subsc.patch deleted file mode 100644 index 73acafa..0000000 --- a/SOURCES/0007-subman-Force-re-subscribe-if-the-admin-already-subsc.patch +++ /dev/null @@ -1,260 +0,0 @@ -From 477dc8accccab568002bd19caa3fbf898bc05aad Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 25 Aug 2020 10:34:03 -0400 -Subject: [PATCH 07/15] subman: Force re-subscribe if the admin already - subscribed - -It's possible for an admin to to half-enroll the system with RHN, -using the CLI tools. - -Meaning, it's possible for them to register the system with the -service, but not attach to a purchased license for the machine, -the, so called, entitlements. - -The subman module always does both halves of the registration process -in lock step. This means, if an admin tries to register using GNOME -while in a half-registered state, subman will fail because the first -step, the registration step, is already finished. - -This commit addresses that problem by trying to unregister up front -before registering. ---- - plugins/subman/gsd-subman-helper.c | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index f84e91bf..3931ef2e 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -51,61 +51,60 @@ _helper_convert_error (const gchar *json_txt, GError **error) - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "no message' in %s", json_txt); - return; - } - message = json_object_get_string_member (json_obj, "message"); - if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED, - message); - return; - } - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - message); - } - - static gboolean - _helper_unregister (GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - -- g_debug ("unregistering"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Unregister", - "com.redhat.RHSM1.Unregister", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "Unregister", - g_variant_new ("(a{sv}s)", - proxy_options, - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - return res != NULL; - } - - static gboolean - _helper_auto_attach (GError **error) - { - const gchar *str = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; -@@ -208,60 +207,61 @@ main (int argc, char *argv[]) - { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &prefix, "Registration server prefix", NULL }, - { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &port, "Registration server port", NULL }, - { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &proxy_server, "Proxy settings", NULL }, - { NULL} - }; - - /* check calling UID */ - if (getuid () != 0 || geteuid () != 0) { - g_printerr ("This program can only be used by the root user\n"); - return G_IO_ERROR_NOT_SUPPORTED; - } - - setlocale (LC_ALL, ""); - locale = setlocale (LC_MESSAGES, NULL); - - g_option_context_add_main_entries (context, options, NULL); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("Failed to parse arguments: %s\n", error->message); - return G_IO_ERROR_NOT_SUPPORTED; - } - - /* uncommon actions */ - if (kind == NULL) { - g_printerr ("No --kind specified\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (g_strcmp0 (kind, "unregister") == 0) { -+ g_debug ("unregistering"); - if (!_helper_unregister (&error)) { - g_printerr ("Failed to Unregister: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - return EXIT_SUCCESS; - } - if (g_strcmp0 (kind, "auto-attach") == 0) { - if (!_helper_auto_attach (&error)) { - g_printerr ("Failed to AutoAttach: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - return EXIT_SUCCESS; - } - - /* connect to abstract socket for reasons */ - if (address == NULL) { - g_printerr ("No --address specified\n"); - return G_IO_ERROR_INVALID_DATA; - } - conn_private = g_dbus_connection_new_for_address_sync (address, - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - NULL, NULL, - &error); - if (conn_private == NULL) { - g_printerr ("Invalid --address specified: %s\n", error->message); - return G_IO_ERROR_INVALID_DATA; - } - proxy = g_dbus_proxy_new_sync (conn_private, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, /* GDBusInterfaceInfo */ -@@ -277,96 +277,103 @@ main (int argc, char *argv[]) - /* no options */ - subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - - /* set registration server */ - if (hostname == NULL || hostname[0] == '\0') - hostname = g_strdup ("subscription.rhsm.redhat.com"); - if (prefix == NULL || prefix[0] == '\0') - prefix = g_strdup ("/subscription"); - if (port == NULL || port[0] == '\0') - port = g_strdup ("443"); - subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); - g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); - g_variant_builder_add (subman_conopts, "{ss}", "port", port); - - /* call into RHSM */ - if (g_strcmp0 (kind, "register-with-key") == 0) { - g_auto(GStrv) activation_keys = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - - if (activation_key == NULL) { - g_printerr ("Required --activation-key\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - -+ g_debug ("trying to unregister in case machine is already registered"); -+ _helper_unregister (NULL); -+ - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, - "RegisterWithActivationKeys", - g_variant_new ("(s^asa{ss}a{ss}s)", - organisation, - activation_keys, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); - return error->code; - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - -- g_debug ("registering using username and password"); - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (password == NULL) { - g_printerr ("Required --password\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } -+ -+ g_debug ("trying to unregister in case machine is already registered"); -+ _helper_unregister (NULL); -+ -+ g_debug ("registering using username and password"); - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", - organisation, - username, - password, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to Register: %s\n", error->message); - return error->code; - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); - return G_IO_ERROR_INVALID_DATA; - } - - /* set the new hostname */ - if (!_helper_save_config ("server.hostname", hostname, &error)) { - g_printerr ("Failed to save hostname: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.prefix", prefix, &error)) { - g_printerr ("Failed to save prefix: %s\n", error->message); --- -2.30.0 - diff --git a/SOURCES/0008-subman-Don-t-send-secrets-through-command-line.patch b/SOURCES/0008-subman-Don-t-send-secrets-through-command-line.patch deleted file mode 100644 index bd85eaf..0000000 --- a/SOURCES/0008-subman-Don-t-send-secrets-through-command-line.patch +++ /dev/null @@ -1,576 +0,0 @@ -From b73800da7f384eea66b6eb67f5f40129f3dfc372 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 25 Aug 2020 16:20:42 -0400 -Subject: [PATCH 08/15] subman: Don't send secrets through command line - -The command line is introspectable with "ps", and it even gets logged -to syslog, so it's not suitable for passing secrets. - -Unfortunately, the user's password is currently passed. - -This commit addresses that problem by passing the password through -stdin, instead. ---- - plugins/subman/gsd-subman-helper.c | 32 ++++++++------ - plugins/subman/gsd-subscription-manager.c | 52 ++++++++++++++++++++--- - plugins/subman/meson.build | 2 +- - 3 files changed, 66 insertions(+), 20 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index 3931ef2e..edf1e41f 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -1,59 +1,61 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes - * - * Licensed under the GNU General Public License Version 2 - * - * 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. - */ - - #include "config.h" - -+ - #include - #include - #include - #include - - #include -+#include - #include - - #define DBUS_TIMEOUT 300000 /* 5 minutes */ - static const char *locale; - - static void - _helper_convert_error (const gchar *json_txt, GError **error) - { - JsonNode *json_root; - JsonObject *json_obj; - const gchar *message; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* this may be plain text or JSON :| */ - if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - json_txt); - return; - } - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "no message' in %s", json_txt); - return; - } -@@ -149,86 +151,82 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Config", - "com.redhat.RHSM1.Config", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - res = g_dbus_proxy_call_sync (proxy, "Set", - g_variant_new ("(svs)", - key, - g_variant_new_string (value), - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - return res != NULL; - } - - int - main (int argc, char *argv[]) - { - g_autofree gchar *activation_key = NULL; - g_autofree gchar *address = NULL; - g_autofree gchar *hostname = NULL; - g_autofree gchar *kind = NULL; - g_autofree gchar *organisation = NULL; -- g_autofree gchar *password = NULL; - g_autofree gchar *port = NULL; - g_autofree gchar *prefix = NULL; - g_autofree gchar *proxy_server = NULL; - g_autofree gchar *username = NULL; - g_autoptr(GDBusConnection) conn_private = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GError) error = NULL; - g_autoptr(GOptionContext) context = g_option_context_new (NULL); - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariantBuilder) subman_conopts = NULL; - g_autoptr(GVariantBuilder) subman_options = NULL; -+ g_autoptr(GInputStream) standard_input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE); - - const GOptionEntry options[] = { - { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &kind, "Kind, e.g. 'username' or 'key'", NULL }, - { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &address, "UNIX address", NULL }, - { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &username, "Username", NULL }, -- { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -- &password, "Password", NULL }, - { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, - &organisation, "Organisation", NULL }, -- { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, -- &activation_key, "Activation keys", NULL }, - { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &hostname, "Registration server hostname", NULL }, - { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &prefix, "Registration server prefix", NULL }, - { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &port, "Registration server port", NULL }, - { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, - &proxy_server, "Proxy settings", NULL }, - { NULL} - }; - - /* check calling UID */ - if (getuid () != 0 || geteuid () != 0) { - g_printerr ("This program can only be used by the root user\n"); - return G_IO_ERROR_NOT_SUPPORTED; - } - - setlocale (LC_ALL, ""); - locale = setlocale (LC_MESSAGES, NULL); - - g_option_context_add_main_entries (context, options, NULL); - if (!g_option_context_parse (context, &argc, &argv, &error)) { - g_printerr ("Failed to parse arguments: %s\n", error->message); - return G_IO_ERROR_NOT_SUPPORTED; - } - - /* uncommon actions */ - if (kind == NULL) { - g_printerr ("No --kind specified\n"); - return G_IO_ERROR_INVALID_DATA; -@@ -267,109 +265,117 @@ main (int argc, char *argv[]) - NULL, /* GDBusInterfaceInfo */ - NULL, /* name */ - "/com/redhat/RHSM1/Register", - "com.redhat.RHSM1.Register", - NULL, &error); - if (proxy == NULL) { - g_printerr ("Count not contact RHSM: %s\n", error->message); - return G_IO_ERROR_NOT_FOUND; - } - - /* no options */ - subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - - /* set registration server */ - if (hostname == NULL || hostname[0] == '\0') - hostname = g_strdup ("subscription.rhsm.redhat.com"); - if (prefix == NULL || prefix[0] == '\0') - prefix = g_strdup ("/subscription"); - if (port == NULL || port[0] == '\0') - port = g_strdup ("443"); - subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); - g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); - g_variant_builder_add (subman_conopts, "{ss}", "port", port); - - /* call into RHSM */ - if (g_strcmp0 (kind, "register-with-key") == 0) { - g_auto(GStrv) activation_keys = NULL; - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; -+ gchar activation_key[PIPE_BUF + 1] = ""; - -- if (activation_key == NULL) { -- g_printerr ("Required --activation-key\n"); -- return G_IO_ERROR_INVALID_DATA; -- } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - -+ g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local); -+ -+ if (error_local != NULL) { -+ g_printerr ("Could not read activation key: %s\n", error_local->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, - "RegisterWithActivationKeys", - g_variant_new ("(s^asa{ss}a{ss}s)", - organisation, - activation_keys, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); - return error->code; - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; -+ gchar password[PIPE_BUF + 1] = ""; - - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } -- if (password == NULL) { -- g_printerr ("Required --password\n"); -- return G_IO_ERROR_INVALID_DATA; -- } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - -+ g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local); -+ -+ if (error_local != NULL) { -+ g_printerr ("Could not read password: %s\n", error_local->message); -+ return G_IO_ERROR_INVALID_DATA; -+ } -+ - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - - g_debug ("registering using username and password"); - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", - organisation, - username, - password, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); - g_printerr ("Failed to Register: %s\n", error->message); - return error->code; - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); - return G_IO_ERROR_INVALID_DATA; - } - - /* set the new hostname */ - if (!_helper_save_config ("server.hostname", hostname, &error)) { - g_printerr ("Failed to save hostname: %s\n", error->message); -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index e2c16056..0838d490 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -1,53 +1,54 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes - * Copyright (C) 2019 Kalev Lember - * - * 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, see . - * - */ - - #include "config.h" - - #include -+#include - #include - #include - #include - #include - - #include "gnome-settings-profile.h" - #include "gsd-subman-common.h" - #include "gsd-subscription-manager.h" - - #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" - #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" - #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" - - #define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" - #define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" - #define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" - - static const gchar introspection_xml[] = - "" - " " - " " - " " - " " - " " - " " - " " - " " - ""; - - #define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) -@@ -517,129 +518,168 @@ _client_maybe__show_notification (GsdSubscriptionManager *manager) - } - } - - /* nag again */ - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - } - - static gboolean - _client_register_with_keys (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *activation_key, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-key", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, -- "--activation-key", activation_key, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } -- if (!_client_subprocess_wait_check (subprocess, error)) -+ -+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); - return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ g_bytes_get_size (stderr_buf), -+ g_bytes_get_data (stderr_buf, NULL)); -+ } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - - /* success */ - return TRUE; - } - - static gboolean - _client_register (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *username, - const gchar *password, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; - - /* fallback */ - if (organisation == NULL) - organisation = ""; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, -+ error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-username", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - "--username", username, -- "--password", password, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } -- if (!_client_subprocess_wait_check (subprocess, error)) -+ -+ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); - return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ g_bytes_get_size (stderr_buf), -+ g_bytes_get_data (stderr_buf, NULL)); -+ } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_unregister (GsdSubscriptionManager *manager, GError **error) - { - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } -diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build -index bfd073b6..e4b4589d 100644 ---- a/plugins/subman/meson.build -+++ b/plugins/subman/meson.build -@@ -22,35 +22,35 @@ executable( - c_args: cflags, - install: true, - install_rpath: gsd_pkglibdir, - install_dir: gsd_libexecdir - ) - - # .Register needs to be called from root as subman can't do PolicyKit... - policy = 'org.gnome.settings-daemon.plugins.subman.policy' - policy_in = configure_file( - input: policy + '.in.in', - output: policy + '.in', - configuration: plugins_conf - ) - - i18n.merge_file( - policy, - input: policy_in, - output: policy, - po_dir: po_dir, - install: true, - install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions') - ) - - install_data('org.gnome.settings-daemon.plugins.subman.rules', - install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d')) - - executable( - 'gsd-subman-helper', - 'gsd-subman-helper.c', - include_directories: top_inc, -- dependencies: [gio_dep, jsonglib_dep], -+ dependencies: [gio_dep, gio_unix_dep, jsonglib_dep], - install: true, - install_rpath: gsd_pkglibdir, - install_dir: gsd_libexecdir - ) --- -2.30.0 - diff --git a/SOURCES/0009-subman-Don-t-treat-failure-to-attach-as-fatal.patch b/SOURCES/0009-subman-Don-t-treat-failure-to-attach-as-fatal.patch deleted file mode 100644 index 5edb2ae..0000000 --- a/SOURCES/0009-subman-Don-t-treat-failure-to-attach-as-fatal.patch +++ /dev/null @@ -1,310 +0,0 @@ -From 1255b2b83284d262f6b8c3ceb23d499ddbf77d48 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Thu, 21 Jan 2021 09:52:19 -0500 -Subject: [PATCH 09/15] subman: Don't treat failure to attach as fatal - -Many organizations don't require specific subscriptions to get -updates (called "simple content access"). At the moment, -those systems get an error when registering. - -This commit quiets the error. ---- - plugins/subman/gsd-subman-helper.c | 46 ++++++++++++++++++++++++------ - 1 file changed, 37 insertions(+), 9 deletions(-) - -diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c -index edf1e41f..53a4d56b 100644 ---- a/plugins/subman/gsd-subman-helper.c -+++ b/plugins/subman/gsd-subman-helper.c -@@ -25,145 +25,169 @@ - #include - #include - #include - #include - - #include - #include - #include - - #define DBUS_TIMEOUT 300000 /* 5 minutes */ - static const char *locale; - - static void - _helper_convert_error (const gchar *json_txt, GError **error) - { - JsonNode *json_root; - JsonObject *json_obj; - const gchar *message; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* this may be plain text or JSON :| */ - if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - json_txt); - return; - } - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -+ if (json_object_has_member (json_obj, "severity")) { -+ const gchar *severity; -+ -+ /* warnings are non-fatal so we ignore them -+ */ -+ severity = json_object_get_string_member (json_obj, "severity"); -+ if (g_strstr_len (severity, -1, "warning") != NULL) { -+ return; -+ } -+ } -+ - if (!json_object_has_member (json_obj, "message")) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_DATA, - "no message' in %s", json_txt); - return; - } - message = json_object_get_string_member (json_obj, "message"); - if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED, - message); - return; - } - g_set_error_literal (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - message); - } - - static gboolean - _helper_unregister (GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Unregister", - "com.redhat.RHSM1.Unregister", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "Unregister", - g_variant_new ("(a{sv}s)", - proxy_options, - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); - return res != NULL; - } - - static gboolean - _helper_auto_attach (GError **error) - { - const gchar *str = NULL; -+ g_autoptr(GError) error_local = NULL; - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariantBuilder) proxy_options = NULL; - g_autoptr(GVariant) res = NULL; - - g_debug ("auto-attaching subscriptions"); - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Attach", - "com.redhat.RHSM1.Attach", -- NULL, error); -+ NULL, &error_local); - if (proxy == NULL) { -- g_prefix_error (error, "Failed to get proxy: "); -+ g_dbus_error_strip_remote_error (error_local); -+ g_propagate_prefixed_error (error, -+ g_steal_pointer (&error_local), -+ "Failed to get proxy: "); - return FALSE; - } - proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); - res = g_dbus_proxy_call_sync (proxy, - "AutoAttach", - g_variant_new ("(sa{sv}s)", - "", /* now? */ - proxy_options, - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, -- NULL, error); -- if (res == NULL) -- return FALSE; -+ NULL, &error_local); -+ if (res == NULL) { -+ g_dbus_error_strip_remote_error (error_local); -+ _helper_convert_error (error_local->message, error); -+ -+ if (*error != NULL) { -+ g_prefix_error (error, "Failed to get proxy: "); -+ return FALSE; -+ } -+ -+ return TRUE; -+ } - g_variant_get (res, "(&s)", &str); - g_debug ("Attach.AutoAttach: %s", str); - return TRUE; - } - - static gboolean - _helper_save_config (const gchar *key, const gchar *value, GError **error) - { - g_autoptr(GDBusProxy) proxy = NULL; - g_autoptr(GVariant) res = NULL; - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, - NULL, - "com.redhat.RHSM1", - "/com/redhat/RHSM1/Config", - "com.redhat.RHSM1.Config", - NULL, error); - if (proxy == NULL) { - g_prefix_error (error, "Failed to get proxy: "); - return FALSE; - } - res = g_dbus_proxy_call_sync (proxy, "Set", - g_variant_new ("(svs)", - key, - g_variant_new_string (value), - locale), - G_DBUS_CALL_FLAGS_NONE, - DBUS_TIMEOUT, - NULL, error); -@@ -298,105 +322,109 @@ main (int argc, char *argv[]) - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - - g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local); - - if (error_local != NULL) { - g_printerr ("Could not read activation key: %s\n", error_local->message); - return G_IO_ERROR_INVALID_DATA; - } - - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - - g_debug ("registering using activation key"); - activation_keys = g_strsplit (activation_key, ",", -1); - res = g_dbus_proxy_call_sync (proxy, - "RegisterWithActivationKeys", - g_variant_new ("(s^asa{ss}a{ss}s)", - organisation, - activation_keys, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); -- g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -- return error->code; -+ if (error != NULL) { -+ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); -+ return error->code; -+ } - } - } else if (g_strcmp0 (kind, "register-with-username") == 0) { - g_autoptr(GError) error_local = NULL; - g_autoptr(GVariant) res = NULL; - gchar password[PIPE_BUF + 1] = ""; - - if (username == NULL) { - g_printerr ("Required --username\n"); - return G_IO_ERROR_INVALID_DATA; - } - if (organisation == NULL) { - g_printerr ("Required --organisation\n"); - return G_IO_ERROR_INVALID_DATA; - } - - g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local); - - if (error_local != NULL) { - g_printerr ("Could not read password: %s\n", error_local->message); - return G_IO_ERROR_INVALID_DATA; - } - - g_debug ("trying to unregister in case machine is already registered"); - _helper_unregister (NULL); - - g_debug ("registering using username and password"); - res = g_dbus_proxy_call_sync (proxy, - "Register", - g_variant_new ("(sssa{ss}a{ss}s)", - organisation, - username, - password, - subman_options, - subman_conopts, - locale), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - DBUS_TIMEOUT, - NULL, &error_local); - if (res == NULL) { - g_dbus_error_strip_remote_error (error_local); - _helper_convert_error (error_local->message, &error); -- g_printerr ("Failed to Register: %s\n", error->message); -- return error->code; -+ if (error != NULL) { -+ g_printerr ("Failed to Register: %s\n", error->message); -+ return error->code; -+ } - } - } else { - g_printerr ("Invalid --kind specified: %s\n", kind); - return G_IO_ERROR_INVALID_DATA; - } - - /* set the new hostname */ - if (!_helper_save_config ("server.hostname", hostname, &error)) { - g_printerr ("Failed to save hostname: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.prefix", prefix, &error)) { - g_printerr ("Failed to save prefix: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - if (!_helper_save_config ("server.port", port, &error)) { - g_printerr ("Failed to save port: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - - /* wait for rhsmd to notice the new config */ - g_usleep (G_USEC_PER_SEC * 5); - - /* auto-attach */ - if (!_helper_auto_attach (&error)) { - g_printerr ("Failed to AutoAttach: %s\n", error->message); - return G_IO_ERROR_NOT_INITIALIZED; - } - - return EXIT_SUCCESS; --- -2.30.0 - diff --git a/SOURCES/0010-subman-Add-new-no-installed-products-state.patch b/SOURCES/0010-subman-Add-new-no-installed-products-state.patch deleted file mode 100644 index efe9990..0000000 --- a/SOURCES/0010-subman-Add-new-no-installed-products-state.patch +++ /dev/null @@ -1,427 +0,0 @@ -From d53c27802c69773d63d108f57912035fd3caabf9 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:24:36 -0500 -Subject: [PATCH 10/15] subman: Add new no-installed-products state - -It's possible, though unlikley, the system has -no packages installed from Red Hat supported package sets. - -This commit adds a new state to track that situation. ---- - plugins/subman/gsd-subman-common.c | 2 ++ - plugins/subman/gsd-subman-common.h | 1 + - plugins/subman/gsd-subscription-manager.c | 17 +++++++---------- - 3 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c -index e515131e..eef5175d 100644 ---- a/plugins/subman/gsd-subman-common.c -+++ b/plugins/subman/gsd-subman-common.c -@@ -5,32 +5,34 @@ - * 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, see . - * - */ - - #include "config.h" - - #include "gsd-subman-common.h" - - const gchar * - gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) - { - if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID) - return "valid"; - if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) - return "invalid"; - if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) - return "disabled"; - if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) - return "partially-valid"; -+ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS) -+ return "no-installed-products"; - return "unknown"; - } -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index fccf9f6a..f8a3d9f4 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -3,38 +3,39 @@ - * Copyright (C) 2019 Richard Hughes - * - * 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, see . - * - */ - - #ifndef __GSD_SUBMAN_COMMON_H - #define __GSD_SUBMAN_COMMON_H - - #include - - G_BEGIN_DECLS - - typedef enum { - GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, - GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, - GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, - GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST - } GsdSubmanSubscriptionStatus; - - const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); - - G_END_DECLS - - #endif /* __GSD_SUBMAN_COMMON_H */ -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 0838d490..46f8d35c 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -242,60 +242,67 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err - product->version = g_strdup (json_array_get_string_element (json_product, 2)); - product->arch = g_strdup (json_array_get_string_element (json_product, 3)); - product->status = g_strdup (json_array_get_string_element (json_product, 4)); - product->starts = g_strdup (json_array_get_string_element (json_product, 6)); - product->ends = g_strdup (json_array_get_string_element (json_product, 7)); - - g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); - } - - /* emit notification for g-c-c */ - _emit_property_changed (manager, "InstalledProducts", - _make_installed_products_variant (priv->installed_products)); - - return TRUE; - } - - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) uuid = NULL; - const gchar *uuid_txt = NULL; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) status = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; -+ if (!_client_installed_products_update (manager, error)) -+ goto out; -+ -+ if (priv->installed_products->len == 0) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; -+ goto out; -+ } - - uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], - "GetUuid", - g_variant_new ("(s)", - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (uuid == NULL) - return FALSE; - - g_variant_get (uuid, "(&s)", &uuid_txt); - - status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (status == NULL) - return FALSE; - g_variant_get (status, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); - if (!json_object_has_member (json_obj, "valid")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "no Entitlement.GetStatus valid in %s", json_txt); -@@ -563,62 +570,60 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - - if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { - g_prefix_error (error, "failed to run pkexec: "); - return FALSE; - } - - rc = g_subprocess_get_exit_status (subprocess); - if (rc != 0) { - if (g_bytes_get_size (stderr_buf) == 0) { - g_set_error_literal (error, G_IO_ERROR, rc, - "Failed to run helper without stderr"); - return FALSE; - } - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", - g_bytes_get_size (stderr_buf), - g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - _client_maybe__show_notification (manager); - - /* success */ - return TRUE; - } - - static gboolean - _client_register (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *username, - const gchar *password, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; - g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); - g_autoptr(GBytes) stderr_buf = NULL; - gint rc; - - /* fallback */ - if (organisation == NULL) - organisation = ""; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, -@@ -632,62 +637,60 @@ _client_register (GsdSubscriptionManager *manager, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - - if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { - g_prefix_error (error, "failed to run pkexec: "); - return FALSE; - } - - rc = g_subprocess_get_exit_status (subprocess); - if (rc != 0) { - if (g_bytes_get_size (stderr_buf) == 0) { - g_set_error_literal (error, G_IO_ERROR, rc, - "Failed to run helper without stderr"); - return FALSE; - } - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", - g_bytes_get_size (stderr_buf), - g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_unregister (GsdSubscriptionManager *manager, GError **error) - { - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - return TRUE; -@@ -714,64 +717,60 @@ _client_update_config (GsdSubscriptionManager *manager, GError **error) - dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); - val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); - if (val_server != NULL) { - g_variant_iter_init (&iter, val_server); - while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { - g_debug ("%s=%s", key, value); - g_hash_table_insert (priv->config, - g_steal_pointer (&key), - g_steal_pointer (&value)); - } - } - return TRUE; - } - - static void - _subman_proxy_signal_cb (GDBusProxy *proxy, - const gchar *sender_name, - const gchar *signal_name, - GVariant *parameters, - GsdSubscriptionManager *manager) - { - g_autoptr(GError) error = NULL; - if (!_client_syspurpose_update (manager, &error)) { - g_warning ("failed to update syspurpose: %s", error->message); - g_clear_error (&error); - } - if (!_client_subscription_status_update (manager, &error)) { - g_warning ("failed to update subscription status: %s", error->message); - g_clear_error (&error); - } -- if (!_client_installed_products_update (manager, &error)) { -- g_warning ("failed to update installed products: %s", error->message); -- g_clear_error (&error); -- } - _client_maybe__show_notification (manager); - } - - static void - _client_unload (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) - g_clear_object (&priv->proxies[i]); - g_hash_table_unref (priv->config); - } - - static const gchar * - _rhsm_interface_to_string (_RhsmInterface kind) - { - if (kind == _RHSM_INTERFACE_CONFIG) - return "Config"; - if (kind == _RHSM_INTERFACE_REGISTER_SERVER) - return "RegisterServer"; - if (kind == _RHSM_INTERFACE_ATTACH) - return "Attach"; - if (kind == _RHSM_INTERFACE_ENTITLEMENT) - return "Entitlement"; - if (kind == _RHSM_INTERFACE_PRODUCTS) - return "Products"; - if (kind == _RHSM_INTERFACE_CONSUMER) - return "Consumer"; - if (kind == _RHSM_INTERFACE_SYSPURPOSE) - return "Syspurpose"; - return NULL; -@@ -782,62 +781,60 @@ _client_load (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - - priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); - - /* connect to all the interfaces on the *different* objects :| */ - for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { - const gchar *kind = _rhsm_interface_to_string (i); - g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); - g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); - priv->proxies[i] = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "com.redhat.RHSM1", - opath, iface, - NULL, - error); - if (priv->proxies[i] == NULL) - return FALSE; - /* we want to get notified if the status of the system changes */ - g_signal_connect (priv->proxies[i], "g-signal", - G_CALLBACK (_subman_proxy_signal_cb), manager); - } - - /* get initial status */ - if (!_client_update_config (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; -- if (!_client_installed_products_update (manager, error)) -- return FALSE; - if (!_client_syspurpose_update (manager, error)) - return FALSE; - - /* success */ - return TRUE; - } - - gboolean - gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) - { - gboolean ret; - g_debug ("Starting subscription manager"); - gnome_settings_profile_start (NULL); - ret = _client_load (manager, error); - _client_maybe__show_notification (manager); - gnome_settings_profile_end (NULL); - return ret; - } - - void - gsd_subscription_manager_stop (GsdSubscriptionManager *manager) - { - g_debug ("Stopping subscription manager"); - _client_unload (manager); - } - - static void - gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) - { - GObjectClass *object_class = G_OBJECT_CLASS (klass); --- -2.30.0 - diff --git a/SOURCES/0011-subman-Fix-some-build-warnings.patch b/SOURCES/0011-subman-Fix-some-build-warnings.patch deleted file mode 100644 index 2d70f9b..0000000 --- a/SOURCES/0011-subman-Fix-some-build-warnings.patch +++ /dev/null @@ -1,146 +0,0 @@ -From 432850e943d72daedb1d352a0332d3fdee6078e2 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:26:40 -0500 -Subject: [PATCH 11/15] subman: Fix some build warnings - ---- - plugins/subman/gsd-subscription-manager.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 46f8d35c..1f9ca447 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -561,62 +561,62 @@ _client_register_with_keys (GsdSubscriptionManager *manager, - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-key", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - - if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { - g_prefix_error (error, "failed to run pkexec: "); - return FALSE; - } - - rc = g_subprocess_get_exit_status (subprocess); - if (rc != 0) { - if (g_bytes_get_size (stderr_buf) == 0) { - g_set_error_literal (error, G_IO_ERROR, rc, - "Failed to run helper without stderr"); - return FALSE; - } - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", -- g_bytes_get_size (stderr_buf), -- g_bytes_get_data (stderr_buf, NULL)); -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - - /* success */ - return TRUE; - } - - static gboolean - _client_register (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *username, - const gchar *password, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; - g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); - g_autoptr(GBytes) stderr_buf = NULL; - gint rc; - - /* fallback */ - if (organisation == NULL) - organisation = ""; -@@ -628,62 +628,62 @@ _client_register (GsdSubscriptionManager *manager, - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, - error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-username", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, - "--username", username, - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - - if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { - g_prefix_error (error, "failed to run pkexec: "); - return FALSE; - } - - rc = g_subprocess_get_exit_status (subprocess); - if (rc != 0) { - if (g_bytes_get_size (stderr_buf) == 0) { - g_set_error_literal (error, G_IO_ERROR, rc, - "Failed to run helper without stderr"); - return FALSE; - } - - g_set_error (error, G_IO_ERROR, rc, - "%.*s", -- g_bytes_get_size (stderr_buf), -- g_bytes_get_data (stderr_buf, NULL)); -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); - } - - /* FIXME: also do on error? */ - if (!_client_register_stop (manager, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - - static gboolean - _client_unregister (GsdSubscriptionManager *manager, GError **error) - { - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) --- -2.30.0 - diff --git a/SOURCES/0012-subman-Add-DBus-API-to-subscribe-for-updates-on-alre.patch b/SOURCES/0012-subman-Add-DBus-API-to-subscribe-for-updates-on-alre.patch deleted file mode 100644 index 30758fb..0000000 --- a/SOURCES/0012-subman-Add-DBus-API-to-subscribe-for-updates-on-alre.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 3bb3b2b09d34deafadd3cfe3355137afab20cb23 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:27:42 -0500 -Subject: [PATCH 12/15] subman: Add DBus API to subscribe for updates on - already registered system - -It's possible an admin may have registered their system without -attaching any subscriptions to it. - -At the moment, gnome-settings-daemon only provides a way to register -and subscribe in one step. - -This commit adds an API to support doing the last half of the process -on its own. ---- - plugins/subman/gsd-subscription-manager.c | 51 +++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 1f9ca447..705f8b11 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -19,60 +19,61 @@ - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - - #include "gnome-settings-profile.h" - #include "gsd-subman-common.h" - #include "gsd-subscription-manager.h" - - #define GSD_DBUS_NAME "org.gnome.SettingsDaemon" - #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" - #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" - - #define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" - #define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" - #define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" - - static const gchar introspection_xml[] = - "" - " " - " " - " " - " " - " " -+" " - " " - " " - " " - ""; - - #define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) - - typedef enum { - _RHSM_INTERFACE_CONFIG, - _RHSM_INTERFACE_REGISTER_SERVER, - _RHSM_INTERFACE_ATTACH, - _RHSM_INTERFACE_ENTITLEMENT, - _RHSM_INTERFACE_PRODUCTS, - _RHSM_INTERFACE_CONSUMER, - _RHSM_INTERFACE_SYSPURPOSE, - _RHSM_INTERFACE_LAST - } _RhsmInterface; - - struct GsdSubscriptionManagerPrivate - { - /* D-Bus */ - guint name_id; - GDBusNodeInfo *introspection_data; - GDBusConnection *connection; - GCancellable *bus_cancellable; - - GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; - GHashTable *config; /* str:str */ - GPtrArray *installed_products; - gchar *address; -@@ -669,60 +670,104 @@ _client_register (GsdSubscriptionManager *manager, - } - - static gboolean - _client_unregister (GsdSubscriptionManager *manager, GError **error) - { - g_autoptr(GSubprocess) subprocess = NULL; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "unregister", - NULL); - if (subprocess == NULL) { - g_prefix_error (error, "failed to find pkexec: "); - return FALSE; - } - if (!_client_subprocess_wait_check (subprocess, error)) - return FALSE; - if (!_client_subscription_status_update (manager, error)) - return FALSE; - if (!_client_installed_products_update (manager, error)) - return FALSE; - _client_maybe__show_notification (manager); - return TRUE; - } - -+static gboolean -+_client_attach (GsdSubscriptionManager *manager, -+ GError **error) -+{ -+ g_autoptr(GSubprocess) subprocess = NULL; -+ g_autoptr(GBytes) stderr_buf = NULL; -+ gint rc; -+ -+ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); -+ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, -+ error, -+ "pkexec", LIBEXECDIR "/gsd-subman-helper", -+ "--kind", "auto-attach", -+ NULL); -+ if (subprocess == NULL) { -+ g_prefix_error (error, "failed to find pkexec: "); -+ return FALSE; -+ } -+ -+ if (!g_subprocess_communicate (subprocess, NULL, NULL, NULL, &stderr_buf, error)) { -+ g_prefix_error (error, "failed to run pkexec: "); -+ return FALSE; -+ } -+ -+ rc = g_subprocess_get_exit_status (subprocess); -+ if (rc != 0) { -+ if (g_bytes_get_size (stderr_buf) == 0) { -+ g_set_error_literal (error, G_IO_ERROR, rc, -+ "Failed to run helper without stderr"); -+ return FALSE; -+ } -+ -+ g_set_error (error, G_IO_ERROR, rc, -+ "%.*s", -+ (int) g_bytes_get_size (stderr_buf), -+ (char *) g_bytes_get_data (stderr_buf, NULL)); -+ } -+ -+ if (!_client_subscription_status_update (manager, error)) -+ return FALSE; -+ _client_maybe__show_notification (manager); -+ return TRUE; -+} -+ - static gboolean - _client_update_config (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) val = NULL; - g_autoptr(GVariant) val_server = NULL; - g_autoptr(GVariantDict) dict = NULL; - GVariantIter iter; - gchar *key; - gchar *value; - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], - "GetAll", - g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); - val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); - if (val_server != NULL) { - g_variant_iter_init (&iter, val_server); - while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { - g_debug ("%s=%s", key, value); - g_hash_table_insert (priv->config, - g_steal_pointer (&key), - g_steal_pointer (&value)); - } - } - return TRUE; -@@ -1002,60 +1047,66 @@ handle_method_call (GDBusConnection *connection, - g_dbus_method_invocation_return_gerror (invocation, error); - return; - } - } else if (g_strcmp0 (kind, "key") == 0) { - const gchar *activation_key = NULL; - g_variant_dict_lookup (dict, "hostname", "&s", &hostname); - g_variant_dict_lookup (dict, "organisation", "&s", &organisation); - g_variant_dict_lookup (dict, "activation-key", "&s", &activation_key); - if (!_client_register_with_keys (manager, - hostname, - organisation, - activation_key, - &error)) { - g_dbus_method_invocation_return_gerror (invocation, error); - return; - } - } else { - g_dbus_method_invocation_return_error_literal (invocation, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid kind specified"); - - return; - } - g_dbus_method_invocation_return_value (invocation, NULL); - } else if (g_strcmp0 (method_name, "Unregister") == 0) { - if (!_client_unregister (manager, &error)) { - g_dbus_method_invocation_return_gerror (invocation, error); - return; - } - g_dbus_method_invocation_return_value (invocation, NULL); -+ } else if (g_strcmp0 (method_name, "Attach") == 0) { -+ if (!_client_attach (manager, &error)) { -+ g_dbus_method_invocation_return_gerror (invocation, error); -+ return; -+ } -+ g_dbus_method_invocation_return_value (invocation, NULL); - } else { - g_assert_not_reached (); - } - } - - static GVariant * - handle_get_property (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GError **error, gpointer user_data) - { - GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); - GsdSubscriptionManagerPrivate *priv = manager->priv; - - if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "No such interface: %s", interface_name); - return NULL; - } - - if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) - return g_variant_new_uint32 (priv->subscription_status); - - if (g_strcmp0 (property_name, "InstalledProducts") == 0) - return _make_installed_products_variant (priv->installed_products); - - g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, - "Failed to get property: %s", property_name); --- -2.30.0 - diff --git a/SOURCES/0013-subman-Improve-subscription-status-handling.patch b/SOURCES/0013-subman-Improve-subscription-status-handling.patch deleted file mode 100644 index 40d6c68..0000000 --- a/SOURCES/0013-subman-Improve-subscription-status-handling.patch +++ /dev/null @@ -1,141 +0,0 @@ -From d9eb6331efa92cd28a8ba3ccc1665c3744296465 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:34:03 -0500 -Subject: [PATCH 13/15] subman: Improve subscription status handling - -This commit improves how subscription-manager status is -parsed to give more detailed information about subscription -state. ---- - plugins/subman/gsd-subscription-manager.c | 33 +++++++++++++++++++---- - 1 file changed, 28 insertions(+), 5 deletions(-) - -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 705f8b11..6d80bfa9 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -262,93 +262,116 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) uuid = NULL; - const gchar *uuid_txt = NULL; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) status = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; - if (!_client_installed_products_update (manager, error)) - goto out; - - if (priv->installed_products->len == 0) { - priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; - goto out; - } - - uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], - "GetUuid", - g_variant_new ("(s)", - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (uuid == NULL) - return FALSE; - - g_variant_get (uuid, "(&s)", &uuid_txt); - -+ if (uuid_txt[0] == '\0') { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; -+ goto out; -+ } -+ - status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (status == NULL) - return FALSE; - g_variant_get (status, "(&s)", &json_txt); - g_debug ("Entitlement.GetStatus JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; - json_root = json_parser_get_root (json_parser); - json_obj = json_node_get_object (json_root); -+ -+ const gchar *status_id = NULL; -+ -+ if (json_object_has_member (json_obj, "status_id")) { -+ status_id = json_object_get_string_member (json_obj, "status_id"); -+ } -+ - if (!json_object_has_member (json_obj, "valid")) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "no Entitlement.GetStatus valid in %s", json_txt); - return FALSE; - } - - gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); - -- if (uuid_txt[0] != '\0') { -- if (is_valid) { -+ if (is_valid) { -+ if (g_strcmp0 (status_id, "disabled") != 0) { - priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; - } else { -- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; -+ } -+ goto out; -+ } -+ -+ for (guint i = 0; i < priv->installed_products->len; i++) { -+ ProductData *product = g_ptr_array_index (priv->installed_products, i); -+ -+ if (g_strcmp0 (product->status, "subscribed") == 0) { -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; -+ goto out; - } -- } else { -- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - } - -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; -+ -+out: - /* emit notification for g-c-c */ - if (priv->subscription_status != priv->subscription_status_last) { - _emit_property_changed (manager, "SubscriptionStatus", - g_variant_new_uint32 (priv->subscription_status)); - } - - return TRUE; - } - - static gboolean - _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) val = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], - "GetSyspurpose", - g_variant_new ("(s)", "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (val == NULL) - return FALSE; - g_variant_get (val, "(&s)", &json_txt); - g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); - if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) - return FALSE; --- -2.30.0 - diff --git a/SOURCES/0014-subman-Drop-LAST-from-status-enum.patch b/SOURCES/0014-subman-Drop-LAST-from-status-enum.patch deleted file mode 100644 index 4f5c99e..0000000 --- a/SOURCES/0014-subman-Drop-LAST-from-status-enum.patch +++ /dev/null @@ -1,56 +0,0 @@ -From a78b25b9507edb958a46779f2bb808bf678fa4a7 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 11:55:19 -0500 -Subject: [PATCH 14/15] subman: Drop "LAST" from status enum - -It's unused, so get rid of it. ---- - plugins/subman/gsd-subman-common.h | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index f8a3d9f4..88226564 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -4,38 +4,37 @@ - * - * 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, see . - * - */ - - #ifndef __GSD_SUBMAN_COMMON_H - #define __GSD_SUBMAN_COMMON_H - - #include - - G_BEGIN_DECLS - - typedef enum { - GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, - GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, - GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, -- GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST - } GsdSubmanSubscriptionStatus; - - const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); - - G_END_DECLS - - #endif /* __GSD_SUBMAN_COMMON_H */ --- -2.30.0 - diff --git a/SOURCES/0015-subman-Clean-up-notification-behavior.patch b/SOURCES/0015-subman-Clean-up-notification-behavior.patch deleted file mode 100644 index 96585cd..0000000 --- a/SOURCES/0015-subman-Clean-up-notification-behavior.patch +++ /dev/null @@ -1,419 +0,0 @@ -From 3412be1f63df2a5967ef92c27028368df1646b5c Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 24 Jan 2021 12:41:20 -0500 -Subject: [PATCH 15/15] subman: Clean up notification behavior - -Notifications were only displayed for some status transitions. - -This commit introduces some booleans based on the old and new -statuses to make the code clearer and to make it easier to hit -all the cases. ---- - plugins/subman/gsd-subman-common.h | 1 + - plugins/subman/gsd-subscription-manager.c | 141 ++++++++++++++++++---- - 2 files changed, 120 insertions(+), 22 deletions(-) - -diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h -index 88226564..9397dbe4 100644 ---- a/plugins/subman/gsd-subman-common.h -+++ b/plugins/subman/gsd-subman-common.h -@@ -1,40 +1,41 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2019 Richard Hughes - * - * 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, see . - * - */ - - #ifndef __GSD_SUBMAN_COMMON_H - #define __GSD_SUBMAN_COMMON_H - - #include - - G_BEGIN_DECLS - - typedef enum { -+ GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ = -1, - GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, - GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, - GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, - GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, - } GsdSubmanSubscriptionStatus; - - const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); - - G_END_DECLS - - #endif /* __GSD_SUBMAN_COMMON_H */ -diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c -index 6d80bfa9..aaccbbc6 100644 ---- a/plugins/subman/gsd-subscription-manager.c -+++ b/plugins/subman/gsd-subscription-manager.c -@@ -243,60 +243,61 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err - product->version = g_strdup (json_array_get_string_element (json_product, 2)); - product->arch = g_strdup (json_array_get_string_element (json_product, 3)); - product->status = g_strdup (json_array_get_string_element (json_product, 4)); - product->starts = g_strdup (json_array_get_string_element (json_product, 6)); - product->ends = g_strdup (json_array_get_string_element (json_product, 7)); - - g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); - } - - /* emit notification for g-c-c */ - _emit_property_changed (manager, "InstalledProducts", - _make_installed_products_variant (priv->installed_products)); - - return TRUE; - } - - static gboolean - _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GVariant) uuid = NULL; - const gchar *uuid_txt = NULL; - JsonNode *json_root; - JsonObject *json_obj; - const gchar *json_txt = NULL; - g_autoptr(GVariant) status = NULL; - g_autoptr(JsonParser) json_parser = json_parser_new (); - - /* save old value */ - priv->subscription_status_last = priv->subscription_status; -+ - if (!_client_installed_products_update (manager, error)) - goto out; - - if (priv->installed_products->len == 0) { - priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; - goto out; - } - - uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], - "GetUuid", - g_variant_new ("(s)", - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, - -1, NULL, error); - if (uuid == NULL) - return FALSE; - - g_variant_get (uuid, "(&s)", &uuid_txt); - - if (uuid_txt[0] == '\0') { - priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; - goto out; - } - - status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], - "GetStatus", - g_variant_new ("(ss)", - "", /* assumed as 'now' */ - "C.UTF-8"), - G_DBUS_CALL_FLAGS_NONE, -@@ -485,109 +486,203 @@ typedef enum { - static void - _show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - switch (notify_kind) { - case _NOTIFY_EXPIRED: - notify_notification_close (priv->notification_registered, NULL); - notify_notification_close (priv->notification_registration_required, NULL); - notify_notification_show (priv->notification_expired, NULL); - break; - case _NOTIFY_REGISTRATION_REQUIRED: - notify_notification_close (priv->notification_registered, NULL); - notify_notification_close (priv->notification_expired, NULL); - notify_notification_show (priv->notification_registration_required, NULL); - break; - case _NOTIFY_REGISTERED: - notify_notification_close (priv->notification_expired, NULL); - notify_notification_close (priv->notification_registration_required, NULL); - notify_notification_show (priv->notification_registered, NULL); - break; - default: - break; - } - g_timer_reset (priv->timer_last_notified); - } - - static void - _client_maybe__show_notification (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; -+ gboolean was_read, was_registered, had_subscriptions, needed_subscriptions; -+ gboolean is_read, is_registered, has_subscriptions, needs_subscriptions; -+ -+ switch (priv->subscription_status_last) { -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: -+ was_read = FALSE; -+ was_registered = FALSE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: -+ was_read = TRUE; -+ was_registered = FALSE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = TRUE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = FALSE; -+ had_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: -+ was_read = TRUE; -+ was_registered = TRUE; -+ needed_subscriptions = TRUE; -+ had_subscriptions = FALSE; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: -+ was_read = TRUE; -+ was_registered = FALSE; -+ needed_subscriptions = FALSE; -+ had_subscriptions = FALSE; -+ break; -+ } -+ -+ switch (priv->subscription_status) { -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: -+ is_read = FALSE; -+ is_registered = FALSE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: -+ is_read = TRUE; -+ is_registered = FALSE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = TRUE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = TRUE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: -+ is_read = TRUE; -+ is_registered = TRUE; -+ needs_subscriptions = FALSE; -+ has_subscriptions = FALSE; -+ break; -+ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: -+ is_read = TRUE; -+ is_registered = FALSE; -+ needs_subscriptions = FALSE; -+ has_subscriptions = FALSE; -+ break; -+ } - - /* startup */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ if (!was_read && is_read && priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } - - /* something changed */ -- if (priv->subscription_status_last != priv->subscription_status) { -+ if (was_read && is_read && priv->subscription_status_last != priv->subscription_status) { - g_debug ("transisition from subscription status '%s' to '%s'", - gsd_subman_subscription_status_to_string (priv->subscription_status_last), - gsd_subman_subscription_status_to_string (priv->subscription_status)); - -- /* needs registration */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { -- _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); -+ /* needs subscription */ -+ if (is_registered && needs_subscriptions && !has_subscriptions) { -+ _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - - /* was unregistered */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { -+ if (was_registered && !is_registered) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } - -- /* registered */ -- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && -- g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { -- _show_notification (manager, _NOTIFY_REGISTERED); -- return; -+ /* just registered */ -+ if (!was_registered && is_registered) { -+ if (!needs_subscriptions || has_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ } -+ -+ /* subscriptions changed */ -+ if (was_registered && is_registered) { -+ /* subscribed */ -+ if (!had_subscriptions && -+ needs_subscriptions && has_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } -+ -+ /* simple content access enabled */ -+ if (needed_subscriptions && !had_subscriptions && !needs_subscriptions) { -+ _show_notification (manager, _NOTIFY_REGISTERED); -+ return; -+ } - } - } - - /* nag again */ -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && -+ if (!is_registered && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); - return; - } -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && -- g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { -- _show_notification (manager, _NOTIFY_EXPIRED); -- return; -- } -- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && -+ if (is_registered && !has_subscriptions && needs_subscriptions && - g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { - _show_notification (manager, _NOTIFY_EXPIRED); - return; - } - } - - static gboolean - _client_register_with_keys (GsdSubscriptionManager *manager, - const gchar *hostname, - const gchar *organisation, - const gchar *activation_key, - GError **error) - { - GsdSubscriptionManagerPrivate *priv = manager->priv; - g_autoptr(GSubprocess) subprocess = NULL; - g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); - g_autoptr(GBytes) stderr_buf = NULL; - gint rc; - - /* apparently: "we can't send registration credentials over the regular - * system or session bus since those aren't really locked down..." */ - if (!_client_register_start (manager, error)) - return FALSE; - g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); - subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, - "pkexec", LIBEXECDIR "/gsd-subman-helper", - "--kind", "register-with-key", - "--address", priv->address, - "--hostname", hostname, - "--organisation", organisation, -@@ -914,60 +1009,62 @@ gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) - static void - _launch_info_overview (void) - { - const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; - g_debug ("Running gnome-control-center info-overview"); - g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, - NULL, NULL, NULL, NULL); - } - - static void - _notify_closed_cb (NotifyNotification *notification, gpointer user_data) - { - /* FIXME: only launch when clicking on the main body, not the window close */ - if (notify_notification_get_closed_reason (notification) == 0x400) - _launch_info_overview (); - } - - static void - _notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) - { - _launch_info_overview (); - } - - static void - gsd_subscription_manager_init (GsdSubscriptionManager *manager) - { - GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); - - priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); - priv->timer_last_notified = g_timer_new (); -+ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; -+ priv->subscription_status_last = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; - - /* expired */ - priv->notification_expired = - notify_notification_new (_("Subscription Has Expired"), - _("Add or renew a subscription to continue receiving software updates."), - NULL); - notify_notification_set_app_name (priv->notification_expired, _("Subscription")); - notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); - notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); - notify_notification_add_action (priv->notification_expired, - "info-overview", _("Subscribe System…"), - _notify_clicked_cb, - manager, NULL); - g_signal_connect (priv->notification_expired, "closed", - G_CALLBACK (_notify_closed_cb), manager); - - /* registered */ - priv->notification_registered = - notify_notification_new (_("Registration Successful"), - _("The system has been registered and software updates have been enabled."), - NULL); - notify_notification_set_app_name (priv->notification_registered, _("Subscription")); - notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); - notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); - notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); - g_signal_connect (priv->notification_registered, "closed", - G_CALLBACK (_notify_closed_cb), manager); - - /* registration required */ --- -2.30.0 - diff --git a/SOURCES/0016-subman-Update-POTFILES.in.patch b/SOURCES/0016-subman-Update-POTFILES.in.patch deleted file mode 100644 index f2882e1..0000000 --- a/SOURCES/0016-subman-Update-POTFILES.in.patch +++ /dev/null @@ -1,25 +0,0 @@ -From ff1278ecdebb5b23c80589a65f053d535a4d4f6a Mon Sep 17 00:00:00 2001 -From: Kalev Lember -Date: Fri, 12 Feb 2021 14:51:29 +0100 -Subject: [PATCH 16/16] subman: Update POTFILES.in - ---- - po/POTFILES.in | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/po/POTFILES.in b/po/POTFILES.in -index 7f17d5b5..9b94dc0f 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -25,6 +25,8 @@ plugins/print-notifications/gsd-printer.c - plugins/print-notifications/gsd-print-notifications-manager.c - plugins/smartcard/gsd-smartcard-manager.c - plugins/smartcard/gsd-smartcard-service.c -+plugins/subman/gsd-subscription-manager.c -+plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in - plugins/wacom/gsd-wacom-manager.c - plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in - plugins/xsettings/gsd-xsettings-manager.c --- -2.29.2 - diff --git a/SPECS/gnome-settings-daemon.spec b/SPECS/gnome-settings-daemon.spec index 077379b..221888b 100644 --- a/SPECS/gnome-settings-daemon.spec +++ b/SPECS/gnome-settings-daemon.spec @@ -12,7 +12,7 @@ Name: gnome-settings-daemon Version: 3.32.0 -Release: 19%{?dist}.alma +Release: 21%{?dist}.alma.1 Summary: The daemon sharing settings from GNOME to GTK+/KDE applications License: GPLv2+ @@ -89,7 +89,11 @@ Patch00002: 0002-account-reshow-the-notification-when-screen-unlocks.patch Patch00003: 0003-account-display-nag-screen-periodically.patch Patch00004: 0004-account-don-t-poll-more-frequently-than-notification.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1796190 Patch10001: 0001-smartcard-Cancel-cancellable-when-stopping.patch +Patch10002: 0002-smartcard-Change-manager-to-non-blocking.patch +Patch10003: 0003-smartcard-Change-timeout-on-spurious-event-error.patch +Patch10004: 0004-smartcard-check-for-the-addition-of-new-smartcard-re.patch Patch20001: 0001-xsettings-Add-an-entry-for-the-overlay-scrolling-set.patch @@ -99,6 +103,7 @@ Patch30001: 0001-media-keys-Mark-screen-cast-as-stopped-if-it-was-sig.patch Patch40001: 0001-housekeeping-Add-a-GPU-memory-usage-notification.patch # subscription manager integration +%if %{with subman} Patch50001: 0001-subman-Add-a-new-plugin-to-provide-system-subscripti.patch Patch50002: 0002-subman-Add-InstalledProducts-dbus-property-for-g-c-c.patch Patch50003: 0003-subman-Increase-RHSM-dbus-call-timeouts.patch @@ -115,6 +120,10 @@ Patch50013: 0013-subman-Improve-subscription-status-handling.patch Patch50014: 0014-subman-Drop-LAST-from-status-enum.patch Patch50015: 0015-subman-Clean-up-notification-behavior.patch Patch50016: 0016-subman-Update-POTFILES.in.patch +# https://issues.redhat.com/browse/RHEL-5074 +Patch50018: subman-set-notification-icon.patch +%endif + # https://bugzilla.redhat.com/show_bug.cgi?id=1876291 Patch50017: 0017-Update-translations.patch @@ -173,7 +182,14 @@ developing applications that use %{name}. %endif %build -%meson +%meson \ +%if %{with subman} + -Dsubscription_manager=true +%else + -Dsubscription_manager=false +%endif + + %meson_build %install @@ -267,6 +283,7 @@ mkdir $RPM_BUILD_ROOT%{_libdir}/gnome-settings-daemon-3.0/gtk-modules %{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Sharing.desktop %{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.sharing.gschema.xml +%if %{with subman} %if %{with subman} %{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Subscription.desktop %{_libexecdir}/gsd-subman @@ -274,6 +291,7 @@ mkdir $RPM_BUILD_ROOT%{_libdir}/gnome-settings-daemon-3.0/gtk-modules %{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.subman.policy %{_datadir}/polkit-1/rules.d/org.gnome.settings-daemon.plugins.subman.rules %endif +%endif %{_libdir}/gnome-settings-daemon-3.0/libgsd.so @@ -289,9 +307,20 @@ mkdir $RPM_BUILD_ROOT%{_libdir}/gnome-settings-daemon-3.0/gtk-modules %{_libdir}/pkgconfig/gnome-settings-daemon.pc %changelog -* Tue May 16 2023 Andrew Lukoshko - 4.32.0-19.alma +* Mon Dec 22 2025 Andrei Lukoshko - 3.32.0-21.alma.1 - Disable subman plugin +* Mon Nov 03 2025 Felipe Borges - 3.32.0-21 +- Add icon to subman notifications + Resolves: RHEL-5074 + +* Mon Jul 24 2023 Ray Strode - 3.32.0-20 +- Backport some upstream smartcard changes that make it work + better with p11-kit + Resolves: #1796190 +- Rework how subscription-manager plugin is conditionalized so + it doens't get built on centos 8 stream + * Fri Feb 17 2023 Felipe Borges - 4.32.0-19 - Make power-button-action default to poweroff on servers - Resolves: #1920829