Skip to content

Commit 4801d72

Browse files
src: enable X509sToArrayOfStrings to skip errors
Fixes: #61636
1 parent 8e561a3 commit 4801d72

File tree

1 file changed

+45
-6
lines changed

1 file changed

+45
-6
lines changed

src/crypto/crypto_context.cc

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "node.h"
1010
#include "node_buffer.h"
1111
#include "node_options.h"
12+
#include "node_process-inl.h"
1213
#include "util.h"
1314
#include "v8.h"
1415

@@ -1084,35 +1085,73 @@ template <typename It>
10841085
MaybeLocal<Array> X509sToArrayOfStrings(Environment* env,
10851086
It first,
10861087
It last,
1087-
size_t size) {
1088+
size_t size,
1089+
bool skip_on_error = false) {
10881090
ClearErrorOnReturn clear_error_on_return;
10891091
EscapableHandleScope scope(env->isolate());
10901092

1091-
LocalVector<Value> result(env->isolate(), size);
1092-
size_t i = 0;
1093-
for (It cur = first; cur != last; ++cur, ++i) {
1093+
LocalVector<Value> result(env->isolate());
1094+
result.reserve(size);
1095+
size_t skipped = 0;
1096+
for (It cur = first; cur != last; ++cur) {
10941097
X509View view(*cur);
10951098
auto pem_bio = view.toPEM();
10961099
if (!pem_bio) {
1100+
if (skip_on_error) {
1101+
auto subject_bio = view.getSubject();
1102+
char* subject_data = nullptr;
1103+
std::string subject_str = "<unknown>";
1104+
if (subject_bio) {
1105+
long subject_size = BIO_get_mem_data(subject_bio.get(), &subject_data);
1106+
if (subject_size > 0 && subject_data) {
1107+
subject_str = std::string(subject_data, subject_size);
1108+
}
1109+
}
1110+
per_process::Debug(DebugCategory::CRYPTO,
1111+
"Skipping system certificate with subject "
1112+
"'%s' because X509 to PEM conversion failed\n",
1113+
subject_str.c_str());
1114+
skipped++;
1115+
continue;
1116+
}
10971117
ThrowCryptoError(env, ERR_get_error(), "X509 to PEM conversion");
10981118
return MaybeLocal<Array>();
10991119
}
11001120

11011121
char* pem_data = nullptr;
11021122
auto pem_size = BIO_get_mem_data(pem_bio.get(), &pem_data);
11031123
if (pem_size <= 0 || !pem_data) {
1124+
if (skip_on_error) {
1125+
per_process::Debug(DebugCategory::CRYPTO,
1126+
"Skipping a system certificate "
1127+
"because reading PEM data failed\n");
1128+
skipped++;
1129+
continue;
1130+
}
11041131
ThrowCryptoError(env, ERR_get_error(), "Reading PEM data");
11051132
return MaybeLocal<Array>();
11061133
}
1134+
1135+
Local<Value> str;
11071136
// PEM is base64-encoded, so it must be one-byte.
11081137
if (!String::NewFromOneByte(env->isolate(),
11091138
reinterpret_cast<uint8_t*>(pem_data),
11101139
v8::NewStringType::kNormal,
11111140
pem_size)
1112-
.ToLocal(&result[i])) {
1141+
.ToLocal(&str)) {
11131142
return MaybeLocal<Array>();
11141143
}
1144+
result.push_back(str);
11151145
}
1146+
1147+
if (skipped > 0) {
1148+
ProcessEmitWarning(
1149+
env,
1150+
"Skipped %zu system certificate(s) that could not be converted "
1151+
"to PEM format. Use NODE_DEBUG=crypto for details.",
1152+
skipped);
1153+
}
1154+
11161155
return scope.Escape(Array::New(env->isolate(), result.data(), result.size()));
11171156
}
11181157

@@ -1196,7 +1235,7 @@ void GetSystemCACertificates(const FunctionCallbackInfo<Value>& args) {
11961235
Environment* env = Environment::GetCurrent(args);
11971236
Local<Array> results;
11981237
std::vector<X509*>& certs = GetSystemStoreCACertificates();
1199-
if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size())
1238+
if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size(), true)
12001239
.ToLocal(&results)) {
12011240
args.GetReturnValue().Set(results);
12021241
}

0 commit comments

Comments
 (0)