The Firmware Security panel exposes the host security levels and details. The information is generated by fwupd. The panel also exposes hardware configuration changes to pinpoint the configuration changing time. Currently this panel shows: - HSI and secure boot status - Details of HSI and secure boot - Configuration changelog - Digested security level - Extended protection
310 lines
13 KiB
C
310 lines
13 KiB
C
/* cc-firmware-security-dialog.c
|
|
*
|
|
* Copyright (C) 2021 Red Hat, Inc
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Kate Hsuan <hpa@redhat.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib/gi18n-lib.h>
|
|
|
|
#include "cc-firmware-security-panel.h"
|
|
#include "cc-firmware-security-dialog.h"
|
|
#include "cc-firmware-security-utils.h"
|
|
|
|
struct _CcFirmwareSecurityDialog
|
|
{
|
|
AdwWindow parent;
|
|
|
|
GtkWidget *firmware_security_dialog_icon;
|
|
GtkWidget *firmware_security_dialog_title_label;
|
|
GtkWidget *firmware_security_dialog_body_label;
|
|
GtkWidget *firmware_security_dialog_min_row;
|
|
GtkWidget *firmware_security_dialog_basic_row;
|
|
GtkWidget *firmware_security_dialog_extend_row;
|
|
GtkWidget *firmware_security_dialog_hsi1_pg;
|
|
GtkWidget *firmware_security_dialog_hsi2_pg;
|
|
GtkWidget *firmware_security_dialog_hsi3_pg;
|
|
GtkWidget *firmware_security_dialog_hsi_label;
|
|
AdwLeaflet *leaflet;
|
|
AdwWindowTitle *second_page_title;
|
|
|
|
gboolean is_created;
|
|
|
|
GHashTable *hsi1_dict;
|
|
GHashTable *hsi2_dict;
|
|
GHashTable *hsi3_dict;
|
|
GHashTable *hsi4_dict;
|
|
|
|
guint hsi_number;
|
|
};
|
|
|
|
G_DEFINE_TYPE (CcFirmwareSecurityDialog, cc_firmware_security_dialog, ADW_TYPE_WINDOW)
|
|
|
|
static void
|
|
set_dialog_item_layer1 (CcFirmwareSecurityDialog *self,
|
|
const gchar *icon_name,
|
|
const gchar *style,
|
|
const gchar *title,
|
|
const gchar *body)
|
|
{
|
|
g_autofree gchar *str = NULL;
|
|
|
|
/* TRANSLATORS: HSI stands for Host Security ID and device refers to the computer as a whole */
|
|
str = g_strdup_printf (_("Device conforms to HSI level %d"), self->hsi_number);
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (self->firmware_security_dialog_icon), icon_name);
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_icon, style);
|
|
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_title_label), title);
|
|
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_body_label), body);
|
|
gtk_label_set_text (GTK_LABEL (self->firmware_security_dialog_hsi_label), str);
|
|
}
|
|
|
|
static void
|
|
update_dialog (CcFirmwareSecurityDialog *self)
|
|
{
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_min_row), "dialog-error-symbolic");
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_basic_row), "dialog-error-symbolic");
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_extend_row), "dialog-error-symbolic");
|
|
|
|
if (self->hsi_number < 1)
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_min_row, "gray-icon");
|
|
if (self->hsi_number < 2)
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_basic_row, "gray-icon");
|
|
if (self->hsi_number < 3)
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_extend_row, "gray-icon");
|
|
|
|
switch (self->hsi_number)
|
|
{
|
|
case 0:
|
|
set_dialog_item_layer1 (self,
|
|
"dialog-warning-symbolic",
|
|
"error",
|
|
_("No Protection"),
|
|
_("This device has no protection against hardware security issues. This could "
|
|
"be because of a hardware or firmware configuration issue. It is "
|
|
"recommended to contact your IT support provider."));
|
|
break;
|
|
|
|
case 1:
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_min_row),
|
|
"emblem-default-symbolic");
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_min_row, "success-icon");
|
|
set_dialog_item_layer1 (self,
|
|
"security-low-symbolic",
|
|
"neutral",
|
|
_("Minimal Protection"),
|
|
_("This device has minimal protection against hardware security issues. This "
|
|
"is the lowest device security level and only provides protection against "
|
|
"simple security threats."));
|
|
break;
|
|
|
|
case 2:
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_basic_row),
|
|
"emblem-default-symbolic");
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_basic_row, "success-icon");
|
|
set_dialog_item_layer1 (self,
|
|
"security-medium-symbolic",
|
|
"warning",
|
|
_("Basic Protection"),
|
|
_("This device has basic protection against hardware security issues. This "
|
|
"provides protection against some common security threats."));
|
|
break;
|
|
|
|
case 3:
|
|
case 4:
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (self->firmware_security_dialog_extend_row),
|
|
"emblem-default-symbolic");
|
|
gtk_widget_add_css_class (self->firmware_security_dialog_extend_row, "success-icon");
|
|
set_dialog_item_layer1 (self,
|
|
"security-high-symbolic",
|
|
"good",
|
|
_("Extended Protection"),
|
|
_("This device has extended protection against hardware security issues. This "
|
|
"is the highest device security level and provides protection against "
|
|
"advanced security threats."));
|
|
break;
|
|
|
|
default:
|
|
set_dialog_item_layer1 (self,
|
|
"dialog-warning-symbolic",
|
|
"error",
|
|
_("Error: unable to determine HSI level."),
|
|
_("Error: unable to determine Incorrect HSI level."));
|
|
}
|
|
}
|
|
|
|
static GtkWidget *
|
|
hsi_create_pg_row (const gchar *icon_name,
|
|
const gchar *style,
|
|
const gchar *item_name)
|
|
{
|
|
GtkWidget *row;
|
|
|
|
row = adw_action_row_new ();
|
|
adw_action_row_set_icon_name (ADW_ACTION_ROW (row), icon_name);
|
|
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), fu_security_attr_get_name (item_name));
|
|
|
|
return row;
|
|
}
|
|
|
|
static void
|
|
update_hsi_listbox (CcFirmwareSecurityDialog *self,
|
|
const gint hsi_level)
|
|
{
|
|
g_autoptr (GList) hash_keys = NULL;
|
|
GHashTable *hsi_dict = NULL;
|
|
GtkWidget *pg_row;
|
|
GtkWidget *hsi_pg;
|
|
guint64 flags = 0;
|
|
|
|
switch (hsi_level)
|
|
{
|
|
case 1:
|
|
hsi_dict = self->hsi1_dict;
|
|
hsi_pg = self->firmware_security_dialog_hsi1_pg;
|
|
break;
|
|
case 2:
|
|
hsi_dict = self->hsi2_dict;
|
|
hsi_pg = self->firmware_security_dialog_hsi2_pg;
|
|
break;
|
|
case 3:
|
|
hsi_dict = self->hsi3_dict;
|
|
hsi_pg = self->firmware_security_dialog_hsi3_pg;
|
|
break;
|
|
case 4:
|
|
hsi_dict = self->hsi4_dict;
|
|
hsi_pg = self->firmware_security_dialog_hsi3_pg;
|
|
break;
|
|
}
|
|
|
|
hash_keys = g_hash_table_get_keys (hsi_dict);
|
|
for (GList *item = g_list_first (hash_keys); item != NULL; item = g_list_next (item))
|
|
{
|
|
flags = GPOINTER_TO_INT (g_hash_table_lookup (hsi_dict, item->data));
|
|
if (firmware_security_attr_has_flag (flags, FWUPD_SECURITY_ATTR_FLAG_SUCCESS))
|
|
{
|
|
pg_row = hsi_create_pg_row ("emblem-default-symbolic", "color_green", item->data);
|
|
gtk_widget_add_css_class (pg_row, "success-icon");
|
|
}
|
|
else
|
|
{
|
|
pg_row = hsi_create_pg_row ("dialog-error-symbolic", "color_dim", item->data);
|
|
gtk_widget_add_css_class (pg_row, "error-icon");
|
|
}
|
|
adw_preferences_group_add (ADW_PREFERENCES_GROUP (hsi_pg), GTK_WIDGET (pg_row));
|
|
}
|
|
self->is_created = TRUE;
|
|
}
|
|
|
|
static void
|
|
on_hsi_clicked_cb (GtkWidget *widget,
|
|
CcFirmwareSecurityDialog *self)
|
|
{
|
|
adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_FORWARD);
|
|
|
|
if (!self->is_created)
|
|
{
|
|
update_hsi_listbox (self, 1);
|
|
update_hsi_listbox (self, 2);
|
|
update_hsi_listbox (self, 3);
|
|
update_hsi_listbox (self, 4);
|
|
self->is_created = TRUE;
|
|
}
|
|
|
|
if (widget == self->firmware_security_dialog_min_row)
|
|
{
|
|
adw_window_title_set_title (self->second_page_title, _("Minimal Security Protections"));
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, TRUE);
|
|
}
|
|
else if (widget == self->firmware_security_dialog_basic_row)
|
|
{
|
|
adw_window_title_set_title (self->second_page_title, _("Basic Security Protections"));
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, TRUE);
|
|
}
|
|
else if (widget == self->firmware_security_dialog_extend_row)
|
|
{
|
|
adw_window_title_set_title (self->second_page_title, _("Extended Security Protections"));
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, TRUE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_fw_back_button_clicked_cb (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
CcFirmwareSecurityDialog *self = CC_FIRMWARE_SECURITY_DIALOG (data);
|
|
|
|
adw_leaflet_navigate (self->leaflet, ADW_NAVIGATION_DIRECTION_BACK);
|
|
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi1_pg, FALSE);
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi2_pg, FALSE);
|
|
gtk_widget_set_visible (self->firmware_security_dialog_hsi3_pg, FALSE);
|
|
}
|
|
|
|
static void
|
|
cc_firmware_security_dialog_class_init (CcFirmwareSecurityDialogClass *klass)
|
|
{
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
|
|
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/firmware-security/cc-firmware-security-dialog.ui");
|
|
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_icon);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_title_label);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_body_label);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi_label);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_min_row);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_basic_row);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_extend_row);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi1_pg);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi2_pg);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, firmware_security_dialog_hsi3_pg);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, leaflet);
|
|
gtk_widget_class_bind_template_child (widget_class, CcFirmwareSecurityDialog, second_page_title);
|
|
|
|
gtk_widget_class_bind_template_callback (widget_class, on_hsi_clicked_cb);
|
|
gtk_widget_class_bind_template_callback (widget_class, on_fw_back_button_clicked_cb);
|
|
}
|
|
|
|
static void
|
|
cc_firmware_security_dialog_init (CcFirmwareSecurityDialog *dialog)
|
|
{
|
|
gtk_widget_init_template (GTK_WIDGET (dialog));
|
|
load_custom_css ("/org/gnome/control-center/firmware-security/security-level.css");
|
|
}
|
|
|
|
GtkWidget *
|
|
cc_firmware_security_dialog_new (guint hsi_number,
|
|
GHashTable *hsi1_dict,
|
|
GHashTable *hsi2_dict,
|
|
GHashTable *hsi3_dict,
|
|
GHashTable *hsi4_dict)
|
|
{
|
|
CcFirmwareSecurityDialog *dialog;
|
|
|
|
dialog = g_object_new (CC_TYPE_FIRMWARE_SECURITY_DIALOG, NULL);
|
|
dialog->hsi_number = hsi_number;
|
|
dialog->is_created = FALSE;
|
|
dialog->hsi1_dict = hsi1_dict;
|
|
dialog->hsi2_dict = hsi2_dict;
|
|
dialog->hsi3_dict = hsi3_dict;
|
|
dialog->hsi4_dict = hsi4_dict;
|
|
update_dialog (dialog);
|
|
|
|
return GTK_WIDGET (dialog);
|
|
}
|