Allow configuring URI scheme preferences

This would allow, for instance, only allowing IPFS downloads or preferring
https over http downloads.
This commit is contained in:
Richard Hughes 2021-01-28 10:59:49 +00:00
parent 200990f3f7
commit b856f0bc42
4 changed files with 82 additions and 0 deletions

View File

@ -36,3 +36,9 @@ ApprovedFirmware=
# Allow blocking specific devices by their checksum, either SHA1 or SHA256 # Allow blocking specific devices by their checksum, either SHA1 or SHA256
# Uses semicolons as delimiter # Uses semicolons as delimiter
BlockedFirmware= BlockedFirmware=
# Allowed URI schemes in the preference order; failed downloads from the first
# scheme will be retried with the next in order until no choices remain.
#
# If unset or no schemes are listed, the default will be: file,https,http,ipfs
UriSchemes=

View File

@ -31,6 +31,7 @@ struct _FuConfig
GPtrArray *disabled_plugins; /* (element-type utf-8) */ GPtrArray *disabled_plugins; /* (element-type utf-8) */
GPtrArray *approved_firmware; /* (element-type utf-8) */ GPtrArray *approved_firmware; /* (element-type utf-8) */
GPtrArray *blocked_firmware; /* (element-type utf-8) */ GPtrArray *blocked_firmware; /* (element-type utf-8) */
GPtrArray *uri_schemes; /* (element-type utf-8) */
guint64 archive_size_max; guint64 archive_size_max;
guint idle_timeout; guint idle_timeout;
gchar *config_file; gchar *config_file;
@ -54,6 +55,7 @@ fu_config_reload (FuConfig *self, GError **error)
guint idle_timeout; guint idle_timeout;
g_auto(GStrv) approved_firmware = NULL; g_auto(GStrv) approved_firmware = NULL;
g_auto(GStrv) blocked_firmware = NULL; g_auto(GStrv) blocked_firmware = NULL;
g_auto(GStrv) uri_schemes = NULL;
g_auto(GStrv) devices = NULL; g_auto(GStrv) devices = NULL;
g_auto(GStrv) plugins = NULL; g_auto(GStrv) plugins = NULL;
g_autofree gchar *domains = NULL; g_autofree gchar *domains = NULL;
@ -122,6 +124,26 @@ fu_config_reload (FuConfig *self, GError **error)
} }
} }
/* get download schemes */
g_ptr_array_set_size (self->uri_schemes, 0);
uri_schemes = g_key_file_get_string_list (keyfile,
"fwupd",
"UriSchemes",
NULL, /* length */
NULL);
if (uri_schemes != NULL) {
for (guint i = 0; uri_schemes[i] != NULL; i++) {
g_ptr_array_add (self->uri_schemes,
g_strdup (uri_schemes[i]));
}
}
if (self->uri_schemes->len == 0) {
g_ptr_array_add (self->uri_schemes, g_strdup ("file"));
g_ptr_array_add (self->uri_schemes, g_strdup ("https"));
g_ptr_array_add (self->uri_schemes, g_strdup ("http"));
g_ptr_array_add (self->uri_schemes, g_strdup ("ipfs"));
}
/* get maximum archive size, defaulting to something sane */ /* get maximum archive size, defaulting to something sane */
archive_size_max = g_key_file_get_uint64 (keyfile, archive_size_max = g_key_file_get_uint64 (keyfile,
"fwupd", "fwupd",
@ -263,6 +285,24 @@ fu_config_get_blocked_firmware (FuConfig *self)
return self->blocked_firmware; return self->blocked_firmware;
} }
guint
fu_config_get_uri_scheme_prio (FuConfig *self, const gchar *scheme)
{
#if GLIB_CHECK_VERSION(2,54,0)
guint idx = G_MAXUINT;
g_ptr_array_find_with_equal_func (self->uri_schemes,
scheme, g_str_equal, &idx);
return idx;
#else
for (guint i = 0; i < self->uri_schemes->len; i++)
const gchar *scheme_tmp = g_ptr_array_index (self->uri_schemes, i);
if (g_str_equal (scheme_tmp, scheme))
return i;
}
return G_MAXUINT;
#endif
}
guint64 guint64
fu_config_get_archive_size_max (FuConfig *self) fu_config_get_archive_size_max (FuConfig *self)
{ {
@ -318,6 +358,7 @@ fu_config_init (FuConfig *self)
self->disabled_plugins = g_ptr_array_new_with_free_func (g_free); self->disabled_plugins = g_ptr_array_new_with_free_func (g_free);
self->approved_firmware = g_ptr_array_new_with_free_func (g_free); self->approved_firmware = g_ptr_array_new_with_free_func (g_free);
self->blocked_firmware = g_ptr_array_new_with_free_func (g_free); self->blocked_firmware = g_ptr_array_new_with_free_func (g_free);
self->uri_schemes = g_ptr_array_new_with_free_func (g_free);
} }
static void static void
@ -333,6 +374,7 @@ fu_config_finalize (GObject *obj)
g_ptr_array_unref (self->disabled_plugins); g_ptr_array_unref (self->disabled_plugins);
g_ptr_array_unref (self->approved_firmware); g_ptr_array_unref (self->approved_firmware);
g_ptr_array_unref (self->blocked_firmware); g_ptr_array_unref (self->blocked_firmware);
g_ptr_array_unref (self->uri_schemes);
g_free (self->config_file); g_free (self->config_file);
G_OBJECT_CLASS (fu_config_parent_class)->finalize (obj); G_OBJECT_CLASS (fu_config_parent_class)->finalize (obj);

View File

@ -27,5 +27,7 @@ GPtrArray *fu_config_get_disabled_devices (FuConfig *self);
GPtrArray *fu_config_get_disabled_plugins (FuConfig *self); GPtrArray *fu_config_get_disabled_plugins (FuConfig *self);
GPtrArray *fu_config_get_approved_firmware (FuConfig *self); GPtrArray *fu_config_get_approved_firmware (FuConfig *self);
GPtrArray *fu_config_get_blocked_firmware (FuConfig *self); GPtrArray *fu_config_get_blocked_firmware (FuConfig *self);
guint fu_config_get_uri_scheme_prio (FuConfig *self,
const gchar *protocol);
gboolean fu_config_get_update_motd (FuConfig *self); gboolean fu_config_get_update_motd (FuConfig *self);
gboolean fu_config_get_enumerate_all_devices (FuConfig *self); gboolean fu_config_get_enumerate_all_devices (FuConfig *self);

View File

@ -325,6 +325,23 @@ fu_engine_get_release_version (FuEngine *self, FuDevice *dev, XbNode *rel, GErro
return fu_common_version_from_uint32 ((guint32) ver_uint32, fmt); return fu_common_version_from_uint32 ((guint32) ver_uint32, fmt);
} }
static gint
fu_engine_scheme_compare_cb (gconstpointer a, gconstpointer b, gpointer user_data)
{
FuEngine *self = FU_ENGINE (user_data);
const gchar *location1 = *((const gchar ** )a);
const gchar *location2 = *((const gchar **) b);
g_autofree gchar *scheme1 = fu_common_uri_get_scheme (location1);
g_autofree gchar *scheme2 = fu_common_uri_get_scheme (location2);
guint prio1 = fu_config_get_uri_scheme_prio (self->config, scheme1);
guint prio2 = fu_config_get_uri_scheme_prio (self->config, scheme2);
if (prio1 < prio2)
return -1;
if (prio1 > prio2)
return 1;
return 0;
}
static gboolean static gboolean
fu_engine_set_release_from_artifact (FuEngine *self, fu_engine_set_release_from_artifact (FuEngine *self,
FwupdRelease *rel, FwupdRelease *rel,
@ -341,6 +358,17 @@ fu_engine_set_release_from_artifact (FuEngine *self,
if (locations != NULL) { if (locations != NULL) {
for (guint i = 0; i < locations->len; i++) { for (guint i = 0; i < locations->len; i++) {
XbNode *n = g_ptr_array_index (locations, i); XbNode *n = g_ptr_array_index (locations, i);
g_autofree gchar *scheme = NULL;
/* check the scheme is allowed */
scheme = fu_common_uri_get_scheme (xb_node_get_text (n));
if (scheme != NULL) {
guint prio = fu_config_get_uri_scheme_prio (self->config, scheme);
if (prio == G_MAXUINT)
continue;
}
/* build the complete URI */
if (remote != NULL) { if (remote != NULL) {
g_autofree gchar *uri = NULL; g_autofree gchar *uri = NULL;
uri = fwupd_remote_build_firmware_uri (remote, uri = fwupd_remote_build_firmware_uri (remote,
@ -530,6 +558,10 @@ fu_engine_set_release_from_appstream (FuEngine *self,
tmp = xb_node_query_text (component, "custom/value[@key='LVFS::UpdateImage']", NULL); tmp = xb_node_query_text (component, "custom/value[@key='LVFS::UpdateImage']", NULL);
if (tmp != NULL) if (tmp != NULL)
fwupd_release_set_update_image (rel, tmp); fwupd_release_set_update_image (rel, tmp);
/* sort the locations by scheme */
g_ptr_array_sort_with_data (fwupd_release_get_locations (rel),
fu_engine_scheme_compare_cb, self);
return TRUE; return TRUE;
} }