@@ -95,37 +95,27 @@ struct X509Less {
9595};
9696using X509Set = std::set<ncrypto::X509Pointer, X509Less>;
9797
98- // Per-thread root cert store. See NewRootCertStore() on what it contains.
99- static thread_local DeleteFnPtr<X509_STORE , X509_STORE_free> root_cert_store;
100- // If the user calls tls.setDefaultCACertificates() this will be used
101- // to hold the user-provided certificates, the root_cert_store and any new
102- // copy generated by NewRootCertStore() will then contain the certificates
103- // from this set.
104- static thread_local std::unique_ptr<X509Set> root_certs_from_users;
105- static thread_local bool has_cleanup_hook = false ;
106-
107- static void CleanupRootCertStore (void *) {
108- root_cert_store.reset ();
109- root_certs_from_users.reset ();
110- has_cleanup_hook = false ;
111- }
112-
113- static void EnsureRootCertStoreCleanupHook (Environment* env) {
114- if (env == nullptr || has_cleanup_hook) {
115- return ;
116- }
98+ struct RootCertStore {
99+ // See NewRootCertStore() on what it contains.
100+ DeleteFnPtr<X509_STORE , X509_STORE_free> store;
101+ // Set by tls.setDefaultCACertificates(). Once set, NewRootCertStore()
102+ // copies these certificates instead of loading the defaults.
103+ std::unique_ptr<X509Set> certs_from_users;
104+ };
117105
118- env->AddCleanupHook (CleanupRootCertStore, nullptr );
119- has_cleanup_hook = true ;
106+ void FreeRootCertStore (RootCertStore* root_certs) {
107+ delete root_certs;
108+ }
109+
110+ static RootCertStore* GetRootCertStore (Environment* env) {
111+ if (!env->root_cert_store ) env->root_cert_store .reset (new RootCertStore ());
112+ return env->root_cert_store .get ();
120113}
121114
122115X509_STORE * GetOrCreateRootCertStore (Environment* env) {
123- EnsureRootCertStoreCleanupHook (env);
124- if (root_cert_store != nullptr ) {
125- return root_cert_store.get ();
126- }
127- root_cert_store.reset (NewRootCertStore (env));
128- return root_cert_store.get ();
116+ RootCertStore* root_certs = GetRootCertStore (env);
117+ if (!root_certs->store ) root_certs->store .reset (NewRootCertStore (env));
118+ return root_certs->store .get ();
129119}
130120
131121// Takes a string or buffer and loads it into a BIO.
@@ -1062,8 +1052,10 @@ X509_STORE* NewRootCertStore(Environment* env) {
10621052 // If the root cert store is already reset by users through
10631053 // tls.setDefaultCACertificates(), just create a copy from the
10641054 // user-provided certificates.
1065- if (root_certs_from_users != nullptr ) {
1066- for (const auto & cert : *root_certs_from_users) {
1055+ const X509Set* certs_from_users =
1056+ env != nullptr ? GetRootCertStore (env)->certs_from_users .get () : nullptr ;
1057+ if (certs_from_users != nullptr ) {
1058+ for (const auto & cert : *certs_from_users) {
10671059 CHECK_EQ (1 , X509_STORE_add_cert (store, cert.get ()));
10681060 }
10691061 return store;
@@ -1230,12 +1222,13 @@ MaybeLocal<Array> X509sToArrayOfStrings(Environment* env,
12301222
12311223void GetUserRootCertificates (const FunctionCallbackInfo<Value>& args) {
12321224 Environment* env = Environment::GetCurrent (args);
1233- CHECK_NOT_NULL (root_certs_from_users);
1225+ const auto & certs_from_users = GetRootCertStore (env)->certs_from_users ;
1226+ CHECK (certs_from_users);
12341227 Local<Array> results;
12351228 if (X509sToArrayOfStrings (env,
1236- root_certs_from_users ->begin (),
1237- root_certs_from_users ->end (),
1238- root_certs_from_users ->size ())
1229+ certs_from_users ->begin (),
1230+ certs_from_users ->end (),
1231+ certs_from_users ->size ())
12391232 .ToLocal (&results)) {
12401233 args.GetReturnValue ().Set (results);
12411234 }
@@ -1246,12 +1239,12 @@ void ResetRootCertStore(const FunctionCallbackInfo<Value>& args) {
12461239 CHECK (args[0 ]->IsArray ());
12471240 Local<Array> cert_array = args[0 ].As <Array>();
12481241 Environment* env = Environment::GetCurrent (context);
1249- EnsureRootCertStoreCleanupHook (env);
1242+ RootCertStore* root_certs = GetRootCertStore (env);
12501243
12511244 if (cert_array->Length () == 0 ) {
12521245 // If the array is empty, just clear the user certs and reset the store.
1253- root_cert_store .reset ();
1254- root_certs_from_users = std::make_unique<X509Set>();
1246+ root_certs-> store .reset ();
1247+ root_certs-> certs_from_users = std::make_unique<X509Set>();
12551248 return ;
12561249 }
12571250
@@ -1263,7 +1256,6 @@ void ResetRootCertStore(const FunctionCallbackInfo<Value>& args) {
12631256 }
12641257
12651258 if (certs->empty ()) {
1266- Environment* env = Environment::GetCurrent (context);
12671259 return THROW_ERR_CRYPTO_OPERATION_FAILED (
12681260 env, " No valid certificates found in the provided array" );
12691261 }
@@ -1275,11 +1267,11 @@ void ResetRootCertStore(const FunctionCallbackInfo<Value>& args) {
12751267 // is not consumed by insert (element already exists).
12761268 }
12771269
1278- root_certs_from_users = std::move (new_set);
1270+ root_certs-> certs_from_users = std::move (new_set);
12791271
1280- // Reset the global root cert store so it will be recreated with the
1281- // new certificates.
1282- root_cert_store .reset ();
1272+ // Reset the root cert store so it will be recreated with the new
1273+ // certificates.
1274+ root_certs-> store .reset ();
12831275}
12841276
12851277void GetSystemCACertificates (const FunctionCallbackInfo<Value>& args) {
0 commit comments