blob: 48837139b4d1c58848b3db94c1194084989bb243 [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughes5c9b1fc2021-01-07 14:20:49 +00002 * Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00003 *
Mario Limonciello51308e62018-05-28 20:05:46 -05004 * SPDX-License-Identifier: LGPL-2.1+
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00005 */
6
Richard Hughesb08e7bc2018-09-11 10:51:13 +01007#define G_LOG_DOMAIN "FuMain"
8
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00009#include "config.h"
10
Richard Hughes481aa2a2018-09-18 20:51:46 +010011#include <xmlb.h>
Richard Hughes9945edb2017-06-19 10:03:55 +010012#include <fwupd.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000013#include <gio/gunixfdlist.h>
14#include <glib/gi18n.h>
Mario Limonciello6754f5a2018-10-11 10:50:03 -050015#include <glib-unix.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000016#include <locale.h>
Érico Nogueira391647f2021-03-29 14:45:20 -030017#ifdef HAVE_MALLOC_H
Richard Hughesd0ba4692021-02-22 20:57:21 +000018#include <malloc.h>
Érico Nogueira391647f2021-03-29 14:45:20 -030019#endif
Mario Limonciello11b71f42020-10-13 13:39:14 -050020#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000021#include <polkit/polkit.h>
Mario Limonciello11b71f42020-10-13 13:39:14 -050022#endif
Richard Hughesa0531342020-10-23 10:47:26 +010023#ifdef HAVE_SYSTEMD
24#include <systemd/sd-daemon.h>
25#endif
Mario Limoncielloeb4c7642019-11-11 10:31:29 -060026#include <stdio.h>
Richard Hughes67ec8982015-03-03 11:39:27 +000027#include <stdlib.h>
Richard Hughesd5aab652020-02-25 12:47:50 +000028#include <jcat.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000029
Richard Hughes68982c62017-09-13 15:40:14 +010030#include "fwupd-device-private.h"
Richard Hughes7bcb8d42020-10-08 15:47:47 +010031#include "fwupd-plugin-private.h"
Richard Hughes196c6c62020-05-11 19:42:47 +010032#include "fwupd-security-attr-private.h"
Richard Hughes1642b3b2017-06-05 17:40:08 +010033#include "fwupd-release-private.h"
Richard Hughes4c369702017-06-16 15:31:38 +010034#include "fwupd-remote-private.h"
Richard Hughesd6db6b42017-04-12 15:03:10 +010035#include "fwupd-resources.h"
Richard Hughes8e9762d2016-03-17 10:14:15 +000036
Richard Hughes943d2c92017-06-21 09:04:39 +010037#include "fu-common.h"
Richard Hughes8bbfdf42015-02-26 22:28:09 +000038#include "fu-debug.h"
Richard Hughes68982c62017-09-13 15:40:14 +010039#include "fu-device-private.h"
Richard Hughes9945edb2017-06-19 10:03:55 +010040#include "fu-engine.h"
Richard Hughes4ad41f02018-05-08 14:35:36 +010041#include "fu-install-task.h"
Richard Hughesf58ac732020-05-12 15:23:44 +010042#include "fu-security-attrs-private.h"
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000043
Mario Limonciello11b71f42020-10-13 13:39:14 -050044#ifdef HAVE_POLKIT
Philip Withnallbc339aa2016-11-22 16:13:22 +000045#ifndef HAVE_POLKIT_0_114
Mario Limoncielloa98df552018-04-16 12:15:51 -050046#pragma clang diagnostic push
47#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes60f48c22015-10-08 20:25:51 +010048G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitAuthorizationResult, g_object_unref)
49G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitSubject, g_object_unref)
Mario Limoncielloa98df552018-04-16 12:15:51 -050050#pragma clang diagnostic pop
Mario Limonciello11b71f42020-10-13 13:39:14 -050051#endif /* HAVE_POLKIT_0_114 */
52#endif /* HAVE_POLKIT */
Richard Hughes60f48c22015-10-08 20:25:51 +010053
Richard Hughesa018b3c2020-08-28 17:08:19 +010054typedef enum {
55 FU_MAIN_MACHINE_KIND_PHYSICAL,
56 FU_MAIN_MACHINE_KIND_VIRTUAL,
57 FU_MAIN_MACHINE_KIND_CONTAINER,
58} FuMainMachineKind;
59
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000060typedef struct {
61 GDBusConnection *connection;
62 GDBusNodeInfo *introspection_daemon;
Richard Hughes18423292015-03-09 17:10:50 +000063 GDBusProxy *proxy_uid;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000064 GMainLoop *loop;
Richard Hughesf3dc1622019-03-27 12:48:39 +000065 GFileMonitor *argv0_monitor;
Richard Hughesdf89cd52020-06-26 20:25:18 +010066 GHashTable *sender_features; /* sender:FwupdFeatureFlags */
Richard Hughes603e4f62019-12-11 13:44:09 +000067#if GLIB_CHECK_VERSION(2,63,3)
68 GMemoryMonitor *memory_monitor;
69#endif
Mario Limonciello11b71f42020-10-13 13:39:14 -050070#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000071 PolkitAuthority *authority;
Mario Limonciello11b71f42020-10-13 13:39:14 -050072#endif
Richard Hughesf0a799e2017-01-17 20:13:30 +000073 guint owner_id;
Richard Hughes9945edb2017-06-19 10:03:55 +010074 FuEngine *engine;
Mario Limonciello6754f5a2018-10-11 10:50:03 -050075 gboolean update_in_progress;
76 gboolean pending_sigterm;
Richard Hughesa018b3c2020-08-28 17:08:19 +010077 FuMainMachineKind machine_kind;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000078} FuMainPrivate;
79
Mario Limonciello6754f5a2018-10-11 10:50:03 -050080static gboolean
81fu_main_sigterm_cb (gpointer user_data)
82{
83 FuMainPrivate *priv = (FuMainPrivate *) user_data;
84 if (!priv->update_in_progress) {
85 g_main_loop_quit (priv->loop);
86 return G_SOURCE_REMOVE;
87 }
88 g_warning ("Received SIGTERM during a firmware update, ignoring");
89 priv->pending_sigterm = TRUE;
90 return G_SOURCE_CONTINUE;
91}
92
Richard Hughesd7022b52015-03-11 19:47:06 +000093static void
Richard Hughes9945edb2017-06-19 10:03:55 +010094fu_main_engine_changed_cb (FuEngine *engine, FuMainPrivate *priv)
Richard Hughesd7022b52015-03-11 19:47:06 +000095{
96 /* not yet connected */
97 if (priv->connection == NULL)
98 return;
99 g_dbus_connection_emit_signal (priv->connection,
100 NULL,
101 FWUPD_DBUS_PATH,
102 FWUPD_DBUS_INTERFACE,
103 "Changed",
104 NULL, NULL);
105}
106
Richard Hughes8ca33782016-04-28 15:04:31 +0100107static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100108fu_main_engine_device_added_cb (FuEngine *engine,
109 FuDevice *device,
110 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100111{
112 GVariant *val;
113
114 /* not yet connected */
115 if (priv->connection == NULL)
116 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100117 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100118 g_dbus_connection_emit_signal (priv->connection,
119 NULL,
120 FWUPD_DBUS_PATH,
121 FWUPD_DBUS_INTERFACE,
122 "DeviceAdded",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100123 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100124}
125
Richard Hughes8ca33782016-04-28 15:04:31 +0100126static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100127fu_main_engine_device_removed_cb (FuEngine *engine,
128 FuDevice *device,
129 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100130{
131 GVariant *val;
132
133 /* not yet connected */
134 if (priv->connection == NULL)
135 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100136 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100137 g_dbus_connection_emit_signal (priv->connection,
138 NULL,
139 FWUPD_DBUS_PATH,
140 FWUPD_DBUS_INTERFACE,
141 "DeviceRemoved",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100142 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100143}
144
Richard Hughes8ca33782016-04-28 15:04:31 +0100145static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100146fu_main_engine_device_changed_cb (FuEngine *engine,
147 FuDevice *device,
148 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100149{
150 GVariant *val;
151
152 /* not yet connected */
153 if (priv->connection == NULL)
154 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100155 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100156 g_dbus_connection_emit_signal (priv->connection,
157 NULL,
158 FWUPD_DBUS_PATH,
159 FWUPD_DBUS_INTERFACE,
160 "DeviceChanged",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100161 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100162}
163
Richard Hughes773ce982015-03-09 22:40:57 +0000164static void
165fu_main_emit_property_changed (FuMainPrivate *priv,
166 const gchar *property_name,
167 GVariant *property_value)
168{
169 GVariantBuilder builder;
170 GVariantBuilder invalidated_builder;
171
172 /* not yet connected */
Richard Hughes34fcc022018-09-19 16:16:15 +0100173 if (priv->connection == NULL) {
174 g_variant_unref (g_variant_ref_sink (property_value));
Richard Hughes773ce982015-03-09 22:40:57 +0000175 return;
Richard Hughes34fcc022018-09-19 16:16:15 +0100176 }
Richard Hughes773ce982015-03-09 22:40:57 +0000177
178 /* build the dict */
179 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
Richard Hughes8356a832019-03-21 17:04:38 +0000180 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
Richard Hughes773ce982015-03-09 22:40:57 +0000181 g_variant_builder_add (&builder,
182 "{sv}",
183 property_name,
184 property_value);
185 g_dbus_connection_emit_signal (priv->connection,
186 NULL,
187 FWUPD_DBUS_PATH,
188 "org.freedesktop.DBus.Properties",
189 "PropertiesChanged",
190 g_variant_new ("(sa{sv}as)",
191 FWUPD_DBUS_INTERFACE,
192 &builder,
193 &invalidated_builder),
194 NULL);
195 g_variant_builder_clear (&builder);
196 g_variant_builder_clear (&invalidated_builder);
197}
198
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100199static void
200fu_main_set_status (FuMainPrivate *priv, FwupdStatus status)
201{
202 g_debug ("Emitting PropertyChanged('Status'='%s')",
203 fwupd_status_to_string (status));
204 fu_main_emit_property_changed (priv, "Status",
205 g_variant_new_uint32 (status));
206}
Richard Hughes773ce982015-03-09 22:40:57 +0000207
Richard Hughes9945edb2017-06-19 10:03:55 +0100208static void
209fu_main_engine_status_changed_cb (FuEngine *engine,
210 FwupdStatus status,
211 FuMainPrivate *priv)
212{
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100213 fu_main_set_status (priv, status);
Richard Hughes75b965d2018-11-15 13:51:21 +0000214
215 /* engine has gone idle */
216 if (status == FWUPD_STATUS_SHUTDOWN)
217 g_main_loop_quit (priv->loop);
Richard Hughes773ce982015-03-09 22:40:57 +0000218}
219
Richard Hughes876c0072016-08-17 14:51:03 +0100220static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100221fu_main_engine_percentage_changed_cb (FuEngine *engine,
222 guint percentage,
223 FuMainPrivate *priv)
Richard Hughes876c0072016-08-17 14:51:03 +0100224{
Richard Hughes876c0072016-08-17 14:51:03 +0100225 g_debug ("Emitting PropertyChanged('Percentage'='%u%%')", percentage);
226 fu_main_emit_property_changed (priv, "Percentage",
227 g_variant_new_uint32 (percentage));
228}
229
Richard Hughesdf89cd52020-06-26 20:25:18 +0100230static FuEngineRequest *
231fu_main_create_request (FuMainPrivate *priv, const gchar *sender, GError **error)
Mario Limoncielloe3016602018-09-06 11:20:59 -0500232{
Richard Hughesdf89cd52020-06-26 20:25:18 +0100233 FwupdFeatureFlags *feature_flags;
234 FwupdDeviceFlags device_flags = FWUPD_DEVICE_FLAG_NONE;
235 uid_t calling_uid = 0;
236 g_autoptr(FuEngineRequest) request = fu_engine_request_new ();
Mario Limoncielloe3016602018-09-06 11:20:59 -0500237 g_autoptr(GVariant) value = NULL;
238
Richard Hughesdf89cd52020-06-26 20:25:18 +0100239 g_return_val_if_fail (sender != NULL, NULL);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500240
Richard Hughesdf89cd52020-06-26 20:25:18 +0100241 /* did the client set the list of supported feature */
242 feature_flags = g_hash_table_lookup (priv->sender_features, sender);
243 if (feature_flags != NULL)
244 fu_engine_request_set_feature_flags (request, *feature_flags);
245
246 /* are we root and therefore trusted? */
Mario Limoncielloe3016602018-09-06 11:20:59 -0500247 value = g_dbus_proxy_call_sync (priv->proxy_uid,
248 "GetConnectionUnixUser",
249 g_variant_new ("(s)", sender),
250 G_DBUS_CALL_FLAGS_NONE,
251 2000,
252 NULL,
253 error);
254 if (value == NULL) {
255 g_prefix_error (error, "failed to read user id of caller: ");
Richard Hughesbfe6c772020-08-17 14:48:23 +0100256 return NULL;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500257 }
258 g_variant_get (value, "(u)", &calling_uid);
259 if (calling_uid == 0)
Richard Hughesdf89cd52020-06-26 20:25:18 +0100260 device_flags |= FWUPD_DEVICE_FLAG_TRUSTED;
261 fu_engine_request_set_device_flags (request, device_flags);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500262
Richard Hughesdf89cd52020-06-26 20:25:18 +0100263 /* success */
264 return g_steal_pointer (&request);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500265}
266
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000267static GVariant *
Richard Hughesdf89cd52020-06-26 20:25:18 +0100268fu_main_device_array_to_variant (FuMainPrivate *priv, FuEngineRequest *request,
Mario Limoncielloe3016602018-09-06 11:20:59 -0500269 GPtrArray *devices, GError **error)
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000270{
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000271 GVariantBuilder builder;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500272
Richard Hughes9945edb2017-06-19 10:03:55 +0100273 g_return_val_if_fail (devices->len > 0, NULL);
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000274 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500275
Richard Hughesf192bf02016-07-22 08:26:43 +0100276 for (guint i = 0; i < devices->len; i++) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100277 FuDevice *device = g_ptr_array_index (devices, i);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500278 GVariant *tmp = fwupd_device_to_variant_full (FWUPD_DEVICE (device),
Richard Hughesdf89cd52020-06-26 20:25:18 +0100279 fu_engine_request_get_device_flags (request));
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000280 g_variant_builder_add_value (&builder, tmp);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000281 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100282 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000283}
284
Richard Hughes9945edb2017-06-19 10:03:55 +0100285static GVariant *
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100286fu_main_plugin_array_to_variant (GPtrArray *plugins)
287{
288 GVariantBuilder builder;
289
290 g_return_val_if_fail (plugins->len > 0, NULL);
291 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
292
293 for (guint i = 0; i < plugins->len; i++) {
294 FuDevice *plugin = g_ptr_array_index (plugins, i);
295 GVariant *tmp = fwupd_plugin_to_variant (FWUPD_PLUGIN (plugin));
296 g_variant_builder_add_value (&builder, tmp);
297 }
298 return g_variant_new ("(aa{sv})", &builder);
299}
300
301static GVariant *
Richard Hughes9945edb2017-06-19 10:03:55 +0100302fu_main_release_array_to_variant (GPtrArray *results)
Richard Hughes060af612016-08-17 17:32:34 +0100303{
Richard Hughes9945edb2017-06-19 10:03:55 +0100304 GVariantBuilder builder;
305 g_return_val_if_fail (results->len > 0, NULL);
306 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
307 for (guint i = 0; i < results->len; i++) {
308 FwupdRelease *rel = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100309 GVariant *tmp = fwupd_release_to_variant (rel);
Richard Hughes9945edb2017-06-19 10:03:55 +0100310 g_variant_builder_add_value (&builder, tmp);
311 }
312 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100313}
314
Richard Hughes9945edb2017-06-19 10:03:55 +0100315static GVariant *
316fu_main_remote_array_to_variant (GPtrArray *remotes)
Richard Hughes060af612016-08-17 17:32:34 +0100317{
Richard Hughes9945edb2017-06-19 10:03:55 +0100318 GVariantBuilder builder;
319 g_return_val_if_fail (remotes->len > 0, NULL);
320 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
321 for (guint i = 0; i < remotes->len; i++) {
322 FwupdRemote *remote = g_ptr_array_index (remotes, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100323 GVariant *tmp = fwupd_remote_to_variant (remote);
Richard Hughes9945edb2017-06-19 10:03:55 +0100324 g_variant_builder_add_value (&builder, tmp);
325 }
326 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100327}
328
Richard Hughes9945edb2017-06-19 10:03:55 +0100329static GVariant *
330fu_main_result_array_to_variant (GPtrArray *results)
Richard Hughes8bbfdf42015-02-26 22:28:09 +0000331{
Richard Hughes9945edb2017-06-19 10:03:55 +0100332 GVariantBuilder builder;
333 g_return_val_if_fail (results->len > 0, NULL);
334 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
335 for (guint i = 0; i < results->len; i++) {
Richard Hughes93b15762017-09-15 11:05:23 +0100336 FwupdDevice *result = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100337 GVariant *tmp = fwupd_device_to_variant (result);
Richard Hughes9945edb2017-06-19 10:03:55 +0100338 g_variant_builder_add_value (&builder, tmp);
339 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100340 return g_variant_new ("(aa{sv})", &builder);
Richard Hughesf508e762015-02-27 12:49:36 +0000341}
342
Richard Hughesf508e762015-02-27 12:49:36 +0000343typedef struct {
344 GDBusMethodInvocation *invocation;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100345 FuEngineRequest *request;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500346#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100347 PolkitSubject *subject;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500348#endif
Richard Hughes4ad41f02018-05-08 14:35:36 +0100349 GPtrArray *install_tasks;
350 GPtrArray *action_ids;
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000351 GPtrArray *checksums;
Richard Hughes3d607622019-03-07 16:59:27 +0000352 guint64 flags;
Richard Hughes5d14def2015-10-07 17:43:10 +0100353 GBytes *blob_cab;
Richard Hughes67ec8982015-03-03 11:39:27 +0000354 FuMainPrivate *priv;
Richard Hughes9945edb2017-06-19 10:03:55 +0100355 gchar *device_id;
Richard Hughesa6bd5582017-09-07 14:32:22 +0100356 gchar *remote_id;
357 gchar *key;
358 gchar *value;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100359 XbSilo *silo;
Richard Hughesf508e762015-02-27 12:49:36 +0000360} FuMainAuthHelper;
361
Richard Hughesf508e762015-02-27 12:49:36 +0000362static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100363fu_main_auth_helper_free (FuMainAuthHelper *helper)
Richard Hughesf508e762015-02-27 12:49:36 +0000364{
Richard Hughes4ced4662016-08-26 11:02:31 +0100365 if (helper->blob_cab != NULL)
Richard Hughes5d14def2015-10-07 17:43:10 +0100366 g_bytes_unref (helper->blob_cab);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500367#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100368 if (helper->subject != NULL)
369 g_object_unref (helper->subject);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500370#endif
Richard Hughes481aa2a2018-09-18 20:51:46 +0100371 if (helper->silo != NULL)
372 g_object_unref (helper->silo);
Richard Hughesdf89cd52020-06-26 20:25:18 +0100373 if (helper->request != NULL)
374 g_object_unref (helper->request);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100375 if (helper->install_tasks != NULL)
376 g_ptr_array_unref (helper->install_tasks);
377 if (helper->action_ids != NULL)
378 g_ptr_array_unref (helper->action_ids);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000379 if (helper->checksums != NULL)
380 g_ptr_array_unref (helper->checksums);
Richard Hughes9945edb2017-06-19 10:03:55 +0100381 g_free (helper->device_id);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100382 g_free (helper->remote_id);
383 g_free (helper->key);
384 g_free (helper->value);
Richard Hughes67ec8982015-03-03 11:39:27 +0000385 g_object_unref (helper->invocation);
Richard Hughesf508e762015-02-27 12:49:36 +0000386 g_free (helper);
387}
388
Mario Limoncielloa98df552018-04-16 12:15:51 -0500389#pragma clang diagnostic push
390#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes9945edb2017-06-19 10:03:55 +0100391G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainAuthHelper, fu_main_auth_helper_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -0500392#pragma clang diagnostic pop
Richard Hughes9945edb2017-06-19 10:03:55 +0100393
Mario Limonciello11b71f42020-10-13 13:39:14 -0500394#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100395/* error may or may not already have been set */
Richard Hughesb75c92d2016-02-20 20:22:00 +0000396static gboolean
Richard Hughes9945edb2017-06-19 10:03:55 +0100397fu_main_authorization_is_valid (PolkitAuthorizationResult *auth, GError **error)
Richard Hughes9a410ce2016-02-28 15:58:54 +0000398{
Richard Hughes9945edb2017-06-19 10:03:55 +0100399 /* failed */
Richard Hughesf508e762015-02-27 12:49:36 +0000400 if (auth == NULL) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100401 g_autofree gchar *message = g_strdup ((*error)->message);
402 g_clear_error (error);
403 g_set_error (error,
Richard Hughes060af612016-08-17 17:32:34 +0100404 FWUPD_ERROR,
405 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100406 "Could not check for auth: %s", message);
407 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000408 }
409
410 /* did not auth */
411 if (!polkit_authorization_result_get_is_authorized (auth)) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100412 g_set_error_literal (error,
Richard Hughes060af612016-08-17 17:32:34 +0100413 FWUPD_ERROR,
414 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100415 "Failed to obtain auth");
416 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000417 }
418
419 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100420 return TRUE;
Richard Hughes5d14def2015-10-07 17:43:10 +0100421}
Mario Limonciello11b71f42020-10-13 13:39:14 -0500422#else
423static gboolean
424fu_main_authorization_is_trusted (FuEngineRequest *request, GError **error)
425{
426 FwupdDeviceFlags flags = fu_engine_request_get_device_flags (request);
427 if ((flags & FWUPD_DEVICE_FLAG_TRUSTED) == 0) {
428 g_set_error_literal (error,
429 FWUPD_ERROR,
430 FWUPD_ERROR_AUTH_FAILED,
431 "permission denied: untrusted client process");
432 return FALSE;
433 }
434 return TRUE;
435}
436#endif /* HAVE_POLKIT */
Richard Hughes5d14def2015-10-07 17:43:10 +0100437
Richard Hughesdf7950b2016-01-31 10:18:40 +0000438static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100439fu_main_authorize_unlock_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100440{
Richard Hughes9945edb2017-06-19 10:03:55 +0100441 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
442 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500443#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100444 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100445
Richard Hughes9945edb2017-06-19 10:03:55 +0100446 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100447 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100448 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
449 res, &error);
450 if (!fu_main_authorization_is_valid (auth, &error)) {
451 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100452 return;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100453 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500454#else
455 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
456 g_dbus_method_invocation_return_gerror (helper->invocation, error);
457 return;
458 }
459#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +0100460
461 /* authenticated */
462 if (!fu_engine_unlock (helper->priv->engine, helper->device_id, &error)) {
463 g_dbus_method_invocation_return_gerror (helper->invocation, error);
464 return;
465 }
466
467 /* success */
468 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100469}
470
471static void
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000472fu_main_authorize_set_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
473{
474 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
475 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500476#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000477 g_autoptr(PolkitAuthorizationResult) auth = NULL;
478
479 /* get result */
480 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
481 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
482 res, &error);
483 if (!fu_main_authorization_is_valid (auth, &error)) {
484 g_dbus_method_invocation_return_gerror (helper->invocation, error);
485 return;
486 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500487#else
488 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
489 g_dbus_method_invocation_return_gerror (helper->invocation, error);
490 return;
491 }
492#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000493
494 /* success */
495 for (guint i = 0; i < helper->checksums->len; i++) {
496 const gchar *csum = g_ptr_array_index (helper->checksums, i);
497 fu_engine_add_approved_firmware (helper->priv->engine, csum);
498 }
499 g_dbus_method_invocation_return_value (helper->invocation, NULL);
500}
501
502static void
Richard Hughes31206832020-07-27 15:31:11 +0100503fu_main_authorize_set_blocked_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
504{
505 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
506 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500507#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +0100508 g_autoptr(PolkitAuthorizationResult) auth = NULL;
509
510 /* get result */
511 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
512 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
513 res, &error);
514 if (!fu_main_authorization_is_valid (auth, &error)) {
515 g_dbus_method_invocation_return_gerror (helper->invocation, error);
516 return;
517 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500518#else
519 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
520 g_dbus_method_invocation_return_gerror (helper->invocation, error);
521 return;
522 }
523#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +0100524
525 /* success */
526 if (!fu_engine_set_blocked_firmware (helper->priv->engine, helper->checksums, &error)) {
527 g_dbus_method_invocation_return_gerror (helper->invocation, error);
528 return;
529 }
530 g_dbus_method_invocation_return_value (helper->invocation, NULL);
531}
532
533static void
Richard Hughes3d607622019-03-07 16:59:27 +0000534fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
535{
536 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
537 g_autofree gchar *sig = NULL;
538 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500539#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +0000540 g_autoptr(PolkitAuthorizationResult) auth = NULL;
541
542 /* get result */
543 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
544 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
545 res, &error);
546 if (!fu_main_authorization_is_valid (auth, &error)) {
547 g_dbus_method_invocation_return_gerror (helper->invocation, error);
548 return;
549 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500550#else
551 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
552 g_dbus_method_invocation_return_gerror (helper->invocation, error);
553 return;
554 }
555#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +0000556
557 /* authenticated */
558 sig = fu_engine_self_sign (helper->priv->engine, helper->value, helper->flags, &error);
559 if (sig == NULL) {
560 g_dbus_method_invocation_return_gerror (helper->invocation, error);
561 return;
562 }
563
564 /* success */
565 g_dbus_method_invocation_return_value (helper->invocation, g_variant_new ("(s)", sig));
566}
567
568static void
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100569fu_main_modify_config_cb (GObject *source, GAsyncResult *res, gpointer user_data)
570{
571 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
572 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500573#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100574 g_autoptr(PolkitAuthorizationResult) auth = NULL;
575
576 /* get result */
577 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
578 res, &error);
579 if (!fu_main_authorization_is_valid (auth, &error)) {
580 g_dbus_method_invocation_return_gerror (helper->invocation, error);
581 return;
582 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500583#else
584 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
585 g_dbus_method_invocation_return_gerror (helper->invocation, error);
586 return;
587 }
588#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100589
590 if (!fu_engine_modify_config (helper->priv->engine, helper->key, helper->value, &error)) {
591 g_dbus_method_invocation_return_gerror (helper->invocation, error);
592 return;
593 }
594
595 /* success */
596 g_dbus_method_invocation_return_value (helper->invocation, NULL);
597}
598
599static void
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600600fu_main_authorize_activate_cb (GObject *source, GAsyncResult *res, gpointer user_data)
601{
602 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
603 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500604#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600605 g_autoptr(PolkitAuthorizationResult) auth = NULL;
606
607 /* get result */
608 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
609 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
610 res, &error);
611 if (!fu_main_authorization_is_valid (auth, &error)) {
612 g_dbus_method_invocation_return_gerror (helper->invocation, error);
613 return;
614 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500615#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600616
617 /* authenticated */
618 if (!fu_engine_activate (helper->priv->engine, helper->device_id, &error)) {
619 g_dbus_method_invocation_return_gerror (helper->invocation, error);
620 return;
621 }
622
623 /* success */
624 g_dbus_method_invocation_return_value (helper->invocation, NULL);
625}
626
627static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100628fu_main_authorize_verify_update_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughesdf7950b2016-01-31 10:18:40 +0000629{
Richard Hughes9945edb2017-06-19 10:03:55 +0100630 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
631 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500632#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100633 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughesdf7950b2016-01-31 10:18:40 +0000634
Richard Hughes9945edb2017-06-19 10:03:55 +0100635 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100636 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100637 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
638 res, &error);
639 if (!fu_main_authorization_is_valid (auth, &error)) {
640 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughesdf7950b2016-01-31 10:18:40 +0000641 return;
Richard Hughesf192bf02016-07-22 08:26:43 +0100642 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500643#else
644 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
645 g_dbus_method_invocation_return_gerror (helper->invocation, error);
646 return;
647 }
648#endif /* HAVE_POLKIT */
Richard Hughesdf7950b2016-01-31 10:18:40 +0000649
Richard Hughes9945edb2017-06-19 10:03:55 +0100650 /* authenticated */
651 if (!fu_engine_verify_update (helper->priv->engine, helper->device_id, &error)) {
652 g_dbus_method_invocation_return_gerror (helper->invocation, error);
653 return;
Richard Hughes404cc512016-12-21 16:09:48 +0000654 }
655
656 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100657 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes99147f12016-05-17 09:35:04 +0100658}
659
Richard Hughes9945edb2017-06-19 10:03:55 +0100660static void
Richard Hughesa6bd5582017-09-07 14:32:22 +0100661fu_main_authorize_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
662{
663 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
664 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500665#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100666 g_autoptr(PolkitAuthorizationResult) auth = NULL;
667
668 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100669 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100670 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
671 res, &error);
672 if (!fu_main_authorization_is_valid (auth, &error)) {
673 g_dbus_method_invocation_return_gerror (helper->invocation, error);
674 return;
675 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500676#else
677 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
678 g_dbus_method_invocation_return_gerror (helper->invocation, error);
679 return;
680 }
681#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +0100682
683 /* authenticated */
684 if (!fu_engine_modify_remote (helper->priv->engine,
685 helper->remote_id,
686 helper->key,
687 helper->value,
688 &error)) {
689 g_dbus_method_invocation_return_gerror (helper->invocation, error);
690 return;
691 }
692
693 /* success */
694 g_dbus_method_invocation_return_value (helper->invocation, NULL);
695}
696
Richard Hughes4ad41f02018-05-08 14:35:36 +0100697static void fu_main_authorize_install_queue (FuMainAuthHelper *helper);
698
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500699#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100700static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100701fu_main_authorize_install_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes404cc512016-12-21 16:09:48 +0000702{
Richard Hughes9945edb2017-06-19 10:03:55 +0100703 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
Richard Hughes46832432015-09-11 13:43:15 +0100704 g_autoptr(GError) error = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +0100705 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes18423292015-03-09 17:10:50 +0000706
Richard Hughes9945edb2017-06-19 10:03:55 +0100707 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100708 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100709 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
710 res, &error);
711 if (!fu_main_authorization_is_valid (auth, &error)) {
712 g_dbus_method_invocation_return_gerror (helper->invocation, error);
713 return;
Richard Hughes0e883ee2015-03-18 17:22:33 +0000714 }
715
Richard Hughes4ad41f02018-05-08 14:35:36 +0100716 /* do the next authentication action ID */
717 fu_main_authorize_install_queue (g_steal_pointer (&helper));
718}
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500719#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100720
721static void
722fu_main_authorize_install_queue (FuMainAuthHelper *helper_ref)
723{
724 FuMainPrivate *priv = helper_ref->priv;
725 g_autoptr(FuMainAuthHelper) helper = helper_ref;
726 g_autoptr(GError) error = NULL;
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500727 gboolean ret;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100728
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500729#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100730 /* still more things to to authenticate */
731 if (helper->action_ids->len > 0) {
732 g_autofree gchar *action_id = g_strdup (g_ptr_array_index (helper->action_ids, 0));
733 g_autoptr(PolkitSubject) subject = g_object_ref (helper->subject);
734 g_ptr_array_remove_index (helper->action_ids, 0);
735 polkit_authority_check_authorization (priv->authority, subject,
736 action_id, NULL,
737 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
738 NULL,
739 fu_main_authorize_install_cb,
740 g_steal_pointer (&helper));
Richard Hughes9945edb2017-06-19 10:03:55 +0100741 return;
Richard Hughes654f6b82016-04-25 12:29:48 +0100742 }
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500743#endif /* HAVE_POLKIT */
Richard Hughes654f6b82016-04-25 12:29:48 +0100744
Richard Hughes4ad41f02018-05-08 14:35:36 +0100745 /* all authenticated, so install all the things */
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500746 priv->update_in_progress = TRUE;
747 ret = fu_engine_install_tasks (helper->priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100748 helper->request,
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500749 helper->install_tasks,
750 helper->blob_cab,
751 helper->flags,
752 &error);
753 priv->update_in_progress = FALSE;
754 if (priv->pending_sigterm)
755 g_main_loop_quit (priv->loop);
756 if (!ret) {
Richard Hughesdbd8c762018-06-15 20:31:40 +0100757 g_dbus_method_invocation_return_gerror (helper->invocation, error);
758 return;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100759 }
760
Richard Hughes654f6b82016-04-25 12:29:48 +0100761 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100762 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes4c369702017-06-16 15:31:38 +0100763}
764
Richard Hughes4ad41f02018-05-08 14:35:36 +0100765#if !GLIB_CHECK_VERSION(2,54,0)
766static gboolean
767g_ptr_array_find (GPtrArray *haystack, gconstpointer needle, guint *index_)
768{
769 for (guint i = 0; i < haystack->len; i++) {
770 gconstpointer *tmp = g_ptr_array_index (haystack, i);
771 if (tmp == needle) {
772 if (index_ != NULL) {
773 *index_ = i;
774 return TRUE;
775 }
776 }
777 }
778 return FALSE;
779}
780#endif
781
Richard Hughes9f86ade2018-05-10 21:11:22 +0100782static gint
783fu_main_install_task_sort_cb (gconstpointer a, gconstpointer b)
784{
785 FuInstallTask *task_a = *((FuInstallTask **) a);
786 FuInstallTask *task_b = *((FuInstallTask **) b);
Richard Hughesc02cb832018-05-20 10:31:04 +0100787 return fu_install_task_compare (task_a, task_b);
Richard Hughes9f86ade2018-05-10 21:11:22 +0100788}
789
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500790static GPtrArray *
791fu_main_get_device_family (FuMainAuthHelper *helper, GError **error)
792{
793 FuDevice *parent;
794 GPtrArray *children;
795 g_autoptr(FuDevice) device = NULL;
796 g_autoptr(GPtrArray) devices_possible = NULL;
797
798 /* get the device */
799 device = fu_engine_get_device (helper->priv->engine, helper->device_id, error);
800 if (device == NULL)
801 return NULL;
802
803 /* device itself */
804 devices_possible = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
805 g_ptr_array_add (devices_possible, g_object_ref (device));
806
807 /* add device children */
808 children = fu_device_get_children (device);
809 for (guint i = 0; i < children->len; i++) {
810 FuDevice *child = g_ptr_array_index (children, i);
811 g_ptr_array_add (devices_possible, g_object_ref (child));
812 }
813
814 /* add parent and siblings, not including the device itself */
815 parent = fu_device_get_parent (device);
816 if (parent != NULL) {
817 GPtrArray *siblings = fu_device_get_children (parent);
818 g_ptr_array_add (devices_possible, g_object_ref (parent));
819 for (guint i = 0; i < siblings->len; i++) {
820 FuDevice *sibling = g_ptr_array_index (siblings, i);
821 if (sibling == device)
822 continue;
823 g_ptr_array_add (devices_possible, g_object_ref (sibling));
824 }
825 }
826
827 /* success */
828 return g_steal_pointer (&devices_possible);
829}
830
Richard Hughes4ad41f02018-05-08 14:35:36 +0100831static gboolean
832fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
833{
834 FuMainPrivate *priv = helper_ref->priv;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100835 g_autoptr(FuMainAuthHelper) helper = helper_ref;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100836 g_autoptr(GPtrArray) components = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100837 g_autoptr(GPtrArray) devices_possible = NULL;
838 g_autoptr(GPtrArray) errors = NULL;
839
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500840 /* get a list of devices that in some way match the device_id */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100841 if (g_strcmp0 (helper->device_id, FWUPD_DEVICE_ID_ANY) == 0) {
842 devices_possible = fu_engine_get_devices (priv->engine, error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500843 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100844 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100845 } else {
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500846 devices_possible = fu_main_get_device_family (helper, error);
847 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100848 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100849 }
850
Richard Hughes481aa2a2018-09-18 20:51:46 +0100851 /* parse silo */
852 helper->silo = fu_engine_get_silo_from_blob (priv->engine,
853 helper->blob_cab,
854 error);
855 if (helper->silo == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100856 return FALSE;
857
Richard Hughes481aa2a2018-09-18 20:51:46 +0100858 /* for each component in the silo */
Richard Hughes4cbe99c2020-11-22 13:14:33 +0000859 components = xb_silo_query (helper->silo,
860 "components/component[@type='firmware']",
861 0, error);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100862 if (components == NULL)
863 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100864 helper->action_ids = g_ptr_array_new_with_free_func (g_free);
865 helper->install_tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
866 errors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_error_free);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100867 for (guint i = 0; i < components->len; i++) {
868 XbNode *component = g_ptr_array_index (components, i);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100869
870 /* do any devices pass the requirements */
871 for (guint j = 0; j < devices_possible->len; j++) {
872 FuDevice *device = g_ptr_array_index (devices_possible, j);
873 const gchar *action_id;
874 g_autoptr(FuInstallTask) task = NULL;
875 g_autoptr(GError) error_local = NULL;
876
877 /* is this component valid for the device */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100878 task = fu_install_task_new (device, component);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100879 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100880 helper->request,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100881 task,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500882 helper->flags | FWUPD_INSTALL_FLAG_FORCE,
883 &error_local)) {
Richard Hughes33dcfb72020-09-28 15:58:39 +0100884 if (!g_error_matches (error_local,
885 FWUPD_ERROR,
886 FWUPD_ERROR_NOT_FOUND)) {
887 g_debug ("first pass requirement on %s:%s failed: %s",
888 fu_device_get_id (device),
889 xb_node_query_text (component, "id", NULL),
890 error_local->message);
891 }
Mario Limonciello537da0e2020-03-09 15:38:17 -0500892 g_ptr_array_add (errors, g_steal_pointer (&error_local));
893 continue;
894 }
895
896 /* make a second pass using possibly updated version format now */
897 fu_engine_md_refresh_device_from_component (priv->engine, device, component);
898 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100899 helper->request,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500900 task,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100901 helper->flags,
Richard Hughes4ad41f02018-05-08 14:35:36 +0100902 &error_local)) {
Mario Limonciello537da0e2020-03-09 15:38:17 -0500903 g_debug ("second pass requirement on %s:%s failed: %s",
Richard Hughes4ad41f02018-05-08 14:35:36 +0100904 fu_device_get_id (device),
Richard Hughes481aa2a2018-09-18 20:51:46 +0100905 xb_node_query_text (component, "id", NULL),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100906 error_local->message);
907 g_ptr_array_add (errors, g_steal_pointer (&error_local));
908 continue;
909 }
Mario Limonciello381c27c2020-10-23 16:32:26 -0500910 if (!fu_engine_check_trust (task, &error_local)) {
911 g_ptr_array_add (errors, g_steal_pointer (&error_local));
912 continue;
913 }
Richard Hughes4ad41f02018-05-08 14:35:36 +0100914
Mario Limonciello7a3df4b2019-01-31 10:27:22 -0600915 /* if component should have an update message from CAB */
916 fu_device_incorporate_from_component (device, component);
917
Richard Hughes4ad41f02018-05-08 14:35:36 +0100918 /* get the action IDs for the valid device */
919 action_id = fu_install_task_get_action_id (task);
920 if (!g_ptr_array_find (helper->action_ids, action_id, NULL))
921 g_ptr_array_add (helper->action_ids, g_strdup (action_id));
922 g_ptr_array_add (helper->install_tasks, g_steal_pointer (&task));
923 }
924 }
925
Richard Hughes9f86ade2018-05-10 21:11:22 +0100926 /* order the install tasks by the device priority */
927 g_ptr_array_sort (helper->install_tasks, fu_main_install_task_sort_cb);
928
Richard Hughes4ad41f02018-05-08 14:35:36 +0100929 /* nothing suitable */
930 if (helper->install_tasks->len == 0) {
Richard Hughese82eef32018-05-20 10:41:26 +0100931 GError *error_tmp = fu_common_error_array_get_best (errors);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100932 g_propagate_error (error, error_tmp);
933 return FALSE;
934 }
935
936 /* authenticate all things in the action_ids */
937 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
938 fu_main_authorize_install_queue (g_steal_pointer (&helper));
939 return TRUE;
940}
941
Richard Hughesb6f79552017-11-11 07:58:17 +0000942static gboolean
943fu_main_device_id_valid (const gchar *device_id, GError **error)
944{
945 if (g_strcmp0 (device_id, FWUPD_DEVICE_ID_ANY) == 0)
946 return TRUE;
947 if (device_id != NULL && strlen (device_id) >= 4)
948 return TRUE;
949 g_set_error (error,
950 FWUPD_ERROR,
951 FWUPD_ERROR_INTERNAL,
952 "invalid device ID: %s",
953 device_id);
954 return FALSE;
955}
956
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000957static void
958fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
959 const gchar *object_path, const gchar *interface_name,
960 const gchar *method_name, GVariant *parameters,
961 GDBusMethodInvocation *invocation, gpointer user_data)
962{
963 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughes9945edb2017-06-19 10:03:55 +0100964 GVariant *val = NULL;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100965 g_autoptr(FuEngineRequest) request = NULL;
Richard Hughes060af612016-08-17 17:32:34 +0100966 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000967
Richard Hughesdf89cd52020-06-26 20:25:18 +0100968 /* build request */
969 request = fu_main_create_request (priv, sender, &error);
970 if (request == NULL) {
971 g_dbus_method_invocation_return_gerror (invocation, error);
972 return;
973 }
974
Richard Hughes75b965d2018-11-15 13:51:21 +0000975 /* activity */
976 fu_engine_idle_reset (priv->engine);
977
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000978 if (g_strcmp0 (method_name, "GetDevices") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100979 g_autoptr(GPtrArray) devices = NULL;
Richard Hughesf508e762015-02-27 12:49:36 +0000980 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100981 devices = fu_engine_get_devices (priv->engine, &error);
982 if (devices == NULL) {
983 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100984 return;
985 }
Richard Hughesdf89cd52020-06-26 20:25:18 +0100986 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500987 if (val == NULL) {
988 g_dbus_method_invocation_return_gerror (invocation, error);
989 return;
990 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100991 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100992 return;
993 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100994 if (g_strcmp0 (method_name, "GetPlugins") == 0) {
995 g_debug ("Called %s()", method_name);
996 val = fu_main_plugin_array_to_variant (fu_engine_get_plugins (priv->engine));
997 g_dbus_method_invocation_return_value (invocation, val);
998 return;
999 }
Richard Hughese4a100c2017-06-04 21:23:50 +01001000 if (g_strcmp0 (method_name, "GetReleases") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001001 const gchar *device_id;
Richard Hughese4a100c2017-06-04 21:23:50 +01001002 g_autoptr(GPtrArray) releases = NULL;
Richard Hughese4a100c2017-06-04 21:23:50 +01001003 g_variant_get (parameters, "(&s)", &device_id);
1004 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001005 if (!fu_main_device_id_valid (device_id, &error)) {
1006 g_dbus_method_invocation_return_gerror (invocation, error);
1007 return;
1008 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001009 releases = fu_engine_get_releases (priv->engine, request, device_id, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001010 if (releases == NULL) {
1011 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughese4a100c2017-06-04 21:23:50 +01001012 return;
1013 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001014 val = fu_main_release_array_to_variant (releases);
1015 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughese4a100c2017-06-04 21:23:50 +01001016 return;
1017 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001018 if (g_strcmp0 (method_name, "GetApprovedFirmware") == 0) {
1019 GVariantBuilder builder;
1020 GPtrArray *checksums = fu_engine_get_approved_firmware (priv->engine);
1021 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1022 for (guint i = 0; i < checksums->len; i++) {
1023 const gchar *checksum = g_ptr_array_index (checksums, i);
1024 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1025 }
1026 val = g_variant_builder_end (&builder);
1027 g_dbus_method_invocation_return_value (invocation,
1028 g_variant_new_tuple (&val, 1));
1029 return;
1030 }
Richard Hughes31206832020-07-27 15:31:11 +01001031 if (g_strcmp0 (method_name, "GetBlockedFirmware") == 0) {
1032 GVariantBuilder builder;
1033 GPtrArray *checksums = fu_engine_get_blocked_firmware (priv->engine);
1034 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1035 for (guint i = 0; i < checksums->len; i++) {
1036 const gchar *checksum = g_ptr_array_index (checksums, i);
1037 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1038 }
1039 val = g_variant_builder_end (&builder);
1040 g_dbus_method_invocation_return_value (invocation,
1041 g_variant_new_tuple (&val, 1));
1042 return;
1043 }
Richard Hughes6ecc4ca2020-05-20 18:42:46 +01001044 if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
1045 GHashTableIter iter;
1046 GVariantBuilder builder;
1047 const gchar *key;
1048 const gchar *value;
1049 g_autoptr(GHashTable) metadata = NULL;
1050
1051 metadata = fu_engine_get_report_metadata (priv->engine, &error);
1052 if (metadata == NULL) {
1053 g_dbus_method_invocation_return_gerror (invocation, error);
1054 return;
1055 }
1056 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
1057 g_hash_table_iter_init (&iter, metadata);
1058 while (g_hash_table_iter_next (&iter,
1059 (gpointer *) &key,
1060 (gpointer *) &value)) {
1061 g_variant_builder_add_value (&builder,
1062 g_variant_new ("{ss}", key, value));
1063 }
1064 val = g_variant_builder_end (&builder);
1065 g_dbus_method_invocation_return_value (invocation,
1066 g_variant_new_tuple (&val, 1));
1067 return;
1068 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001069 if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
1070 g_autofree gchar *checksums_str = NULL;
1071 g_auto(GStrv) checksums = NULL;
1072 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001073#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001074 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001075#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001076
1077 g_variant_get (parameters, "(^as)", &checksums);
1078 checksums_str = g_strjoinv (",", checksums);
1079 g_debug ("Called %s(%s)", method_name, checksums_str);
1080
1081 /* authenticate */
1082 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1083 helper = g_new0 (FuMainAuthHelper, 1);
1084 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001085 helper->request = g_steal_pointer (&request);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001086 helper->invocation = g_object_ref (invocation);
1087 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1088 for (guint i = 0; checksums[i] != NULL; i++)
1089 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001090#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001091 subject = polkit_system_bus_name_new (sender);
1092 polkit_authority_check_authorization (priv->authority, subject,
1093 "org.freedesktop.fwupd.set-approved-firmware",
1094 NULL,
1095 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1096 NULL,
1097 fu_main_authorize_set_approved_firmware_cb,
1098 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001099#else
1100 fu_main_authorize_set_approved_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1101#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001102 return;
1103 }
Richard Hughes31206832020-07-27 15:31:11 +01001104 if (g_strcmp0 (method_name, "SetBlockedFirmware") == 0) {
1105 g_autofree gchar *checksums_str = NULL;
1106 g_auto(GStrv) checksums = NULL;
1107 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001108#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001109 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001110#endif
Richard Hughes31206832020-07-27 15:31:11 +01001111 g_variant_get (parameters, "(^as)", &checksums);
1112 checksums_str = g_strjoinv (",", checksums);
1113 g_debug ("Called %s(%s)", method_name, checksums_str);
1114
1115 /* authenticate */
1116 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1117 helper = g_new0 (FuMainAuthHelper, 1);
1118 helper->priv = priv;
1119 helper->request = g_steal_pointer (&request);
1120 helper->invocation = g_object_ref (invocation);
1121 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1122 for (guint i = 0; checksums[i] != NULL; i++)
1123 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001124#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001125 subject = polkit_system_bus_name_new (sender);
1126 polkit_authority_check_authorization (priv->authority, subject,
1127 "org.freedesktop.fwupd.set-approved-firmware",
1128 NULL,
1129 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1130 NULL,
1131 fu_main_authorize_set_blocked_firmware_cb,
1132 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001133#else
1134 fu_main_authorize_set_blocked_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1135#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +01001136 return;
1137 }
Richard Hughes3d607622019-03-07 16:59:27 +00001138 if (g_strcmp0 (method_name, "SelfSign") == 0) {
1139 GVariant *prop_value;
1140 gchar *prop_key;
1141 g_autofree gchar *value = NULL;
1142 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001143#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001144 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001145#endif
Richard Hughes3d607622019-03-07 16:59:27 +00001146 g_autoptr(GVariantIter) iter = NULL;
1147
1148 g_variant_get (parameters, "(sa{sv})", &value, &iter);
1149 g_debug ("Called %s(%s)", method_name, value);
1150
1151 /* get flags */
1152 helper = g_new0 (FuMainAuthHelper, 1);
1153 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
1154 g_debug ("got option %s", prop_key);
1155 if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
1156 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001157 helper->flags |= JCAT_SIGN_FLAG_ADD_TIMESTAMP;
Richard Hughes3d607622019-03-07 16:59:27 +00001158 if (g_strcmp0 (prop_key, "add-cert") == 0 &&
1159 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001160 helper->flags |= JCAT_SIGN_FLAG_ADD_CERT;
Richard Hughes3d607622019-03-07 16:59:27 +00001161 g_variant_unref (prop_value);
1162 }
1163
1164 /* authenticate */
1165 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1166 helper->priv = priv;
1167 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001168 helper->request = g_steal_pointer (&request);
Richard Hughes3d607622019-03-07 16:59:27 +00001169 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001170#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001171 subject = polkit_system_bus_name_new (sender);
1172 polkit_authority_check_authorization (priv->authority, subject,
1173 "org.freedesktop.fwupd.self-sign",
1174 NULL,
1175 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1176 NULL,
1177 fu_main_authorize_self_sign_cb,
1178 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001179#else
1180 fu_main_authorize_self_sign_cb (NULL, NULL, g_steal_pointer (&helper));
1181#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +00001182 return;
1183 }
Richard Hughes97284b12017-09-13 17:07:58 +01001184 if (g_strcmp0 (method_name, "GetDowngrades") == 0) {
1185 const gchar *device_id;
1186 g_autoptr(GPtrArray) releases = NULL;
1187 g_variant_get (parameters, "(&s)", &device_id);
1188 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001189 if (!fu_main_device_id_valid (device_id, &error)) {
1190 g_dbus_method_invocation_return_gerror (invocation, error);
1191 return;
1192 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001193 releases = fu_engine_get_downgrades (priv->engine, request, device_id, &error);
Richard Hughes97284b12017-09-13 17:07:58 +01001194 if (releases == NULL) {
1195 g_dbus_method_invocation_return_gerror (invocation, error);
1196 return;
1197 }
1198 val = fu_main_release_array_to_variant (releases);
1199 g_dbus_method_invocation_return_value (invocation, val);
1200 return;
1201 }
Richard Hughesa96413a2017-09-13 17:19:59 +01001202 if (g_strcmp0 (method_name, "GetUpgrades") == 0) {
1203 const gchar *device_id;
1204 g_autoptr(GPtrArray) releases = NULL;
1205 g_variant_get (parameters, "(&s)", &device_id);
1206 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001207 if (!fu_main_device_id_valid (device_id, &error)) {
1208 g_dbus_method_invocation_return_gerror (invocation, error);
1209 return;
1210 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001211 releases = fu_engine_get_upgrades (priv->engine, request, device_id, &error);
Richard Hughesa96413a2017-09-13 17:19:59 +01001212 if (releases == NULL) {
1213 g_dbus_method_invocation_return_gerror (invocation, error);
1214 return;
1215 }
1216 val = fu_main_release_array_to_variant (releases);
1217 g_dbus_method_invocation_return_value (invocation, val);
1218 return;
1219 }
Richard Hughes4c369702017-06-16 15:31:38 +01001220 if (g_strcmp0 (method_name, "GetRemotes") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001221 g_autoptr(GPtrArray) remotes = NULL;
Richard Hughes4c369702017-06-16 15:31:38 +01001222 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001223 remotes = fu_engine_get_remotes (priv->engine, &error);
1224 if (remotes == NULL) {
1225 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes4c369702017-06-16 15:31:38 +01001226 return;
1227 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001228 val = fu_main_remote_array_to_variant (remotes);
1229 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes4c369702017-06-16 15:31:38 +01001230 return;
1231 }
Richard Hughes476363a2018-01-11 10:08:58 +00001232 if (g_strcmp0 (method_name, "GetHistory") == 0) {
1233 g_autoptr(GPtrArray) devices = NULL;
1234 g_debug ("Called %s()", method_name);
1235 devices = fu_engine_get_history (priv->engine, &error);
1236 if (devices == NULL) {
1237 g_dbus_method_invocation_return_gerror (invocation, error);
1238 return;
1239 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001240 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -05001241 if (val == NULL) {
1242 g_dbus_method_invocation_return_gerror (invocation, error);
1243 return;
1244 }
Richard Hughes476363a2018-01-11 10:08:58 +00001245 g_dbus_method_invocation_return_value (invocation, val);
1246 return;
1247 }
Richard Hughes196c6c62020-05-11 19:42:47 +01001248 if (g_strcmp0 (method_name, "GetHostSecurityAttrs") == 0) {
Richard Hughesf58ac732020-05-12 15:23:44 +01001249 g_autoptr(FuSecurityAttrs) attrs = NULL;
Richard Hughes196c6c62020-05-11 19:42:47 +01001250 g_debug ("Called %s()", method_name);
Richard Hughesa018b3c2020-08-28 17:08:19 +01001251 if (priv->machine_kind != FU_MAIN_MACHINE_KIND_PHYSICAL) {
1252 g_dbus_method_invocation_return_error_literal (invocation,
1253 FWUPD_ERROR,
1254 FWUPD_ERROR_NOT_SUPPORTED,
1255 "HSI unavailable for hypervisor");
1256 return;
1257 }
Richard Hughes56e7ae52020-05-17 21:00:23 +01001258 attrs = fu_engine_get_host_security_attrs (priv->engine);
Richard Hughesf58ac732020-05-12 15:23:44 +01001259 val = fu_security_attrs_to_variant (attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001260 g_dbus_method_invocation_return_value (invocation, val);
1261 return;
1262 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001263 if (g_strcmp0 (method_name, "ClearResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001264 const gchar *device_id;
1265 g_variant_get (parameters, "(&s)", &device_id);
1266 g_debug ("Called %s(%s)", method_name, device_id);
1267 if (!fu_engine_clear_results (priv->engine, device_id, &error)) {
1268 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001269 return;
1270 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001271 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001272 return;
1273 }
Richard Hughes6b222952018-01-11 10:20:48 +00001274 if (g_strcmp0 (method_name, "ModifyDevice") == 0) {
1275 const gchar *device_id;
1276 const gchar *key = NULL;
1277 const gchar *value = NULL;
1278
1279 /* check the id exists */
1280 g_variant_get (parameters, "(&s&s&s)", &device_id, &key, &value);
1281 g_debug ("Called %s(%s,%s=%s)", method_name, device_id, key, value);
1282 if (!fu_engine_modify_device (priv->engine, device_id, key, value, &error)) {
1283 g_dbus_method_invocation_return_gerror (invocation, error);
1284 return;
1285 }
1286 g_dbus_method_invocation_return_value (invocation, NULL);
1287 return;
1288 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001289 if (g_strcmp0 (method_name, "GetResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001290 const gchar *device_id = NULL;
Richard Hughes93b15762017-09-15 11:05:23 +01001291 g_autoptr(FwupdDevice) result = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +01001292 g_variant_get (parameters, "(&s)", &device_id);
1293 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001294 if (!fu_main_device_id_valid (device_id, &error)) {
1295 g_dbus_method_invocation_return_gerror (invocation, error);
1296 return;
1297 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001298 result = fu_engine_get_results (priv->engine, device_id, &error);
1299 if (result == NULL) {
1300 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001301 return;
1302 }
Richard Hughese0bd53e2017-09-17 08:29:02 +01001303 val = fwupd_device_to_variant (result);
1304 g_dbus_method_invocation_return_value (invocation,
1305 g_variant_new_tuple (&val, 1));
Richard Hughes0e883ee2015-03-18 17:22:33 +00001306 return;
1307 }
Richard Hughesba73c762017-09-15 14:31:17 +01001308 if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
Richard Hughes1b50d962017-06-02 12:23:00 +01001309 GDBusMessage *message;
1310 GUnixFDList *fd_list;
Richard Hughes9945edb2017-06-19 10:03:55 +01001311 const gchar *remote_id = NULL;
Richard Hughes1b50d962017-06-02 12:23:00 +01001312 gint fd_data;
1313 gint fd_sig;
1314
Richard Hughes9945edb2017-06-19 10:03:55 +01001315 g_variant_get (parameters, "(&shh)", &remote_id, &fd_data, &fd_sig);
1316 g_debug ("Called %s(%s,%i,%i)", method_name, remote_id, fd_data, fd_sig);
Richard Hughes1b50d962017-06-02 12:23:00 +01001317
Richard Hughes5935ebd2017-06-16 15:40:31 +01001318 /* update the metadata store */
Richard Hughes1b50d962017-06-02 12:23:00 +01001319 message = g_dbus_method_invocation_get_message (invocation);
1320 fd_list = g_dbus_message_get_unix_fd_list (message);
1321 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
1322 g_set_error (&error,
1323 FWUPD_ERROR,
1324 FWUPD_ERROR_INTERNAL,
1325 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001326 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001327 return;
1328 }
1329 fd_data = g_unix_fd_list_get (fd_list, 0, &error);
1330 if (fd_data < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001331 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001332 return;
1333 }
1334 fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
1335 if (fd_sig < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001336 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001337 return;
1338 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001339
1340 /* store new metadata (will close the fds when done) */
1341 if (!fu_engine_update_metadata (priv->engine, remote_id,
1342 fd_data, fd_sig, &error)) {
Richard Hughesf3d46c62017-11-28 14:01:30 +00001343 g_prefix_error (&error, "Failed to update metadata for %s: ", remote_id);
Richard Hughes9945edb2017-06-19 10:03:55 +01001344 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001345 return;
1346 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001347 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001348 return;
1349 }
Richard Hughes9a410ce2016-02-28 15:58:54 +00001350 if (g_strcmp0 (method_name, "Unlock") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001351 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001352 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001353#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001354 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001355#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +01001356 g_variant_get (parameters, "(&s)", &device_id);
1357 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001358 if (!fu_main_device_id_valid (device_id, &error)) {
1359 g_dbus_method_invocation_return_gerror (invocation, error);
1360 return;
1361 }
Richard Hughesfe5cc902016-06-29 10:00:00 +01001362
Richard Hughes9a410ce2016-02-28 15:58:54 +00001363 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001364 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes9945edb2017-06-19 10:03:55 +01001365 helper = g_new0 (FuMainAuthHelper, 1);
1366 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001367 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001368 helper->invocation = g_object_ref (invocation);
1369 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001370#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001371 subject = polkit_system_bus_name_new (sender);
Richard Hughes9945edb2017-06-19 10:03:55 +01001372 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes9a410ce2016-02-28 15:58:54 +00001373 "org.freedesktop.fwupd.device-unlock",
1374 NULL,
1375 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1376 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001377 fu_main_authorize_unlock_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001378 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001379#else
1380 fu_main_authorize_unlock_cb (NULL, NULL, g_steal_pointer (&helper));
1381#endif /* HAVE_POLKIT */
Richard Hughes9a410ce2016-02-28 15:58:54 +00001382 return;
1383 }
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001384 if (g_strcmp0 (method_name, "Activate") == 0) {
1385 const gchar *device_id = NULL;
1386 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001387#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001388 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001389#endif
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001390 g_variant_get (parameters, "(&s)", &device_id);
1391 g_debug ("Called %s(%s)", method_name, device_id);
1392 if (!fu_main_device_id_valid (device_id, &error)) {
1393 g_dbus_method_invocation_return_gerror (invocation, error);
1394 return;
1395 }
1396
1397 /* authenticate */
1398 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1399 helper = g_new0 (FuMainAuthHelper, 1);
1400 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001401 helper->request = g_steal_pointer (&request);
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001402 helper->invocation = g_object_ref (invocation);
1403 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001404#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001405 subject = polkit_system_bus_name_new (sender);
1406 polkit_authority_check_authorization (priv->authority, subject,
1407 "org.freedesktop.fwupd.device-activate",
1408 NULL,
1409 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1410 NULL,
1411 fu_main_authorize_activate_cb,
1412 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001413#else
1414 fu_main_authorize_activate_cb (NULL, NULL, g_steal_pointer (&helper));
1415#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001416 return;
1417 }
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001418 if (g_strcmp0 (method_name, "ModifyConfig") == 0) {
1419 g_autofree gchar *key = NULL;
1420 g_autofree gchar *value = NULL;
1421 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001422#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001423 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001424#endif
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001425 g_variant_get (parameters, "(ss)", &key, &value);
1426 g_debug ("Called %s(%s=%s)", method_name, key, value);
1427
1428 /* authenticate */
1429 helper = g_new0 (FuMainAuthHelper, 1);
1430 helper->priv = priv;
1431 helper->key = g_steal_pointer (&key);
1432 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001433 helper->request = g_steal_pointer (&request);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001434 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001435#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001436 subject = polkit_system_bus_name_new (sender);
1437 polkit_authority_check_authorization (priv->authority, subject,
1438 "org.freedesktop.fwupd.modify-config",
1439 NULL,
1440 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1441 NULL,
1442 fu_main_modify_config_cb,
1443 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001444#else
1445 fu_main_modify_config_cb (NULL, NULL, g_steal_pointer (&helper));
1446#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001447 return;
1448 }
Richard Hughesa6bd5582017-09-07 14:32:22 +01001449 if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
Richard Hughesa6bd5582017-09-07 14:32:22 +01001450 const gchar *remote_id = NULL;
1451 const gchar *key = NULL;
1452 const gchar *value = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001453 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001454#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001455 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001456#endif
Richard Hughesa6bd5582017-09-07 14:32:22 +01001457 /* check the id exists */
1458 g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
1459 g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
1460
1461 /* create helper object */
1462 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001463 helper->request = g_steal_pointer (&request);
Richard Hughesa6bd5582017-09-07 14:32:22 +01001464 helper->invocation = g_object_ref (invocation);
1465 helper->remote_id = g_strdup (remote_id);
1466 helper->key = g_strdup (key);
1467 helper->value = g_strdup (value);
1468 helper->priv = priv;
1469
1470 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001471 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001472#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001473 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001474 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughesa6bd5582017-09-07 14:32:22 +01001475 "org.freedesktop.fwupd.modify-remote",
1476 NULL,
1477 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1478 NULL,
1479 fu_main_authorize_modify_remote_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001480 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001481#else
1482 fu_main_authorize_modify_remote_cb (NULL, NULL, g_steal_pointer (&helper));
1483#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +01001484 return;
1485 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001486 if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001487 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001488 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001489#ifdef HAVE_POLKIT
Richard Hughes29c220d2016-12-14 17:09:54 +00001490 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001491#endif
Richard Hughes29c220d2016-12-14 17:09:54 +00001492
1493 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001494 g_variant_get (parameters, "(&s)", &device_id);
1495 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001496 if (!fu_main_device_id_valid (device_id, &error)) {
1497 g_dbus_method_invocation_return_gerror (invocation, error);
1498 return;
1499 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001500
Richard Hughes9945edb2017-06-19 10:03:55 +01001501 /* create helper object */
Richard Hughes29c220d2016-12-14 17:09:54 +00001502 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001503 helper->request = g_steal_pointer (&request);
Richard Hughes29c220d2016-12-14 17:09:54 +00001504 helper->invocation = g_object_ref (invocation);
Richard Hughes9945edb2017-06-19 10:03:55 +01001505 helper->device_id = g_strdup (device_id);
Richard Hughes29c220d2016-12-14 17:09:54 +00001506 helper->priv = priv;
Richard Hughes29c220d2016-12-14 17:09:54 +00001507
1508 /* authenticate */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001509#ifdef HAVE_POLKIT
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001510 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes29c220d2016-12-14 17:09:54 +00001511 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001512 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes29c220d2016-12-14 17:09:54 +00001513 "org.freedesktop.fwupd.verify-update",
1514 NULL,
1515 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1516 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001517 fu_main_authorize_verify_update_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001518 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001519#else
1520 fu_main_authorize_verify_update_cb (NULL, NULL, g_steal_pointer (&helper));
1521#endif /* HAVE_POLKIT */
Richard Hughes29c220d2016-12-14 17:09:54 +00001522 return;
1523 }
Richard Hughesa043c2e2015-06-29 08:43:18 +01001524 if (g_strcmp0 (method_name, "Verify") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001525 const gchar *device_id = NULL;
1526 g_variant_get (parameters, "(&s)", &device_id);
1527 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001528 if (!fu_main_device_id_valid (device_id, &error)) {
1529 g_dbus_method_invocation_return_gerror (invocation, error);
1530 return;
1531 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001532 if (!fu_engine_verify (priv->engine, device_id, &error)) {
1533 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001534 return;
1535 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001536 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001537 return;
1538 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001539 if (g_strcmp0 (method_name, "SetFeatureFlags") == 0) {
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001540 FwupdFeatureFlags feature_flags;
1541 guint64 feature_flags_u64 = 0;
1542 g_variant_get (parameters, "(t)", &feature_flags_u64);
1543 g_debug ("Called %s(%" G_GUINT64_FORMAT ")", method_name, feature_flags_u64);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001544
1545 /* old flags for the same sender will be automatically destroyed */
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001546 feature_flags = feature_flags_u64;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001547 g_hash_table_insert (priv->sender_features,
1548 g_strdup (sender),
Richard Hughesc9088e72021-03-15 15:58:13 +00001549#if GLIB_CHECK_VERSION(2,67,4)
1550 g_memdup2 (&feature_flags, sizeof(feature_flags)));
1551#else
Richard Hughesdf89cd52020-06-26 20:25:18 +01001552 g_memdup (&feature_flags, sizeof(feature_flags)));
Richard Hughesc9088e72021-03-15 15:58:13 +00001553#endif
Richard Hughesdf89cd52020-06-26 20:25:18 +01001554 g_dbus_method_invocation_return_value (invocation, NULL);
1555 return;
1556 }
Richard Hughes63a407a2015-07-22 08:54:14 +01001557 if (g_strcmp0 (method_name, "Install") == 0) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001558 GVariant *prop_value;
Richard Hughes9945edb2017-06-19 10:03:55 +01001559 const gchar *device_id = NULL;
Richard Hughes74cc2172015-02-27 13:19:46 +00001560 gchar *prop_key;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001561 gint32 fd_handle = 0;
1562 gint fd;
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001563 guint64 archive_size_max;
Richard Hughes9945edb2017-06-19 10:03:55 +01001564 GDBusMessage *message;
1565 GUnixFDList *fd_list;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001566 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001567 g_autoptr(GVariantIter) iter = NULL;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001568
1569 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001570 g_variant_get (parameters, "(&sha{sv})", &device_id, &fd_handle, &iter);
1571 g_debug ("Called %s(%s,%i)", method_name, device_id, fd_handle);
Richard Hughesb6f79552017-11-11 07:58:17 +00001572 if (!fu_main_device_id_valid (device_id, &error)) {
1573 g_dbus_method_invocation_return_gerror (invocation, error);
1574 return;
1575 }
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001576
Richard Hughes9945edb2017-06-19 10:03:55 +01001577 /* create helper object */
1578 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001579 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001580 helper->invocation = g_object_ref (invocation);
1581 helper->device_id = g_strdup (device_id);
1582 helper->priv = priv;
1583
1584 /* get flags */
1585 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001586 g_debug ("got option %s", prop_key);
1587 if (g_strcmp0 (prop_key, "offline") == 0 &&
1588 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001589 helper->flags |= FWUPD_INSTALL_FLAG_OFFLINE;
Richard Hughese7c12642015-03-04 20:28:59 +00001590 if (g_strcmp0 (prop_key, "allow-older") == 0 &&
1591 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001592 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_OLDER;
Richard Hughese7c12642015-03-04 20:28:59 +00001593 if (g_strcmp0 (prop_key, "allow-reinstall") == 0 &&
1594 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001595 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
Richard Hughes5bbf0132020-10-05 13:44:39 +01001596 if (g_strcmp0 (prop_key, "allow-branch-switch") == 0 &&
1597 g_variant_get_boolean (prop_value) == TRUE)
1598 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH;
Mario Limonciello71a5b982016-05-10 15:38:53 -05001599 if (g_strcmp0 (prop_key, "force") == 0 &&
Richard Hughes6450d0d2020-10-06 16:05:24 +01001600 g_variant_get_boolean (prop_value) == TRUE) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001601 helper->flags |= FWUPD_INSTALL_FLAG_FORCE;
Richard Hughes6450d0d2020-10-06 16:05:24 +01001602 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
1603 }
1604 if (g_strcmp0 (prop_key, "ignore-power") == 0 &&
1605 g_variant_get_boolean (prop_value) == TRUE)
1606 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
Richard Hughes76e0f942018-05-14 16:24:00 +01001607 if (g_strcmp0 (prop_key, "no-history") == 0 &&
1608 g_variant_get_boolean (prop_value) == TRUE)
1609 helper->flags |= FWUPD_INSTALL_FLAG_NO_HISTORY;
Richard Hughes1ffde6c2015-03-02 22:44:48 +00001610 g_variant_unref (prop_value);
Richard Hughes74cc2172015-02-27 13:19:46 +00001611 }
1612
Richard Hughes9945edb2017-06-19 10:03:55 +01001613
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001614 /* get the fd */
1615 message = g_dbus_method_invocation_get_message (invocation);
1616 fd_list = g_dbus_message_get_unix_fd_list (message);
1617 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001618 g_set_error (&error,
1619 FWUPD_ERROR,
1620 FWUPD_ERROR_INTERNAL,
1621 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001622 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001623 return;
1624 }
Richard Hughes7419e962016-11-22 19:48:06 +00001625 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001626 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001627 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001628 return;
1629 }
1630
Richard Hughes9945edb2017-06-19 10:03:55 +01001631 /* parse the cab file before authenticating so we can work out
1632 * what action ID to use, for instance, if this is trusted --
1633 * this will also close the fd when done */
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001634 archive_size_max = fu_engine_get_archive_size_max (priv->engine);
1635 helper->blob_cab = fu_common_get_contents_fd (fd, archive_size_max, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001636 if (helper->blob_cab == NULL) {
1637 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes5d14def2015-10-07 17:43:10 +01001638 return;
1639 }
Richard Hughes4ad41f02018-05-08 14:35:36 +01001640
1641 /* install all the things in the store */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001642#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +01001643 helper->subject = polkit_system_bus_name_new (sender);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001644#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +01001645 if (!fu_main_install_with_helper (g_steal_pointer (&helper), &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001646 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes18423292015-03-09 17:10:50 +00001647 return;
1648 }
1649
Richard Hughes4ad41f02018-05-08 14:35:36 +01001650 /* async return */
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001651 return;
1652 }
Richard Hughes07f963a2017-09-15 14:28:47 +01001653 if (g_strcmp0 (method_name, "GetDetails") == 0) {
Richard Hughes7289a6b2016-05-29 09:27:47 +01001654 GDBusMessage *message;
1655 GUnixFDList *fd_list;
1656 gint32 fd_handle = 0;
1657 gint fd;
Richard Hughes9945edb2017-06-19 10:03:55 +01001658 g_autoptr(GPtrArray) results = NULL;
Richard Hughes7289a6b2016-05-29 09:27:47 +01001659
1660 /* get parameters */
1661 g_variant_get (parameters, "(h)", &fd_handle);
1662 g_debug ("Called %s(%i)", method_name, fd_handle);
1663
1664 /* get the fd */
1665 message = g_dbus_method_invocation_get_message (invocation);
1666 fd_list = g_dbus_message_get_unix_fd_list (message);
1667 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001668 g_set_error (&error,
1669 FWUPD_ERROR,
1670 FWUPD_ERROR_INTERNAL,
1671 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001672 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001673 return;
1674 }
Richard Hughes7419e962016-11-22 19:48:06 +00001675 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001676 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001677 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001678 return;
1679 }
1680
Richard Hughes9945edb2017-06-19 10:03:55 +01001681 /* get details about the file (will close the fd when done) */
Richard Hughesdf89cd52020-06-26 20:25:18 +01001682 results = fu_engine_get_details (priv->engine, request, fd, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001683 if (results == NULL) {
1684 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001685 return;
1686 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001687 val = fu_main_result_array_to_variant (results);
1688 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001689 return;
1690 }
Richard Hughes060af612016-08-17 17:32:34 +01001691 g_set_error (&error,
1692 G_DBUS_ERROR,
1693 G_DBUS_ERROR_UNKNOWN_METHOD,
1694 "no such method %s", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001695 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001696}
1697
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001698static GVariant *
1699fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
1700 const gchar *object_path, const gchar *interface_name,
1701 const gchar *property_name, GError **error,
1702 gpointer user_data)
1703{
Richard Hughes773ce982015-03-09 22:40:57 +00001704 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1705
Richard Hughes75b965d2018-11-15 13:51:21 +00001706 /* activity */
1707 fu_engine_idle_reset (priv->engine);
1708
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001709 if (g_strcmp0 (property_name, "DaemonVersion") == 0)
Richard Hughesfe4b3ea2020-03-30 10:53:20 +01001710 return g_variant_new_string (SOURCE_VERSION);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001711
Richard Hughesf425d292019-01-18 17:57:39 +00001712 if (g_strcmp0 (property_name, "Tainted") == 0)
1713 return g_variant_new_boolean (fu_engine_get_tainted (priv->engine));
1714
Richard Hughes773ce982015-03-09 22:40:57 +00001715 if (g_strcmp0 (property_name, "Status") == 0)
Richard Hughes9945edb2017-06-19 10:03:55 +01001716 return g_variant_new_uint32 (fu_engine_get_status (priv->engine));
Richard Hughes773ce982015-03-09 22:40:57 +00001717
Mario Limonciello20cc9ee2019-09-05 07:27:26 -05001718 if (g_strcmp0 (property_name, "HostProduct") == 0)
1719 return g_variant_new_string (fu_engine_get_host_product (priv->engine));
1720
Richard Hughes0917fb62019-09-21 12:55:37 +01001721 if (g_strcmp0 (property_name, "HostMachineId") == 0)
1722 return g_variant_new_string (fu_engine_get_host_machine_id (priv->engine));
1723
Richard Hughes196c6c62020-05-11 19:42:47 +01001724 if (g_strcmp0 (property_name, "HostSecurityId") == 0)
1725 return g_variant_new_string (fu_engine_get_host_security_id (priv->engine));
1726
Mario Limoncielloeb4c7642019-11-11 10:31:29 -06001727 if (g_strcmp0 (property_name, "Interactive") == 0)
1728 return g_variant_new_boolean (isatty (fileno (stdout)) != 0);
1729
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001730 /* return an error */
1731 g_set_error (error,
Richard Hughes8645ec92015-03-19 10:14:32 +00001732 G_DBUS_ERROR,
1733 G_DBUS_ERROR_UNKNOWN_PROPERTY,
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001734 "failed to get daemon property %s",
1735 property_name);
1736 return NULL;
1737}
1738
Richard Hughesfd468842015-04-22 16:44:08 +01001739static void
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001740fu_main_on_bus_acquired_cb (GDBusConnection *connection,
1741 const gchar *name,
1742 gpointer user_data)
1743{
1744 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1745 guint registration_id;
Richard Hughes46832432015-09-11 13:43:15 +01001746 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001747 static const GDBusInterfaceVTable interface_vtable = {
1748 fu_main_daemon_method_call,
1749 fu_main_daemon_get_property,
1750 NULL
1751 };
1752
1753 priv->connection = g_object_ref (connection);
1754 registration_id = g_dbus_connection_register_object (connection,
1755 FWUPD_DBUS_PATH,
1756 priv->introspection_daemon->interfaces[0],
1757 &interface_vtable,
1758 priv, /* user_data */
1759 NULL, /* user_data_free_func */
1760 NULL); /* GError** */
1761 g_assert (registration_id > 0);
Richard Hughes18423292015-03-09 17:10:50 +00001762
1763 /* connect to D-Bus directly */
1764 priv->proxy_uid =
1765 g_dbus_proxy_new_sync (priv->connection,
1766 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1767 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1768 NULL,
1769 "org.freedesktop.DBus",
1770 "/org/freedesktop/DBus",
1771 "org.freedesktop.DBus",
1772 NULL,
1773 &error);
1774 if (priv->proxy_uid == NULL) {
1775 g_warning ("cannot connect to DBus: %s", error->message);
1776 return;
1777 }
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001778}
1779
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001780static void
1781fu_main_on_name_acquired_cb (GDBusConnection *connection,
1782 const gchar *name,
1783 gpointer user_data)
1784{
Richard Hughes33dcfb72020-09-28 15:58:39 +01001785 g_debug ("acquired name: %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001786}
1787
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001788static void
1789fu_main_on_name_lost_cb (GDBusConnection *connection,
1790 const gchar *name,
1791 gpointer user_data)
1792{
1793 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Mario Limonciello471a0e22020-06-09 10:49:49 -05001794 g_warning ("another service has claimed the dbus name %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001795 g_main_loop_quit (priv->loop);
1796}
1797
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001798static gboolean
1799fu_main_timed_exit_cb (gpointer user_data)
1800{
1801 GMainLoop *loop = (GMainLoop *) user_data;
1802 g_main_loop_quit (loop);
1803 return G_SOURCE_REMOVE;
1804}
1805
Richard Hughesf3dc1622019-03-27 12:48:39 +00001806static void
1807fu_main_argv_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file,
1808 GFileMonitorEvent event_type, gpointer user_data)
1809{
1810 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1811
1812 /* can do straight away? */
1813 if (priv->update_in_progress) {
1814 g_warning ("binary changed during a firmware update, ignoring");
1815 return;
1816 }
1817 g_debug ("binary changed, shutting down");
1818 g_main_loop_quit (priv->loop);
1819}
1820
Richard Hughes603e4f62019-12-11 13:44:09 +00001821#if GLIB_CHECK_VERSION(2,63,3)
1822static void
1823fu_main_memory_monitor_warning_cb (GMemoryMonitor *memory_monitor,
1824 GMemoryMonitorWarningLevel level,
1825 FuMainPrivate *priv)
1826{
1827 /* can do straight away? */
1828 if (priv->update_in_progress) {
1829 g_warning ("OOM during a firmware update, ignoring");
1830 priv->pending_sigterm = TRUE;
1831 return;
1832 }
1833 g_debug ("OOM event, shutting down");
1834 g_main_loop_quit (priv->loop);
1835}
1836#endif
1837
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001838static GDBusNodeInfo *
1839fu_main_load_introspection (const gchar *filename, GError **error)
1840{
Richard Hughes46832432015-09-11 13:43:15 +01001841 g_autoptr(GBytes) data = NULL;
1842 g_autofree gchar *path = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001843
1844 /* lookup data */
1845 path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL);
1846 data = g_resource_lookup_data (fu_get_resource (),
1847 path,
1848 G_RESOURCE_LOOKUP_FLAGS_NONE,
1849 error);
1850 if (data == NULL)
1851 return NULL;
1852
1853 /* build introspection from XML */
1854 return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error);
1855}
1856
Richard Hughesa018b3c2020-08-28 17:08:19 +01001857static gboolean
1858fu_main_is_hypervisor (void)
1859{
1860 g_autofree gchar *buf = NULL;
1861 gsize bufsz = 0;
1862 if (!g_file_get_contents ("/proc/cpuinfo", &buf, &bufsz, NULL))
1863 return FALSE;
1864 return g_strstr_len (buf, (gssize) bufsz, "hypervisor") != NULL;
1865}
1866
1867static gboolean
1868fu_main_is_container (void)
1869{
1870 g_autofree gchar *buf = NULL;
1871 gsize bufsz = 0;
1872 if (!g_file_get_contents ("/proc/1/cgroup", &buf, &bufsz, NULL))
1873 return FALSE;
1874 if (g_strstr_len (buf, (gssize) bufsz, "docker") != NULL)
1875 return TRUE;
1876 if (g_strstr_len (buf, (gssize) bufsz, "lxc") != NULL)
1877 return TRUE;
1878 return FALSE;
1879}
1880
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001881static void
1882fu_main_private_free (FuMainPrivate *priv)
1883{
Richard Hughesdf89cd52020-06-26 20:25:18 +01001884 g_hash_table_unref (priv->sender_features);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001885 if (priv->loop != NULL)
1886 g_main_loop_unref (priv->loop);
1887 if (priv->owner_id > 0)
1888 g_bus_unown_name (priv->owner_id);
1889 if (priv->proxy_uid != NULL)
1890 g_object_unref (priv->proxy_uid);
Richard Hughes9945edb2017-06-19 10:03:55 +01001891 if (priv->engine != NULL)
1892 g_object_unref (priv->engine);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001893 if (priv->connection != NULL)
1894 g_object_unref (priv->connection);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001895#ifdef HAVE_POLKIT
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001896 if (priv->authority != NULL)
1897 g_object_unref (priv->authority);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001898#endif
Richard Hughes0b6f5832020-09-01 20:15:02 +01001899 if (priv->argv0_monitor != NULL) {
1900 g_file_monitor_cancel (priv->argv0_monitor);
Richard Hughesf3dc1622019-03-27 12:48:39 +00001901 g_object_unref (priv->argv0_monitor);
Richard Hughes0b6f5832020-09-01 20:15:02 +01001902 }
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001903 if (priv->introspection_daemon != NULL)
1904 g_dbus_node_info_unref (priv->introspection_daemon);
Richard Hughes603e4f62019-12-11 13:44:09 +00001905#if GLIB_CHECK_VERSION(2,63,3)
1906 if (priv->memory_monitor != NULL)
1907 g_object_unref (priv->memory_monitor);
1908#endif
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001909 g_free (priv);
1910}
1911
Mario Limoncielloa98df552018-04-16 12:15:51 -05001912#pragma clang diagnostic push
1913#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001914G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainPrivate, fu_main_private_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -05001915#pragma clang diagnostic pop
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001916
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001917int
1918main (int argc, char *argv[])
1919{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001920 gboolean immediate_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001921 gboolean timed_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001922 const GOptionEntry options[] = {
1923 { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit,
1924 /* TRANSLATORS: exit after we've started up, used for user profiling */
1925 _("Exit after a small delay"), NULL },
1926 { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit,
1927 /* TRANSLATORS: exit straight away, used for automatic profiling */
1928 _("Exit after the engine has loaded"), NULL },
1929 { NULL}
1930 };
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001931 g_autoptr(FuMainPrivate) priv = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001932 g_autoptr(GError) error = NULL;
Richard Hughesf3dc1622019-03-27 12:48:39 +00001933 g_autoptr(GFile) argv0_file = g_file_new_for_path (argv[0]);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001934 g_autoptr(GOptionContext) context = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001935
1936 setlocale (LC_ALL, "");
1937
Richard Hughes668ee212019-11-22 09:17:46 +00001938 bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001939 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1940 textdomain (GETTEXT_PACKAGE);
1941
1942 /* TRANSLATORS: program name */
Richard Hughes63a407a2015-07-22 08:54:14 +01001943 g_set_application_name (_("Firmware Update Daemon"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001944 context = g_option_context_new (NULL);
1945 g_option_context_add_main_entries (context, options, NULL);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001946 g_option_context_add_group (context, fu_debug_get_option_group ());
Richard Hughes8ded6ca2015-03-16 12:51:36 +00001947 /* TRANSLATORS: program summary */
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001948 g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001949 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1950 g_printerr ("Failed to parse command line: %s\n", error->message);
1951 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001952 }
1953
1954 /* create new objects */
1955 priv = g_new0 (FuMainPrivate, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001956 priv->sender_features = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001957 priv->loop = g_main_loop_new (NULL, FALSE);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001958
Richard Hughes9945edb2017-06-19 10:03:55 +01001959 /* load engine */
Richard Hughes5b5f6552018-05-18 10:22:39 +01001960 priv->engine = fu_engine_new (FU_APP_FLAGS_NONE);
Richard Hughes9945edb2017-06-19 10:03:55 +01001961 g_signal_connect (priv->engine, "changed",
1962 G_CALLBACK (fu_main_engine_changed_cb),
1963 priv);
1964 g_signal_connect (priv->engine, "device-added",
1965 G_CALLBACK (fu_main_engine_device_added_cb),
1966 priv);
1967 g_signal_connect (priv->engine, "device-removed",
1968 G_CALLBACK (fu_main_engine_device_removed_cb),
1969 priv);
1970 g_signal_connect (priv->engine, "device-changed",
1971 G_CALLBACK (fu_main_engine_device_changed_cb),
1972 priv);
1973 g_signal_connect (priv->engine, "status-changed",
1974 G_CALLBACK (fu_main_engine_status_changed_cb),
1975 priv);
1976 g_signal_connect (priv->engine, "percentage-changed",
1977 G_CALLBACK (fu_main_engine_percentage_changed_cb),
1978 priv);
Richard Hughesc7d870a2020-12-10 10:05:35 +00001979 if (!fu_engine_load (priv->engine,
1980 FU_ENGINE_LOAD_FLAG_COLDPLUG |
1981 FU_ENGINE_LOAD_FLAG_HWINFO |
1982 FU_ENGINE_LOAD_FLAG_REMOTES,
1983 &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001984 g_printerr ("Failed to load engine: %s\n", error->message);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001985 return EXIT_FAILURE;
Richard Hughes804c0752015-08-04 14:53:52 +01001986 }
1987
Mario Limonciello6754f5a2018-10-11 10:50:03 -05001988 g_unix_signal_add_full (G_PRIORITY_DEFAULT,
1989 SIGTERM, fu_main_sigterm_cb,
1990 priv, NULL);
1991
Richard Hughesf3dc1622019-03-27 12:48:39 +00001992 /* restart the daemon if the binary gets replaced */
1993 priv->argv0_monitor = g_file_monitor_file (argv0_file, G_FILE_MONITOR_NONE,
1994 NULL, &error);
1995 g_signal_connect (priv->argv0_monitor, "changed",
1996 G_CALLBACK (fu_main_argv_changed_cb), priv);
1997
Richard Hughes603e4f62019-12-11 13:44:09 +00001998#if GLIB_CHECK_VERSION(2,63,3)
1999 /* shut down on low memory event as we can just rescan hardware */
2000 priv->memory_monitor = g_memory_monitor_dup_default ();
2001 g_signal_connect (G_OBJECT (priv->memory_monitor), "low-memory-warning",
2002 G_CALLBACK (fu_main_memory_monitor_warning_cb), priv);
2003#endif
2004
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002005 /* load introspection from file */
2006 priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
2007 &error);
2008 if (priv->introspection_daemon == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002009 g_printerr ("Failed to load introspection: %s\n", error->message);
2010 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002011 }
2012
Mario Limonciello11b71f42020-10-13 13:39:14 -05002013#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +00002014 /* get authority */
2015 priv->authority = polkit_authority_get_sync (NULL, &error);
2016 if (priv->authority == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002017 g_printerr ("Failed to load authority: %s\n", error->message);
2018 return EXIT_FAILURE;
Richard Hughesf508e762015-02-27 12:49:36 +00002019 }
Mario Limonciello11b71f42020-10-13 13:39:14 -05002020#endif
Richard Hughesf508e762015-02-27 12:49:36 +00002021
Richard Hughesa018b3c2020-08-28 17:08:19 +01002022 /* are we a VM? */
2023 if (fu_main_is_hypervisor ()) {
2024 priv->machine_kind = FU_MAIN_MACHINE_KIND_VIRTUAL;
2025 } else if (fu_main_is_container ()) {
2026 priv->machine_kind = FU_MAIN_MACHINE_KIND_CONTAINER;
2027 }
2028
Richard Hughesebae3962018-09-09 13:40:49 +01002029 /* own the object */
2030 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
2031 FWUPD_DBUS_SERVICE,
2032 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
2033 G_BUS_NAME_OWNER_FLAGS_REPLACE,
2034 fu_main_on_bus_acquired_cb,
2035 fu_main_on_name_acquired_cb,
2036 fu_main_on_name_lost_cb,
2037 priv, NULL);
2038
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002039 /* Only timeout and close the mainloop if we have specified it
2040 * on the command line */
2041 if (immediate_exit)
2042 g_idle_add (fu_main_timed_exit_cb, priv->loop);
2043 else if (timed_exit)
2044 g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop);
2045
Érico Nogueira391647f2021-03-29 14:45:20 -03002046#ifdef HAVE_MALLOC_TRIM
Richard Hughesd0ba4692021-02-22 20:57:21 +00002047 /* drop heap except one page */
2048 malloc_trim (4096);
Norbert Kamiński76e19932021-03-08 11:38:43 +01002049#endif
Richard Hughesd0ba4692021-02-22 20:57:21 +00002050
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002051 /* wait */
Richard Hughes33dcfb72020-09-28 15:58:39 +01002052 g_message ("Daemon ready for requests (locale %s)", g_getenv ("LANG"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002053 g_main_loop_run (priv->loop);
2054
Richard Hughesa0531342020-10-23 10:47:26 +01002055#ifdef HAVE_SYSTEMD
2056 /* notify the service manager */
2057 sd_notify (0, "STOPPING=1");
2058#endif
2059
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002060 /* success */
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002061 return EXIT_SUCCESS;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002062}