6
6
#include " node.h"
7
7
#include " node_api.h"
8
8
#include " uv.h"
9
+ #if HAVE_OPENSSL
10
+ #include < openssl/err.h>
11
+ #include < openssl/ssl.h>
12
+ #include < openssl/bn.h>
13
+ #include < openssl/dh.h>
14
+ #include < openssl/ec.h>
15
+ #include < openssl/rsa.h>
16
+ #include < openssl/rand.h>
17
+ #endif
9
18
10
19
using namespace node ;
11
20
using namespace v8 ;
12
21
22
+ // This version can potentially be lowered if/when
23
+ // https://github.com/nodejs/node/pull/44121 is backported.
24
+ #if !NODE_VERSION_AT_LEAST(19, 0, 0)
25
+ #define USE_OWN_LEGACY_PROCESS_INITIALIZATION 1
26
+ #endif
27
+
28
+ #ifdef USE_OWN_LEGACY_PROCESS_INITIALIZATION
13
29
namespace boxednode {
14
30
void InitializeOncePerProcess ();
15
31
void TearDownOncePerProcess ();
16
32
}
33
+ #endif
17
34
18
35
extern " C" {
19
36
typedef void (*register_boxednode_linked_module)(const void **, const void **);
@@ -170,20 +187,38 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
170
187
}
171
188
172
189
static int BoxednodeMain (std::vector<std::string> args) {
173
- boxednode::InitializeOncePerProcess ();
174
190
std::vector<std::string> exec_args;
175
191
std::vector<std::string> errors;
176
192
177
- args.insert (args.begin (), " --" );
193
+ if (args.size () > 0 )
194
+ args.insert (args.begin () + 1 , " --" );
178
195
179
196
// Parse Node.js CLI options, and print any errors that have occurred while
180
197
// trying to parse them.
198
+ #ifdef USE_OWN_LEGACY_PROCESS_INITIALIZATION
199
+ boxednode::InitializeOncePerProcess ();
181
200
int exit_code = node::InitializeNodeWithArgs (&args, &exec_args, &errors);
182
201
for (const std::string& error : errors)
183
202
fprintf (stderr, " %s: %s\n " , args[0 ].c_str (), error.c_str ());
184
203
if (exit_code != 0 ) {
185
204
return exit_code;
186
205
}
206
+ #else
207
+ if (args.size () > 1 )
208
+ args.insert (args.begin () + 1 , " --openssl-shared-config" );
209
+ auto result = node::InitializeOncePerProcess (args, {
210
+ node::ProcessInitializationFlags::kNoInitializeV8 ,
211
+ node::ProcessInitializationFlags::kNoInitializeNodeV8Platform ,
212
+ node::ProcessInitializationFlags::kNoPrintHelpOrVersionOutput
213
+ });
214
+ for (const std::string& error : result->errors ())
215
+ fprintf (stderr, " %s: %s\n " , args[0 ].c_str (), error.c_str ());
216
+ if (result->exit_code () != 0 ) {
217
+ return result->exit_code ();
218
+ }
219
+ args = result->args ();
220
+ exec_args = result->exec_args ();
221
+ #endif
187
222
188
223
// Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way
189
224
// to create a v8::Platform instance that Node.js can use when creating
@@ -198,8 +233,13 @@ static int BoxednodeMain(std::vector<std::string> args) {
198
233
int ret = RunNodeInstance (platform.get (), args, exec_args);
199
234
200
235
V8::Dispose ();
236
+ #ifdef USE_OWN_LEGACY_PROCESS_INITIALIZATION
201
237
V8::ShutdownPlatform ();
202
238
boxednode::TearDownOncePerProcess ();
239
+ #else
240
+ V8::DisposePlatform ();
241
+ node::TearDownOncePerProcess ();
242
+ #endif
203
243
return ret;
204
244
}
205
245
@@ -242,7 +282,7 @@ int main(int argc, char** argv) {
242
282
#endif
243
283
244
284
// The code below is mostly lifted directly from node.cc
245
- // TODO(addaleax): Expose these APIs on the Node.js side.
285
+ # ifdef USE_OWN_LEGACY_PROCESS_INITIALIZATION
246
286
247
287
#if defined(__APPLE__) || defined(__linux__) || defined(_WIN32)
248
288
#define NODE_USE_V8_WASM_TRAP_HANDLER 1
@@ -279,6 +319,30 @@ static PVOID old_vectored_exception_handler;
279
319
280
320
namespace boxednode {
281
321
322
+ #if HAVE_OPENSSL
323
+ static void CheckEntropy () {
324
+ for (;;) {
325
+ int status = RAND_status ();
326
+ assert (status >= 0 ); // Cannot fail.
327
+ if (status != 0 )
328
+ break ;
329
+
330
+ // Give up, RAND_poll() not supported.
331
+ if (RAND_poll () == 0 )
332
+ break ;
333
+ }
334
+ }
335
+
336
+ static bool EntropySource (unsigned char * buffer, size_t length) {
337
+ // Ensure that OpenSSL's PRNG is properly seeded.
338
+ CheckEntropy ();
339
+ // RAND_bytes() can return 0 to indicate that the entropy data is not truly
340
+ // random. That's okay, it's still better than V8's stock source of entropy,
341
+ // which is /dev/urandom on UNIX platforms and the current time on Windows.
342
+ return RAND_bytes (buffer, length) != -1 ;
343
+ }
344
+ #endif
345
+
282
346
void ResetStdio ();
283
347
284
348
#ifdef __POSIX__
@@ -550,9 +614,41 @@ void ResetStdio() {
550
614
#endif // __POSIX__
551
615
}
552
616
617
+ static void InitializeOpenSSL () {
618
+ #if HAVE_OPENSSL && !defined(OPENSSL_IS_BORINGSSL)
619
+ // In the case of FIPS builds we should make sure
620
+ // the random source is properly initialized first.
621
+ #if OPENSSL_VERSION_MAJOR >= 3
622
+ // Use OPENSSL_CONF environment variable is set.
623
+ const char * conf_file = getenv (" OPENSSL_CONF" );
624
+
625
+ OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new ();
626
+ OPENSSL_INIT_set_config_filename (settings, conf_file);
627
+ OPENSSL_INIT_set_config_appname (settings, " openssl_conf" );
628
+ OPENSSL_INIT_set_config_file_flags (settings,
629
+ CONF_MFLAGS_IGNORE_MISSING_FILE);
630
+
631
+ OPENSSL_init_crypto (OPENSSL_INIT_LOAD_CONFIG, settings);
632
+ OPENSSL_INIT_free (settings);
633
+
634
+ if (ERR_peek_error () != 0 ) {
635
+ fprintf (stderr, " OpenSSL configuration error:\n " );
636
+ ERR_print_errors_fp (stderr);
637
+ exit (1 );
638
+ }
639
+ #else // OPENSSL_VERSION_MAJOR < 3
640
+ if (FIPS_mode ()) {
641
+ OPENSSL_init ();
642
+ }
643
+ #endif
644
+ V8::SetEntropySource (boxednode::EntropySource);
645
+ #endif
646
+ }
647
+
553
648
void InitializeOncePerProcess () {
554
649
atexit (ResetStdio);
555
650
PlatformInit ();
651
+ InitializeOpenSSL ();
556
652
}
557
653
558
654
void TearDownOncePerProcess () {
@@ -562,3 +658,5 @@ void TearDownOncePerProcess() {
562
658
}
563
659
564
660
} // namespace boxednode
661
+
662
+ #endif // USE_OWN_LEGACY_PROCESS_INITIALIZATION
0 commit comments