Skip to content

Commit

Permalink
Added support for reading system store crtificates in windows
Browse files Browse the repository at this point in the history
  • Loading branch information
twitharshil committed Sep 6, 2022
1 parent 50a4131 commit 285a83d
Showing 1 changed file with 90 additions and 5 deletions.
95 changes: 90 additions & 5 deletions src/crypto/crypto_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
#include <openssl/engine.h>
#endif // !OPENSSL_NO_ENGINE

#ifdef _WIN32
#include <Windows.h>
#include <wincrypt.h>

#include "base64-inl.h"
#endif

namespace node {

using v8::Array;
Expand Down Expand Up @@ -190,17 +197,84 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,

} // namespace

void ReadSystemStoreCertificates(
std::vector<std::string>* 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<wchar_t> pszName(cbSize);

CHECK_GT(CertGetNameStringW(pCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr,
pszName.data(), cbSize),
0);

const char* certificate_src_ptr =
reinterpret_cast<const char*>(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<X509*> root_certs_vector;
static Mutex root_certs_vector_mutex;
Mutex::ScopedLock lock(root_certs_vector_mutex);

if (root_certs_vector.empty() &&
per_process::cli_options->ssl_openssl_cert_store == false) {

std::vector<std::string> 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
Expand Down Expand Up @@ -234,19 +308,30 @@ X509_STORE* NewRootCertStore() {

void GetRootCertificates(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
Local<Value> result[arraysize(root_certs)];

std::vector<std::string> 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<Local<Value>> result(combined_root_certs.size());

for (size_t i = 0; i < combined_root_certs.size(); i++) {
if (!String::NewFromOneByte(
env->isolate(),
reinterpret_cast<const uint8_t*>(root_certs[i]))
reinterpret_cast<const uint8_t*>(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>& value) {
Expand Down

0 comments on commit 285a83d

Please sign in to comment.