@@ -47,10 +47,15 @@ static const char* const root_certs[] = {
4747
4848static const char system_cert_path[] = NODE_OPENSSL_SYSTEM_CERT_PATH;
4949
50- static X509_STORE* root_cert_store;
51-
5250static bool extra_root_certs_loaded = false ;
5351
52+ inline X509_STORE* GetOrCreateRootCertStore () {
53+ static X509_STORE* store;
54+ static uv_once_t once = UV_ONCE_INIT;
55+ uv_once (&once, [] { store = NewRootCertStore (); });
56+ return store;
57+ }
58+
5459// Takes a string or buffer and loads it into a BIO.
5560// Caller responsible for BIO_free_all-ing the returned object.
5661BIOPointer LoadBIO (Environment* env, Local<Value> v) {
@@ -701,7 +706,7 @@ void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
701706 X509_STORE* cert_store = SSL_CTX_get_cert_store (sc->ctx_ .get ());
702707 while (X509Pointer x509 = X509Pointer (PEM_read_bio_X509_AUX (
703708 bio.get (), nullptr , NoPasswordCallback, nullptr ))) {
704- if (cert_store == root_cert_store ) {
709+ if (cert_store == GetOrCreateRootCertStore () ) {
705710 cert_store = NewRootCertStore ();
706711 SSL_CTX_set_cert_store (sc->ctx_ .get (), cert_store);
707712 }
@@ -731,7 +736,7 @@ void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
731736 return THROW_ERR_CRYPTO_OPERATION_FAILED (env, " Failed to parse CRL" );
732737
733738 X509_STORE* cert_store = SSL_CTX_get_cert_store (sc->ctx_ .get ());
734- if (cert_store == root_cert_store ) {
739+ if (cert_store == GetOrCreateRootCertStore () ) {
735740 cert_store = NewRootCertStore ();
736741 SSL_CTX_set_cert_store (sc->ctx_ .get (), cert_store);
737742 }
@@ -745,14 +750,10 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
745750 SecureContext* sc;
746751 ASSIGN_OR_RETURN_UNWRAP (&sc, args.Holder ());
747752 ClearErrorOnReturn clear_error_on_return;
748-
749- if (root_cert_store == nullptr ) {
750- root_cert_store = NewRootCertStore ();
751- }
752-
753+ X509_STORE* store = GetOrCreateRootCertStore ();
753754 // Increment reference count so global store is not deleted along with CTX.
754- X509_STORE_up_ref (root_cert_store );
755- SSL_CTX_set_cert_store (sc->ctx_ .get (), root_cert_store );
755+ X509_STORE_up_ref (store );
756+ SSL_CTX_set_cert_store (sc->ctx_ .get (), store );
756757}
757758
758759void SecureContext::SetCipherSuites (const FunctionCallbackInfo<Value>& args) {
@@ -1025,7 +1026,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
10251026 for (int i = 0 ; i < sk_X509_num (extra_certs.get ()); i++) {
10261027 X509* ca = sk_X509_value (extra_certs.get (), i);
10271028
1028- if (cert_store == root_cert_store ) {
1029+ if (cert_store == GetOrCreateRootCertStore () ) {
10291030 cert_store = NewRootCertStore ();
10301031 SSL_CTX_set_cert_store (sc->ctx_ .get (), cert_store);
10311032 }
@@ -1328,24 +1329,18 @@ unsigned long AddCertsFromFile( // NOLINT(runtime/int)
13281329
13291330// UseExtraCaCerts is called only once at the start of the Node.js process.
13301331void UseExtraCaCerts (const std::string& file) {
1332+ if (file.empty ()) return ;
13311333 ClearErrorOnReturn clear_error_on_return;
1332-
1333- if (root_cert_store == nullptr ) {
1334- root_cert_store = NewRootCertStore ();
1335-
1336- if (!file.empty ()) {
1337- unsigned long err = AddCertsFromFile ( // NOLINT(runtime/int)
1338- root_cert_store,
1339- file.c_str ());
1340- if (err) {
1341- fprintf (stderr,
1342- " Warning: Ignoring extra certs from `%s`, load failed: %s\n " ,
1343- file.c_str (),
1344- ERR_error_string (err, nullptr ));
1345- } else {
1346- extra_root_certs_loaded = true ;
1347- }
1348- }
1334+ X509_STORE* store = GetOrCreateRootCertStore ();
1335+ if (auto err = AddCertsFromFile (store, file.c_str ())) {
1336+ char buf[256 ];
1337+ ERR_error_string_n (err, buf, sizeof (buf));
1338+ fprintf (stderr,
1339+ " Warning: Ignoring extra certs from `%s`, load failed: %s\n " ,
1340+ file.c_str (),
1341+ buf);
1342+ } else {
1343+ extra_root_certs_loaded = true ;
13491344 }
13501345}
13511346
0 commit comments