From dcdebc392181bf975697f1d6ac414e5e2ef637bd Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 28 Jan 2017 13:27:02 +0100 Subject: [PATCH 1/5] src: make copies of startup environment variables Mutations of the environment can invalidate pointers to environment variables, so make `secure_getenv()` copy them out instead of returning pointers. PR-URL: https://github.com/nodejs/node/pull/11051 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- src/node.cc | 49 ++++++++++++++++++++++++++++---------------- src/node_i18n.cc | 12 +++++------ src/node_i18n.h | 3 ++- src/node_internals.h | 2 ++ 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/node.cc b/src/node.cc index 0ee0133df41c75..5eb7e1af24112c 100644 --- a/src/node.cc +++ b/src/node.cc @@ -154,7 +154,7 @@ static node_module* modlist_addon; #if defined(NODE_HAVE_I18N_SUPPORT) // Path to ICU data (for i18n / Intl) -static const char* icu_data_dir = nullptr; +static std::string icu_data_dir; // NOLINT(runtime/string) #endif // used by C++ modules as well @@ -901,12 +901,21 @@ Local UVException(Isolate* isolate, // Look up environment variable unless running as setuid root. -inline const char* secure_getenv(const char* key) { +inline bool SafeGetenv(const char* key, std::string* text) { #ifndef _WIN32 - if (getuid() != geteuid() || getgid() != getegid()) - return nullptr; + // TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE) + // is non-zero on Linux. + if (getuid() != geteuid() || getgid() != getegid()) { + text->clear(); + return false; + } #endif - return getenv(key); + if (const char* value = getenv(key)) { + *text = value; + return true; + } + text->clear(); + return false; } @@ -3063,11 +3072,11 @@ void SetupProcessObject(Environment* env, #if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION) // ICU-related versions are now handled on the js side, see bootstrap_node.js - if (icu_data_dir != nullptr) { + if (!icu_data_dir.empty()) { // Did the user attempt (via env var or parameter) to set an ICU path? READONLY_PROPERTY(process, "icu_data_dir", - OneByteString(env->isolate(), icu_data_dir)); + OneByteString(env->isolate(), icu_data_dir.c_str())); } #endif @@ -3696,7 +3705,7 @@ static void ParseArgs(int* argc, #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { - icu_data_dir = arg + 15; + icu_data_dir.assign(arg, 15); #endif } else if (strcmp(arg, "--expose-internals") == 0 || strcmp(arg, "--expose_internals") == 0) { @@ -4183,8 +4192,10 @@ void Init(int* argc, #endif // Allow for environment set preserving symlinks. - if (auto preserve_symlinks = secure_getenv("NODE_PRESERVE_SYMLINKS")) { - config_preserve_symlinks = (*preserve_symlinks == '1'); + { + std::string text; + config_preserve_symlinks = + SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1'; } // Parse a few arguments which are specific to Node. @@ -4213,12 +4224,11 @@ void Init(int* argc, #endif #if defined(NODE_HAVE_I18N_SUPPORT) - if (icu_data_dir == nullptr) { - // if the parameter isn't given, use the env variable. - icu_data_dir = secure_getenv("NODE_ICU_DATA"); - } + // If the parameter isn't given, use the env variable. + if (icu_data_dir.empty()) + SafeGetenv("NODE_ICU_DATA", &icu_data_dir); // Initialize ICU. - // If icu_data_dir is nullptr here, it will load the 'minimal' data. + // If icu_data_dir is empty here, it will load the 'minimal' data. if (!i18n::InitializeICUDirectory(icu_data_dir)) { FatalError(nullptr, "Could not initialize ICU " "(check NODE_ICU_DATA or --icu-data-dir parameters)"); @@ -4483,8 +4493,11 @@ int Start(int argc, char** argv) { Init(&argc, const_cast(argv), &exec_argc, &exec_argv); #if HAVE_OPENSSL - if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS")) - crypto::UseExtraCaCerts(extra); + { + std::string extra_ca_certs; + if (SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs)) + crypto::UseExtraCaCerts(extra_ca_certs); + } #ifdef NODE_FIPS_MODE // In the case of FIPS builds we should make sure // the random source is properly initialized first. @@ -4493,7 +4506,7 @@ int Start(int argc, char** argv) { // V8 on Windows doesn't have a good source of entropy. Seed it from // OpenSSL's pool. V8::SetEntropySource(crypto::EntropySource); -#endif +#endif // HAVE_OPENSSL v8_platform.Initialize(v8_thread_pool_size); V8::Initialize(); diff --git a/src/node_i18n.cc b/src/node_i18n.cc index a98fdca4d1bffd..40d048fa36d0ce 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -404,12 +404,8 @@ static void GetVersion(const FunctionCallbackInfo& args) { } } -bool InitializeICUDirectory(const char* icu_data_path) { - if (icu_data_path != nullptr) { - flag_icu_data_dir = true; - u_setDataDirectory(icu_data_path); - return true; // no error - } else { +bool InitializeICUDirectory(const std::string& path) { + if (path.empty()) { UErrorCode status = U_ZERO_ERROR; #ifdef NODE_HAVE_SMALL_ICU // install the 'small' data. @@ -418,6 +414,10 @@ bool InitializeICUDirectory(const char* icu_data_path) { // no small data, so nothing to do. #endif // !NODE_HAVE_SMALL_ICU return (status == U_ZERO_ERROR); + } else { + flag_icu_data_dir = true; + u_setDataDirectory(path.c_str()); + return true; // No error. } } diff --git a/src/node_i18n.h b/src/node_i18n.h index 21a579526ddc1a..0bfd3c5c859792 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "node.h" +#include #if defined(NODE_HAVE_I18N_SUPPORT) @@ -13,7 +14,7 @@ extern bool flag_icu_data_dir; namespace i18n { -bool InitializeICUDirectory(const char* icu_data_path); +bool InitializeICUDirectory(const std::string& path); int32_t ToASCII(MaybeStackBuffer* buf, const char* input, diff --git a/src/node_internals.h b/src/node_internals.h index 0a65be7642ff2a..c22cb22c948bd2 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -12,6 +12,8 @@ #include #include +#include + struct sockaddr; // Variation on NODE_DEFINE_CONSTANT that sets a String value. From ce10b06f2bb6a4fdf55adba4c69867cc25d2bbcb Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 11 Feb 2017 14:00:22 +0100 Subject: [PATCH 2/5] src: make --icu-data-dir= switch testable Move some code around so we can properly test whether the switch actually does anything. PR-URL: https://github.com/nodejs/node/pull/11255 Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- lib/internal/process.js | 4 +--- src/node.cc | 13 +------------ src/node_config.cc | 7 +++++-- src/node_i18n.cc | 3 --- src/node_i18n.h | 2 +- test/parallel/test-intl-no-icu-data.js | 7 +++++++ 6 files changed, 15 insertions(+), 21 deletions(-) create mode 100644 test/parallel/test-intl-no-icu-data.js diff --git a/lib/internal/process.js b/lib/internal/process.js index 441fb722edb153..a756f0d429c10d 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -122,7 +122,7 @@ function setupConfig(_source) { const oldV8BreakIterator = Intl.v8BreakIterator; const des = Object.getOwnPropertyDescriptor(Intl, 'v8BreakIterator'); des.value = require('internal/util').deprecate(function v8BreakIterator() { - if (processConfig.hasSmallICU && !process.icu_data_dir) { + if (processConfig.hasSmallICU && !processConfig.icuDataDir) { // Intl.v8BreakIterator() would crash w/ fatal error, so throw instead. throw new Error('v8BreakIterator: full ICU data not installed. ' + 'See https://github.com/nodejs/node/wiki/Intl'); @@ -131,8 +131,6 @@ function setupConfig(_source) { }, 'Intl.v8BreakIterator is deprecated and will be removed soon.'); Object.defineProperty(Intl, 'v8BreakIterator', des); } - // Don’t let icu_data_dir leak through. - delete process.icu_data_dir; } diff --git a/src/node.cc b/src/node.cc index 5eb7e1af24112c..64c90911a9a131 100644 --- a/src/node.cc +++ b/src/node.cc @@ -154,7 +154,7 @@ static node_module* modlist_addon; #if defined(NODE_HAVE_I18N_SUPPORT) // Path to ICU data (for i18n / Intl) -static std::string icu_data_dir; // NOLINT(runtime/string) +std::string icu_data_dir; // NOLINT(runtime/string) #endif // used by C++ modules as well @@ -3069,17 +3069,6 @@ void SetupProcessObject(Environment* env, "ares", FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR)); -#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION) - // ICU-related versions are now handled on the js side, see bootstrap_node.js - - if (!icu_data_dir.empty()) { - // Did the user attempt (via env var or parameter) to set an ICU path? - READONLY_PROPERTY(process, - "icu_data_dir", - OneByteString(env->isolate(), icu_data_dir.c_str())); - } -#endif - const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION); READONLY_PROPERTY( versions, diff --git a/src/node_config.cc b/src/node_config.cc index 401345f6a608be..98b219c3e81d1b 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -38,8 +38,11 @@ void InitConfig(Local target, READONLY_BOOLEAN_PROPERTY("hasSmallICU"); #endif // NODE_HAVE_SMALL_ICU - if (flag_icu_data_dir) - READONLY_BOOLEAN_PROPERTY("usingICUDataDir"); + target->DefineOwnProperty(env->context(), + OneByteString(env->isolate(), "icuDataDir"), + OneByteString(env->isolate(), icu_data_dir.data())) + .FromJust(); + #endif // NODE_HAVE_I18N_SUPPORT if (config_preserve_symlinks) diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 40d048fa36d0ce..648012a50601e3 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -70,8 +70,6 @@ using v8::Object; using v8::String; using v8::Value; -bool flag_icu_data_dir = false; - namespace i18n { const size_t kStorageSize = 1024; @@ -415,7 +413,6 @@ bool InitializeICUDirectory(const std::string& path) { #endif // !NODE_HAVE_SMALL_ICU return (status == U_ZERO_ERROR); } else { - flag_icu_data_dir = true; u_setDataDirectory(path.c_str()); return true; // No error. } diff --git a/src/node_i18n.h b/src/node_i18n.h index 0bfd3c5c859792..21567eeb3ec38f 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -10,7 +10,7 @@ namespace node { -extern bool flag_icu_data_dir; +extern std::string icu_data_dir; // NOLINT(runtime/string) namespace i18n { diff --git a/test/parallel/test-intl-no-icu-data.js b/test/parallel/test-intl-no-icu-data.js new file mode 100644 index 00000000000000..dd14c146719fb1 --- /dev/null +++ b/test/parallel/test-intl-no-icu-data.js @@ -0,0 +1,7 @@ +// Flags: --icu-data-dir=test/fixtures/empty/ +'use strict'; +require('../common'); +const assert = require('assert'); + +// No-op when ICU case mappings are unavailable. +assert.strictEqual('ç'.toLocaleUpperCase('el'), 'ç'); From d0b9c3407fb3acd333092a7d386ee2985f6107bf Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 11 Feb 2017 14:04:58 +0100 Subject: [PATCH 3/5] src: fix --icu-data-dir= regression Commit a8734af ("src: make copies of startup environment variables") from two weeks ago introduced a regression in the capturing of the `--icu-data-dir=` switch: it captured the string up to the `=` instead of what comes after it. PR-URL: https://github.com/nodejs/node/pull/11255 Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- src/node.cc | 2 +- test/parallel/test-intl-no-icu-data.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 64c90911a9a131..ebcfb74188d152 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3694,7 +3694,7 @@ static void ParseArgs(int* argc, #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { - icu_data_dir.assign(arg, 15); + icu_data_dir.assign(arg + 15); #endif } else if (strcmp(arg, "--expose-internals") == 0 || strcmp(arg, "--expose_internals") == 0) { diff --git a/test/parallel/test-intl-no-icu-data.js b/test/parallel/test-intl-no-icu-data.js index dd14c146719fb1..ce5e9a08121cdc 100644 --- a/test/parallel/test-intl-no-icu-data.js +++ b/test/parallel/test-intl-no-icu-data.js @@ -2,6 +2,8 @@ 'use strict'; require('../common'); const assert = require('assert'); +const config = process.binding('config'); // No-op when ICU case mappings are unavailable. assert.strictEqual('ç'.toLocaleUpperCase('el'), 'ç'); +assert.strictEqual(config.icuDataDir, 'test/fixtures/empty/'); From dc77c6edff394b996a8e491a20d8957363d3dd99 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Fri, 27 Jan 2017 11:49:14 -0800 Subject: [PATCH 4/5] src: add SafeGetenv() to internal API Allow it to be used anywhere in src/ that env variables with security implications are accessed. PR-URL: #11006 Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- src/node.cc | 2 +- src/node_internals.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index ebcfb74188d152..0e35fea72da40d 100644 --- a/src/node.cc +++ b/src/node.cc @@ -901,7 +901,7 @@ Local UVException(Isolate* isolate, // Look up environment variable unless running as setuid root. -inline bool SafeGetenv(const char* key, std::string* text) { +bool SafeGetenv(const char* key, std::string* text) { #ifndef _WIN32 // TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE) // is non-zero on Linux. diff --git a/src/node_internals.h b/src/node_internals.h index c22cb22c948bd2..adfb453895a650 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -108,6 +108,8 @@ void RegisterSignalHandler(int signal, bool reset_handler = false); #endif +bool SafeGetenv(const char* key, std::string* text); + template constexpr size_t arraysize(const T(&)[N]) { return N; } From a3bf4a248661fd2f71d69c922e89672fcf315a46 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 25 Jan 2017 14:13:34 -0800 Subject: [PATCH 5/5] crypto: support OPENSSL_CONF again A side-effect of https://github.com/nodejs/node-private/pull/82 was to remove support for OPENSSL_CONF, as well as removing the default read of a configuration file on startup. Partly revert this, allowing OPENSSL_CONF to be used to specify a configuration file to read on startup, but do not read a file by default. If the --openssl-config command line option is provided, its value is used, not the OPENSSL_CONF environment variable. Fix: https://github.com/nodejs/node/issues/10938 PR-URL: https://github.com/nodejs/node/pull/11006 Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- doc/api/cli.md | 13 +++++++++++++ doc/node.1 | 10 ++++++++++ src/node.cc | 14 ++++++++++---- src/node_crypto.cc | 4 ++-- src/node_internals.h | 2 +- test/parallel/test-crypto-fips.js | 25 ++++++++++++++++++++++--- 6 files changed, 58 insertions(+), 10 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 809bd326a6273c..099c4c993d113c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -363,6 +363,18 @@ misformatted, but any errors are otherwise ignored. Note that neither the well known nor extra certificates are used when the `ca` options property is explicitly specified for a TLS or HTTPS client or server. +### `OPENSSL_CONF=file` + + +Load an OpenSSL configuration file on startup. Among other uses, this can be +used to enable FIPS-compliant crypto if Node.js is built with `./configure +\-\-openssl\-fips`. + +If the [`--openssl-config`][] command line option is used, the environment +variable is ignored. + ### `SSL_CERT_DIR=dir` If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's directory @@ -386,3 +398,4 @@ OpenSSL, it may cause them to trust the same CAs as node. [debugger]: debugger.html [REPL]: repl.html [SlowBuffer]: buffer.html#buffer_class_slowbuffer +[`--openssl-config`]: #cli_openssl_config_file diff --git a/doc/node.1 b/doc/node.1 index ffe72e1d022aa6..026485d3920923 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -243,6 +243,16 @@ asynchronous when outputting to a TTY on platforms which support async stdio. Setting this will void any guarantee that stdio will not be interleaved or dropped at program exit. \fBAvoid use.\fR +.TP +.BR OPENSSL_CONF = \fIfile\fR +Load an OpenSSL configuration file on startup. Among other uses, this can be +used to enable FIPS-compliant crypto if Node.js is built with +\fB./configure \-\-openssl\-fips\fR. + +If the +\fB\-\-openssl\-config\fR +command line option is used, the environment variable is ignored. + .TP .BR SSL_CERT_DIR = \fIdir\fR If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's directory diff --git a/src/node.cc b/src/node.cc index 0e35fea72da40d..f19a2867f85f71 100644 --- a/src/node.cc +++ b/src/node.cc @@ -174,7 +174,7 @@ bool ssl_openssl_cert_store = bool enable_fips_crypto = false; bool force_fips_crypto = false; # endif // NODE_FIPS_MODE -const char* openssl_config = nullptr; +std::string openssl_config; // NOLINT(runtime/string) #endif // HAVE_OPENSSL // true if process warnings should be suppressed @@ -3519,8 +3519,9 @@ static void PrintHelp() { " --enable-fips enable FIPS crypto at startup\n" " --force-fips force FIPS crypto (cannot be disabled)\n" #endif /* NODE_FIPS_MODE */ - " --openssl-config=path load OpenSSL configuration file from\n" - " the specified path\n" + " --openssl-config=file load OpenSSL configuration from the\n" + " specified file (overrides\n" + " OPENSSL_CONF)\n" #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) " --icu-data-dir=dir set ICU data load path to dir\n" @@ -3553,6 +3554,8 @@ static void PrintHelp() { " prefixed to the module search path\n" "NODE_REPL_HISTORY path to the persistent REPL history\n" " file\n" + "OPENSSL_CONF load OpenSSL configuration from file\n" + "\n" "Documentation can be found at https://nodejs.org/\n"); } @@ -3690,7 +3693,7 @@ static void ParseArgs(int* argc, force_fips_crypto = true; #endif /* NODE_FIPS_MODE */ } else if (strncmp(arg, "--openssl-config=", 17) == 0) { - openssl_config = arg + 17; + openssl_config.assign(arg + 17); #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { @@ -4187,6 +4190,9 @@ void Init(int* argc, SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1'; } + if (openssl_config.empty()) + SafeGetenv("OPENSSL_CONF", &openssl_config); + // Parse a few arguments which are specific to Node. int v8_argc; const char** v8_argv; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 072a48f40c58dc..90e54f6398d859 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -5881,14 +5881,14 @@ void InitCryptoOnce() { OPENSSL_no_config(); // --openssl-config=... - if (openssl_config != nullptr) { + if (!openssl_config.empty()) { OPENSSL_load_builtin_modules(); #ifndef OPENSSL_NO_ENGINE ENGINE_load_builtin_engines(); #endif ERR_clear_error(); CONF_modules_load_file( - openssl_config, + openssl_config.c_str(), nullptr, CONF_MFLAGS_DEFAULT_SECTION); int err = ERR_get_error(); diff --git a/src/node_internals.h b/src/node_internals.h index adfb453895a650..f786adcdb3121c 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -36,7 +36,7 @@ namespace node { // Set in node.cc by ParseArgs with the value of --openssl-config. // Used in node_crypto.cc when initializing OpenSSL. -extern const char* openssl_config; +extern std::string openssl_config; // Set in node.cc by ParseArgs when --preserve-symlinks is used. // Used in node_config.cc to set a constant on process.binding('config') diff --git a/test/parallel/test-crypto-fips.js b/test/parallel/test-crypto-fips.js index 6fd3352740c8c3..ae510741943ca8 100644 --- a/test/parallel/test-crypto-fips.js +++ b/test/parallel/test-crypto-fips.js @@ -37,8 +37,9 @@ function testHelper(stream, args, expectedOutput, cmd, env) { env: env }); - console.error('Spawned child [pid:' + child.pid + '] with cmd ' + - cmd + ' and args \'' + args + '\''); + console.error('Spawned child [pid:' + child.pid + '] with cmd \'' + + cmd + '\' expect %j with args \'' + args + '\'' + + ' OPENSSL_CONF=%j', expectedOutput, env.OPENSSL_CONF); function childOk(child) { console.error('Child #' + ++num_children_ok + @@ -92,10 +93,26 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, 'require("crypto").fips', process.env); -// OPENSSL_CONF should _not_ be able to turn on FIPS mode + +// OPENSSL_CONF should be able to turn on FIPS mode testHelper( 'stdout', [], + compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, + 'require("crypto").fips', + addToEnv('OPENSSL_CONF', CNF_FIPS_ON)); + +// --openssl-config option should override OPENSSL_CONF +testHelper( + 'stdout', + [`--openssl-config=${CNF_FIPS_ON}`], + compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, + 'require("crypto").fips', + addToEnv('OPENSSL_CONF', CNF_FIPS_OFF)); + +testHelper( + 'stdout', + [`--openssl-config=${CNF_FIPS_OFF}`], FIPS_DISABLED, 'require("crypto").fips', addToEnv('OPENSSL_CONF', CNF_FIPS_ON)); @@ -107,6 +124,7 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, 'require("crypto").fips', process.env); + // OPENSSL_CONF should _not_ make a difference to --enable-fips testHelper( compiledWithFips() ? 'stdout' : 'stderr', @@ -122,6 +140,7 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, 'require("crypto").fips', process.env); + // Using OPENSSL_CONF should not make a difference to --force-fips testHelper( compiledWithFips() ? 'stdout' : 'stderr',