blob: 5c65c1f9cfbe3f827ab684341d112f1335911d04 [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>
Richard Hughesd0ba4692021-02-22 20:57:21 +000017#include <malloc.h>
Mario Limonciello11b71f42020-10-13 13:39:14 -050018#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000019#include <polkit/polkit.h>
Mario Limonciello11b71f42020-10-13 13:39:14 -050020#endif
Richard Hughesa0531342020-10-23 10:47:26 +010021#ifdef HAVE_SYSTEMD
22#include <systemd/sd-daemon.h>
23#endif
Mario Limoncielloeb4c7642019-11-11 10:31:29 -060024#include <stdio.h>
Richard Hughes67ec8982015-03-03 11:39:27 +000025#include <stdlib.h>
Richard Hughesd5aab652020-02-25 12:47:50 +000026#include <jcat.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000027
Richard Hughes68982c62017-09-13 15:40:14 +010028#include "fwupd-device-private.h"
Richard Hughes7bcb8d42020-10-08 15:47:47 +010029#include "fwupd-plugin-private.h"
Richard Hughes196c6c62020-05-11 19:42:47 +010030#include "fwupd-security-attr-private.h"
Richard Hughes1642b3b2017-06-05 17:40:08 +010031#include "fwupd-release-private.h"
Richard Hughes4c369702017-06-16 15:31:38 +010032#include "fwupd-remote-private.h"
Richard Hughesd6db6b42017-04-12 15:03:10 +010033#include "fwupd-resources.h"
Richard Hughes8e9762d2016-03-17 10:14:15 +000034
Richard Hughes943d2c92017-06-21 09:04:39 +010035#include "fu-common.h"
Richard Hughes8bbfdf42015-02-26 22:28:09 +000036#include "fu-debug.h"
Richard Hughes68982c62017-09-13 15:40:14 +010037#include "fu-device-private.h"
Richard Hughes9945edb2017-06-19 10:03:55 +010038#include "fu-engine.h"
Richard Hughes4ad41f02018-05-08 14:35:36 +010039#include "fu-install-task.h"
Richard Hughesf58ac732020-05-12 15:23:44 +010040#include "fu-security-attrs-private.h"
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000041
Mario Limonciello11b71f42020-10-13 13:39:14 -050042#ifdef HAVE_POLKIT
Philip Withnallbc339aa2016-11-22 16:13:22 +000043#ifndef HAVE_POLKIT_0_114
Mario Limoncielloa98df552018-04-16 12:15:51 -050044#pragma clang diagnostic push
45#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes60f48c22015-10-08 20:25:51 +010046G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitAuthorizationResult, g_object_unref)
47G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitSubject, g_object_unref)
Mario Limoncielloa98df552018-04-16 12:15:51 -050048#pragma clang diagnostic pop
Mario Limonciello11b71f42020-10-13 13:39:14 -050049#endif /* HAVE_POLKIT_0_114 */
50#endif /* HAVE_POLKIT */
Richard Hughes60f48c22015-10-08 20:25:51 +010051
Richard Hughesa018b3c2020-08-28 17:08:19 +010052typedef enum {
53 FU_MAIN_MACHINE_KIND_PHYSICAL,
54 FU_MAIN_MACHINE_KIND_VIRTUAL,
55 FU_MAIN_MACHINE_KIND_CONTAINER,
56} FuMainMachineKind;
57
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000058typedef struct {
59 GDBusConnection *connection;
60 GDBusNodeInfo *introspection_daemon;
Richard Hughes18423292015-03-09 17:10:50 +000061 GDBusProxy *proxy_uid;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000062 GMainLoop *loop;
Richard Hughesf3dc1622019-03-27 12:48:39 +000063 GFileMonitor *argv0_monitor;
Richard Hughesdf89cd52020-06-26 20:25:18 +010064 GHashTable *sender_features; /* sender:FwupdFeatureFlags */
Richard Hughes603e4f62019-12-11 13:44:09 +000065#if GLIB_CHECK_VERSION(2,63,3)
66 GMemoryMonitor *memory_monitor;
67#endif
Mario Limonciello11b71f42020-10-13 13:39:14 -050068#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000069 PolkitAuthority *authority;
Mario Limonciello11b71f42020-10-13 13:39:14 -050070#endif
Richard Hughesf0a799e2017-01-17 20:13:30 +000071 guint owner_id;
Richard Hughes9945edb2017-06-19 10:03:55 +010072 FuEngine *engine;
Mario Limonciello6754f5a2018-10-11 10:50:03 -050073 gboolean update_in_progress;
74 gboolean pending_sigterm;
Richard Hughesa018b3c2020-08-28 17:08:19 +010075 FuMainMachineKind machine_kind;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000076} FuMainPrivate;
77
Mario Limonciello6754f5a2018-10-11 10:50:03 -050078static gboolean
79fu_main_sigterm_cb (gpointer user_data)
80{
81 FuMainPrivate *priv = (FuMainPrivate *) user_data;
82 if (!priv->update_in_progress) {
83 g_main_loop_quit (priv->loop);
84 return G_SOURCE_REMOVE;
85 }
86 g_warning ("Received SIGTERM during a firmware update, ignoring");
87 priv->pending_sigterm = TRUE;
88 return G_SOURCE_CONTINUE;
89}
90
Richard Hughesd7022b52015-03-11 19:47:06 +000091static void
Richard Hughes9945edb2017-06-19 10:03:55 +010092fu_main_engine_changed_cb (FuEngine *engine, FuMainPrivate *priv)
Richard Hughesd7022b52015-03-11 19:47:06 +000093{
94 /* not yet connected */
95 if (priv->connection == NULL)
96 return;
97 g_dbus_connection_emit_signal (priv->connection,
98 NULL,
99 FWUPD_DBUS_PATH,
100 FWUPD_DBUS_INTERFACE,
101 "Changed",
102 NULL, NULL);
103}
104
Richard Hughes8ca33782016-04-28 15:04:31 +0100105static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100106fu_main_engine_device_added_cb (FuEngine *engine,
107 FuDevice *device,
108 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100109{
110 GVariant *val;
111
112 /* not yet connected */
113 if (priv->connection == NULL)
114 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100115 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100116 g_dbus_connection_emit_signal (priv->connection,
117 NULL,
118 FWUPD_DBUS_PATH,
119 FWUPD_DBUS_INTERFACE,
120 "DeviceAdded",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100121 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100122}
123
Richard Hughes8ca33782016-04-28 15:04:31 +0100124static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100125fu_main_engine_device_removed_cb (FuEngine *engine,
126 FuDevice *device,
127 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100128{
129 GVariant *val;
130
131 /* not yet connected */
132 if (priv->connection == NULL)
133 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100134 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100135 g_dbus_connection_emit_signal (priv->connection,
136 NULL,
137 FWUPD_DBUS_PATH,
138 FWUPD_DBUS_INTERFACE,
139 "DeviceRemoved",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100140 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100141}
142
Richard Hughes8ca33782016-04-28 15:04:31 +0100143static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100144fu_main_engine_device_changed_cb (FuEngine *engine,
145 FuDevice *device,
146 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100147{
148 GVariant *val;
149
150 /* not yet connected */
151 if (priv->connection == NULL)
152 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100153 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100154 g_dbus_connection_emit_signal (priv->connection,
155 NULL,
156 FWUPD_DBUS_PATH,
157 FWUPD_DBUS_INTERFACE,
158 "DeviceChanged",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100159 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100160}
161
Richard Hughes773ce982015-03-09 22:40:57 +0000162static void
163fu_main_emit_property_changed (FuMainPrivate *priv,
164 const gchar *property_name,
165 GVariant *property_value)
166{
167 GVariantBuilder builder;
168 GVariantBuilder invalidated_builder;
169
170 /* not yet connected */
Richard Hughes34fcc022018-09-19 16:16:15 +0100171 if (priv->connection == NULL) {
172 g_variant_unref (g_variant_ref_sink (property_value));
Richard Hughes773ce982015-03-09 22:40:57 +0000173 return;
Richard Hughes34fcc022018-09-19 16:16:15 +0100174 }
Richard Hughes773ce982015-03-09 22:40:57 +0000175
176 /* build the dict */
177 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
Richard Hughes8356a832019-03-21 17:04:38 +0000178 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
Richard Hughes773ce982015-03-09 22:40:57 +0000179 g_variant_builder_add (&builder,
180 "{sv}",
181 property_name,
182 property_value);
183 g_dbus_connection_emit_signal (priv->connection,
184 NULL,
185 FWUPD_DBUS_PATH,
186 "org.freedesktop.DBus.Properties",
187 "PropertiesChanged",
188 g_variant_new ("(sa{sv}as)",
189 FWUPD_DBUS_INTERFACE,
190 &builder,
191 &invalidated_builder),
192 NULL);
193 g_variant_builder_clear (&builder);
194 g_variant_builder_clear (&invalidated_builder);
195}
196
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100197static void
198fu_main_set_status (FuMainPrivate *priv, FwupdStatus status)
199{
200 g_debug ("Emitting PropertyChanged('Status'='%s')",
201 fwupd_status_to_string (status));
202 fu_main_emit_property_changed (priv, "Status",
203 g_variant_new_uint32 (status));
204}
Richard Hughes773ce982015-03-09 22:40:57 +0000205
Richard Hughes9945edb2017-06-19 10:03:55 +0100206static void
207fu_main_engine_status_changed_cb (FuEngine *engine,
208 FwupdStatus status,
209 FuMainPrivate *priv)
210{
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100211 fu_main_set_status (priv, status);
Richard Hughes75b965d2018-11-15 13:51:21 +0000212
213 /* engine has gone idle */
214 if (status == FWUPD_STATUS_SHUTDOWN)
215 g_main_loop_quit (priv->loop);
Richard Hughes773ce982015-03-09 22:40:57 +0000216}
217
Richard Hughes876c0072016-08-17 14:51:03 +0100218static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100219fu_main_engine_percentage_changed_cb (FuEngine *engine,
220 guint percentage,
221 FuMainPrivate *priv)
Richard Hughes876c0072016-08-17 14:51:03 +0100222{
Richard Hughes876c0072016-08-17 14:51:03 +0100223 g_debug ("Emitting PropertyChanged('Percentage'='%u%%')", percentage);
224 fu_main_emit_property_changed (priv, "Percentage",
225 g_variant_new_uint32 (percentage));
226}
227
Richard Hughesdf89cd52020-06-26 20:25:18 +0100228static FuEngineRequest *
229fu_main_create_request (FuMainPrivate *priv, const gchar *sender, GError **error)
Mario Limoncielloe3016602018-09-06 11:20:59 -0500230{
Richard Hughesdf89cd52020-06-26 20:25:18 +0100231 FwupdFeatureFlags *feature_flags;
232 FwupdDeviceFlags device_flags = FWUPD_DEVICE_FLAG_NONE;
233 uid_t calling_uid = 0;
234 g_autoptr(FuEngineRequest) request = fu_engine_request_new ();
Mario Limoncielloe3016602018-09-06 11:20:59 -0500235 g_autoptr(GVariant) value = NULL;
236
Richard Hughesdf89cd52020-06-26 20:25:18 +0100237 g_return_val_if_fail (sender != NULL, NULL);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500238
Richard Hughesdf89cd52020-06-26 20:25:18 +0100239 /* did the client set the list of supported feature */
240 feature_flags = g_hash_table_lookup (priv->sender_features, sender);
241 if (feature_flags != NULL)
242 fu_engine_request_set_feature_flags (request, *feature_flags);
243
244 /* are we root and therefore trusted? */
Mario Limoncielloe3016602018-09-06 11:20:59 -0500245 value = g_dbus_proxy_call_sync (priv->proxy_uid,
246 "GetConnectionUnixUser",
247 g_variant_new ("(s)", sender),
248 G_DBUS_CALL_FLAGS_NONE,
249 2000,
250 NULL,
251 error);
252 if (value == NULL) {
253 g_prefix_error (error, "failed to read user id of caller: ");
Richard Hughesbfe6c772020-08-17 14:48:23 +0100254 return NULL;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500255 }
256 g_variant_get (value, "(u)", &calling_uid);
257 if (calling_uid == 0)
Richard Hughesdf89cd52020-06-26 20:25:18 +0100258 device_flags |= FWUPD_DEVICE_FLAG_TRUSTED;
259 fu_engine_request_set_device_flags (request, device_flags);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500260
Richard Hughesdf89cd52020-06-26 20:25:18 +0100261 /* success */
262 return g_steal_pointer (&request);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500263}
264
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000265static GVariant *
Richard Hughesdf89cd52020-06-26 20:25:18 +0100266fu_main_device_array_to_variant (FuMainPrivate *priv, FuEngineRequest *request,
Mario Limoncielloe3016602018-09-06 11:20:59 -0500267 GPtrArray *devices, GError **error)
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000268{
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000269 GVariantBuilder builder;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500270
Richard Hughes9945edb2017-06-19 10:03:55 +0100271 g_return_val_if_fail (devices->len > 0, NULL);
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000272 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500273
Richard Hughesf192bf02016-07-22 08:26:43 +0100274 for (guint i = 0; i < devices->len; i++) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100275 FuDevice *device = g_ptr_array_index (devices, i);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500276 GVariant *tmp = fwupd_device_to_variant_full (FWUPD_DEVICE (device),
Richard Hughesdf89cd52020-06-26 20:25:18 +0100277 fu_engine_request_get_device_flags (request));
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000278 g_variant_builder_add_value (&builder, tmp);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000279 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100280 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000281}
282
Richard Hughes9945edb2017-06-19 10:03:55 +0100283static GVariant *
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100284fu_main_plugin_array_to_variant (GPtrArray *plugins)
285{
286 GVariantBuilder builder;
287
288 g_return_val_if_fail (plugins->len > 0, NULL);
289 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
290
291 for (guint i = 0; i < plugins->len; i++) {
292 FuDevice *plugin = g_ptr_array_index (plugins, i);
293 GVariant *tmp = fwupd_plugin_to_variant (FWUPD_PLUGIN (plugin));
294 g_variant_builder_add_value (&builder, tmp);
295 }
296 return g_variant_new ("(aa{sv})", &builder);
297}
298
299static GVariant *
Richard Hughes9945edb2017-06-19 10:03:55 +0100300fu_main_release_array_to_variant (GPtrArray *results)
Richard Hughes060af612016-08-17 17:32:34 +0100301{
Richard Hughes9945edb2017-06-19 10:03:55 +0100302 GVariantBuilder builder;
303 g_return_val_if_fail (results->len > 0, NULL);
304 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
305 for (guint i = 0; i < results->len; i++) {
306 FwupdRelease *rel = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100307 GVariant *tmp = fwupd_release_to_variant (rel);
Richard Hughes9945edb2017-06-19 10:03:55 +0100308 g_variant_builder_add_value (&builder, tmp);
309 }
310 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100311}
312
Richard Hughes9945edb2017-06-19 10:03:55 +0100313static GVariant *
314fu_main_remote_array_to_variant (GPtrArray *remotes)
Richard Hughes060af612016-08-17 17:32:34 +0100315{
Richard Hughes9945edb2017-06-19 10:03:55 +0100316 GVariantBuilder builder;
317 g_return_val_if_fail (remotes->len > 0, NULL);
318 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
319 for (guint i = 0; i < remotes->len; i++) {
320 FwupdRemote *remote = g_ptr_array_index (remotes, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100321 GVariant *tmp = fwupd_remote_to_variant (remote);
Richard Hughes9945edb2017-06-19 10:03:55 +0100322 g_variant_builder_add_value (&builder, tmp);
323 }
324 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100325}
326
Richard Hughes9945edb2017-06-19 10:03:55 +0100327static GVariant *
328fu_main_result_array_to_variant (GPtrArray *results)
Richard Hughes8bbfdf42015-02-26 22:28:09 +0000329{
Richard Hughes9945edb2017-06-19 10:03:55 +0100330 GVariantBuilder builder;
331 g_return_val_if_fail (results->len > 0, NULL);
332 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
333 for (guint i = 0; i < results->len; i++) {
Richard Hughes93b15762017-09-15 11:05:23 +0100334 FwupdDevice *result = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100335 GVariant *tmp = fwupd_device_to_variant (result);
Richard Hughes9945edb2017-06-19 10:03:55 +0100336 g_variant_builder_add_value (&builder, tmp);
337 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100338 return g_variant_new ("(aa{sv})", &builder);
Richard Hughesf508e762015-02-27 12:49:36 +0000339}
340
Richard Hughesf508e762015-02-27 12:49:36 +0000341typedef struct {
342 GDBusMethodInvocation *invocation;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100343 FuEngineRequest *request;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500344#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100345 PolkitSubject *subject;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500346#endif
Richard Hughes4ad41f02018-05-08 14:35:36 +0100347 GPtrArray *install_tasks;
348 GPtrArray *action_ids;
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000349 GPtrArray *checksums;
Richard Hughes3d607622019-03-07 16:59:27 +0000350 guint64 flags;
Richard Hughes5d14def2015-10-07 17:43:10 +0100351 GBytes *blob_cab;
Richard Hughes67ec8982015-03-03 11:39:27 +0000352 FuMainPrivate *priv;
Richard Hughes9945edb2017-06-19 10:03:55 +0100353 gchar *device_id;
Richard Hughesa6bd5582017-09-07 14:32:22 +0100354 gchar *remote_id;
355 gchar *key;
356 gchar *value;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100357 XbSilo *silo;
Richard Hughesf508e762015-02-27 12:49:36 +0000358} FuMainAuthHelper;
359
Richard Hughesf508e762015-02-27 12:49:36 +0000360static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100361fu_main_auth_helper_free (FuMainAuthHelper *helper)
Richard Hughesf508e762015-02-27 12:49:36 +0000362{
Richard Hughes4ced4662016-08-26 11:02:31 +0100363 if (helper->blob_cab != NULL)
Richard Hughes5d14def2015-10-07 17:43:10 +0100364 g_bytes_unref (helper->blob_cab);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500365#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100366 if (helper->subject != NULL)
367 g_object_unref (helper->subject);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500368#endif
Richard Hughes481aa2a2018-09-18 20:51:46 +0100369 if (helper->silo != NULL)
370 g_object_unref (helper->silo);
Richard Hughesdf89cd52020-06-26 20:25:18 +0100371 if (helper->request != NULL)
372 g_object_unref (helper->request);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100373 if (helper->install_tasks != NULL)
374 g_ptr_array_unref (helper->install_tasks);
375 if (helper->action_ids != NULL)
376 g_ptr_array_unref (helper->action_ids);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000377 if (helper->checksums != NULL)
378 g_ptr_array_unref (helper->checksums);
Richard Hughes9945edb2017-06-19 10:03:55 +0100379 g_free (helper->device_id);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100380 g_free (helper->remote_id);
381 g_free (helper->key);
382 g_free (helper->value);
Richard Hughes67ec8982015-03-03 11:39:27 +0000383 g_object_unref (helper->invocation);
Richard Hughesf508e762015-02-27 12:49:36 +0000384 g_free (helper);
385}
386
Mario Limoncielloa98df552018-04-16 12:15:51 -0500387#pragma clang diagnostic push
388#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes9945edb2017-06-19 10:03:55 +0100389G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainAuthHelper, fu_main_auth_helper_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -0500390#pragma clang diagnostic pop
Richard Hughes9945edb2017-06-19 10:03:55 +0100391
Mario Limonciello11b71f42020-10-13 13:39:14 -0500392#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100393/* error may or may not already have been set */
Richard Hughesb75c92d2016-02-20 20:22:00 +0000394static gboolean
Richard Hughes9945edb2017-06-19 10:03:55 +0100395fu_main_authorization_is_valid (PolkitAuthorizationResult *auth, GError **error)
Richard Hughes9a410ce2016-02-28 15:58:54 +0000396{
Richard Hughes9945edb2017-06-19 10:03:55 +0100397 /* failed */
Richard Hughesf508e762015-02-27 12:49:36 +0000398 if (auth == NULL) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100399 g_autofree gchar *message = g_strdup ((*error)->message);
400 g_clear_error (error);
401 g_set_error (error,
Richard Hughes060af612016-08-17 17:32:34 +0100402 FWUPD_ERROR,
403 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100404 "Could not check for auth: %s", message);
405 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000406 }
407
408 /* did not auth */
409 if (!polkit_authorization_result_get_is_authorized (auth)) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100410 g_set_error_literal (error,
Richard Hughes060af612016-08-17 17:32:34 +0100411 FWUPD_ERROR,
412 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100413 "Failed to obtain auth");
414 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000415 }
416
417 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100418 return TRUE;
Richard Hughes5d14def2015-10-07 17:43:10 +0100419}
Mario Limonciello11b71f42020-10-13 13:39:14 -0500420#else
421static gboolean
422fu_main_authorization_is_trusted (FuEngineRequest *request, GError **error)
423{
424 FwupdDeviceFlags flags = fu_engine_request_get_device_flags (request);
425 if ((flags & FWUPD_DEVICE_FLAG_TRUSTED) == 0) {
426 g_set_error_literal (error,
427 FWUPD_ERROR,
428 FWUPD_ERROR_AUTH_FAILED,
429 "permission denied: untrusted client process");
430 return FALSE;
431 }
432 return TRUE;
433}
434#endif /* HAVE_POLKIT */
Richard Hughes5d14def2015-10-07 17:43:10 +0100435
Richard Hughesdf7950b2016-01-31 10:18:40 +0000436static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100437fu_main_authorize_unlock_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100438{
Richard Hughes9945edb2017-06-19 10:03:55 +0100439 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
440 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500441#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100442 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100443
Richard Hughes9945edb2017-06-19 10:03:55 +0100444 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100445 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100446 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
447 res, &error);
448 if (!fu_main_authorization_is_valid (auth, &error)) {
449 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100450 return;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100451 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500452#else
453 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
454 g_dbus_method_invocation_return_gerror (helper->invocation, error);
455 return;
456 }
457#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +0100458
459 /* authenticated */
460 if (!fu_engine_unlock (helper->priv->engine, helper->device_id, &error)) {
461 g_dbus_method_invocation_return_gerror (helper->invocation, error);
462 return;
463 }
464
465 /* success */
466 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100467}
468
469static void
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000470fu_main_authorize_set_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
471{
472 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
473 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500474#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000475 g_autoptr(PolkitAuthorizationResult) auth = NULL;
476
477 /* get result */
478 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
479 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
480 res, &error);
481 if (!fu_main_authorization_is_valid (auth, &error)) {
482 g_dbus_method_invocation_return_gerror (helper->invocation, error);
483 return;
484 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500485#else
486 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
487 g_dbus_method_invocation_return_gerror (helper->invocation, error);
488 return;
489 }
490#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000491
492 /* success */
493 for (guint i = 0; i < helper->checksums->len; i++) {
494 const gchar *csum = g_ptr_array_index (helper->checksums, i);
495 fu_engine_add_approved_firmware (helper->priv->engine, csum);
496 }
497 g_dbus_method_invocation_return_value (helper->invocation, NULL);
498}
499
500static void
Richard Hughes31206832020-07-27 15:31:11 +0100501fu_main_authorize_set_blocked_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
502{
503 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
504 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500505#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +0100506 g_autoptr(PolkitAuthorizationResult) auth = NULL;
507
508 /* get result */
509 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
510 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
511 res, &error);
512 if (!fu_main_authorization_is_valid (auth, &error)) {
513 g_dbus_method_invocation_return_gerror (helper->invocation, error);
514 return;
515 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500516#else
517 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
518 g_dbus_method_invocation_return_gerror (helper->invocation, error);
519 return;
520 }
521#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +0100522
523 /* success */
524 if (!fu_engine_set_blocked_firmware (helper->priv->engine, helper->checksums, &error)) {
525 g_dbus_method_invocation_return_gerror (helper->invocation, error);
526 return;
527 }
528 g_dbus_method_invocation_return_value (helper->invocation, NULL);
529}
530
531static void
Richard Hughes3d607622019-03-07 16:59:27 +0000532fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
533{
534 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
535 g_autofree gchar *sig = NULL;
536 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500537#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +0000538 g_autoptr(PolkitAuthorizationResult) auth = NULL;
539
540 /* get result */
541 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
542 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
543 res, &error);
544 if (!fu_main_authorization_is_valid (auth, &error)) {
545 g_dbus_method_invocation_return_gerror (helper->invocation, error);
546 return;
547 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500548#else
549 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
550 g_dbus_method_invocation_return_gerror (helper->invocation, error);
551 return;
552 }
553#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +0000554
555 /* authenticated */
556 sig = fu_engine_self_sign (helper->priv->engine, helper->value, helper->flags, &error);
557 if (sig == NULL) {
558 g_dbus_method_invocation_return_gerror (helper->invocation, error);
559 return;
560 }
561
562 /* success */
563 g_dbus_method_invocation_return_value (helper->invocation, g_variant_new ("(s)", sig));
564}
565
566static void
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100567fu_main_modify_config_cb (GObject *source, GAsyncResult *res, gpointer user_data)
568{
569 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
570 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500571#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100572 g_autoptr(PolkitAuthorizationResult) auth = NULL;
573
574 /* get result */
575 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
576 res, &error);
577 if (!fu_main_authorization_is_valid (auth, &error)) {
578 g_dbus_method_invocation_return_gerror (helper->invocation, error);
579 return;
580 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500581#else
582 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
583 g_dbus_method_invocation_return_gerror (helper->invocation, error);
584 return;
585 }
586#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100587
588 if (!fu_engine_modify_config (helper->priv->engine, helper->key, helper->value, &error)) {
589 g_dbus_method_invocation_return_gerror (helper->invocation, error);
590 return;
591 }
592
593 /* success */
594 g_dbus_method_invocation_return_value (helper->invocation, NULL);
595}
596
597static void
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600598fu_main_authorize_activate_cb (GObject *source, GAsyncResult *res, gpointer user_data)
599{
600 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
601 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500602#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600603 g_autoptr(PolkitAuthorizationResult) auth = NULL;
604
605 /* get result */
606 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
607 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
608 res, &error);
609 if (!fu_main_authorization_is_valid (auth, &error)) {
610 g_dbus_method_invocation_return_gerror (helper->invocation, error);
611 return;
612 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500613#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600614
615 /* authenticated */
616 if (!fu_engine_activate (helper->priv->engine, helper->device_id, &error)) {
617 g_dbus_method_invocation_return_gerror (helper->invocation, error);
618 return;
619 }
620
621 /* success */
622 g_dbus_method_invocation_return_value (helper->invocation, NULL);
623}
624
625static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100626fu_main_authorize_verify_update_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughesdf7950b2016-01-31 10:18:40 +0000627{
Richard Hughes9945edb2017-06-19 10:03:55 +0100628 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
629 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500630#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100631 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughesdf7950b2016-01-31 10:18:40 +0000632
Richard Hughes9945edb2017-06-19 10:03:55 +0100633 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100634 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100635 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
636 res, &error);
637 if (!fu_main_authorization_is_valid (auth, &error)) {
638 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughesdf7950b2016-01-31 10:18:40 +0000639 return;
Richard Hughesf192bf02016-07-22 08:26:43 +0100640 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500641#else
642 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
643 g_dbus_method_invocation_return_gerror (helper->invocation, error);
644 return;
645 }
646#endif /* HAVE_POLKIT */
Richard Hughesdf7950b2016-01-31 10:18:40 +0000647
Richard Hughes9945edb2017-06-19 10:03:55 +0100648 /* authenticated */
649 if (!fu_engine_verify_update (helper->priv->engine, helper->device_id, &error)) {
650 g_dbus_method_invocation_return_gerror (helper->invocation, error);
651 return;
Richard Hughes404cc512016-12-21 16:09:48 +0000652 }
653
654 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100655 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes99147f12016-05-17 09:35:04 +0100656}
657
Richard Hughes9945edb2017-06-19 10:03:55 +0100658static void
Richard Hughesa6bd5582017-09-07 14:32:22 +0100659fu_main_authorize_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
660{
661 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
662 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500663#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100664 g_autoptr(PolkitAuthorizationResult) auth = NULL;
665
666 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100667 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100668 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
669 res, &error);
670 if (!fu_main_authorization_is_valid (auth, &error)) {
671 g_dbus_method_invocation_return_gerror (helper->invocation, error);
672 return;
673 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500674#else
675 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
676 g_dbus_method_invocation_return_gerror (helper->invocation, error);
677 return;
678 }
679#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +0100680
681 /* authenticated */
682 if (!fu_engine_modify_remote (helper->priv->engine,
683 helper->remote_id,
684 helper->key,
685 helper->value,
686 &error)) {
687 g_dbus_method_invocation_return_gerror (helper->invocation, error);
688 return;
689 }
690
691 /* success */
692 g_dbus_method_invocation_return_value (helper->invocation, NULL);
693}
694
Richard Hughes4ad41f02018-05-08 14:35:36 +0100695static void fu_main_authorize_install_queue (FuMainAuthHelper *helper);
696
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500697#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100698static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100699fu_main_authorize_install_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes404cc512016-12-21 16:09:48 +0000700{
Richard Hughes9945edb2017-06-19 10:03:55 +0100701 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
Richard Hughes46832432015-09-11 13:43:15 +0100702 g_autoptr(GError) error = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +0100703 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes18423292015-03-09 17:10:50 +0000704
Richard Hughes9945edb2017-06-19 10:03:55 +0100705 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100706 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100707 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
708 res, &error);
709 if (!fu_main_authorization_is_valid (auth, &error)) {
710 g_dbus_method_invocation_return_gerror (helper->invocation, error);
711 return;
Richard Hughes0e883ee2015-03-18 17:22:33 +0000712 }
713
Richard Hughes4ad41f02018-05-08 14:35:36 +0100714 /* do the next authentication action ID */
715 fu_main_authorize_install_queue (g_steal_pointer (&helper));
716}
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500717#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100718
719static void
720fu_main_authorize_install_queue (FuMainAuthHelper *helper_ref)
721{
722 FuMainPrivate *priv = helper_ref->priv;
723 g_autoptr(FuMainAuthHelper) helper = helper_ref;
724 g_autoptr(GError) error = NULL;
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500725 gboolean ret;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100726
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500727#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100728 /* still more things to to authenticate */
729 if (helper->action_ids->len > 0) {
730 g_autofree gchar *action_id = g_strdup (g_ptr_array_index (helper->action_ids, 0));
731 g_autoptr(PolkitSubject) subject = g_object_ref (helper->subject);
732 g_ptr_array_remove_index (helper->action_ids, 0);
733 polkit_authority_check_authorization (priv->authority, subject,
734 action_id, NULL,
735 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
736 NULL,
737 fu_main_authorize_install_cb,
738 g_steal_pointer (&helper));
Richard Hughes9945edb2017-06-19 10:03:55 +0100739 return;
Richard Hughes654f6b82016-04-25 12:29:48 +0100740 }
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500741#endif /* HAVE_POLKIT */
Richard Hughes654f6b82016-04-25 12:29:48 +0100742
Richard Hughes4ad41f02018-05-08 14:35:36 +0100743 /* all authenticated, so install all the things */
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500744 priv->update_in_progress = TRUE;
745 ret = fu_engine_install_tasks (helper->priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100746 helper->request,
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500747 helper->install_tasks,
748 helper->blob_cab,
749 helper->flags,
750 &error);
751 priv->update_in_progress = FALSE;
752 if (priv->pending_sigterm)
753 g_main_loop_quit (priv->loop);
754 if (!ret) {
Richard Hughesdbd8c762018-06-15 20:31:40 +0100755 g_dbus_method_invocation_return_gerror (helper->invocation, error);
756 return;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100757 }
758
Richard Hughes654f6b82016-04-25 12:29:48 +0100759 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100760 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes4c369702017-06-16 15:31:38 +0100761}
762
Richard Hughes4ad41f02018-05-08 14:35:36 +0100763#if !GLIB_CHECK_VERSION(2,54,0)
764static gboolean
765g_ptr_array_find (GPtrArray *haystack, gconstpointer needle, guint *index_)
766{
767 for (guint i = 0; i < haystack->len; i++) {
768 gconstpointer *tmp = g_ptr_array_index (haystack, i);
769 if (tmp == needle) {
770 if (index_ != NULL) {
771 *index_ = i;
772 return TRUE;
773 }
774 }
775 }
776 return FALSE;
777}
778#endif
779
Richard Hughes9f86ade2018-05-10 21:11:22 +0100780static gint
781fu_main_install_task_sort_cb (gconstpointer a, gconstpointer b)
782{
783 FuInstallTask *task_a = *((FuInstallTask **) a);
784 FuInstallTask *task_b = *((FuInstallTask **) b);
Richard Hughesc02cb832018-05-20 10:31:04 +0100785 return fu_install_task_compare (task_a, task_b);
Richard Hughes9f86ade2018-05-10 21:11:22 +0100786}
787
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500788static GPtrArray *
789fu_main_get_device_family (FuMainAuthHelper *helper, GError **error)
790{
791 FuDevice *parent;
792 GPtrArray *children;
793 g_autoptr(FuDevice) device = NULL;
794 g_autoptr(GPtrArray) devices_possible = NULL;
795
796 /* get the device */
797 device = fu_engine_get_device (helper->priv->engine, helper->device_id, error);
798 if (device == NULL)
799 return NULL;
800
801 /* device itself */
802 devices_possible = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
803 g_ptr_array_add (devices_possible, g_object_ref (device));
804
805 /* add device children */
806 children = fu_device_get_children (device);
807 for (guint i = 0; i < children->len; i++) {
808 FuDevice *child = g_ptr_array_index (children, i);
809 g_ptr_array_add (devices_possible, g_object_ref (child));
810 }
811
812 /* add parent and siblings, not including the device itself */
813 parent = fu_device_get_parent (device);
814 if (parent != NULL) {
815 GPtrArray *siblings = fu_device_get_children (parent);
816 g_ptr_array_add (devices_possible, g_object_ref (parent));
817 for (guint i = 0; i < siblings->len; i++) {
818 FuDevice *sibling = g_ptr_array_index (siblings, i);
819 if (sibling == device)
820 continue;
821 g_ptr_array_add (devices_possible, g_object_ref (sibling));
822 }
823 }
824
825 /* success */
826 return g_steal_pointer (&devices_possible);
827}
828
Richard Hughes4ad41f02018-05-08 14:35:36 +0100829static gboolean
830fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
831{
832 FuMainPrivate *priv = helper_ref->priv;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100833 g_autoptr(FuMainAuthHelper) helper = helper_ref;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100834 g_autoptr(GPtrArray) components = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100835 g_autoptr(GPtrArray) devices_possible = NULL;
836 g_autoptr(GPtrArray) errors = NULL;
837
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500838 /* get a list of devices that in some way match the device_id */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100839 if (g_strcmp0 (helper->device_id, FWUPD_DEVICE_ID_ANY) == 0) {
840 devices_possible = fu_engine_get_devices (priv->engine, error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500841 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100842 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100843 } else {
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500844 devices_possible = fu_main_get_device_family (helper, error);
845 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100846 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100847 }
848
Richard Hughes481aa2a2018-09-18 20:51:46 +0100849 /* parse silo */
850 helper->silo = fu_engine_get_silo_from_blob (priv->engine,
851 helper->blob_cab,
852 error);
853 if (helper->silo == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100854 return FALSE;
855
Richard Hughes481aa2a2018-09-18 20:51:46 +0100856 /* for each component in the silo */
Richard Hughes4cbe99c2020-11-22 13:14:33 +0000857 components = xb_silo_query (helper->silo,
858 "components/component[@type='firmware']",
859 0, error);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100860 if (components == NULL)
861 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100862 helper->action_ids = g_ptr_array_new_with_free_func (g_free);
863 helper->install_tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
864 errors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_error_free);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100865 for (guint i = 0; i < components->len; i++) {
866 XbNode *component = g_ptr_array_index (components, i);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100867
868 /* do any devices pass the requirements */
869 for (guint j = 0; j < devices_possible->len; j++) {
870 FuDevice *device = g_ptr_array_index (devices_possible, j);
871 const gchar *action_id;
872 g_autoptr(FuInstallTask) task = NULL;
873 g_autoptr(GError) error_local = NULL;
874
875 /* is this component valid for the device */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100876 task = fu_install_task_new (device, component);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100877 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100878 helper->request,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100879 task,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500880 helper->flags | FWUPD_INSTALL_FLAG_FORCE,
881 &error_local)) {
Richard Hughes33dcfb72020-09-28 15:58:39 +0100882 if (!g_error_matches (error_local,
883 FWUPD_ERROR,
884 FWUPD_ERROR_NOT_FOUND)) {
885 g_debug ("first pass requirement on %s:%s failed: %s",
886 fu_device_get_id (device),
887 xb_node_query_text (component, "id", NULL),
888 error_local->message);
889 }
Mario Limonciello537da0e2020-03-09 15:38:17 -0500890 g_ptr_array_add (errors, g_steal_pointer (&error_local));
891 continue;
892 }
893
894 /* make a second pass using possibly updated version format now */
895 fu_engine_md_refresh_device_from_component (priv->engine, device, component);
896 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100897 helper->request,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500898 task,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100899 helper->flags,
Richard Hughes4ad41f02018-05-08 14:35:36 +0100900 &error_local)) {
Mario Limonciello537da0e2020-03-09 15:38:17 -0500901 g_debug ("second pass requirement on %s:%s failed: %s",
Richard Hughes4ad41f02018-05-08 14:35:36 +0100902 fu_device_get_id (device),
Richard Hughes481aa2a2018-09-18 20:51:46 +0100903 xb_node_query_text (component, "id", NULL),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100904 error_local->message);
905 g_ptr_array_add (errors, g_steal_pointer (&error_local));
906 continue;
907 }
Mario Limonciello381c27c2020-10-23 16:32:26 -0500908 if (!fu_engine_check_trust (task, &error_local)) {
909 g_ptr_array_add (errors, g_steal_pointer (&error_local));
910 continue;
911 }
Richard Hughes4ad41f02018-05-08 14:35:36 +0100912
Mario Limonciello7a3df4b2019-01-31 10:27:22 -0600913 /* if component should have an update message from CAB */
914 fu_device_incorporate_from_component (device, component);
915
Richard Hughes4ad41f02018-05-08 14:35:36 +0100916 /* get the action IDs for the valid device */
917 action_id = fu_install_task_get_action_id (task);
918 if (!g_ptr_array_find (helper->action_ids, action_id, NULL))
919 g_ptr_array_add (helper->action_ids, g_strdup (action_id));
920 g_ptr_array_add (helper->install_tasks, g_steal_pointer (&task));
921 }
922 }
923
Richard Hughes9f86ade2018-05-10 21:11:22 +0100924 /* order the install tasks by the device priority */
925 g_ptr_array_sort (helper->install_tasks, fu_main_install_task_sort_cb);
926
Richard Hughes4ad41f02018-05-08 14:35:36 +0100927 /* nothing suitable */
928 if (helper->install_tasks->len == 0) {
Richard Hughese82eef32018-05-20 10:41:26 +0100929 GError *error_tmp = fu_common_error_array_get_best (errors);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100930 g_propagate_error (error, error_tmp);
931 return FALSE;
932 }
933
934 /* authenticate all things in the action_ids */
935 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
936 fu_main_authorize_install_queue (g_steal_pointer (&helper));
937 return TRUE;
938}
939
Richard Hughesb6f79552017-11-11 07:58:17 +0000940static gboolean
941fu_main_device_id_valid (const gchar *device_id, GError **error)
942{
943 if (g_strcmp0 (device_id, FWUPD_DEVICE_ID_ANY) == 0)
944 return TRUE;
945 if (device_id != NULL && strlen (device_id) >= 4)
946 return TRUE;
947 g_set_error (error,
948 FWUPD_ERROR,
949 FWUPD_ERROR_INTERNAL,
950 "invalid device ID: %s",
951 device_id);
952 return FALSE;
953}
954
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000955static void
956fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
957 const gchar *object_path, const gchar *interface_name,
958 const gchar *method_name, GVariant *parameters,
959 GDBusMethodInvocation *invocation, gpointer user_data)
960{
961 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughes9945edb2017-06-19 10:03:55 +0100962 GVariant *val = NULL;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100963 g_autoptr(FuEngineRequest) request = NULL;
Richard Hughes060af612016-08-17 17:32:34 +0100964 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000965
Richard Hughesdf89cd52020-06-26 20:25:18 +0100966 /* build request */
967 request = fu_main_create_request (priv, sender, &error);
968 if (request == NULL) {
969 g_dbus_method_invocation_return_gerror (invocation, error);
970 return;
971 }
972
Richard Hughes75b965d2018-11-15 13:51:21 +0000973 /* activity */
974 fu_engine_idle_reset (priv->engine);
975
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000976 if (g_strcmp0 (method_name, "GetDevices") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100977 g_autoptr(GPtrArray) devices = NULL;
Richard Hughesf508e762015-02-27 12:49:36 +0000978 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100979 devices = fu_engine_get_devices (priv->engine, &error);
980 if (devices == NULL) {
981 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100982 return;
983 }
Richard Hughesdf89cd52020-06-26 20:25:18 +0100984 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500985 if (val == NULL) {
986 g_dbus_method_invocation_return_gerror (invocation, error);
987 return;
988 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100989 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100990 return;
991 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100992 if (g_strcmp0 (method_name, "GetPlugins") == 0) {
993 g_debug ("Called %s()", method_name);
994 val = fu_main_plugin_array_to_variant (fu_engine_get_plugins (priv->engine));
995 g_dbus_method_invocation_return_value (invocation, val);
996 return;
997 }
Richard Hughese4a100c2017-06-04 21:23:50 +0100998 if (g_strcmp0 (method_name, "GetReleases") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100999 const gchar *device_id;
Richard Hughese4a100c2017-06-04 21:23:50 +01001000 g_autoptr(GPtrArray) releases = NULL;
Richard Hughese4a100c2017-06-04 21:23:50 +01001001 g_variant_get (parameters, "(&s)", &device_id);
1002 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001003 if (!fu_main_device_id_valid (device_id, &error)) {
1004 g_dbus_method_invocation_return_gerror (invocation, error);
1005 return;
1006 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001007 releases = fu_engine_get_releases (priv->engine, request, device_id, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001008 if (releases == NULL) {
1009 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughese4a100c2017-06-04 21:23:50 +01001010 return;
1011 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001012 val = fu_main_release_array_to_variant (releases);
1013 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughese4a100c2017-06-04 21:23:50 +01001014 return;
1015 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001016 if (g_strcmp0 (method_name, "GetApprovedFirmware") == 0) {
1017 GVariantBuilder builder;
1018 GPtrArray *checksums = fu_engine_get_approved_firmware (priv->engine);
1019 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1020 for (guint i = 0; i < checksums->len; i++) {
1021 const gchar *checksum = g_ptr_array_index (checksums, i);
1022 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1023 }
1024 val = g_variant_builder_end (&builder);
1025 g_dbus_method_invocation_return_value (invocation,
1026 g_variant_new_tuple (&val, 1));
1027 return;
1028 }
Richard Hughes31206832020-07-27 15:31:11 +01001029 if (g_strcmp0 (method_name, "GetBlockedFirmware") == 0) {
1030 GVariantBuilder builder;
1031 GPtrArray *checksums = fu_engine_get_blocked_firmware (priv->engine);
1032 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1033 for (guint i = 0; i < checksums->len; i++) {
1034 const gchar *checksum = g_ptr_array_index (checksums, i);
1035 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1036 }
1037 val = g_variant_builder_end (&builder);
1038 g_dbus_method_invocation_return_value (invocation,
1039 g_variant_new_tuple (&val, 1));
1040 return;
1041 }
Richard Hughes6ecc4ca2020-05-20 18:42:46 +01001042 if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
1043 GHashTableIter iter;
1044 GVariantBuilder builder;
1045 const gchar *key;
1046 const gchar *value;
1047 g_autoptr(GHashTable) metadata = NULL;
1048
1049 metadata = fu_engine_get_report_metadata (priv->engine, &error);
1050 if (metadata == NULL) {
1051 g_dbus_method_invocation_return_gerror (invocation, error);
1052 return;
1053 }
1054 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
1055 g_hash_table_iter_init (&iter, metadata);
1056 while (g_hash_table_iter_next (&iter,
1057 (gpointer *) &key,
1058 (gpointer *) &value)) {
1059 g_variant_builder_add_value (&builder,
1060 g_variant_new ("{ss}", key, value));
1061 }
1062 val = g_variant_builder_end (&builder);
1063 g_dbus_method_invocation_return_value (invocation,
1064 g_variant_new_tuple (&val, 1));
1065 return;
1066 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001067 if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
1068 g_autofree gchar *checksums_str = NULL;
1069 g_auto(GStrv) checksums = NULL;
1070 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001071#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001072 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001073#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001074
1075 g_variant_get (parameters, "(^as)", &checksums);
1076 checksums_str = g_strjoinv (",", checksums);
1077 g_debug ("Called %s(%s)", method_name, checksums_str);
1078
1079 /* authenticate */
1080 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1081 helper = g_new0 (FuMainAuthHelper, 1);
1082 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001083 helper->request = g_steal_pointer (&request);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001084 helper->invocation = g_object_ref (invocation);
1085 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1086 for (guint i = 0; checksums[i] != NULL; i++)
1087 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001088#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001089 subject = polkit_system_bus_name_new (sender);
1090 polkit_authority_check_authorization (priv->authority, subject,
1091 "org.freedesktop.fwupd.set-approved-firmware",
1092 NULL,
1093 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1094 NULL,
1095 fu_main_authorize_set_approved_firmware_cb,
1096 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001097#else
1098 fu_main_authorize_set_approved_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1099#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001100 return;
1101 }
Richard Hughes31206832020-07-27 15:31:11 +01001102 if (g_strcmp0 (method_name, "SetBlockedFirmware") == 0) {
1103 g_autofree gchar *checksums_str = NULL;
1104 g_auto(GStrv) checksums = NULL;
1105 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001106#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001107 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001108#endif
Richard Hughes31206832020-07-27 15:31:11 +01001109 g_variant_get (parameters, "(^as)", &checksums);
1110 checksums_str = g_strjoinv (",", checksums);
1111 g_debug ("Called %s(%s)", method_name, checksums_str);
1112
1113 /* authenticate */
1114 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1115 helper = g_new0 (FuMainAuthHelper, 1);
1116 helper->priv = priv;
1117 helper->request = g_steal_pointer (&request);
1118 helper->invocation = g_object_ref (invocation);
1119 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1120 for (guint i = 0; checksums[i] != NULL; i++)
1121 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001122#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001123 subject = polkit_system_bus_name_new (sender);
1124 polkit_authority_check_authorization (priv->authority, subject,
1125 "org.freedesktop.fwupd.set-approved-firmware",
1126 NULL,
1127 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1128 NULL,
1129 fu_main_authorize_set_blocked_firmware_cb,
1130 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001131#else
1132 fu_main_authorize_set_blocked_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1133#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +01001134 return;
1135 }
Richard Hughes3d607622019-03-07 16:59:27 +00001136 if (g_strcmp0 (method_name, "SelfSign") == 0) {
1137 GVariant *prop_value;
1138 gchar *prop_key;
1139 g_autofree gchar *value = NULL;
1140 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001141#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001142 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001143#endif
Richard Hughes3d607622019-03-07 16:59:27 +00001144 g_autoptr(GVariantIter) iter = NULL;
1145
1146 g_variant_get (parameters, "(sa{sv})", &value, &iter);
1147 g_debug ("Called %s(%s)", method_name, value);
1148
1149 /* get flags */
1150 helper = g_new0 (FuMainAuthHelper, 1);
1151 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
1152 g_debug ("got option %s", prop_key);
1153 if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
1154 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001155 helper->flags |= JCAT_SIGN_FLAG_ADD_TIMESTAMP;
Richard Hughes3d607622019-03-07 16:59:27 +00001156 if (g_strcmp0 (prop_key, "add-cert") == 0 &&
1157 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001158 helper->flags |= JCAT_SIGN_FLAG_ADD_CERT;
Richard Hughes3d607622019-03-07 16:59:27 +00001159 g_variant_unref (prop_value);
1160 }
1161
1162 /* authenticate */
1163 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1164 helper->priv = priv;
1165 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001166 helper->request = g_steal_pointer (&request);
Richard Hughes3d607622019-03-07 16:59:27 +00001167 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001168#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001169 subject = polkit_system_bus_name_new (sender);
1170 polkit_authority_check_authorization (priv->authority, subject,
1171 "org.freedesktop.fwupd.self-sign",
1172 NULL,
1173 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1174 NULL,
1175 fu_main_authorize_self_sign_cb,
1176 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001177#else
1178 fu_main_authorize_self_sign_cb (NULL, NULL, g_steal_pointer (&helper));
1179#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +00001180 return;
1181 }
Richard Hughes97284b12017-09-13 17:07:58 +01001182 if (g_strcmp0 (method_name, "GetDowngrades") == 0) {
1183 const gchar *device_id;
1184 g_autoptr(GPtrArray) releases = NULL;
1185 g_variant_get (parameters, "(&s)", &device_id);
1186 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001187 if (!fu_main_device_id_valid (device_id, &error)) {
1188 g_dbus_method_invocation_return_gerror (invocation, error);
1189 return;
1190 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001191 releases = fu_engine_get_downgrades (priv->engine, request, device_id, &error);
Richard Hughes97284b12017-09-13 17:07:58 +01001192 if (releases == NULL) {
1193 g_dbus_method_invocation_return_gerror (invocation, error);
1194 return;
1195 }
1196 val = fu_main_release_array_to_variant (releases);
1197 g_dbus_method_invocation_return_value (invocation, val);
1198 return;
1199 }
Richard Hughesa96413a2017-09-13 17:19:59 +01001200 if (g_strcmp0 (method_name, "GetUpgrades") == 0) {
1201 const gchar *device_id;
1202 g_autoptr(GPtrArray) releases = NULL;
1203 g_variant_get (parameters, "(&s)", &device_id);
1204 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001205 if (!fu_main_device_id_valid (device_id, &error)) {
1206 g_dbus_method_invocation_return_gerror (invocation, error);
1207 return;
1208 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001209 releases = fu_engine_get_upgrades (priv->engine, request, device_id, &error);
Richard Hughesa96413a2017-09-13 17:19:59 +01001210 if (releases == NULL) {
1211 g_dbus_method_invocation_return_gerror (invocation, error);
1212 return;
1213 }
1214 val = fu_main_release_array_to_variant (releases);
1215 g_dbus_method_invocation_return_value (invocation, val);
1216 return;
1217 }
Richard Hughes4c369702017-06-16 15:31:38 +01001218 if (g_strcmp0 (method_name, "GetRemotes") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001219 g_autoptr(GPtrArray) remotes = NULL;
Richard Hughes4c369702017-06-16 15:31:38 +01001220 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001221 remotes = fu_engine_get_remotes (priv->engine, &error);
1222 if (remotes == NULL) {
1223 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes4c369702017-06-16 15:31:38 +01001224 return;
1225 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001226 val = fu_main_remote_array_to_variant (remotes);
1227 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes4c369702017-06-16 15:31:38 +01001228 return;
1229 }
Richard Hughes476363a2018-01-11 10:08:58 +00001230 if (g_strcmp0 (method_name, "GetHistory") == 0) {
1231 g_autoptr(GPtrArray) devices = NULL;
1232 g_debug ("Called %s()", method_name);
1233 devices = fu_engine_get_history (priv->engine, &error);
1234 if (devices == NULL) {
1235 g_dbus_method_invocation_return_gerror (invocation, error);
1236 return;
1237 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001238 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -05001239 if (val == NULL) {
1240 g_dbus_method_invocation_return_gerror (invocation, error);
1241 return;
1242 }
Richard Hughes476363a2018-01-11 10:08:58 +00001243 g_dbus_method_invocation_return_value (invocation, val);
1244 return;
1245 }
Richard Hughes196c6c62020-05-11 19:42:47 +01001246 if (g_strcmp0 (method_name, "GetHostSecurityAttrs") == 0) {
Richard Hughesf58ac732020-05-12 15:23:44 +01001247 g_autoptr(FuSecurityAttrs) attrs = NULL;
Richard Hughes196c6c62020-05-11 19:42:47 +01001248 g_debug ("Called %s()", method_name);
Richard Hughesa018b3c2020-08-28 17:08:19 +01001249 if (priv->machine_kind != FU_MAIN_MACHINE_KIND_PHYSICAL) {
1250 g_dbus_method_invocation_return_error_literal (invocation,
1251 FWUPD_ERROR,
1252 FWUPD_ERROR_NOT_SUPPORTED,
1253 "HSI unavailable for hypervisor");
1254 return;
1255 }
Richard Hughes56e7ae52020-05-17 21:00:23 +01001256 attrs = fu_engine_get_host_security_attrs (priv->engine);
Richard Hughesf58ac732020-05-12 15:23:44 +01001257 val = fu_security_attrs_to_variant (attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001258 g_dbus_method_invocation_return_value (invocation, val);
1259 return;
1260 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001261 if (g_strcmp0 (method_name, "ClearResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001262 const gchar *device_id;
1263 g_variant_get (parameters, "(&s)", &device_id);
1264 g_debug ("Called %s(%s)", method_name, device_id);
1265 if (!fu_engine_clear_results (priv->engine, device_id, &error)) {
1266 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001267 return;
1268 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001269 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001270 return;
1271 }
Richard Hughes6b222952018-01-11 10:20:48 +00001272 if (g_strcmp0 (method_name, "ModifyDevice") == 0) {
1273 const gchar *device_id;
1274 const gchar *key = NULL;
1275 const gchar *value = NULL;
1276
1277 /* check the id exists */
1278 g_variant_get (parameters, "(&s&s&s)", &device_id, &key, &value);
1279 g_debug ("Called %s(%s,%s=%s)", method_name, device_id, key, value);
1280 if (!fu_engine_modify_device (priv->engine, device_id, key, value, &error)) {
1281 g_dbus_method_invocation_return_gerror (invocation, error);
1282 return;
1283 }
1284 g_dbus_method_invocation_return_value (invocation, NULL);
1285 return;
1286 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001287 if (g_strcmp0 (method_name, "GetResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001288 const gchar *device_id = NULL;
Richard Hughes93b15762017-09-15 11:05:23 +01001289 g_autoptr(FwupdDevice) result = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +01001290 g_variant_get (parameters, "(&s)", &device_id);
1291 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001292 if (!fu_main_device_id_valid (device_id, &error)) {
1293 g_dbus_method_invocation_return_gerror (invocation, error);
1294 return;
1295 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001296 result = fu_engine_get_results (priv->engine, device_id, &error);
1297 if (result == NULL) {
1298 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001299 return;
1300 }
Richard Hughese0bd53e2017-09-17 08:29:02 +01001301 val = fwupd_device_to_variant (result);
1302 g_dbus_method_invocation_return_value (invocation,
1303 g_variant_new_tuple (&val, 1));
Richard Hughes0e883ee2015-03-18 17:22:33 +00001304 return;
1305 }
Richard Hughesba73c762017-09-15 14:31:17 +01001306 if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
Richard Hughes1b50d962017-06-02 12:23:00 +01001307 GDBusMessage *message;
1308 GUnixFDList *fd_list;
Richard Hughes9945edb2017-06-19 10:03:55 +01001309 const gchar *remote_id = NULL;
Richard Hughes1b50d962017-06-02 12:23:00 +01001310 gint fd_data;
1311 gint fd_sig;
1312
Richard Hughes9945edb2017-06-19 10:03:55 +01001313 g_variant_get (parameters, "(&shh)", &remote_id, &fd_data, &fd_sig);
1314 g_debug ("Called %s(%s,%i,%i)", method_name, remote_id, fd_data, fd_sig);
Richard Hughes1b50d962017-06-02 12:23:00 +01001315
Richard Hughes5935ebd2017-06-16 15:40:31 +01001316 /* update the metadata store */
Richard Hughes1b50d962017-06-02 12:23:00 +01001317 message = g_dbus_method_invocation_get_message (invocation);
1318 fd_list = g_dbus_message_get_unix_fd_list (message);
1319 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
1320 g_set_error (&error,
1321 FWUPD_ERROR,
1322 FWUPD_ERROR_INTERNAL,
1323 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001324 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001325 return;
1326 }
1327 fd_data = g_unix_fd_list_get (fd_list, 0, &error);
1328 if (fd_data < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001329 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001330 return;
1331 }
1332 fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
1333 if (fd_sig < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001334 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001335 return;
1336 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001337
1338 /* store new metadata (will close the fds when done) */
1339 if (!fu_engine_update_metadata (priv->engine, remote_id,
1340 fd_data, fd_sig, &error)) {
Richard Hughesf3d46c62017-11-28 14:01:30 +00001341 g_prefix_error (&error, "Failed to update metadata for %s: ", remote_id);
Richard Hughes9945edb2017-06-19 10:03:55 +01001342 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001343 return;
1344 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001345 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001346 return;
1347 }
Richard Hughes9a410ce2016-02-28 15:58:54 +00001348 if (g_strcmp0 (method_name, "Unlock") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001349 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001350 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001351#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001352 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001353#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +01001354 g_variant_get (parameters, "(&s)", &device_id);
1355 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001356 if (!fu_main_device_id_valid (device_id, &error)) {
1357 g_dbus_method_invocation_return_gerror (invocation, error);
1358 return;
1359 }
Richard Hughesfe5cc902016-06-29 10:00:00 +01001360
Richard Hughes9a410ce2016-02-28 15:58:54 +00001361 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001362 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes9945edb2017-06-19 10:03:55 +01001363 helper = g_new0 (FuMainAuthHelper, 1);
1364 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001365 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001366 helper->invocation = g_object_ref (invocation);
1367 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001368#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001369 subject = polkit_system_bus_name_new (sender);
Richard Hughes9945edb2017-06-19 10:03:55 +01001370 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes9a410ce2016-02-28 15:58:54 +00001371 "org.freedesktop.fwupd.device-unlock",
1372 NULL,
1373 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1374 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001375 fu_main_authorize_unlock_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001376 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001377#else
1378 fu_main_authorize_unlock_cb (NULL, NULL, g_steal_pointer (&helper));
1379#endif /* HAVE_POLKIT */
Richard Hughes9a410ce2016-02-28 15:58:54 +00001380 return;
1381 }
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001382 if (g_strcmp0 (method_name, "Activate") == 0) {
1383 const gchar *device_id = NULL;
1384 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001385#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001386 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001387#endif
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001388 g_variant_get (parameters, "(&s)", &device_id);
1389 g_debug ("Called %s(%s)", method_name, device_id);
1390 if (!fu_main_device_id_valid (device_id, &error)) {
1391 g_dbus_method_invocation_return_gerror (invocation, error);
1392 return;
1393 }
1394
1395 /* authenticate */
1396 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1397 helper = g_new0 (FuMainAuthHelper, 1);
1398 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001399 helper->request = g_steal_pointer (&request);
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001400 helper->invocation = g_object_ref (invocation);
1401 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001402#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001403 subject = polkit_system_bus_name_new (sender);
1404 polkit_authority_check_authorization (priv->authority, subject,
1405 "org.freedesktop.fwupd.device-activate",
1406 NULL,
1407 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1408 NULL,
1409 fu_main_authorize_activate_cb,
1410 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001411#else
1412 fu_main_authorize_activate_cb (NULL, NULL, g_steal_pointer (&helper));
1413#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001414 return;
1415 }
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001416 if (g_strcmp0 (method_name, "ModifyConfig") == 0) {
1417 g_autofree gchar *key = NULL;
1418 g_autofree gchar *value = NULL;
1419 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001420#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001421 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001422#endif
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001423 g_variant_get (parameters, "(ss)", &key, &value);
1424 g_debug ("Called %s(%s=%s)", method_name, key, value);
1425
1426 /* authenticate */
1427 helper = g_new0 (FuMainAuthHelper, 1);
1428 helper->priv = priv;
1429 helper->key = g_steal_pointer (&key);
1430 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001431 helper->request = g_steal_pointer (&request);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001432 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001433#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001434 subject = polkit_system_bus_name_new (sender);
1435 polkit_authority_check_authorization (priv->authority, subject,
1436 "org.freedesktop.fwupd.modify-config",
1437 NULL,
1438 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1439 NULL,
1440 fu_main_modify_config_cb,
1441 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001442#else
1443 fu_main_modify_config_cb (NULL, NULL, g_steal_pointer (&helper));
1444#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001445 return;
1446 }
Richard Hughesa6bd5582017-09-07 14:32:22 +01001447 if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
Richard Hughesa6bd5582017-09-07 14:32:22 +01001448 const gchar *remote_id = NULL;
1449 const gchar *key = NULL;
1450 const gchar *value = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001451 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001452#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001453 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001454#endif
Richard Hughesa6bd5582017-09-07 14:32:22 +01001455 /* check the id exists */
1456 g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
1457 g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
1458
1459 /* create helper object */
1460 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001461 helper->request = g_steal_pointer (&request);
Richard Hughesa6bd5582017-09-07 14:32:22 +01001462 helper->invocation = g_object_ref (invocation);
1463 helper->remote_id = g_strdup (remote_id);
1464 helper->key = g_strdup (key);
1465 helper->value = g_strdup (value);
1466 helper->priv = priv;
1467
1468 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001469 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001470#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001471 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001472 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughesa6bd5582017-09-07 14:32:22 +01001473 "org.freedesktop.fwupd.modify-remote",
1474 NULL,
1475 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1476 NULL,
1477 fu_main_authorize_modify_remote_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001478 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001479#else
1480 fu_main_authorize_modify_remote_cb (NULL, NULL, g_steal_pointer (&helper));
1481#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +01001482 return;
1483 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001484 if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001485 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001486 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001487#ifdef HAVE_POLKIT
Richard Hughes29c220d2016-12-14 17:09:54 +00001488 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001489#endif
Richard Hughes29c220d2016-12-14 17:09:54 +00001490
1491 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001492 g_variant_get (parameters, "(&s)", &device_id);
1493 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001494 if (!fu_main_device_id_valid (device_id, &error)) {
1495 g_dbus_method_invocation_return_gerror (invocation, error);
1496 return;
1497 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001498
Richard Hughes9945edb2017-06-19 10:03:55 +01001499 /* create helper object */
Richard Hughes29c220d2016-12-14 17:09:54 +00001500 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001501 helper->request = g_steal_pointer (&request);
Richard Hughes29c220d2016-12-14 17:09:54 +00001502 helper->invocation = g_object_ref (invocation);
Richard Hughes9945edb2017-06-19 10:03:55 +01001503 helper->device_id = g_strdup (device_id);
Richard Hughes29c220d2016-12-14 17:09:54 +00001504 helper->priv = priv;
Richard Hughes29c220d2016-12-14 17:09:54 +00001505
1506 /* authenticate */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001507#ifdef HAVE_POLKIT
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001508 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes29c220d2016-12-14 17:09:54 +00001509 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001510 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes29c220d2016-12-14 17:09:54 +00001511 "org.freedesktop.fwupd.verify-update",
1512 NULL,
1513 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1514 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001515 fu_main_authorize_verify_update_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001516 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001517#else
1518 fu_main_authorize_verify_update_cb (NULL, NULL, g_steal_pointer (&helper));
1519#endif /* HAVE_POLKIT */
Richard Hughes29c220d2016-12-14 17:09:54 +00001520 return;
1521 }
Richard Hughesa043c2e2015-06-29 08:43:18 +01001522 if (g_strcmp0 (method_name, "Verify") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001523 const gchar *device_id = NULL;
1524 g_variant_get (parameters, "(&s)", &device_id);
1525 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001526 if (!fu_main_device_id_valid (device_id, &error)) {
1527 g_dbus_method_invocation_return_gerror (invocation, error);
1528 return;
1529 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001530 if (!fu_engine_verify (priv->engine, device_id, &error)) {
1531 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001532 return;
1533 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001534 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001535 return;
1536 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001537 if (g_strcmp0 (method_name, "SetFeatureFlags") == 0) {
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001538 FwupdFeatureFlags feature_flags;
1539 guint64 feature_flags_u64 = 0;
1540 g_variant_get (parameters, "(t)", &feature_flags_u64);
1541 g_debug ("Called %s(%" G_GUINT64_FORMAT ")", method_name, feature_flags_u64);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001542
1543 /* old flags for the same sender will be automatically destroyed */
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001544 feature_flags = feature_flags_u64;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001545 g_hash_table_insert (priv->sender_features,
1546 g_strdup (sender),
Richard Hughesc9088e72021-03-15 15:58:13 +00001547#if GLIB_CHECK_VERSION(2,67,4)
1548 g_memdup2 (&feature_flags, sizeof(feature_flags)));
1549#else
Richard Hughesdf89cd52020-06-26 20:25:18 +01001550 g_memdup (&feature_flags, sizeof(feature_flags)));
Richard Hughesc9088e72021-03-15 15:58:13 +00001551#endif
Richard Hughesdf89cd52020-06-26 20:25:18 +01001552 g_dbus_method_invocation_return_value (invocation, NULL);
1553 return;
1554 }
Richard Hughes63a407a2015-07-22 08:54:14 +01001555 if (g_strcmp0 (method_name, "Install") == 0) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001556 GVariant *prop_value;
Richard Hughes9945edb2017-06-19 10:03:55 +01001557 const gchar *device_id = NULL;
Richard Hughes74cc2172015-02-27 13:19:46 +00001558 gchar *prop_key;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001559 gint32 fd_handle = 0;
1560 gint fd;
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001561 guint64 archive_size_max;
Richard Hughes9945edb2017-06-19 10:03:55 +01001562 GDBusMessage *message;
1563 GUnixFDList *fd_list;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001564 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001565 g_autoptr(GVariantIter) iter = NULL;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001566
1567 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001568 g_variant_get (parameters, "(&sha{sv})", &device_id, &fd_handle, &iter);
1569 g_debug ("Called %s(%s,%i)", method_name, device_id, fd_handle);
Richard Hughesb6f79552017-11-11 07:58:17 +00001570 if (!fu_main_device_id_valid (device_id, &error)) {
1571 g_dbus_method_invocation_return_gerror (invocation, error);
1572 return;
1573 }
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001574
Richard Hughes9945edb2017-06-19 10:03:55 +01001575 /* create helper object */
1576 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001577 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001578 helper->invocation = g_object_ref (invocation);
1579 helper->device_id = g_strdup (device_id);
1580 helper->priv = priv;
1581
1582 /* get flags */
1583 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001584 g_debug ("got option %s", prop_key);
1585 if (g_strcmp0 (prop_key, "offline") == 0 &&
1586 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001587 helper->flags |= FWUPD_INSTALL_FLAG_OFFLINE;
Richard Hughese7c12642015-03-04 20:28:59 +00001588 if (g_strcmp0 (prop_key, "allow-older") == 0 &&
1589 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001590 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_OLDER;
Richard Hughese7c12642015-03-04 20:28:59 +00001591 if (g_strcmp0 (prop_key, "allow-reinstall") == 0 &&
1592 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001593 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
Richard Hughes5bbf0132020-10-05 13:44:39 +01001594 if (g_strcmp0 (prop_key, "allow-branch-switch") == 0 &&
1595 g_variant_get_boolean (prop_value) == TRUE)
1596 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH;
Mario Limonciello71a5b982016-05-10 15:38:53 -05001597 if (g_strcmp0 (prop_key, "force") == 0 &&
Richard Hughes6450d0d2020-10-06 16:05:24 +01001598 g_variant_get_boolean (prop_value) == TRUE) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001599 helper->flags |= FWUPD_INSTALL_FLAG_FORCE;
Richard Hughes6450d0d2020-10-06 16:05:24 +01001600 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
1601 }
1602 if (g_strcmp0 (prop_key, "ignore-power") == 0 &&
1603 g_variant_get_boolean (prop_value) == TRUE)
1604 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
Richard Hughes76e0f942018-05-14 16:24:00 +01001605 if (g_strcmp0 (prop_key, "no-history") == 0 &&
1606 g_variant_get_boolean (prop_value) == TRUE)
1607 helper->flags |= FWUPD_INSTALL_FLAG_NO_HISTORY;
Richard Hughes1ffde6c2015-03-02 22:44:48 +00001608 g_variant_unref (prop_value);
Richard Hughes74cc2172015-02-27 13:19:46 +00001609 }
1610
Richard Hughes9945edb2017-06-19 10:03:55 +01001611
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001612 /* get the fd */
1613 message = g_dbus_method_invocation_get_message (invocation);
1614 fd_list = g_dbus_message_get_unix_fd_list (message);
1615 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001616 g_set_error (&error,
1617 FWUPD_ERROR,
1618 FWUPD_ERROR_INTERNAL,
1619 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001620 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001621 return;
1622 }
Richard Hughes7419e962016-11-22 19:48:06 +00001623 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001624 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001625 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001626 return;
1627 }
1628
Richard Hughes9945edb2017-06-19 10:03:55 +01001629 /* parse the cab file before authenticating so we can work out
1630 * what action ID to use, for instance, if this is trusted --
1631 * this will also close the fd when done */
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001632 archive_size_max = fu_engine_get_archive_size_max (priv->engine);
1633 helper->blob_cab = fu_common_get_contents_fd (fd, archive_size_max, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001634 if (helper->blob_cab == NULL) {
1635 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes5d14def2015-10-07 17:43:10 +01001636 return;
1637 }
Richard Hughes4ad41f02018-05-08 14:35:36 +01001638
1639 /* install all the things in the store */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001640#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +01001641 helper->subject = polkit_system_bus_name_new (sender);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001642#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +01001643 if (!fu_main_install_with_helper (g_steal_pointer (&helper), &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001644 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes18423292015-03-09 17:10:50 +00001645 return;
1646 }
1647
Richard Hughes4ad41f02018-05-08 14:35:36 +01001648 /* async return */
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001649 return;
1650 }
Richard Hughes07f963a2017-09-15 14:28:47 +01001651 if (g_strcmp0 (method_name, "GetDetails") == 0) {
Richard Hughes7289a6b2016-05-29 09:27:47 +01001652 GDBusMessage *message;
1653 GUnixFDList *fd_list;
1654 gint32 fd_handle = 0;
1655 gint fd;
Richard Hughes9945edb2017-06-19 10:03:55 +01001656 g_autoptr(GPtrArray) results = NULL;
Richard Hughes7289a6b2016-05-29 09:27:47 +01001657
1658 /* get parameters */
1659 g_variant_get (parameters, "(h)", &fd_handle);
1660 g_debug ("Called %s(%i)", method_name, fd_handle);
1661
1662 /* get the fd */
1663 message = g_dbus_method_invocation_get_message (invocation);
1664 fd_list = g_dbus_message_get_unix_fd_list (message);
1665 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001666 g_set_error (&error,
1667 FWUPD_ERROR,
1668 FWUPD_ERROR_INTERNAL,
1669 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001670 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001671 return;
1672 }
Richard Hughes7419e962016-11-22 19:48:06 +00001673 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001674 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001675 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001676 return;
1677 }
1678
Richard Hughes9945edb2017-06-19 10:03:55 +01001679 /* get details about the file (will close the fd when done) */
Richard Hughesdf89cd52020-06-26 20:25:18 +01001680 results = fu_engine_get_details (priv->engine, request, fd, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001681 if (results == NULL) {
1682 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001683 return;
1684 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001685 val = fu_main_result_array_to_variant (results);
1686 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001687 return;
1688 }
Richard Hughes060af612016-08-17 17:32:34 +01001689 g_set_error (&error,
1690 G_DBUS_ERROR,
1691 G_DBUS_ERROR_UNKNOWN_METHOD,
1692 "no such method %s", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001693 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001694}
1695
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001696static GVariant *
1697fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
1698 const gchar *object_path, const gchar *interface_name,
1699 const gchar *property_name, GError **error,
1700 gpointer user_data)
1701{
Richard Hughes773ce982015-03-09 22:40:57 +00001702 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1703
Richard Hughes75b965d2018-11-15 13:51:21 +00001704 /* activity */
1705 fu_engine_idle_reset (priv->engine);
1706
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001707 if (g_strcmp0 (property_name, "DaemonVersion") == 0)
Richard Hughesfe4b3ea2020-03-30 10:53:20 +01001708 return g_variant_new_string (SOURCE_VERSION);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001709
Richard Hughesf425d292019-01-18 17:57:39 +00001710 if (g_strcmp0 (property_name, "Tainted") == 0)
1711 return g_variant_new_boolean (fu_engine_get_tainted (priv->engine));
1712
Richard Hughes773ce982015-03-09 22:40:57 +00001713 if (g_strcmp0 (property_name, "Status") == 0)
Richard Hughes9945edb2017-06-19 10:03:55 +01001714 return g_variant_new_uint32 (fu_engine_get_status (priv->engine));
Richard Hughes773ce982015-03-09 22:40:57 +00001715
Mario Limonciello20cc9ee2019-09-05 07:27:26 -05001716 if (g_strcmp0 (property_name, "HostProduct") == 0)
1717 return g_variant_new_string (fu_engine_get_host_product (priv->engine));
1718
Richard Hughes0917fb62019-09-21 12:55:37 +01001719 if (g_strcmp0 (property_name, "HostMachineId") == 0)
1720 return g_variant_new_string (fu_engine_get_host_machine_id (priv->engine));
1721
Richard Hughes196c6c62020-05-11 19:42:47 +01001722 if (g_strcmp0 (property_name, "HostSecurityId") == 0)
1723 return g_variant_new_string (fu_engine_get_host_security_id (priv->engine));
1724
Mario Limoncielloeb4c7642019-11-11 10:31:29 -06001725 if (g_strcmp0 (property_name, "Interactive") == 0)
1726 return g_variant_new_boolean (isatty (fileno (stdout)) != 0);
1727
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001728 /* return an error */
1729 g_set_error (error,
Richard Hughes8645ec92015-03-19 10:14:32 +00001730 G_DBUS_ERROR,
1731 G_DBUS_ERROR_UNKNOWN_PROPERTY,
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001732 "failed to get daemon property %s",
1733 property_name);
1734 return NULL;
1735}
1736
Richard Hughesfd468842015-04-22 16:44:08 +01001737static void
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001738fu_main_on_bus_acquired_cb (GDBusConnection *connection,
1739 const gchar *name,
1740 gpointer user_data)
1741{
1742 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1743 guint registration_id;
Richard Hughes46832432015-09-11 13:43:15 +01001744 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001745 static const GDBusInterfaceVTable interface_vtable = {
1746 fu_main_daemon_method_call,
1747 fu_main_daemon_get_property,
1748 NULL
1749 };
1750
1751 priv->connection = g_object_ref (connection);
1752 registration_id = g_dbus_connection_register_object (connection,
1753 FWUPD_DBUS_PATH,
1754 priv->introspection_daemon->interfaces[0],
1755 &interface_vtable,
1756 priv, /* user_data */
1757 NULL, /* user_data_free_func */
1758 NULL); /* GError** */
1759 g_assert (registration_id > 0);
Richard Hughes18423292015-03-09 17:10:50 +00001760
1761 /* connect to D-Bus directly */
1762 priv->proxy_uid =
1763 g_dbus_proxy_new_sync (priv->connection,
1764 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1765 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1766 NULL,
1767 "org.freedesktop.DBus",
1768 "/org/freedesktop/DBus",
1769 "org.freedesktop.DBus",
1770 NULL,
1771 &error);
1772 if (priv->proxy_uid == NULL) {
1773 g_warning ("cannot connect to DBus: %s", error->message);
1774 return;
1775 }
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001776}
1777
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001778static void
1779fu_main_on_name_acquired_cb (GDBusConnection *connection,
1780 const gchar *name,
1781 gpointer user_data)
1782{
Richard Hughes33dcfb72020-09-28 15:58:39 +01001783 g_debug ("acquired name: %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001784}
1785
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001786static void
1787fu_main_on_name_lost_cb (GDBusConnection *connection,
1788 const gchar *name,
1789 gpointer user_data)
1790{
1791 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Mario Limonciello471a0e22020-06-09 10:49:49 -05001792 g_warning ("another service has claimed the dbus name %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001793 g_main_loop_quit (priv->loop);
1794}
1795
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001796static gboolean
1797fu_main_timed_exit_cb (gpointer user_data)
1798{
1799 GMainLoop *loop = (GMainLoop *) user_data;
1800 g_main_loop_quit (loop);
1801 return G_SOURCE_REMOVE;
1802}
1803
Richard Hughesf3dc1622019-03-27 12:48:39 +00001804static void
1805fu_main_argv_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file,
1806 GFileMonitorEvent event_type, gpointer user_data)
1807{
1808 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1809
1810 /* can do straight away? */
1811 if (priv->update_in_progress) {
1812 g_warning ("binary changed during a firmware update, ignoring");
1813 return;
1814 }
1815 g_debug ("binary changed, shutting down");
1816 g_main_loop_quit (priv->loop);
1817}
1818
Richard Hughes603e4f62019-12-11 13:44:09 +00001819#if GLIB_CHECK_VERSION(2,63,3)
1820static void
1821fu_main_memory_monitor_warning_cb (GMemoryMonitor *memory_monitor,
1822 GMemoryMonitorWarningLevel level,
1823 FuMainPrivate *priv)
1824{
1825 /* can do straight away? */
1826 if (priv->update_in_progress) {
1827 g_warning ("OOM during a firmware update, ignoring");
1828 priv->pending_sigterm = TRUE;
1829 return;
1830 }
1831 g_debug ("OOM event, shutting down");
1832 g_main_loop_quit (priv->loop);
1833}
1834#endif
1835
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001836static GDBusNodeInfo *
1837fu_main_load_introspection (const gchar *filename, GError **error)
1838{
Richard Hughes46832432015-09-11 13:43:15 +01001839 g_autoptr(GBytes) data = NULL;
1840 g_autofree gchar *path = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001841
1842 /* lookup data */
1843 path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL);
1844 data = g_resource_lookup_data (fu_get_resource (),
1845 path,
1846 G_RESOURCE_LOOKUP_FLAGS_NONE,
1847 error);
1848 if (data == NULL)
1849 return NULL;
1850
1851 /* build introspection from XML */
1852 return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error);
1853}
1854
Richard Hughesa018b3c2020-08-28 17:08:19 +01001855static gboolean
1856fu_main_is_hypervisor (void)
1857{
1858 g_autofree gchar *buf = NULL;
1859 gsize bufsz = 0;
1860 if (!g_file_get_contents ("/proc/cpuinfo", &buf, &bufsz, NULL))
1861 return FALSE;
1862 return g_strstr_len (buf, (gssize) bufsz, "hypervisor") != NULL;
1863}
1864
1865static gboolean
1866fu_main_is_container (void)
1867{
1868 g_autofree gchar *buf = NULL;
1869 gsize bufsz = 0;
1870 if (!g_file_get_contents ("/proc/1/cgroup", &buf, &bufsz, NULL))
1871 return FALSE;
1872 if (g_strstr_len (buf, (gssize) bufsz, "docker") != NULL)
1873 return TRUE;
1874 if (g_strstr_len (buf, (gssize) bufsz, "lxc") != NULL)
1875 return TRUE;
1876 return FALSE;
1877}
1878
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001879static void
1880fu_main_private_free (FuMainPrivate *priv)
1881{
Richard Hughesdf89cd52020-06-26 20:25:18 +01001882 g_hash_table_unref (priv->sender_features);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001883 if (priv->loop != NULL)
1884 g_main_loop_unref (priv->loop);
1885 if (priv->owner_id > 0)
1886 g_bus_unown_name (priv->owner_id);
1887 if (priv->proxy_uid != NULL)
1888 g_object_unref (priv->proxy_uid);
Richard Hughes9945edb2017-06-19 10:03:55 +01001889 if (priv->engine != NULL)
1890 g_object_unref (priv->engine);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001891 if (priv->connection != NULL)
1892 g_object_unref (priv->connection);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001893#ifdef HAVE_POLKIT
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001894 if (priv->authority != NULL)
1895 g_object_unref (priv->authority);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001896#endif
Richard Hughes0b6f5832020-09-01 20:15:02 +01001897 if (priv->argv0_monitor != NULL) {
1898 g_file_monitor_cancel (priv->argv0_monitor);
Richard Hughesf3dc1622019-03-27 12:48:39 +00001899 g_object_unref (priv->argv0_monitor);
Richard Hughes0b6f5832020-09-01 20:15:02 +01001900 }
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001901 if (priv->introspection_daemon != NULL)
1902 g_dbus_node_info_unref (priv->introspection_daemon);
Richard Hughes603e4f62019-12-11 13:44:09 +00001903#if GLIB_CHECK_VERSION(2,63,3)
1904 if (priv->memory_monitor != NULL)
1905 g_object_unref (priv->memory_monitor);
1906#endif
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001907 g_free (priv);
1908}
1909
Mario Limoncielloa98df552018-04-16 12:15:51 -05001910#pragma clang diagnostic push
1911#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001912G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainPrivate, fu_main_private_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -05001913#pragma clang diagnostic pop
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001914
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001915int
1916main (int argc, char *argv[])
1917{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001918 gboolean immediate_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001919 gboolean timed_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001920 const GOptionEntry options[] = {
1921 { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit,
1922 /* TRANSLATORS: exit after we've started up, used for user profiling */
1923 _("Exit after a small delay"), NULL },
1924 { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit,
1925 /* TRANSLATORS: exit straight away, used for automatic profiling */
1926 _("Exit after the engine has loaded"), NULL },
1927 { NULL}
1928 };
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001929 g_autoptr(FuMainPrivate) priv = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001930 g_autoptr(GError) error = NULL;
Richard Hughesf3dc1622019-03-27 12:48:39 +00001931 g_autoptr(GFile) argv0_file = g_file_new_for_path (argv[0]);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001932 g_autoptr(GOptionContext) context = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001933
1934 setlocale (LC_ALL, "");
1935
Richard Hughes668ee212019-11-22 09:17:46 +00001936 bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001937 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1938 textdomain (GETTEXT_PACKAGE);
1939
1940 /* TRANSLATORS: program name */
Richard Hughes63a407a2015-07-22 08:54:14 +01001941 g_set_application_name (_("Firmware Update Daemon"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001942 context = g_option_context_new (NULL);
1943 g_option_context_add_main_entries (context, options, NULL);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001944 g_option_context_add_group (context, fu_debug_get_option_group ());
Richard Hughes8ded6ca2015-03-16 12:51:36 +00001945 /* TRANSLATORS: program summary */
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001946 g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001947 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1948 g_printerr ("Failed to parse command line: %s\n", error->message);
1949 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001950 }
1951
1952 /* create new objects */
1953 priv = g_new0 (FuMainPrivate, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001954 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 +00001955 priv->loop = g_main_loop_new (NULL, FALSE);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001956
Richard Hughes9945edb2017-06-19 10:03:55 +01001957 /* load engine */
Richard Hughes5b5f6552018-05-18 10:22:39 +01001958 priv->engine = fu_engine_new (FU_APP_FLAGS_NONE);
Richard Hughes9945edb2017-06-19 10:03:55 +01001959 g_signal_connect (priv->engine, "changed",
1960 G_CALLBACK (fu_main_engine_changed_cb),
1961 priv);
1962 g_signal_connect (priv->engine, "device-added",
1963 G_CALLBACK (fu_main_engine_device_added_cb),
1964 priv);
1965 g_signal_connect (priv->engine, "device-removed",
1966 G_CALLBACK (fu_main_engine_device_removed_cb),
1967 priv);
1968 g_signal_connect (priv->engine, "device-changed",
1969 G_CALLBACK (fu_main_engine_device_changed_cb),
1970 priv);
1971 g_signal_connect (priv->engine, "status-changed",
1972 G_CALLBACK (fu_main_engine_status_changed_cb),
1973 priv);
1974 g_signal_connect (priv->engine, "percentage-changed",
1975 G_CALLBACK (fu_main_engine_percentage_changed_cb),
1976 priv);
Richard Hughesc7d870a2020-12-10 10:05:35 +00001977 if (!fu_engine_load (priv->engine,
1978 FU_ENGINE_LOAD_FLAG_COLDPLUG |
1979 FU_ENGINE_LOAD_FLAG_HWINFO |
1980 FU_ENGINE_LOAD_FLAG_REMOTES,
1981 &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001982 g_printerr ("Failed to load engine: %s\n", error->message);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001983 return EXIT_FAILURE;
Richard Hughes804c0752015-08-04 14:53:52 +01001984 }
1985
Mario Limonciello6754f5a2018-10-11 10:50:03 -05001986 g_unix_signal_add_full (G_PRIORITY_DEFAULT,
1987 SIGTERM, fu_main_sigterm_cb,
1988 priv, NULL);
1989
Richard Hughesf3dc1622019-03-27 12:48:39 +00001990 /* restart the daemon if the binary gets replaced */
1991 priv->argv0_monitor = g_file_monitor_file (argv0_file, G_FILE_MONITOR_NONE,
1992 NULL, &error);
1993 g_signal_connect (priv->argv0_monitor, "changed",
1994 G_CALLBACK (fu_main_argv_changed_cb), priv);
1995
Richard Hughes603e4f62019-12-11 13:44:09 +00001996#if GLIB_CHECK_VERSION(2,63,3)
1997 /* shut down on low memory event as we can just rescan hardware */
1998 priv->memory_monitor = g_memory_monitor_dup_default ();
1999 g_signal_connect (G_OBJECT (priv->memory_monitor), "low-memory-warning",
2000 G_CALLBACK (fu_main_memory_monitor_warning_cb), priv);
2001#endif
2002
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002003 /* load introspection from file */
2004 priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
2005 &error);
2006 if (priv->introspection_daemon == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002007 g_printerr ("Failed to load introspection: %s\n", error->message);
2008 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002009 }
2010
Mario Limonciello11b71f42020-10-13 13:39:14 -05002011#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +00002012 /* get authority */
2013 priv->authority = polkit_authority_get_sync (NULL, &error);
2014 if (priv->authority == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002015 g_printerr ("Failed to load authority: %s\n", error->message);
2016 return EXIT_FAILURE;
Richard Hughesf508e762015-02-27 12:49:36 +00002017 }
Mario Limonciello11b71f42020-10-13 13:39:14 -05002018#endif
Richard Hughesf508e762015-02-27 12:49:36 +00002019
Richard Hughesa018b3c2020-08-28 17:08:19 +01002020 /* are we a VM? */
2021 if (fu_main_is_hypervisor ()) {
2022 priv->machine_kind = FU_MAIN_MACHINE_KIND_VIRTUAL;
2023 } else if (fu_main_is_container ()) {
2024 priv->machine_kind = FU_MAIN_MACHINE_KIND_CONTAINER;
2025 }
2026
Richard Hughesebae3962018-09-09 13:40:49 +01002027 /* own the object */
2028 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
2029 FWUPD_DBUS_SERVICE,
2030 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
2031 G_BUS_NAME_OWNER_FLAGS_REPLACE,
2032 fu_main_on_bus_acquired_cb,
2033 fu_main_on_name_acquired_cb,
2034 fu_main_on_name_lost_cb,
2035 priv, NULL);
2036
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002037 /* Only timeout and close the mainloop if we have specified it
2038 * on the command line */
2039 if (immediate_exit)
2040 g_idle_add (fu_main_timed_exit_cb, priv->loop);
2041 else if (timed_exit)
2042 g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop);
2043
Richard Hughesd0ba4692021-02-22 20:57:21 +00002044 /* drop heap except one page */
2045 malloc_trim (4096);
2046
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002047 /* wait */
Richard Hughes33dcfb72020-09-28 15:58:39 +01002048 g_message ("Daemon ready for requests (locale %s)", g_getenv ("LANG"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002049 g_main_loop_run (priv->loop);
2050
Richard Hughesa0531342020-10-23 10:47:26 +01002051#ifdef HAVE_SYSTEMD
2052 /* notify the service manager */
2053 sd_notify (0, "STOPPING=1");
2054#endif
2055
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002056 /* success */
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002057 return EXIT_SUCCESS;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002058}