/* * Copyright (C) 2020 Richard Hughes * * SPDX-License-Identifier: LGPL-2.1+ */ #include "config.h" #include #include #include "fwupd-common-private.h" #include "fwupd-enums-private.h" #include "fwupd-security-attr-private.h" /** * SECTION:fwupd-security-attr * * An object that represents an Host Security ID attribute. */ static void fwupd_security_attr_finalize (GObject *object); typedef struct { gchar *appstream_id; GPtrArray *obsoletes; 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: A #FwupdSecurityAttrFlags, 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: A #FwupdSecurityAttrResult, 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: A #FwupdSecurityAttrFlags, 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_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: 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: 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: 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: 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: the self 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: the self flags, e.g. %FWUPD_SECURITY_ATTR_FLAG_OBSOLETED * * Sets the self 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 * * Adds a specific self flag to the self. * * 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 #FwupdSecurityAttrFlags * * Finds if the self has a specific self 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 #FwupdSecurityAttrLevel, 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 #FwupdSecurityAttrLevel, 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 #FwupdSecurityAttrResult, 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 * * Creates a GVariant from the self data. * * Returns: the GVariant, 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->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_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); } static void fwupd_security_attr_json_add_string (JsonBuilder *builder, const gchar *key, const gchar *str) { if (str == NULL) return; json_builder_set_member_name (builder, key); json_builder_add_string_value (builder, str); } static void fwupd_security_attr_json_add_int (JsonBuilder *builder, const gchar *key, guint64 num) { if (num == 0) return; json_builder_set_member_name (builder, key); json_builder_add_int_value (builder, num); } /** * fwupd_security_attr_to_json: * @self: A #FwupdSecurityAttr * @builder: A #JsonBuilder * * Adds a fwupd self 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_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_APPSTREAM_ID, priv->appstream_id); fwupd_security_attr_json_add_int (builder, FWUPD_RESULT_KEY_HSI_LEVEL, priv->level); fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_HSI_RESULT, fwupd_security_attr_result_to_string (priv->result)); fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_NAME, priv->name); fwupd_security_attr_json_add_string (builder, FWUPD_RESULT_KEY_PLUGIN, priv->plugin); fwupd_security_attr_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->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_security_attr_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); } 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); } 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_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: a #GVariant * * Creates a new self using packed 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: a #GVariant * * Creates an array of new security_attrs using packed 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 self. * * 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); }