CertificateSettings: Create basic Cert Store application

This commit adds a new application named CertificateSettings that
houses our Cert Store. It should be expanded in the future.
This commit is contained in:
Fabian Dellwing 2023-03-27 20:04:24 +02:00 committed by Andrew Kaster
parent 459dee1f86
commit c273784c3e
9 changed files with 237 additions and 0 deletions

View file

@ -0,0 +1,6 @@
[App]
Name=Certificate Settings
Executable=/bin/CertificateSettings
Category=Settings
Description=Access and change the system's certificates
ExcludeFromSystemMenu=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

View file

@ -7,6 +7,7 @@ add_subdirectory(BrowserSettings)
add_subdirectory(Calculator)
add_subdirectory(Calendar)
add_subdirectory(CalendarSettings)
add_subdirectory(CertificateSettings)
add_subdirectory(CharacterMap)
add_subdirectory(ClockSettings)
add_subdirectory(CrashReporter)

View file

@ -0,0 +1,19 @@
serenity_component(
CertificateSettings
REQUIRED
TARGETS CertificateSettings
)
compile_gml(CertificateStore.gml CertificateStoreGML.h certificate_store_gml)
set(SOURCES
CertificateStore.cpp
main.cpp
)
set(GENERATED_SOURCES
CertificateStoreGML.h
)
serenity_app(CertificateSettings ICON certificate)
target_link_libraries(CertificateSettings PRIVATE LibCore LibCrypto LibGfx LibGUI LibMain LibTLS)

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2023, Fabian Dellwing <fabian@dellwing.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CertificateStore.h"
#include <Applications/CertificateSettings/CertificateStoreGML.h>
#include <LibCrypto/ASN1/PEM.h>
namespace CertificateSettings {
NonnullRefPtr<CertificateStoreModel> CertificateStoreModel::create() { return adopt_ref(*new CertificateStoreModel); }
ErrorOr<void> CertificateStoreModel::load()
{
// FIXME: In the future, we will allow users to import their own certificates. To support this, we would need to change this logic
auto cacert_file = TRY(Core::File::open("/etc/cacert.pem"sv, Core::File::OpenMode::Read));
auto data = TRY(cacert_file->read_until_eof());
m_certificates = TRY(DefaultRootCACertificates::the().reload_certificates(data));
return {};
}
DeprecatedString CertificateStoreModel::column_name(int column) const
{
switch (column) {
case Column::IssuedTo:
return "Issued To";
case Column::IssuedBy:
return "Issued By";
case Column::Expire:
return "Expiration Date";
default:
VERIFY_NOT_REACHED();
}
}
GUI::Variant CertificateStoreModel::data(GUI::ModelIndex const& index, GUI::ModelRole role) const
{
if (role != GUI::ModelRole::Display)
return {};
if (m_certificates.is_empty())
return {};
auto cert = m_certificates.at(index.row());
switch (index.column()) {
case Column::IssuedTo:
return cert.subject.subject.is_empty() ? cert.subject.unit : cert.subject.subject;
case Column::IssuedBy:
return cert.issuer.subject.is_empty() ? cert.issuer.unit : cert.issuer.subject;
case Column::Expire:
return cert.not_after.to_deprecated_string("%Y-%m-%d"sv);
default:
VERIFY_NOT_REACHED();
}
return {};
}
ErrorOr<NonnullRefPtr<CertificateStoreWidget>> CertificateStoreWidget::try_create()
{
auto widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) CertificateStoreWidget()));
TRY(widget->initialize());
return widget;
}
ErrorOr<void> CertificateStoreWidget::initialize()
{
TRY(load_from_gml(certificate_store_gml));
m_root_ca_tableview = find_descendant_of_type_named<GUI::TableView>("root_ca_tableview");
m_root_ca_tableview->set_highlight_selected_rows(true);
m_root_ca_tableview->set_alternating_row_colors(false);
m_root_ca_model = CertificateStoreModel::create();
TRY(m_root_ca_model->load());
m_root_ca_tableview->set_model(m_root_ca_model);
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedTo, 150);
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedBy, 150);
return {};
}
}

View file

@ -0,0 +1,40 @@
@GUI::Widget {
fill_with_background_color: true
layout: @GUI::VerticalBoxLayout {
margins: [8]
}
@GUI::GroupBox {
title: "Trusted Root Certification Authorities"
fixed_height: 500
fixed_width: 465
layout: @GUI::VerticalBoxLayout {
margins: [8]
}
@GUI::TableView {
name: "root_ca_tableview"
}
@GUI::Widget {
layout: @GUI::HorizontalBoxLayout {
spacing: 6
}
preferred_height: "fit"
@GUI::Button {
name: "import_button"
text: "Import"
fixed_width: 80
enabled: false
}
@GUI::Button {
name: "export_button"
text: "Export"
fixed_width: 80
enabled: false
}
}
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2023, Fabian Dellwing <fabian@dellwing.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGUI/Model.h>
#include <LibGUI/SettingsWindow.h>
#include <LibGUI/TableView.h>
#include <LibTLS/Certificate.h>
namespace CertificateSettings {
class CertificateStoreModel : public GUI::Model {
public:
enum Column {
IssuedTo,
IssuedBy,
Expire,
__Count
};
static NonnullRefPtr<CertificateStoreModel> create();
virtual ~CertificateStoreModel() override = default;
virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_certificates.size(); }
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual DeprecatedString column_name(int) const override;
virtual GUI::Variant data(GUI::ModelIndex const&, GUI::ModelRole) const override;
virtual ErrorOr<void> load();
private:
Vector<Certificate> m_certificates;
};
class CertificateStoreWidget : public GUI::SettingsWindow::Tab {
C_OBJECT_ABSTRACT(CertStoreWidget)
public:
virtual ~CertificateStoreWidget() override = default;
static ErrorOr<NonnullRefPtr<CertificateStoreWidget>> try_create();
virtual void apply_settings() override {};
private:
CertificateStoreWidget() = default;
ErrorOr<void> initialize();
RefPtr<CertificateStoreModel> m_root_ca_model;
RefPtr<GUI::TableView> m_root_ca_tableview;
};
}

View file

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023, Fabian Dellwing <fabian@dellwing.net>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CertificateStore.h"
#include <LibCore/System.h>
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
#include <LibGUI/SettingsWindow.h>
#include <LibMain/Main.h>
#include <unistd.h>
ErrorOr<int> serenity_main(Main::Arguments args)
{
TRY(Core::System::pledge("stdio rpath wpath cpath recvfd sendfd unix"));
auto app = TRY(GUI::Application::try_create(args));
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil("/etc/cacert.pem", "r"));
TRY(Core::System::unveil("/etc/timezone", "r"));
TRY(Core::System::unveil(nullptr, nullptr));
auto app_icon = GUI::Icon::default_icon("certificate"sv);
auto window = TRY(GUI::SettingsWindow::create("Certificates", GUI::SettingsWindow::ShowDefaultsButton::No));
auto cert_store_widget = TRY(window->add_tab<CertificateSettings::CertificateStoreWidget>(TRY("Certificate Store"_string), "certificate"sv));
window->set_icon(app_icon.bitmap_for_size(16));
window->show();
return app->exec();
}