blob: 261009ba04b3201d3e9cebcca01d676f2087eb42 [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
Richard Hughes4ad41f02018-05-08 14:35:36 +0100790static gboolean
791fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
792{
793 FuMainPrivate *priv = helper_ref->priv;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100794 g_autoptr(FuMainAuthHelper) helper = helper_ref;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100795 g_autoptr(GPtrArray) components = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100796 g_autoptr(GPtrArray) devices_possible = NULL;
797 g_autoptr(GPtrArray) errors = NULL;
798
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500799 /* get a list of devices that in some way match the device_id */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100800 if (g_strcmp0 (helper->device_id, FWUPD_DEVICE_ID_ANY) == 0) {
801 devices_possible = fu_engine_get_devices (priv->engine, error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500802 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100803 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100804 } else {
Richard Hughes79ef15f2021-04-28 09:49:19 +0100805 g_autoptr(FuDevice) device = NULL;
806 device = fu_engine_get_device (priv->engine, helper->device_id, error);
807 if (device == NULL)
808 return FALSE;
Richard Hughes63bc42e2021-04-22 09:32:07 +0100809 devices_possible = fu_engine_get_devices_by_composite_id (priv->engine,
Richard Hughes79ef15f2021-04-28 09:49:19 +0100810 fu_device_get_composite_id (device),
Richard Hughes63bc42e2021-04-22 09:32:07 +0100811 error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500812 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100813 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100814 }
815
Richard Hughes481aa2a2018-09-18 20:51:46 +0100816 /* parse silo */
817 helper->silo = fu_engine_get_silo_from_blob (priv->engine,
818 helper->blob_cab,
819 error);
820 if (helper->silo == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100821 return FALSE;
822
Richard Hughes481aa2a2018-09-18 20:51:46 +0100823 /* for each component in the silo */
Richard Hughes4cbe99c2020-11-22 13:14:33 +0000824 components = xb_silo_query (helper->silo,
825 "components/component[@type='firmware']",
826 0, error);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100827 if (components == NULL)
828 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100829 helper->action_ids = g_ptr_array_new_with_free_func (g_free);
830 helper->install_tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
831 errors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_error_free);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100832 for (guint i = 0; i < components->len; i++) {
833 XbNode *component = g_ptr_array_index (components, i);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100834
835 /* do any devices pass the requirements */
836 for (guint j = 0; j < devices_possible->len; j++) {
837 FuDevice *device = g_ptr_array_index (devices_possible, j);
838 const gchar *action_id;
839 g_autoptr(FuInstallTask) task = NULL;
840 g_autoptr(GError) error_local = NULL;
841
842 /* is this component valid for the device */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100843 task = fu_install_task_new (device, component);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100844 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100845 helper->request,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100846 task,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500847 helper->flags | FWUPD_INSTALL_FLAG_FORCE,
848 &error_local)) {
Richard Hughes33dcfb72020-09-28 15:58:39 +0100849 if (!g_error_matches (error_local,
850 FWUPD_ERROR,
851 FWUPD_ERROR_NOT_FOUND)) {
852 g_debug ("first pass requirement on %s:%s failed: %s",
853 fu_device_get_id (device),
854 xb_node_query_text (component, "id", NULL),
855 error_local->message);
856 }
Mario Limonciello537da0e2020-03-09 15:38:17 -0500857 g_ptr_array_add (errors, g_steal_pointer (&error_local));
858 continue;
859 }
860
861 /* make a second pass using possibly updated version format now */
862 fu_engine_md_refresh_device_from_component (priv->engine, device, component);
863 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100864 helper->request,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500865 task,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100866 helper->flags,
Richard Hughes4ad41f02018-05-08 14:35:36 +0100867 &error_local)) {
Mario Limonciello537da0e2020-03-09 15:38:17 -0500868 g_debug ("second pass requirement on %s:%s failed: %s",
Richard Hughes4ad41f02018-05-08 14:35:36 +0100869 fu_device_get_id (device),
Richard Hughes481aa2a2018-09-18 20:51:46 +0100870 xb_node_query_text (component, "id", NULL),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100871 error_local->message);
872 g_ptr_array_add (errors, g_steal_pointer (&error_local));
873 continue;
874 }
Mario Limonciello381c27c2020-10-23 16:32:26 -0500875 if (!fu_engine_check_trust (task, &error_local)) {
876 g_ptr_array_add (errors, g_steal_pointer (&error_local));
877 continue;
878 }
Richard Hughes4ad41f02018-05-08 14:35:36 +0100879
Mario Limonciello7a3df4b2019-01-31 10:27:22 -0600880 /* if component should have an update message from CAB */
881 fu_device_incorporate_from_component (device, component);
882
Richard Hughes4ad41f02018-05-08 14:35:36 +0100883 /* get the action IDs for the valid device */
884 action_id = fu_install_task_get_action_id (task);
885 if (!g_ptr_array_find (helper->action_ids, action_id, NULL))
886 g_ptr_array_add (helper->action_ids, g_strdup (action_id));
887 g_ptr_array_add (helper->install_tasks, g_steal_pointer (&task));
888 }
889 }
890
Richard Hughes9f86ade2018-05-10 21:11:22 +0100891 /* order the install tasks by the device priority */
892 g_ptr_array_sort (helper->install_tasks, fu_main_install_task_sort_cb);
893
Richard Hughes4ad41f02018-05-08 14:35:36 +0100894 /* nothing suitable */
895 if (helper->install_tasks->len == 0) {
Richard Hughese82eef32018-05-20 10:41:26 +0100896 GError *error_tmp = fu_common_error_array_get_best (errors);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100897 g_propagate_error (error, error_tmp);
898 return FALSE;
899 }
900
901 /* authenticate all things in the action_ids */
902 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
903 fu_main_authorize_install_queue (g_steal_pointer (&helper));
904 return TRUE;
905}
906
Richard Hughesb6f79552017-11-11 07:58:17 +0000907static gboolean
908fu_main_device_id_valid (const gchar *device_id, GError **error)
909{
910 if (g_strcmp0 (device_id, FWUPD_DEVICE_ID_ANY) == 0)
911 return TRUE;
912 if (device_id != NULL && strlen (device_id) >= 4)
913 return TRUE;
914 g_set_error (error,
915 FWUPD_ERROR,
916 FWUPD_ERROR_INTERNAL,
917 "invalid device ID: %s",
918 device_id);
919 return FALSE;
920}
921
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000922static void
923fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
924 const gchar *object_path, const gchar *interface_name,
925 const gchar *method_name, GVariant *parameters,
926 GDBusMethodInvocation *invocation, gpointer user_data)
927{
928 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughes9945edb2017-06-19 10:03:55 +0100929 GVariant *val = NULL;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100930 g_autoptr(FuEngineRequest) request = NULL;
Richard Hughes060af612016-08-17 17:32:34 +0100931 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000932
Richard Hughesdf89cd52020-06-26 20:25:18 +0100933 /* build request */
934 request = fu_main_create_request (priv, sender, &error);
935 if (request == NULL) {
936 g_dbus_method_invocation_return_gerror (invocation, error);
937 return;
938 }
939
Richard Hughes75b965d2018-11-15 13:51:21 +0000940 /* activity */
941 fu_engine_idle_reset (priv->engine);
942
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000943 if (g_strcmp0 (method_name, "GetDevices") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100944 g_autoptr(GPtrArray) devices = NULL;
Richard Hughesf508e762015-02-27 12:49:36 +0000945 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100946 devices = fu_engine_get_devices (priv->engine, &error);
947 if (devices == NULL) {
948 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100949 return;
950 }
Richard Hughesdf89cd52020-06-26 20:25:18 +0100951 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500952 if (val == NULL) {
953 g_dbus_method_invocation_return_gerror (invocation, error);
954 return;
955 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100956 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100957 return;
958 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100959 if (g_strcmp0 (method_name, "GetPlugins") == 0) {
960 g_debug ("Called %s()", method_name);
961 val = fu_main_plugin_array_to_variant (fu_engine_get_plugins (priv->engine));
962 g_dbus_method_invocation_return_value (invocation, val);
963 return;
964 }
Richard Hughese4a100c2017-06-04 21:23:50 +0100965 if (g_strcmp0 (method_name, "GetReleases") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100966 const gchar *device_id;
Richard Hughese4a100c2017-06-04 21:23:50 +0100967 g_autoptr(GPtrArray) releases = NULL;
Richard Hughese4a100c2017-06-04 21:23:50 +0100968 g_variant_get (parameters, "(&s)", &device_id);
969 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +0000970 if (!fu_main_device_id_valid (device_id, &error)) {
971 g_dbus_method_invocation_return_gerror (invocation, error);
972 return;
973 }
Richard Hughesdf89cd52020-06-26 20:25:18 +0100974 releases = fu_engine_get_releases (priv->engine, request, device_id, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +0100975 if (releases == NULL) {
976 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughese4a100c2017-06-04 21:23:50 +0100977 return;
978 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100979 val = fu_main_release_array_to_variant (releases);
980 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughese4a100c2017-06-04 21:23:50 +0100981 return;
982 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000983 if (g_strcmp0 (method_name, "GetApprovedFirmware") == 0) {
984 GVariantBuilder builder;
985 GPtrArray *checksums = fu_engine_get_approved_firmware (priv->engine);
986 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
987 for (guint i = 0; i < checksums->len; i++) {
988 const gchar *checksum = g_ptr_array_index (checksums, i);
989 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
990 }
991 val = g_variant_builder_end (&builder);
992 g_dbus_method_invocation_return_value (invocation,
993 g_variant_new_tuple (&val, 1));
994 return;
995 }
Richard Hughes31206832020-07-27 15:31:11 +0100996 if (g_strcmp0 (method_name, "GetBlockedFirmware") == 0) {
997 GVariantBuilder builder;
998 GPtrArray *checksums = fu_engine_get_blocked_firmware (priv->engine);
999 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1000 for (guint i = 0; i < checksums->len; i++) {
1001 const gchar *checksum = g_ptr_array_index (checksums, i);
1002 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1003 }
1004 val = g_variant_builder_end (&builder);
1005 g_dbus_method_invocation_return_value (invocation,
1006 g_variant_new_tuple (&val, 1));
1007 return;
1008 }
Richard Hughes6ecc4ca2020-05-20 18:42:46 +01001009 if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
1010 GHashTableIter iter;
1011 GVariantBuilder builder;
1012 const gchar *key;
1013 const gchar *value;
1014 g_autoptr(GHashTable) metadata = NULL;
1015
1016 metadata = fu_engine_get_report_metadata (priv->engine, &error);
1017 if (metadata == NULL) {
1018 g_dbus_method_invocation_return_gerror (invocation, error);
1019 return;
1020 }
1021 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
1022 g_hash_table_iter_init (&iter, metadata);
1023 while (g_hash_table_iter_next (&iter,
1024 (gpointer *) &key,
1025 (gpointer *) &value)) {
1026 g_variant_builder_add_value (&builder,
1027 g_variant_new ("{ss}", key, value));
1028 }
1029 val = g_variant_builder_end (&builder);
1030 g_dbus_method_invocation_return_value (invocation,
1031 g_variant_new_tuple (&val, 1));
1032 return;
1033 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001034 if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
1035 g_autofree gchar *checksums_str = NULL;
1036 g_auto(GStrv) checksums = NULL;
1037 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001038#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001039 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001040#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001041
1042 g_variant_get (parameters, "(^as)", &checksums);
1043 checksums_str = g_strjoinv (",", checksums);
1044 g_debug ("Called %s(%s)", method_name, checksums_str);
1045
1046 /* authenticate */
1047 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1048 helper = g_new0 (FuMainAuthHelper, 1);
1049 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001050 helper->request = g_steal_pointer (&request);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001051 helper->invocation = g_object_ref (invocation);
1052 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1053 for (guint i = 0; checksums[i] != NULL; i++)
1054 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001055#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001056 subject = polkit_system_bus_name_new (sender);
1057 polkit_authority_check_authorization (priv->authority, subject,
1058 "org.freedesktop.fwupd.set-approved-firmware",
1059 NULL,
1060 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1061 NULL,
1062 fu_main_authorize_set_approved_firmware_cb,
1063 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001064#else
1065 fu_main_authorize_set_approved_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1066#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001067 return;
1068 }
Richard Hughes31206832020-07-27 15:31:11 +01001069 if (g_strcmp0 (method_name, "SetBlockedFirmware") == 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 Hughes31206832020-07-27 15:31:11 +01001074 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001075#endif
Richard Hughes31206832020-07-27 15:31:11 +01001076 g_variant_get (parameters, "(^as)", &checksums);
1077 checksums_str = g_strjoinv (",", checksums);
1078 g_debug ("Called %s(%s)", method_name, checksums_str);
1079
1080 /* authenticate */
1081 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1082 helper = g_new0 (FuMainAuthHelper, 1);
1083 helper->priv = priv;
1084 helper->request = g_steal_pointer (&request);
1085 helper->invocation = g_object_ref (invocation);
1086 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1087 for (guint i = 0; checksums[i] != NULL; i++)
1088 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001089#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001090 subject = polkit_system_bus_name_new (sender);
1091 polkit_authority_check_authorization (priv->authority, subject,
1092 "org.freedesktop.fwupd.set-approved-firmware",
1093 NULL,
1094 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1095 NULL,
1096 fu_main_authorize_set_blocked_firmware_cb,
1097 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001098#else
1099 fu_main_authorize_set_blocked_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1100#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +01001101 return;
1102 }
Richard Hughes3d607622019-03-07 16:59:27 +00001103 if (g_strcmp0 (method_name, "SelfSign") == 0) {
1104 GVariant *prop_value;
1105 gchar *prop_key;
1106 g_autofree gchar *value = NULL;
1107 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001108#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001109 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001110#endif
Richard Hughes3d607622019-03-07 16:59:27 +00001111 g_autoptr(GVariantIter) iter = NULL;
1112
1113 g_variant_get (parameters, "(sa{sv})", &value, &iter);
1114 g_debug ("Called %s(%s)", method_name, value);
1115
1116 /* get flags */
1117 helper = g_new0 (FuMainAuthHelper, 1);
1118 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
1119 g_debug ("got option %s", prop_key);
1120 if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
1121 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001122 helper->flags |= JCAT_SIGN_FLAG_ADD_TIMESTAMP;
Richard Hughes3d607622019-03-07 16:59:27 +00001123 if (g_strcmp0 (prop_key, "add-cert") == 0 &&
1124 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001125 helper->flags |= JCAT_SIGN_FLAG_ADD_CERT;
Richard Hughes3d607622019-03-07 16:59:27 +00001126 g_variant_unref (prop_value);
1127 }
1128
1129 /* authenticate */
1130 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1131 helper->priv = priv;
1132 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001133 helper->request = g_steal_pointer (&request);
Richard Hughes3d607622019-03-07 16:59:27 +00001134 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001135#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001136 subject = polkit_system_bus_name_new (sender);
1137 polkit_authority_check_authorization (priv->authority, subject,
1138 "org.freedesktop.fwupd.self-sign",
1139 NULL,
1140 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1141 NULL,
1142 fu_main_authorize_self_sign_cb,
1143 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001144#else
1145 fu_main_authorize_self_sign_cb (NULL, NULL, g_steal_pointer (&helper));
1146#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +00001147 return;
1148 }
Richard Hughes97284b12017-09-13 17:07:58 +01001149 if (g_strcmp0 (method_name, "GetDowngrades") == 0) {
1150 const gchar *device_id;
1151 g_autoptr(GPtrArray) releases = NULL;
1152 g_variant_get (parameters, "(&s)", &device_id);
1153 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001154 if (!fu_main_device_id_valid (device_id, &error)) {
1155 g_dbus_method_invocation_return_gerror (invocation, error);
1156 return;
1157 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001158 releases = fu_engine_get_downgrades (priv->engine, request, device_id, &error);
Richard Hughes97284b12017-09-13 17:07:58 +01001159 if (releases == NULL) {
1160 g_dbus_method_invocation_return_gerror (invocation, error);
1161 return;
1162 }
1163 val = fu_main_release_array_to_variant (releases);
1164 g_dbus_method_invocation_return_value (invocation, val);
1165 return;
1166 }
Richard Hughesa96413a2017-09-13 17:19:59 +01001167 if (g_strcmp0 (method_name, "GetUpgrades") == 0) {
1168 const gchar *device_id;
1169 g_autoptr(GPtrArray) releases = NULL;
1170 g_variant_get (parameters, "(&s)", &device_id);
1171 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001172 if (!fu_main_device_id_valid (device_id, &error)) {
1173 g_dbus_method_invocation_return_gerror (invocation, error);
1174 return;
1175 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001176 releases = fu_engine_get_upgrades (priv->engine, request, device_id, &error);
Richard Hughesa96413a2017-09-13 17:19:59 +01001177 if (releases == NULL) {
1178 g_dbus_method_invocation_return_gerror (invocation, error);
1179 return;
1180 }
1181 val = fu_main_release_array_to_variant (releases);
1182 g_dbus_method_invocation_return_value (invocation, val);
1183 return;
1184 }
Richard Hughes4c369702017-06-16 15:31:38 +01001185 if (g_strcmp0 (method_name, "GetRemotes") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001186 g_autoptr(GPtrArray) remotes = NULL;
Richard Hughes4c369702017-06-16 15:31:38 +01001187 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001188 remotes = fu_engine_get_remotes (priv->engine, &error);
1189 if (remotes == NULL) {
1190 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes4c369702017-06-16 15:31:38 +01001191 return;
1192 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001193 val = fu_main_remote_array_to_variant (remotes);
1194 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes4c369702017-06-16 15:31:38 +01001195 return;
1196 }
Richard Hughes476363a2018-01-11 10:08:58 +00001197 if (g_strcmp0 (method_name, "GetHistory") == 0) {
1198 g_autoptr(GPtrArray) devices = NULL;
1199 g_debug ("Called %s()", method_name);
1200 devices = fu_engine_get_history (priv->engine, &error);
1201 if (devices == NULL) {
1202 g_dbus_method_invocation_return_gerror (invocation, error);
1203 return;
1204 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001205 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -05001206 if (val == NULL) {
1207 g_dbus_method_invocation_return_gerror (invocation, error);
1208 return;
1209 }
Richard Hughes476363a2018-01-11 10:08:58 +00001210 g_dbus_method_invocation_return_value (invocation, val);
1211 return;
1212 }
Richard Hughes196c6c62020-05-11 19:42:47 +01001213 if (g_strcmp0 (method_name, "GetHostSecurityAttrs") == 0) {
Richard Hughesf58ac732020-05-12 15:23:44 +01001214 g_autoptr(FuSecurityAttrs) attrs = NULL;
Richard Hughes196c6c62020-05-11 19:42:47 +01001215 g_debug ("Called %s()", method_name);
Richard Hughesa018b3c2020-08-28 17:08:19 +01001216 if (priv->machine_kind != FU_MAIN_MACHINE_KIND_PHYSICAL) {
1217 g_dbus_method_invocation_return_error_literal (invocation,
1218 FWUPD_ERROR,
1219 FWUPD_ERROR_NOT_SUPPORTED,
1220 "HSI unavailable for hypervisor");
1221 return;
1222 }
Richard Hughes56e7ae52020-05-17 21:00:23 +01001223 attrs = fu_engine_get_host_security_attrs (priv->engine);
Richard Hughesf58ac732020-05-12 15:23:44 +01001224 val = fu_security_attrs_to_variant (attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001225 g_dbus_method_invocation_return_value (invocation, val);
1226 return;
1227 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001228 if (g_strcmp0 (method_name, "ClearResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001229 const gchar *device_id;
1230 g_variant_get (parameters, "(&s)", &device_id);
1231 g_debug ("Called %s(%s)", method_name, device_id);
1232 if (!fu_engine_clear_results (priv->engine, device_id, &error)) {
1233 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001234 return;
1235 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001236 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001237 return;
1238 }
Richard Hughes6b222952018-01-11 10:20:48 +00001239 if (g_strcmp0 (method_name, "ModifyDevice") == 0) {
1240 const gchar *device_id;
1241 const gchar *key = NULL;
1242 const gchar *value = NULL;
1243
1244 /* check the id exists */
1245 g_variant_get (parameters, "(&s&s&s)", &device_id, &key, &value);
1246 g_debug ("Called %s(%s,%s=%s)", method_name, device_id, key, value);
1247 if (!fu_engine_modify_device (priv->engine, device_id, key, value, &error)) {
1248 g_dbus_method_invocation_return_gerror (invocation, error);
1249 return;
1250 }
1251 g_dbus_method_invocation_return_value (invocation, NULL);
1252 return;
1253 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001254 if (g_strcmp0 (method_name, "GetResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001255 const gchar *device_id = NULL;
Richard Hughes93b15762017-09-15 11:05:23 +01001256 g_autoptr(FwupdDevice) result = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +01001257 g_variant_get (parameters, "(&s)", &device_id);
1258 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001259 if (!fu_main_device_id_valid (device_id, &error)) {
1260 g_dbus_method_invocation_return_gerror (invocation, error);
1261 return;
1262 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001263 result = fu_engine_get_results (priv->engine, device_id, &error);
1264 if (result == NULL) {
1265 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001266 return;
1267 }
Richard Hughese0bd53e2017-09-17 08:29:02 +01001268 val = fwupd_device_to_variant (result);
1269 g_dbus_method_invocation_return_value (invocation,
1270 g_variant_new_tuple (&val, 1));
Richard Hughes0e883ee2015-03-18 17:22:33 +00001271 return;
1272 }
Richard Hughesba73c762017-09-15 14:31:17 +01001273 if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
Richard Hughes1b50d962017-06-02 12:23:00 +01001274 GDBusMessage *message;
1275 GUnixFDList *fd_list;
Richard Hughes9945edb2017-06-19 10:03:55 +01001276 const gchar *remote_id = NULL;
Richard Hughes1b50d962017-06-02 12:23:00 +01001277 gint fd_data;
1278 gint fd_sig;
1279
Richard Hughes9945edb2017-06-19 10:03:55 +01001280 g_variant_get (parameters, "(&shh)", &remote_id, &fd_data, &fd_sig);
1281 g_debug ("Called %s(%s,%i,%i)", method_name, remote_id, fd_data, fd_sig);
Richard Hughes1b50d962017-06-02 12:23:00 +01001282
Richard Hughes5935ebd2017-06-16 15:40:31 +01001283 /* update the metadata store */
Richard Hughes1b50d962017-06-02 12:23:00 +01001284 message = g_dbus_method_invocation_get_message (invocation);
1285 fd_list = g_dbus_message_get_unix_fd_list (message);
1286 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
1287 g_set_error (&error,
1288 FWUPD_ERROR,
1289 FWUPD_ERROR_INTERNAL,
1290 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001291 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001292 return;
1293 }
1294 fd_data = g_unix_fd_list_get (fd_list, 0, &error);
1295 if (fd_data < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001296 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001297 return;
1298 }
1299 fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
1300 if (fd_sig < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001301 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001302 return;
1303 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001304
1305 /* store new metadata (will close the fds when done) */
1306 if (!fu_engine_update_metadata (priv->engine, remote_id,
1307 fd_data, fd_sig, &error)) {
Richard Hughesf3d46c62017-11-28 14:01:30 +00001308 g_prefix_error (&error, "Failed to update metadata for %s: ", remote_id);
Richard Hughes9945edb2017-06-19 10:03:55 +01001309 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001310 return;
1311 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001312 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001313 return;
1314 }
Richard Hughes9a410ce2016-02-28 15:58:54 +00001315 if (g_strcmp0 (method_name, "Unlock") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001316 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001317 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001318#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001319 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001320#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +01001321 g_variant_get (parameters, "(&s)", &device_id);
1322 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001323 if (!fu_main_device_id_valid (device_id, &error)) {
1324 g_dbus_method_invocation_return_gerror (invocation, error);
1325 return;
1326 }
Richard Hughesfe5cc902016-06-29 10:00:00 +01001327
Richard Hughes9a410ce2016-02-28 15:58:54 +00001328 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001329 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes9945edb2017-06-19 10:03:55 +01001330 helper = g_new0 (FuMainAuthHelper, 1);
1331 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001332 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001333 helper->invocation = g_object_ref (invocation);
1334 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001335#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001336 subject = polkit_system_bus_name_new (sender);
Richard Hughes9945edb2017-06-19 10:03:55 +01001337 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes9a410ce2016-02-28 15:58:54 +00001338 "org.freedesktop.fwupd.device-unlock",
1339 NULL,
1340 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1341 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001342 fu_main_authorize_unlock_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001343 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001344#else
1345 fu_main_authorize_unlock_cb (NULL, NULL, g_steal_pointer (&helper));
1346#endif /* HAVE_POLKIT */
Richard Hughes9a410ce2016-02-28 15:58:54 +00001347 return;
1348 }
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001349 if (g_strcmp0 (method_name, "Activate") == 0) {
1350 const gchar *device_id = NULL;
1351 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001352#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001353 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001354#endif
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001355 g_variant_get (parameters, "(&s)", &device_id);
1356 g_debug ("Called %s(%s)", method_name, device_id);
1357 if (!fu_main_device_id_valid (device_id, &error)) {
1358 g_dbus_method_invocation_return_gerror (invocation, error);
1359 return;
1360 }
1361
1362 /* authenticate */
1363 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1364 helper = g_new0 (FuMainAuthHelper, 1);
1365 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001366 helper->request = g_steal_pointer (&request);
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001367 helper->invocation = g_object_ref (invocation);
1368 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001369#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001370 subject = polkit_system_bus_name_new (sender);
1371 polkit_authority_check_authorization (priv->authority, subject,
1372 "org.freedesktop.fwupd.device-activate",
1373 NULL,
1374 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1375 NULL,
1376 fu_main_authorize_activate_cb,
1377 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001378#else
1379 fu_main_authorize_activate_cb (NULL, NULL, g_steal_pointer (&helper));
1380#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001381 return;
1382 }
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001383 if (g_strcmp0 (method_name, "ModifyConfig") == 0) {
1384 g_autofree gchar *key = NULL;
1385 g_autofree gchar *value = NULL;
1386 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001387#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001388 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001389#endif
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001390 g_variant_get (parameters, "(ss)", &key, &value);
1391 g_debug ("Called %s(%s=%s)", method_name, key, value);
1392
1393 /* authenticate */
1394 helper = g_new0 (FuMainAuthHelper, 1);
1395 helper->priv = priv;
1396 helper->key = g_steal_pointer (&key);
1397 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001398 helper->request = g_steal_pointer (&request);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001399 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001400#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001401 subject = polkit_system_bus_name_new (sender);
1402 polkit_authority_check_authorization (priv->authority, subject,
1403 "org.freedesktop.fwupd.modify-config",
1404 NULL,
1405 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1406 NULL,
1407 fu_main_modify_config_cb,
1408 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001409#else
1410 fu_main_modify_config_cb (NULL, NULL, g_steal_pointer (&helper));
1411#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001412 return;
1413 }
Richard Hughesa6bd5582017-09-07 14:32:22 +01001414 if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
Richard Hughesa6bd5582017-09-07 14:32:22 +01001415 const gchar *remote_id = NULL;
1416 const gchar *key = NULL;
1417 const gchar *value = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001418 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001419#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001420 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001421#endif
Richard Hughesa6bd5582017-09-07 14:32:22 +01001422 /* check the id exists */
1423 g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
1424 g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
1425
1426 /* create helper object */
1427 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001428 helper->request = g_steal_pointer (&request);
Richard Hughesa6bd5582017-09-07 14:32:22 +01001429 helper->invocation = g_object_ref (invocation);
1430 helper->remote_id = g_strdup (remote_id);
1431 helper->key = g_strdup (key);
1432 helper->value = g_strdup (value);
1433 helper->priv = priv;
1434
1435 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001436 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001437#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001438 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001439 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughesa6bd5582017-09-07 14:32:22 +01001440 "org.freedesktop.fwupd.modify-remote",
1441 NULL,
1442 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1443 NULL,
1444 fu_main_authorize_modify_remote_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001445 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001446#else
1447 fu_main_authorize_modify_remote_cb (NULL, NULL, g_steal_pointer (&helper));
1448#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +01001449 return;
1450 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001451 if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001452 const gchar *device_id = 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 Hughes29c220d2016-12-14 17:09:54 +00001455 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001456#endif
Richard Hughes29c220d2016-12-14 17:09:54 +00001457
1458 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001459 g_variant_get (parameters, "(&s)", &device_id);
1460 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001461 if (!fu_main_device_id_valid (device_id, &error)) {
1462 g_dbus_method_invocation_return_gerror (invocation, error);
1463 return;
1464 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001465
Richard Hughes9945edb2017-06-19 10:03:55 +01001466 /* create helper object */
Richard Hughes29c220d2016-12-14 17:09:54 +00001467 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001468 helper->request = g_steal_pointer (&request);
Richard Hughes29c220d2016-12-14 17:09:54 +00001469 helper->invocation = g_object_ref (invocation);
Richard Hughes9945edb2017-06-19 10:03:55 +01001470 helper->device_id = g_strdup (device_id);
Richard Hughes29c220d2016-12-14 17:09:54 +00001471 helper->priv = priv;
Richard Hughes29c220d2016-12-14 17:09:54 +00001472
1473 /* authenticate */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001474#ifdef HAVE_POLKIT
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001475 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes29c220d2016-12-14 17:09:54 +00001476 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001477 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes29c220d2016-12-14 17:09:54 +00001478 "org.freedesktop.fwupd.verify-update",
1479 NULL,
1480 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1481 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001482 fu_main_authorize_verify_update_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001483 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001484#else
1485 fu_main_authorize_verify_update_cb (NULL, NULL, g_steal_pointer (&helper));
1486#endif /* HAVE_POLKIT */
Richard Hughes29c220d2016-12-14 17:09:54 +00001487 return;
1488 }
Richard Hughesa043c2e2015-06-29 08:43:18 +01001489 if (g_strcmp0 (method_name, "Verify") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001490 const gchar *device_id = NULL;
1491 g_variant_get (parameters, "(&s)", &device_id);
1492 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001493 if (!fu_main_device_id_valid (device_id, &error)) {
1494 g_dbus_method_invocation_return_gerror (invocation, error);
1495 return;
1496 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001497 if (!fu_engine_verify (priv->engine, device_id, &error)) {
1498 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001499 return;
1500 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001501 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001502 return;
1503 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001504 if (g_strcmp0 (method_name, "SetFeatureFlags") == 0) {
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001505 FwupdFeatureFlags feature_flags;
1506 guint64 feature_flags_u64 = 0;
1507 g_variant_get (parameters, "(t)", &feature_flags_u64);
1508 g_debug ("Called %s(%" G_GUINT64_FORMAT ")", method_name, feature_flags_u64);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001509
1510 /* old flags for the same sender will be automatically destroyed */
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001511 feature_flags = feature_flags_u64;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001512 g_hash_table_insert (priv->sender_features,
1513 g_strdup (sender),
Richard Hughesc9088e72021-03-15 15:58:13 +00001514#if GLIB_CHECK_VERSION(2,67,4)
1515 g_memdup2 (&feature_flags, sizeof(feature_flags)));
1516#else
Richard Hughesdf89cd52020-06-26 20:25:18 +01001517 g_memdup (&feature_flags, sizeof(feature_flags)));
Richard Hughesc9088e72021-03-15 15:58:13 +00001518#endif
Richard Hughesdf89cd52020-06-26 20:25:18 +01001519 g_dbus_method_invocation_return_value (invocation, NULL);
1520 return;
1521 }
Richard Hughes63a407a2015-07-22 08:54:14 +01001522 if (g_strcmp0 (method_name, "Install") == 0) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001523 GVariant *prop_value;
Richard Hughes9945edb2017-06-19 10:03:55 +01001524 const gchar *device_id = NULL;
Richard Hughes74cc2172015-02-27 13:19:46 +00001525 gchar *prop_key;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001526 gint32 fd_handle = 0;
1527 gint fd;
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001528 guint64 archive_size_max;
Richard Hughes9945edb2017-06-19 10:03:55 +01001529 GDBusMessage *message;
1530 GUnixFDList *fd_list;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001531 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001532 g_autoptr(GVariantIter) iter = NULL;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001533
1534 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001535 g_variant_get (parameters, "(&sha{sv})", &device_id, &fd_handle, &iter);
1536 g_debug ("Called %s(%s,%i)", method_name, device_id, fd_handle);
Richard Hughesb6f79552017-11-11 07:58:17 +00001537 if (!fu_main_device_id_valid (device_id, &error)) {
1538 g_dbus_method_invocation_return_gerror (invocation, error);
1539 return;
1540 }
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001541
Richard Hughes9945edb2017-06-19 10:03:55 +01001542 /* create helper object */
1543 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001544 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001545 helper->invocation = g_object_ref (invocation);
1546 helper->device_id = g_strdup (device_id);
1547 helper->priv = priv;
1548
1549 /* get flags */
1550 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001551 g_debug ("got option %s", prop_key);
1552 if (g_strcmp0 (prop_key, "offline") == 0 &&
1553 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001554 helper->flags |= FWUPD_INSTALL_FLAG_OFFLINE;
Richard Hughese7c12642015-03-04 20:28:59 +00001555 if (g_strcmp0 (prop_key, "allow-older") == 0 &&
1556 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001557 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_OLDER;
Richard Hughese7c12642015-03-04 20:28:59 +00001558 if (g_strcmp0 (prop_key, "allow-reinstall") == 0 &&
1559 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001560 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
Richard Hughes5bbf0132020-10-05 13:44:39 +01001561 if (g_strcmp0 (prop_key, "allow-branch-switch") == 0 &&
1562 g_variant_get_boolean (prop_value) == TRUE)
1563 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH;
Mario Limonciello71a5b982016-05-10 15:38:53 -05001564 if (g_strcmp0 (prop_key, "force") == 0 &&
Richard Hughes6450d0d2020-10-06 16:05:24 +01001565 g_variant_get_boolean (prop_value) == TRUE) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001566 helper->flags |= FWUPD_INSTALL_FLAG_FORCE;
Richard Hughes6450d0d2020-10-06 16:05:24 +01001567 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
1568 }
1569 if (g_strcmp0 (prop_key, "ignore-power") == 0 &&
1570 g_variant_get_boolean (prop_value) == TRUE)
1571 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
Richard Hughes76e0f942018-05-14 16:24:00 +01001572 if (g_strcmp0 (prop_key, "no-history") == 0 &&
1573 g_variant_get_boolean (prop_value) == TRUE)
1574 helper->flags |= FWUPD_INSTALL_FLAG_NO_HISTORY;
Richard Hughes1ffde6c2015-03-02 22:44:48 +00001575 g_variant_unref (prop_value);
Richard Hughes74cc2172015-02-27 13:19:46 +00001576 }
1577
Richard Hughes9945edb2017-06-19 10:03:55 +01001578
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001579 /* get the fd */
1580 message = g_dbus_method_invocation_get_message (invocation);
1581 fd_list = g_dbus_message_get_unix_fd_list (message);
1582 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001583 g_set_error (&error,
1584 FWUPD_ERROR,
1585 FWUPD_ERROR_INTERNAL,
1586 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001587 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001588 return;
1589 }
Richard Hughes7419e962016-11-22 19:48:06 +00001590 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001591 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001592 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001593 return;
1594 }
1595
Richard Hughes9945edb2017-06-19 10:03:55 +01001596 /* parse the cab file before authenticating so we can work out
1597 * what action ID to use, for instance, if this is trusted --
1598 * this will also close the fd when done */
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001599 archive_size_max = fu_engine_get_archive_size_max (priv->engine);
1600 helper->blob_cab = fu_common_get_contents_fd (fd, archive_size_max, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001601 if (helper->blob_cab == NULL) {
1602 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes5d14def2015-10-07 17:43:10 +01001603 return;
1604 }
Richard Hughes4ad41f02018-05-08 14:35:36 +01001605
1606 /* install all the things in the store */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001607#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +01001608 helper->subject = polkit_system_bus_name_new (sender);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001609#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +01001610 if (!fu_main_install_with_helper (g_steal_pointer (&helper), &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001611 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes18423292015-03-09 17:10:50 +00001612 return;
1613 }
1614
Richard Hughes4ad41f02018-05-08 14:35:36 +01001615 /* async return */
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001616 return;
1617 }
Richard Hughes07f963a2017-09-15 14:28:47 +01001618 if (g_strcmp0 (method_name, "GetDetails") == 0) {
Richard Hughes7289a6b2016-05-29 09:27:47 +01001619 GDBusMessage *message;
1620 GUnixFDList *fd_list;
1621 gint32 fd_handle = 0;
1622 gint fd;
Richard Hughes9945edb2017-06-19 10:03:55 +01001623 g_autoptr(GPtrArray) results = NULL;
Richard Hughes7289a6b2016-05-29 09:27:47 +01001624
1625 /* get parameters */
1626 g_variant_get (parameters, "(h)", &fd_handle);
1627 g_debug ("Called %s(%i)", method_name, fd_handle);
1628
1629 /* get the fd */
1630 message = g_dbus_method_invocation_get_message (invocation);
1631 fd_list = g_dbus_message_get_unix_fd_list (message);
1632 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001633 g_set_error (&error,
1634 FWUPD_ERROR,
1635 FWUPD_ERROR_INTERNAL,
1636 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001637 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001638 return;
1639 }
Richard Hughes7419e962016-11-22 19:48:06 +00001640 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001641 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001642 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001643 return;
1644 }
1645
Richard Hughes9945edb2017-06-19 10:03:55 +01001646 /* get details about the file (will close the fd when done) */
Richard Hughesdf89cd52020-06-26 20:25:18 +01001647 results = fu_engine_get_details (priv->engine, request, fd, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001648 if (results == NULL) {
1649 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001650 return;
1651 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001652 val = fu_main_result_array_to_variant (results);
1653 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001654 return;
1655 }
Richard Hughes060af612016-08-17 17:32:34 +01001656 g_set_error (&error,
1657 G_DBUS_ERROR,
1658 G_DBUS_ERROR_UNKNOWN_METHOD,
1659 "no such method %s", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001660 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001661}
1662
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001663static GVariant *
1664fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
1665 const gchar *object_path, const gchar *interface_name,
1666 const gchar *property_name, GError **error,
1667 gpointer user_data)
1668{
Richard Hughes773ce982015-03-09 22:40:57 +00001669 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1670
Richard Hughes75b965d2018-11-15 13:51:21 +00001671 /* activity */
1672 fu_engine_idle_reset (priv->engine);
1673
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001674 if (g_strcmp0 (property_name, "DaemonVersion") == 0)
Richard Hughesfe4b3ea2020-03-30 10:53:20 +01001675 return g_variant_new_string (SOURCE_VERSION);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001676
Richard Hughesf425d292019-01-18 17:57:39 +00001677 if (g_strcmp0 (property_name, "Tainted") == 0)
1678 return g_variant_new_boolean (fu_engine_get_tainted (priv->engine));
1679
Richard Hughes773ce982015-03-09 22:40:57 +00001680 if (g_strcmp0 (property_name, "Status") == 0)
Richard Hughes9945edb2017-06-19 10:03:55 +01001681 return g_variant_new_uint32 (fu_engine_get_status (priv->engine));
Richard Hughes773ce982015-03-09 22:40:57 +00001682
Mario Limonciello20cc9ee2019-09-05 07:27:26 -05001683 if (g_strcmp0 (property_name, "HostProduct") == 0)
1684 return g_variant_new_string (fu_engine_get_host_product (priv->engine));
1685
Richard Hughes0917fb62019-09-21 12:55:37 +01001686 if (g_strcmp0 (property_name, "HostMachineId") == 0)
1687 return g_variant_new_string (fu_engine_get_host_machine_id (priv->engine));
1688
Richard Hughes196c6c62020-05-11 19:42:47 +01001689 if (g_strcmp0 (property_name, "HostSecurityId") == 0)
1690 return g_variant_new_string (fu_engine_get_host_security_id (priv->engine));
1691
Mario Limoncielloeb4c7642019-11-11 10:31:29 -06001692 if (g_strcmp0 (property_name, "Interactive") == 0)
1693 return g_variant_new_boolean (isatty (fileno (stdout)) != 0);
1694
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001695 /* return an error */
1696 g_set_error (error,
Richard Hughes8645ec92015-03-19 10:14:32 +00001697 G_DBUS_ERROR,
1698 G_DBUS_ERROR_UNKNOWN_PROPERTY,
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001699 "failed to get daemon property %s",
1700 property_name);
1701 return NULL;
1702}
1703
Richard Hughesfd468842015-04-22 16:44:08 +01001704static void
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001705fu_main_on_bus_acquired_cb (GDBusConnection *connection,
1706 const gchar *name,
1707 gpointer user_data)
1708{
1709 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1710 guint registration_id;
Richard Hughes46832432015-09-11 13:43:15 +01001711 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001712 static const GDBusInterfaceVTable interface_vtable = {
1713 fu_main_daemon_method_call,
1714 fu_main_daemon_get_property,
1715 NULL
1716 };
1717
1718 priv->connection = g_object_ref (connection);
1719 registration_id = g_dbus_connection_register_object (connection,
1720 FWUPD_DBUS_PATH,
1721 priv->introspection_daemon->interfaces[0],
1722 &interface_vtable,
1723 priv, /* user_data */
1724 NULL, /* user_data_free_func */
1725 NULL); /* GError** */
1726 g_assert (registration_id > 0);
Richard Hughes18423292015-03-09 17:10:50 +00001727
1728 /* connect to D-Bus directly */
1729 priv->proxy_uid =
1730 g_dbus_proxy_new_sync (priv->connection,
1731 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1732 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1733 NULL,
1734 "org.freedesktop.DBus",
1735 "/org/freedesktop/DBus",
1736 "org.freedesktop.DBus",
1737 NULL,
1738 &error);
1739 if (priv->proxy_uid == NULL) {
1740 g_warning ("cannot connect to DBus: %s", error->message);
1741 return;
1742 }
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001743}
1744
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001745static void
1746fu_main_on_name_acquired_cb (GDBusConnection *connection,
1747 const gchar *name,
1748 gpointer user_data)
1749{
Richard Hughes33dcfb72020-09-28 15:58:39 +01001750 g_debug ("acquired name: %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001751}
1752
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001753static void
1754fu_main_on_name_lost_cb (GDBusConnection *connection,
1755 const gchar *name,
1756 gpointer user_data)
1757{
1758 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughesa8167d22021-04-14 19:33:53 +01001759 if (priv->update_in_progress) {
1760 g_warning ("name lost during a firmware update, ignoring");
1761 return;
1762 }
Mario Limonciello471a0e22020-06-09 10:49:49 -05001763 g_warning ("another service has claimed the dbus name %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001764 g_main_loop_quit (priv->loop);
1765}
1766
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001767static gboolean
1768fu_main_timed_exit_cb (gpointer user_data)
1769{
1770 GMainLoop *loop = (GMainLoop *) user_data;
1771 g_main_loop_quit (loop);
1772 return G_SOURCE_REMOVE;
1773}
1774
Richard Hughesf3dc1622019-03-27 12:48:39 +00001775static void
1776fu_main_argv_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file,
1777 GFileMonitorEvent event_type, gpointer user_data)
1778{
1779 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1780
1781 /* can do straight away? */
1782 if (priv->update_in_progress) {
1783 g_warning ("binary changed during a firmware update, ignoring");
1784 return;
1785 }
1786 g_debug ("binary changed, shutting down");
1787 g_main_loop_quit (priv->loop);
1788}
1789
Richard Hughes603e4f62019-12-11 13:44:09 +00001790#if GLIB_CHECK_VERSION(2,63,3)
1791static void
1792fu_main_memory_monitor_warning_cb (GMemoryMonitor *memory_monitor,
1793 GMemoryMonitorWarningLevel level,
1794 FuMainPrivate *priv)
1795{
1796 /* can do straight away? */
1797 if (priv->update_in_progress) {
1798 g_warning ("OOM during a firmware update, ignoring");
1799 priv->pending_sigterm = TRUE;
1800 return;
1801 }
1802 g_debug ("OOM event, shutting down");
1803 g_main_loop_quit (priv->loop);
1804}
1805#endif
1806
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001807static GDBusNodeInfo *
1808fu_main_load_introspection (const gchar *filename, GError **error)
1809{
Richard Hughes46832432015-09-11 13:43:15 +01001810 g_autoptr(GBytes) data = NULL;
1811 g_autofree gchar *path = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001812
1813 /* lookup data */
1814 path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL);
1815 data = g_resource_lookup_data (fu_get_resource (),
1816 path,
1817 G_RESOURCE_LOOKUP_FLAGS_NONE,
1818 error);
1819 if (data == NULL)
1820 return NULL;
1821
1822 /* build introspection from XML */
1823 return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error);
1824}
1825
Richard Hughesa018b3c2020-08-28 17:08:19 +01001826static gboolean
1827fu_main_is_hypervisor (void)
1828{
1829 g_autofree gchar *buf = NULL;
1830 gsize bufsz = 0;
1831 if (!g_file_get_contents ("/proc/cpuinfo", &buf, &bufsz, NULL))
1832 return FALSE;
1833 return g_strstr_len (buf, (gssize) bufsz, "hypervisor") != NULL;
1834}
1835
1836static gboolean
1837fu_main_is_container (void)
1838{
1839 g_autofree gchar *buf = NULL;
1840 gsize bufsz = 0;
1841 if (!g_file_get_contents ("/proc/1/cgroup", &buf, &bufsz, NULL))
1842 return FALSE;
1843 if (g_strstr_len (buf, (gssize) bufsz, "docker") != NULL)
1844 return TRUE;
1845 if (g_strstr_len (buf, (gssize) bufsz, "lxc") != NULL)
1846 return TRUE;
1847 return FALSE;
1848}
1849
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001850static void
1851fu_main_private_free (FuMainPrivate *priv)
1852{
Richard Hughesdf89cd52020-06-26 20:25:18 +01001853 g_hash_table_unref (priv->sender_features);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001854 if (priv->loop != NULL)
1855 g_main_loop_unref (priv->loop);
1856 if (priv->owner_id > 0)
1857 g_bus_unown_name (priv->owner_id);
1858 if (priv->proxy_uid != NULL)
1859 g_object_unref (priv->proxy_uid);
Richard Hughes9945edb2017-06-19 10:03:55 +01001860 if (priv->engine != NULL)
1861 g_object_unref (priv->engine);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001862 if (priv->connection != NULL)
1863 g_object_unref (priv->connection);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001864#ifdef HAVE_POLKIT
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001865 if (priv->authority != NULL)
1866 g_object_unref (priv->authority);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001867#endif
Richard Hughes0b6f5832020-09-01 20:15:02 +01001868 if (priv->argv0_monitor != NULL) {
1869 g_file_monitor_cancel (priv->argv0_monitor);
Richard Hughesf3dc1622019-03-27 12:48:39 +00001870 g_object_unref (priv->argv0_monitor);
Richard Hughes0b6f5832020-09-01 20:15:02 +01001871 }
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001872 if (priv->introspection_daemon != NULL)
1873 g_dbus_node_info_unref (priv->introspection_daemon);
Richard Hughes603e4f62019-12-11 13:44:09 +00001874#if GLIB_CHECK_VERSION(2,63,3)
1875 if (priv->memory_monitor != NULL)
1876 g_object_unref (priv->memory_monitor);
1877#endif
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001878 g_free (priv);
1879}
1880
Mario Limoncielloa98df552018-04-16 12:15:51 -05001881#pragma clang diagnostic push
1882#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001883G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainPrivate, fu_main_private_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -05001884#pragma clang diagnostic pop
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001885
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001886int
1887main (int argc, char *argv[])
1888{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001889 gboolean immediate_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001890 gboolean timed_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001891 const GOptionEntry options[] = {
1892 { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit,
1893 /* TRANSLATORS: exit after we've started up, used for user profiling */
1894 _("Exit after a small delay"), NULL },
1895 { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit,
1896 /* TRANSLATORS: exit straight away, used for automatic profiling */
1897 _("Exit after the engine has loaded"), NULL },
1898 { NULL}
1899 };
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001900 g_autoptr(FuMainPrivate) priv = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001901 g_autoptr(GError) error = NULL;
Richard Hughesf3dc1622019-03-27 12:48:39 +00001902 g_autoptr(GFile) argv0_file = g_file_new_for_path (argv[0]);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001903 g_autoptr(GOptionContext) context = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001904
1905 setlocale (LC_ALL, "");
1906
Richard Hughes668ee212019-11-22 09:17:46 +00001907 bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001908 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1909 textdomain (GETTEXT_PACKAGE);
1910
1911 /* TRANSLATORS: program name */
Richard Hughes63a407a2015-07-22 08:54:14 +01001912 g_set_application_name (_("Firmware Update Daemon"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001913 context = g_option_context_new (NULL);
1914 g_option_context_add_main_entries (context, options, NULL);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001915 g_option_context_add_group (context, fu_debug_get_option_group ());
Richard Hughes8ded6ca2015-03-16 12:51:36 +00001916 /* TRANSLATORS: program summary */
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001917 g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001918 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1919 g_printerr ("Failed to parse command line: %s\n", error->message);
1920 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001921 }
1922
1923 /* create new objects */
1924 priv = g_new0 (FuMainPrivate, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001925 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 +00001926 priv->loop = g_main_loop_new (NULL, FALSE);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001927
Richard Hughes9945edb2017-06-19 10:03:55 +01001928 /* load engine */
Richard Hughes5b5f6552018-05-18 10:22:39 +01001929 priv->engine = fu_engine_new (FU_APP_FLAGS_NONE);
Richard Hughes9945edb2017-06-19 10:03:55 +01001930 g_signal_connect (priv->engine, "changed",
1931 G_CALLBACK (fu_main_engine_changed_cb),
1932 priv);
1933 g_signal_connect (priv->engine, "device-added",
1934 G_CALLBACK (fu_main_engine_device_added_cb),
1935 priv);
1936 g_signal_connect (priv->engine, "device-removed",
1937 G_CALLBACK (fu_main_engine_device_removed_cb),
1938 priv);
1939 g_signal_connect (priv->engine, "device-changed",
1940 G_CALLBACK (fu_main_engine_device_changed_cb),
1941 priv);
1942 g_signal_connect (priv->engine, "status-changed",
1943 G_CALLBACK (fu_main_engine_status_changed_cb),
1944 priv);
1945 g_signal_connect (priv->engine, "percentage-changed",
1946 G_CALLBACK (fu_main_engine_percentage_changed_cb),
1947 priv);
Richard Hughesc7d870a2020-12-10 10:05:35 +00001948 if (!fu_engine_load (priv->engine,
1949 FU_ENGINE_LOAD_FLAG_COLDPLUG |
1950 FU_ENGINE_LOAD_FLAG_HWINFO |
1951 FU_ENGINE_LOAD_FLAG_REMOTES,
1952 &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001953 g_printerr ("Failed to load engine: %s\n", error->message);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001954 return EXIT_FAILURE;
Richard Hughes804c0752015-08-04 14:53:52 +01001955 }
1956
Mario Limonciello6754f5a2018-10-11 10:50:03 -05001957 g_unix_signal_add_full (G_PRIORITY_DEFAULT,
1958 SIGTERM, fu_main_sigterm_cb,
1959 priv, NULL);
1960
Richard Hughesf3dc1622019-03-27 12:48:39 +00001961 /* restart the daemon if the binary gets replaced */
1962 priv->argv0_monitor = g_file_monitor_file (argv0_file, G_FILE_MONITOR_NONE,
1963 NULL, &error);
1964 g_signal_connect (priv->argv0_monitor, "changed",
1965 G_CALLBACK (fu_main_argv_changed_cb), priv);
1966
Richard Hughes603e4f62019-12-11 13:44:09 +00001967#if GLIB_CHECK_VERSION(2,63,3)
1968 /* shut down on low memory event as we can just rescan hardware */
1969 priv->memory_monitor = g_memory_monitor_dup_default ();
1970 g_signal_connect (G_OBJECT (priv->memory_monitor), "low-memory-warning",
1971 G_CALLBACK (fu_main_memory_monitor_warning_cb), priv);
1972#endif
1973
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001974 /* load introspection from file */
1975 priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
1976 &error);
1977 if (priv->introspection_daemon == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001978 g_printerr ("Failed to load introspection: %s\n", error->message);
1979 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001980 }
1981
Mario Limonciello11b71f42020-10-13 13:39:14 -05001982#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +00001983 /* get authority */
1984 priv->authority = polkit_authority_get_sync (NULL, &error);
1985 if (priv->authority == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001986 g_printerr ("Failed to load authority: %s\n", error->message);
1987 return EXIT_FAILURE;
Richard Hughesf508e762015-02-27 12:49:36 +00001988 }
Mario Limonciello11b71f42020-10-13 13:39:14 -05001989#endif
Richard Hughesf508e762015-02-27 12:49:36 +00001990
Richard Hughesa018b3c2020-08-28 17:08:19 +01001991 /* are we a VM? */
1992 if (fu_main_is_hypervisor ()) {
1993 priv->machine_kind = FU_MAIN_MACHINE_KIND_VIRTUAL;
1994 } else if (fu_main_is_container ()) {
1995 priv->machine_kind = FU_MAIN_MACHINE_KIND_CONTAINER;
1996 }
1997
Richard Hughesebae3962018-09-09 13:40:49 +01001998 /* own the object */
1999 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
2000 FWUPD_DBUS_SERVICE,
2001 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
2002 G_BUS_NAME_OWNER_FLAGS_REPLACE,
2003 fu_main_on_bus_acquired_cb,
2004 fu_main_on_name_acquired_cb,
2005 fu_main_on_name_lost_cb,
2006 priv, NULL);
2007
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002008 /* Only timeout and close the mainloop if we have specified it
2009 * on the command line */
2010 if (immediate_exit)
2011 g_idle_add (fu_main_timed_exit_cb, priv->loop);
2012 else if (timed_exit)
2013 g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop);
2014
Érico Nogueira391647f2021-03-29 14:45:20 -03002015#ifdef HAVE_MALLOC_TRIM
Richard Hughesd0ba4692021-02-22 20:57:21 +00002016 /* drop heap except one page */
2017 malloc_trim (4096);
Norbert Kamiński76e19932021-03-08 11:38:43 +01002018#endif
Richard Hughesd0ba4692021-02-22 20:57:21 +00002019
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002020 /* wait */
Richard Hughes33dcfb72020-09-28 15:58:39 +01002021 g_message ("Daemon ready for requests (locale %s)", g_getenv ("LANG"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002022 g_main_loop_run (priv->loop);
2023
Richard Hughesa0531342020-10-23 10:47:26 +01002024#ifdef HAVE_SYSTEMD
2025 /* notify the service manager */
2026 sd_notify (0, "STOPPING=1");
2027#endif
2028
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002029 /* success */
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002030 return EXIT_SUCCESS;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002031}