summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibTLS
diff options
context:
space:
mode:
authorFabian Dellwing <fabian.dellwing@gmail.com>2023-03-14 14:14:01 +0100
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2023-03-16 18:54:20 +0330
commit12cd74495acc0e8ca0516406c29b4ace45d62133 (patch)
tree68664f9616465f637a5fb206a9cd04389e599eb4 /Userland/Libraries/LibTLS
parentda6130a6d81cc1e485fa36998acd754ec7793090 (diff)
downloadserenity-12cd74495acc0e8ca0516406c29b4ace45d62133.zip
LibTLS+Base: Rework default system certificate parser
Change the default system certificate parser from our arbitrary INI format to well-known PEM format.
Diffstat (limited to 'Userland/Libraries/LibTLS')
-rw-r--r--Userland/Libraries/LibTLS/Certificate.h2
-rw-r--r--Userland/Libraries/LibTLS/TLSv12.cpp63
2 files changed, 38 insertions, 27 deletions
diff --git a/Userland/Libraries/LibTLS/Certificate.h b/Userland/Libraries/LibTLS/Certificate.h
index d56e5abb20..694c737927 100644
--- a/Userland/Libraries/LibTLS/Certificate.h
+++ b/Userland/Libraries/LibTLS/Certificate.h
@@ -132,7 +132,7 @@ public:
Vector<Certificate> const& certificates() const { return m_ca_certificates; }
- void reload_certificates(Core::ConfigFile&);
+ void reload_certificates(ByteBuffer&);
static DefaultRootCACertificates& the() { return s_the; }
diff --git a/Userland/Libraries/LibTLS/TLSv12.cpp b/Userland/Libraries/LibTLS/TLSv12.cpp
index 4228f1a665..bde92fa923 100644
--- a/Userland/Libraries/LibTLS/TLSv12.cpp
+++ b/Userland/Libraries/LibTLS/TLSv12.cpp
@@ -9,11 +9,13 @@
#include <AK/Endian.h>
#include <LibCore/ConfigFile.h>
#include <LibCore/DateTime.h>
+#include <LibCore/File.h>
#include <LibCore/Timer.h>
#include <LibCrypto/ASN1/ASN1.h>
#include <LibCrypto/ASN1/PEM.h>
#include <LibCrypto/PK/Code/EMSA_PKCS1_V1_5.h>
#include <LibCrypto/PK/Code/EMSA_PSS.h>
+#include <LibTLS/Certificate.h>
#include <LibTLS/TLSv12.h>
#include <errno.h>
@@ -468,40 +470,49 @@ Vector<Certificate> TLSv12::parse_pem_certificate(ReadonlyBytes certificate_pem_
Singleton<DefaultRootCACertificates> DefaultRootCACertificates::s_the;
DefaultRootCACertificates::DefaultRootCACertificates()
{
- // FIXME: This might not be the best format, find a better way to represent CA certificates.
- auto config_result = Core::ConfigFile::open_for_system("ca_certs");
- if (config_result.is_error()) {
- dbgln("Failed to load CA Certificates: {}", config_result.error());
+ auto cacert_result = Core::File::open("/etc/cacert.pem"sv, Core::File::OpenMode::Read);
+ if (cacert_result.is_error()) {
+ dbgln("Failed to load CA Certificates: {}", cacert_result.error());
return;
}
- auto config = config_result.release_value();
- reload_certificates(config);
+ auto cacert_file = cacert_result.release_value();
+ auto data_result = cacert_file->read_until_eof();
+ if (data_result.is_error()) {
+ dbgln("Failed to load CA Certificates: {}", data_result.error());
+ return;
+ }
+ auto data = data_result.release_value();
+ reload_certificates(data);
}
-void DefaultRootCACertificates::reload_certificates(Core::ConfigFile& config)
+void DefaultRootCACertificates::reload_certificates(ByteBuffer& data)
{
+ auto decode_result = Crypto::decode_pems(data);
+ if (decode_result.is_error()) {
+ dbgln("Failed to load CA Certificates: {}", decode_result.error());
+ return;
+ }
m_ca_certificates.clear();
- for (auto& entity : config.groups()) {
- for (auto& subject : config.keys(entity)) {
- auto certificate_base64 = config.read_entry(entity, subject);
- auto certificate_data_result = decode_base64(certificate_base64);
- if (certificate_data_result.is_error()) {
- dbgln("Skipping CA Certificate {} {}: out of memory", entity, subject);
- continue;
- }
- auto certificate_data = certificate_data_result.release_value();
- auto certificate_result = Certificate::parse_asn1(certificate_data.bytes());
- // If the certificate does not parse it is likely using elliptic curve keys/signatures, which are not
- // supported right now. Currently, ca_certs.ini should only contain certificates with RSA keys/signatures.
- if (!certificate_result.has_value()) {
- dbgln("Skipping CA Certificate {} {}: unable to parse", entity, subject);
- continue;
- }
- auto certificate = certificate_result.release_value();
- m_ca_certificates.append(move(certificate));
+ auto certs = decode_result.release_value();
+
+ for (auto& cert : certs) {
+ auto certificate_result = Certificate::parse_asn1(cert.bytes());
+ // If the certificate does not parse it is likely using elliptic curve keys/signatures, which are not
+ // supported right now. It might make sense to cleanup cacert.pem before adding it to the system.
+ if (!certificate_result.has_value()) {
+ // FIXME: It would be nice to have more informations about the certificate we failed to parse.
+ // Like: Issuer, Algorithm, CN, etc
+ continue;
}
+ auto certificate = certificate_result.release_value();
+ // FIXME: We might want to check additional things here to make sure we only load root CAs:
+ // - Root certificates are self-signed
+ // - Either it has matched Authority Key Identifier with Subject Key Identifier,
+ // - in some cases there is no Authority Key identifier, then Issuer string should match with Subject string
+ if (certificate.is_certificate_authority)
+ m_ca_certificates.append(move(certificate));
}
- dbgln("Loaded {} CA Certificates", m_ca_certificates.size());
+ dbgln("Loaded {} of {} ({:.2}%) provided CA Certificates", m_ca_certificates.size(), certs.size(), (m_ca_certificates.size() * 100.0) / certs.size());
}
}