diff --git a/Libraries/LibTLS/CMakeLists.txt b/Libraries/LibTLS/CMakeLists.txt index f21dc89a922..6af75ed4a07 100644 --- a/Libraries/LibTLS/CMakeLists.txt +++ b/Libraries/LibTLS/CMakeLists.txt @@ -1,6 +1,7 @@ add_cxx_compile_options(-Wvla) set(SOURCES + DefaultRootCACertificates.cpp Handshake.cpp HandshakeCertificate.cpp HandshakeClient.cpp diff --git a/Libraries/LibTLS/DefaultRootCACertificates.cpp b/Libraries/LibTLS/DefaultRootCACertificates.cpp new file mode 100644 index 00000000000..b545e03e0fe --- /dev/null +++ b/Libraries/LibTLS/DefaultRootCACertificates.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020, Ali Mohammad Pur + * Copyright (c) 2025, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace TLS { + +static Vector s_default_ca_certificate_paths; + +void DefaultRootCACertificates::set_default_certificate_paths(Span paths) +{ + s_default_ca_certificate_paths.clear(); + s_default_ca_certificate_paths.ensure_capacity(paths.size()); + for (auto& path : paths) + s_default_ca_certificate_paths.unchecked_append(path); +} + +DefaultRootCACertificates::DefaultRootCACertificates() +{ + auto load_result = load_certificates(s_default_ca_certificate_paths); + if (load_result.is_error()) { + dbgln("Failed to load CA Certificates: {}", load_result.error()); + return; + } + + m_ca_certificates = load_result.release_value(); +} + +DefaultRootCACertificates& DefaultRootCACertificates::the() +{ + static thread_local DefaultRootCACertificates s_the; + return s_the; +} + +ErrorOr> DefaultRootCACertificates::load_certificates(Span custom_cert_paths) +{ + auto cacert_file_or_error = Core::File::open("/etc/cacert.pem"sv, Core::File::OpenMode::Read); + ByteBuffer data; + if (!cacert_file_or_error.is_error()) + data = TRY(cacert_file_or_error.value()->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()))); + } + + for (auto& custom_cert_path : custom_cert_paths) { + if (FileSystem::exists(custom_cert_path)) { + auto custom_cert_file = TRY(Core::File::open(custom_cert_path, Core::File::OpenMode::Read)); + TRY(data.try_append(TRY(custom_cert_file->read_until_eof()))); + } + } + + return TRY(parse_pem_root_certificate_authorities(data)); +} + +ErrorOr> DefaultRootCACertificates::parse_pem_root_certificate_authorities(ByteBuffer& data) +{ + Vector certificates; + + auto certs = TRY(Crypto::decode_pems(data)); + + for (auto& cert : certs) { + auto certificate_result = Certificate::parse_certificate(cert.data); + if (certificate_result.is_error()) { + // FIXME: It would be nice to have more informations about the certificate we failed to parse. + // Like: Issuer, Algorithm, CN, etc + dbgln("Failed to load certificate: {}", certificate_result.error()); + continue; + } + auto certificate = certificate_result.release_value(); + if (certificate.is_certificate_authority && certificate.is_self_signed()) { + TRY(certificates.try_append(move(certificate))); + } else { + dbgln("Skipped '{}' because it is not a valid root CA", TRY(certificate.subject.to_string())); + } + } + + dbgln_if(TLS_DEBUG, "Loaded {} of {} ({:.2}%) provided CA Certificates", certificates.size(), certs.size(), (certificates.size() * 100.0) / certs.size()); + + return certificates; +} + +} diff --git a/Libraries/LibTLS/DefaultRootCACertificates.h b/Libraries/LibTLS/DefaultRootCACertificates.h new file mode 100644 index 00000000000..0fc0ddc6226 --- /dev/null +++ b/Libraries/LibTLS/DefaultRootCACertificates.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Ali Mohammad Pur + * Copyright (c) 2025, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace TLS { + +using Crypto::Certificate::Certificate; + +class DefaultRootCACertificates { +public: + DefaultRootCACertificates(); + + Vector const& certificates() const { return m_ca_certificates; } + + static ErrorOr> parse_pem_root_certificate_authorities(ByteBuffer&); + static ErrorOr> load_certificates(Span custom_cert_paths = {}); + + static DefaultRootCACertificates& the(); + + static void set_default_certificate_paths(Span paths); + +private: + Vector m_ca_certificates; +}; +} + +using TLS::DefaultRootCACertificates; diff --git a/Libraries/LibTLS/TLSv12.cpp b/Libraries/LibTLS/TLSv12.cpp index 2669fed5501..ac07bd0723f 100644 --- a/Libraries/LibTLS/TLSv12.cpp +++ b/Libraries/LibTLS/TLSv12.cpp @@ -9,18 +9,14 @@ #include #include #include -#include -#include -#include #include #include #include #include #include #include -#include +#include #include -#include namespace TLS { @@ -509,83 +505,6 @@ Vector TLSv12::parse_pem_certificate(ReadonlyBytes certificate_pem_ return { move(certificate) }; } -static Vector s_default_ca_certificate_paths; - -void DefaultRootCACertificates::set_default_certificate_paths(Span paths) -{ - s_default_ca_certificate_paths.clear(); - s_default_ca_certificate_paths.ensure_capacity(paths.size()); - for (auto& path : paths) - s_default_ca_certificate_paths.unchecked_append(path); -} - -DefaultRootCACertificates::DefaultRootCACertificates() -{ - auto load_result = load_certificates(s_default_ca_certificate_paths); - if (load_result.is_error()) { - dbgln("Failed to load CA Certificates: {}", load_result.error()); - return; - } - - m_ca_certificates = load_result.release_value(); -} - -DefaultRootCACertificates& DefaultRootCACertificates::the() -{ - static thread_local DefaultRootCACertificates s_the; - return s_the; -} - -ErrorOr> DefaultRootCACertificates::load_certificates(Span custom_cert_paths) -{ - auto cacert_file_or_error = Core::File::open("/etc/cacert.pem"sv, Core::File::OpenMode::Read); - ByteBuffer data; - if (!cacert_file_or_error.is_error()) - data = TRY(cacert_file_or_error.value()->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()))); - } - - for (auto& custom_cert_path : custom_cert_paths) { - if (FileSystem::exists(custom_cert_path)) { - auto custom_cert_file = TRY(Core::File::open(custom_cert_path, Core::File::OpenMode::Read)); - TRY(data.try_append(TRY(custom_cert_file->read_until_eof()))); - } - } - - return TRY(parse_pem_root_certificate_authorities(data)); -} - -ErrorOr> DefaultRootCACertificates::parse_pem_root_certificate_authorities(ByteBuffer& data) -{ - Vector certificates; - - auto certs = TRY(Crypto::decode_pems(data)); - - for (auto& cert : certs) { - auto certificate_result = Certificate::parse_certificate(cert.data); - if (certificate_result.is_error()) { - // FIXME: It would be nice to have more informations about the certificate we failed to parse. - // Like: Issuer, Algorithm, CN, etc - dbgln("Failed to load certificate: {}", certificate_result.error()); - continue; - } - auto certificate = certificate_result.release_value(); - if (certificate.is_certificate_authority && certificate.is_self_signed()) { - TRY(certificates.try_append(move(certificate))); - } else { - dbgln("Skipped '{}' because it is not a valid root CA", TRY(certificate.subject.to_string())); - } - } - - dbgln_if(TLS_DEBUG, "Loaded {} of {} ({:.2}%) provided CA Certificates", certificates.size(), certs.size(), (certificates.size() * 100.0) / certs.size()); - - return certificates; -} - ErrorOr oid_to_curve(Vector curve) { if (curve == Crypto::ASN1::secp384r1_oid) diff --git a/Libraries/LibTLS/TLSv12.h b/Libraries/LibTLS/TLSv12.h index 74c02dea95c..7c456fd9883 100644 --- a/Libraries/LibTLS/TLSv12.h +++ b/Libraries/LibTLS/TLSv12.h @@ -13,12 +13,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include @@ -553,23 +551,4 @@ private: RefPtr m_handshake_timeout_timer; }; -class DefaultRootCACertificates { -public: - DefaultRootCACertificates(); - - Vector const& certificates() const { return m_ca_certificates; } - - static ErrorOr> parse_pem_root_certificate_authorities(ByteBuffer&); - static ErrorOr> load_certificates(Span custom_cert_paths = {}); - - static DefaultRootCACertificates& the(); - - static void set_default_certificate_paths(Span paths); - -private: - Vector m_ca_certificates; -}; - } - -using TLS::DefaultRootCACertificates; diff --git a/Services/RequestServer/main.cpp b/Services/RequestServer/main.cpp index 1f7ed6c6896..edee16b4538 100644 --- a/Services/RequestServer/main.cpp +++ b/Services/RequestServer/main.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff --git a/Tests/LibTLS/TestTLSHandshake.cpp b/Tests/LibTLS/TestTLSHandshake.cpp index d365fe47320..340f9664ead 100644 --- a/Tests/LibTLS/TestTLSHandshake.cpp +++ b/Tests/LibTLS/TestTLSHandshake.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/Utilities/dns.cpp b/Utilities/dns.cpp index c6b28d7b83c..7e06b42ec4f 100644 --- a/Utilities/dns.cpp +++ b/Utilities/dns.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include ErrorOr serenity_main(Main::Arguments arguments)