diff options
Diffstat (limited to 'Userland/Libraries/LibTLS/TLSv12.cpp')
-rw-r--r-- | Userland/Libraries/LibTLS/TLSv12.cpp | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/Userland/Libraries/LibTLS/TLSv12.cpp b/Userland/Libraries/LibTLS/TLSv12.cpp index 572c778e52..ab95df9e1c 100644 --- a/Userland/Libraries/LibTLS/TLSv12.cpp +++ b/Userland/Libraries/LibTLS/TLSv12.cpp @@ -191,7 +191,31 @@ void TLSv12::set_root_certificates(Vector<Certificate> certificates) dbgln_if(TLS_DEBUG, "{}: Set {} root certificates", this, m_context.root_certificates.size()); } -bool Context::verify_chain() const +static bool wildcard_matches(StringView host, StringView subject) +{ + if (host.matches(subject)) + return true; + + if (subject.starts_with("*.")) + return wildcard_matches(host, subject.substring_view(2)); + + return false; +} + +static bool certificate_subject_matches_host(Certificate& cert, StringView host) +{ + if (wildcard_matches(host, cert.subject.subject)) + return true; + + for (auto& san : cert.SAN) { + if (wildcard_matches(host, san)) + return true; + } + + return false; +} + +bool Context::verify_chain(StringView host) const { if (!options.validate_certificates) return true; @@ -209,6 +233,19 @@ bool Context::verify_chain() const return false; } + if (!host.is_empty()) { + auto first_certificate = local_chain->first(); + auto subject_matches = certificate_subject_matches_host(first_certificate, host); + if (!subject_matches) { + dbgln("verify_chain: First certificate does not match the hostname"); + return false; + } + } else { + // FIXME: The host is taken from m_context.extensions.SNI, when is this empty? + dbgln("FIXME: verify_chain called without host"); + return false; + } + for (size_t cert_index = 0; cert_index < local_chain->size(); ++cert_index) { auto cert = local_chain->at(cert_index); |