Compare commits

...

No commits in common. "c8" and "a8-beta" have entirely different histories.
c8 ... a8-beta

21 changed files with 6675 additions and 446 deletions

View File

@ -1,7 +1,7 @@
From b0fb67c05e19a1a8715c1045f02657055d9e2578 Mon Sep 17 00:00:00 2001
From a1c2685bc6b255f22b6ce4645c001d428cb67907 Mon Sep 17 00:00:00 2001
From: Marek Kasik <mkasik@redhat.com>
Date: Wed, 22 May 2019 14:56:42 +0200
Subject: [PATCH 1/4] smartcard: Cancel cancellable when stopping
Subject: [PATCH] smartcard: Cancel cancellable when stopping
self->cancellable in GsdSmartcardManager is not cancelled
at gsd_smartcard_manager_stop() and hence some callbacks are
@ -19,40 +19,13 @@ 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 deletions(-)
1 file changed, 5 insertions(+), 2 deletion(-)
diff --git a/plugins/smartcard/gsd-smartcard-manager.c b/plugins/smartcard/gsd-smartcard-manager.c
index 94ffdd90..09ccecc0 100644
index 014c17be..da1e0d6d 100644
--- a/plugins/smartcard/gsd-smartcard-manager.c
+++ b/plugins/smartcard/gsd-smartcard-manager.c
@@ -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,
@@ -184,7 +184,7 @@
GError **error)
{
GsdSmartcardManagerPrivate *priv = self->priv;
@ -61,9 +34,7 @@ index 94ffdd90..09ccecc0 100644
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),
@@ -190,7 +190,8 @@ watch_one_event_from_driver (GsdSmartcardManager *self,
operation,
NULL);
@ -73,61 +44,7 @@ index 94ffdd90..09ccecc0 100644
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 ();
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;
@@ -773,6 +774,8 @@ gsd_smartcard_manager_stop (GsdSmartcardManager *self)
g_debug ("Stopping smartcard manager");
@ -136,33 +53,6 @@ index 94ffdd90..09ccecc0 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.39.2
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -1,124 +0,0 @@
From 65d854c690cad1ccef6544a8c571bbb723ff9be0 Mon Sep 17 00:00:00 2001
From: Jack Massey <jacknmassey@gmail.com>
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

View File

@ -0,0 +1,768 @@
From f723ed1078e050c4d966d40b2aea74970c74279c Mon Sep 17 00:00:00 2001
From: Kalev Lember <klember@redhat.com>
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 <richard@hughsie.com>
+ * Copyright (C) 2019 Kalev Lember <klember@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <json-glib/json-glib.h>
#include <libnotify/notify.h>
#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[] =
"<node>"
" <interface name='org.gnome.SettingsDaemon.Subscription'>"
" <method name='Register'>"
" <arg type='a{sv}' name='options' direction='in'/>"
" </method>"
" <method name='Unregister'/>"
+" <property name='InstalledProducts' type='aa{sv}' access='read'/>"
" <property name='SubscriptionStatus' type='u' access='read'/>"
" </interface>"
"</node>";
#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

View File

@ -1,83 +0,0 @@
From 5da276e4559d5c3b072a9870db6d78a1fe788339 Mon Sep 17 00:00:00 2001
From: Jack Massey <jacknmassey@gmail.com>
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

View File

@ -0,0 +1,313 @@
From 0d88b2133b20957e00b0eeb0c0f48932485cc73d Mon Sep 17 00:00:00 2001
From: Kalev Lember <klember@redhat.com>
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 <rhughes@redhat.com>
*
* 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 <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <gio/gio.h>
#include <json-glib/json-glib.h>
+#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

View File

@ -1,94 +0,0 @@
From 2b0b62d8b04a2c3d6e1d4fccacfd29dd3da2d04c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20H=C3=A4rdeman?= <david@hardeman.nu>
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

View File

@ -0,0 +1,454 @@
From df08a65d86626ff135a12d96cff6f48f3f1864ae Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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[] =
" <arg type='a{sv}' name='options' direction='in'/>"
" </method>"
" <method name='Unregister'/>"
" <property name='InstalledProducts' type='aa{sv}' access='read'/>"
" <property name='SubscriptionStatus' type='u' access='read'/>"
" </interface>"
"</node>";
#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

View File

@ -0,0 +1,373 @@
From db73e2211ecc746434d78d23d801c92581fa8824 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <rhughes@redhat.com>
*
* 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 <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
+#include <locale.h>
#include <gio/gio.h>
#include <json-glib/json-glib.h>
#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

View File

@ -0,0 +1,236 @@
From f8ddd2c711cd502c74eb9d45360914fe2e6e1b3f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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

View File

@ -0,0 +1,260 @@
From 477dc8accccab568002bd19caa3fbf898bc05aad Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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

View File

@ -0,0 +1,576 @@
From b73800da7f384eea66b6eb67f5f40129f3dfc372 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <rhughes@redhat.com>
*
* 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 <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <gio/gio.h>
+#include <gio/gunixinputstream.h>
#include <json-glib/json-glib.h>
#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 <richard@hughsie.com>
* Copyright (C) 2019 Kalev Lember <klember@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <glib/gi18n.h>
+#include <gio/gunixinputstream.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <json-glib/json-glib.h>
#include <libnotify/notify.h>
#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[] =
"<node>"
" <interface name='org.gnome.SettingsDaemon.Subscription'>"
" <method name='Register'>"
" <arg type='a{sv}' name='options' direction='in'/>"
" </method>"
" <method name='Unregister'/>"
" <property name='InstalledProducts' type='aa{sv}' access='read'/>"
" <property name='SubscriptionStatus' type='u' access='read'/>"
" </interface>"
"</node>";
#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

View File

@ -0,0 +1,310 @@
From 1255b2b83284d262f6b8c3ceb23d499ddbf77d48 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <json-glib/json-glib.h>
#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

View File

@ -0,0 +1,427 @@
From d53c27802c69773d63d108f57912035fd3caabf9 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <http://www.gnu.org/licenses/>.
*
*/
#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 <rhughes@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __GSD_SUBMAN_COMMON_H
#define __GSD_SUBMAN_COMMON_H
#include <glib-object.h>
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

View File

@ -0,0 +1,146 @@
From 432850e943d72daedb1d352a0332d3fdee6078e2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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

View File

@ -0,0 +1,259 @@
From 3bb3b2b09d34deafadd3cfe3355137afab20cb23 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <glib/gi18n.h>
#include <gio/gunixinputstream.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <json-glib/json-glib.h>
#include <libnotify/notify.h>
#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[] =
"<node>"
" <interface name='org.gnome.SettingsDaemon.Subscription'>"
" <method name='Register'>"
" <arg type='a{sv}' name='options' direction='in'/>"
" </method>"
" <method name='Unregister'/>"
+" <method name='Attach'/>"
" <property name='InstalledProducts' type='aa{sv}' access='read'/>"
" <property name='SubscriptionStatus' type='u' access='read'/>"
" </interface>"
"</node>";
#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

View File

@ -0,0 +1,141 @@
From d9eb6331efa92cd28a8ba3ccc1665c3744296465 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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

View File

@ -0,0 +1,56 @@
From a78b25b9507edb958a46779f2bb808bf678fa4a7 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __GSD_SUBMAN_COMMON_H
#define __GSD_SUBMAN_COMMON_H
#include <glib-object.h>
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

View File

@ -0,0 +1,419 @@
From 3412be1f63df2a5967ef92c27028368df1646b5c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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 <rhughes@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifndef __GSD_SUBMAN_COMMON_H
#define __GSD_SUBMAN_COMMON_H
#include <glib-object.h>
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

View File

@ -0,0 +1,25 @@
From ff1278ecdebb5b23c80589a65f053d535a4d4f6a Mon Sep 17 00:00:00 2001
From: Kalev Lember <klember@redhat.com>
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

View File

@ -12,7 +12,7 @@
Name: gnome-settings-daemon
Version: 3.32.0
Release: 21%{?dist}
Release: 19%{?dist}.alma
Summary: The daemon sharing settings from GNOME to GTK+/KDE applications
License: GPLv2+
@ -89,11 +89,7 @@ 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
@ -103,7 +99,6 @@ 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
@ -120,10 +115,6 @@ 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
@ -149,17 +140,40 @@ The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%prep
%autosetup -S git
%setup -q
%patch00001 -p 1
%patch00002 -p 1
%patch00003 -p 1
%patch00004 -p 1
%patch10001 -p 1
%patch20001 -p 1
%patch30001 -p 1
%patch40001 -p 1
%patch50017 -p 1
%patch60001 -p 1
%build
%meson \
%if %{with subman}
-Dsubscription_manager=true
%else
-Dsubscription_manager=false
%patch50001 -p 1
%patch50002 -p 1
%patch50003 -p 1
%patch50004 -p 1
%patch50005 -p 1
%patch50006 -p 1
%patch50007 -p 1
%patch50008 -p 1
%patch50009 -p 1
%patch50010 -p 1
%patch50011 -p 1
%patch50012 -p 1
%patch50013 -p 1
%patch50014 -p 1
%patch50015 -p 1
%patch50016 -p 1
%endif
%build
%meson
%meson_build
%install
@ -275,16 +289,8 @@ mkdir $RPM_BUILD_ROOT%{_libdir}/gnome-settings-daemon-3.0/gtk-modules
%{_libdir}/pkgconfig/gnome-settings-daemon.pc
%changelog
* Mon Nov 03 2025 Felipe Borges <feborges@redhat.com> - 3.32.0-21
- Add icon to subman notifications
Resolves: RHEL-5074
* Mon Jul 24 2023 Ray Strode <rstrode@redhat.com> - 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
* Wed Mar 29 2023 Eduard Abdullin <eabdullin@almalinux.org> - 4.32.0-19.alma
- Disable subman plugin
* Fri Feb 17 2023 Felipe Borges <feborges@redhat.com> - 4.32.0-19
- Make power-button-action default to poweroff on servers