Skip to content

Commit 88ad793

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

File tree

1 file changed

+46
-6
lines changed

1 file changed

+46
-6
lines changed

src/crypto/crypto_context.cc

Lines changed: 46 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,74 @@ 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+
auto subject_size =
1106+
BIO_get_mem_data(subject_bio.get(), &subject_data);
1107+
if (subject_size > 0 && subject_data) {
1108+
subject_str = std::string(subject_data, subject_size);
1109+
}
1110+
}
1111+
per_process::Debug(DebugCategory::CRYPTO,
1112+
"Skipping system certificate with subject "
1113+
"'%s' because X509 to PEM conversion failed\n",
1114+
subject_str.c_str());
1115+
skipped++;
1116+
continue;
1117+
}
10971118
ThrowCryptoError(env, ERR_get_error(), "X509 to PEM conversion");
10981119
return MaybeLocal<Array>();
10991120
}
11001121

11011122
char* pem_data = nullptr;
11021123
auto pem_size = BIO_get_mem_data(pem_bio.get(), &pem_data);
11031124
if (pem_size <= 0 || !pem_data) {
1125+
if (skip_on_error) {
1126+
per_process::Debug(DebugCategory::CRYPTO,
1127+
"Skipping a system certificate "
1128+
"because reading PEM data failed\n");
1129+
skipped++;
1130+
continue;
1131+
}
11041132
ThrowCryptoError(env, ERR_get_error(), "Reading PEM data");
11051133
return MaybeLocal<Array>();
11061134
}
1135+
1136+
Local<Value> str;
11071137
// PEM is base64-encoded, so it must be one-byte.
11081138
if (!String::NewFromOneByte(env->isolate(),
11091139
reinterpret_cast<uint8_t*>(pem_data),
11101140
v8::NewStringType::kNormal,
11111141
pem_size)
1112-
.ToLocal(&result[i])) {
1142+
.ToLocal(&str)) {
11131143
return MaybeLocal<Array>();
11141144
}
1145+
result.push_back(str);
11151146
}
1147+
1148+
if (skipped > 0) {
1149+
ProcessEmitWarning(
1150+
env,
1151+
"Skipped %zu system certificate(s) that could not be converted "
1152+
"to PEM format. Use NODE_DEBUG=crypto for details.",
1153+
skipped);
1154+
}
1155+
11161156
return scope.Escape(Array::New(env->isolate(), result.data(), result.size()));
11171157
}
11181158

@@ -1196,7 +1236,7 @@ void GetSystemCACertificates(const FunctionCallbackInfo<Value>& args) {
11961236
Environment* env = Environment::GetCurrent(args);
11971237
Local<Array> results;
11981238
std::vector<X509*>& certs = GetSystemStoreCACertificates();
1199-
if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size())
1239+
if (X509sToArrayOfStrings(env, certs.begin(), certs.end(), certs.size(), true)
12001240
.ToLocal(&results)) {
12011241
args.GetReturnValue().Set(results);
12021242
}

0 commit comments

Comments
 (0)