diff --git a/libfwupd/fwupd-client.c b/libfwupd/fwupd-client.c
index 15369a927..1d6ab65ef 100644
--- a/libfwupd/fwupd-client.c
+++ b/libfwupd/fwupd-client.c
@@ -1296,6 +1296,61 @@ fwupd_client_get_remotes (FwupdClient *client, GCancellable *cancellable, GError
return fwupd_client_parse_remotes_from_data (val);
}
+/**
+ * fwupd_client_modify_remote:
+ * @client: A #FwupdClient
+ * @remote_id: the remote ID, e.g. "lvfs-testing"
+ * @key: the key, e.g. "Enabled"
+ * @value: the key, e.g. "true"
+ * @cancellable: the #GCancellable, or %NULL
+ * @error: the #GError, or %NULL
+ *
+ * Modifies a system remote in a specific way.
+ *
+ * NOTE: User authentication may be required to complete this action.
+ *
+ * Returns: %TRUE for success
+ *
+ * Since: 0.9.8
+ **/
+gboolean
+fwupd_client_modify_remote (FwupdClient *client,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error)
+{
+ FwupdClientPrivate *priv = GET_PRIVATE (client);
+ g_autoptr(GVariant) val = NULL;
+
+ g_return_val_if_fail (FWUPD_IS_CLIENT (client), FALSE);
+ g_return_val_if_fail (remote_id != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ /* connect */
+ if (!fwupd_client_connect (client, cancellable, error))
+ return FALSE;
+
+ /* call into daemon */
+ val = g_dbus_proxy_call_sync (priv->proxy,
+ "ModifyRemote",
+ g_variant_new ("(sss)", remote_id, key, value),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (val == NULL) {
+ if (error != NULL)
+ fwupd_client_fixup_dbus_error (*error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
static FwupdRemote *
fwupd_client_get_remote_by_id_noref (GPtrArray *remotes, const gchar *remote_id)
{
diff --git a/libfwupd/fwupd-client.h b/libfwupd/fwupd-client.h
index 9fbedfdc1..c4a7f266a 100644
--- a/libfwupd/fwupd-client.h
+++ b/libfwupd/fwupd-client.h
@@ -122,6 +122,12 @@ gboolean fwupd_client_update_metadata_with_id (FwupdClient *client,
const gchar *signature_fn,
GCancellable *cancellable,
GError **error);
+gboolean fwupd_client_modify_remote (FwupdClient *client,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GCancellable *cancellable,
+ GError **error);
FwupdStatus fwupd_client_get_status (FwupdClient *client);
guint fwupd_client_get_percentage (FwupdClient *client);
const gchar *fwupd_client_get_daemon_version (FwupdClient *client);
diff --git a/libfwupd/fwupd-remote.c b/libfwupd/fwupd-remote.c
index 4c7c5ca32..a11780a37 100644
--- a/libfwupd/fwupd-remote.c
+++ b/libfwupd/fwupd-remote.c
@@ -41,6 +41,7 @@ struct _FwupdRemote
gchar *filename_asc;
gchar *filename_cache;
gchar *filename_cache_sig;
+ gchar *filename_source;
gboolean enabled;
SoupURI *uri;
SoupURI *uri_asc;
@@ -104,6 +105,13 @@ fwupd_remote_set_id (FwupdRemote *self, const gchar *id)
g_strdelimit (self->id, ".", '\0');
}
+static void
+fwupd_remote_set_filename_source (FwupdRemote *self, const gchar *filename_source)
+{
+ g_free (self->filename_source);
+ self->filename_source = g_strdup (filename_source);
+}
+
static const gchar *
fwupd_remote_get_suffix_for_keyring_kind (FwupdKeyringKind keyring_kind)
{
@@ -350,6 +358,7 @@ fwupd_remote_load_from_filename (FwupdRemote *self,
self->order_after = g_strsplit_set (order_after, ",:;", -1);
/* success */
+ fwupd_remote_set_filename_source (self, filename);
return TRUE;
}
@@ -403,6 +412,23 @@ fwupd_remote_get_filename_cache_sig (FwupdRemote *self)
return self->filename_cache_sig;
}
+/**
+ * fwupd_remote_get_filename_source:
+ * @self: A #FwupdRemote
+ *
+ * Gets the path and filename of the remote itself, typically a `.conf` file.
+ *
+ * Returns: a string, or %NULL for unset
+ *
+ * Since: 0.9.8
+ **/
+const gchar *
+fwupd_remote_get_filename_source (FwupdRemote *self)
+{
+ g_return_val_if_fail (FWUPD_IS_REMOTE (self), NULL);
+ return self->filename_source;
+}
+
/**
* fwupd_remote_get_priority:
* @self: A #FwupdRemote
@@ -767,6 +793,10 @@ fwupd_remote_to_variant_builder (FwupdRemote *self, GVariantBuilder *builder)
g_variant_builder_add (builder, "{sv}", "FilenameCache",
g_variant_new_string (self->filename_cache));
}
+ if (self->filename_source != NULL) {
+ g_variant_builder_add (builder, "{sv}", "FilenameSource",
+ g_variant_new_string (self->filename_source));
+ }
g_variant_builder_add (builder, "{sv}", "Enabled",
g_variant_new_boolean (self->enabled));
}
@@ -793,6 +823,8 @@ fwupd_remote_set_from_variant_iter (FwupdRemote *self, GVariantIter *iter)
fwupd_remote_set_metadata_uri (self, g_variant_get_string (value, NULL));
if (g_strcmp0 (key, "FilenameCache") == 0)
fwupd_remote_set_filename_cache (self, g_variant_get_string (value, NULL));
+ if (g_strcmp0 (key, "FilenameSource") == 0)
+ fwupd_remote_set_filename_source (self, g_variant_get_string (value, NULL));
}
while (g_variant_iter_loop (iter3, "{sv}", &key, &value)) {
if (g_strcmp0 (key, "Username") == 0) {
@@ -932,6 +964,7 @@ fwupd_remote_finalize (GObject *obj)
g_free (self->filename_asc);
g_free (self->filename_cache);
g_free (self->filename_cache_sig);
+ g_free (self->filename_source);
g_strfreev (self->order_after);
g_strfreev (self->order_before);
if (self->uri != NULL)
diff --git a/libfwupd/fwupd-remote.h b/libfwupd/fwupd-remote.h
index 2f7171770..33aa82089 100644
--- a/libfwupd/fwupd-remote.h
+++ b/libfwupd/fwupd-remote.h
@@ -50,6 +50,7 @@ const gchar *fwupd_remote_get_username (FwupdRemote *self);
const gchar *fwupd_remote_get_password (FwupdRemote *self);
const gchar *fwupd_remote_get_filename_cache (FwupdRemote *self);
const gchar *fwupd_remote_get_filename_cache_sig (FwupdRemote *self);
+const gchar *fwupd_remote_get_filename_source (FwupdRemote *self);
const gchar *fwupd_remote_get_firmware_base_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_metadata_uri (FwupdRemote *self);
const gchar *fwupd_remote_get_metadata_uri_sig (FwupdRemote *self);
diff --git a/policy/org.freedesktop.fwupd.policy.in b/policy/org.freedesktop.fwupd.policy.in
index c157e65f0..04d2c6370 100644
--- a/policy/org.freedesktop.fwupd.policy.in
+++ b/policy/org.freedesktop.fwupd.policy.in
@@ -101,4 +101,15 @@
+
+ Modify a configured remote
+
+ Authentication is required to modify a configured remote used for firmware updates
+
+ auth_admin
+ no
+ auth_admin_keep
+
+
+
diff --git a/src/fu-engine.c b/src/fu-engine.c
index 0a01058d8..a5837a8d0 100644
--- a/src/fu-engine.c
+++ b/src/fu-engine.c
@@ -496,6 +496,61 @@ fu_engine_load_verify_store (GError **error)
return g_steal_pointer (&store);
}
+/**
+ * fu_engine_modify_remote:
+ * @self: A #FuEngine
+ * @remote_id: A remote ID
+ * @key: the key, e.g. "Enabled"
+ * @value: the key, e.g. "true"
+ * @error: A #GError, or %NULL
+ *
+ * Updates the verification store entry for a specific device.
+ *
+ * Returns: %TRUE for success
+ **/
+gboolean
+fu_engine_modify_remote (FuEngine *self,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GError **error)
+{
+ FwupdRemote *remote;
+ const gchar *filename;
+ const gchar *keys[] = { "Enabled", "MetadataURI", "FirmwareBaseURI", NULL };
+ g_autoptr(GKeyFile) keyfile = g_key_file_new ();
+
+ /* check remote is valid */
+ remote = fu_config_get_remote_by_id (self->config, remote_id);
+ if (remote == NULL) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "remote %s not found", remote_id);
+ return FALSE;
+ }
+
+ /* check keys are valid */
+ if (!g_strv_contains (keys, key)) {
+ g_set_error (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_NOT_FOUND,
+ "key %s not supported", key);
+ return FALSE;
+ }
+
+ /* modify the remote filename */
+ filename = fwupd_remote_get_filename_source (remote);
+ if (!g_key_file_load_from_file (keyfile, filename,
+ G_KEY_FILE_KEEP_COMMENTS,
+ error)) {
+ g_prefix_error (error, "failed to load %s: ", filename);
+ return FALSE;
+ }
+ g_key_file_set_string (keyfile, "fwupd Remote", key, value);
+ return g_key_file_save_to_file (keyfile, filename, error);
+}
+
/**
* fu_engine_verify_update:
* @self: A #FuEngine
diff --git a/src/fu-engine.h b/src/fu-engine.h
index 027f6bfe9..5e8dbb403 100644
--- a/src/fu-engine.h
+++ b/src/fu-engine.h
@@ -80,6 +80,11 @@ gboolean fu_engine_verify (FuEngine *self,
gboolean fu_engine_verify_update (FuEngine *self,
const gchar *device_id,
GError **error);
+gboolean fu_engine_modify_remote (FuEngine *self,
+ const gchar *remote_id,
+ const gchar *key,
+ const gchar *value,
+ GError **error);
gboolean fu_engine_install (FuEngine *self,
const gchar *device_id,
AsStore *store,
diff --git a/src/fu-main.c b/src/fu-main.c
index cf066291b..6adef59a2 100644
--- a/src/fu-main.c
+++ b/src/fu-main.c
@@ -242,6 +242,9 @@ typedef struct {
GBytes *blob_cab;
FuMainPrivate *priv;
gchar *device_id;
+ gchar *remote_id;
+ gchar *key;
+ gchar *value;
} FuMainAuthHelper;
static void
@@ -252,6 +255,9 @@ fu_main_auth_helper_free (FuMainAuthHelper *helper)
if (helper->store != NULL)
g_object_unref (helper->store);
g_free (helper->device_id);
+ g_free (helper->remote_id);
+ g_free (helper->key);
+ g_free (helper->value);
g_object_unref (helper->invocation);
g_free (helper);
}
@@ -336,6 +342,35 @@ fu_main_authorize_verify_update_cb (GObject *source, GAsyncResult *res, gpointer
g_dbus_method_invocation_return_value (helper->invocation, NULL);
}
+static void
+fu_main_authorize_modify_remote_cb (GObject *source, GAsyncResult *res, gpointer user_data)
+{
+ g_autoptr(FuMainAuthHelper) helper = (FuMainAuthHelper *) user_data;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(PolkitAuthorizationResult) auth = NULL;
+
+ /* get result */
+ auth = polkit_authority_check_authorization_finish (POLKIT_AUTHORITY (source),
+ res, &error);
+ if (!fu_main_authorization_is_valid (auth, &error)) {
+ g_dbus_method_invocation_return_gerror (helper->invocation, error);
+ return;
+ }
+
+ /* authenticated */
+ if (!fu_engine_modify_remote (helper->priv->engine,
+ helper->remote_id,
+ helper->key,
+ helper->value,
+ &error)) {
+ g_dbus_method_invocation_return_gerror (helper->invocation, error);
+ return;
+ }
+
+ /* success */
+ g_dbus_method_invocation_return_value (helper->invocation, NULL);
+}
+
static void
fu_main_authorize_install_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
@@ -516,6 +551,36 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
helper);
return;
}
+ if (g_strcmp0 (method_name, "ModifyRemote") == 0) {
+ FuMainAuthHelper *helper;
+ const gchar *remote_id = NULL;
+ const gchar *key = NULL;
+ const gchar *value = NULL;
+ g_autoptr(PolkitSubject) subject = NULL;
+
+ /* check the id exists */
+ g_variant_get (parameters, "(&s&s&s)", &remote_id, &key, &value);
+ g_debug ("Called %s(%s,%s=%s)", method_name, remote_id, key, value);
+
+ /* create helper object */
+ helper = g_new0 (FuMainAuthHelper, 1);
+ helper->invocation = g_object_ref (invocation);
+ helper->remote_id = g_strdup (remote_id);
+ helper->key = g_strdup (key);
+ helper->value = g_strdup (value);
+ helper->priv = priv;
+
+ /* authenticate */
+ subject = polkit_system_bus_name_new (sender);
+ polkit_authority_check_authorization (helper->priv->authority, subject,
+ "org.freedesktop.fwupd.modify-remote",
+ NULL,
+ POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
+ NULL,
+ fu_main_authorize_modify_remote_cb,
+ helper);
+ return;
+ }
if (g_strcmp0 (method_name, "VerifyUpdate") == 0) {
FuMainAuthHelper *helper;
const gchar *device_id = NULL;
diff --git a/src/fu-util.c b/src/fu-util.c
index cbb72c4c9..343768bf2 100644
--- a/src/fu-util.c
+++ b/src/fu-util.c
@@ -1409,6 +1409,21 @@ fu_util_update (FuUtilPrivate *priv, gchar **values, GError **error)
return TRUE;
}
+static gboolean
+fu_util_modify_remote (FuUtilPrivate *priv, gchar **values, GError **error)
+{
+ if (g_strv_length (values) < 3) {
+ g_set_error_literal (error,
+ FWUPD_ERROR,
+ FWUPD_ERROR_INVALID_ARGS,
+ "Invalid arguments: expected REMOTE-ID KEY VALUE");
+ return FALSE;
+ }
+ return fwupd_client_modify_remote (priv->client,
+ values[0], values[1], values[2],
+ NULL, error);
+}
+
static gboolean
fu_util_downgrade (FuUtilPrivate *priv, gchar **values, GError **error)
{
@@ -1737,6 +1752,12 @@ main (int argc, char *argv[])
/* TRANSLATORS: command description */
_("Dump SMBIOS data from a file"),
fu_util_smbios_dump);
+ fu_util_add (priv->cmd_array,
+ "modify-remote",
+ NULL,
+ /* TRANSLATORS: command description */
+ _("Modifies a given remote"),
+ fu_util_modify_remote);
/* do stuff on ctrl+c */
priv->cancellable = g_cancellable_new ();
diff --git a/src/org.freedesktop.fwupd.xml b/src/org.freedesktop.fwupd.xml
index 8f6e25999..0a4df29e7 100644
--- a/src/org.freedesktop.fwupd.xml
+++ b/src/org.freedesktop.fwupd.xml
@@ -339,6 +339,44 @@
+
+
+
+
+
+ Modifies a remote in some way.
+
+
+
+
+
+
+
+ Remote ID, e.g. 'lvfs-testing'.
+
+
+
+
+
+
+
+
+ The key, e.g. 'Enabled'.
+
+
+
+
+
+
+
+
+ The value of the correct type, e.g. a URL.
+
+
+
+
+
+