From 285a83d6a4095e9b5bde240400fb590bb413234a Mon Sep 17 00:00:00 2001 From: Harshil Jain Date: Tue, 6 Sep 2022 11:57:28 +0530 Subject: [PATCH] Added support for reading system store crtificates in windows --- src/crypto/crypto_context.cc | 95 ++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc index 7eab9de37cb3a1..570f3caf3ff96f 100644 --- a/src/crypto/crypto_context.cc +++ b/src/crypto/crypto_context.cc @@ -18,6 +18,13 @@ #include #endif // !OPENSSL_NO_ENGINE +#ifdef _WIN32 +#include +#include + +#include "base64-inl.h" +#endif + namespace node { using v8::Array; @@ -190,6 +197,62 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, } // namespace +void ReadSystemStoreCertificates( + std::vector* system_root_certificates) { + const HCERTSTORE hStore = CertOpenSystemStoreW(0, L"ROOT"); + CHECK_NE(hStore, NULL); + + auto cleanup = OnScopeLeave( + [hStore]() { CHECK_EQ(CertCloseStore(hStore, 0), TRUE); }); + + PCCERT_CONTEXT pCtx = nullptr; + + while ((pCtx = CertEnumCertificatesInStore(hStore, pCtx)) != nullptr) { + const DWORD cbSize = CertGetNameStringW(pCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, + 0, nullptr, nullptr, 0); + + CHECK_GT(cbSize, 0); + + std::vector pszName(cbSize); + + CHECK_GT(CertGetNameStringW(pCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, + pszName.data(), cbSize), + 0); + + const char* certificate_src_ptr = + reinterpret_cast(pCtx->pbCertEncoded); + const size_t slen = pCtx->cbCertEncoded; + const size_t dlen = base64_encoded_size(slen); + + char* certificate_dst_ptr = UncheckedMalloc(dlen); + + CHECK_NOT_NULL(certificate_dst_ptr); + + auto cleanup = OnScopeLeave( + [certificate_dst_ptr]() { free(certificate_dst_ptr); }); + + const size_t written = base64_encode(certificate_src_ptr, slen, + certificate_dst_ptr, dlen); + CHECK_EQ(written, dlen); + + std::string base64_string_output(certificate_dst_ptr, dlen); + + constexpr size_t distance = 72; + size_t pos = distance; + + while (pos < base64_string_output.size()) { + base64_string_output.insert(pos, "\n"); + pos += distance + 1; + } + + base64_string_output = "-----BEGIN CERTIFICATE-----\n" + + base64_string_output + + "\n-----END CERTIFICATE-----"; + + system_root_certificates->emplace_back(std::move(base64_string_output)); + } +} + X509_STORE* NewRootCertStore() { static std::vector root_certs_vector; static Mutex root_certs_vector_mutex; @@ -197,10 +260,21 @@ X509_STORE* NewRootCertStore() { if (root_certs_vector.empty() && per_process::cli_options->ssl_openssl_cert_store == false) { + + std::vector combined_root_certs; + for (size_t i = 0; i < arraysize(root_certs); i++) { + combined_root_certs.emplace_back(root_certs[i]); + } + +#ifdef _WIN32 + ReadSystemStoreCertificates(&combined_root_certs); +#endif + + for (size_t i = 0; i < combined_root_certs.size(); i++) { X509* x509 = - PEM_read_bio_X509(NodeBIO::NewFixed(root_certs[i], - strlen(root_certs[i])).get(), + PEM_read_bio_X509(NodeBIO::NewFixed(combined_root_certs[i].c_str(), + combined_root_certs[i].length()).get(), nullptr, // no re-use of X509 structure NoPasswordCallback, nullptr); // no callback data @@ -234,19 +308,30 @@ X509_STORE* NewRootCertStore() { void GetRootCertificates(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); - Local result[arraysize(root_certs)]; + + std::vector combined_root_certs; for (size_t i = 0; i < arraysize(root_certs); i++) { + combined_root_certs.emplace_back(root_certs[i]); + } + +#ifdef _WIN32 + ReadSystemStoreCertificates(&combined_root_certs); +#endif + + std::vector> result(combined_root_certs.size()); + + for (size_t i = 0; i < combined_root_certs.size(); i++) { if (!String::NewFromOneByte( env->isolate(), - reinterpret_cast(root_certs[i])) + reinterpret_cast(combined_root_certs[i].c_str())) .ToLocal(&result[i])) { return; } } args.GetReturnValue().Set( - Array::New(env->isolate(), result, arraysize(root_certs))); + Array::New(env->isolate(), result.data(), combined_root_certs.size())); } bool SecureContext::HasInstance(Environment* env, const Local& value) {