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:
parent
c273784c3e
commit
7ce75ee3c5
5 changed files with 64 additions and 4 deletions
|
@ -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)
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
name: "import_button"
|
||||
text: "Import"
|
||||
fixed_width: 80
|
||||
enabled: false
|
||||
}
|
||||
|
||||
@GUI::Button {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue