blob: fa1e02b3b4a7e7c49a2b930b096fcd963e96b086 [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>
Richard Hughesf508e762015-02-27 12:49:36 +000017#include <polkit/polkit.h>
Richard Hughes67ec8982015-03-03 11:39:27 +000018#include <stdlib.h>
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000019
Richard Hughes68982c62017-09-13 15:40:14 +010020#include "fwupd-device-private.h"
Richard Hughes1642b3b2017-06-05 17:40:08 +010021#include "fwupd-release-private.h"
Richard Hughes4c369702017-06-16 15:31:38 +010022#include "fwupd-remote-private.h"
Richard Hughesd6db6b42017-04-12 15:03:10 +010023#include "fwupd-resources.h"
Richard Hughes8e9762d2016-03-17 10:14:15 +000024
Richard Hughes943d2c92017-06-21 09:04:39 +010025#include "fu-common.h"
Richard Hughes8bbfdf42015-02-26 22:28:09 +000026#include "fu-debug.h"
Richard Hughes68982c62017-09-13 15:40:14 +010027#include "fu-device-private.h"
Richard Hughes9945edb2017-06-19 10:03:55 +010028#include "fu-engine.h"
Richard Hughes4ad41f02018-05-08 14:35:36 +010029#include "fu-install-task.h"
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000030
Philip Withnallbc339aa2016-11-22 16:13:22 +000031#ifndef HAVE_POLKIT_0_114
Mario Limoncielloa98df552018-04-16 12:15:51 -050032#pragma clang diagnostic push
33#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes60f48c22015-10-08 20:25:51 +010034G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitAuthorizationResult, g_object_unref)
35G_DEFINE_AUTOPTR_CLEANUP_FUNC(PolkitSubject, g_object_unref)
Mario Limoncielloa98df552018-04-16 12:15:51 -050036#pragma clang diagnostic pop
Richard Hughes60f48c22015-10-08 20:25:51 +010037#endif
38
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000039typedef struct {
40 GDBusConnection *connection;
41 GDBusNodeInfo *introspection_daemon;
Richard Hughes18423292015-03-09 17:10:50 +000042 GDBusProxy *proxy_uid;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000043 GMainLoop *loop;
Richard Hughesf3dc1622019-03-27 12:48:39 +000044 GFileMonitor *argv0_monitor;
Richard Hughesf508e762015-02-27 12:49:36 +000045 PolkitAuthority *authority;
Richard Hughesf0a799e2017-01-17 20:13:30 +000046 guint owner_id;
Richard Hughes9945edb2017-06-19 10:03:55 +010047 FuEngine *engine;
Mario Limonciello6754f5a2018-10-11 10:50:03 -050048 gboolean update_in_progress;
49 gboolean pending_sigterm;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +000050} FuMainPrivate;
51
Mario Limonciello6754f5a2018-10-11 10:50:03 -050052static gboolean
53fu_main_sigterm_cb (gpointer user_data)
54{
55 FuMainPrivate *priv = (FuMainPrivate *) user_data;
56 if (!priv->update_in_progress) {
57 g_main_loop_quit (priv->loop);
58 return G_SOURCE_REMOVE;
59 }
60 g_warning ("Received SIGTERM during a firmware update, ignoring");
61 priv->pending_sigterm = TRUE;
62 return G_SOURCE_CONTINUE;
63}
64
Richard Hughesd7022b52015-03-11 19:47:06 +000065static void
Richard Hughes9945edb2017-06-19 10:03:55 +010066fu_main_engine_changed_cb (FuEngine *engine, FuMainPrivate *priv)
Richard Hughesd7022b52015-03-11 19:47:06 +000067{
68 /* not yet connected */
69 if (priv->connection == NULL)
70 return;
71 g_dbus_connection_emit_signal (priv->connection,
72 NULL,
73 FWUPD_DBUS_PATH,
74 FWUPD_DBUS_INTERFACE,
75 "Changed",
76 NULL, NULL);
77}
78
Richard Hughes8ca33782016-04-28 15:04:31 +010079static void
Richard Hughes9945edb2017-06-19 10:03:55 +010080fu_main_engine_device_added_cb (FuEngine *engine,
81 FuDevice *device,
82 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +010083{
84 GVariant *val;
85
86 /* not yet connected */
87 if (priv->connection == NULL)
88 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +010089 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +010090 g_dbus_connection_emit_signal (priv->connection,
91 NULL,
92 FWUPD_DBUS_PATH,
93 FWUPD_DBUS_INTERFACE,
94 "DeviceAdded",
Richard Hughese0bd53e2017-09-17 08:29:02 +010095 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +010096}
97
Richard Hughes8ca33782016-04-28 15:04:31 +010098static void
Richard Hughes9945edb2017-06-19 10:03:55 +010099fu_main_engine_device_removed_cb (FuEngine *engine,
100 FuDevice *device,
101 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100102{
103 GVariant *val;
104
105 /* not yet connected */
106 if (priv->connection == NULL)
107 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100108 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100109 g_dbus_connection_emit_signal (priv->connection,
110 NULL,
111 FWUPD_DBUS_PATH,
112 FWUPD_DBUS_INTERFACE,
113 "DeviceRemoved",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100114 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100115}
116
Richard Hughes8ca33782016-04-28 15:04:31 +0100117static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100118fu_main_engine_device_changed_cb (FuEngine *engine,
119 FuDevice *device,
120 FuMainPrivate *priv)
Richard Hughes8ca33782016-04-28 15:04:31 +0100121{
122 GVariant *val;
123
124 /* not yet connected */
125 if (priv->connection == NULL)
126 return;
Richard Hughese0bd53e2017-09-17 08:29:02 +0100127 val = fwupd_device_to_variant (FWUPD_DEVICE (device));
Richard Hughes8ca33782016-04-28 15:04:31 +0100128 g_dbus_connection_emit_signal (priv->connection,
129 NULL,
130 FWUPD_DBUS_PATH,
131 FWUPD_DBUS_INTERFACE,
132 "DeviceChanged",
Richard Hughese0bd53e2017-09-17 08:29:02 +0100133 g_variant_new_tuple (&val, 1), NULL);
Richard Hughes8ca33782016-04-28 15:04:31 +0100134}
135
Richard Hughes773ce982015-03-09 22:40:57 +0000136static void
137fu_main_emit_property_changed (FuMainPrivate *priv,
138 const gchar *property_name,
139 GVariant *property_value)
140{
141 GVariantBuilder builder;
142 GVariantBuilder invalidated_builder;
143
144 /* not yet connected */
Richard Hughes34fcc022018-09-19 16:16:15 +0100145 if (priv->connection == NULL) {
146 g_variant_unref (g_variant_ref_sink (property_value));
Richard Hughes773ce982015-03-09 22:40:57 +0000147 return;
Richard Hughes34fcc022018-09-19 16:16:15 +0100148 }
Richard Hughes773ce982015-03-09 22:40:57 +0000149
150 /* build the dict */
151 g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
Richard Hughes8356a832019-03-21 17:04:38 +0000152 g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
Richard Hughes773ce982015-03-09 22:40:57 +0000153 g_variant_builder_add (&builder,
154 "{sv}",
155 property_name,
156 property_value);
157 g_dbus_connection_emit_signal (priv->connection,
158 NULL,
159 FWUPD_DBUS_PATH,
160 "org.freedesktop.DBus.Properties",
161 "PropertiesChanged",
162 g_variant_new ("(sa{sv}as)",
163 FWUPD_DBUS_INTERFACE,
164 &builder,
165 &invalidated_builder),
166 NULL);
167 g_variant_builder_clear (&builder);
168 g_variant_builder_clear (&invalidated_builder);
169}
170
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100171static void
172fu_main_set_status (FuMainPrivate *priv, FwupdStatus status)
173{
174 g_debug ("Emitting PropertyChanged('Status'='%s')",
175 fwupd_status_to_string (status));
176 fu_main_emit_property_changed (priv, "Status",
177 g_variant_new_uint32 (status));
178}
Richard Hughes773ce982015-03-09 22:40:57 +0000179
Richard Hughes9945edb2017-06-19 10:03:55 +0100180static void
181fu_main_engine_status_changed_cb (FuEngine *engine,
182 FwupdStatus status,
183 FuMainPrivate *priv)
184{
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100185 fu_main_set_status (priv, status);
Richard Hughes75b965d2018-11-15 13:51:21 +0000186
187 /* engine has gone idle */
188 if (status == FWUPD_STATUS_SHUTDOWN)
189 g_main_loop_quit (priv->loop);
Richard Hughes773ce982015-03-09 22:40:57 +0000190}
191
Richard Hughes876c0072016-08-17 14:51:03 +0100192static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100193fu_main_engine_percentage_changed_cb (FuEngine *engine,
194 guint percentage,
195 FuMainPrivate *priv)
Richard Hughes876c0072016-08-17 14:51:03 +0100196{
Richard Hughes876c0072016-08-17 14:51:03 +0100197 g_debug ("Emitting PropertyChanged('Percentage'='%u%%')", percentage);
198 fu_main_emit_property_changed (priv, "Percentage",
199 g_variant_new_uint32 (percentage));
200}
201
Mario Limoncielloe3016602018-09-06 11:20:59 -0500202static gboolean
203fu_main_get_device_flags_for_sender (FuMainPrivate *priv, const char *sender,
204 FwupdDeviceFlags *flags, GError **error)
205{
206 uid_t calling_uid;
207 g_autoptr(GVariant) value = NULL;
208
209 g_return_val_if_fail (sender != NULL, FALSE);
210 g_return_val_if_fail (flags != NULL, FALSE);
211
212 value = g_dbus_proxy_call_sync (priv->proxy_uid,
213 "GetConnectionUnixUser",
214 g_variant_new ("(s)", sender),
215 G_DBUS_CALL_FLAGS_NONE,
216 2000,
217 NULL,
218 error);
219 if (value == NULL) {
220 g_prefix_error (error, "failed to read user id of caller: ");
221 return FALSE;
222 }
223 g_variant_get (value, "(u)", &calling_uid);
224 if (calling_uid == 0)
225 *flags |= FWUPD_DEVICE_FLAG_TRUSTED;
226
227 return TRUE;
228}
229
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000230static GVariant *
Mario Limoncielloe3016602018-09-06 11:20:59 -0500231fu_main_device_array_to_variant (FuMainPrivate *priv, const gchar *sender,
232 GPtrArray *devices, GError **error)
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000233{
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000234 GVariantBuilder builder;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500235 FwupdDeviceFlags flags = FWUPD_DEVICE_FLAG_NONE;
236
Richard Hughes9945edb2017-06-19 10:03:55 +0100237 g_return_val_if_fail (devices->len > 0, NULL);
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000238 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500239
240 if (!fu_main_get_device_flags_for_sender (priv, sender, &flags, error))
Richard Hughes83cce1b2018-09-10 16:42:30 +0100241 return NULL;
Mario Limoncielloe3016602018-09-06 11:20:59 -0500242
Richard Hughesf192bf02016-07-22 08:26:43 +0100243 for (guint i = 0; i < devices->len; i++) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100244 FuDevice *device = g_ptr_array_index (devices, i);
Mario Limoncielloe3016602018-09-06 11:20:59 -0500245 GVariant *tmp = fwupd_device_to_variant_full (FWUPD_DEVICE (device),
246 flags);
Richard Hughes1ffde6c2015-03-02 22:44:48 +0000247 g_variant_builder_add_value (&builder, tmp);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000248 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100249 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000250}
251
Richard Hughes9945edb2017-06-19 10:03:55 +0100252static GVariant *
253fu_main_release_array_to_variant (GPtrArray *results)
Richard Hughes060af612016-08-17 17:32:34 +0100254{
Richard Hughes9945edb2017-06-19 10:03:55 +0100255 GVariantBuilder builder;
256 g_return_val_if_fail (results->len > 0, NULL);
257 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
258 for (guint i = 0; i < results->len; i++) {
259 FwupdRelease *rel = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100260 GVariant *tmp = fwupd_release_to_variant (rel);
Richard Hughes9945edb2017-06-19 10:03:55 +0100261 g_variant_builder_add_value (&builder, tmp);
262 }
263 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100264}
265
Richard Hughes9945edb2017-06-19 10:03:55 +0100266static GVariant *
267fu_main_remote_array_to_variant (GPtrArray *remotes)
Richard Hughes060af612016-08-17 17:32:34 +0100268{
Richard Hughes9945edb2017-06-19 10:03:55 +0100269 GVariantBuilder builder;
270 g_return_val_if_fail (remotes->len > 0, NULL);
271 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
272 for (guint i = 0; i < remotes->len; i++) {
273 FwupdRemote *remote = g_ptr_array_index (remotes, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100274 GVariant *tmp = fwupd_remote_to_variant (remote);
Richard Hughes9945edb2017-06-19 10:03:55 +0100275 g_variant_builder_add_value (&builder, tmp);
276 }
277 return g_variant_new ("(aa{sv})", &builder);
Richard Hughes060af612016-08-17 17:32:34 +0100278}
279
Richard Hughes9945edb2017-06-19 10:03:55 +0100280static GVariant *
281fu_main_result_array_to_variant (GPtrArray *results)
Richard Hughes8bbfdf42015-02-26 22:28:09 +0000282{
Richard Hughes9945edb2017-06-19 10:03:55 +0100283 GVariantBuilder builder;
284 g_return_val_if_fail (results->len > 0, NULL);
285 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
286 for (guint i = 0; i < results->len; i++) {
Richard Hughes93b15762017-09-15 11:05:23 +0100287 FwupdDevice *result = g_ptr_array_index (results, i);
Richard Hughese0bd53e2017-09-17 08:29:02 +0100288 GVariant *tmp = fwupd_device_to_variant (result);
Richard Hughes9945edb2017-06-19 10:03:55 +0100289 g_variant_builder_add_value (&builder, tmp);
290 }
Richard Hughes9e1b1402017-09-15 16:29:54 +0100291 return g_variant_new ("(aa{sv})", &builder);
Richard Hughesf508e762015-02-27 12:49:36 +0000292}
293
Richard Hughesf508e762015-02-27 12:49:36 +0000294typedef struct {
295 GDBusMethodInvocation *invocation;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100296 PolkitSubject *subject;
297 GPtrArray *install_tasks;
298 GPtrArray *action_ids;
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000299 GPtrArray *checksums;
Richard Hughes3d607622019-03-07 16:59:27 +0000300 guint64 flags;
Richard Hughes5d14def2015-10-07 17:43:10 +0100301 GBytes *blob_cab;
Richard Hughes67ec8982015-03-03 11:39:27 +0000302 FuMainPrivate *priv;
Richard Hughes9945edb2017-06-19 10:03:55 +0100303 gchar *device_id;
Richard Hughesa6bd5582017-09-07 14:32:22 +0100304 gchar *remote_id;
305 gchar *key;
306 gchar *value;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100307 XbSilo *silo;
Richard Hughesf508e762015-02-27 12:49:36 +0000308} FuMainAuthHelper;
309
Richard Hughesf508e762015-02-27 12:49:36 +0000310static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100311fu_main_auth_helper_free (FuMainAuthHelper *helper)
Richard Hughesf508e762015-02-27 12:49:36 +0000312{
Richard Hughes4ced4662016-08-26 11:02:31 +0100313 if (helper->blob_cab != NULL)
Richard Hughes5d14def2015-10-07 17:43:10 +0100314 g_bytes_unref (helper->blob_cab);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100315 if (helper->subject != NULL)
316 g_object_unref (helper->subject);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100317 if (helper->silo != NULL)
318 g_object_unref (helper->silo);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100319 if (helper->install_tasks != NULL)
320 g_ptr_array_unref (helper->install_tasks);
321 if (helper->action_ids != NULL)
322 g_ptr_array_unref (helper->action_ids);
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000323 if (helper->checksums != NULL)
324 g_ptr_array_unref (helper->checksums);
Richard Hughes9945edb2017-06-19 10:03:55 +0100325 g_free (helper->device_id);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100326 g_free (helper->remote_id);
327 g_free (helper->key);
328 g_free (helper->value);
Richard Hughes67ec8982015-03-03 11:39:27 +0000329 g_object_unref (helper->invocation);
Richard Hughesf508e762015-02-27 12:49:36 +0000330 g_free (helper);
331}
332
Mario Limoncielloa98df552018-04-16 12:15:51 -0500333#pragma clang diagnostic push
334#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughes9945edb2017-06-19 10:03:55 +0100335G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainAuthHelper, fu_main_auth_helper_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -0500336#pragma clang diagnostic pop
Richard Hughes9945edb2017-06-19 10:03:55 +0100337
338/* error may or may not already have been set */
Richard Hughesb75c92d2016-02-20 20:22:00 +0000339static gboolean
Richard Hughes9945edb2017-06-19 10:03:55 +0100340fu_main_authorization_is_valid (PolkitAuthorizationResult *auth, GError **error)
Richard Hughes9a410ce2016-02-28 15:58:54 +0000341{
Richard Hughes9945edb2017-06-19 10:03:55 +0100342 /* failed */
Richard Hughesf508e762015-02-27 12:49:36 +0000343 if (auth == NULL) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100344 g_autofree gchar *message = g_strdup ((*error)->message);
345 g_clear_error (error);
346 g_set_error (error,
Richard Hughes060af612016-08-17 17:32:34 +0100347 FWUPD_ERROR,
348 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100349 "Could not check for auth: %s", message);
350 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000351 }
352
353 /* did not auth */
354 if (!polkit_authorization_result_get_is_authorized (auth)) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100355 g_set_error_literal (error,
Richard Hughes060af612016-08-17 17:32:34 +0100356 FWUPD_ERROR,
357 FWUPD_ERROR_AUTH_FAILED,
Richard Hughes9945edb2017-06-19 10:03:55 +0100358 "Failed to obtain auth");
359 return FALSE;
Richard Hughesf508e762015-02-27 12:49:36 +0000360 }
361
362 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100363 return TRUE;
Richard Hughes5d14def2015-10-07 17:43:10 +0100364}
365
Richard Hughesdf7950b2016-01-31 10:18:40 +0000366static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100367fu_main_authorize_unlock_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100368{
Richard Hughes9945edb2017-06-19 10:03:55 +0100369 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
370 g_autoptr(GError) error = NULL;
371 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100372
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100373
Richard Hughes9945edb2017-06-19 10:03:55 +0100374 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100375 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100376 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
377 res, &error);
378 if (!fu_main_authorization_is_valid (auth, &error)) {
379 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100380 return;
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100381 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100382
383 /* authenticated */
384 if (!fu_engine_unlock (helper->priv->engine, helper->device_id, &error)) {
385 g_dbus_method_invocation_return_gerror (helper->invocation, error);
386 return;
387 }
388
389 /* success */
390 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes3d2fc1e2017-06-08 14:26:31 +0100391}
392
393static void
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000394fu_main_authorize_set_approved_firmware_cb (GObject *source, GAsyncResult *res, gpointer user_data)
395{
396 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
397 g_autoptr(GError) error = NULL;
398 g_autoptr(PolkitAuthorizationResult) auth = NULL;
399
400 /* get result */
401 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
402 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
403 res, &error);
404 if (!fu_main_authorization_is_valid (auth, &error)) {
405 g_dbus_method_invocation_return_gerror (helper->invocation, error);
406 return;
407 }
408
409 /* success */
410 for (guint i = 0; i < helper->checksums->len; i++) {
411 const gchar *csum = g_ptr_array_index (helper->checksums, i);
412 fu_engine_add_approved_firmware (helper->priv->engine, csum);
413 }
414 g_dbus_method_invocation_return_value (helper->invocation, NULL);
415}
416
417static void
Richard Hughes3d607622019-03-07 16:59:27 +0000418fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
419{
420 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
421 g_autofree gchar *sig = NULL;
422 g_autoptr(GError) error = NULL;
423 g_autoptr(PolkitAuthorizationResult) auth = NULL;
424
425 /* get result */
426 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
427 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
428 res, &error);
429 if (!fu_main_authorization_is_valid (auth, &error)) {
430 g_dbus_method_invocation_return_gerror (helper->invocation, error);
431 return;
432 }
433
434 /* authenticated */
435 sig = fu_engine_self_sign (helper->priv->engine, helper->value, helper->flags, &error);
436 if (sig == NULL) {
437 g_dbus_method_invocation_return_gerror (helper->invocation, error);
438 return;
439 }
440
441 /* success */
442 g_dbus_method_invocation_return_value (helper->invocation, g_variant_new ("(s)", sig));
443}
444
445static void
Mario Limonciellobfcf75b2019-04-17 15:05:39 +0100446fu_main_modify_config_cb (GObject *source, GAsyncResult *res, gpointer user_data)
447{
448 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
449 g_autoptr(GError) error = NULL;
450 g_autoptr(PolkitAuthorizationResult) auth = NULL;
451
452 /* get result */
453 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
454 res, &error);
455 if (!fu_main_authorization_is_valid (auth, &error)) {
456 g_dbus_method_invocation_return_gerror (helper->invocation, error);
457 return;
458 }
459
460 if (!fu_engine_modify_config (helper->priv->engine, helper->key, helper->value, &error)) {
461 g_dbus_method_invocation_return_gerror (helper->invocation, error);
462 return;
463 }
464
465 /* success */
466 g_dbus_method_invocation_return_value (helper->invocation, NULL);
467}
468
469static void
Mario Limonciello96a0dd52019-02-25 13:50:03 -0600470fu_main_authorize_activate_cb (GObject *source, GAsyncResult *res, gpointer user_data)
471{
472 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
473 g_autoptr(GError) error = NULL;
474 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 }
484
485 /* authenticated */
486 if (!fu_engine_activate (helper->priv->engine, helper->device_id, &error)) {
487 g_dbus_method_invocation_return_gerror (helper->invocation, error);
488 return;
489 }
490
491 /* success */
492 g_dbus_method_invocation_return_value (helper->invocation, NULL);
493}
494
495static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100496fu_main_authorize_verify_update_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughesdf7950b2016-01-31 10:18:40 +0000497{
Richard Hughes9945edb2017-06-19 10:03:55 +0100498 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
499 g_autoptr(GError) error = NULL;
500 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughesdf7950b2016-01-31 10:18:40 +0000501
Richard Hughes9945edb2017-06-19 10:03:55 +0100502 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100503 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100504 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
505 res, &error);
506 if (!fu_main_authorization_is_valid (auth, &error)) {
507 g_dbus_method_invocation_return_gerror (helper->invocation, error);
Richard Hughesdf7950b2016-01-31 10:18:40 +0000508 return;
Richard Hughesf192bf02016-07-22 08:26:43 +0100509 }
Richard Hughesdf7950b2016-01-31 10:18:40 +0000510
Richard Hughes9945edb2017-06-19 10:03:55 +0100511 /* authenticated */
512 if (!fu_engine_verify_update (helper->priv->engine, helper->device_id, &error)) {
513 g_dbus_method_invocation_return_gerror (helper->invocation, error);
514 return;
Richard Hughes404cc512016-12-21 16:09:48 +0000515 }
516
517 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100518 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes99147f12016-05-17 09:35:04 +0100519}
520
Richard Hughes9945edb2017-06-19 10:03:55 +0100521static void
Richard Hughesa6bd5582017-09-07 14:32:22 +0100522fu_main_authorize_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
523{
524 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
525 g_autoptr(GError) error = NULL;
526 g_autoptr(PolkitAuthorizationResult) auth = NULL;
527
528 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100529 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughesa6bd5582017-09-07 14:32:22 +0100530 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
531 res, &error);
532 if (!fu_main_authorization_is_valid (auth, &error)) {
533 g_dbus_method_invocation_return_gerror (helper->invocation, error);
534 return;
535 }
536
537 /* authenticated */
538 if (!fu_engine_modify_remote (helper->priv->engine,
539 helper->remote_id,
540 helper->key,
541 helper->value,
542 &error)) {
543 g_dbus_method_invocation_return_gerror (helper->invocation, error);
544 return;
545 }
546
547 /* success */
548 g_dbus_method_invocation_return_value (helper->invocation, NULL);
549}
550
Richard Hughes4ad41f02018-05-08 14:35:36 +0100551static void fu_main_authorize_install_queue (FuMainAuthHelper *helper);
552
Richard Hughesa6bd5582017-09-07 14:32:22 +0100553static void
Richard Hughes9945edb2017-06-19 10:03:55 +0100554fu_main_authorize_install_cb (GObject *source, GAsyncResult *res, gpointer user_data)
Richard Hughes404cc512016-12-21 16:09:48 +0000555{
Richard Hughes9945edb2017-06-19 10:03:55 +0100556 g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
Richard Hughes46832432015-09-11 13:43:15 +0100557 g_autoptr(GError) error = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +0100558 g_autoptr(PolkitAuthorizationResult) auth = NULL;
Richard Hughes18423292015-03-09 17:10:50 +0000559
Richard Hughes9945edb2017-06-19 10:03:55 +0100560 /* get result */
Richard Hughes87f8a4a2017-10-02 09:42:06 +0100561 fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
Richard Hughes9945edb2017-06-19 10:03:55 +0100562 auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
563 res, &error);
564 if (!fu_main_authorization_is_valid (auth, &error)) {
565 g_dbus_method_invocation_return_gerror (helper->invocation, error);
566 return;
Richard Hughes0e883ee2015-03-18 17:22:33 +0000567 }
568
Richard Hughes4ad41f02018-05-08 14:35:36 +0100569 /* do the next authentication action ID */
570 fu_main_authorize_install_queue (g_steal_pointer (&helper));
571}
572
573static void
574fu_main_authorize_install_queue (FuMainAuthHelper *helper_ref)
575{
576 FuMainPrivate *priv = helper_ref->priv;
577 g_autoptr(FuMainAuthHelper) helper = helper_ref;
578 g_autoptr(GError) error = NULL;
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500579 gboolean ret;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100580
581 /* still more things to to authenticate */
582 if (helper->action_ids->len > 0) {
583 g_autofree gchar *action_id = g_strdup (g_ptr_array_index (helper->action_ids, 0));
584 g_autoptr(PolkitSubject) subject = g_object_ref (helper->subject);
585 g_ptr_array_remove_index (helper->action_ids, 0);
586 polkit_authority_check_authorization (priv->authority, subject,
587 action_id, NULL,
588 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
589 NULL,
590 fu_main_authorize_install_cb,
591 g_steal_pointer (&helper));
Richard Hughes9945edb2017-06-19 10:03:55 +0100592 return;
Richard Hughes654f6b82016-04-25 12:29:48 +0100593 }
594
Richard Hughes4ad41f02018-05-08 14:35:36 +0100595 /* all authenticated, so install all the things */
Mario Limonciello6754f5a2018-10-11 10:50:03 -0500596 priv->update_in_progress = TRUE;
597 ret = fu_engine_install_tasks (helper->priv->engine,
598 helper->install_tasks,
599 helper->blob_cab,
600 helper->flags,
601 &error);
602 priv->update_in_progress = FALSE;
603 if (priv->pending_sigterm)
604 g_main_loop_quit (priv->loop);
605 if (!ret) {
Richard Hughesdbd8c762018-06-15 20:31:40 +0100606 g_dbus_method_invocation_return_gerror (helper->invocation, error);
607 return;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100608 }
609
Richard Hughes654f6b82016-04-25 12:29:48 +0100610 /* success */
Richard Hughes9945edb2017-06-19 10:03:55 +0100611 g_dbus_method_invocation_return_value (helper->invocation, NULL);
Richard Hughes4c369702017-06-16 15:31:38 +0100612}
613
Richard Hughes4ad41f02018-05-08 14:35:36 +0100614#if !GLIB_CHECK_VERSION(2,54,0)
615static gboolean
616g_ptr_array_find (GPtrArray *haystack, gconstpointer needle, guint *index_)
617{
618 for (guint i = 0; i < haystack->len; i++) {
619 gconstpointer *tmp = g_ptr_array_index (haystack, i);
620 if (tmp == needle) {
621 if (index_ != NULL) {
622 *index_ = i;
623 return TRUE;
624 }
625 }
626 }
627 return FALSE;
628}
629#endif
630
Richard Hughes9f86ade2018-05-10 21:11:22 +0100631static gint
632fu_main_install_task_sort_cb (gconstpointer a, gconstpointer b)
633{
634 FuInstallTask *task_a = *((FuInstallTask **) a);
635 FuInstallTask *task_b = *((FuInstallTask **) b);
Richard Hughesc02cb832018-05-20 10:31:04 +0100636 return fu_install_task_compare (task_a, task_b);
Richard Hughes9f86ade2018-05-10 21:11:22 +0100637}
638
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500639static GPtrArray *
640fu_main_get_device_family (FuMainAuthHelper *helper, GError **error)
641{
642 FuDevice *parent;
643 GPtrArray *children;
644 g_autoptr(FuDevice) device = NULL;
645 g_autoptr(GPtrArray) devices_possible = NULL;
646
647 /* get the device */
648 device = fu_engine_get_device (helper->priv->engine, helper->device_id, error);
649 if (device == NULL)
650 return NULL;
651
652 /* device itself */
653 devices_possible = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
654 g_ptr_array_add (devices_possible, g_object_ref (device));
655
656 /* add device children */
657 children = fu_device_get_children (device);
658 for (guint i = 0; i < children->len; i++) {
659 FuDevice *child = g_ptr_array_index (children, i);
660 g_ptr_array_add (devices_possible, g_object_ref (child));
661 }
662
663 /* add parent and siblings, not including the device itself */
664 parent = fu_device_get_parent (device);
665 if (parent != NULL) {
666 GPtrArray *siblings = fu_device_get_children (parent);
667 g_ptr_array_add (devices_possible, g_object_ref (parent));
668 for (guint i = 0; i < siblings->len; i++) {
669 FuDevice *sibling = g_ptr_array_index (siblings, i);
670 if (sibling == device)
671 continue;
672 g_ptr_array_add (devices_possible, g_object_ref (sibling));
673 }
674 }
675
676 /* success */
677 return g_steal_pointer (&devices_possible);
678}
679
Richard Hughes4ad41f02018-05-08 14:35:36 +0100680static gboolean
681fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
682{
683 FuMainPrivate *priv = helper_ref->priv;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100684 g_autoptr(FuMainAuthHelper) helper = helper_ref;
Richard Hughes481aa2a2018-09-18 20:51:46 +0100685 g_autoptr(GPtrArray) components = NULL;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100686 g_autoptr(GPtrArray) devices_possible = NULL;
687 g_autoptr(GPtrArray) errors = NULL;
688
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500689 /* get a list of devices that in some way match the device_id */
Richard Hughes4ad41f02018-05-08 14:35:36 +0100690 if (g_strcmp0 (helper->device_id, FWUPD_DEVICE_ID_ANY) == 0) {
691 devices_possible = fu_engine_get_devices (priv->engine, error);
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500692 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100693 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100694 } else {
Mario Limonciello2dd731b2018-10-09 15:25:18 -0500695 devices_possible = fu_main_get_device_family (helper, error);
696 if (devices_possible == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100697 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100698 }
699
Richard Hughes481aa2a2018-09-18 20:51:46 +0100700 /* parse silo */
701 helper->silo = fu_engine_get_silo_from_blob (priv->engine,
702 helper->blob_cab,
703 error);
704 if (helper->silo == NULL)
Richard Hughes4ad41f02018-05-08 14:35:36 +0100705 return FALSE;
706
Richard Hughes481aa2a2018-09-18 20:51:46 +0100707 /* for each component in the silo */
Mario Limonciello51ddf182019-01-26 00:31:58 -0600708 components = xb_silo_query (helper->silo, "components/component", 0, error);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100709 if (components == NULL)
710 return FALSE;
Richard Hughes4ad41f02018-05-08 14:35:36 +0100711 helper->action_ids = g_ptr_array_new_with_free_func (g_free);
712 helper->install_tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
713 errors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_error_free);
Richard Hughes481aa2a2018-09-18 20:51:46 +0100714 for (guint i = 0; i < components->len; i++) {
715 XbNode *component = g_ptr_array_index (components, i);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100716
717 /* do any devices pass the requirements */
718 for (guint j = 0; j < devices_possible->len; j++) {
719 FuDevice *device = g_ptr_array_index (devices_possible, j);
720 const gchar *action_id;
721 g_autoptr(FuInstallTask) task = NULL;
722 g_autoptr(GError) error_local = NULL;
723
724 /* is this component valid for the device */
Richard Hughes481aa2a2018-09-18 20:51:46 +0100725 task = fu_install_task_new (device, component);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100726 if (!fu_engine_check_requirements (priv->engine,
Richard Hughes1d1f5cf2018-05-19 23:06:03 +0100727 task,
728 helper->flags,
Richard Hughes4ad41f02018-05-08 14:35:36 +0100729 &error_local)) {
730 g_debug ("requirement on %s:%s failed: %s",
731 fu_device_get_id (device),
Richard Hughes481aa2a2018-09-18 20:51:46 +0100732 xb_node_query_text (component, "id", NULL),
Richard Hughes4ad41f02018-05-08 14:35:36 +0100733 error_local->message);
734 g_ptr_array_add (errors, g_steal_pointer (&error_local));
735 continue;
736 }
737
Mario Limonciello7a3df4b2019-01-31 10:27:22 -0600738 /* if component should have an update message from CAB */
739 fu_device_incorporate_from_component (device, component);
740
Richard Hughes4ad41f02018-05-08 14:35:36 +0100741 /* get the action IDs for the valid device */
742 action_id = fu_install_task_get_action_id (task);
743 if (!g_ptr_array_find (helper->action_ids, action_id, NULL))
744 g_ptr_array_add (helper->action_ids, g_strdup (action_id));
745 g_ptr_array_add (helper->install_tasks, g_steal_pointer (&task));
746 }
747 }
748
Richard Hughes9f86ade2018-05-10 21:11:22 +0100749 /* order the install tasks by the device priority */
750 g_ptr_array_sort (helper->install_tasks, fu_main_install_task_sort_cb);
751
Richard Hughes4ad41f02018-05-08 14:35:36 +0100752 /* nothing suitable */
753 if (helper->install_tasks->len == 0) {
Richard Hughese82eef32018-05-20 10:41:26 +0100754 GError *error_tmp = fu_common_error_array_get_best (errors);
Richard Hughes4ad41f02018-05-08 14:35:36 +0100755 g_propagate_error (error, error_tmp);
756 return FALSE;
757 }
758
759 /* authenticate all things in the action_ids */
760 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
761 fu_main_authorize_install_queue (g_steal_pointer (&helper));
762 return TRUE;
763}
764
Richard Hughesb6f79552017-11-11 07:58:17 +0000765static gboolean
766fu_main_device_id_valid (const gchar *device_id, GError **error)
767{
768 if (g_strcmp0 (device_id, FWUPD_DEVICE_ID_ANY) == 0)
769 return TRUE;
770 if (device_id != NULL && strlen (device_id) >= 4)
771 return TRUE;
772 g_set_error (error,
773 FWUPD_ERROR,
774 FWUPD_ERROR_INTERNAL,
775 "invalid device ID: %s",
776 device_id);
777 return FALSE;
778}
779
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000780static void
781fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
782 const gchar *object_path, const gchar *interface_name,
783 const gchar *method_name, GVariant *parameters,
784 GDBusMethodInvocation *invocation, gpointer user_data)
785{
786 FuMainPrivate *priv = (FuMainPrivate *) user_data;
Richard Hughes9945edb2017-06-19 10:03:55 +0100787 GVariant *val = NULL;
Richard Hughes060af612016-08-17 17:32:34 +0100788 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000789
Richard Hughes75b965d2018-11-15 13:51:21 +0000790 /* activity */
791 fu_engine_idle_reset (priv->engine);
792
Richard Hughes8dbfb1c2015-02-26 13:07:40 +0000793 if (g_strcmp0 (method_name, "GetDevices") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100794 g_autoptr(GPtrArray) devices = NULL;
Richard Hughesf508e762015-02-27 12:49:36 +0000795 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100796 devices = fu_engine_get_devices (priv->engine, &error);
797 if (devices == NULL) {
798 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100799 return;
800 }
Mario Limoncielloe3016602018-09-06 11:20:59 -0500801 val = fu_main_device_array_to_variant (priv, sender, devices, &error);
802 if (val == NULL) {
803 g_dbus_method_invocation_return_gerror (invocation, error);
804 return;
805 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100806 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7708a0f2015-07-21 08:41:22 +0100807 return;
808 }
Richard Hughese4a100c2017-06-04 21:23:50 +0100809 if (g_strcmp0 (method_name, "GetReleases") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100810 const gchar *device_id;
Richard Hughese4a100c2017-06-04 21:23:50 +0100811 g_autoptr(GPtrArray) releases = NULL;
Richard Hughese4a100c2017-06-04 21:23:50 +0100812 g_variant_get (parameters, "(&s)", &device_id);
813 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +0000814 if (!fu_main_device_id_valid (device_id, &error)) {
815 g_dbus_method_invocation_return_gerror (invocation, error);
816 return;
817 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100818 releases = fu_engine_get_releases (priv->engine, device_id, &error);
819 if (releases == NULL) {
820 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughese4a100c2017-06-04 21:23:50 +0100821 return;
822 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100823 val = fu_main_release_array_to_variant (releases);
824 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughese4a100c2017-06-04 21:23:50 +0100825 return;
826 }
Richard Hughes8dd4c1c2019-03-03 18:27:57 +0000827 if (g_strcmp0 (method_name, "GetApprovedFirmware") == 0) {
828 GVariantBuilder builder;
829 GPtrArray *checksums = fu_engine_get_approved_firmware (priv->engine);
830 g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
831 for (guint i = 0; i < checksums->len; i++) {
832 const gchar *checksum = g_ptr_array_index (checksums, i);
833 g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
834 }
835 val = g_variant_builder_end (&builder);
836 g_dbus_method_invocation_return_value (invocation,
837 g_variant_new_tuple (&val, 1));
838 return;
839 }
840 if (g_strcmp0 (method_name, "SetApprovedFirmware") == 0) {
841 g_autofree gchar *checksums_str = NULL;
842 g_auto(GStrv) checksums = NULL;
843 g_autoptr(FuMainAuthHelper) helper = NULL;
844 g_autoptr(PolkitSubject) subject = NULL;
845
846 g_variant_get (parameters, "(^as)", &checksums);
847 checksums_str = g_strjoinv (",", checksums);
848 g_debug ("Called %s(%s)", method_name, checksums_str);
849
850 /* authenticate */
851 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
852 helper = g_new0 (FuMainAuthHelper, 1);
853 helper->priv = priv;
854 helper->invocation = g_object_ref (invocation);
855 helper->checksums = g_ptr_array_new_with_free_func (g_free);
856 for (guint i = 0; checksums[i] != NULL; i++)
857 g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
858 subject = polkit_system_bus_name_new (sender);
859 polkit_authority_check_authorization (priv->authority, subject,
860 "org.freedesktop.fwupd.set-approved-firmware",
861 NULL,
862 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
863 NULL,
864 fu_main_authorize_set_approved_firmware_cb,
865 g_steal_pointer (&helper));
866 return;
867 }
Richard Hughes3d607622019-03-07 16:59:27 +0000868 if (g_strcmp0 (method_name, "SelfSign") == 0) {
869 GVariant *prop_value;
870 gchar *prop_key;
871 g_autofree gchar *value = NULL;
872 g_autoptr(FuMainAuthHelper) helper = NULL;
873 g_autoptr(PolkitSubject) subject = NULL;
874 g_autoptr(GVariantIter) iter = NULL;
875
876 g_variant_get (parameters, "(sa{sv})", &value, &iter);
877 g_debug ("Called %s(%s)", method_name, value);
878
879 /* get flags */
880 helper = g_new0 (FuMainAuthHelper, 1);
881 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
882 g_debug ("got option %s", prop_key);
883 if (g_strcmp0 (prop_key, "add-timestamp") == 0 &&
884 g_variant_get_boolean (prop_value) == TRUE)
885 helper->flags |= FU_KEYRING_SIGN_FLAG_ADD_TIMESTAMP;
886 if (g_strcmp0 (prop_key, "add-cert") == 0 &&
887 g_variant_get_boolean (prop_value) == TRUE)
888 helper->flags |= FU_KEYRING_SIGN_FLAG_ADD_CERT;
889 g_variant_unref (prop_value);
890 }
891
892 /* authenticate */
893 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
894 helper->priv = priv;
895 helper->value = g_steal_pointer (&value);
896 helper->invocation = g_object_ref (invocation);
897 subject = polkit_system_bus_name_new (sender);
898 polkit_authority_check_authorization (priv->authority, subject,
899 "org.freedesktop.fwupd.self-sign",
900 NULL,
901 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
902 NULL,
903 fu_main_authorize_self_sign_cb,
904 g_steal_pointer (&helper));
905 return;
906 }
Richard Hughes97284b12017-09-13 17:07:58 +0100907 if (g_strcmp0 (method_name, "GetDowngrades") == 0) {
908 const gchar *device_id;
909 g_autoptr(GPtrArray) releases = NULL;
910 g_variant_get (parameters, "(&s)", &device_id);
911 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +0000912 if (!fu_main_device_id_valid (device_id, &error)) {
913 g_dbus_method_invocation_return_gerror (invocation, error);
914 return;
915 }
Richard Hughes97284b12017-09-13 17:07:58 +0100916 releases = fu_engine_get_downgrades (priv->engine, device_id, &error);
917 if (releases == NULL) {
918 g_dbus_method_invocation_return_gerror (invocation, error);
919 return;
920 }
921 val = fu_main_release_array_to_variant (releases);
922 g_dbus_method_invocation_return_value (invocation, val);
923 return;
924 }
Richard Hughesa96413a2017-09-13 17:19:59 +0100925 if (g_strcmp0 (method_name, "GetUpgrades") == 0) {
926 const gchar *device_id;
927 g_autoptr(GPtrArray) releases = NULL;
928 g_variant_get (parameters, "(&s)", &device_id);
929 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +0000930 if (!fu_main_device_id_valid (device_id, &error)) {
931 g_dbus_method_invocation_return_gerror (invocation, error);
932 return;
933 }
Richard Hughesa96413a2017-09-13 17:19:59 +0100934 releases = fu_engine_get_upgrades (priv->engine, device_id, &error);
935 if (releases == NULL) {
936 g_dbus_method_invocation_return_gerror (invocation, error);
937 return;
938 }
939 val = fu_main_release_array_to_variant (releases);
940 g_dbus_method_invocation_return_value (invocation, val);
941 return;
942 }
Richard Hughes4c369702017-06-16 15:31:38 +0100943 if (g_strcmp0 (method_name, "GetRemotes") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100944 g_autoptr(GPtrArray) remotes = NULL;
Richard Hughes4c369702017-06-16 15:31:38 +0100945 g_debug ("Called %s()", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +0100946 remotes = fu_engine_get_remotes (priv->engine, &error);
947 if (remotes == NULL) {
948 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes4c369702017-06-16 15:31:38 +0100949 return;
950 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100951 val = fu_main_remote_array_to_variant (remotes);
952 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes4c369702017-06-16 15:31:38 +0100953 return;
954 }
Richard Hughes476363a2018-01-11 10:08:58 +0000955 if (g_strcmp0 (method_name, "GetHistory") == 0) {
956 g_autoptr(GPtrArray) devices = NULL;
957 g_debug ("Called %s()", method_name);
958 devices = fu_engine_get_history (priv->engine, &error);
959 if (devices == NULL) {
960 g_dbus_method_invocation_return_gerror (invocation, error);
961 return;
962 }
Mario Limoncielloe3016602018-09-06 11:20:59 -0500963 val = fu_main_device_array_to_variant (priv, sender, devices, &error);
964 if (val == NULL) {
965 g_dbus_method_invocation_return_gerror (invocation, error);
966 return;
967 }
Richard Hughes476363a2018-01-11 10:08:58 +0000968 g_dbus_method_invocation_return_value (invocation, val);
969 return;
970 }
Richard Hughes0e883ee2015-03-18 17:22:33 +0000971 if (g_strcmp0 (method_name, "ClearResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100972 const gchar *device_id;
973 g_variant_get (parameters, "(&s)", &device_id);
974 g_debug ("Called %s(%s)", method_name, device_id);
975 if (!fu_engine_clear_results (priv->engine, device_id, &error)) {
976 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +0000977 return;
978 }
Richard Hughes9945edb2017-06-19 10:03:55 +0100979 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughes0e883ee2015-03-18 17:22:33 +0000980 return;
981 }
Richard Hughes6b222952018-01-11 10:20:48 +0000982 if (g_strcmp0 (method_name, "ModifyDevice") == 0) {
983 const gchar *device_id;
984 const gchar *key = NULL;
985 const gchar *value = NULL;
986
987 /* check the id exists */
988 g_variant_get (parameters, "(&s&s&s)", &device_id, &key, &value);
989 g_debug ("Called %s(%s,%s=%s)", method_name, device_id, key, value);
990 if (!fu_engine_modify_device (priv->engine, device_id, key, value, &error)) {
991 g_dbus_method_invocation_return_gerror (invocation, error);
992 return;
993 }
994 g_dbus_method_invocation_return_value (invocation, NULL);
995 return;
996 }
Richard Hughes0e883ee2015-03-18 17:22:33 +0000997 if (g_strcmp0 (method_name, "GetResults") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +0100998 const gchar *device_id = NULL;
Richard Hughes93b15762017-09-15 11:05:23 +0100999 g_autoptr(FwupdDevice) result = NULL;
Richard Hughes9945edb2017-06-19 10:03:55 +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 Hughes9945edb2017-06-19 10:03:55 +01001006 result = fu_engine_get_results (priv->engine, device_id, &error);
1007 if (result == NULL) {
1008 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes0e883ee2015-03-18 17:22:33 +00001009 return;
1010 }
Richard Hughese0bd53e2017-09-17 08:29:02 +01001011 val = fwupd_device_to_variant (result);
1012 g_dbus_method_invocation_return_value (invocation,
1013 g_variant_new_tuple (&val, 1));
Richard Hughes0e883ee2015-03-18 17:22:33 +00001014 return;
1015 }
Richard Hughesba73c762017-09-15 14:31:17 +01001016 if (g_strcmp0 (method_name, "UpdateMetadata") == 0) {
Richard Hughes1b50d962017-06-02 12:23:00 +01001017 GDBusMessage *message;
1018 GUnixFDList *fd_list;
Richard Hughes9945edb2017-06-19 10:03:55 +01001019 const gchar *remote_id = NULL;
Richard Hughes1b50d962017-06-02 12:23:00 +01001020 gint fd_data;
1021 gint fd_sig;
1022
Richard Hughes9945edb2017-06-19 10:03:55 +01001023 g_variant_get (parameters, "(&shh)", &remote_id, &fd_data, &fd_sig);
1024 g_debug ("Called %s(%s,%i,%i)", method_name, remote_id, fd_data, fd_sig);
Richard Hughes1b50d962017-06-02 12:23:00 +01001025
Richard Hughes5935ebd2017-06-16 15:40:31 +01001026 /* update the metadata store */
Richard Hughes1b50d962017-06-02 12:23:00 +01001027 message = g_dbus_method_invocation_get_message (invocation);
1028 fd_list = g_dbus_message_get_unix_fd_list (message);
1029 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 2) {
1030 g_set_error (&error,
1031 FWUPD_ERROR,
1032 FWUPD_ERROR_INTERNAL,
1033 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001034 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001035 return;
1036 }
1037 fd_data = g_unix_fd_list_get (fd_list, 0, &error);
1038 if (fd_data < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001039 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001040 return;
1041 }
1042 fd_sig = g_unix_fd_list_get (fd_list, 1, &error);
1043 if (fd_sig < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001044 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes1b50d962017-06-02 12:23:00 +01001045 return;
1046 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001047
1048 /* store new metadata (will close the fds when done) */
1049 if (!fu_engine_update_metadata (priv->engine, remote_id,
1050 fd_data, fd_sig, &error)) {
Richard Hughesf3d46c62017-11-28 14:01:30 +00001051 g_prefix_error (&error, "Failed to update metadata for %s: ", remote_id);
Richard Hughes9945edb2017-06-19 10:03:55 +01001052 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001053 return;
1054 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001055 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesae0efdc2015-06-24 16:18:29 +01001056 return;
1057 }
Richard Hughes9a410ce2016-02-28 15:58:54 +00001058 if (g_strcmp0 (method_name, "Unlock") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001059 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001060 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes9a410ce2016-02-28 15:58:54 +00001061 g_autoptr(PolkitSubject) subject = NULL;
1062
Richard Hughes9945edb2017-06-19 10:03:55 +01001063 g_variant_get (parameters, "(&s)", &device_id);
1064 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001065 if (!fu_main_device_id_valid (device_id, &error)) {
1066 g_dbus_method_invocation_return_gerror (invocation, error);
1067 return;
1068 }
Richard Hughesfe5cc902016-06-29 10:00:00 +01001069
Richard Hughes9a410ce2016-02-28 15:58:54 +00001070 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001071 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes9945edb2017-06-19 10:03:55 +01001072 helper = g_new0 (FuMainAuthHelper, 1);
1073 helper->priv = priv;
1074 helper->invocation = g_object_ref (invocation);
1075 helper->device_id = g_strdup (device_id);
Richard Hughes9a410ce2016-02-28 15:58:54 +00001076 subject = polkit_system_bus_name_new (sender);
Richard Hughes9945edb2017-06-19 10:03:55 +01001077 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes9a410ce2016-02-28 15:58:54 +00001078 "org.freedesktop.fwupd.device-unlock",
1079 NULL,
1080 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1081 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001082 fu_main_authorize_unlock_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001083 g_steal_pointer (&helper));
Richard Hughes9a410ce2016-02-28 15:58:54 +00001084 return;
1085 }
Mario Limonciello96a0dd52019-02-25 13:50:03 -06001086 if (g_strcmp0 (method_name, "Activate") == 0) {
1087 const gchar *device_id = NULL;
1088 g_autoptr(FuMainAuthHelper) helper = NULL;
1089 g_autoptr(PolkitSubject) subject = NULL;
1090
1091 g_variant_get (parameters, "(&s)", &device_id);
1092 g_debug ("Called %s(%s)", method_name, device_id);
1093 if (!fu_main_device_id_valid (device_id, &error)) {
1094 g_dbus_method_invocation_return_gerror (invocation, error);
1095 return;
1096 }
1097
1098 /* authenticate */
1099 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
1100 helper = g_new0 (FuMainAuthHelper, 1);
1101 helper->priv = priv;
1102 helper->invocation = g_object_ref (invocation);
1103 helper->device_id = g_strdup (device_id);
1104 subject = polkit_system_bus_name_new (sender);
1105 polkit_authority_check_authorization (priv->authority, subject,
1106 "org.freedesktop.fwupd.device-activate",
1107 NULL,
1108 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1109 NULL,
1110 fu_main_authorize_activate_cb,
1111 g_steal_pointer (&helper));
1112 return;
1113 }
Mario Limonciellobfcf75b2019-04-17 15:05:39 +01001114 if (g_strcmp0 (method_name, "ModifyConfig") == 0) {
1115 g_autofree gchar *key = NULL;
1116 g_autofree gchar *value = NULL;
1117 g_autoptr(FuMainAuthHelper) helper = NULL;
1118 g_autoptr(PolkitSubject) subject = NULL;
1119
1120 g_variant_get (parameters, "(ss)", &key, &value);
1121 g_debug ("Called %s(%s=%s)", method_name, key, value);
1122
1123 /* authenticate */
1124 helper = g_new0 (FuMainAuthHelper, 1);
1125 helper->priv = priv;
1126 helper->key = g_steal_pointer (&key);
1127 helper->value = g_steal_pointer (&value);
1128 helper->invocation = g_object_ref (invocation);
1129 subject = polkit_system_bus_name_new (sender);
1130 polkit_authority_check_authorization (priv->authority, subject,
1131 "org.freedesktop.fwupd.modify-config",
1132 NULL,
1133 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1134 NULL,
1135 fu_main_modify_config_cb,
1136 g_steal_pointer (&helper));
1137 return;
1138 }
Richard Hughesa6bd5582017-09-07 14:32:22 +01001139 if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
Richard Hughesa6bd5582017-09-07 14:32:22 +01001140 const gchar *remote_id = NULL;
1141 const gchar *key = NULL;
1142 const gchar *value = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001143 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughesa6bd5582017-09-07 14:32:22 +01001144 g_autoptr(PolkitSubject) subject = NULL;
1145
1146 /* check the id exists */
1147 g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
1148 g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
1149
1150 /* create helper object */
1151 helper = g_new0 (FuMainAuthHelper, 1);
1152 helper->invocation = g_object_ref (invocation);
1153 helper->remote_id = g_strdup (remote_id);
1154 helper->key = g_strdup (key);
1155 helper->value = g_strdup (value);
1156 helper->priv = priv;
1157
1158 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001159 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughesa6bd5582017-09-07 14:32:22 +01001160 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001161 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughesa6bd5582017-09-07 14:32:22 +01001162 "org.freedesktop.fwupd.modify-remote",
1163 NULL,
1164 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1165 NULL,
1166 fu_main_authorize_modify_remote_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001167 g_steal_pointer (&helper));
Richard Hughesa6bd5582017-09-07 14:32:22 +01001168 return;
1169 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001170 if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001171 const gchar *device_id = NULL;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001172 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes29c220d2016-12-14 17:09:54 +00001173 g_autoptr(PolkitSubject) subject = NULL;
1174
1175 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001176 g_variant_get (parameters, "(&s)", &device_id);
1177 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001178 if (!fu_main_device_id_valid (device_id, &error)) {
1179 g_dbus_method_invocation_return_gerror (invocation, error);
1180 return;
1181 }
Richard Hughes29c220d2016-12-14 17:09:54 +00001182
Richard Hughes9945edb2017-06-19 10:03:55 +01001183 /* create helper object */
Richard Hughes29c220d2016-12-14 17:09:54 +00001184 helper = g_new0 (FuMainAuthHelper, 1);
Richard Hughes29c220d2016-12-14 17:09:54 +00001185 helper->invocation = g_object_ref (invocation);
Richard Hughes9945edb2017-06-19 10:03:55 +01001186 helper->device_id = g_strdup (device_id);
Richard Hughes29c220d2016-12-14 17:09:54 +00001187 helper->priv = priv;
Richard Hughes29c220d2016-12-14 17:09:54 +00001188
1189 /* authenticate */
Richard Hughes87f8a4a2017-10-02 09:42:06 +01001190 fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
Richard Hughes29c220d2016-12-14 17:09:54 +00001191 subject = polkit_system_bus_name_new (sender);
Mario Limonciello6b9f07c2018-04-16 13:52:09 -05001192 polkit_authority_check_authorization (priv->authority, subject,
Richard Hughes29c220d2016-12-14 17:09:54 +00001193 "org.freedesktop.fwupd.verify-update",
1194 NULL,
1195 POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
1196 NULL,
Richard Hughes9945edb2017-06-19 10:03:55 +01001197 fu_main_authorize_verify_update_cb,
Richard Hughes747b9ee2018-04-16 16:46:58 +01001198 g_steal_pointer (&helper));
Richard Hughes29c220d2016-12-14 17:09:54 +00001199 return;
1200 }
Richard Hughesa043c2e2015-06-29 08:43:18 +01001201 if (g_strcmp0 (method_name, "Verify") == 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001202 const gchar *device_id = NULL;
1203 g_variant_get (parameters, "(&s)", &device_id);
1204 g_debug ("Called %s(%s)", method_name, device_id);
Richard Hughesb6f79552017-11-11 07:58:17 +00001205 if (!fu_main_device_id_valid (device_id, &error)) {
1206 g_dbus_method_invocation_return_gerror (invocation, error);
1207 return;
1208 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001209 if (!fu_engine_verify (priv->engine, device_id, &error)) {
1210 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001211 return;
1212 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001213 g_dbus_method_invocation_return_value (invocation, NULL);
Richard Hughesa043c2e2015-06-29 08:43:18 +01001214 return;
1215 }
Richard Hughes63a407a2015-07-22 08:54:14 +01001216 if (g_strcmp0 (method_name, "Install") == 0) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001217 GVariant *prop_value;
Richard Hughes9945edb2017-06-19 10:03:55 +01001218 const gchar *device_id = NULL;
Richard Hughes74cc2172015-02-27 13:19:46 +00001219 gchar *prop_key;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001220 gint32 fd_handle = 0;
1221 gint fd;
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001222 guint64 archive_size_max;
Richard Hughes9945edb2017-06-19 10:03:55 +01001223 GDBusMessage *message;
1224 GUnixFDList *fd_list;
Richard Hughes747b9ee2018-04-16 16:46:58 +01001225 g_autoptr(FuMainAuthHelper) helper = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001226 g_autoptr(GVariantIter) iter = NULL;
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001227
1228 /* check the id exists */
Richard Hughes9945edb2017-06-19 10:03:55 +01001229 g_variant_get (parameters, "(&sha{sv})", &device_id, &fd_handle, &iter);
1230 g_debug ("Called %s(%s,%i)", method_name, device_id, fd_handle);
Richard Hughesb6f79552017-11-11 07:58:17 +00001231 if (!fu_main_device_id_valid (device_id, &error)) {
1232 g_dbus_method_invocation_return_gerror (invocation, error);
1233 return;
1234 }
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001235
Richard Hughes9945edb2017-06-19 10:03:55 +01001236 /* create helper object */
1237 helper = g_new0 (FuMainAuthHelper, 1);
1238 helper->invocation = g_object_ref (invocation);
1239 helper->device_id = g_strdup (device_id);
1240 helper->priv = priv;
1241
1242 /* get flags */
1243 while (g_variant_iter_next (iter, "{&sv}", &prop_key, &prop_value)) {
Richard Hughes74cc2172015-02-27 13:19:46 +00001244 g_debug ("got option %s", prop_key);
1245 if (g_strcmp0 (prop_key, "offline") == 0 &&
1246 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001247 helper->flags |= FWUPD_INSTALL_FLAG_OFFLINE;
Richard Hughese7c12642015-03-04 20:28:59 +00001248 if (g_strcmp0 (prop_key, "allow-older") == 0 &&
1249 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001250 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_OLDER;
Richard Hughese7c12642015-03-04 20:28:59 +00001251 if (g_strcmp0 (prop_key, "allow-reinstall") == 0 &&
1252 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001253 helper->flags |= FWUPD_INSTALL_FLAG_ALLOW_REINSTALL;
Mario Limonciello71a5b982016-05-10 15:38:53 -05001254 if (g_strcmp0 (prop_key, "force") == 0 &&
1255 g_variant_get_boolean (prop_value) == TRUE)
Richard Hughes9945edb2017-06-19 10:03:55 +01001256 helper->flags |= FWUPD_INSTALL_FLAG_FORCE;
Richard Hughes76e0f942018-05-14 16:24:00 +01001257 if (g_strcmp0 (prop_key, "no-history") == 0 &&
1258 g_variant_get_boolean (prop_value) == TRUE)
1259 helper->flags |= FWUPD_INSTALL_FLAG_NO_HISTORY;
Richard Hughes1ffde6c2015-03-02 22:44:48 +00001260 g_variant_unref (prop_value);
Richard Hughes74cc2172015-02-27 13:19:46 +00001261 }
1262
Richard Hughes9945edb2017-06-19 10:03:55 +01001263
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001264 /* get the fd */
1265 message = g_dbus_method_invocation_get_message (invocation);
1266 fd_list = g_dbus_message_get_unix_fd_list (message);
1267 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001268 g_set_error (&error,
1269 FWUPD_ERROR,
1270 FWUPD_ERROR_INTERNAL,
1271 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001272 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001273 return;
1274 }
Richard Hughes7419e962016-11-22 19:48:06 +00001275 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001276 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001277 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001278 return;
1279 }
1280
Richard Hughes9945edb2017-06-19 10:03:55 +01001281 /* parse the cab file before authenticating so we can work out
1282 * what action ID to use, for instance, if this is trusted --
1283 * this will also close the fd when done */
Richard Hughesc7bbbc22018-01-02 22:22:25 +00001284 archive_size_max = fu_engine_get_archive_size_max (priv->engine);
1285 helper->blob_cab = fu_common_get_contents_fd (fd, archive_size_max, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001286 if (helper->blob_cab == NULL) {
1287 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes5d14def2015-10-07 17:43:10 +01001288 return;
1289 }
Richard Hughes4ad41f02018-05-08 14:35:36 +01001290
1291 /* install all the things in the store */
1292 helper->subject = polkit_system_bus_name_new (sender);
1293 if (!fu_main_install_with_helper (g_steal_pointer (&helper), &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001294 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes18423292015-03-09 17:10:50 +00001295 return;
1296 }
1297
Richard Hughes4ad41f02018-05-08 14:35:36 +01001298 /* async return */
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001299 return;
1300 }
Richard Hughes07f963a2017-09-15 14:28:47 +01001301 if (g_strcmp0 (method_name, "GetDetails") == 0) {
Richard Hughes7289a6b2016-05-29 09:27:47 +01001302 GDBusMessage *message;
1303 GUnixFDList *fd_list;
1304 gint32 fd_handle = 0;
1305 gint fd;
Richard Hughes9945edb2017-06-19 10:03:55 +01001306 g_autoptr(GPtrArray) results = NULL;
Richard Hughes7289a6b2016-05-29 09:27:47 +01001307
1308 /* get parameters */
1309 g_variant_get (parameters, "(h)", &fd_handle);
1310 g_debug ("Called %s(%i)", method_name, fd_handle);
1311
1312 /* get the fd */
1313 message = g_dbus_method_invocation_get_message (invocation);
1314 fd_list = g_dbus_message_get_unix_fd_list (message);
1315 if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
Richard Hughes060af612016-08-17 17:32:34 +01001316 g_set_error (&error,
1317 FWUPD_ERROR,
1318 FWUPD_ERROR_INTERNAL,
1319 "invalid handle");
Richard Hughes9945edb2017-06-19 10:03:55 +01001320 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001321 return;
1322 }
Richard Hughes7419e962016-11-22 19:48:06 +00001323 fd = g_unix_fd_list_get (fd_list, 0, &error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001324 if (fd < 0) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001325 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001326 return;
1327 }
1328
Richard Hughes9945edb2017-06-19 10:03:55 +01001329 /* get details about the file (will close the fd when done) */
Richard Hughes07f963a2017-09-15 14:28:47 +01001330 results = fu_engine_get_details (priv->engine, fd, &error);
Richard Hughes9945edb2017-06-19 10:03:55 +01001331 if (results == NULL) {
1332 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001333 return;
1334 }
Richard Hughes9945edb2017-06-19 10:03:55 +01001335 val = fu_main_result_array_to_variant (results);
1336 g_dbus_method_invocation_return_value (invocation, val);
Richard Hughes7289a6b2016-05-29 09:27:47 +01001337 return;
1338 }
Richard Hughes060af612016-08-17 17:32:34 +01001339 g_set_error (&error,
1340 G_DBUS_ERROR,
1341 G_DBUS_ERROR_UNKNOWN_METHOD,
1342 "no such method %s", method_name);
Richard Hughes9945edb2017-06-19 10:03:55 +01001343 g_dbus_method_invocation_return_gerror (invocation, error);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001344}
1345
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001346static GVariant *
1347fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
1348 const gchar *object_path, const gchar *interface_name,
1349 const gchar *property_name, GError **error,
1350 gpointer user_data)
1351{
Richard Hughes773ce982015-03-09 22:40:57 +00001352 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1353
Richard Hughes75b965d2018-11-15 13:51:21 +00001354 /* activity */
1355 fu_engine_idle_reset (priv->engine);
1356
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001357 if (g_strcmp0 (property_name, "DaemonVersion") == 0)
1358 return g_variant_new_string (VERSION);
1359
Richard Hughesf425d292019-01-18 17:57:39 +00001360 if (g_strcmp0 (property_name, "Tainted") == 0)
1361 return g_variant_new_boolean (fu_engine_get_tainted (priv->engine));
1362
Richard Hughes773ce982015-03-09 22:40:57 +00001363 if (g_strcmp0 (property_name, "Status") == 0)
Richard Hughes9945edb2017-06-19 10:03:55 +01001364 return g_variant_new_uint32 (fu_engine_get_status (priv->engine));
Richard Hughes773ce982015-03-09 22:40:57 +00001365
Mario Limonciello20cc9ee2019-09-05 07:27:26 -05001366 if (g_strcmp0 (property_name, "HostProduct") == 0)
1367 return g_variant_new_string (fu_engine_get_host_product (priv->engine));
1368
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001369 /* return an error */
1370 g_set_error (error,
Richard Hughes8645ec92015-03-19 10:14:32 +00001371 G_DBUS_ERROR,
1372 G_DBUS_ERROR_UNKNOWN_PROPERTY,
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001373 "failed to get daemon property %s",
1374 property_name);
1375 return NULL;
1376}
1377
Richard Hughesfd468842015-04-22 16:44:08 +01001378static void
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001379fu_main_on_bus_acquired_cb (GDBusConnection *connection,
1380 const gchar *name,
1381 gpointer user_data)
1382{
1383 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1384 guint registration_id;
Richard Hughes46832432015-09-11 13:43:15 +01001385 g_autoptr(GError) error = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001386 static const GDBusInterfaceVTable interface_vtable = {
1387 fu_main_daemon_method_call,
1388 fu_main_daemon_get_property,
1389 NULL
1390 };
1391
1392 priv->connection = g_object_ref (connection);
1393 registration_id = g_dbus_connection_register_object (connection,
1394 FWUPD_DBUS_PATH,
1395 priv->introspection_daemon->interfaces[0],
1396 &interface_vtable,
1397 priv, /* user_data */
1398 NULL, /* user_data_free_func */
1399 NULL); /* GError** */
1400 g_assert (registration_id > 0);
Richard Hughes18423292015-03-09 17:10:50 +00001401
1402 /* connect to D-Bus directly */
1403 priv->proxy_uid =
1404 g_dbus_proxy_new_sync (priv->connection,
1405 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
1406 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
1407 NULL,
1408 "org.freedesktop.DBus",
1409 "/org/freedesktop/DBus",
1410 "org.freedesktop.DBus",
1411 NULL,
1412 &error);
1413 if (priv->proxy_uid == NULL) {
1414 g_warning ("cannot connect to DBus: %s", error->message);
1415 return;
1416 }
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001417}
1418
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001419static void
1420fu_main_on_name_acquired_cb (GDBusConnection *connection,
1421 const gchar *name,
1422 gpointer user_data)
1423{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001424 g_debug ("FuMain: acquired name: %s", name);
1425}
1426
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001427static void
1428fu_main_on_name_lost_cb (GDBusConnection *connection,
1429 const gchar *name,
1430 gpointer user_data)
1431{
1432 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1433 g_debug ("FuMain: lost name: %s", name);
1434 g_main_loop_quit (priv->loop);
1435}
1436
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001437static gboolean
1438fu_main_timed_exit_cb (gpointer user_data)
1439{
1440 GMainLoop *loop = (GMainLoop *) user_data;
1441 g_main_loop_quit (loop);
1442 return G_SOURCE_REMOVE;
1443}
1444
Richard Hughesf3dc1622019-03-27 12:48:39 +00001445static void
1446fu_main_argv_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file,
1447 GFileMonitorEvent event_type, gpointer user_data)
1448{
1449 FuMainPrivate *priv = (FuMainPrivate *) user_data;
1450
1451 /* can do straight away? */
1452 if (priv->update_in_progress) {
1453 g_warning ("binary changed during a firmware update, ignoring");
1454 return;
1455 }
1456 g_debug ("binary changed, shutting down");
1457 g_main_loop_quit (priv->loop);
1458}
1459
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001460static GDBusNodeInfo *
1461fu_main_load_introspection (const gchar *filename, GError **error)
1462{
Richard Hughes46832432015-09-11 13:43:15 +01001463 g_autoptr(GBytes) data = NULL;
1464 g_autofree gchar *path = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001465
1466 /* lookup data */
1467 path = g_build_filename ("/org/freedesktop/fwupd", filename, NULL);
1468 data = g_resource_lookup_data (fu_get_resource (),
1469 path,
1470 G_RESOURCE_LOOKUP_FLAGS_NONE,
1471 error);
1472 if (data == NULL)
1473 return NULL;
1474
1475 /* build introspection from XML */
1476 return g_dbus_node_info_new_for_xml (g_bytes_get_data (data, NULL), error);
1477}
1478
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001479static void
1480fu_main_private_free (FuMainPrivate *priv)
1481{
1482 if (priv->loop != NULL)
1483 g_main_loop_unref (priv->loop);
1484 if (priv->owner_id > 0)
1485 g_bus_unown_name (priv->owner_id);
1486 if (priv->proxy_uid != NULL)
1487 g_object_unref (priv->proxy_uid);
Richard Hughes9945edb2017-06-19 10:03:55 +01001488 if (priv->engine != NULL)
1489 g_object_unref (priv->engine);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001490 if (priv->connection != NULL)
1491 g_object_unref (priv->connection);
1492 if (priv->authority != NULL)
1493 g_object_unref (priv->authority);
Richard Hughesf3dc1622019-03-27 12:48:39 +00001494 if (priv->argv0_monitor != NULL)
1495 g_object_unref (priv->argv0_monitor);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001496 if (priv->introspection_daemon != NULL)
1497 g_dbus_node_info_unref (priv->introspection_daemon);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001498 g_free (priv);
1499}
1500
Mario Limoncielloa98df552018-04-16 12:15:51 -05001501#pragma clang diagnostic push
1502#pragma clang diagnostic ignored "-Wunused-function"
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001503G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuMainPrivate, fu_main_private_free)
Mario Limoncielloa98df552018-04-16 12:15:51 -05001504#pragma clang diagnostic pop
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001505
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001506int
1507main (int argc, char *argv[])
1508{
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001509 gboolean immediate_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001510 gboolean timed_exit = FALSE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001511 const GOptionEntry options[] = {
1512 { "timed-exit", '\0', 0, G_OPTION_ARG_NONE, &timed_exit,
1513 /* TRANSLATORS: exit after we've started up, used for user profiling */
1514 _("Exit after a small delay"), NULL },
1515 { "immediate-exit", '\0', 0, G_OPTION_ARG_NONE, &immediate_exit,
1516 /* TRANSLATORS: exit straight away, used for automatic profiling */
1517 _("Exit after the engine has loaded"), NULL },
1518 { NULL}
1519 };
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001520 g_autoptr(FuMainPrivate) priv = NULL;
Richard Hughes46832432015-09-11 13:43:15 +01001521 g_autoptr(GError) error = NULL;
Richard Hughesf3dc1622019-03-27 12:48:39 +00001522 g_autoptr(GFile) argv0_file = g_file_new_for_path (argv[0]);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001523 g_autoptr(GOptionContext) context = NULL;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001524
1525 setlocale (LC_ALL, "");
1526
1527 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1528 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1529 textdomain (GETTEXT_PACKAGE);
1530
1531 /* TRANSLATORS: program name */
Richard Hughes63a407a2015-07-22 08:54:14 +01001532 g_set_application_name (_("Firmware Update Daemon"));
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001533 context = g_option_context_new (NULL);
1534 g_option_context_add_main_entries (context, options, NULL);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001535 g_option_context_add_group (context, fu_debug_get_option_group ());
Richard Hughes8ded6ca2015-03-16 12:51:36 +00001536 /* TRANSLATORS: program summary */
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001537 g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001538 if (!g_option_context_parse (context, &argc, &argv, &error)) {
1539 g_printerr ("Failed to parse command line: %s\n", error->message);
1540 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001541 }
1542
1543 /* create new objects */
1544 priv = g_new0 (FuMainPrivate, 1);
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001545 priv->loop = g_main_loop_new (NULL, FALSE);
Richard Hughes8bbfdf42015-02-26 22:28:09 +00001546
Richard Hughes9945edb2017-06-19 10:03:55 +01001547 /* load engine */
Richard Hughes5b5f6552018-05-18 10:22:39 +01001548 priv->engine = fu_engine_new (FU_APP_FLAGS_NONE);
Richard Hughes9945edb2017-06-19 10:03:55 +01001549 g_signal_connect (priv->engine, "changed",
1550 G_CALLBACK (fu_main_engine_changed_cb),
1551 priv);
1552 g_signal_connect (priv->engine, "device-added",
1553 G_CALLBACK (fu_main_engine_device_added_cb),
1554 priv);
1555 g_signal_connect (priv->engine, "device-removed",
1556 G_CALLBACK (fu_main_engine_device_removed_cb),
1557 priv);
1558 g_signal_connect (priv->engine, "device-changed",
1559 G_CALLBACK (fu_main_engine_device_changed_cb),
1560 priv);
1561 g_signal_connect (priv->engine, "status-changed",
1562 G_CALLBACK (fu_main_engine_status_changed_cb),
1563 priv);
1564 g_signal_connect (priv->engine, "percentage-changed",
1565 G_CALLBACK (fu_main_engine_percentage_changed_cb),
1566 priv);
Richard Hughesc8cc77c2019-03-07 11:57:24 +00001567 if (!fu_engine_load (priv->engine, FU_ENGINE_LOAD_FLAG_NONE, &error)) {
Richard Hughes9945edb2017-06-19 10:03:55 +01001568 g_printerr ("Failed to load engine: %s\n", error->message);
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001569 return EXIT_FAILURE;
Richard Hughes804c0752015-08-04 14:53:52 +01001570 }
1571
Mario Limonciello6754f5a2018-10-11 10:50:03 -05001572 g_unix_signal_add_full (G_PRIORITY_DEFAULT,
1573 SIGTERM, fu_main_sigterm_cb,
1574 priv, NULL);
1575
Richard Hughesf3dc1622019-03-27 12:48:39 +00001576 /* restart the daemon if the binary gets replaced */
1577 priv->argv0_monitor = g_file_monitor_file (argv0_file, G_FILE_MONITOR_NONE,
1578 NULL, &error);
1579 g_signal_connect (priv->argv0_monitor, "changed",
1580 G_CALLBACK (fu_main_argv_changed_cb), priv);
1581
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001582 /* load introspection from file */
1583 priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
1584 &error);
1585 if (priv->introspection_daemon == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001586 g_printerr ("Failed to load introspection: %s\n", error->message);
1587 return EXIT_FAILURE;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001588 }
1589
Richard Hughesf508e762015-02-27 12:49:36 +00001590 /* get authority */
1591 priv->authority = polkit_authority_get_sync (NULL, &error);
1592 if (priv->authority == NULL) {
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001593 g_printerr ("Failed to load authority: %s\n", error->message);
1594 return EXIT_FAILURE;
Richard Hughesf508e762015-02-27 12:49:36 +00001595 }
1596
Richard Hughesebae3962018-09-09 13:40:49 +01001597 /* own the object */
1598 priv->owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
1599 FWUPD_DBUS_SERVICE,
1600 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
1601 G_BUS_NAME_OWNER_FLAGS_REPLACE,
1602 fu_main_on_bus_acquired_cb,
1603 fu_main_on_name_acquired_cb,
1604 fu_main_on_name_lost_cb,
1605 priv, NULL);
1606
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001607 /* Only timeout and close the mainloop if we have specified it
1608 * on the command line */
1609 if (immediate_exit)
1610 g_idle_add (fu_main_timed_exit_cb, priv->loop);
1611 else if (timed_exit)
1612 g_timeout_add_seconds (5, fu_main_timed_exit_cb, priv->loop);
1613
Mario Limonciello46bb4e92019-01-07 09:44:31 -06001614 g_debug ("Started with locale %s", g_getenv ("LANG"));
1615
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001616 /* wait */
Richard Hughes4619f9f2017-06-14 13:55:30 +01001617 g_message ("Daemon ready for requests");
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001618 g_main_loop_run (priv->loop);
1619
1620 /* success */
Richard Hughesf29a6ee2017-06-02 19:50:37 +01001621 return EXIT_SUCCESS;
Richard Hughes8dbfb1c2015-02-26 13:07:40 +00001622}