1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:37:35 +00:00

CertificateSettings: Add import functionality

This commit is contained in:
Fabian Dellwing 2023-04-01 13:05:47 +02:00 committed by Andrew Kaster
parent c273784c3e
commit 7ce75ee3c5
5 changed files with 64 additions and 4 deletions

View file

@ -16,4 +16,4 @@ set(GENERATED_SOURCES
)
serenity_app(CertificateSettings ICON certificate)
target_link_libraries(CertificateSettings PRIVATE LibCore LibCrypto LibGfx LibGUI LibMain LibTLS)
target_link_libraries(CertificateSettings PRIVATE LibCore LibCrypto LibFileSystem LibFileSystemAccessClient LibGfx LibGUI LibMain LibTLS)

View file

@ -7,6 +7,9 @@
#include "CertificateStore.h"
#include <Applications/CertificateSettings/CertificateStoreGML.h>
#include <LibCrypto/ASN1/PEM.h>
#include <LibFileSystem/FileSystem.h>
#include <LibFileSystemAccessClient/Client.h>
#include <LibGUI/MessageBox.h>
namespace CertificateSettings {
@ -14,9 +17,15 @@ NonnullRefPtr<CertificateStoreModel> CertificateStoreModel::create() { return ad
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());
auto user_cert_path = TRY(String::formatted("{}/.config/certs.pem", Core::StandardPaths::home_directory()));
if (FileSystem::exists(user_cert_path)) {
auto user_cert_file = TRY(Core::File::open(user_cert_path, Core::File::OpenMode::Read));
TRY(data.try_append(TRY(user_cert_file->read_until_eof())));
}
m_certificates = TRY(DefaultRootCACertificates::the().reload_certificates(data));
return {};
@ -59,6 +68,44 @@ GUI::Variant CertificateStoreModel::data(GUI::ModelIndex const& index, GUI::Mode
return {};
}
ErrorOr<size_t> CertificateStoreModel::add(Vector<Certificate> const& certificates)
{
auto size = m_certificates.size();
TRY(m_certificates.try_extend(certificates));
return m_certificates.size() - size;
}
ErrorOr<void> CertificateStoreWidget::import_pem()
{
auto fsac_result = FileSystemAccessClient::Client::the().open_file(window(), "Choose PEM to import...");
if (fsac_result.is_error())
return {};
auto fsac_file = fsac_result.release_value();
auto filename = fsac_file.filename();
if (!(filename.ends_with_bytes(".pem"sv) || filename.ends_with_bytes(".crt"sv)))
return Error::from_string_view("File is not a .pem or .crt file."sv);
auto data = TRY(fsac_file.release_stream()->read_until_eof());
auto count = TRY(m_root_ca_model->add(TRY(DefaultRootCACertificates::the().reload_certificates(data))));
if (count == 0) {
return Error::from_string_view("No valid CA found to import."sv);
}
auto cert_file = TRY(Core::File::open(TRY(String::formatted("{}/.config/certs.pem", Core::StandardPaths::home_directory())), Core::File::OpenMode::Write | Core::File::OpenMode::Append));
TRY(cert_file->write_until_depleted(data.bytes()));
cert_file->close();
m_root_ca_model->invalidate();
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedTo, 150);
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedBy, 150);
GUI::MessageBox::show(window(), TRY(String::formatted("Successfully imported {} CAs.", count)), "Success"sv);
return {};
}
ErrorOr<NonnullRefPtr<CertificateStoreWidget>> CertificateStoreWidget::try_create()
{
auto widget = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) CertificateStoreWidget()));
@ -80,6 +127,14 @@ ErrorOr<void> CertificateStoreWidget::initialize()
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedTo, 150);
m_root_ca_tableview->set_column_width(CertificateStoreModel::Column::IssuedBy, 150);
m_import_ca_button = find_descendant_of_type_named<GUI::Button>("import_button");
m_import_ca_button->on_click = [&](auto) {
auto import_result = import_pem();
if (import_result.is_error()) {
GUI::MessageBox::show_error(window(), DeprecatedString::formatted("{}", import_result.release_error()));
}
};
return {};
}
}

View file

@ -26,7 +26,6 @@
name: "import_button"
text: "Import"
fixed_width: 80
enabled: false
}
@GUI::Button {

View file

@ -30,6 +30,7 @@ public:
virtual DeprecatedString column_name(int) const override;
virtual GUI::Variant data(GUI::ModelIndex const&, GUI::ModelRole) const override;
virtual ErrorOr<void> load();
virtual ErrorOr<size_t> add(Vector<Certificate> const&);
private:
Vector<Certificate> m_certificates;
@ -45,8 +46,10 @@ public:
private:
CertificateStoreWidget() = default;
ErrorOr<void> initialize();
ErrorOr<void> import_pem();
RefPtr<CertificateStoreModel> m_root_ca_model;
RefPtr<GUI::TableView> m_root_ca_tableview;
RefPtr<GUI::Button> m_import_ca_button;
};
}

View file

@ -6,6 +6,7 @@
#include "CertificateStore.h"
#include <LibCore/StandardPaths.h>
#include <LibCore/System.h>
#include <LibGUI/Application.h>
#include <LibGUI/Icon.h>
@ -19,9 +20,11 @@ ErrorOr<int> serenity_main(Main::Arguments args)
auto app = TRY(GUI::Application::try_create(args));
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil(TRY(String::formatted("{}/.config/certs.pem", Core::StandardPaths::home_directory())), "rwc"_short_string));
TRY(Core::System::unveil("/tmp/session/%sid/portal/filesystemaccess", "rw"));
TRY(Core::System::unveil("/etc/cacert.pem", "r"));
TRY(Core::System::unveil("/etc/timezone", "r"));
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil(nullptr, nullptr));
auto app_icon = GUI::Icon::default_icon("certificate"sv);