Skip to content

Commit 38913f9

Browse files
committed
crypto: make --use-system-ca per-env rather than per-process
1 parent 47d8b88 commit 38913f9

13 files changed

+269
-47
lines changed

src/crypto/crypto_common.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
6161
(err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) ||
6262
(err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) ||
6363
((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) &&
64-
!per_process::cli_options->use_system_ca);
64+
!env->options()->use_system_ca);
6565

6666
if (suggest_system_ca) {
6767
reason.append("; if the root CA is installed locally, "

src/crypto/crypto_context.cc

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ static thread_local X509_STORE* root_cert_store = nullptr;
101101
// from this set.
102102
static thread_local std::unique_ptr<X509Set> root_certs_from_users;
103103

104-
X509_STORE* GetOrCreateRootCertStore() {
104+
X509_STORE* GetOrCreateRootCertStore(Environment* env) {
105105
if (root_cert_store != nullptr) {
106106
return root_cert_store;
107107
}
108-
root_cert_store = NewRootCertStore();
108+
root_cert_store = NewRootCertStore(env);
109109
return root_cert_store;
110110
}
111111

@@ -861,6 +861,7 @@ static std::vector<X509*>& GetExtraCACertificates() {
861861
}
862862

863863
static void LoadCACertificates(void* data) {
864+
Environment* env = static_cast<Environment*>(data);
864865
per_process::Debug(DebugCategory::CRYPTO,
865866
"Started loading bundled root certificates off-thread\n");
866867
GetBundledRootCertificates();
@@ -873,7 +874,7 @@ static void LoadCACertificates(void* data) {
873874

874875
{
875876
Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex);
876-
if (!per_process::cli_options->use_system_ca) {
877+
if (!env->options()->use_system_ca) {
877878
return;
878879
}
879880
}
@@ -917,7 +918,8 @@ void StartLoadingCertificatesOffThread(
917918
return;
918919
}
919920
tried_cert_loading_off_thread.store(true);
920-
int r = uv_thread_create(&cert_loading_thread, LoadCACertificates, nullptr);
921+
Environment* env = Environment::GetCurrent(args);
922+
int r = uv_thread_create(&cert_loading_thread, LoadCACertificates, env);
921923
cert_loading_thread_started.store(r == 0);
922924
if (r != 0) {
923925
FPrintF(stderr,
@@ -947,13 +949,13 @@ void StartLoadingCertificatesOffThread(
947949
// with all the other flags.
948950
// 7. Certificates from --use-bundled-ca, --use-system-ca and
949951
// NODE_EXTRA_CA_CERTS are cached after first load. Certificates
950-
// from --use-system-ca are not cached and always reloaded from
952+
// from --use-openssl-ca are not cached and always reloaded from
951953
// disk.
952954
// 8. If users have reset the root cert store by calling
953955
// tls.setDefaultCACertificates(), the store will be populated with
954956
// the certificates provided by users.
955957
// TODO(joyeecheung): maybe these rules need a bit of consolidation?
956-
X509_STORE* NewRootCertStore() {
958+
X509_STORE* NewRootCertStore(Environment* env) {
957959
X509_STORE* store = X509_STORE_new();
958960
CHECK_NOT_NULL(store);
959961

@@ -982,7 +984,7 @@ X509_STORE* NewRootCertStore() {
982984
for (X509* cert : GetBundledRootCertificates()) {
983985
CHECK_EQ(1, X509_STORE_add_cert(store, cert));
984986
}
985-
if (per_process::cli_options->use_system_ca) {
987+
if (env->options()->use_system_ca) {
986988
for (X509* cert : GetSystemStoreCACertificates()) {
987989
CHECK_EQ(1, X509_STORE_add_cert(store, cert));
988990
}
@@ -1189,7 +1191,7 @@ void ResetRootCertStore(const FunctionCallbackInfo<Value>& args) {
11891191

11901192
// TODO(joyeecheung): we can probably just reset it to nullptr
11911193
// and let the next call to NewRootCertStore() create a new one.
1192-
root_cert_store = NewRootCertStore();
1194+
root_cert_store = nullptr;
11931195
}
11941196

11951197
void GetSystemCACertificates(const FunctionCallbackInfo<Value>& args) {
@@ -1700,11 +1702,12 @@ void SecureContext::SetX509StoreFlag(unsigned long flags) {
17001702
}
17011703

17021704
X509_STORE* SecureContext::GetCertStoreOwnedByThisSecureContext() {
1705+
Environment* env = this->env();
17031706
if (own_cert_store_cache_ != nullptr) return own_cert_store_cache_;
17041707

17051708
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
1706-
if (cert_store == GetOrCreateRootCertStore()) {
1707-
cert_store = NewRootCertStore();
1709+
if (cert_store == GetOrCreateRootCertStore(env)) {
1710+
cert_store = NewRootCertStore(env);
17081711
SSL_CTX_set_cert_store(ctx_.get(), cert_store);
17091712
}
17101713

@@ -1777,7 +1780,8 @@ void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
17771780

17781781
void SecureContext::SetRootCerts() {
17791782
ClearErrorOnReturn clear_error_on_return;
1780-
auto store = GetOrCreateRootCertStore();
1783+
Environment* env = this->env();
1784+
auto store = GetOrCreateRootCertStore(env);
17811785

17821786
// Increment reference count so global store is not deleted along with CTX.
17831787
X509_STORE_up_ref(store);

src/crypto/crypto_context.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ constexpr int kMaxSupportedVersion = TLS1_3_VERSION;
1919
void GetRootCertificates(
2020
const v8::FunctionCallbackInfo<v8::Value>& args);
2121

22-
X509_STORE* NewRootCertStore();
22+
X509_STORE* NewRootCertStore(Environment* env);
2323

24-
X509_STORE* GetOrCreateRootCertStore();
24+
X509_STORE* GetOrCreateRootCertStore(Environment* env);
2525

2626
ncrypto::BIOPointer LoadBIO(Environment* env, v8::Local<v8::Value> v);
2727

src/node.cc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -871,15 +871,6 @@ static ExitCode InitializeNodeWithArgsInternal(
871871
// default value.
872872
V8::SetFlagsFromString("--rehash-snapshot");
873873

874-
#if HAVE_OPENSSL
875-
// TODO(joyeecheung): make this a per-env option and move the normalization
876-
// into HandleEnvOptions.
877-
std::string use_system_ca;
878-
if (credentials::SafeGetenv("NODE_USE_SYSTEM_CA", &use_system_ca) &&
879-
use_system_ca == "1") {
880-
per_process::cli_options->use_system_ca = true;
881-
}
882-
#endif // HAVE_OPENSSL
883874
HandleEnvOptions(per_process::cli_options->per_isolate->per_env);
884875

885876
std::string node_options;

src/node_options.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
10161016
&EnvironmentOptions::trace_env_native_stack,
10171017
kAllowedInEnvvar);
10181018

1019+
AddOption("--use-system-ca",
1020+
"use system's CA store",
1021+
&EnvironmentOptions::use_system_ca,
1022+
kAllowedInEnvvar);
1023+
10191024
AddOption(
10201025
"--trace-require-module",
10211026
"Print access to require(esm). Options are 'all' (print all usage) and "
@@ -1356,10 +1361,6 @@ PerProcessOptionsParser::PerProcessOptionsParser(
13561361
,
13571362
&PerProcessOptions::use_openssl_ca,
13581363
kAllowedInEnvvar);
1359-
AddOption("--use-system-ca",
1360-
"use system's CA store",
1361-
&PerProcessOptions::use_system_ca,
1362-
kAllowedInEnvvar);
13631364
AddOption("--use-bundled-ca",
13641365
"use bundled CA store"
13651366
#if !defined(NODE_OPENSSL_CERT_STORE)
@@ -2098,6 +2099,10 @@ void HandleEnvOptions(std::shared_ptr<EnvironmentOptions> env_options,
20982099

20992100
env_options->use_env_proxy = opt_getter("NODE_USE_ENV_PROXY") == "1";
21002101

2102+
#if HAVE_OPENSSL
2103+
env_options->use_system_ca = opt_getter("NODE_USE_SYSTEM_CA") == "1";
2104+
#endif // HAVE_OPENSSL
2105+
21012106
if (env_options->redirect_warnings.empty())
21022107
env_options->redirect_warnings = opt_getter("NODE_REDIRECT_WARNINGS");
21032108
}

src/node_options.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ class EnvironmentOptions : public Options {
221221
bool trace_env = false;
222222
bool trace_env_js_stack = false;
223223
bool trace_env_native_stack = false;
224+
bool use_system_ca = false;
224225
std::string trace_require_module;
225226
bool extra_info_on_fatal_exception = true;
226227
std::string unhandled_rejections;
@@ -357,7 +358,6 @@ class PerProcessOptions : public Options {
357358
bool ssl_openssl_cert_store = false;
358359
#endif
359360
bool use_openssl_ca = false;
360-
bool use_system_ca = false;
361361
bool use_bundled_ca = false;
362362
bool enable_fips_crypto = false;
363363
bool force_fips_crypto = false;

src/quic/endpoint.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ void Endpoint::Listen(const Session::Options& options) {
895895
"not what you want.");
896896
}
897897

898-
auto context = TLSContext::CreateServer(options.tls_options);
898+
auto context = TLSContext::CreateServer(env(), options.tls_options);
899899
if (!*context) {
900900
THROW_ERR_INVALID_STATE(
901901
env(), "Failed to create TLS context: %s", context->validation_error());
@@ -928,7 +928,7 @@ BaseObjectPtr<Session> Endpoint::Connect(
928928
config,
929929
session_ticket.has_value() ? "yes" : "no");
930930

931-
auto tls_context = TLSContext::CreateClient(options.tls_options);
931+
auto tls_context = TLSContext::CreateClient(env(), options.tls_options);
932932
if (!*tls_context) {
933933
THROW_ERR_INVALID_STATE(env(),
934934
"Failed to create TLS context: %s",

src/quic/tlscontext.cc

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -293,16 +293,18 @@ bool OSSLContext::ConfigureClient() const {
293293

294294
// ============================================================================
295295

296-
std::shared_ptr<TLSContext> TLSContext::CreateClient(const Options& options) {
297-
return std::make_shared<TLSContext>(Side::CLIENT, options);
296+
std::shared_ptr<TLSContext> TLSContext::CreateClient(Environment* env,
297+
const Options& options) {
298+
return std::make_shared<TLSContext>(env, Side::CLIENT, options);
298299
}
299300

300-
std::shared_ptr<TLSContext> TLSContext::CreateServer(const Options& options) {
301-
return std::make_shared<TLSContext>(Side::SERVER, options);
301+
std::shared_ptr<TLSContext> TLSContext::CreateServer(Environment* env,
302+
const Options& options) {
303+
return std::make_shared<TLSContext>(env, Side::SERVER, options);
302304
}
303305

304-
TLSContext::TLSContext(Side side, const Options& options)
305-
: side_(side), options_(options), ctx_(Initialize()) {}
306+
TLSContext::TLSContext(Environment* env, Side side, const Options& options)
307+
: side_(side), options_(options), env_(env), ctx_(Initialize()) {}
306308

307309
TLSContext::operator SSL_CTX*() const {
308310
DCHECK(ctx_);
@@ -460,14 +462,14 @@ SSLCtxPointer TLSContext::Initialize() {
460462
{
461463
ClearErrorOnReturn clear_error_on_return;
462464
if (options_.ca.empty()) {
463-
auto store = crypto::GetOrCreateRootCertStore();
465+
auto store = crypto::GetOrCreateRootCertStore(env_);
464466
X509_STORE_up_ref(store);
465467
SSL_CTX_set_cert_store(ctx.get(), store);
466468
} else {
467469
for (const auto& ca : options_.ca) {
468470
uv_buf_t buf = ca;
469471
if (buf.len == 0) {
470-
auto store = crypto::GetOrCreateRootCertStore();
472+
auto store = crypto::GetOrCreateRootCertStore(env_);
471473
X509_STORE_up_ref(store);
472474
SSL_CTX_set_cert_store(ctx.get(), store);
473475
} else {
@@ -477,8 +479,8 @@ SSLCtxPointer TLSContext::Initialize() {
477479
while (
478480
auto x509 = X509Pointer(PEM_read_bio_X509_AUX(
479481
bio.get(), nullptr, crypto::NoPasswordCallback, nullptr))) {
480-
if (cert_store == crypto::GetOrCreateRootCertStore()) {
481-
cert_store = crypto::NewRootCertStore();
482+
if (cert_store == crypto::GetOrCreateRootCertStore(env_)) {
483+
cert_store = crypto::NewRootCertStore(env_);
482484
SSL_CTX_set_cert_store(ctx.get(), cert_store);
483485
}
484486
CHECK_EQ(1, X509_STORE_add_cert(cert_store, x509.get()));
@@ -535,8 +537,8 @@ SSLCtxPointer TLSContext::Initialize() {
535537
}
536538

537539
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx.get());
538-
if (cert_store == crypto::GetOrCreateRootCertStore()) {
539-
cert_store = crypto::NewRootCertStore();
540+
if (cert_store == crypto::GetOrCreateRootCertStore(env_)) {
541+
cert_store = crypto::NewRootCertStore(env_);
540542
SSL_CTX_set_cert_store(ctx.get(), cert_store);
541543
}
542544

src/quic/tlscontext.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,12 @@ class TLSContext final : public MemoryRetainer,
229229
std::string ToString() const;
230230
};
231231

232-
static std::shared_ptr<TLSContext> CreateClient(const Options& options);
233-
static std::shared_ptr<TLSContext> CreateServer(const Options& options);
232+
static std::shared_ptr<TLSContext> CreateClient(Environment* env,
233+
const Options& options);
234+
static std::shared_ptr<TLSContext> CreateServer(Environment* env,
235+
const Options& options);
234236

235-
TLSContext(Side side, const Options& options);
237+
TLSContext(Environment* env, Side side, const Options& options);
236238
DISALLOW_COPY_AND_MOVE(TLSContext)
237239

238240
// Each QUIC Session has exactly one TLSSession. Each TLSSession maintains
@@ -242,6 +244,7 @@ class TLSContext final : public MemoryRetainer,
242244

243245
inline Side side() const { return side_; }
244246
inline const Options& options() const { return options_; }
247+
inline Environment* env() const { return env_; }
245248
inline operator bool() const { return ctx_ != nullptr; }
246249
inline operator const ncrypto::SSLCtxPointer&() const { return ctx_; }
247250

@@ -269,6 +272,7 @@ class TLSContext final : public MemoryRetainer,
269272

270273
Side side_;
271274
Options options_;
275+
Environment* env_;
272276
ncrypto::X509Pointer cert_;
273277
ncrypto::X509Pointer issuer_;
274278
ncrypto::SSLCtxPointer ctx_;

test/cctest/test_node_crypto.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
TEST(NodeCrypto, NewRootCertStore) {
1717
node::per_process::cli_options->ssl_openssl_cert_store = true;
18-
X509_STORE* store = node::crypto::NewRootCertStore();
18+
X509_STORE* store = node::crypto::NewRootCertStore(nullptr);
1919
ASSERT_TRUE(store);
2020
ASSERT_EQ(ERR_peek_error(), 0UL) << "NewRootCertStore should not have left "
2121
"any errors on the OpenSSL error stack\n";

0 commit comments

Comments
 (0)