blob: 0a5f1549761ff61f420cef4657ce4e765e9ddbb4 [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002 * Copyright (C) 2015-2017 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>
Mario Limonciello11b71f42020-10-13 13:39:14 -050017#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000018#include <polkit/polkit.h>
Mario Limonciello11b71f42020-10-13 13:39:14 -050019#endif
Richard Hughesa0531342020-10-23 10:47:26 +010020#ifdef HAVE_SYSTEMD
21#include <systemd/sd-daemon.h>
22#endif
Mario Limoncielloeb4c7642019-11-11 10:31:29 -060023#include <stdio.h>
Richard Hughes67ec8982015-03-03 11:39:27 +000024#include <stdlib.h>
Richard Hughesd5aab652020-02-25 12:47:50 +000025#include <jcat.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000026
Richard Hughes68982c62017-09-13 15:40:14 +010027#include "fwupd-device-private.h"
Richard Hughes7bcb8d42020-10-08 15:47:47 +010028#include "fwupd-plugin-private.h"
Richard Hughes196c6c62020-05-11 19:42:47 +010029#include "fwupd-security-attr-private.h"
Richard Hughes1642b3b2017-06-05 17:40:08 +010030#include "fwupd-release-private.h"
Richard Hughes4c369702017-06-16 15:31:38 +010031#include "fwupd-remote-private.h"
Richard Hughesd6db6b42017-04-12 15:03:10 +010032#include "fwupd-resources.h"
Richard Hughes8e9762d2016-03-17 10:14:15 +000033
Richard Hughes943d2c92017-06-21 09:04:39 +010034#include "fu-common.h"
Richard Hughes8bbfdf42015-02-26 22:28:09 +000035#include "fu-debug.h"
Richard Hughes68982c62017-09-13 15:40:14 +010036#include "fu-device-private.h"
Richard Hughes9945edb2017-06-19 10:03:55 +010037#include "fu-engine.h"
Richard Hughes4ad41f02018-05-08 14:35:36 +010038#include "fu-install-task.h"
Richard Hughesf58ac732020-05-12 15:23:44 +010039#include "fu-security-attrs-private.h"
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000040
Mario Limonciello11b71f42020-10-13 13:39:14 -050041#ifdef HAVE_POLKIT
Philip Withnallbc339aa2016-11-22 16:13:22 +000042#ifndef HAVE_POLKIT_0_114
Mario Limoncielloa98df552018-04-16 12:15:51 -050043#pragma clang diagnostic push
44#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes60f48c22015-10-08 20:25:51 +010045G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitAuthorizationResult, g_object_unref)
46G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitSubject, g_object_unref)
Mario Limoncielloa98df552018-04-16 12:15:51 -050047#pragma clang diagnostic pop
Mario Limonciello11b71f42020-10-13 13:39:14 -050048#endif /* HAVE_POLKIT_0_114 */
49#endif /* HAVE_POLKIT */
Richard Hughes60f48c22015-10-08 20:25:51 +010050
Richard Hughesa018b3c2020-08-28 17:08:19 +010051typedef enum {
52 FU_MAIN_MACHINE_KIND_PHYSICAL,
53 FU_MAIN_MACHINE_KIND_VIRTUAL,
54 FU_MAIN_MACHINE_KIND_CONTAINER,
55} FuMainMachineKind;
56
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000057typedef struct {
58 GDBusConnection *connection;
59 GDBusNodeInfo *introspection_daemon;
Richard Hughes18423292015-03-09 17:10:50 +000060 GDBusProxy *proxy_uid;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000061 GMainLoop *loop;
Richard Hughesf3dc1622019-03-27 12:48:39 +000062 GFileMonitor *argv0_monitor;
Richard Hughesdf89cd52020-06-26 20:25:18 +010063 GHashTable *sender_features; /* sender:FwupdFeatureFlags */
Richard Hughes603e4f62019-12-11 13:44:09 +000064#if GLIB_CHECK_VERSION(2,63,3)
65 GMemoryMonitor *memory_monitor;
66#endif
Mario Limonciello11b71f42020-10-13 13:39:14 -050067#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +000068 PolkitAuthority *authority;
Mario Limonciello11b71f42020-10-13 13:39:14 -050069#endif
Richard Hughesf0a799e2017-01-17 20:13:30 +000070 guint owner_id;
Richard Hughes9945edb2017-06-19 10:03:55 +010071 FuEngine *engine;
Mario Limonciello6754f5a2018-10-11 10:50:03 -050072 gboolean update_in_progress;
73 gboolean pending_sigterm;
Richard Hughesa018b3c2020-08-28 17:08:19 +010074 FuMainMachineKind machine_kind;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000075} FuMainPrivate;
76
Mario Limonciello6754f5a2018-10-11 10:50:03 -050077static gboolean
78fu_main_sigterm_cb (gpointer user_data)
79{
80 FuMainPrivate *priv = (FuMainPrivate *) user_data;
81 if (!priv->update_in_progress) {
82 g_main_loop_quit (priv->loop);
83 return G_SOURCE_REMOVE;
84 }
85 g_warning ("Received SIGTERM during a firmware update, ignoring");
86 priv->pending_sigterm = TRUE;
87 return G_SOURCE_CONTINUE;
88}
89
Richard Hughesd7022b52015-03-11 19:47:06 +000090static void
Richard Hughes9945edb2017-06-19 10:03:55 +010091fu_main_engine_changed_cb (FuEngine *engine, FuMainPrivate *priv)
Richard Hughesd7022b52015-03-11 19:47:06 +000092{
93 /* not yet connected */
94 if (priv->connection == NULL)
95 return;
96 g_dbus_connection_emit_signal (priv->connection,
97 NULL,
98 FWUPD_DBUS_PATH,
99 FWUPD_DBUS_INTERFACE,
100 "Changed",
101 NULL, NULL);
102}
103
Richard Hughes8ca33782016-04-28 15:04:31 +0100104static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100105fu_main_engine_device_added_cb (FuEngine *engine,
106 FuDevice *device,
107 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100108{
109 GVariant *val;
110
111 /* not yet connected */
112 if (priv->connection == NULL)
113 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100114 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100115 g_dbus_connection_emit_signal (priv->connection,
116 NULL,
117 FWUPD_DBUS_PATH,
118 FWUPD_DBUS_INTERFACE,
119 "DeviceAdded",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100120 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100121}
122
Richard Hughes8ca33782016-04-28 15:04:31 +0100123static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100124fu_main_engine_device_removed_cb (FuEngine *engine,
125 FuDevice *device,
126 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100127{
128 GVariant *val;
129
130 /* not yet connected */
131 if (priv->connection == NULL)
132 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100133 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100134 g_dbus_connection_emit_signal (priv->connection,
135 NULL,
136 FWUPD_DBUS_PATH,
137 FWUPD_DBUS_INTERFACE,
138 "DeviceRemoved",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100139 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100140}
141
Richard Hughes8ca33782016-04-28 15:04:31 +0100142static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100143fu_main_engine_device_changed_cb (FuEngine *engine,
144 FuDevice *device,
145 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100146{
147 GVariant *val;
148
149 /* not yet connected */
150 if (priv->connection == NULL)
151 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100152 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100153 g_dbus_connection_emit_signal (priv->connection,
154 NULL,
155 FWUPD_DBUS_PATH,
156 FWUPD_DBUS_INTERFACE,
157 "DeviceChanged",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100158 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100159}
160
Richard Hughes773ce982015-03-09 22:40:57 +0000161static void
162fu_main_emit_property_changed (FuMainPrivate *priv,
163 const gchar *property_name,
164 GVariant *property_value)
165{
166 GVariantBuilder builder;
167 GVariantBuilder invalidated_builder;
168
169 /* not yet connected */
Richard Hughes34fcc022018-09-19 16:16:15 +0100170 if (priv->connection == NULL) {
171 g_variant_unref (g_variant_ref_sink (property_value));
Richard Hughes773ce982015-03-09 22:40:57 +0000172 return;
Richard Hughes34fcc022018-09-19 16:16:15 +0100173 }
Richard Hughes773ce982015-03-09 22:40:57 +0000174
175 /* build the dict */
176 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
Richard Hughes8356a832019-03-21 17:04:38 +0000177 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
Richard Hughes773ce982015-03-09 22:40:57 +0000178 g_variant_builder_add (&builder,
179 "{sv}",
180 property_name,
181 property_value);
182 g_dbus_connection_emit_signal (priv->connection,
183 NULL,
184 FWUPD_DBUS_PATH,
185 "org.freedesktop.DBus.Properties",
186 "PropertiesChanged",
187 g_variant_new ("(sa{sv}as)",
188 FWUPD_DBUS_INTERFACE,
189 &builder,
190 &invalidated_builder),
191 NULL);
192 g_variant_builder_clear (&builder);
193 g_variant_builder_clear (&invalidated_builder);
194}
195
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100196static void
197fu_main_set_status (FuMainPrivate *priv, FwupdStatus status)
198{
199 g_debug ("Emitting PropertyChanged('Status'='%s')",
200 fwupd_status_to_string (status));
201 fu_main_emit_property_changed (priv, "Status",
202 g_variant_new_uint32 (status));
203}
Richard Hughes773ce982015-03-09 22:40:57 +0000204
Richard Hughes9945edb2017-06-19 10:03:55 +0100205static void
206fu_main_engine_status_changed_cb (FuEngine *engine,
207 FwupdStatus status,
208 FuMainPrivate *priv)
209{
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100210 fu_main_set_status (priv, status);
Richard Hughes75b965d2018-11-15 13:51:21 +0000211
212 /* engine has gone idle */
213 if (status == FWUPD_STATUS_SHUTDOWN)
214 g_main_loop_quit (priv->loop);
Richard Hughes773ce982015-03-09 22:40:57 +0000215}
216
Richard Hughes876c0072016-08-17 14:51:03 +0100217static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100218fu_main_engine_percentage_changed_cb (FuEngine *engine,
219 guint percentage,
220 FuMainPrivate *priv)
Richard Hughes876c0072016-08-17 14:51:03 +0100221{
Richard Hughes876c0072016-08-17 14:51:03 +0100222 g_debug ("Emitting PropertyChanged('Percentage'='%u%%')", percentage);
223 fu_main_emit_property_changed (priv, "Percentage",
224 g_variant_new_uint32 (percentage));
225}
226
Richard Hughesdf89cd52020-06-26 20:25:18 +0100227static FuEngineRequest *
228fu_main_create_request (FuMainPrivate *priv, const gchar *sender, GError **error)
Mario Limoncielloe3016602018-09-06 11:20:59 -0500229{
Richard Hughesdf89cd52020-06-26 20:25:18 +0100230 FwupdFeatureFlags *feature_flags;
231 FwupdDeviceFlags device_flags = FWUPD_DEVICE_FLAG_NONE;
232 uid_t calling_uid = 0;
233 g_autoptr(FuEngineRequest) request = fu_engine_request_new ();
Mario Limoncielloe3016602018-09-06 11:20:59 -0500234 g_autoptr(GVariant) value = NULL;
235
Richard Hughesdf89cd52020-06-26 20:25:18 +0100236 g_return_val_if_fail (sender != NULL, NULL);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500237
Richard Hughesdf89cd52020-06-26 20:25:18 +0100238 /* did the client set the list of supported feature */
239 feature_flags = g_hash_table_lookup (priv->sender_features, sender);
240 if (feature_flags != NULL)
241 fu_engine_request_set_feature_flags (request, *feature_flags);
242
243 /* are we root and therefore trusted? */
Mario Limoncielloe3016602018-09-06 11:20:59 -0500244 value = g_dbus_proxy_call_sync (priv->proxy_uid,
245 "GetConnectionUnixUser",
246 g_variant_new ("(s)", sender),
247 G_DBUS_CALL_FLAGS_NONE,
248 2000,
249 NULL,
250 error);
251 if (value == NULL) {
252 g_prefix_error (error, "failed to read user id of caller: ");
Richard Hughesbfe6c772020-08-17 14:48:23 +0100253 return NULL;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500254 }
255 g_variant_get (value, "(u)", &calling_uid);
256 if (calling_uid == 0)
Richard Hughesdf89cd52020-06-26 20:25:18 +0100257 device_flags |= FWUPD_DEVICE_FLAG_TRUSTED;
258 fu_engine_request_set_device_flags (request, device_flags);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500259
Richard Hughesdf89cd52020-06-26 20:25:18 +0100260 /* success */
261 return g_steal_pointer (&request);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500262}
263
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000264static GVariant *
Richard Hughesdf89cd52020-06-26 20:25:18 +0100265fu_main_device_array_to_variant (FuMainPrivate *priv, FuEngineRequest *request,
Mario Limoncielloe3016602018-09-06 11:20:59 -0500266 GPtrArray *devices, GError **error)
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000267{
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000268 GVariantBuilder builder;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500269
Richard Hughes9945edb2017-06-19 10:03:55 +0100270 g_return_val_if_fail (devices->len > 0, NULL);
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000271 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500272
Richard Hughesf192bf02016-07-22 08:26:43 +0100273 for (guint i = 0; i < devices->len; i++) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100274 FuDevice *device = g_ptr_array_index (devices, i);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500275 GVariant *tmp = fwupd_device_to_variant_full (FWUPD_DEVICE (device),
Richard Hughesdf89cd52020-06-26 20:25:18 +0100276 fu_engine_request_get_device_flags (request));
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000277 g_variant_builder_add_value (&builder, tmp);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000278 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100279 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000280}
281
Richard Hughes9945edb2017-06-19 10:03:55 +0100282static GVariant *
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100283fu_main_plugin_array_to_variant (GPtrArray *plugins)
284{
285 GVariantBuilder builder;
286
287 g_return_val_if_fail (plugins->len > 0, NULL);
288 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
289
290 for (guint i = 0; i < plugins->len; i++) {
291 FuDevice *plugin = g_ptr_array_index (plugins, i);
292 GVariant *tmp = fwupd_plugin_to_variant (FWUPD_PLUGIN (plugin));
293 g_variant_builder_add_value (&builder, tmp);
294 }
295 return g_variant_new ("(aa{sv})", &builder);
296}
297
298static GVariant *
Richard Hughes9945edb2017-06-19 10:03:55 +0100299fu_main_release_array_to_variant (GPtrArray *results)
Richard Hughes060af612016-08-17 17:32:34 +0100300{
Richard Hughes9945edb2017-06-19 10:03:55 +0100301 GVariantBuilder builder;
302 g_return_val_if_fail (results->len > 0, NULL);
303 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
304 for (guint i = 0; i < results->len; i++) {
305 FwupdRelease *rel = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100306 GVariant *tmp = fwupd_release_to_variant (rel);
Richard Hughes9945edb2017-06-19 10:03:55 +0100307 g_variant_builder_add_value (&builder, tmp);
308 }
309 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100310}
311
Richard Hughes9945edb2017-06-19 10:03:55 +0100312static GVariant *
313fu_main_remote_array_to_variant (GPtrArray *remotes)
Richard Hughes060af612016-08-17 17:32:34 +0100314{
Richard Hughes9945edb2017-06-19 10:03:55 +0100315 GVariantBuilder builder;
316 g_return_val_if_fail (remotes->len > 0, NULL);
317 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
318 for (guint i = 0; i < remotes->len; i++) {
319 FwupdRemote *remote = g_ptr_array_index (remotes, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100320 GVariant *tmp = fwupd_remote_to_variant (remote);
Richard Hughes9945edb2017-06-19 10:03:55 +0100321 g_variant_builder_add_value (&builder, tmp);
322 }
323 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100324}
325
Richard Hughes9945edb2017-06-19 10:03:55 +0100326static GVariant *
327fu_main_result_array_to_variant (GPtrArray *results)
Richard Hughes8bbfdf42015-02-26 22:28:09 +0000328{
Richard Hughes9945edb2017-06-19 10:03:55 +0100329 GVariantBuilder builder;
330 g_return_val_if_fail (results->len > 0, NULL);
331 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
332 for (guint i = 0; i < results->len; i++) {
Richard Hughes93b15762017-09-15 11:05:23 +0100333 FwupdDevice *result = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100334 GVariant *tmp = fwupd_device_to_variant (result);
Richard Hughes9945edb2017-06-19 10:03:55 +0100335 g_variant_builder_add_value (&builder, tmp);
336 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100337 return g_variant_new ("(aa{sv})", &builder);
Richard Hughesf508e762015-02-27 12:49:36 +0000338}
339
Richard Hughesf508e762015-02-27 12:49:36 +0000340typedef struct {
341 GDBusMethodInvocation *invocation;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100342 FuEngineRequest *request;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500343#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100344 PolkitSubject *subject;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500345#endif
Richard Hughes4ad41f02018-05-08 14:35:36 +0100346 GPtrArray *install_tasks;
347 GPtrArray *action_ids;
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000348 GPtrArray *checksums;
Richard Hughes3d607622019-03-07 16:59:27 +0000349 guint64 flags;
Richard Hughes5d14def2015-10-07 17:43:10 +0100350 GBytes *blob_cab;
Richard Hughes67ec8982015-03-03 11:39:27 +0000351 FuMainPrivate *priv;
Richard Hughes9945edb2017-06-19 10:03:55 +0100352 gchar *device_id;
Richard Hughesa6bd5582017-09-07 14:32:22 +0100353 gchar *remote_id;
354 gchar *key;
355 gchar *value;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100356 XbSilo *silo;
Richard Hughesf508e762015-02-27 12:49:36 +0000357} FuMainAuthHelper;
358
Richard Hughesf508e762015-02-27 12:49:36 +0000359static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100360fu_main_auth_helper_free (FuMainAuthHelper *helper)
Richard Hughesf508e762015-02-27 12:49:36 +0000361{
Richard Hughes4ced4662016-08-26 11:02:31 +0100362 if (helper->blob_cab != NULL)
Richard Hughes5d14def2015-10-07 17:43:10 +0100363 g_bytes_unref (helper->blob_cab);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500364#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100365 if (helper->subject != NULL)
366 g_object_unref (helper->subject);
Mario Limonciello11b71f42020-10-13 13:39:14 -0500367#endif
Richard Hughes481aa2a2018-09-18 20:51:46 +0100368 if (helper->silo != NULL)
369 g_object_unref (helper->silo);
Richard Hughesdf89cd52020-06-26 20:25:18 +0100370 if (helper->request != NULL)
371 g_object_unref (helper->request);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100372 if (helper->install_tasks != NULL)
373 g_ptr_array_unref (helper->install_tasks);
374 if (helper->action_ids != NULL)
375 g_ptr_array_unref (helper->action_ids);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000376 if (helper->checksums != NULL)
377 g_ptr_array_unref (helper->checksums);
Richard Hughes9945edb2017-06-19 10:03:55 +0100378 g_free (helper->device_id);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100379 g_free (helper->remote_id);
380 g_free (helper->key);
381 g_free (helper->value);
Richard Hughes67ec8982015-03-03 11:39:27 +0000382 g_object_unref (helper->invocation);
Richard Hughesf508e762015-02-27 12:49:36 +0000383 g_free (helper);
384}
385
Mario Limoncielloa98df552018-04-16 12:15:51 -0500386#pragma clang diagnostic push
387#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes9945edb2017-06-19 10:03:55 +0100388G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainAuthHelper, fu_main_auth_helper_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -0500389#pragma clang diagnostic pop
Richard Hughes9945edb2017-06-19 10:03:55 +0100390
Mario Limonciello11b71f42020-10-13 13:39:14 -0500391#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100392/* error may or may not already have been set */
Richard Hughesb75c92d2016-02-20 20:22:00 +0000393static gboolean
Richard Hughes9945edb2017-06-19 10:03:55 +0100394fu_main_authorization_is_valid (PolkitAuthorizationResult *auth, GError **error)
Richard Hughes9a410ce2016-02-28 15:58:54 +0000395{
Richard Hughes9945edb2017-06-19 10:03:55 +0100396 /* failed */
Richard Hughesf508e762015-02-27 12:49:36 +0000397 if (auth == NULL) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100398 g_autofree gchar *message = g_strdup ((*error)->message);
399 g_clear_error (error);
400 g_set_error (error,
Richard Hughes060af612016-08-17 17:32:34 +0100401 FWUPD_ERROR,
402 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100403 "Could not check for auth: %s", message);
404 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000405 }
406
407 /* did not auth */
408 if (!polkit_authorization_result_get_is_authorized (auth)) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100409 g_set_error_literal (error,
Richard Hughes060af612016-08-17 17:32:34 +0100410 FWUPD_ERROR,
411 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100412 "Failed to obtain auth");
413 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000414 }
415
416 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100417 return TRUE;
Richard Hughes5d14def2015-10-07 17:43:10 +0100418}
Mario Limonciello11b71f42020-10-13 13:39:14 -0500419#else
420static gboolean
421fu_main_authorization_is_trusted (FuEngineRequest *request, GError **error)
422{
423 FwupdDeviceFlags flags = fu_engine_request_get_device_flags (request);
424 if ((flags & FWUPD_DEVICE_FLAG_TRUSTED) == 0) {
425 g_set_error_literal (error,
426 FWUPD_ERROR,
427 FWUPD_ERROR_AUTH_FAILED,
428 "permission denied: untrusted client process");
429 return FALSE;
430 }
431 return TRUE;
432}
433#endif /* HAVE_POLKIT */
Richard Hughes5d14def2015-10-07 17:43:10 +0100434
Richard Hughesdf7950b2016-01-31 10:18:40 +0000435static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100436fu_main_authorize_unlock_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100437{
Richard Hughes9945edb2017-06-19 10:03:55 +0100438 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
439 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500440#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100441 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100442
Richard Hughes9945edb2017-06-19 10:03:55 +0100443 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100444 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100445 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
446 res, &error);
447 if (!fu_main_authorization_is_valid (auth, &error)) {
448 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100449 return;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100450 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500451#else
452 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
453 g_dbus_method_invocation_return_gerror (helper->invocation, error);
454 return;
455 }
456#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +0100457
458 /* authenticated */
459 if (!fu_engine_unlock (helper->priv->engine, helper->device_id, &error)) {
460 g_dbus_method_invocation_return_gerror (helper->invocation, error);
461 return;
462 }
463
464 /* success */
465 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100466}
467
468static void
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000469fu_main_authorize_set_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
470{
471 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
472 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500473#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000474 g_autoptr(PolkitAuthorizationResult) auth = NULL;
475
476 /* get result */
477 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
478 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
479 res, &error);
480 if (!fu_main_authorization_is_valid (auth, &error)) {
481 g_dbus_method_invocation_return_gerror (helper->invocation, error);
482 return;
483 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500484#else
485 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
486 g_dbus_method_invocation_return_gerror (helper->invocation, error);
487 return;
488 }
489#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000490
491 /* success */
492 for (guint i = 0; i < helper->checksums->len; i++) {
493 const gchar *csum = g_ptr_array_index (helper->checksums, i);
494 fu_engine_add_approved_firmware (helper->priv->engine, csum);
495 }
496 g_dbus_method_invocation_return_value (helper->invocation, NULL);
497}
498
499static void
Richard Hughes31206832020-07-27 15:31:11 +0100500fu_main_authorize_set_blocked_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
501{
502 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
503 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500504#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +0100505 g_autoptr(PolkitAuthorizationResult) auth = NULL;
506
507 /* get result */
508 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
509 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
510 res, &error);
511 if (!fu_main_authorization_is_valid (auth, &error)) {
512 g_dbus_method_invocation_return_gerror (helper->invocation, error);
513 return;
514 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500515#else
516 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
517 g_dbus_method_invocation_return_gerror (helper->invocation, error);
518 return;
519 }
520#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +0100521
522 /* success */
523 if (!fu_engine_set_blocked_firmware (helper->priv->engine, helper->checksums, &error)) {
524 g_dbus_method_invocation_return_gerror (helper->invocation, error);
525 return;
526 }
527 g_dbus_method_invocation_return_value (helper->invocation, NULL);
528}
529
530static void
Richard Hughes3d607622019-03-07 16:59:27 +0000531fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
532{
533 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
534 g_autofree gchar *sig = NULL;
535 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500536#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +0000537 g_autoptr(PolkitAuthorizationResult) auth = NULL;
538
539 /* get result */
540 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
541 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
542 res, &error);
543 if (!fu_main_authorization_is_valid (auth, &error)) {
544 g_dbus_method_invocation_return_gerror (helper->invocation, error);
545 return;
546 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500547#else
548 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
549 g_dbus_method_invocation_return_gerror (helper->invocation, error);
550 return;
551 }
552#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +0000553
554 /* authenticated */
555 sig = fu_engine_self_sign (helper->priv->engine, helper->value, helper->flags, &error);
556 if (sig == NULL) {
557 g_dbus_method_invocation_return_gerror (helper->invocation, error);
558 return;
559 }
560
561 /* success */
562 g_dbus_method_invocation_return_value (helper->invocation, g_variant_new ("(s)", sig));
563}
564
565static void
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100566fu_main_modify_config_cb (GObject *source, GAsyncResult *res, gpointer user_data)
567{
568 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
569 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500570#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100571 g_autoptr(PolkitAuthorizationResult) auth = NULL;
572
573 /* get result */
574 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
575 res, &error);
576 if (!fu_main_authorization_is_valid (auth, &error)) {
577 g_dbus_method_invocation_return_gerror (helper->invocation, error);
578 return;
579 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500580#else
581 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
582 g_dbus_method_invocation_return_gerror (helper->invocation, error);
583 return;
584 }
585#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100586
587 if (!fu_engine_modify_config (helper->priv->engine, helper->key, helper->value, &error)) {
588 g_dbus_method_invocation_return_gerror (helper->invocation, error);
589 return;
590 }
591
592 /* success */
593 g_dbus_method_invocation_return_value (helper->invocation, NULL);
594}
595
596static void
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600597fu_main_authorize_activate_cb (GObject *source, GAsyncResult *res, gpointer user_data)
598{
599 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
600 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500601#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600602 g_autoptr(PolkitAuthorizationResult) auth = NULL;
603
604 /* get result */
605 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
606 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
607 res, &error);
608 if (!fu_main_authorization_is_valid (auth, &error)) {
609 g_dbus_method_invocation_return_gerror (helper->invocation, error);
610 return;
611 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500612#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600613
614 /* authenticated */
615 if (!fu_engine_activate (helper->priv->engine, helper->device_id, &error)) {
616 g_dbus_method_invocation_return_gerror (helper->invocation, error);
617 return;
618 }
619
620 /* success */
621 g_dbus_method_invocation_return_value (helper->invocation, NULL);
622}
623
624static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100625fu_main_authorize_verify_update_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughesdf7950b2016-01-31 10:18:40 +0000626{
Richard Hughes9945edb2017-06-19 10:03:55 +0100627 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
628 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500629#ifdef HAVE_POLKIT
Richard Hughes9945edb2017-06-19 10:03:55 +0100630 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughesdf7950b2016-01-31 10:18:40 +0000631
Richard Hughes9945edb2017-06-19 10:03:55 +0100632 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100633 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100634 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
635 res, &error);
636 if (!fu_main_authorization_is_valid (auth, &error)) {
637 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughesdf7950b2016-01-31 10:18:40 +0000638 return;
Richard Hughesf192bf02016-07-22 08:26:43 +0100639 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500640#else
641 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
642 g_dbus_method_invocation_return_gerror (helper->invocation, error);
643 return;
644 }
645#endif /* HAVE_POLKIT */
Richard Hughesdf7950b2016-01-31 10:18:40 +0000646
Richard Hughes9945edb2017-06-19 10:03:55 +0100647 /* authenticated */
648 if (!fu_engine_verify_update (helper->priv->engine, helper->device_id, &error)) {
649 g_dbus_method_invocation_return_gerror (helper->invocation, error);
650 return;
Richard Hughes404cc512016-12-21 16:09:48 +0000651 }
652
653 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100654 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes99147f12016-05-17 09:35:04 +0100655}
656
Richard Hughes9945edb2017-06-19 10:03:55 +0100657static void
Richard Hughesa6bd5582017-09-07 14:32:22 +0100658fu_main_authorize_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
659{
660 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
661 g_autoptr(GError) error = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -0500662#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100663 g_autoptr(PolkitAuthorizationResult) auth = NULL;
664
665 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100666 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100667 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
668 res, &error);
669 if (!fu_main_authorization_is_valid (auth, &error)) {
670 g_dbus_method_invocation_return_gerror (helper->invocation, error);
671 return;
672 }
Mario Limonciello11b71f42020-10-13 13:39:14 -0500673#else
674 if (!fu_main_authorization_is_trusted (helper->request, &error)) {
675 g_dbus_method_invocation_return_gerror (helper->invocation, error);
676 return;
677 }
678#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +0100679
680 /* authenticated */
681 if (!fu_engine_modify_remote (helper->priv->engine,
682 helper->remote_id,
683 helper->key,
684 helper->value,
685 &error)) {
686 g_dbus_method_invocation_return_gerror (helper->invocation, error);
687 return;
688 }
689
690 /* success */
691 g_dbus_method_invocation_return_value (helper->invocation, NULL);
692}
693
Richard Hughes4ad41f02018-05-08 14:35:36 +0100694static void fu_main_authorize_install_queue (FuMainAuthHelper *helper);
695
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500696#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +0100697static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100698fu_main_authorize_install_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes404cc512016-12-21 16:09:48 +0000699{
Richard Hughes9945edb2017-06-19 10:03:55 +0100700 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
Richard Hughes46832432015-09-11 13:43:15 +0100701 g_autoptr(GError) error = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +0100702 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes18423292015-03-09 17:10:50 +0000703
Richard Hughes9945edb2017-06-19 10:03:55 +0100704 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100705 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100706 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
707 res, &error);
708 if (!fu_main_authorization_is_valid (auth, &error)) {
709 g_dbus_method_invocation_return_gerror (helper->invocation, error);
710 return;
Richard Hughes0e883ee2015-03-18 17:22:33 +0000711 }
712
Richard Hughes4ad41f02018-05-08 14:35:36 +0100713 /* do the next authentication action ID */
714 fu_main_authorize_install_queue (g_steal_pointer (&helper));
715}
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500716#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100717
718static void
719fu_main_authorize_install_queue (FuMainAuthHelper *helper_ref)
720{
721 FuMainPrivate *priv = helper_ref->priv;
722 g_autoptr(FuMainAuthHelper) helper = helper_ref;
723 g_autoptr(GError) error = NULL;
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500724 gboolean ret;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100725
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500726#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +0100727 /* still more things to to authenticate */
728 if (helper->action_ids->len > 0) {
729 g_autofree gchar *action_id = g_strdup (g_ptr_array_index (helper->action_ids, 0));
730 g_autoptr(PolkitSubject) subject = g_object_ref (helper->subject);
731 g_ptr_array_remove_index (helper->action_ids, 0);
732 polkit_authority_check_authorization (priv->authority, subject,
733 action_id, NULL,
734 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
735 NULL,
736 fu_main_authorize_install_cb,
737 g_steal_pointer (&helper));
Richard Hughes9945edb2017-06-19 10:03:55 +0100738 return;
Richard Hughes654f6b82016-04-25 12:29:48 +0100739 }
Mario Limonciello6fc11ec2020-10-26 08:56:28 -0500740#endif /* HAVE_POLKIT */
Richard Hughes654f6b82016-04-25 12:29:48 +0100741
Richard Hughes4ad41f02018-05-08 14:35:36 +0100742 /* all authenticated, so install all the things */
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500743 priv->update_in_progress = TRUE;
744 ret = fu_engine_install_tasks (helper->priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100745 helper->request,
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500746 helper->install_tasks,
747 helper->blob_cab,
748 helper->flags,
749 &error);
750 priv->update_in_progress = FALSE;
751 if (priv->pending_sigterm)
752 g_main_loop_quit (priv->loop);
753 if (!ret) {
Richard Hughesdbd8c762018-06-15 20:31:40 +0100754 g_dbus_method_invocation_return_gerror (helper->invocation, error);
755 return;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100756 }
757
Richard Hughes654f6b82016-04-25 12:29:48 +0100758 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100759 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes4c369702017-06-16 15:31:38 +0100760}
761
Richard Hughes4ad41f02018-05-08 14:35:36 +0100762#if !GLIB_CHECK_VERSION(2,54,0)
763static gboolean
764g_ptr_array_find (GPtrArray *haystack, gconstpointer needle, guint *index_)
765{
766 for (guint i = 0; i < haystack->len; i++) {
767 gconstpointer *tmp = g_ptr_array_index (haystack, i);
768 if (tmp == needle) {
769 if (index_ != NULL) {
770 *index_ = i;
771 return TRUE;
772 }
773 }
774 }
775 return FALSE;
776}
777#endif
778
Richard Hughes9f86ade2018-05-10 21:11:22 +0100779static gint
780fu_main_install_task_sort_cb (gconstpointer a, gconstpointer b)
781{
782 FuInstallTask *task_a = *((FuInstallTask **) a);
783 FuInstallTask *task_b = *((FuInstallTask **) b);
Richard Hughesc02cb832018-05-20 10:31:04 +0100784 return fu_install_task_compare (task_a, task_b);
Richard Hughes9f86ade2018-05-10 21:11:22 +0100785}
786
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500787static GPtrArray *
788fu_main_get_device_family (FuMainAuthHelper *helper, GError **error)
789{
790 FuDevice *parent;
791 GPtrArray *children;
792 g_autoptr(FuDevice) device = NULL;
793 g_autoptr(GPtrArray) devices_possible = NULL;
794
795 /* get the device */
796 device = fu_engine_get_device (helper->priv->engine, helper->device_id, error);
797 if (device == NULL)
798 return NULL;
799
800 /* device itself */
801 devices_possible = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
802 g_ptr_array_add (devices_possible, g_object_ref (device));
803
804 /* add device children */
805 children = fu_device_get_children (device);
806 for (guint i = 0; i < children->len; i++) {
807 FuDevice *child = g_ptr_array_index (children, i);
808 g_ptr_array_add (devices_possible, g_object_ref (child));
809 }
810
811 /* add parent and siblings, not including the device itself */
812 parent = fu_device_get_parent (device);
813 if (parent != NULL) {
814 GPtrArray *siblings = fu_device_get_children (parent);
815 g_ptr_array_add (devices_possible, g_object_ref (parent));
816 for (guint i = 0; i < siblings->len; i++) {
817 FuDevice *sibling = g_ptr_array_index (siblings, i);
818 if (sibling == device)
819 continue;
820 g_ptr_array_add (devices_possible, g_object_ref (sibling));
821 }
822 }
823
824 /* success */
825 return g_steal_pointer (&devices_possible);
826}
827
Richard Hughes4ad41f02018-05-08 14:35:36 +0100828static gboolean
829fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
830{
831 FuMainPrivate *priv = helper_ref->priv;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100832 g_autoptr(FuMainAuthHelper) helper = helper_ref;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100833 g_autoptr(GPtrArray) components = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100834 g_autoptr(GPtrArray) devices_possible = NULL;
835 g_autoptr(GPtrArray) errors = NULL;
836
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500837 /* get a list of devices that in some way match the device_id */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100838 if (g_strcmp0 (helper->device_id, FWUPD_DEVICE_ID_ANY) == 0) {
839 devices_possible = fu_engine_get_devices (priv->engine, error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500840 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100841 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100842 } else {
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500843 devices_possible = fu_main_get_device_family (helper, error);
844 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100845 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100846 }
847
Richard Hughes481aa2a2018-09-18 20:51:46 +0100848 /* parse silo */
849 helper->silo = fu_engine_get_silo_from_blob (priv->engine,
850 helper->blob_cab,
851 error);
852 if (helper->silo == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100853 return FALSE;
854
Richard Hughes481aa2a2018-09-18 20:51:46 +0100855 /* for each component in the silo */
Richard Hughes4cbe99c2020-11-22 13:14:33 +0000856 components = xb_silo_query (helper->silo,
857 "components/component[@type='firmware']",
858 0, error);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100859 if (components == NULL)
860 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100861 helper->action_ids = g_ptr_array_new_with_free_func (g_free);
862 helper->install_tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
863 errors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_error_free);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100864 for (guint i = 0; i < components->len; i++) {
865 XbNode *component = g_ptr_array_index (components, i);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100866
867 /* do any devices pass the requirements */
868 for (guint j = 0; j < devices_possible->len; j++) {
869 FuDevice *device = g_ptr_array_index (devices_possible, j);
870 const gchar *action_id;
871 g_autoptr(FuInstallTask) task = NULL;
872 g_autoptr(GError) error_local = NULL;
873
874 /* is this component valid for the device */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100875 task = fu_install_task_new (device, component);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100876 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100877 helper->request,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100878 task,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500879 helper->flags | FWUPD_INSTALL_FLAG_FORCE,
880 &error_local)) {
Richard Hughes33dcfb72020-09-28 15:58:39 +0100881 if (!g_error_matches (error_local,
882 FWUPD_ERROR,
883 FWUPD_ERROR_NOT_FOUND)) {
884 g_debug ("first pass requirement on %s:%s failed: %s",
885 fu_device_get_id (device),
886 xb_node_query_text (component, "id", NULL),
887 error_local->message);
888 }
Mario Limonciello537da0e2020-03-09 15:38:17 -0500889 g_ptr_array_add (errors, g_steal_pointer (&error_local));
890 continue;
891 }
892
893 /* make a second pass using possibly updated version format now */
894 fu_engine_md_refresh_device_from_component (priv->engine, device, component);
895 if (!fu_engine_check_requirements (priv->engine,
Richard Hughesdf89cd52020-06-26 20:25:18 +0100896 helper->request,
Mario Limonciello537da0e2020-03-09 15:38:17 -0500897 task,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100898 helper->flags,
Richard Hughes4ad41f02018-05-08 14:35:36 +0100899 &error_local)) {
Mario Limonciello537da0e2020-03-09 15:38:17 -0500900 g_debug ("second pass requirement on %s:%s failed: %s",
Richard Hughes4ad41f02018-05-08 14:35:36 +0100901 fu_device_get_id (device),
Richard Hughes481aa2a2018-09-18 20:51:46 +0100902 xb_node_query_text (component, "id", NULL),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100903 error_local->message);
904 g_ptr_array_add (errors, g_steal_pointer (&error_local));
905 continue;
906 }
Mario Limonciello381c27c2020-10-23 16:32:26 -0500907 if (!fu_engine_check_trust (task, &error_local)) {
908 g_ptr_array_add (errors, g_steal_pointer (&error_local));
909 continue;
910 }
Richard Hughes4ad41f02018-05-08 14:35:36 +0100911
Mario Limonciello7a3df4b2019-01-31 10:27:22 -0600912 /* if component should have an update message from CAB */
913 fu_device_incorporate_from_component (device, component);
914
Richard Hughes4ad41f02018-05-08 14:35:36 +0100915 /* get the action IDs for the valid device */
916 action_id = fu_install_task_get_action_id (task);
917 if (!g_ptr_array_find (helper->action_ids, action_id, NULL))
918 g_ptr_array_add (helper->action_ids, g_strdup (action_id));
919 g_ptr_array_add (helper->install_tasks, g_steal_pointer (&task));
920 }
921 }
922
Richard Hughes9f86ade2018-05-10 21:11:22 +0100923 /* order the install tasks by the device priority */
924 g_ptr_array_sort (helper->install_tasks, fu_main_install_task_sort_cb);
925
Richard Hughes4ad41f02018-05-08 14:35:36 +0100926 /* nothing suitable */
927 if (helper->install_tasks->len == 0) {
Richard Hughese82eef32018-05-20 10:41:26 +0100928 GError *error_tmp = fu_common_error_array_get_best (errors);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100929 g_propagate_error (error, error_tmp);
930 return FALSE;
931 }
932
933 /* authenticate all things in the action_ids */
934 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
935 fu_main_authorize_install_queue (g_steal_pointer (&helper));
936 return TRUE;
937}
938
Richard Hughesb6f79552017-11-11 07:58:17 +0000939static gboolean
940fu_main_device_id_valid (const gchar *device_id, GError **error)
941{
942 if (g_strcmp0 (device_id, FWUPD_DEVICE_ID_ANY) == 0)
943 return TRUE;
944 if (device_id != NULL && strlen (device_id) >= 4)
945 return TRUE;
946 g_set_error (error,
947 FWUPD_ERROR,
948 FWUPD_ERROR_INTERNAL,
949 "invalid device ID: %s",
950 device_id);
951 return FALSE;
952}
953
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000954static void
955fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
956 const gchar *object_path, const gchar *interface_name,
957 const gchar *method_name, GVariant *parameters,
958 GDBusMethodInvocation *invocation, gpointer user_data)
959{
960 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughes9945edb2017-06-19 10:03:55 +0100961 GVariant *val = NULL;
Richard Hughesdf89cd52020-06-26 20:25:18 +0100962 g_autoptr(FuEngineRequest) request = NULL;
Richard Hughes060af612016-08-17 17:32:34 +0100963 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000964
Richard Hughesdf89cd52020-06-26 20:25:18 +0100965 /* build request */
966 request = fu_main_create_request (priv, sender, &error);
967 if (request == NULL) {
968 g_dbus_method_invocation_return_gerror (invocation, error);
969 return;
970 }
971
Richard Hughes75b965d2018-11-15 13:51:21 +0000972 /* activity */
973 fu_engine_idle_reset (priv->engine);
974
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000975 if (g_strcmp0 (method_name, "GetDevices") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100976 g_autoptr(GPtrArray) devices = NULL;
Richard Hughesf508e762015-02-27 12:49:36 +0000977 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100978 devices = fu_engine_get_devices (priv->engine, &error);
979 if (devices == NULL) {
980 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100981 return;
982 }
Richard Hughesdf89cd52020-06-26 20:25:18 +0100983 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500984 if (val == NULL) {
985 g_dbus_method_invocation_return_gerror (invocation, error);
986 return;
987 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100988 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100989 return;
990 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100991 if (g_strcmp0 (method_name, "GetPlugins") == 0) {
992 g_debug ("Called %s()", method_name);
993 val = fu_main_plugin_array_to_variant (fu_engine_get_plugins (priv->engine));
994 g_dbus_method_invocation_return_value (invocation, val);
995 return;
996 }
Richard Hughese4a100c2017-06-04 21:23:50 +0100997 if (g_strcmp0 (method_name, "GetReleases") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100998 const gchar *device_id;
Richard Hughese4a100c2017-06-04 21:23:50 +0100999 g_autoptr(GPtrArray) releases = NULL;
Richard Hughese4a100c2017-06-04 21:23:50 +01001000 g_variant_get (parameters, "(&s)", &device_id);
1001 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001002 if (!fu_main_device_id_valid (device_id, &error)) {
1003 g_dbus_method_invocation_return_gerror (invocation, error);
1004 return;
1005 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001006 releases = fu_engine_get_releases (priv->engine, request, device_id, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001007 if (releases == NULL) {
1008 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughese4a100c2017-06-04 21:23:50 +01001009 return;
1010 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001011 val = fu_main_release_array_to_variant (releases);
1012 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughese4a100c2017-06-04 21:23:50 +01001013 return;
1014 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001015 if (g_strcmp0 (method_name, "GetApprovedFirmware") == 0) {
1016 GVariantBuilder builder;
1017 GPtrArray *checksums = fu_engine_get_approved_firmware (priv->engine);
1018 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1019 for (guint i = 0; i < checksums->len; i++) {
1020 const gchar *checksum = g_ptr_array_index (checksums, i);
1021 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1022 }
1023 val = g_variant_builder_end (&builder);
1024 g_dbus_method_invocation_return_value (invocation,
1025 g_variant_new_tuple (&val, 1));
1026 return;
1027 }
Richard Hughes31206832020-07-27 15:31:11 +01001028 if (g_strcmp0 (method_name, "GetBlockedFirmware") == 0) {
1029 GVariantBuilder builder;
1030 GPtrArray *checksums = fu_engine_get_blocked_firmware (priv->engine);
1031 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
1032 for (guint i = 0; i < checksums->len; i++) {
1033 const gchar *checksum = g_ptr_array_index (checksums, i);
1034 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
1035 }
1036 val = g_variant_builder_end (&builder);
1037 g_dbus_method_invocation_return_value (invocation,
1038 g_variant_new_tuple (&val, 1));
1039 return;
1040 }
Richard Hughes6ecc4ca2020-05-20 18:42:46 +01001041 if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
1042 GHashTableIter iter;
1043 GVariantBuilder builder;
1044 const gchar *key;
1045 const gchar *value;
1046 g_autoptr(GHashTable) metadata = NULL;
1047
1048 metadata = fu_engine_get_report_metadata (priv->engine, &error);
1049 if (metadata == NULL) {
1050 g_dbus_method_invocation_return_gerror (invocation, error);
1051 return;
1052 }
1053 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
1054 g_hash_table_iter_init (&iter, metadata);
1055 while (g_hash_table_iter_next (&iter,
1056 (gpointer *) &key,
1057 (gpointer *) &value)) {
1058 g_variant_builder_add_value (&builder,
1059 g_variant_new ("{ss}", key, value));
1060 }
1061 val = g_variant_builder_end (&builder);
1062 g_dbus_method_invocation_return_value (invocation,
1063 g_variant_new_tuple (&val, 1));
1064 return;
1065 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001066 if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
1067 g_autofree gchar *checksums_str = NULL;
1068 g_auto(GStrv) checksums = NULL;
1069 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001070#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001071 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001072#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001073
1074 g_variant_get (parameters, "(^as)", &checksums);
1075 checksums_str = g_strjoinv (",", checksums);
1076 g_debug ("Called %s(%s)", method_name, checksums_str);
1077
1078 /* authenticate */
1079 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1080 helper = g_new0 (FuMainAuthHelper, 1);
1081 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001082 helper->request = g_steal_pointer (&request);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001083 helper->invocation = g_object_ref (invocation);
1084 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1085 for (guint i = 0; checksums[i] != NULL; i++)
1086 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001087#ifdef HAVE_POLKIT
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001088 subject = polkit_system_bus_name_new (sender);
1089 polkit_authority_check_authorization (priv->authority, subject,
1090 "org.freedesktop.fwupd.set-approved-firmware",
1091 NULL,
1092 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1093 NULL,
1094 fu_main_authorize_set_approved_firmware_cb,
1095 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001096#else
1097 fu_main_authorize_set_approved_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1098#endif /* HAVE_POLKIT */
Richard Hughes8dd4c1c2019-03-03 18:27:57 +00001099 return;
1100 }
Richard Hughes31206832020-07-27 15:31:11 +01001101 if (g_strcmp0 (method_name, "SetBlockedFirmware") == 0) {
1102 g_autofree gchar *checksums_str = NULL;
1103 g_auto(GStrv) checksums = NULL;
1104 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001105#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001106 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001107#endif
Richard Hughes31206832020-07-27 15:31:11 +01001108 g_variant_get (parameters, "(^as)", &checksums);
1109 checksums_str = g_strjoinv (",", checksums);
1110 g_debug ("Called %s(%s)", method_name, checksums_str);
1111
1112 /* authenticate */
1113 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1114 helper = g_new0 (FuMainAuthHelper, 1);
1115 helper->priv = priv;
1116 helper->request = g_steal_pointer (&request);
1117 helper->invocation = g_object_ref (invocation);
1118 helper->checksums = g_ptr_array_new_with_free_func (g_free);
1119 for (guint i = 0; checksums[i] != NULL; i++)
1120 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001121#ifdef HAVE_POLKIT
Richard Hughes31206832020-07-27 15:31:11 +01001122 subject = polkit_system_bus_name_new (sender);
1123 polkit_authority_check_authorization (priv->authority, subject,
1124 "org.freedesktop.fwupd.set-approved-firmware",
1125 NULL,
1126 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1127 NULL,
1128 fu_main_authorize_set_blocked_firmware_cb,
1129 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001130#else
1131 fu_main_authorize_set_blocked_firmware_cb (NULL, NULL, g_steal_pointer (&helper));
1132#endif /* HAVE_POLKIT */
Richard Hughes31206832020-07-27 15:31:11 +01001133 return;
1134 }
Richard Hughes3d607622019-03-07 16:59:27 +00001135 if (g_strcmp0 (method_name, "SelfSign") == 0) {
1136 GVariant *prop_value;
1137 gchar *prop_key;
1138 g_autofree gchar *value = NULL;
1139 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001140#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001141 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001142#endif
Richard Hughes3d607622019-03-07 16:59:27 +00001143 g_autoptr(GVariantIter) iter = NULL;
1144
1145 g_variant_get (parameters, "(sa{sv})", &value, &iter);
1146 g_debug ("Called %s(%s)", method_name, value);
1147
1148 /* get flags */
1149 helper = g_new0 (FuMainAuthHelper, 1);
1150 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
1151 g_debug ("got option %s", prop_key);
1152 if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
1153 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001154 helper->flags |= JCAT_SIGN_FLAG_ADD_TIMESTAMP;
Richard Hughes3d607622019-03-07 16:59:27 +00001155 if (g_strcmp0 (prop_key, "add-cert") == 0 &&
1156 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughesd5aab652020-02-25 12:47:50 +00001157 helper->flags |= JCAT_SIGN_FLAG_ADD_CERT;
Richard Hughes3d607622019-03-07 16:59:27 +00001158 g_variant_unref (prop_value);
1159 }
1160
1161 /* authenticate */
1162 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1163 helper->priv = priv;
1164 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001165 helper->request = g_steal_pointer (&request);
Richard Hughes3d607622019-03-07 16:59:27 +00001166 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001167#ifdef HAVE_POLKIT
Richard Hughes3d607622019-03-07 16:59:27 +00001168 subject = polkit_system_bus_name_new (sender);
1169 polkit_authority_check_authorization (priv->authority, subject,
1170 "org.freedesktop.fwupd.self-sign",
1171 NULL,
1172 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1173 NULL,
1174 fu_main_authorize_self_sign_cb,
1175 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001176#else
1177 fu_main_authorize_self_sign_cb (NULL, NULL, g_steal_pointer (&helper));
1178#endif /* HAVE_POLKIT */
Richard Hughes3d607622019-03-07 16:59:27 +00001179 return;
1180 }
Richard Hughes97284b12017-09-13 17:07:58 +01001181 if (g_strcmp0 (method_name, "GetDowngrades") == 0) {
1182 const gchar *device_id;
1183 g_autoptr(GPtrArray) releases = NULL;
1184 g_variant_get (parameters, "(&s)", &device_id);
1185 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001186 if (!fu_main_device_id_valid (device_id, &error)) {
1187 g_dbus_method_invocation_return_gerror (invocation, error);
1188 return;
1189 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001190 releases = fu_engine_get_downgrades (priv->engine, request, device_id, &error);
Richard Hughes97284b12017-09-13 17:07:58 +01001191 if (releases == NULL) {
1192 g_dbus_method_invocation_return_gerror (invocation, error);
1193 return;
1194 }
1195 val = fu_main_release_array_to_variant (releases);
1196 g_dbus_method_invocation_return_value (invocation, val);
1197 return;
1198 }
Richard Hughesa96413a2017-09-13 17:19:59 +01001199 if (g_strcmp0 (method_name, "GetUpgrades") == 0) {
1200 const gchar *device_id;
1201 g_autoptr(GPtrArray) releases = NULL;
1202 g_variant_get (parameters, "(&s)", &device_id);
1203 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001204 if (!fu_main_device_id_valid (device_id, &error)) {
1205 g_dbus_method_invocation_return_gerror (invocation, error);
1206 return;
1207 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001208 releases = fu_engine_get_upgrades (priv->engine, request, device_id, &error);
Richard Hughesa96413a2017-09-13 17:19:59 +01001209 if (releases == NULL) {
1210 g_dbus_method_invocation_return_gerror (invocation, error);
1211 return;
1212 }
1213 val = fu_main_release_array_to_variant (releases);
1214 g_dbus_method_invocation_return_value (invocation, val);
1215 return;
1216 }
Richard Hughes4c369702017-06-16 15:31:38 +01001217 if (g_strcmp0 (method_name, "GetRemotes") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001218 g_autoptr(GPtrArray) remotes = NULL;
Richard Hughes4c369702017-06-16 15:31:38 +01001219 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001220 remotes = fu_engine_get_remotes (priv->engine, &error);
1221 if (remotes == NULL) {
1222 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes4c369702017-06-16 15:31:38 +01001223 return;
1224 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001225 val = fu_main_remote_array_to_variant (remotes);
1226 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes4c369702017-06-16 15:31:38 +01001227 return;
1228 }
Richard Hughes476363a2018-01-11 10:08:58 +00001229 if (g_strcmp0 (method_name, "GetHistory") == 0) {
1230 g_autoptr(GPtrArray) devices = NULL;
1231 g_debug ("Called %s()", method_name);
1232 devices = fu_engine_get_history (priv->engine, &error);
1233 if (devices == NULL) {
1234 g_dbus_method_invocation_return_gerror (invocation, error);
1235 return;
1236 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001237 val = fu_main_device_array_to_variant (priv, request, devices, &error);
Mario Limoncielloe3016602018-09-06 11:20:59 -05001238 if (val == NULL) {
1239 g_dbus_method_invocation_return_gerror (invocation, error);
1240 return;
1241 }
Richard Hughes476363a2018-01-11 10:08:58 +00001242 g_dbus_method_invocation_return_value (invocation, val);
1243 return;
1244 }
Richard Hughes196c6c62020-05-11 19:42:47 +01001245 if (g_strcmp0 (method_name, "GetHostSecurityAttrs") == 0) {
Richard Hughesf58ac732020-05-12 15:23:44 +01001246 g_autoptr(FuSecurityAttrs) attrs = NULL;
Richard Hughes196c6c62020-05-11 19:42:47 +01001247 g_debug ("Called %s()", method_name);
Richard Hughesa018b3c2020-08-28 17:08:19 +01001248 if (priv->machine_kind != FU_MAIN_MACHINE_KIND_PHYSICAL) {
1249 g_dbus_method_invocation_return_error_literal (invocation,
1250 FWUPD_ERROR,
1251 FWUPD_ERROR_NOT_SUPPORTED,
1252 "HSI unavailable for hypervisor");
1253 return;
1254 }
Richard Hughes56e7ae52020-05-17 21:00:23 +01001255 attrs = fu_engine_get_host_security_attrs (priv->engine);
Richard Hughesf58ac732020-05-12 15:23:44 +01001256 val = fu_security_attrs_to_variant (attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001257 g_dbus_method_invocation_return_value (invocation, val);
1258 return;
1259 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001260 if (g_strcmp0 (method_name, "ClearResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001261 const gchar *device_id;
1262 g_variant_get (parameters, "(&s)", &device_id);
1263 g_debug ("Called %s(%s)", method_name, device_id);
1264 if (!fu_engine_clear_results (priv->engine, device_id, &error)) {
1265 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001266 return;
1267 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001268 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001269 return;
1270 }
Richard Hughes6b222952018-01-11 10:20:48 +00001271 if (g_strcmp0 (method_name, "ModifyDevice") == 0) {
1272 const gchar *device_id;
1273 const gchar *key = NULL;
1274 const gchar *value = NULL;
1275
1276 /* check the id exists */
1277 g_variant_get (parameters, "(&s&s&s)", &device_id, &key, &value);
1278 g_debug ("Called %s(%s,%s=%s)", method_name, device_id, key, value);
1279 if (!fu_engine_modify_device (priv->engine, device_id, key, value, &error)) {
1280 g_dbus_method_invocation_return_gerror (invocation, error);
1281 return;
1282 }
1283 g_dbus_method_invocation_return_value (invocation, NULL);
1284 return;
1285 }
Richard Hughes0e883ee2015-03-18 17:22:33 +00001286 if (g_strcmp0 (method_name, "GetResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001287 const gchar *device_id = NULL;
Richard Hughes93b15762017-09-15 11:05:23 +01001288 g_autoptr(FwupdDevice) result = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +01001289 g_variant_get (parameters, "(&s)", &device_id);
1290 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001291 if (!fu_main_device_id_valid (device_id, &error)) {
1292 g_dbus_method_invocation_return_gerror (invocation, error);
1293 return;
1294 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001295 result = fu_engine_get_results (priv->engine, device_id, &error);
1296 if (result == NULL) {
1297 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001298 return;
1299 }
Richard Hughese0bd53e2017-09-17 08:29:02 +01001300 val = fwupd_device_to_variant (result);
1301 g_dbus_method_invocation_return_value (invocation,
1302 g_variant_new_tuple (&val, 1));
Richard Hughes0e883ee2015-03-18 17:22:33 +00001303 return;
1304 }
Richard Hughesba73c762017-09-15 14:31:17 +01001305 if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
Richard Hughes1b50d962017-06-02 12:23:00 +01001306 GDBusMessage *message;
1307 GUnixFDList *fd_list;
Richard Hughes9945edb2017-06-19 10:03:55 +01001308 const gchar *remote_id = NULL;
Richard Hughes1b50d962017-06-02 12:23:00 +01001309 gint fd_data;
1310 gint fd_sig;
1311
Richard Hughes9945edb2017-06-19 10:03:55 +01001312 g_variant_get (parameters, "(&shh)", &remote_id, &fd_data, &fd_sig);
1313 g_debug ("Called %s(%s,%i,%i)", method_name, remote_id, fd_data, fd_sig);
Richard Hughes1b50d962017-06-02 12:23:00 +01001314
Richard Hughes5935ebd2017-06-16 15:40:31 +01001315 /* update the metadata store */
Richard Hughes1b50d962017-06-02 12:23:00 +01001316 message = g_dbus_method_invocation_get_message (invocation);
1317 fd_list = g_dbus_message_get_unix_fd_list (message);
1318 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
1319 g_set_error (&error,
1320 FWUPD_ERROR,
1321 FWUPD_ERROR_INTERNAL,
1322 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001323 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001324 return;
1325 }
1326 fd_data = g_unix_fd_list_get (fd_list, 0, &error);
1327 if (fd_data < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001328 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001329 return;
1330 }
1331 fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
1332 if (fd_sig < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001333 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001334 return;
1335 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001336
1337 /* store new metadata (will close the fds when done) */
1338 if (!fu_engine_update_metadata (priv->engine, remote_id,
1339 fd_data, fd_sig, &error)) {
Richard Hughesf3d46c62017-11-28 14:01:30 +00001340 g_prefix_error (&error, "Failed to update metadata for %s: ", remote_id);
Richard Hughes9945edb2017-06-19 10:03:55 +01001341 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001342 return;
1343 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001344 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001345 return;
1346 }
Richard Hughes9a410ce2016-02-28 15:58:54 +00001347 if (g_strcmp0 (method_name, "Unlock") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001348 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001349 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001350#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001351 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001352#endif /* HAVE_POLKIT */
Richard Hughes9945edb2017-06-19 10:03:55 +01001353 g_variant_get (parameters, "(&s)", &device_id);
1354 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001355 if (!fu_main_device_id_valid (device_id, &error)) {
1356 g_dbus_method_invocation_return_gerror (invocation, error);
1357 return;
1358 }
Richard Hughesfe5cc902016-06-29 10:00:00 +01001359
Richard Hughes9a410ce2016-02-28 15:58:54 +00001360 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001361 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes9945edb2017-06-19 10:03:55 +01001362 helper = g_new0 (FuMainAuthHelper, 1);
1363 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001364 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001365 helper->invocation = g_object_ref (invocation);
1366 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001367#ifdef HAVE_POLKIT
Richard Hughes9a410ce2016-02-28 15:58:54 +00001368 subject = polkit_system_bus_name_new (sender);
Richard Hughes9945edb2017-06-19 10:03:55 +01001369 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes9a410ce2016-02-28 15:58:54 +00001370 "org.freedesktop.fwupd.device-unlock",
1371 NULL,
1372 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1373 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001374 fu_main_authorize_unlock_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001375 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001376#else
1377 fu_main_authorize_unlock_cb (NULL, NULL, g_steal_pointer (&helper));
1378#endif /* HAVE_POLKIT */
Richard Hughes9a410ce2016-02-28 15:58:54 +00001379 return;
1380 }
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001381 if (g_strcmp0 (method_name, "Activate") == 0) {
1382 const gchar *device_id = NULL;
1383 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001384#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001385 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001386#endif
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001387 g_variant_get (parameters, "(&s)", &device_id);
1388 g_debug ("Called %s(%s)", method_name, device_id);
1389 if (!fu_main_device_id_valid (device_id, &error)) {
1390 g_dbus_method_invocation_return_gerror (invocation, error);
1391 return;
1392 }
1393
1394 /* authenticate */
1395 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1396 helper = g_new0 (FuMainAuthHelper, 1);
1397 helper->priv = priv;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001398 helper->request = g_steal_pointer (&request);
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001399 helper->invocation = g_object_ref (invocation);
1400 helper->device_id = g_strdup (device_id);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001401#ifdef HAVE_POLKIT
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001402 subject = polkit_system_bus_name_new (sender);
1403 polkit_authority_check_authorization (priv->authority, subject,
1404 "org.freedesktop.fwupd.device-activate",
1405 NULL,
1406 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1407 NULL,
1408 fu_main_authorize_activate_cb,
1409 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001410#else
1411 fu_main_authorize_activate_cb (NULL, NULL, g_steal_pointer (&helper));
1412#endif /* HAVE_POLKIT */
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001413 return;
1414 }
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001415 if (g_strcmp0 (method_name, "ModifyConfig") == 0) {
1416 g_autofree gchar *key = NULL;
1417 g_autofree gchar *value = NULL;
1418 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001419#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001420 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001421#endif
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001422 g_variant_get (parameters, "(ss)", &key, &value);
1423 g_debug ("Called %s(%s=%s)", method_name, key, value);
1424
1425 /* authenticate */
1426 helper = g_new0 (FuMainAuthHelper, 1);
1427 helper->priv = priv;
1428 helper->key = g_steal_pointer (&key);
1429 helper->value = g_steal_pointer (&value);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001430 helper->request = g_steal_pointer (&request);
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001431 helper->invocation = g_object_ref (invocation);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001432#ifdef HAVE_POLKIT
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001433 subject = polkit_system_bus_name_new (sender);
1434 polkit_authority_check_authorization (priv->authority, subject,
1435 "org.freedesktop.fwupd.modify-config",
1436 NULL,
1437 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1438 NULL,
1439 fu_main_modify_config_cb,
1440 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001441#else
1442 fu_main_modify_config_cb (NULL, NULL, g_steal_pointer (&helper));
1443#endif /* HAVE_POLKIT */
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001444 return;
1445 }
Richard Hughesa6bd5582017-09-07 14:32:22 +01001446 if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
Richard Hughesa6bd5582017-09-07 14:32:22 +01001447 const gchar *remote_id = NULL;
1448 const gchar *key = NULL;
1449 const gchar *value = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001450 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001451#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001452 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001453#endif
Richard Hughesa6bd5582017-09-07 14:32:22 +01001454 /* check the id exists */
1455 g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
1456 g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
1457
1458 /* create helper object */
1459 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001460 helper->request = g_steal_pointer (&request);
Richard Hughesa6bd5582017-09-07 14:32:22 +01001461 helper->invocation = g_object_ref (invocation);
1462 helper->remote_id = g_strdup (remote_id);
1463 helper->key = g_strdup (key);
1464 helper->value = g_strdup (value);
1465 helper->priv = priv;
1466
1467 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001468 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001469#ifdef HAVE_POLKIT
Richard Hughesa6bd5582017-09-07 14:32:22 +01001470 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001471 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughesa6bd5582017-09-07 14:32:22 +01001472 "org.freedesktop.fwupd.modify-remote",
1473 NULL,
1474 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1475 NULL,
1476 fu_main_authorize_modify_remote_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001477 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001478#else
1479 fu_main_authorize_modify_remote_cb (NULL, NULL, g_steal_pointer (&helper));
1480#endif /* HAVE_POLKIT */
Richard Hughesa6bd5582017-09-07 14:32:22 +01001481 return;
1482 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001483 if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001484 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001485 g_autoptr(FuMainAuthHelper) helper = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001486#ifdef HAVE_POLKIT
Richard Hughes29c220d2016-12-14 17:09:54 +00001487 g_autoptr(PolkitSubject) subject = NULL;
Mario Limonciello11b71f42020-10-13 13:39:14 -05001488#endif
Richard Hughes29c220d2016-12-14 17:09:54 +00001489
1490 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001491 g_variant_get (parameters, "(&s)", &device_id);
1492 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001493 if (!fu_main_device_id_valid (device_id, &error)) {
1494 g_dbus_method_invocation_return_gerror (invocation, error);
1495 return;
1496 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001497
Richard Hughes9945edb2017-06-19 10:03:55 +01001498 /* create helper object */
Richard Hughes29c220d2016-12-14 17:09:54 +00001499 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001500 helper->request = g_steal_pointer (&request);
Richard Hughes29c220d2016-12-14 17:09:54 +00001501 helper->invocation = g_object_ref (invocation);
Richard Hughes9945edb2017-06-19 10:03:55 +01001502 helper->device_id = g_strdup (device_id);
Richard Hughes29c220d2016-12-14 17:09:54 +00001503 helper->priv = priv;
Richard Hughes29c220d2016-12-14 17:09:54 +00001504
1505 /* authenticate */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001506#ifdef HAVE_POLKIT
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001507 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes29c220d2016-12-14 17:09:54 +00001508 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001509 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes29c220d2016-12-14 17:09:54 +00001510 "org.freedesktop.fwupd.verify-update",
1511 NULL,
1512 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1513 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001514 fu_main_authorize_verify_update_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001515 g_steal_pointer (&helper));
Mario Limonciello11b71f42020-10-13 13:39:14 -05001516#else
1517 fu_main_authorize_verify_update_cb (NULL, NULL, g_steal_pointer (&helper));
1518#endif /* HAVE_POLKIT */
Richard Hughes29c220d2016-12-14 17:09:54 +00001519 return;
1520 }
Richard Hughesa043c2e2015-06-29 08:43:18 +01001521 if (g_strcmp0 (method_name, "Verify") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001522 const gchar *device_id = NULL;
1523 g_variant_get (parameters, "(&s)", &device_id);
1524 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001525 if (!fu_main_device_id_valid (device_id, &error)) {
1526 g_dbus_method_invocation_return_gerror (invocation, error);
1527 return;
1528 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001529 if (!fu_engine_verify (priv->engine, device_id, &error)) {
1530 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001531 return;
1532 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001533 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001534 return;
1535 }
Richard Hughesdf89cd52020-06-26 20:25:18 +01001536 if (g_strcmp0 (method_name, "SetFeatureFlags") == 0) {
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001537 FwupdFeatureFlags feature_flags;
1538 guint64 feature_flags_u64 = 0;
1539 g_variant_get (parameters, "(t)", &feature_flags_u64);
1540 g_debug ("Called %s(%" G_GUINT64_FORMAT ")", method_name, feature_flags_u64);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001541
1542 /* old flags for the same sender will be automatically destroyed */
Marcus Comstedt2bb19ea2020-11-28 09:49:22 +01001543 feature_flags = feature_flags_u64;
Richard Hughesdf89cd52020-06-26 20:25:18 +01001544 g_hash_table_insert (priv->sender_features,
1545 g_strdup (sender),
1546 g_memdup (&feature_flags, sizeof(feature_flags)));
1547 g_dbus_method_invocation_return_value (invocation, NULL);
1548 return;
1549 }
Richard Hughes63a407a2015-07-22 08:54:14 +01001550 if (g_strcmp0 (method_name, "Install") == 0) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001551 GVariant *prop_value;
Richard Hughes9945edb2017-06-19 10:03:55 +01001552 const gchar *device_id = NULL;
Richard Hughes74cc2172015-02-27 13:19:46 +00001553 gchar *prop_key;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001554 gint32 fd_handle = 0;
1555 gint fd;
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001556 guint64 archive_size_max;
Richard Hughes9945edb2017-06-19 10:03:55 +01001557 GDBusMessage *message;
1558 GUnixFDList *fd_list;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001559 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001560 g_autoptr(GVariantIter) iter = NULL;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001561
1562 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001563 g_variant_get (parameters, "(&sha{sv})", &device_id, &fd_handle, &iter);
1564 g_debug ("Called %s(%s,%i)", method_name, device_id, fd_handle);
Richard Hughesb6f79552017-11-11 07:58:17 +00001565 if (!fu_main_device_id_valid (device_id, &error)) {
1566 g_dbus_method_invocation_return_gerror (invocation, error);
1567 return;
1568 }
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001569
Richard Hughes9945edb2017-06-19 10:03:55 +01001570 /* create helper object */
1571 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001572 helper->request = g_steal_pointer (&request);
Richard Hughes9945edb2017-06-19 10:03:55 +01001573 helper->invocation = g_object_ref (invocation);
1574 helper->device_id = g_strdup (device_id);
1575 helper->priv = priv;
1576
1577 /* get flags */
1578 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001579 g_debug ("got option %s", prop_key);
1580 if (g_strcmp0 (prop_key, "offline") == 0 &&
1581 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001582 helper->flags |= FWUPD_INSTALL_FLAG_OFFLINE;
Richard Hughese7c12642015-03-04 20:28:59 +00001583 if (g_strcmp0 (prop_key, "allow-older") == 0 &&
1584 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001585 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_OLDER;
Richard Hughese7c12642015-03-04 20:28:59 +00001586 if (g_strcmp0 (prop_key, "allow-reinstall") == 0 &&
1587 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001588 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
Richard Hughes5bbf0132020-10-05 13:44:39 +01001589 if (g_strcmp0 (prop_key, "allow-branch-switch") == 0 &&
1590 g_variant_get_boolean (prop_value) == TRUE)
1591 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_BRANCH_SWITCH;
Mario Limonciello71a5b982016-05-10 15:38:53 -05001592 if (g_strcmp0 (prop_key, "force") == 0 &&
Richard Hughes6450d0d2020-10-06 16:05:24 +01001593 g_variant_get_boolean (prop_value) == TRUE) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001594 helper->flags |= FWUPD_INSTALL_FLAG_FORCE;
Richard Hughes6450d0d2020-10-06 16:05:24 +01001595 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
1596 }
1597 if (g_strcmp0 (prop_key, "ignore-power") == 0 &&
1598 g_variant_get_boolean (prop_value) == TRUE)
1599 helper->flags |= FWUPD_INSTALL_FLAG_IGNORE_POWER;
Richard Hughes76e0f942018-05-14 16:24:00 +01001600 if (g_strcmp0 (prop_key, "no-history") == 0 &&
1601 g_variant_get_boolean (prop_value) == TRUE)
1602 helper->flags |= FWUPD_INSTALL_FLAG_NO_HISTORY;
Richard Hughes1ffde6c2015-03-02 22:44:48 +00001603 g_variant_unref (prop_value);
Richard Hughes74cc2172015-02-27 13:19:46 +00001604 }
1605
Richard Hughes9945edb2017-06-19 10:03:55 +01001606
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001607 /* get the fd */
1608 message = g_dbus_method_invocation_get_message (invocation);
1609 fd_list = g_dbus_message_get_unix_fd_list (message);
1610 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001611 g_set_error (&error,
1612 FWUPD_ERROR,
1613 FWUPD_ERROR_INTERNAL,
1614 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001615 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001616 return;
1617 }
Richard Hughes7419e962016-11-22 19:48:06 +00001618 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001619 if (fd < 0) {
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 }
1623
Richard Hughes9945edb2017-06-19 10:03:55 +01001624 /* parse the cab file before authenticating so we can work out
1625 * what action ID to use, for instance, if this is trusted --
1626 * this will also close the fd when done */
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001627 archive_size_max = fu_engine_get_archive_size_max (priv->engine);
1628 helper->blob_cab = fu_common_get_contents_fd (fd, archive_size_max, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001629 if (helper->blob_cab == NULL) {
1630 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes5d14def2015-10-07 17:43:10 +01001631 return;
1632 }
Richard Hughes4ad41f02018-05-08 14:35:36 +01001633
1634 /* install all the things in the store */
Mario Limonciello11b71f42020-10-13 13:39:14 -05001635#ifdef HAVE_POLKIT
Richard Hughes4ad41f02018-05-08 14:35:36 +01001636 helper->subject = polkit_system_bus_name_new (sender);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001637#endif /* HAVE_POLKIT */
Richard Hughes4ad41f02018-05-08 14:35:36 +01001638 if (!fu_main_install_with_helper (g_steal_pointer (&helper), &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001639 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes18423292015-03-09 17:10:50 +00001640 return;
1641 }
1642
Richard Hughes4ad41f02018-05-08 14:35:36 +01001643 /* async return */
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001644 return;
1645 }
Richard Hughes07f963a2017-09-15 14:28:47 +01001646 if (g_strcmp0 (method_name, "GetDetails") == 0) {
Richard Hughes7289a6b2016-05-29 09:27:47 +01001647 GDBusMessage *message;
1648 GUnixFDList *fd_list;
1649 gint32 fd_handle = 0;
1650 gint fd;
Richard Hughes9945edb2017-06-19 10:03:55 +01001651 g_autoptr(GPtrArray) results = NULL;
Richard Hughes7289a6b2016-05-29 09:27:47 +01001652
1653 /* get parameters */
1654 g_variant_get (parameters, "(h)", &fd_handle);
1655 g_debug ("Called %s(%i)", method_name, fd_handle);
1656
1657 /* get the fd */
1658 message = g_dbus_method_invocation_get_message (invocation);
1659 fd_list = g_dbus_message_get_unix_fd_list (message);
1660 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001661 g_set_error (&error,
1662 FWUPD_ERROR,
1663 FWUPD_ERROR_INTERNAL,
1664 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001665 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001666 return;
1667 }
Richard Hughes7419e962016-11-22 19:48:06 +00001668 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001669 if (fd < 0) {
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 }
1673
Richard Hughes9945edb2017-06-19 10:03:55 +01001674 /* get details about the file (will close the fd when done) */
Richard Hughesdf89cd52020-06-26 20:25:18 +01001675 results = fu_engine_get_details (priv->engine, request, fd, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001676 if (results == NULL) {
1677 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001678 return;
1679 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001680 val = fu_main_result_array_to_variant (results);
1681 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001682 return;
1683 }
Richard Hughes060af612016-08-17 17:32:34 +01001684 g_set_error (&error,
1685 G_DBUS_ERROR,
1686 G_DBUS_ERROR_UNKNOWN_METHOD,
1687 "no such method %s", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001688 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001689}
1690
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001691static GVariant *
1692fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
1693 const gchar *object_path, const gchar *interface_name,
1694 const gchar *property_name, GError **error,
1695 gpointer user_data)
1696{
Richard Hughes773ce982015-03-09 22:40:57 +00001697 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1698
Richard Hughes75b965d2018-11-15 13:51:21 +00001699 /* activity */
1700 fu_engine_idle_reset (priv->engine);
1701
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001702 if (g_strcmp0 (property_name, "DaemonVersion") == 0)
Richard Hughesfe4b3ea2020-03-30 10:53:20 +01001703 return g_variant_new_string (SOURCE_VERSION);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001704
Richard Hughesf425d292019-01-18 17:57:39 +00001705 if (g_strcmp0 (property_name, "Tainted") == 0)
1706 return g_variant_new_boolean (fu_engine_get_tainted (priv->engine));
1707
Richard Hughes773ce982015-03-09 22:40:57 +00001708 if (g_strcmp0 (property_name, "Status") == 0)
Richard Hughes9945edb2017-06-19 10:03:55 +01001709 return g_variant_new_uint32 (fu_engine_get_status (priv->engine));
Richard Hughes773ce982015-03-09 22:40:57 +00001710
Mario Limonciello20cc9ee2019-09-05 07:27:26 -05001711 if (g_strcmp0 (property_name, "HostProduct") == 0)
1712 return g_variant_new_string (fu_engine_get_host_product (priv->engine));
1713
Richard Hughes0917fb62019-09-21 12:55:37 +01001714 if (g_strcmp0 (property_name, "HostMachineId") == 0)
1715 return g_variant_new_string (fu_engine_get_host_machine_id (priv->engine));
1716
Richard Hughes196c6c62020-05-11 19:42:47 +01001717 if (g_strcmp0 (property_name, "HostSecurityId") == 0)
1718 return g_variant_new_string (fu_engine_get_host_security_id (priv->engine));
1719
Mario Limoncielloeb4c7642019-11-11 10:31:29 -06001720 if (g_strcmp0 (property_name, "Interactive") == 0)
1721 return g_variant_new_boolean (isatty (fileno (stdout)) != 0);
1722
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001723 /* return an error */
1724 g_set_error (error,
Richard Hughes8645ec92015-03-19 10:14:32 +00001725 G_DBUS_ERROR,
1726 G_DBUS_ERROR_UNKNOWN_PROPERTY,
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001727 "failed to get daemon property %s",
1728 property_name);
1729 return NULL;
1730}
1731
Richard Hughesfd468842015-04-22 16:44:08 +01001732static void
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001733fu_main_on_bus_acquired_cb (GDBusConnection *connection,
1734 const gchar *name,
1735 gpointer user_data)
1736{
1737 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1738 guint registration_id;
Richard Hughes46832432015-09-11 13:43:15 +01001739 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001740 static const GDBusInterfaceVTable interface_vtable = {
1741 fu_main_daemon_method_call,
1742 fu_main_daemon_get_property,
1743 NULL
1744 };
1745
1746 priv->connection = g_object_ref (connection);
1747 registration_id = g_dbus_connection_register_object (connection,
1748 FWUPD_DBUS_PATH,
1749 priv->introspection_daemon->interfaces[0],
1750 &interface_vtable,
1751 priv, /* user_data */
1752 NULL, /* user_data_free_func */
1753 NULL); /* GError** */
1754 g_assert (registration_id > 0);
Richard Hughes18423292015-03-09 17:10:50 +00001755
1756 /* connect to D-Bus directly */
1757 priv->proxy_uid =
1758 g_dbus_proxy_new_sync (priv->connection,
1759 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1760 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1761 NULL,
1762 "org.freedesktop.DBus",
1763 "/org/freedesktop/DBus",
1764 "org.freedesktop.DBus",
1765 NULL,
1766 &error);
1767 if (priv->proxy_uid == NULL) {
1768 g_warning ("cannot connect to DBus: %s", error->message);
1769 return;
1770 }
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001771}
1772
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001773static void
1774fu_main_on_name_acquired_cb (GDBusConnection *connection,
1775 const gchar *name,
1776 gpointer user_data)
1777{
Richard Hughes33dcfb72020-09-28 15:58:39 +01001778 g_debug ("acquired name: %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001779}
1780
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001781static void
1782fu_main_on_name_lost_cb (GDBusConnection *connection,
1783 const gchar *name,
1784 gpointer user_data)
1785{
1786 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Mario Limonciello471a0e22020-06-09 10:49:49 -05001787 g_warning ("another service has claimed the dbus name %s", name);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001788 g_main_loop_quit (priv->loop);
1789}
1790
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001791static gboolean
1792fu_main_timed_exit_cb (gpointer user_data)
1793{
1794 GMainLoop *loop = (GMainLoop *) user_data;
1795 g_main_loop_quit (loop);
1796 return G_SOURCE_REMOVE;
1797}
1798
Richard Hughesf3dc1622019-03-27 12:48:39 +00001799static void
1800fu_main_argv_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file,
1801 GFileMonitorEvent event_type, gpointer user_data)
1802{
1803 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1804
1805 /* can do straight away? */
1806 if (priv->update_in_progress) {
1807 g_warning ("binary changed during a firmware update, ignoring");
1808 return;
1809 }
1810 g_debug ("binary changed, shutting down");
1811 g_main_loop_quit (priv->loop);
1812}
1813
Richard Hughes603e4f62019-12-11 13:44:09 +00001814#if GLIB_CHECK_VERSION(2,63,3)
1815static void
1816fu_main_memory_monitor_warning_cb (GMemoryMonitor *memory_monitor,
1817 GMemoryMonitorWarningLevel level,
1818 FuMainPrivate *priv)
1819{
1820 /* can do straight away? */
1821 if (priv->update_in_progress) {
1822 g_warning ("OOM during a firmware update, ignoring");
1823 priv->pending_sigterm = TRUE;
1824 return;
1825 }
1826 g_debug ("OOM event, shutting down");
1827 g_main_loop_quit (priv->loop);
1828}
1829#endif
1830
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001831static GDBusNodeInfo *
1832fu_main_load_introspection (const gchar *filename, GError **error)
1833{
Richard Hughes46832432015-09-11 13:43:15 +01001834 g_autoptr(GBytes) data = NULL;
1835 g_autofree gchar *path = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001836
1837 /* lookup data */
1838 path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL);
1839 data = g_resource_lookup_data (fu_get_resource (),
1840 path,
1841 G_RESOURCE_LOOKUP_FLAGS_NONE,
1842 error);
1843 if (data == NULL)
1844 return NULL;
1845
1846 /* build introspection from XML */
1847 return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error);
1848}
1849
Richard Hughesa018b3c2020-08-28 17:08:19 +01001850static gboolean
1851fu_main_is_hypervisor (void)
1852{
1853 g_autofree gchar *buf = NULL;
1854 gsize bufsz = 0;
1855 if (!g_file_get_contents ("/proc/cpuinfo", &buf, &bufsz, NULL))
1856 return FALSE;
1857 return g_strstr_len (buf, (gssize) bufsz, "hypervisor") != NULL;
1858}
1859
1860static gboolean
1861fu_main_is_container (void)
1862{
1863 g_autofree gchar *buf = NULL;
1864 gsize bufsz = 0;
1865 if (!g_file_get_contents ("/proc/1/cgroup", &buf, &bufsz, NULL))
1866 return FALSE;
1867 if (g_strstr_len (buf, (gssize) bufsz, "docker") != NULL)
1868 return TRUE;
1869 if (g_strstr_len (buf, (gssize) bufsz, "lxc") != NULL)
1870 return TRUE;
1871 return FALSE;
1872}
1873
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001874static void
1875fu_main_private_free (FuMainPrivate *priv)
1876{
Richard Hughesdf89cd52020-06-26 20:25:18 +01001877 g_hash_table_unref (priv->sender_features);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001878 if (priv->loop != NULL)
1879 g_main_loop_unref (priv->loop);
1880 if (priv->owner_id > 0)
1881 g_bus_unown_name (priv->owner_id);
1882 if (priv->proxy_uid != NULL)
1883 g_object_unref (priv->proxy_uid);
Richard Hughes9945edb2017-06-19 10:03:55 +01001884 if (priv->engine != NULL)
1885 g_object_unref (priv->engine);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001886 if (priv->connection != NULL)
1887 g_object_unref (priv->connection);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001888#ifdef HAVE_POLKIT
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001889 if (priv->authority != NULL)
1890 g_object_unref (priv->authority);
Mario Limonciello11b71f42020-10-13 13:39:14 -05001891#endif
Richard Hughes0b6f5832020-09-01 20:15:02 +01001892 if (priv->argv0_monitor != NULL) {
1893 g_file_monitor_cancel (priv->argv0_monitor);
Richard Hughesf3dc1622019-03-27 12:48:39 +00001894 g_object_unref (priv->argv0_monitor);
Richard Hughes0b6f5832020-09-01 20:15:02 +01001895 }
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001896 if (priv->introspection_daemon != NULL)
1897 g_dbus_node_info_unref (priv->introspection_daemon);
Richard Hughes603e4f62019-12-11 13:44:09 +00001898#if GLIB_CHECK_VERSION(2,63,3)
1899 if (priv->memory_monitor != NULL)
1900 g_object_unref (priv->memory_monitor);
1901#endif
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001902 g_free (priv);
1903}
1904
Mario Limoncielloa98df552018-04-16 12:15:51 -05001905#pragma clang diagnostic push
1906#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001907G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainPrivate, fu_main_private_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -05001908#pragma clang diagnostic pop
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001909
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001910int
1911main (int argc, char *argv[])
1912{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001913 gboolean immediate_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001914 gboolean timed_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001915 const GOptionEntry options[] = {
1916 { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit,
1917 /* TRANSLATORS: exit after we've started up, used for user profiling */
1918 _("Exit after a small delay"), NULL },
1919 { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit,
1920 /* TRANSLATORS: exit straight away, used for automatic profiling */
1921 _("Exit after the engine has loaded"), NULL },
1922 { NULL}
1923 };
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001924 g_autoptr(FuMainPrivate) priv = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001925 g_autoptr(GError) error = NULL;
Richard Hughesf3dc1622019-03-27 12:48:39 +00001926 g_autoptr(GFile) argv0_file = g_file_new_for_path (argv[0]);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001927 g_autoptr(GOptionContext) context = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001928
1929 setlocale (LC_ALL, "");
1930
Richard Hughes668ee212019-11-22 09:17:46 +00001931 bindtextdomain (GETTEXT_PACKAGE, FWUPD_LOCALEDIR);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001932 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1933 textdomain (GETTEXT_PACKAGE);
1934
1935 /* TRANSLATORS: program name */
Richard Hughes63a407a2015-07-22 08:54:14 +01001936 g_set_application_name (_("Firmware Update Daemon"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001937 context = g_option_context_new (NULL);
1938 g_option_context_add_main_entries (context, options, NULL);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001939 g_option_context_add_group (context, fu_debug_get_option_group ());
Richard Hughes8ded6ca2015-03-16 12:51:36 +00001940 /* TRANSLATORS: program summary */
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001941 g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001942 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1943 g_printerr ("Failed to parse command line: %s\n", error->message);
1944 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001945 }
1946
1947 /* create new objects */
1948 priv = g_new0 (FuMainPrivate, 1);
Richard Hughesdf89cd52020-06-26 20:25:18 +01001949 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 +00001950 priv->loop = g_main_loop_new (NULL, FALSE);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001951
Richard Hughes9945edb2017-06-19 10:03:55 +01001952 /* load engine */
Richard Hughes5b5f6552018-05-18 10:22:39 +01001953 priv->engine = fu_engine_new (FU_APP_FLAGS_NONE);
Richard Hughes9945edb2017-06-19 10:03:55 +01001954 g_signal_connect (priv->engine, "changed",
1955 G_CALLBACK (fu_main_engine_changed_cb),
1956 priv);
1957 g_signal_connect (priv->engine, "device-added",
1958 G_CALLBACK (fu_main_engine_device_added_cb),
1959 priv);
1960 g_signal_connect (priv->engine, "device-removed",
1961 G_CALLBACK (fu_main_engine_device_removed_cb),
1962 priv);
1963 g_signal_connect (priv->engine, "device-changed",
1964 G_CALLBACK (fu_main_engine_device_changed_cb),
1965 priv);
1966 g_signal_connect (priv->engine, "status-changed",
1967 G_CALLBACK (fu_main_engine_status_changed_cb),
1968 priv);
1969 g_signal_connect (priv->engine, "percentage-changed",
1970 G_CALLBACK (fu_main_engine_percentage_changed_cb),
1971 priv);
Richard Hughesc8cc77c2019-03-07 11:57:24 +00001972 if (!fu_engine_load (priv->engine, FU_ENGINE_LOAD_FLAG_NONE, &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001973 g_printerr ("Failed to load engine: %s\n", error->message);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001974 return EXIT_FAILURE;
Richard Hughes804c0752015-08-04 14:53:52 +01001975 }
1976
Mario Limonciello6754f5a2018-10-11 10:50:03 -05001977 g_unix_signal_add_full (G_PRIORITY_DEFAULT,
1978 SIGTERM, fu_main_sigterm_cb,
1979 priv, NULL);
1980
Richard Hughesf3dc1622019-03-27 12:48:39 +00001981 /* restart the daemon if the binary gets replaced */
1982 priv->argv0_monitor = g_file_monitor_file (argv0_file, G_FILE_MONITOR_NONE,
1983 NULL, &error);
1984 g_signal_connect (priv->argv0_monitor, "changed",
1985 G_CALLBACK (fu_main_argv_changed_cb), priv);
1986
Richard Hughes603e4f62019-12-11 13:44:09 +00001987#if GLIB_CHECK_VERSION(2,63,3)
1988 /* shut down on low memory event as we can just rescan hardware */
1989 priv->memory_monitor = g_memory_monitor_dup_default ();
1990 g_signal_connect (G_OBJECT (priv->memory_monitor), "low-memory-warning",
1991 G_CALLBACK (fu_main_memory_monitor_warning_cb), priv);
1992#endif
1993
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001994 /* load introspection from file */
1995 priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
1996 &error);
1997 if (priv->introspection_daemon == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001998 g_printerr ("Failed to load introspection: %s\n", error->message);
1999 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002000 }
2001
Mario Limonciello11b71f42020-10-13 13:39:14 -05002002#ifdef HAVE_POLKIT
Richard Hughesf508e762015-02-27 12:49:36 +00002003 /* get authority */
2004 priv->authority = polkit_authority_get_sync (NULL, &error);
2005 if (priv->authority == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002006 g_printerr ("Failed to load authority: %s\n", error->message);
2007 return EXIT_FAILURE;
Richard Hughesf508e762015-02-27 12:49:36 +00002008 }
Mario Limonciello11b71f42020-10-13 13:39:14 -05002009#endif
Richard Hughesf508e762015-02-27 12:49:36 +00002010
Richard Hughesa018b3c2020-08-28 17:08:19 +01002011 /* are we a VM? */
2012 if (fu_main_is_hypervisor ()) {
2013 priv->machine_kind = FU_MAIN_MACHINE_KIND_VIRTUAL;
2014 } else if (fu_main_is_container ()) {
2015 priv->machine_kind = FU_MAIN_MACHINE_KIND_CONTAINER;
2016 }
2017
Richard Hughesebae3962018-09-09 13:40:49 +01002018 /* own the object */
2019 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
2020 FWUPD_DBUS_SERVICE,
2021 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
2022 G_BUS_NAME_OWNER_FLAGS_REPLACE,
2023 fu_main_on_bus_acquired_cb,
2024 fu_main_on_name_acquired_cb,
2025 fu_main_on_name_lost_cb,
2026 priv, NULL);
2027
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002028 /* Only timeout and close the mainloop if we have specified it
2029 * on the command line */
2030 if (immediate_exit)
2031 g_idle_add (fu_main_timed_exit_cb, priv->loop);
2032 else if (timed_exit)
2033 g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop);
2034
2035 /* wait */
Richard Hughes33dcfb72020-09-28 15:58:39 +01002036 g_message ("Daemon ready for requests (locale %s)", g_getenv ("LANG"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002037 g_main_loop_run (priv->loop);
2038
Richard Hughesa0531342020-10-23 10:47:26 +01002039#ifdef HAVE_SYSTEMD
2040 /* notify the service manager */
2041 sd_notify (0, "STOPPING=1");
2042#endif
2043
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002044 /* success */
Richard Hughesf29a6ee2017-06-02 19:50:37 +01002045 return EXIT_SUCCESS;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00002046}