diff options
author | Fabian Dellwing <fabian.dellwing@gmail.com> | 2023-04-01 13:05:47 +0200 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2023-04-03 19:58:47 -0600 |
commit | 7ce75ee3c5db93aa0e24d6dda6bd33be04222d3d (patch) | |
tree | af99290c60c85c6f01d03c6e96464b3456541edb /Userland/Applications/CertificateSettings | |
parent | c273784c3efad395a913715c793feffc91f16743 (diff) | |
download | serenity-7ce75ee3c5db93aa0e24d6dda6bd33be04222d3d.zip |
CertificateSettings: Add import functionality
Diffstat (limited to 'Userland/Applications/CertificateSettings')
5 files changed, 64 insertions, 4 deletions
diff --git a/Userland/Applications/CertificateSettings/CMakeLists.txt b/Userland/Applications/CertificateSettings/CMakeLists.txt index 26d4e6fec9..c36a82de5c 100644 --- a/Userland/Applications/CertificateSettings/CMakeLists.txt +++ b/Userland/Applications/CertificateSettings/CMakeLists.txt @@ -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) diff --git a/Userland/Applications/CertificateSettings/CertificateStore.cpp b/Userland/Applications/CertificateSettings/CertificateStore.cpp index 4101bbed03..a036954c8a 100644 --- a/Userland/Applications/CertificateSettings/CertificateStore.cpp +++ b/Userland/Applications/CertificateSettings/CertificateStore.cpp @@ -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 {}; } } diff --git a/Userland/Applications/CertificateSettings/CertificateStore.gml b/Userland/Applications/CertificateSettings/CertificateStore.gml index 4385b34109..d8bac71955 100644 --- a/Userland/Applications/CertificateSettings/CertificateStore.gml +++ b/Userland/Applications/CertificateSettings/CertificateStore.gml @@ -26,7 +26,6 @@ name: "import_button" text: "Import" fixed_width: 80 - enabled: false } @GUI::Button { diff --git a/Userland/Applications/CertificateSettings/CertificateStore.h b/Userland/Applications/CertificateSettings/CertificateStore.h index ffcc3fd4f1..8369b00cb2 100644 --- a/Userland/Applications/CertificateSettings/CertificateStore.h +++ b/Userland/Applications/CertificateSettings/CertificateStore.h @@ -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; }; } diff --git a/Userland/Applications/CertificateSettings/main.cpp b/Userland/Applications/CertificateSettings/main.cpp index e434f6c88c..48a22a81af 100644 --- a/Userland/Applications/CertificateSettings/main.cpp +++ b/Userland/Applications/CertificateSettings/main.cpp @@ -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); |