mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-03 01:06:06 +00:00

This indicates the GUID in some way contributed to the result decided. It also allows us to match the submitted HSI results back to a firmware stream on the LVFS, which allows us to allow vendors to see a subset of results for uploaded devices.
1045 lines
28 KiB
C
1045 lines
28 KiB
C
/*
|
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gio/gio.h>
|
|
#include <string.h>
|
|
|
|
#include "fwupd-common-private.h"
|
|
#include "fwupd-enums-private.h"
|
|
#include "fwupd-security-attr-private.h"
|
|
|
|
/**
|
|
* FwupdSecurityAttr:
|
|
*
|
|
* A Host Security ID attribute that represents something that was measured.
|
|
*/
|
|
|
|
static void
|
|
fwupd_security_attr_finalize(GObject *object);
|
|
|
|
typedef struct {
|
|
gchar *appstream_id;
|
|
GPtrArray *obsoletes;
|
|
GPtrArray *guids;
|
|
GHashTable *metadata; /* (nullable) */
|
|
gchar *name;
|
|
gchar *plugin;
|
|
gchar *url;
|
|
FwupdSecurityAttrLevel level;
|
|
FwupdSecurityAttrResult result;
|
|
FwupdSecurityAttrFlags flags;
|
|
} FwupdSecurityAttrPrivate;
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE(FwupdSecurityAttr, fwupd_security_attr, G_TYPE_OBJECT)
|
|
#define GET_PRIVATE(o) (fwupd_security_attr_get_instance_private(o))
|
|
|
|
/**
|
|
* fwupd_security_attr_flag_to_string:
|
|
* @flag: security attribute flags, e.g. %FWUPD_SECURITY_ATTR_FLAG_SUCCESS
|
|
*
|
|
* Returns the printable string for the flag.
|
|
*
|
|
* Returns: string, or %NULL
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_flag_to_string(FwupdSecurityAttrFlags flag)
|
|
{
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_NONE)
|
|
return "none";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_SUCCESS)
|
|
return "success";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_OBSOLETED)
|
|
return "obsoleted";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES)
|
|
return "runtime-updates";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION)
|
|
return "runtime-attestation";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE)
|
|
return "runtime-issue";
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_result_to_string:
|
|
* @result: security attribute result, e.g. %FWUPD_SECURITY_ATTR_RESULT_ENABLED
|
|
*
|
|
* Returns the printable string for the result enum.
|
|
*
|
|
* Returns: string, or %NULL
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_result_to_string(FwupdSecurityAttrResult result)
|
|
{
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_VALID)
|
|
return "valid";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_VALID)
|
|
return "not-valid";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_ENABLED)
|
|
return "enabled";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENABLED)
|
|
return "not-enabled";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_LOCKED)
|
|
return "locked";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_LOCKED)
|
|
return "not-locked";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_ENCRYPTED)
|
|
return "encrypted";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_ENCRYPTED)
|
|
return "not-encrypted";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_TAINTED)
|
|
return "tainted";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_TAINTED)
|
|
return "not-tainted";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_FOUND)
|
|
return "found";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_FOUND)
|
|
return "not-found";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_SUPPORTED)
|
|
return "supported";
|
|
if (result == FWUPD_SECURITY_ATTR_RESULT_NOT_SUPPORTED)
|
|
return "not-supported";
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_flag_to_suffix:
|
|
* @flag: security attribute flags, e.g. %FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES
|
|
*
|
|
* Returns the string suffix for the flag.
|
|
*
|
|
* Returns: string, or %NULL
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_flag_to_suffix(FwupdSecurityAttrFlags flag)
|
|
{
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_UPDATES)
|
|
return "U";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ATTESTATION)
|
|
return "A";
|
|
if (flag == FWUPD_SECURITY_ATTR_FLAG_RUNTIME_ISSUE)
|
|
return "!";
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_obsoletes:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the list of attribute obsoletes. The obsoleted attributes will not
|
|
* contribute to the calculated HSI value or be visible in command line tools.
|
|
*
|
|
* Returns: (element-type utf8) (transfer none): the obsoletes, which may be empty
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
GPtrArray *
|
|
fwupd_security_attr_get_obsoletes(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->obsoletes;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_add_obsolete:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @appstream_id: the appstream_id or plugin name
|
|
*
|
|
* Adds an attribute appstream_id to obsolete. The obsoleted attribute will not
|
|
* contribute to the calculated HSI value or be visible in command line tools.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_add_obsolete(FwupdSecurityAttr *self, const gchar *appstream_id)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
g_return_if_fail(appstream_id != NULL);
|
|
if (fwupd_security_attr_has_obsolete(self, appstream_id))
|
|
return;
|
|
g_ptr_array_add(priv->obsoletes, g_strdup(appstream_id));
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_has_obsolete:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @appstream_id: the attribute appstream_id
|
|
*
|
|
* Finds out if the attribute obsoletes a specific appstream_id.
|
|
*
|
|
* Returns: %TRUE if the self matches
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
gboolean
|
|
fwupd_security_attr_has_obsolete(FwupdSecurityAttr *self, const gchar *appstream_id)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), FALSE);
|
|
g_return_val_if_fail(appstream_id != NULL, FALSE);
|
|
for (guint i = 0; i < priv->obsoletes->len; i++) {
|
|
const gchar *obsolete_tmp = g_ptr_array_index(priv->obsoletes, i);
|
|
if (g_strcmp0(obsolete_tmp, appstream_id) == 0)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_guids:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the list of attribute GUIDs. The GUID values will not modify the calculated HSI value.
|
|
*
|
|
* Returns: (element-type utf8) (transfer none): the GUIDs, which may be empty
|
|
*
|
|
* Since: 1.7.0
|
|
**/
|
|
GPtrArray *
|
|
fwupd_security_attr_get_guids(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->guids;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_add_guid:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @guid: the GUID
|
|
*
|
|
* Adds a device GUID to the attribute. This indicates the GUID in some way contributed to the
|
|
* result decided.
|
|
*
|
|
* Since: 1.7.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_add_guid(FwupdSecurityAttr *self, const gchar *guid)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
g_return_if_fail(fwupd_guid_is_valid(guid));
|
|
if (fwupd_security_attr_has_guid(self, guid))
|
|
return;
|
|
g_ptr_array_add(priv->guids, g_strdup(guid));
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_add_guids:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @guids: (element-type utf8): the GUIDs
|
|
*
|
|
* Adds device GUIDs to the attribute. This indicates the GUIDs in some way contributed to the
|
|
* result decided.
|
|
*
|
|
* Since: 1.7.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_add_guids(FwupdSecurityAttr *self, GPtrArray *guids)
|
|
{
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
g_return_if_fail(guids != NULL);
|
|
for (guint i = 0; i < guids->len; i++) {
|
|
const gchar *guid = g_ptr_array_index(guids, i);
|
|
fwupd_security_attr_add_guid(self, guid);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_has_guid:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @guid: the attribute guid
|
|
*
|
|
* Finds out if a specific GUID was added to the attribute.
|
|
*
|
|
* Returns: %TRUE if the self matches
|
|
*
|
|
* Since: 1.7.0
|
|
**/
|
|
gboolean
|
|
fwupd_security_attr_has_guid(FwupdSecurityAttr *self, const gchar *guid)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), FALSE);
|
|
g_return_val_if_fail(guid != NULL, FALSE);
|
|
for (guint i = 0; i < priv->guids->len; i++) {
|
|
const gchar *guid_tmp = g_ptr_array_index(priv->guids, i);
|
|
if (g_strcmp0(guid_tmp, guid) == 0)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_appstream_id:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the AppStream ID.
|
|
*
|
|
* Returns: the AppStream ID, or %NULL if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_get_appstream_id(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->appstream_id;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_appstream_id:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @appstream_id: (nullable): the AppStream component ID, e.g. `com.intel.BiosGuard`
|
|
*
|
|
* Sets the AppStream ID.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_appstream_id(FwupdSecurityAttr *self, const gchar *appstream_id)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
|
|
/* not changed */
|
|
if (g_strcmp0(priv->appstream_id, appstream_id) == 0)
|
|
return;
|
|
|
|
/* sanity check */
|
|
if (!g_str_has_prefix(appstream_id, "org.fwupd.hsi."))
|
|
g_critical("HSI attributes need to have a 'org.fwupd.hsi.' prefix");
|
|
|
|
g_free(priv->appstream_id);
|
|
priv->appstream_id = g_strdup(appstream_id);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_url:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the attribute URL.
|
|
*
|
|
* Returns: the attribute result, or %NULL if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_get_url(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->url;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_name:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @name: (nullable): the attribute name
|
|
*
|
|
* Sets the attribute name.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_name(FwupdSecurityAttr *self, const gchar *name)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
|
|
/* not changed */
|
|
if (g_strcmp0(priv->name, name) == 0)
|
|
return;
|
|
|
|
g_free(priv->name);
|
|
priv->name = g_strdup(name);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_plugin:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @plugin: (nullable): the plugin name
|
|
*
|
|
* Sets the plugin that created the attribute.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_plugin(FwupdSecurityAttr *self, const gchar *plugin)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
|
|
/* not changed */
|
|
if (g_strcmp0(priv->plugin, plugin) == 0)
|
|
return;
|
|
|
|
g_free(priv->plugin);
|
|
priv->plugin = g_strdup(plugin);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_url:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @url: (nullable): the attribute URL
|
|
*
|
|
* Sets the attribute result.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_url(FwupdSecurityAttr *self, const gchar *url)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
|
|
/* not changed */
|
|
if (g_strcmp0(priv->url, url) == 0)
|
|
return;
|
|
|
|
g_free(priv->url);
|
|
priv->url = g_strdup(url);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_name:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the attribute name.
|
|
*
|
|
* Returns: the attribute name, or %NULL if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_get_name(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->name;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_plugin:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the plugin that created the attribute.
|
|
*
|
|
* Returns: the plugin name, or %NULL if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_get_plugin(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
return priv->plugin;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_flags:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the self flags.
|
|
*
|
|
* Returns: security attribute flags, or 0 if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
FwupdSecurityAttrFlags
|
|
fwupd_security_attr_get_flags(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), 0);
|
|
return priv->flags;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_flags:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @flags: security attribute flags, e.g. %FWUPD_SECURITY_ATTR_FLAG_OBSOLETED
|
|
*
|
|
* Sets the attribute flags.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_flags(FwupdSecurityAttr *self, FwupdSecurityAttrFlags flags)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
priv->flags = flags;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_add_flag:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @flag: the #FwupdSecurityAttrFlags, e.g. %FWUPD_SECURITY_ATTR_FLAG_OBSOLETED
|
|
*
|
|
* Adds a specific attribute flag to the attribute.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_add_flag(FwupdSecurityAttr *self, FwupdSecurityAttrFlags flag)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
priv->flags |= flag;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_has_flag:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @flag: the attribute flag, e.g. %FWUPD_SECURITY_ATTR_FLAG_OBSOLETED
|
|
*
|
|
* Finds if the attribute has a specific attribute flag.
|
|
*
|
|
* Returns: %TRUE if the flag is set
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
gboolean
|
|
fwupd_security_attr_has_flag(FwupdSecurityAttr *self, FwupdSecurityAttrFlags flag)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), FALSE);
|
|
return (priv->flags & flag) > 0;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_level:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the HSI level.
|
|
*
|
|
* Returns: the security attribute level, or %FWUPD_SECURITY_ATTR_LEVEL_NONE if unset
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
FwupdSecurityAttrLevel
|
|
fwupd_security_attr_get_level(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), 0);
|
|
return priv->level;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_level:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @level: a security attribute level, e.g. %FWUPD_SECURITY_ATTR_LEVEL_IMPORTANT
|
|
*
|
|
* Sets the HSI level. A @level of %FWUPD_SECURITY_ATTR_LEVEL_NONE is not used
|
|
* for the HSI calculation.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_level(FwupdSecurityAttr *self, FwupdSecurityAttrLevel level)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
priv->level = level;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_set_result:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @result: a security attribute result, e.g. %FWUPD_SECURITY_ATTR_LEVEL_LOCKED
|
|
*
|
|
* Sets the optional HSI result. This is required because some attributes may
|
|
* be a "success" when something is `locked` or may be "failed" if `found`.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_set_result(FwupdSecurityAttr *self, FwupdSecurityAttrResult result)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
priv->result = result;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_result:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Gets the optional HSI result.
|
|
*
|
|
* Returns: the #FwupdSecurityAttrResult, e.g %FWUPD_SECURITY_ATTR_LEVEL_LOCKED
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
FwupdSecurityAttrResult
|
|
fwupd_security_attr_get_result(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), 0);
|
|
return priv->result;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_to_variant:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Serialize the security attribute.
|
|
*
|
|
* Returns: the serialized data, or %NULL for error
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
GVariant *
|
|
fwupd_security_attr_to_variant(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
GVariantBuilder builder;
|
|
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
|
|
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
|
|
if (priv->appstream_id != NULL) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_APPSTREAM_ID,
|
|
g_variant_new_string(priv->appstream_id));
|
|
}
|
|
if (priv->name != NULL) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_NAME,
|
|
g_variant_new_string(priv->name));
|
|
}
|
|
if (priv->url != NULL) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_URI,
|
|
g_variant_new_string(priv->url));
|
|
}
|
|
if (priv->obsoletes->len > 0) {
|
|
g_autofree const gchar **strv = g_new0(const gchar *, priv->obsoletes->len + 1);
|
|
for (guint i = 0; i < priv->obsoletes->len; i++)
|
|
strv[i] = (const gchar *)g_ptr_array_index(priv->obsoletes, i);
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_CATEGORIES,
|
|
g_variant_new_strv(strv, -1));
|
|
}
|
|
if (priv->guids->len > 0) {
|
|
g_autofree const gchar **strv = g_new0(const gchar *, priv->guids->len + 1);
|
|
for (guint i = 0; i < priv->guids->len; i++)
|
|
strv[i] = (const gchar *)g_ptr_array_index(priv->guids, i);
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_GUID,
|
|
g_variant_new_strv(strv, -1));
|
|
}
|
|
if (priv->flags != 0) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_FLAGS,
|
|
g_variant_new_uint64(priv->flags));
|
|
}
|
|
if (priv->level > 0) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_HSI_LEVEL,
|
|
g_variant_new_uint32(priv->level));
|
|
}
|
|
if (priv->result != FWUPD_SECURITY_ATTR_RESULT_UNKNOWN) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_HSI_RESULT,
|
|
g_variant_new_uint32(priv->result));
|
|
}
|
|
if (priv->metadata != NULL) {
|
|
g_variant_builder_add(&builder,
|
|
"{sv}",
|
|
FWUPD_RESULT_KEY_METADATA,
|
|
fwupd_hash_kv_to_variant(priv->metadata));
|
|
}
|
|
return g_variant_new("a{sv}", &builder);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_get_metadata:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @key: metadata key
|
|
*
|
|
* Gets private metadata from the attribute which may be used in the name.
|
|
*
|
|
* Returns: (nullable): the metadata value, or %NULL if unfound
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
const gchar *
|
|
fwupd_security_attr_get_metadata(FwupdSecurityAttr *self, const gchar *key)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
g_return_val_if_fail(key != NULL, NULL);
|
|
|
|
if (priv->metadata == NULL)
|
|
return NULL;
|
|
return g_hash_table_lookup(priv->metadata, key);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_add_metadata:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @key: metadata key
|
|
* @value: (nullable): metadata value
|
|
*
|
|
* Adds metadata to the attribute which may be used in the name.
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_add_metadata(FwupdSecurityAttr *self, const gchar *key, const gchar *value)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
g_return_if_fail(key != NULL);
|
|
|
|
if (priv->metadata == NULL) {
|
|
priv->metadata = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
|
}
|
|
g_hash_table_insert(priv->metadata, g_strdup(key), g_strdup(value));
|
|
}
|
|
|
|
static void
|
|
fwupd_security_attr_from_key_value(FwupdSecurityAttr *self, const gchar *key, GVariant *value)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_APPSTREAM_ID) == 0) {
|
|
fwupd_security_attr_set_appstream_id(self, g_variant_get_string(value, NULL));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
|
|
fwupd_security_attr_set_name(self, g_variant_get_string(value, NULL));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_URI) == 0) {
|
|
fwupd_security_attr_set_url(self, g_variant_get_string(value, NULL));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_FLAGS) == 0) {
|
|
fwupd_security_attr_set_flags(self, g_variant_get_uint64(value));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_HSI_LEVEL) == 0) {
|
|
fwupd_security_attr_set_level(self, g_variant_get_uint32(value));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_HSI_RESULT) == 0) {
|
|
fwupd_security_attr_set_result(self, g_variant_get_uint32(value));
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_GUID) == 0) {
|
|
g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
|
|
for (guint i = 0; strv[i] != NULL; i++)
|
|
fwupd_security_attr_add_guid(self, strv[i]);
|
|
return;
|
|
}
|
|
if (g_strcmp0(key, FWUPD_RESULT_KEY_METADATA) == 0) {
|
|
if (priv->metadata != NULL)
|
|
g_hash_table_unref(priv->metadata);
|
|
priv->metadata = fwupd_variant_to_hash_kv(value);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static void
|
|
fwupd_pad_kv_str(GString *str, const gchar *key, const gchar *value)
|
|
{
|
|
/* ignore */
|
|
if (key == NULL || value == NULL)
|
|
return;
|
|
g_string_append_printf(str, " %s: ", key);
|
|
for (gsize i = strlen(key); i < 20; i++)
|
|
g_string_append(str, " ");
|
|
g_string_append_printf(str, "%s\n", value);
|
|
}
|
|
|
|
static void
|
|
fwupd_pad_kv_tfl(GString *str, const gchar *key, FwupdSecurityAttrFlags security_attr_flags)
|
|
{
|
|
g_autoptr(GString) tmp = g_string_new("");
|
|
for (guint i = 0; i < 64; i++) {
|
|
if ((security_attr_flags & ((guint64)1 << i)) == 0)
|
|
continue;
|
|
g_string_append_printf(tmp,
|
|
"%s|",
|
|
fwupd_security_attr_flag_to_string((guint64)1 << i));
|
|
}
|
|
if (tmp->len == 0) {
|
|
g_string_append(tmp, fwupd_security_attr_flag_to_string(0));
|
|
} else {
|
|
g_string_truncate(tmp, tmp->len - 1);
|
|
}
|
|
fwupd_pad_kv_str(str, key, tmp->str);
|
|
}
|
|
|
|
static void
|
|
fwupd_pad_kv_int(GString *str, const gchar *key, guint32 value)
|
|
{
|
|
g_autofree gchar *tmp = NULL;
|
|
|
|
/* ignore */
|
|
if (value == 0)
|
|
return;
|
|
tmp = g_strdup_printf("%" G_GUINT32_FORMAT, value);
|
|
fwupd_pad_kv_str(str, key, tmp);
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_to_json:
|
|
* @self: a #FwupdSecurityAttr
|
|
* @builder: a JSON builder
|
|
*
|
|
* Adds a fwupd security attribute to a JSON builder
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
void
|
|
fwupd_security_attr_to_json(FwupdSecurityAttr *self, JsonBuilder *builder)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
|
|
g_return_if_fail(FWUPD_IS_SECURITY_ATTR(self));
|
|
g_return_if_fail(builder != NULL);
|
|
|
|
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id);
|
|
fwupd_common_json_add_int(builder, FWUPD_RESULT_KEY_HSI_LEVEL, priv->level);
|
|
fwupd_common_json_add_string(builder,
|
|
FWUPD_RESULT_KEY_HSI_RESULT,
|
|
fwupd_security_attr_result_to_string(priv->result));
|
|
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_NAME, priv->name);
|
|
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
|
|
fwupd_common_json_add_string(builder, FWUPD_RESULT_KEY_URI, priv->url);
|
|
if (priv->flags != FWUPD_SECURITY_ATTR_FLAG_NONE) {
|
|
json_builder_set_member_name(builder, FWUPD_RESULT_KEY_FLAGS);
|
|
json_builder_begin_array(builder);
|
|
for (guint i = 0; i < 64; i++) {
|
|
const gchar *tmp;
|
|
if ((priv->flags & ((guint64)1 << i)) == 0)
|
|
continue;
|
|
tmp = fwupd_security_attr_flag_to_string((guint64)1 << i);
|
|
json_builder_add_string_value(builder, tmp);
|
|
}
|
|
json_builder_end_array(builder);
|
|
}
|
|
if (priv->guids->len > 0) {
|
|
json_builder_set_member_name(builder, FWUPD_RESULT_KEY_GUID);
|
|
json_builder_begin_array(builder);
|
|
for (guint i = 0; i < priv->guids->len; i++) {
|
|
const gchar *guid = g_ptr_array_index(priv->guids, i);
|
|
json_builder_add_string_value(builder, guid);
|
|
}
|
|
json_builder_end_array(builder);
|
|
}
|
|
if (priv->metadata != NULL) {
|
|
g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
|
|
for (GList *l = keys; l != NULL; l = l->next) {
|
|
const gchar *key = l->data;
|
|
const gchar *value = g_hash_table_lookup(priv->metadata, key);
|
|
fwupd_common_json_add_string(builder, key, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_to_string:
|
|
* @self: a #FwupdSecurityAttr
|
|
*
|
|
* Builds a text representation of the object.
|
|
*
|
|
* Returns: text, or %NULL for invalid
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
gchar *
|
|
fwupd_security_attr_to_string(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
GString *str;
|
|
|
|
g_return_val_if_fail(FWUPD_IS_SECURITY_ATTR(self), NULL);
|
|
|
|
str = g_string_new("");
|
|
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id);
|
|
fwupd_pad_kv_int(str, FWUPD_RESULT_KEY_HSI_LEVEL, priv->level);
|
|
fwupd_pad_kv_str(str,
|
|
FWUPD_RESULT_KEY_HSI_RESULT,
|
|
fwupd_security_attr_result_to_string(priv->result));
|
|
if (priv->flags != FWUPD_SECURITY_ATTR_FLAG_NONE)
|
|
fwupd_pad_kv_tfl(str, FWUPD_RESULT_KEY_FLAGS, priv->flags);
|
|
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_NAME, priv->name);
|
|
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
|
|
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_URI, priv->url);
|
|
for (guint i = 0; i < priv->obsoletes->len; i++) {
|
|
const gchar *appstream_id = g_ptr_array_index(priv->obsoletes, i);
|
|
fwupd_pad_kv_str(str, "Obsolete", appstream_id);
|
|
}
|
|
for (guint i = 0; i < priv->guids->len; i++) {
|
|
const gchar *guid = g_ptr_array_index(priv->guids, i);
|
|
fwupd_pad_kv_str(str, FWUPD_RESULT_KEY_GUID, guid);
|
|
}
|
|
if (priv->metadata != NULL) {
|
|
g_autoptr(GList) keys = g_hash_table_get_keys(priv->metadata);
|
|
for (GList *l = keys; l != NULL; l = l->next) {
|
|
const gchar *key = l->data;
|
|
const gchar *value = g_hash_table_lookup(priv->metadata, key);
|
|
fwupd_pad_kv_str(str, key, value);
|
|
}
|
|
}
|
|
|
|
return g_string_free(str, FALSE);
|
|
}
|
|
|
|
static void
|
|
fwupd_security_attr_class_init(FwupdSecurityAttrClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
object_class->finalize = fwupd_security_attr_finalize;
|
|
}
|
|
|
|
static void
|
|
fwupd_security_attr_init(FwupdSecurityAttr *self)
|
|
{
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
priv->obsoletes = g_ptr_array_new_with_free_func(g_free);
|
|
priv->guids = g_ptr_array_new_with_free_func(g_free);
|
|
}
|
|
|
|
static void
|
|
fwupd_security_attr_finalize(GObject *object)
|
|
{
|
|
FwupdSecurityAttr *self = FWUPD_SECURITY_ATTR(object);
|
|
FwupdSecurityAttrPrivate *priv = GET_PRIVATE(self);
|
|
|
|
if (priv->metadata != NULL)
|
|
g_hash_table_unref(priv->metadata);
|
|
g_free(priv->appstream_id);
|
|
g_free(priv->name);
|
|
g_free(priv->plugin);
|
|
g_free(priv->url);
|
|
g_ptr_array_unref(priv->obsoletes);
|
|
g_ptr_array_unref(priv->guids);
|
|
|
|
G_OBJECT_CLASS(fwupd_security_attr_parent_class)->finalize(object);
|
|
}
|
|
|
|
static void
|
|
fwupd_security_attr_set_from_variant_iter(FwupdSecurityAttr *self, GVariantIter *iter)
|
|
{
|
|
GVariant *value;
|
|
const gchar *key;
|
|
while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
|
|
fwupd_security_attr_from_key_value(self, key, value);
|
|
g_variant_unref(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_from_variant:
|
|
* @value: the serialized data
|
|
*
|
|
* Creates a new security attribute using serialized data.
|
|
*
|
|
* Returns: (transfer full): a new #FwupdSecurityAttr, or %NULL if @value was invalid
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
FwupdSecurityAttr *
|
|
fwupd_security_attr_from_variant(GVariant *value)
|
|
{
|
|
FwupdSecurityAttr *rel = NULL;
|
|
const gchar *type_string;
|
|
g_autoptr(GVariantIter) iter = NULL;
|
|
|
|
type_string = g_variant_get_type_string(value);
|
|
if (g_strcmp0(type_string, "(a{sv})") == 0) {
|
|
rel = fwupd_security_attr_new(NULL);
|
|
g_variant_get(value, "(a{sv})", &iter);
|
|
fwupd_security_attr_set_from_variant_iter(rel, iter);
|
|
} else if (g_strcmp0(type_string, "a{sv}") == 0) {
|
|
rel = fwupd_security_attr_new(NULL);
|
|
g_variant_get(value, "a{sv}", &iter);
|
|
fwupd_security_attr_set_from_variant_iter(rel, iter);
|
|
} else {
|
|
g_warning("type %s not known", type_string);
|
|
}
|
|
return rel;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_array_from_variant:
|
|
* @value: the serialized data
|
|
*
|
|
* Creates an array of new security attributes using serialized data.
|
|
*
|
|
* Returns: (transfer container) (element-type FwupdSecurityAttr): attributes, or %NULL if @value
|
|
*was invalid
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
GPtrArray *
|
|
fwupd_security_attr_array_from_variant(GVariant *value)
|
|
{
|
|
GPtrArray *array = NULL;
|
|
gsize sz;
|
|
g_autoptr(GVariant) untuple = NULL;
|
|
|
|
array = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
|
|
untuple = g_variant_get_child_value(value, 0);
|
|
sz = g_variant_n_children(untuple);
|
|
for (guint i = 0; i < sz; i++) {
|
|
FwupdSecurityAttr *rel;
|
|
g_autoptr(GVariant) data = NULL;
|
|
data = g_variant_get_child_value(untuple, i);
|
|
rel = fwupd_security_attr_from_variant(data);
|
|
if (rel == NULL)
|
|
continue;
|
|
g_ptr_array_add(array, rel);
|
|
}
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* fwupd_security_attr_new:
|
|
* @appstream_id: (nullable): the AppStream component ID, e.g. `com.intel.BiosGuard`
|
|
*
|
|
* Creates a new security attribute.
|
|
*
|
|
* Returns: a new #FwupdSecurityAttr
|
|
*
|
|
* Since: 1.5.0
|
|
**/
|
|
FwupdSecurityAttr *
|
|
fwupd_security_attr_new(const gchar *appstream_id)
|
|
{
|
|
FwupdSecurityAttr *self;
|
|
self = g_object_new(FWUPD_TYPE_SECURITY_ATTR, NULL);
|
|
if (appstream_id != NULL)
|
|
fwupd_security_attr_set_appstream_id(self, appstream_id);
|
|
return FWUPD_SECURITY_ATTR(self);
|
|
}
|