Skip to content

Commit 0ab510b

Browse files
committed
src: mark/pop OpenSSL errors in NewRootCertStore
This commit sets the OpenSSL error mark before calling X509_STORE_load_locations and pops the error mark afterwards. The motivation for this is that it is possible that X509_STORE_load_locations can produce errors if the configuration option --openssl-system-ca-path file does not exist. Later if a different function is called which calls an OpenSSL function it could fail because these errors might still be on the OpenSSL error stack. Currently, all functions that call NewRootCertStore clear the OpenSSL error queue upon returning, but this was not the case for example in v12.18.0. Fixes: #35456
1 parent dcf708d commit 0ab510b

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

node.gyp

+7-1
Original file line numberDiff line numberDiff line change
@@ -1361,6 +1361,9 @@
13611361
'defines': [
13621362
'HAVE_OPENSSL=1',
13631363
],
1364+
'sources': [
1365+
'test/cctest/test_node_crypto.cc',
1366+
]
13641367
}],
13651368
[ 'node_use_openssl=="true" and experimental_quic==1', {
13661369
'defines': [
@@ -1385,7 +1388,10 @@
13851388
]
13861389
}],
13871390
['OS=="solaris"', {
1388-
'ldflags': [ '-I<(SHARED_INTERMEDIATE_DIR)' ]
1391+
'ldflags': [ '-I<(SHARED_INTERMEDIATE_DIR)' ],
1392+
'sources!': [
1393+
'test/cctest/test_node_crypto.cc',
1394+
]
13891395
}],
13901396
# Skip cctest while building shared lib node for Windows
13911397
[ 'OS=="win" and node_shared=="true"', {

src/crypto/crypto_context.cc

+4-1
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ static X509_STORE* NewRootCertStore() {
192192
static Mutex root_certs_vector_mutex;
193193
Mutex::ScopedLock lock(root_certs_vector_mutex);
194194

195-
if (root_certs_vector.empty()) {
195+
if (root_certs_vector.empty() &&
196+
per_process::cli_options->ssl_openssl_cert_store == false) {
196197
for (size_t i = 0; i < arraysize(root_certs); i++) {
197198
X509* x509 =
198199
PEM_read_bio_X509(NodeBIO::NewFixed(root_certs[i],
@@ -210,7 +211,9 @@ static X509_STORE* NewRootCertStore() {
210211

211212
X509_STORE* store = X509_STORE_new();
212213
if (*system_cert_path != '\0') {
214+
ERR_set_mark();
213215
X509_STORE_load_locations(store, system_cert_path, nullptr);
216+
ERR_pop_to_mark();
214217
}
215218

216219
Mutex::ScopedLock cli_lock(node::per_process::cli_options_mutex);

test/cctest/test_node_crypto.cc

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// This simulates specifying the configuration option --openssl-system-ca-path
2+
// and settting it to a file that does not exist.
3+
#define NODE_OPENSSL_SYSTEM_CERT_PATH "/missing/ca.pem"
4+
5+
#include "../../src/crypto/crypto_context.cc" // NOLINT(build/include)
6+
#include "node_options.h"
7+
#include "openssl/err.h"
8+
#include "gtest/gtest.h"
9+
10+
/*
11+
* This test verifies that a call to NewRootCertDir with the build time
12+
* configuration option --openssl-system-ca-path set to an missing file, will
13+
* not leave any OpenSSL errors on the OpenSSL error stack.
14+
* See https://github.com/nodejs/node/issues/35456 for details.
15+
*/
16+
TEST(NodeCrypto, NewRootCertStore) {
17+
node::per_process::cli_options->ssl_openssl_cert_store = true;
18+
X509_STORE* store = node::crypto::NewRootCertStore();
19+
ASSERT_TRUE(store);
20+
ASSERT_EQ(ERR_peek_error(), 0UL) << "NewRootCertStore should not have left "
21+
"any errors on the OpenSSL error stack\n";
22+
X509_STORE_free(store);
23+
}

0 commit comments

Comments
 (0)