@@ -60,6 +60,47 @@ X509_STORE* GetOrCreateRootCertStore() {
60
60
return store;
61
61
}
62
62
63
+
64
+ // copies an X509_STORE object, including the certificates and crls it contains.
65
+ X509_STORE* CopyX509Store (X509_STORE* src) {
66
+ // create a new X509_STORE
67
+ X509_STORE* dest = X509_STORE_new ();
68
+
69
+ if (*system_cert_path != ' \0 ' ) {
70
+ ERR_set_mark ();
71
+ X509_STORE_load_locations (dest, system_cert_path, nullptr );
72
+ ERR_pop_to_mark ();
73
+ }
74
+
75
+ if (per_process::cli_options->ssl_openssl_cert_store ) {
76
+ CHECK_EQ (1 , X509_STORE_set_default_paths (dest));
77
+ }
78
+
79
+ // copy flags
80
+ X509_STORE_set1_param (dest, X509_STORE_get0_param (src));
81
+
82
+ // get the certificates and crls from the source store
83
+ STACK_OF (X509_OBJECT)* objs = X509_STORE_get0_objects (src);
84
+ for (int i = 0 ; i < sk_X509_OBJECT_num (objs); i++) {
85
+ X509_OBJECT* obj = sk_X509_OBJECT_value (objs, i);
86
+ int type = X509_OBJECT_get_type (obj);
87
+ if (type == X509_LU_X509) {
88
+ // copy certs
89
+ X509* x509 = X509_OBJECT_get0_X509 (obj);
90
+ X509_up_ref (x509);
91
+ X509_STORE_add_cert (dest, x509);
92
+ } else if (type == X509_LU_CRL) {
93
+ // copy crls
94
+ X509_CRL* crl = X509_OBJECT_get0_X509_CRL (obj);
95
+ X509_CRL_up_ref (crl);
96
+ X509_STORE_add_crl (dest, crl);
97
+ }
98
+ }
99
+
100
+ return dest;
101
+ }
102
+
103
+
63
104
// Takes a string or buffer and loads it into a BIO.
64
105
// Caller responsible for BIO_free_all-ing the returned object.
65
106
BIOPointer LoadBIO (Environment* env, Local<Value> v) {
@@ -785,9 +826,19 @@ void SecureContext::SetCACert(const BIOPointer& bio) {
785
826
if (!bio) return ;
786
827
while (X509Pointer x509 = X509Pointer (PEM_read_bio_X509_AUX (
787
828
bio.get (), nullptr , NoPasswordCallback, nullptr ))) {
788
- CHECK_EQ (1 ,
789
- X509_STORE_add_cert (GetCertStoreOwnedByThisSecureContext (),
790
- x509.get ()));
829
+ // Avoid calling GetCertStoreOwnedByThisSecureContext() in SetCACert method
830
+ // because it will create X509_STORE based on root_certs (more than 150) and is very slow
831
+
832
+ if (!own_cert_store_cache_) {
833
+ // Is cert_store here a globally shared root cert store? There are two possibilities
834
+ // 1. AddRootCerts has been called, and cert_store is a globally shared root cert store
835
+ // 2. AddRootCerts has not been called, and cert_store is the default cert store of OpenSSL
836
+ // Directly creating a new store is not a correct implementation of copy on write
837
+ SSL_CTX_set_cert_store (ctx_.get (), own_cert_store_cache_ = CopyX509Store (SSL_CTX_get_cert_store (ctx_.get ())));
838
+ // No need to call X509_STORE_free manually, SSL_CTX_set_cert_store will take over the ownership of X509_STORE
839
+ }
840
+
841
+ CHECK_EQ (1 , X509_STORE_add_cert (own_cert_store_cache_, x509.get ()));
791
842
CHECK_EQ (1 , SSL_CTX_add_client_CA (ctx_.get (), x509.get ()));
792
843
}
793
844
}
0 commit comments