crypto: support --use-system-ca on non-Windows and non-macOS · nodejs/node@44b19ec · GitHub
Skip to content

Commit 44b19ec

Browse files
joyeecheungRafaelGSS
authored andcommitted
crypto: support --use-system-ca on non-Windows and non-macOS
On other platforms, load from the OpenSSL default certificate file and diretory. This is different from --use-openssl-ca in that it caches the certificates on first load, instead of always reading from disk every time a new root store is needed. When used together with the statically-linked OpenSSL, the default configuration usually leads to this behavior: - If SSL_CERT_FILE is used, load from SSL_CERT_FILE. Otherwise load from /etc/ssl/cert.pem - If SSL_CERT_DIR is used, load from all the files under SSL_CERT_DIR. Otherwise, load from all the files under /etc/ssl/certs PR-URL: #57009 Reviewed-By: Richard Lau <rlau@redhat.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 51494d8 commit 44b19ec

3 files changed

Lines changed: 111 additions & 15 deletions

File tree

doc/api/cli.md

Lines changed: 26 additions & 10 deletions

src/crypto/crypto_context.cc

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
223223
issuer);
224224
}
225225

226-
unsigned long LoadCertsFromFile( // NOLINT(runtime/int)
226+
static unsigned long LoadCertsFromFile( // NOLINT(runtime/int)
227227
std::vector<X509*>* certs,
228228
const char* file) {
229229
MarkPopErrorOnReturn mark_pop_error_on_return;
@@ -645,6 +645,74 @@ void ReadWindowsCertificates(
645645
}
646646
#endif
647647

648+
static void LoadCertsFromDir(std::vector<X509*>* certs,
649+
std::string_view cert_dir) {
650+
uv_fs_t dir_req;
651+
auto cleanup = OnScopeLeave([&dir_req]() { uv_fs_req_cleanup(&dir_req); });
652+
int err = uv_fs_scandir(nullptr, &dir_req, cert_dir.data(), 0, nullptr);
653+
if (err < 0) {
654+
fprintf(stderr,
655+
"Cannot open directory %s to load OpenSSL certificates.\n",
656+
cert_dir.data());
657+
return;
658+
}
659+
660+
uv_fs_t stats_req;
661+
auto cleanup_stats =
662+
OnScopeLeave([&stats_req]() { uv_fs_req_cleanup(&stats_req); });
663+
for (;;) {
664+
uv_dirent_t ent;
665+
666+
int r = uv_fs_scandir_next(&dir_req, &ent);
667+
if (r == UV_EOF) {
668+
break;
669+
}
670+
if (r < 0) {
671+
char message[64];
672+
uv_strerror_r(r, message, sizeof(message));
673+
fprintf(stderr,
674+
"Cannot scan directory %s to load OpenSSL certificates.\n",
675+
cert_dir.data());
676+
return;
677+
}
678+
679+
std::string file_path = std::string(cert_dir) + "/" + ent.name;
680+
int stats_r = uv_fs_stat(nullptr, &stats_req, file_path.c_str(), nullptr);
681+
if (stats_r == 0 &&
682+
(static_cast<uv_stat_t*>(stats_req.ptr)->st_mode & S_IFREG)) {
683+
LoadCertsFromFile(certs, file_path.c_str());
684+
}
685+
}
686+
}
687+
688+
// Loads CA certificates from the default certificate paths respected by
689+
// OpenSSL.
690+
void GetOpenSSLSystemCertificates(std::vector<X509*>* system_store_certs) {
691+
std::string cert_file;
692+
// While configurable when OpenSSL is built, this is usually SSL_CERT_FILE.
693+
if (!credentials::SafeGetenv(X509_get_default_cert_file_env(), &cert_file)) {
694+
// This is usually /etc/ssl/cert.pem if we are using the OpenSSL statically
695+
// linked and built with default configurations.
696+
cert_file = X509_get_default_cert_file();
697+
}
698+
699+
std::string cert_dir;
700+
// While configurable when OpenSSL is built, this is usually SSL_CERT_DIR.
701+
if (!credentials::SafeGetenv(X509_get_default_cert_dir_env(), &cert_dir)) {
702+
// This is usually /etc/ssl/certs if we are using the OpenSSL statically
703+
// linked and built with default configurations.
704+
cert_dir = X509_get_default_cert_dir();
705+
}
706+
707+
if (!cert_file.empty()) {
708+
LoadCertsFromFile(system_store_certs, cert_file.c_str());
709+
}
710+
711+
if (!cert_dir.empty()) {
712+
LoadCertsFromDir(system_store_certs, cert_dir.c_str());
713+
}
714+
}
715+
648716
static std::vector<X509*> InitializeBundledRootCertificates() {
649717
// Read the bundled certificates in node_root_certs.h into
650718
// bundled_root_certs_vector.
@@ -685,6 +753,9 @@ static std::vector<X509*> InitializeSystemStoreCertificates() {
685753
#endif
686754
#ifdef _WIN32
687755
ReadWindowsCertificates(&system_store_certs);
756+
#endif
757+
#if !defined(__APPLE__) && !defined(_WIN32)
758+
GetOpenSSLSystemCertificates(&system_store_certs);
688759
#endif
689760
return system_store_certs;
690761
}

test/parallel/test-native-certs.mjs

Lines changed: 13 additions & 4 deletions

0 commit comments

Comments
 (0)