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