summaryrefslogtreecommitdiff
path: root/Userland/Applications/CertificateSettings
diff options
context:
space:
mode:
authorFabian Dellwing <fabian.dellwing@gmail.com>2023-04-01 13:05:47 +0200
committerAndrew Kaster <andrewdkaster@gmail.com>2023-04-03 19:58:47 -0600
commit7ce75ee3c5db93aa0e24d6dda6bd33be04222d3d (patch)
treeaf99290c60c85c6f01d03c6e96464b3456541edb /Userland/Applications/CertificateSettings
parentc273784c3efad395a913715c793feffc91f16743 (diff)
downloadserenity-7ce75ee3c5db93aa0e24d6dda6bd33be04222d3d.zip
CertificateSettings: Add import functionality
Diffstat (limited to 'Userland/Applications/CertificateSettings')
-rw-r--r--Userland/Applications/CertificateSettings/CMakeLists.txt2
-rw-r--r--Userland/Applications/CertificateSettings/CertificateStore.cpp57
-rw-r--r--Userland/Applications/CertificateSettings/CertificateStore.gml1
-rw-r--r--Userland/Applications/CertificateSettings/CertificateStore.h3
-rw-r--r--Userland/Applications/CertificateSettings/main.cpp5
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);