Blame SOURCES/0008-subman-Don-t-send-secrets-through-command-line.patch

06f198
From b73800da7f384eea66b6eb67f5f40129f3dfc372 Mon Sep 17 00:00:00 2001
06f198
From: Ray Strode <rstrode@redhat.com>
06f198
Date: Tue, 25 Aug 2020 16:20:42 -0400
06f198
Subject: [PATCH 08/15] subman: Don't send secrets through command line
06f198
06f198
The command line is introspectable with "ps", and it even gets logged
06f198
to syslog, so it's not suitable for passing secrets.
06f198
06f198
Unfortunately, the user's password is currently passed.
06f198
06f198
This commit addresses that problem by passing the password through
06f198
stdin, instead.
06f198
---
06f198
 plugins/subman/gsd-subman-helper.c        | 32 ++++++++------
06f198
 plugins/subman/gsd-subscription-manager.c | 52 ++++++++++++++++++++---
06f198
 plugins/subman/meson.build                |  2 +-
06f198
 3 files changed, 66 insertions(+), 20 deletions(-)
06f198
06f198
diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c
06f198
index 3931ef2e..edf1e41f 100644
06f198
--- a/plugins/subman/gsd-subman-helper.c
06f198
+++ b/plugins/subman/gsd-subman-helper.c
06f198
@@ -1,59 +1,61 @@
06f198
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
06f198
  *
06f198
  * Copyright (C) 2019 Richard Hughes <rhughes@redhat.com>
06f198
  *
06f198
  * Licensed under the GNU General Public License Version 2
06f198
  *
06f198
  * This program is free software; you can redistribute it and/or modify
06f198
  * it under the terms of the GNU General Public License as published by
06f198
  * the Free Software Foundation; either version 2 of the License, or
06f198
  * (at your option) any later version.
06f198
  *
06f198
  * This program is distributed in the hope that it will be useful,
06f198
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
06f198
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
06f198
  * GNU General Public License for more details.
06f198
  *
06f198
  * You should have received a copy of the GNU General Public License
06f198
  * along with this program; if not, write to the Free Software
06f198
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
06f198
  */
06f198
 
06f198
 #include "config.h"
06f198
 
06f198
+
06f198
 #include <sys/types.h>
06f198
 #include <unistd.h>
06f198
 #include <stdlib.h>
06f198
 #include <locale.h>
06f198
 
06f198
 #include <gio/gio.h>
06f198
+#include <gio/gunixinputstream.h>
06f198
 #include <json-glib/json-glib.h>
06f198
 
06f198
 #define DBUS_TIMEOUT 300000 /* 5 minutes */
06f198
 static const char *locale;
06f198
 
06f198
 static void
06f198
 _helper_convert_error (const gchar *json_txt, GError **error)
06f198
 {
06f198
 	JsonNode *json_root;
06f198
 	JsonObject *json_obj;
06f198
 	const gchar *message;
06f198
 	g_autoptr(JsonParser) json_parser = json_parser_new ();
06f198
 
06f198
 	/* this may be plain text or JSON :| */
06f198
 	if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) {
06f198
 		g_set_error_literal (error,
06f198
 				     G_IO_ERROR,
06f198
 				     G_IO_ERROR_NOT_SUPPORTED,
06f198
 				     json_txt);
06f198
 		return;
06f198
 	}
06f198
 	json_root = json_parser_get_root (json_parser);
06f198
 	json_obj = json_node_get_object (json_root);
06f198
 	if (!json_object_has_member (json_obj, "message")) {
06f198
 		g_set_error (error,
06f198
 			     G_IO_ERROR,
06f198
 			     G_IO_ERROR_INVALID_DATA,
06f198
 			     "no message' in %s", json_txt);
06f198
 		return;
06f198
 	}
06f198
@@ -149,86 +151,82 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error)
06f198
 					       G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
06f198
 					       G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
06f198
 					       NULL,
06f198
 					       "com.redhat.RHSM1",
06f198
 					       "/com/redhat/RHSM1/Config",
06f198
 					       "com.redhat.RHSM1.Config",
06f198
 					       NULL, error);
06f198
 	if (proxy == NULL) {
06f198
 		g_prefix_error (error, "Failed to get proxy: ");
06f198
 		return FALSE;
06f198
 	}
06f198
 	res = g_dbus_proxy_call_sync (proxy, "Set",
06f198
 				      g_variant_new ("(svs)",
06f198
 						     key,
06f198
 						     g_variant_new_string (value),
06f198
 						     locale),
06f198
 				      G_DBUS_CALL_FLAGS_NONE,
06f198
 				      DBUS_TIMEOUT,
06f198
 				      NULL, error);
06f198
 	return res != NULL;
06f198
 }
06f198
 
06f198
 int
06f198
 main (int argc, char *argv[])
06f198
 {
06f198
 	g_autofree gchar *activation_key = NULL;
06f198
 	g_autofree gchar *address = NULL;
06f198
 	g_autofree gchar *hostname = NULL;
06f198
 	g_autofree gchar *kind = NULL;
06f198
 	g_autofree gchar *organisation = NULL;
06f198
-	g_autofree gchar *password = NULL;
06f198
 	g_autofree gchar *port = NULL;
06f198
 	g_autofree gchar *prefix = NULL;
06f198
 	g_autofree gchar *proxy_server = NULL;
06f198
 	g_autofree gchar *username = NULL;
06f198
 	g_autoptr(GDBusConnection) conn_private = NULL;
06f198
 	g_autoptr(GDBusProxy) proxy = NULL;
06f198
 	g_autoptr(GError) error = NULL;
06f198
 	g_autoptr(GOptionContext) context = g_option_context_new (NULL);
06f198
 	g_autoptr(GVariantBuilder) proxy_options = NULL;
06f198
 	g_autoptr(GVariantBuilder) subman_conopts = NULL;
06f198
 	g_autoptr(GVariantBuilder) subman_options = NULL;
06f198
+	g_autoptr(GInputStream) standard_input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE);
06f198
 
06f198
 	const GOptionEntry options[] = {
06f198
 		{ "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
 			&kind, "Kind, e.g. 'username' or 'key'", NULL },
06f198
 		{ "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
 			&address, "UNIX address", NULL },
06f198
 		{ "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
 			&username, "Username", NULL },
06f198
-		{ "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
-			&password, "Password", NULL },
06f198
 		{ "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
 			&organisation, "Organisation", NULL },
06f198
-		{ "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
06f198
-			&activation_key, "Activation keys", NULL },
06f198
 		{ "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
06f198
 			&hostname, "Registration server hostname", NULL },
06f198
 		{ "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
06f198
 			&prefix, "Registration server prefix", NULL },
06f198
 		{ "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
06f198
 			&port, "Registration server port", NULL },
06f198
 		{ "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING,
06f198
 			&proxy_server, "Proxy settings", NULL },
06f198
 		{ NULL}
06f198
 	};
06f198
 
06f198
 	/* check calling UID */
06f198
 	if (getuid () != 0 || geteuid () != 0) {
06f198
 		g_printerr ("This program can only be used by the root user\n");
06f198
 		return G_IO_ERROR_NOT_SUPPORTED;
06f198
 	}
06f198
 
06f198
 	setlocale (LC_ALL, "");
06f198
 	locale = setlocale (LC_MESSAGES, NULL);
06f198
 
06f198
 	g_option_context_add_main_entries (context, options, NULL);
06f198
 	if (!g_option_context_parse (context, &argc, &argv, &error)) {
06f198
 		g_printerr ("Failed to parse arguments: %s\n", error->message);
06f198
 		return G_IO_ERROR_NOT_SUPPORTED;
06f198
 	}
06f198
 
06f198
 	/* uncommon actions */
06f198
 	if (kind == NULL) {
06f198
 		g_printerr ("No --kind specified\n");
06f198
 		return G_IO_ERROR_INVALID_DATA;
06f198
@@ -267,109 +265,117 @@ main (int argc, char *argv[])
06f198
 				       NULL, /* GDBusInterfaceInfo */
06f198
 				       NULL, /* name */
06f198
 				       "/com/redhat/RHSM1/Register",
06f198
 				       "com.redhat.RHSM1.Register",
06f198
 				       NULL, &error);
06f198
 	if (proxy == NULL) {
06f198
 		g_printerr ("Count not contact RHSM: %s\n", error->message);
06f198
 		return G_IO_ERROR_NOT_FOUND;
06f198
 	}
06f198
 
06f198
 	/* no options */
06f198
 	subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}"));
06f198
 
06f198
 	/* set registration server */
06f198
 	if (hostname == NULL || hostname[0] == '\0')
06f198
 		hostname = g_strdup ("subscription.rhsm.redhat.com");
06f198
 	if (prefix == NULL || prefix[0] == '\0')
06f198
 		prefix = g_strdup ("/subscription");
06f198
 	if (port == NULL || port[0] == '\0')
06f198
 		port = g_strdup ("443");
06f198
 	subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}"));
06f198
 	g_variant_builder_add (subman_conopts, "{ss}", "host", hostname);
06f198
 	g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix);
06f198
 	g_variant_builder_add (subman_conopts, "{ss}", "port", port);
06f198
 
06f198
 	/* call into RHSM */
06f198
 	if (g_strcmp0 (kind, "register-with-key") == 0) {
06f198
 		g_auto(GStrv) activation_keys = NULL;
06f198
 		g_autoptr(GError) error_local = NULL;
06f198
 		g_autoptr(GVariant) res = NULL;
06f198
+		gchar activation_key[PIPE_BUF + 1] = "";
06f198
 
06f198
-		if (activation_key == NULL) {
06f198
-			g_printerr ("Required --activation-key\n");
06f198
-			return G_IO_ERROR_INVALID_DATA;
06f198
-		}
06f198
 		if (organisation == NULL) {
06f198
 			g_printerr ("Required --organisation\n");
06f198
 			return G_IO_ERROR_INVALID_DATA;
06f198
 		}
06f198
 
06f198
+		g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local);
06f198
+
06f198
+		if (error_local != NULL) {
06f198
+			g_printerr ("Could not read activation key: %s\n", error_local->message);
06f198
+			return G_IO_ERROR_INVALID_DATA;
06f198
+		}
06f198
+
06f198
 		g_debug ("trying to unregister in case machine is already registered");
06f198
 		_helper_unregister (NULL);
06f198
 
06f198
 		g_debug ("registering using activation key");
06f198
 		activation_keys = g_strsplit (activation_key, ",", -1);
06f198
 		res = g_dbus_proxy_call_sync (proxy,
06f198
 					      "RegisterWithActivationKeys",
06f198
 					      g_variant_new ("(s^asa{ss}a{ss}s)",
06f198
 							     organisation,
06f198
 							     activation_keys,
06f198
 							     subman_options,
06f198
 							     subman_conopts,
06f198
 							     locale),
06f198
 					      G_DBUS_CALL_FLAGS_NO_AUTO_START,
06f198
 					      DBUS_TIMEOUT,
06f198
 					      NULL, &error_local);
06f198
 		if (res == NULL) {
06f198
 			g_dbus_error_strip_remote_error (error_local);
06f198
 			_helper_convert_error (error_local->message, &error);
06f198
 			g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message);
06f198
 			return error->code;
06f198
 		}
06f198
 	} else if (g_strcmp0 (kind, "register-with-username") == 0) {
06f198
 		g_autoptr(GError) error_local = NULL;
06f198
 		g_autoptr(GVariant) res = NULL;
06f198
+		gchar password[PIPE_BUF + 1] = "";
06f198
 
06f198
 		if (username == NULL) {
06f198
 			g_printerr ("Required --username\n");
06f198
 			return G_IO_ERROR_INVALID_DATA;
06f198
 		}
06f198
-		if (password == NULL) {
06f198
-			g_printerr ("Required --password\n");
06f198
-			return G_IO_ERROR_INVALID_DATA;
06f198
-		}
06f198
 		if (organisation == NULL) {
06f198
 			g_printerr ("Required --organisation\n");
06f198
 			return G_IO_ERROR_INVALID_DATA;
06f198
 		}
06f198
 
06f198
+		g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local);
06f198
+
06f198
+		if (error_local != NULL) {
06f198
+			g_printerr ("Could not read password: %s\n", error_local->message);
06f198
+			return G_IO_ERROR_INVALID_DATA;
06f198
+		}
06f198
+
06f198
 		g_debug ("trying to unregister in case machine is already registered");
06f198
 		_helper_unregister (NULL);
06f198
 
06f198
 		g_debug ("registering using username and password");
06f198
 		res = g_dbus_proxy_call_sync (proxy,
06f198
 					      "Register",
06f198
 					      g_variant_new ("(sssa{ss}a{ss}s)",
06f198
 							     organisation,
06f198
 							     username,
06f198
 							     password,
06f198
 							     subman_options,
06f198
 							     subman_conopts,
06f198
 							     locale),
06f198
 					      G_DBUS_CALL_FLAGS_NO_AUTO_START,
06f198
 					      DBUS_TIMEOUT,
06f198
 					      NULL, &error_local);
06f198
 		if (res == NULL) {
06f198
 			g_dbus_error_strip_remote_error (error_local);
06f198
 			_helper_convert_error (error_local->message, &error);
06f198
 			g_printerr ("Failed to Register: %s\n", error->message);
06f198
 			return error->code;
06f198
 		}
06f198
 	} else {
06f198
 		g_printerr ("Invalid --kind specified: %s\n", kind);
06f198
 		return G_IO_ERROR_INVALID_DATA;
06f198
 	}
06f198
 
06f198
 	/* set the new hostname */
06f198
 	if (!_helper_save_config ("server.hostname", hostname, &error)) {
06f198
 		g_printerr ("Failed to save hostname: %s\n", error->message);
06f198
diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c
06f198
index e2c16056..0838d490 100644
06f198
--- a/plugins/subman/gsd-subscription-manager.c
06f198
+++ b/plugins/subman/gsd-subscription-manager.c
06f198
@@ -1,53 +1,54 @@
06f198
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
06f198
  *
06f198
  * Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
06f198
  * Copyright (C) 2019 Kalev Lember <klember@redhat.com>
06f198
  *
06f198
  * This program is free software; you can redistribute it and/or modify
06f198
  * it under the terms of the GNU General Public License as published by
06f198
  * the Free Software Foundation; either version 2 of the License, or
06f198
  * (at your option) any later version.
06f198
  *
06f198
  * This program is distributed in the hope that it will be useful,
06f198
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
06f198
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
06f198
  * GNU General Public License for more details.
06f198
  *
06f198
  * You should have received a copy of the GNU General Public License
06f198
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
06f198
  *
06f198
  */
06f198
 
06f198
 #include "config.h"
06f198
 
06f198
 #include <glib/gi18n.h>
06f198
+#include <gio/gunixinputstream.h>
06f198
 #include <gdk/gdk.h>
06f198
 #include <gtk/gtk.h>
06f198
 #include <json-glib/json-glib.h>
06f198
 #include <libnotify/notify.h>
06f198
 
06f198
 #include "gnome-settings-profile.h"
06f198
 #include "gsd-subman-common.h"
06f198
 #include "gsd-subscription-manager.h"
06f198
 
06f198
 #define GSD_DBUS_NAME "org.gnome.SettingsDaemon"
06f198
 #define GSD_DBUS_PATH "/org/gnome/SettingsDaemon"
06f198
 #define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon"
06f198
 
06f198
 #define GSD_SUBSCRIPTION_DBUS_NAME		GSD_DBUS_NAME ".Subscription"
06f198
 #define GSD_SUBSCRIPTION_DBUS_PATH		GSD_DBUS_PATH "/Subscription"
06f198
 #define GSD_SUBSCRIPTION_DBUS_INTERFACE		GSD_DBUS_BASE_INTERFACE ".Subscription"
06f198
 
06f198
 static const gchar introspection_xml[] =
06f198
 "<node>"
06f198
 "  <interface name='org.gnome.SettingsDaemon.Subscription'>"
06f198
 "    <method name='Register'>"
06f198
 "      <arg type='a{sv}' name='options' direction='in'/>"
06f198
 "    </method>"
06f198
 "    <method name='Unregister'/>"
06f198
 "    <property name='InstalledProducts' type='aa{sv}' access='read'/>"
06f198
 "    <property name='SubscriptionStatus' type='u' access='read'/>"
06f198
 "  </interface>"
06f198
 "</node>";
06f198
 
06f198
 #define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate))
06f198
@@ -517,129 +518,168 @@ _client_maybe__show_notification (GsdSubscriptionManager *manager)
06f198
 		}
06f198
 	}
06f198
 
06f198
 	/* nag again */
06f198
 	if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN &&
06f198
 	    g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) {
06f198
 		_show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED);
06f198
 		return;
06f198
 	}
06f198
 	if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID &&
06f198
 	    g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) {
06f198
 		_show_notification (manager, _NOTIFY_EXPIRED);
06f198
 		return;
06f198
 	}
06f198
 	if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID &&
06f198
 	    g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) {
06f198
 		_show_notification (manager, _NOTIFY_EXPIRED);
06f198
 		return;
06f198
 	}
06f198
 }
06f198
 
06f198
 static gboolean
06f198
 _client_register_with_keys (GsdSubscriptionManager *manager,
06f198
 				  const gchar *hostname,
06f198
 				  const gchar *organisation,
06f198
 				  const gchar *activation_key,
06f198
 				  GError **error)
06f198
 {
06f198
 	GsdSubscriptionManagerPrivate *priv = manager->priv;
06f198
 	g_autoptr(GSubprocess) subprocess = NULL;
06f198
+	g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1);
06f198
+	g_autoptr(GBytes) stderr_buf = NULL;
06f198
+	gint rc;
06f198
 
06f198
 	/* apparently: "we can't send registration credentials over the regular
06f198
 	 * system or session bus since those aren't really locked down..." */
06f198
 	if (!_client_register_start (manager, error))
06f198
 		return FALSE;
06f198
 	g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
06f198
-	subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
06f198
+	subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
06f198
 				       "pkexec", LIBEXECDIR "/gsd-subman-helper",
06f198
 				       "--kind", "register-with-key",
06f198
 				       "--address", priv->address,
06f198
 				       "--hostname", hostname,
06f198
 				       "--organisation", organisation,
06f198
-				       "--activation-key", activation_key,
06f198
 				       NULL);
06f198
 	if (subprocess == NULL) {
06f198
 		g_prefix_error (error, "failed to find pkexec: ");
06f198
 		return FALSE;
06f198
 	}
06f198
-	if (!_client_subprocess_wait_check (subprocess, error))
06f198
+
06f198
+	if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) {
06f198
+		g_prefix_error (error, "failed to run pkexec: ");
06f198
 		return FALSE;
06f198
+	}
06f198
+
06f198
+	rc = g_subprocess_get_exit_status (subprocess);
06f198
+	if (rc != 0) {
06f198
+		if (g_bytes_get_size (stderr_buf) == 0) {
06f198
+			g_set_error_literal (error, G_IO_ERROR, rc,
06f198
+			                     "Failed to run helper without stderr");
06f198
+			return FALSE;
06f198
+		}
06f198
+
06f198
+		g_set_error (error, G_IO_ERROR, rc,
06f198
+			     "%.*s",
06f198
+			     g_bytes_get_size (stderr_buf),
06f198
+			     g_bytes_get_data (stderr_buf, NULL));
06f198
+	}
06f198
 
06f198
 	/* FIXME: also do on error? */
06f198
 	if (!_client_register_stop (manager, error))
06f198
 		return FALSE;
06f198
 	if (!_client_subscription_status_update (manager, error))
06f198
 		return FALSE;
06f198
 	if (!_client_installed_products_update (manager, error))
06f198
 		return FALSE;
06f198
 	_client_maybe__show_notification (manager);
06f198
 
06f198
 	/* success */
06f198
 	return TRUE;
06f198
 }
06f198
 
06f198
 static gboolean
06f198
 _client_register (GsdSubscriptionManager *manager,
06f198
 			 const gchar *hostname,
06f198
 			 const gchar *organisation,
06f198
 			 const gchar *username,
06f198
 			 const gchar *password,
06f198
 			 GError **error)
06f198
 {
06f198
 	GsdSubscriptionManagerPrivate *priv = manager->priv;
06f198
 	g_autoptr(GSubprocess) subprocess = NULL;
06f198
+	g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1);
06f198
+	g_autoptr(GBytes) stderr_buf = NULL;
06f198
+	gint rc;
06f198
 
06f198
 	/* fallback */
06f198
 	if (organisation == NULL)
06f198
 		organisation = "";
06f198
 
06f198
 	/* apparently: "we can't send registration credentials over the regular
06f198
 	 * system or session bus since those aren't really locked down..." */
06f198
 	if (!_client_register_start (manager, error))
06f198
 		return FALSE;
06f198
 	g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
06f198
-	subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
06f198
+	subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE,
06f198
+				       error,
06f198
 				       "pkexec", LIBEXECDIR "/gsd-subman-helper",
06f198
 				       "--kind", "register-with-username",
06f198
 				       "--address", priv->address,
06f198
 				       "--hostname", hostname,
06f198
 				       "--organisation", organisation,
06f198
 				       "--username", username,
06f198
-				       "--password", password,
06f198
 				       NULL);
06f198
 	if (subprocess == NULL) {
06f198
 		g_prefix_error (error, "failed to find pkexec: ");
06f198
 		return FALSE;
06f198
 	}
06f198
-	if (!_client_subprocess_wait_check (subprocess, error))
06f198
+
06f198
+	if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) {
06f198
+		g_prefix_error (error, "failed to run pkexec: ");
06f198
 		return FALSE;
06f198
+	}
06f198
+
06f198
+	rc = g_subprocess_get_exit_status (subprocess);
06f198
+	if (rc != 0) {
06f198
+		if (g_bytes_get_size (stderr_buf) == 0) {
06f198
+			g_set_error_literal (error, G_IO_ERROR, rc,
06f198
+			                     "Failed to run helper without stderr");
06f198
+			return FALSE;
06f198
+		}
06f198
+
06f198
+		g_set_error (error, G_IO_ERROR, rc,
06f198
+			     "%.*s",
06f198
+			     g_bytes_get_size (stderr_buf),
06f198
+			     g_bytes_get_data (stderr_buf, NULL));
06f198
+	}
06f198
 
06f198
 	/* FIXME: also do on error? */
06f198
 	if (!_client_register_stop (manager, error))
06f198
 		return FALSE;
06f198
 	if (!_client_subscription_status_update (manager, error))
06f198
 		return FALSE;
06f198
 	if (!_client_installed_products_update (manager, error))
06f198
 		return FALSE;
06f198
 	_client_maybe__show_notification (manager);
06f198
 	return TRUE;
06f198
 }
06f198
 
06f198
 static gboolean
06f198
 _client_unregister (GsdSubscriptionManager *manager, GError **error)
06f198
 {
06f198
 	g_autoptr(GSubprocess) subprocess = NULL;
06f198
 
06f198
 	/* apparently: "we can't send registration credentials over the regular
06f198
 	 * system or session bus since those aren't really locked down..." */
06f198
 	if (!_client_register_start (manager, error))
06f198
 		return FALSE;
06f198
 	g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper");
06f198
 	subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error,
06f198
 				       "pkexec", LIBEXECDIR "/gsd-subman-helper",
06f198
 				       "--kind", "unregister",
06f198
 				       NULL);
06f198
 	if (subprocess == NULL) {
06f198
 		g_prefix_error (error, "failed to find pkexec: ");
06f198
 		return FALSE;
06f198
 	}
06f198
diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build
06f198
index bfd073b6..e4b4589d 100644
06f198
--- a/plugins/subman/meson.build
06f198
+++ b/plugins/subman/meson.build
06f198
@@ -22,35 +22,35 @@ executable(
06f198
   c_args: cflags,
06f198
   install: true,
06f198
   install_rpath: gsd_pkglibdir,
06f198
   install_dir: gsd_libexecdir
06f198
 )
06f198
 
06f198
 # .Register needs to be called from root as subman can't do PolicyKit...
06f198
 policy = 'org.gnome.settings-daemon.plugins.subman.policy'
06f198
 policy_in = configure_file(
06f198
   input: policy + '.in.in',
06f198
   output: policy + '.in',
06f198
   configuration: plugins_conf
06f198
 )
06f198
 
06f198
 i18n.merge_file(
06f198
   policy,
06f198
   input: policy_in,
06f198
   output: policy,
06f198
   po_dir: po_dir,
06f198
   install: true,
06f198
   install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions')
06f198
 )
06f198
 
06f198
 install_data('org.gnome.settings-daemon.plugins.subman.rules',
06f198
              install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d'))
06f198
 
06f198
 executable(
06f198
   'gsd-subman-helper',
06f198
   'gsd-subman-helper.c',
06f198
   include_directories: top_inc,
06f198
-  dependencies: [gio_dep, jsonglib_dep],
06f198
+  dependencies: [gio_dep, gio_unix_dep, jsonglib_dep],
06f198
   install: true,
06f198
   install_rpath: gsd_pkglibdir,
06f198
   install_dir: gsd_libexecdir
06f198
 )
06f198
-- 
06f198
2.30.0
06f198