mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-05 22:47:32 +00:00
Allow blocking specific firmware releases by checksum
Fixes https://github.com/fwupd/fwupd/issues/2280
This commit is contained in:
parent
27fd95ae88
commit
3120683143
@ -1,5 +1,6 @@
|
|||||||
_fwupdmgr_cmd_list=(
|
_fwupdmgr_cmd_list=(
|
||||||
'activate'
|
'activate'
|
||||||
|
'block-firmware'
|
||||||
'clear-history'
|
'clear-history'
|
||||||
'clear-offline'
|
'clear-offline'
|
||||||
'clear-results'
|
'clear-results'
|
||||||
@ -7,6 +8,7 @@ _fwupdmgr_cmd_list=(
|
|||||||
'downgrade'
|
'downgrade'
|
||||||
'enable-remote'
|
'enable-remote'
|
||||||
'get-approved-firmware'
|
'get-approved-firmware'
|
||||||
|
'get-blocked-firmware'
|
||||||
'get-details'
|
'get-details'
|
||||||
'get-devices'
|
'get-devices'
|
||||||
'get-history'
|
'get-history'
|
||||||
@ -25,6 +27,7 @@ _fwupdmgr_cmd_list=(
|
|||||||
'security'
|
'security'
|
||||||
'set-approved-firmware'
|
'set-approved-firmware'
|
||||||
'unlock'
|
'unlock'
|
||||||
|
'unblock-firmware'
|
||||||
'update'
|
'update'
|
||||||
'upgrade'
|
'upgrade'
|
||||||
'verify'
|
'verify'
|
||||||
|
@ -32,3 +32,7 @@ EnumerateAllDevices=false
|
|||||||
# A list of firmware checksums that has been approved by the site admin
|
# A list of firmware checksums that has been approved by the site admin
|
||||||
# If unset, all firmware is approved
|
# If unset, all firmware is approved
|
||||||
ApprovedFirmware=
|
ApprovedFirmware=
|
||||||
|
|
||||||
|
# Allow blocking specific devices by their checksum, either SHA1 or SHA256
|
||||||
|
# Uses semicolons as delimiter
|
||||||
|
BlockedFirmware=
|
||||||
|
@ -2128,6 +2128,98 @@ fwupd_client_set_approved_firmware (FwupdClient *client,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fwupd_client_get_blocked_firmware:
|
||||||
|
* @client: A #FwupdClient
|
||||||
|
* @cancellable: the #GCancellable, or %NULL
|
||||||
|
* @error: the #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Gets the list of blocked firmware.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): list of checksums, or %NULL
|
||||||
|
*
|
||||||
|
* Since: 1.4.6
|
||||||
|
**/
|
||||||
|
gchar **
|
||||||
|
fwupd_client_get_blocked_firmware (FwupdClient *client,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FwupdClientPrivate *priv = GET_PRIVATE (client);
|
||||||
|
g_autoptr(GVariant) val = NULL;
|
||||||
|
gchar **retval = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
/* connect */
|
||||||
|
if (!fwupd_client_connect (client, cancellable, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* call into daemon */
|
||||||
|
val = g_dbus_proxy_call_sync (priv->proxy,
|
||||||
|
"GetBlockedFirmware",
|
||||||
|
NULL,
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
if (val == NULL) {
|
||||||
|
if (error != NULL)
|
||||||
|
fwupd_client_fixup_dbus_error (*error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
g_variant_get (val, "(^as)", &retval);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fwupd_client_set_blocked_firmware:
|
||||||
|
* @client: A #FwupdClient
|
||||||
|
* @checksums: Array of checksums
|
||||||
|
* @cancellable: the #GCancellable, or %NULL
|
||||||
|
* @error: the #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Sets the list of blocked firmware.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE for success
|
||||||
|
*
|
||||||
|
* Since: 1.4.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
fwupd_client_set_blocked_firmware (FwupdClient *client,
|
||||||
|
gchar **checksums,
|
||||||
|
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 (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,
|
||||||
|
"SetBlockedFirmware",
|
||||||
|
g_variant_new ("(^as)", checksums),
|
||||||
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1,
|
||||||
|
cancellable,
|
||||||
|
error);
|
||||||
|
if (val == NULL) {
|
||||||
|
if (error != NULL)
|
||||||
|
fwupd_client_fixup_dbus_error (*error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fwupd_client_set_feature_flags:
|
* fwupd_client_set_feature_flags:
|
||||||
* @client: A #FwupdClient
|
* @client: A #FwupdClient
|
||||||
|
@ -205,6 +205,13 @@ gboolean fwupd_client_set_approved_firmware (FwupdClient *client,
|
|||||||
gchar **checksums,
|
gchar **checksums,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
gchar **fwupd_client_get_blocked_firmware (FwupdClient *client,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
gboolean fwupd_client_set_blocked_firmware (FwupdClient *client,
|
||||||
|
gchar **checksums,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
gchar *fwupd_client_self_sign (FwupdClient *client,
|
gchar *fwupd_client_self_sign (FwupdClient *client,
|
||||||
const gchar *value,
|
const gchar *value,
|
||||||
FwupdSelfSignFlags flags,
|
FwupdSelfSignFlags flags,
|
||||||
|
@ -469,6 +469,13 @@ LIBFWUPD_1.4.5 {
|
|||||||
local: *;
|
local: *;
|
||||||
} LIBFWUPD_1.4.1;
|
} LIBFWUPD_1.4.1;
|
||||||
|
|
||||||
|
LIBFWUPD_1.4.6 {
|
||||||
|
global:
|
||||||
|
fwupd_client_get_blocked_firmware;
|
||||||
|
fwupd_client_set_blocked_firmware;
|
||||||
|
local: *;
|
||||||
|
} LIBFWUPD_1.4.5;
|
||||||
|
|
||||||
LIBFWUPD_1.5.0 {
|
LIBFWUPD_1.5.0 {
|
||||||
global:
|
global:
|
||||||
fwupd_client_get_host_security_attrs;
|
fwupd_client_get_host_security_attrs;
|
||||||
@ -508,4 +515,4 @@ LIBFWUPD_1.5.0 {
|
|||||||
fwupd_security_attr_to_string;
|
fwupd_security_attr_to_string;
|
||||||
fwupd_security_attr_to_variant;
|
fwupd_security_attr_to_variant;
|
||||||
local: *;
|
local: *;
|
||||||
} LIBFWUPD_1.4.5;
|
} LIBFWUPD_1.4.6;
|
||||||
|
@ -30,6 +30,7 @@ struct _FuConfig
|
|||||||
GPtrArray *disabled_devices; /* (element-type utf-8) */
|
GPtrArray *disabled_devices; /* (element-type utf-8) */
|
||||||
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) */
|
||||||
guint64 archive_size_max;
|
guint64 archive_size_max;
|
||||||
guint idle_timeout;
|
guint idle_timeout;
|
||||||
gchar *config_file;
|
gchar *config_file;
|
||||||
@ -52,6 +53,7 @@ fu_config_reload (FuConfig *self, GError **error)
|
|||||||
guint64 archive_size_max;
|
guint64 archive_size_max;
|
||||||
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) 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;
|
||||||
@ -106,6 +108,20 @@ fu_config_reload (FuConfig *self, GError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get blocked firmware */
|
||||||
|
g_ptr_array_set_size (self->blocked_firmware, 0);
|
||||||
|
blocked_firmware = g_key_file_get_string_list (keyfile,
|
||||||
|
"fwupd",
|
||||||
|
"BlockedFirmware",
|
||||||
|
NULL, /* length */
|
||||||
|
NULL);
|
||||||
|
if (blocked_firmware != NULL) {
|
||||||
|
for (guint i = 0; blocked_firmware[i] != NULL; i++) {
|
||||||
|
g_ptr_array_add (self->blocked_firmware,
|
||||||
|
g_strdup (blocked_firmware[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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",
|
||||||
@ -227,6 +243,13 @@ fu_config_get_disabled_devices (FuConfig *self)
|
|||||||
return self->disabled_devices;
|
return self->disabled_devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GPtrArray *
|
||||||
|
fu_config_get_blocked_firmware (FuConfig *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (FU_IS_CONFIG (self), NULL);
|
||||||
|
return self->blocked_firmware;
|
||||||
|
}
|
||||||
|
|
||||||
guint64
|
guint64
|
||||||
fu_config_get_archive_size_max (FuConfig *self)
|
fu_config_get_archive_size_max (FuConfig *self)
|
||||||
{
|
{
|
||||||
@ -282,6 +305,7 @@ fu_config_init (FuConfig *self)
|
|||||||
self->disabled_devices = g_ptr_array_new_with_free_func (g_free);
|
self->disabled_devices = g_ptr_array_new_with_free_func (g_free);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -294,6 +318,7 @@ fu_config_finalize (GObject *obj)
|
|||||||
g_ptr_array_unref (self->disabled_devices);
|
g_ptr_array_unref (self->disabled_devices);
|
||||||
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_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);
|
||||||
|
@ -26,5 +26,6 @@ guint fu_config_get_idle_timeout (FuConfig *self);
|
|||||||
GPtrArray *fu_config_get_disabled_devices (FuConfig *self);
|
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);
|
||||||
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);
|
||||||
|
104
src/fu-engine.c
104
src/fu-engine.c
@ -103,6 +103,7 @@ struct _FuEngine
|
|||||||
GHashTable *runtime_versions;
|
GHashTable *runtime_versions;
|
||||||
GHashTable *compile_versions;
|
GHashTable *compile_versions;
|
||||||
GHashTable *approved_firmware; /* (nullable) */
|
GHashTable *approved_firmware; /* (nullable) */
|
||||||
|
GHashTable *blocked_firmware; /* (nullable) */
|
||||||
GHashTable *firmware_gtypes;
|
GHashTable *firmware_gtypes;
|
||||||
gchar *host_machine_id;
|
gchar *host_machine_id;
|
||||||
JcatContext *jcat_context;
|
JcatContext *jcat_context;
|
||||||
@ -527,6 +528,7 @@ fu_engine_modify_config (FuEngine *self, const gchar *key, const gchar *value, G
|
|||||||
const gchar *keys[] = {
|
const gchar *keys[] = {
|
||||||
"ArchiveSizeMax",
|
"ArchiveSizeMax",
|
||||||
"DisabledDevices",
|
"DisabledDevices",
|
||||||
|
"BlockedFirmware",
|
||||||
"DisabledPlugins",
|
"DisabledPlugins",
|
||||||
"IdleTimeout",
|
"IdleTimeout",
|
||||||
"VerboseDomains",
|
"VerboseDomains",
|
||||||
@ -4178,6 +4180,21 @@ fu_engine_check_release_is_approved (FuEngine *self, FwupdRelease *rel)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_engine_check_release_is_blocked (FuEngine *self, FwupdRelease *rel)
|
||||||
|
{
|
||||||
|
GPtrArray *csums = fwupd_release_get_checksums (rel);
|
||||||
|
if (self->blocked_firmware == NULL)
|
||||||
|
return FALSE;
|
||||||
|
for (guint i = 0; i < csums->len; i++) {
|
||||||
|
const gchar *csum = g_ptr_array_index (csums, i);
|
||||||
|
g_debug ("checking %s against blocked list", csum);
|
||||||
|
if (g_hash_table_lookup (self->blocked_firmware, csum) != NULL)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_engine_add_releases_for_device_component (FuEngine *self,
|
fu_engine_add_releases_for_device_component (FuEngine *self,
|
||||||
FuEngineRequest *request,
|
FuEngineRequest *request,
|
||||||
@ -4258,6 +4275,10 @@ fu_engine_add_releases_for_device_component (FuEngine *self,
|
|||||||
fwupd_release_add_flag (rel, FWUPD_RELEASE_FLAG_BLOCKED_VERSION);
|
fwupd_release_add_flag (rel, FWUPD_RELEASE_FLAG_BLOCKED_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* manually blocked */
|
||||||
|
if (fu_engine_check_release_is_blocked (self, rel))
|
||||||
|
fwupd_release_add_flag (rel, FWUPD_RELEASE_FLAG_BLOCKED_APPROVAL);
|
||||||
|
|
||||||
/* check if remote is filtering firmware */
|
/* check if remote is filtering firmware */
|
||||||
remote_id = fwupd_release_get_remote_id (rel);
|
remote_id = fwupd_release_get_remote_id (rel);
|
||||||
if (remote_id != NULL) {
|
if (remote_id != NULL) {
|
||||||
@ -4545,6 +4566,56 @@ fu_engine_add_approved_firmware (FuEngine *self, const gchar *checksum)
|
|||||||
g_hash_table_add (self->approved_firmware, g_strdup (checksum));
|
g_hash_table_add (self->approved_firmware, g_strdup (checksum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GPtrArray *
|
||||||
|
fu_engine_get_blocked_firmware (FuEngine *self)
|
||||||
|
{
|
||||||
|
GPtrArray *checksums = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
if (self->blocked_firmware != NULL) {
|
||||||
|
g_autoptr(GList) keys = g_hash_table_get_keys (self->blocked_firmware);
|
||||||
|
for (GList *l = keys; l != NULL; l = l->next) {
|
||||||
|
const gchar *csum = l->data;
|
||||||
|
g_ptr_array_add (checksums, g_strdup (csum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checksums;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fu_engine_add_blocked_firmware (FuEngine *self, const gchar *checksum)
|
||||||
|
{
|
||||||
|
if (self->blocked_firmware == NULL) {
|
||||||
|
self->blocked_firmware = g_hash_table_new_full (g_str_hash,
|
||||||
|
g_str_equal,
|
||||||
|
g_free,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
g_hash_table_add (self->blocked_firmware, g_strdup (checksum));
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
fu_engine_set_blocked_firmware (FuEngine *self, GPtrArray *checksums, GError **error)
|
||||||
|
{
|
||||||
|
/* update in-memory hash */
|
||||||
|
if (self->blocked_firmware != NULL) {
|
||||||
|
g_hash_table_unref (self->blocked_firmware);
|
||||||
|
self->blocked_firmware = NULL;
|
||||||
|
}
|
||||||
|
for (guint i = 0; i < checksums->len; i++) {
|
||||||
|
const gchar *csum = g_ptr_array_index (checksums, i);
|
||||||
|
fu_engine_add_blocked_firmware (self, csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* save database */
|
||||||
|
if (!fu_history_clear_blocked_firmware (self->history, error))
|
||||||
|
return FALSE;
|
||||||
|
for (guint i = 0; i < checksums->len; i++) {
|
||||||
|
const gchar *csum = g_ptr_array_index (checksums, i);
|
||||||
|
if (!fu_history_add_blocked_firmware (self->history, csum, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gchar *
|
gchar *
|
||||||
fu_engine_self_sign (FuEngine *self,
|
fu_engine_self_sign (FuEngine *self,
|
||||||
const gchar *value,
|
const gchar *value,
|
||||||
@ -6123,7 +6194,8 @@ fu_engine_load (FuEngine *self, FuEngineLoadFlags flags, GError **error)
|
|||||||
{
|
{
|
||||||
FuRemoteListLoadFlags remote_list_flags = FU_REMOTE_LIST_LOAD_FLAG_NONE;
|
FuRemoteListLoadFlags remote_list_flags = FU_REMOTE_LIST_LOAD_FLAG_NONE;
|
||||||
FuQuirksLoadFlags quirks_flags = FU_QUIRKS_LOAD_FLAG_NONE;
|
FuQuirksLoadFlags quirks_flags = FU_QUIRKS_LOAD_FLAG_NONE;
|
||||||
g_autoptr(GPtrArray) checksums = NULL;
|
g_autoptr(GPtrArray) checksums_approved = NULL;
|
||||||
|
g_autoptr(GPtrArray) checksums_blocked = NULL;
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
g_autoptr(GError) error_local = NULL;
|
g_autoptr(GError) error_local = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -6159,21 +6231,33 @@ fu_engine_load (FuEngine *self, FuEngineLoadFlags flags, GError **error)
|
|||||||
/* create client certificate */
|
/* create client certificate */
|
||||||
fu_engine_ensure_client_certificate (self);
|
fu_engine_ensure_client_certificate (self);
|
||||||
|
|
||||||
/* get hardcoded approved firmware */
|
/* get hardcoded approved and blocked firmware */
|
||||||
checksums = fu_config_get_approved_firmware (self->config);
|
checksums_approved = fu_config_get_approved_firmware (self->config);
|
||||||
for (guint i = 0; i < checksums->len; i++) {
|
for (guint i = 0; i < checksums_approved->len; i++) {
|
||||||
const gchar *csum = g_ptr_array_index (checksums, i);
|
const gchar *csum = g_ptr_array_index (checksums_approved, i);
|
||||||
fu_engine_add_approved_firmware (self, csum);
|
fu_engine_add_approved_firmware (self, csum);
|
||||||
}
|
}
|
||||||
|
checksums_blocked = fu_config_get_blocked_firmware (self->config);
|
||||||
|
for (guint i = 0; i < checksums_blocked->len; i++) {
|
||||||
|
const gchar *csum = g_ptr_array_index (checksums_blocked, i);
|
||||||
|
fu_engine_add_blocked_firmware (self, csum);
|
||||||
|
}
|
||||||
|
|
||||||
/* get extra firmware saved to the database */
|
/* get extra firmware saved to the database */
|
||||||
checksums = fu_history_get_approved_firmware (self->history, error);
|
checksums_approved = fu_history_get_approved_firmware (self->history, error);
|
||||||
if (checksums == NULL)
|
if (checksums_approved == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
for (guint i = 0; i < checksums->len; i++) {
|
for (guint i = 0; i < checksums_approved->len; i++) {
|
||||||
const gchar *csum = g_ptr_array_index (checksums, i);
|
const gchar *csum = g_ptr_array_index (checksums_approved, i);
|
||||||
fu_engine_add_approved_firmware (self, csum);
|
fu_engine_add_approved_firmware (self, csum);
|
||||||
}
|
}
|
||||||
|
checksums_blocked = fu_history_get_blocked_firmware (self->history, error);
|
||||||
|
if (checksums_blocked == NULL)
|
||||||
|
return FALSE;
|
||||||
|
for (guint i = 0; i < checksums_blocked->len; i++) {
|
||||||
|
const gchar *csum = g_ptr_array_index (checksums_blocked, i);
|
||||||
|
fu_engine_add_blocked_firmware (self, csum);
|
||||||
|
}
|
||||||
|
|
||||||
/* set up idle exit */
|
/* set up idle exit */
|
||||||
if ((self->app_flags & FU_APP_FLAGS_NO_IDLE_SOURCES) == 0)
|
if ((self->app_flags & FU_APP_FLAGS_NO_IDLE_SOURCES) == 0)
|
||||||
@ -6446,6 +6530,8 @@ fu_engine_finalize (GObject *obj)
|
|||||||
g_source_remove (self->coldplug_id);
|
g_source_remove (self->coldplug_id);
|
||||||
if (self->approved_firmware != NULL)
|
if (self->approved_firmware != NULL)
|
||||||
g_hash_table_unref (self->approved_firmware);
|
g_hash_table_unref (self->approved_firmware);
|
||||||
|
if (self->blocked_firmware != NULL)
|
||||||
|
g_hash_table_unref (self->blocked_firmware);
|
||||||
|
|
||||||
g_free (self->host_machine_id);
|
g_free (self->host_machine_id);
|
||||||
g_free (self->host_security_id);
|
g_free (self->host_security_id);
|
||||||
|
@ -159,6 +159,14 @@ gboolean fu_engine_activate (FuEngine *self,
|
|||||||
GPtrArray *fu_engine_get_approved_firmware (FuEngine *self);
|
GPtrArray *fu_engine_get_approved_firmware (FuEngine *self);
|
||||||
void fu_engine_add_approved_firmware (FuEngine *self,
|
void fu_engine_add_approved_firmware (FuEngine *self,
|
||||||
const gchar *checksum);
|
const gchar *checksum);
|
||||||
|
void fu_engine_set_approved_firmware (FuEngine *self,
|
||||||
|
GPtrArray *checksums);
|
||||||
|
GPtrArray *fu_engine_get_blocked_firmware (FuEngine *self);
|
||||||
|
void fu_engine_add_blocked_firmware (FuEngine *self,
|
||||||
|
const gchar *checksum);
|
||||||
|
gboolean fu_engine_set_blocked_firmware (FuEngine *self,
|
||||||
|
GPtrArray *checksums,
|
||||||
|
GError **error);
|
||||||
gchar *fu_engine_self_sign (FuEngine *self,
|
gchar *fu_engine_self_sign (FuEngine *self,
|
||||||
const gchar *value,
|
const gchar *value,
|
||||||
JcatSignFlags flags,
|
JcatSignFlags flags,
|
||||||
|
163
src/fu-history.c
163
src/fu-history.c
@ -20,7 +20,7 @@
|
|||||||
#include "fu-history.h"
|
#include "fu-history.h"
|
||||||
#include "fu-mutex.h"
|
#include "fu-mutex.h"
|
||||||
|
|
||||||
#define FU_HISTORY_CURRENT_SCHEMA_VERSION 5
|
#define FU_HISTORY_CURRENT_SCHEMA_VERSION 6
|
||||||
|
|
||||||
static void fu_history_finalize (GObject *object);
|
static void fu_history_finalize (GObject *object);
|
||||||
|
|
||||||
@ -181,6 +181,8 @@ fu_history_create_database (FuHistory *self, GError **error)
|
|||||||
"protocol TEXT DEFAULT NULL);"
|
"protocol TEXT DEFAULT NULL);"
|
||||||
"CREATE TABLE IF NOT EXISTS approved_firmware ("
|
"CREATE TABLE IF NOT EXISTS approved_firmware ("
|
||||||
"checksum TEXT);"
|
"checksum TEXT);"
|
||||||
|
"CREATE TABLE IF NOT EXISTS blocked_firmware ("
|
||||||
|
"checksum TEXT);"
|
||||||
"COMMIT;", NULL, NULL, NULL);
|
"COMMIT;", NULL, NULL, NULL);
|
||||||
if (rc != SQLITE_OK) {
|
if (rc != SQLITE_OK) {
|
||||||
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||||
@ -269,6 +271,22 @@ fu_history_migrate_database_v4 (FuHistory *self, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_history_migrate_database_v5 (FuHistory *self, GError **error)
|
||||||
|
{
|
||||||
|
gint rc;
|
||||||
|
rc = sqlite3_exec (self->db,
|
||||||
|
"CREATE TABLE IF NOT EXISTS blocked_firmware (checksum TEXT);",
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||||
|
"Failed to create table: %s",
|
||||||
|
sqlite3_errmsg (self->db));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* returns 0 if database is not initialised */
|
/* returns 0 if database is not initialised */
|
||||||
static guint
|
static guint
|
||||||
fu_history_get_schema_version (FuHistory *self)
|
fu_history_get_schema_version (FuHistory *self)
|
||||||
@ -315,16 +333,26 @@ fu_history_create_or_migrate (FuHistory *self, guint schema_ver, GError **error)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_history_migrate_database_v4 (self, error))
|
if (!fu_history_migrate_database_v4 (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!fu_history_migrate_database_v5 (self, error))
|
||||||
|
return FALSE;
|
||||||
} else if (schema_ver == 3) {
|
} else if (schema_ver == 3) {
|
||||||
g_debug ("migrating v%u database by altering", schema_ver);
|
g_debug ("migrating v%u database by altering", schema_ver);
|
||||||
if (!fu_history_migrate_database_v3 (self, error))
|
if (!fu_history_migrate_database_v3 (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_history_migrate_database_v4 (self, error))
|
if (!fu_history_migrate_database_v4 (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!fu_history_migrate_database_v5 (self, error))
|
||||||
|
return FALSE;
|
||||||
} else if (schema_ver == 4) {
|
} else if (schema_ver == 4) {
|
||||||
g_debug ("migrating v%u database by altering", schema_ver);
|
g_debug ("migrating v%u database by altering", schema_ver);
|
||||||
if (!fu_history_migrate_database_v4 (self, error))
|
if (!fu_history_migrate_database_v4 (self, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!fu_history_migrate_database_v5 (self, error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (schema_ver == 5) {
|
||||||
|
g_debug ("migrating v%u database by altering", schema_ver);
|
||||||
|
if (!fu_history_migrate_database_v5 (self, error))
|
||||||
|
return FALSE;
|
||||||
} else {
|
} else {
|
||||||
/* this is probably okay, but return an error if we ever delete
|
/* this is probably okay, but return an error if we ever delete
|
||||||
* or rename columns */
|
* or rename columns */
|
||||||
@ -1066,6 +1094,139 @@ fu_history_add_approved_firmware (FuHistory *self,
|
|||||||
sqlite3_bind_text (stmt, 1, checksum, -1, SQLITE_STATIC);
|
sqlite3_bind_text (stmt, 1, checksum, -1, SQLITE_STATIC);
|
||||||
return fu_history_stmt_exec (self, stmt, NULL, error);
|
return fu_history_stmt_exec (self, stmt, NULL, error);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* fu_history_get_blocked_firmware:
|
||||||
|
* @self: A #FuHistory
|
||||||
|
* @error: A #GError or NULL
|
||||||
|
*
|
||||||
|
* Returns blocked firmware records.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full) (element-type gchar *): records
|
||||||
|
*
|
||||||
|
* Since: 1.4.6
|
||||||
|
**/
|
||||||
|
GPtrArray *
|
||||||
|
fu_history_get_blocked_firmware (FuHistory *self, GError **error)
|
||||||
|
{
|
||||||
|
gint rc;
|
||||||
|
g_autoptr(GRWLockReaderLocker) locker = NULL;
|
||||||
|
g_autoptr(GPtrArray) array = NULL;
|
||||||
|
g_autoptr(sqlite3_stmt) stmt = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FU_IS_HISTORY (self), NULL);
|
||||||
|
|
||||||
|
/* lazy load */
|
||||||
|
if (self->db == NULL) {
|
||||||
|
if (!fu_history_load (self, error))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get all the blocked firmware */
|
||||||
|
locker = g_rw_lock_reader_locker_new (&self->db_mutex);
|
||||||
|
g_return_val_if_fail (locker != NULL, NULL);
|
||||||
|
rc = sqlite3_prepare_v2 (self->db,
|
||||||
|
"SELECT checksum FROM blocked_firmware;",
|
||||||
|
-1, &stmt, NULL);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||||
|
"Failed to prepare SQL to get checksum: %s",
|
||||||
|
sqlite3_errmsg (self->db));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
array = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
while ((rc = sqlite3_step (stmt)) == SQLITE_ROW) {
|
||||||
|
const gchar *tmp = (const gchar *) sqlite3_column_text (stmt, 0);
|
||||||
|
g_ptr_array_add (array, g_strdup (tmp));
|
||||||
|
}
|
||||||
|
if (rc != SQLITE_DONE) {
|
||||||
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_WRITE,
|
||||||
|
"failed to execute prepared statement: %s",
|
||||||
|
sqlite3_errmsg (self->db));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_steal_pointer (&array);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_history_clear_blocked_firmware:
|
||||||
|
* @self: A #FuHistory
|
||||||
|
* @error: A #GError or NULL
|
||||||
|
*
|
||||||
|
* Clear all blocked firmware records
|
||||||
|
*
|
||||||
|
* Returns: #TRUE for success, #FALSE for failure
|
||||||
|
*
|
||||||
|
* Since: 1.4.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
fu_history_clear_blocked_firmware (FuHistory *self, GError **error)
|
||||||
|
{
|
||||||
|
gint rc;
|
||||||
|
g_autoptr(sqlite3_stmt) stmt = NULL;
|
||||||
|
g_autoptr(GRWLockWriterLocker) locker = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FU_IS_HISTORY (self), FALSE);
|
||||||
|
|
||||||
|
/* lazy load */
|
||||||
|
if (!fu_history_load (self, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* remove entries */
|
||||||
|
locker = g_rw_lock_writer_locker_new (&self->db_mutex);
|
||||||
|
g_return_val_if_fail (locker != NULL, FALSE);
|
||||||
|
rc = sqlite3_prepare_v2 (self->db,
|
||||||
|
"DELETE FROM blocked_firmware;",
|
||||||
|
-1, &stmt, NULL);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||||
|
"Failed to prepare SQL to delete blocked firmware: %s",
|
||||||
|
sqlite3_errmsg (self->db));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return fu_history_stmt_exec (self, stmt, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_history_add_blocked_firmware:
|
||||||
|
* @self: A #FuHistory
|
||||||
|
* @checksum: a string
|
||||||
|
* @error: A #GError or NULL
|
||||||
|
*
|
||||||
|
* Add an blocked firmware record to the database
|
||||||
|
*
|
||||||
|
* Returns: #TRUE for success, #FALSE for failure
|
||||||
|
*
|
||||||
|
* Since: 1.4.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
fu_history_add_blocked_firmware (FuHistory *self, const gchar *checksum, GError **error)
|
||||||
|
{
|
||||||
|
gint rc;
|
||||||
|
g_autoptr(sqlite3_stmt) stmt = NULL;
|
||||||
|
g_autoptr(GRWLockWriterLocker) locker = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FU_IS_HISTORY (self), FALSE);
|
||||||
|
g_return_val_if_fail (checksum != NULL, FALSE);
|
||||||
|
|
||||||
|
/* lazy load */
|
||||||
|
if (!fu_history_load (self, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* add */
|
||||||
|
locker = g_rw_lock_writer_locker_new (&self->db_mutex);
|
||||||
|
g_return_val_if_fail (locker != NULL, FALSE);
|
||||||
|
rc = sqlite3_prepare_v2 (self->db,
|
||||||
|
"INSERT INTO blocked_firmware (checksum) "
|
||||||
|
"VALUES (?1)", -1, &stmt, NULL);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||||
|
"Failed to prepare SQL to insert checksum: %s",
|
||||||
|
sqlite3_errmsg (self->db));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
sqlite3_bind_text (stmt, 1, checksum, -1, SQLITE_STATIC);
|
||||||
|
return fu_history_stmt_exec (self, stmt, NULL, error);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_history_class_init (FuHistoryClass *klass)
|
fu_history_class_init (FuHistoryClass *klass)
|
||||||
|
@ -47,3 +47,10 @@ gboolean fu_history_add_approved_firmware (FuHistory *self,
|
|||||||
GError **error);
|
GError **error);
|
||||||
GPtrArray *fu_history_get_approved_firmware (FuHistory *self,
|
GPtrArray *fu_history_get_approved_firmware (FuHistory *self,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
gboolean fu_history_clear_blocked_firmware (FuHistory *self,
|
||||||
|
GError **error);
|
||||||
|
gboolean fu_history_add_blocked_firmware (FuHistory *self,
|
||||||
|
const gchar *checksum,
|
||||||
|
GError **error);
|
||||||
|
GPtrArray *fu_history_get_blocked_firmware (FuHistory *self,
|
||||||
|
GError **error);
|
||||||
|
@ -430,6 +430,30 @@ fu_main_authorize_set_approved_firmware_cb (GObject *source, GAsyncResult *res,
|
|||||||
g_dbus_method_invocation_return_value (helper->invocation, NULL);
|
g_dbus_method_invocation_return_value (helper->invocation, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_main_authorize_set_blocked_firmware_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 */
|
||||||
|
fu_main_set_status (helper->priv, FWUPD_STATUS_IDLE);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
if (!fu_engine_set_blocked_firmware (helper->priv->engine, helper->checksums, &error)) {
|
||||||
|
g_dbus_method_invocation_return_gerror (helper->invocation, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_dbus_method_invocation_return_value (helper->invocation, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
fu_main_authorize_self_sign_cb (GObject *source, GAsyncResult *res, gpointer user_data)
|
||||||
{
|
{
|
||||||
@ -878,6 +902,19 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
|
|||||||
g_variant_new_tuple (&val, 1));
|
g_variant_new_tuple (&val, 1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (g_strcmp0 (method_name, "GetBlockedFirmware") == 0) {
|
||||||
|
GVariantBuilder builder;
|
||||||
|
GPtrArray *checksums = fu_engine_get_blocked_firmware (priv->engine);
|
||||||
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
for (guint i = 0; i < checksums->len; i++) {
|
||||||
|
const gchar *checksum = g_ptr_array_index (checksums, i);
|
||||||
|
g_variant_builder_add_value (&builder, g_variant_new_string (checksum));
|
||||||
|
}
|
||||||
|
val = g_variant_builder_end (&builder);
|
||||||
|
g_dbus_method_invocation_return_value (invocation,
|
||||||
|
g_variant_new_tuple (&val, 1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
|
if (g_strcmp0 (method_name, "GetReportMetadata") == 0) {
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
GVariantBuilder builder;
|
GVariantBuilder builder;
|
||||||
@ -932,6 +969,35 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
|
|||||||
g_steal_pointer (&helper));
|
g_steal_pointer (&helper));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (g_strcmp0 (method_name, "SetBlockedFirmware") == 0) {
|
||||||
|
g_autofree gchar *checksums_str = NULL;
|
||||||
|
g_auto(GStrv) checksums = NULL;
|
||||||
|
g_autoptr(FuMainAuthHelper) helper = NULL;
|
||||||
|
g_autoptr(PolkitSubject) subject = NULL;
|
||||||
|
|
||||||
|
g_variant_get (parameters, "(^as)", &checksums);
|
||||||
|
checksums_str = g_strjoinv (",", checksums);
|
||||||
|
g_debug ("Called %s(%s)", method_name, checksums_str);
|
||||||
|
|
||||||
|
/* authenticate */
|
||||||
|
fu_main_set_status (priv, FWUPD_STATUS_WAITING_FOR_AUTH);
|
||||||
|
helper = g_new0 (FuMainAuthHelper, 1);
|
||||||
|
helper->priv = priv;
|
||||||
|
helper->request = g_steal_pointer (&request);
|
||||||
|
helper->invocation = g_object_ref (invocation);
|
||||||
|
helper->checksums = g_ptr_array_new_with_free_func (g_free);
|
||||||
|
for (guint i = 0; checksums[i] != NULL; i++)
|
||||||
|
g_ptr_array_add (helper->checksums, g_strdup (checksums[i]));
|
||||||
|
subject = polkit_system_bus_name_new (sender);
|
||||||
|
polkit_authority_check_authorization (priv->authority, subject,
|
||||||
|
"org.freedesktop.fwupd.set-approved-firmware",
|
||||||
|
NULL,
|
||||||
|
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
||||||
|
NULL,
|
||||||
|
fu_main_authorize_set_blocked_firmware_cb,
|
||||||
|
g_steal_pointer (&helper));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (g_strcmp0 (method_name, "SelfSign") == 0) {
|
if (g_strcmp0 (method_name, "SelfSign") == 0) {
|
||||||
GVariant *prop_value;
|
GVariant *prop_value;
|
||||||
gchar *prop_key;
|
gchar *prop_key;
|
||||||
|
174
src/fu-util.c
174
src/fu-util.c
@ -2311,6 +2311,162 @@ fu_util_check_polkit_actions (GError **error)
|
|||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuUtilPrivate, fu_util_private_free)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(FuUtilPrivate, fu_util_private_free)
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
fu_util_get_history_checksum (FuUtilPrivate *priv, GError **error)
|
||||||
|
{
|
||||||
|
const gchar *csum;
|
||||||
|
g_autoptr(FwupdDevice) device = NULL;
|
||||||
|
g_autoptr(FwupdRelease) release = NULL;
|
||||||
|
g_autoptr(GPtrArray) devices = NULL;
|
||||||
|
|
||||||
|
devices = fwupd_client_get_history (priv->client, NULL, error);
|
||||||
|
if (devices == NULL)
|
||||||
|
return NULL;
|
||||||
|
device = fu_util_prompt_for_device (priv, devices, error);
|
||||||
|
if (device == NULL)
|
||||||
|
return NULL;
|
||||||
|
release = fu_util_prompt_for_release (priv, fwupd_device_get_releases (device), error);
|
||||||
|
if (release == NULL)
|
||||||
|
return NULL;
|
||||||
|
csum = fwupd_checksum_get_best (fwupd_release_get_checksums (release));
|
||||||
|
if (csum == NULL) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
"No suitable checksums");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_strdup (csum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_block_firmware (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
|
{
|
||||||
|
guint idx = 0;
|
||||||
|
g_autofree gchar *csum = NULL;
|
||||||
|
g_auto(GStrv) csums_new = NULL;
|
||||||
|
g_auto(GStrv) csums = NULL;
|
||||||
|
|
||||||
|
/* get existing checksums */
|
||||||
|
csums = fwupd_client_get_blocked_firmware (priv->client, priv->cancellable, error);
|
||||||
|
if (csums == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* get new value */
|
||||||
|
if (g_strv_length (values) == 0) {
|
||||||
|
csum = fu_util_get_history_checksum (priv, error);
|
||||||
|
if (csum == NULL)
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
csum = g_strdup (values[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure it's not already there */
|
||||||
|
if (g_strv_contains ((const gchar * const *) csums, csum)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
/* TRANSLATORS: user selected something not possible */
|
||||||
|
_("Firmware is already blocked"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TRANSLATORS: we will not offer this firmware to the user */
|
||||||
|
g_print ("%s %s\n", _("Blocking firmware:"), csum);
|
||||||
|
|
||||||
|
/* remove it from the new list */
|
||||||
|
csums_new = g_new0 (gchar *, g_strv_length (csums) + 2);
|
||||||
|
for (guint i = 0; csums[i] != NULL; i++) {
|
||||||
|
if (g_strcmp0 (csums[i], csum) != 0)
|
||||||
|
csums_new[idx++] = g_strdup (csums[i]);
|
||||||
|
}
|
||||||
|
csums_new[idx] = g_strdup (csum);
|
||||||
|
return fwupd_client_set_blocked_firmware (priv->client, csums_new,
|
||||||
|
priv->cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_unblock_firmware (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
|
{
|
||||||
|
guint idx = 0;
|
||||||
|
g_auto(GStrv) csums = NULL;
|
||||||
|
g_auto(GStrv) csums_new = NULL;
|
||||||
|
g_autofree gchar *csum = NULL;
|
||||||
|
|
||||||
|
/* get existing checksums */
|
||||||
|
csums = fwupd_client_get_blocked_firmware (priv->client, priv->cancellable, error);
|
||||||
|
if (csums == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* empty list */
|
||||||
|
if (g_strv_length (csums) == 0) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
/* TRANSLATORS: nothing to show */
|
||||||
|
_("There are no blocked firmware files"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get new value */
|
||||||
|
if (g_strv_length (values) == 0) {
|
||||||
|
csum = fu_util_get_history_checksum (priv, error);
|
||||||
|
if (csum == NULL)
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
csum = g_strdup (values[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure it's there */
|
||||||
|
if (!g_strv_contains ((const gchar * const *) csums, csum)) {
|
||||||
|
g_set_error_literal (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOTHING_TO_DO,
|
||||||
|
/* TRANSLATORS: user selected something not possible */
|
||||||
|
_("Firmware is not already blocked"));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TRANSLATORS: we will not offer this firmware to the user */
|
||||||
|
g_print ("%s %s\n", _("Unblocking firmware:"), csum);
|
||||||
|
|
||||||
|
/* remove it from the new list */
|
||||||
|
csums_new = g_new0 (gchar *, g_strv_length (csums));
|
||||||
|
for (guint i = 0; csums[i] != NULL; i++) {
|
||||||
|
if (g_strcmp0 (csums[i], csum) != 0)
|
||||||
|
csums_new[idx++] = g_strdup (csums[i]);
|
||||||
|
}
|
||||||
|
return fwupd_client_set_blocked_firmware (priv->client, csums_new,
|
||||||
|
priv->cancellable, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_util_get_blocked_firmware (FuUtilPrivate *priv, gchar **values, GError **error)
|
||||||
|
{
|
||||||
|
g_auto(GStrv) csums = NULL;
|
||||||
|
|
||||||
|
/* get checksums */
|
||||||
|
csums = fwupd_client_get_blocked_firmware (priv->client, priv->cancellable, error);
|
||||||
|
if (csums == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* empty list */
|
||||||
|
if (g_strv_length (csums) == 0) {
|
||||||
|
/* TRANSLATORS: nothing to show */
|
||||||
|
g_print ("%s\n", _("There are no blocked firmware files"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TRANSLATORS: there follows a list of hashes */
|
||||||
|
g_print ("%s\n", _("Blocked firmware files:"));
|
||||||
|
for (guint i = 0; csums[i] != NULL; i++) {
|
||||||
|
g_print ("%u.\t%s\n", i + 1, csums[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char *argv[])
|
main (int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -2557,6 +2713,24 @@ main (int argc, char *argv[])
|
|||||||
/* TRANSLATORS: command description */
|
/* TRANSLATORS: command description */
|
||||||
_("Gets the host security attributes."),
|
_("Gets the host security attributes."),
|
||||||
fu_util_security);
|
fu_util_security);
|
||||||
|
fu_util_cmd_array_add (cmd_array,
|
||||||
|
"block-firmware",
|
||||||
|
"[CHECKSUM]",
|
||||||
|
/* TRANSLATORS: command description */
|
||||||
|
_("Blocks a specific firmware from being installed."),
|
||||||
|
fu_util_block_firmware);
|
||||||
|
fu_util_cmd_array_add (cmd_array,
|
||||||
|
"unblock-firmware",
|
||||||
|
"[CHECKSUM]",
|
||||||
|
/* TRANSLATORS: command description */
|
||||||
|
_("Blocks a specific firmware from being installed."),
|
||||||
|
fu_util_unblock_firmware);
|
||||||
|
fu_util_cmd_array_add (cmd_array,
|
||||||
|
"get-blocked-firmware",
|
||||||
|
NULL,
|
||||||
|
/* TRANSLATORS: command description */
|
||||||
|
_("Gets the list of blocked firmware."),
|
||||||
|
fu_util_get_blocked_firmware);
|
||||||
|
|
||||||
/* do stuff on ctrl+c */
|
/* do stuff on ctrl+c */
|
||||||
priv->cancellable = g_cancellable_new ();
|
priv->cancellable = g_cancellable_new ();
|
||||||
|
@ -489,6 +489,42 @@
|
|||||||
</arg>
|
</arg>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<!--***********************************************************-->
|
||||||
|
<method name='GetBlockedFirmware'>
|
||||||
|
<doc:doc>
|
||||||
|
<doc:description>
|
||||||
|
<doc:para>
|
||||||
|
Gets the list of blocked firmware.
|
||||||
|
</doc:para>
|
||||||
|
</doc:description>
|
||||||
|
</doc:doc>
|
||||||
|
<arg type='as' name='checksums' direction='out'>
|
||||||
|
<doc:doc>
|
||||||
|
<doc:summary>
|
||||||
|
<doc:para>The checksums of the archives</doc:para>
|
||||||
|
</doc:summary>
|
||||||
|
</doc:doc>
|
||||||
|
</arg>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!--***********************************************************-->
|
||||||
|
<method name='SetBlockedFirmware'>
|
||||||
|
<doc:doc>
|
||||||
|
<doc:description>
|
||||||
|
<doc:para>
|
||||||
|
Sets the list of blocked firmware that can be applied to devices.
|
||||||
|
</doc:para>
|
||||||
|
</doc:description>
|
||||||
|
</doc:doc>
|
||||||
|
<arg type='as' name='checksums' direction='in'>
|
||||||
|
<doc:doc>
|
||||||
|
<doc:summary>
|
||||||
|
<doc:para>The checksums of the archives</doc:para>
|
||||||
|
</doc:summary>
|
||||||
|
</doc:doc>
|
||||||
|
</arg>
|
||||||
|
</method>
|
||||||
|
|
||||||
<!--***********************************************************-->
|
<!--***********************************************************-->
|
||||||
<method name='SetFeatureFlags'>
|
<method name='SetFeatureFlags'>
|
||||||
<doc:doc>
|
<doc:doc>
|
||||||
|
Loading…
Reference in New Issue
Block a user