@@ -221,15 +221,15 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
221221 issuer);
222222}
223223
224- unsigned long LoadCertsFromFile ( // NOLINT(runtime/int)
224+ static unsigned long LoadCertsFromFile ( // NOLINT(runtime/int)
225225 std::vector<X509*>* certs,
226226 const char * file) {
227227 MarkPopErrorOnReturn mark_pop_error_on_return;
228228
229229 auto bio = BIOPointer::NewFile (file, " r" );
230230 if (!bio) return ERR_get_error ();
231231
232- while (X509* x509 = PEM_read_bio_X509 (
232+ while (X509* x509 = PEM_read_bio_X509_AUX (
233233 bio.get (), nullptr , NoPasswordCallback, nullptr )) {
234234 certs->push_back (x509);
235235 }
@@ -244,6 +244,19 @@ unsigned long LoadCertsFromFile( // NOLINT(runtime/int)
244244 }
245245}
246246
247+ static void LoadCertsFromFileOrWarn (std::vector<X509*>* certs,
248+ const char * file) {
249+ unsigned long err = LoadCertsFromFile (certs, file); // NOLINT(runtime/int)
250+ if (err) {
251+ char buf[256 ];
252+ ERR_error_string_n (err, buf, sizeof (buf));
253+ fprintf (stderr,
254+ " Warning: Ignoring extra certs from `%s`, load failed: %s\n " ,
255+ extra_root_certs_file.c_str (),
256+ buf);
257+ }
258+ }
259+
247260// Indicates the trust status of a certificate.
248261enum class TrustStatus {
249262 // Trust status is unknown / uninitialized.
@@ -643,6 +656,73 @@ void ReadWindowsCertificates(
643656}
644657#endif
645658
659+ void LoadCertsFromDir (std::vector<X509*>* certs, std::string_view cert_dir) {
660+ uv_fs_t dir_req;
661+ auto cleanup = OnScopeLeave ([&dir_req]() { uv_fs_req_cleanup (&dir_req); });
662+ int err = uv_fs_scandir (nullptr , &dir_req, cert_dir.data (), 0 , nullptr );
663+ if (err < 0 ) {
664+ fprintf (stderr,
665+ " Cannot open directory %s to load OpenSSL certificates.\n " ,
666+ cert_dir.data ());
667+ return ;
668+ }
669+
670+ uv_fs_t stats_req;
671+ auto cleanup_stats =
672+ OnScopeLeave ([&stats_req]() { uv_fs_req_cleanup (&stats_req); });
673+ for (;;) {
674+ uv_dirent_t ent;
675+
676+ int r = uv_fs_scandir_next (&dir_req, &ent);
677+ if (r == UV_EOF) {
678+ break ;
679+ }
680+ if (r < 0 ) {
681+ char message[64 ];
682+ uv_strerror_r (r, message, sizeof (message));
683+ fprintf (stderr,
684+ " Cannot scan directory %s to load OpenSSL certificates.\n " ,
685+ cert_dir.data ());
686+ return ;
687+ }
688+
689+ std::string file_path = std::string (cert_dir) + " /" + ent.name ;
690+ int stats_r = uv_fs_stat (nullptr , &stats_req, file_path.c_str (), nullptr );
691+ if (stats_r == 0 &&
692+ (static_cast <uv_stat_t *>(stats_req.ptr )->st_mode & S_IFREG)) {
693+ LoadCertsFromFile (certs, file_path.c_str ());
694+ }
695+ }
696+ }
697+
698+ // Loads CA certificates from the default certificate paths respected by
699+ // OpenSSL.
700+ void GetOpenSSLSystemCertificates (std::vector<X509*>* system_store_certs) {
701+ std::string cert_file;
702+ // While configurable when OpenSSL is built, this is usually SSL_CERT_FILE.
703+ if (!credentials::SafeGetenv (X509_get_default_cert_file_env (), &cert_file)) {
704+ // This is usually /etc/ssl/cert.pem if we are using the OpenSSL statically
705+ // linked and built with default configurations.
706+ cert_file = X509_get_default_cert_file ();
707+ }
708+
709+ std::string cert_dir;
710+ // While configurable when OpenSSL is built, this is usually SSL_CERT_DIR.
711+ if (!credentials::SafeGetenv (X509_get_default_cert_dir_env (), &cert_dir)) {
712+ // This is usually /etc/ssl/certs if we are using the OpenSSL statically
713+ // linked and built with default configurations.
714+ cert_dir = X509_get_default_cert_dir ();
715+ }
716+
717+ if (!cert_file.empty ()) {
718+ LoadCertsFromFile (system_store_certs, cert_file.c_str ());
719+ }
720+
721+ if (!cert_dir.empty ()) {
722+ LoadCertsFromDir (system_store_certs, cert_dir.c_str ());
723+ }
724+ }
725+
646726static std::vector<X509*> InitializeBundledRootCertificates () {
647727 // Read the bundled certificates in node_root_certs.h into
648728 // bundled_root_certs_vector.
@@ -682,6 +762,9 @@ static std::vector<X509*> InitializeSystemStoreCertificates() {
682762#endif
683763#ifdef _WIN32
684764 ReadWindowsCertificates (&system_store_certs);
765+ #endif
766+ #if !defined(__APPLE__) && !defined(_WIN32)
767+ GetOpenSSLSystemCertificates (&system_store_certs);
685768#endif
686769 return system_store_certs;
687770}
@@ -696,17 +779,7 @@ static std::vector<X509*>& GetSystemStoreRootCertificates() {
696779
697780static std::vector<X509*> InitializeExtraCACertificates () {
698781 std::vector<X509*> extra_certs;
699- unsigned long err = LoadCertsFromFile ( // NOLINT(runtime/int)
700- &extra_certs,
701- extra_root_certs_file.c_str ());
702- if (err) {
703- char buf[256 ];
704- ERR_error_string_n (err, buf, sizeof (buf));
705- fprintf (stderr,
706- " Warning: Ignoring extra certs from `%s`, load failed: %s\n " ,
707- extra_root_certs_file.c_str (),
708- buf);
709- }
782+ LoadCertsFromFileOrWarn (&extra_certs, extra_root_certs_file.c_str ());
710783 return extra_certs;
711784}
712785
0 commit comments