Skip to content

Commit

Permalink
src,deps,build,test: add OpenSSL config appname
Browse files Browse the repository at this point in the history
This commit adds the setting of an appname (configuration section
name), 'nodejs_conf', to be used when reading OpenSSL configuration
files.

The motivation for this is that currently the default OpenSSL
configuration, 'openssl_conf', element will be used which may be
undesirable as it might configure OpenSSL in unwanted ways. With this
commit it is still possible to use a default openssl.cnf file but the
only section that Node.js will read from is a section named
'nodejs_conf'.

Refs: nodejs#40366
  • Loading branch information
danbev committed May 17, 2022
1 parent f095b19 commit 45b7659
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 29 deletions.
5 changes: 4 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ The OpenSSL configuration files will be found in `OPENSSLDIR` directory above:
```console
$ ls -w 1 out/Release/obj.target/deps/openssl/*.cnf
out/Release/obj.target/deps/openssl/fipsmodule.cnf
out/Release/obj.target/deps/openssl/openssl.cnf
out/Release/obj.target/deps/openssl/nodejs-openssl.cnf
```

And the FIPS module will be located in the `MODULESDIR` directory:
Expand All @@ -819,6 +819,9 @@ $ ls out/Release/obj.target/deps/openssl/lib/openssl-modules/
fips.so
```

Running `configure` without `--openssl-is-fips` flag and rebuilding will reset
the FIPS configuration.

### FIPS support when dynamically linking OpenSSL

For quictls/openssl 3.0 it is possible to enable FIPS when dynamically linking.
Expand Down
30 changes: 30 additions & 0 deletions deps/openssl/nodejs-openssl.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use this in order to automatically load providers.
nodejs_conf = openssl_init

# Optionally include a file that is generated by the OpenSSL fipsinstall
# application. This file contains configuration data required by the OpenSSL
# fips provider. It contains a named section e.g. [fips_sect] which is
# referenced from the [provider_sect] below.
# Refer to the OpenSSL security policy for more information.
# .include fipsmodule.cnf

[openssl_init]
providers = provider_sect

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
# fips = fips_sect

# If no providers are activated explicitly, the default one is activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s), you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl. As a consequence applications depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
# activate = 1
16 changes: 8 additions & 8 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -390,18 +390,18 @@
'variables': {
'openssl-cli': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)openssl-cli<(EXECUTABLE_SUFFIX)',
'provider_name': 'libopenssl-fipsmodule',
'opensslconfig': './deps/openssl/openssl/apps/openssl.cnf',
'opensslconfig': './deps/openssl/nodejs-openssl.cnf',
'conditions': [
['GENERATOR == "ninja"', {
'fipsmodule_internal': '<(PRODUCT_DIR)/lib/<(provider_name).so',
'fipsmodule': '<(PRODUCT_DIR)/obj/lib/openssl-modules/fips.so',
'fipsconfig': '<(PRODUCT_DIR)/obj/lib/fipsmodule.cnf',
'opensslconfig_internal': '<(PRODUCT_DIR)/obj/lib/openssl.cnf',
'opensslconfig_internal': '<(PRODUCT_DIR)/obj/lib/nodejs-openssl.cnf',
}, {
'fipsmodule_internal': '<(PRODUCT_DIR)/obj.target/deps/openssl/<(provider_name).so',
'fipsmodule': '<(PRODUCT_DIR)/obj.target/deps/openssl/lib/openssl-modules/fips.so',
'fipsconfig': '<(PRODUCT_DIR)/obj/deps/openssl/fipsmodule.cnf',
'opensslconfig_internal': '<(PRODUCT_DIR)/obj.target/deps/openssl/openssl.cnf',
'fipsconfig': '<(PRODUCT_DIR)/obj.target/deps/openssl/fipsmodule.cnf',
'opensslconfig_internal': '<(PRODUCT_DIR)/obj.target/deps/openssl/nodejs-openssl.cnf',
}],
],
},
Expand Down Expand Up @@ -451,8 +451,8 @@
],
}, {
'variables': {
'opensslconfig_internal': '<(obj_dir)/deps/openssl/openssl.cnf',
'opensslconfig': './deps/openssl/openssl/apps/openssl.cnf',
'opensslconfig_internal': '<(obj_dir)/deps/openssl/nodejs-openssl.cnf',
'opensslconfig': './deps/openssl/nodejs-openssl.cnf',
},
'actions': [
{
Expand All @@ -461,8 +461,8 @@
'outputs': [ '<(opensslconfig_internal)', ],
'action': [
'python', 'tools/copyfile.py',
'./deps/openssl/openssl/apps/openssl.cnf',
'<(obj_dir)/deps/openssl/openssl.cnf',
'<(opensslconfig)',
'<(opensslconfig_internal)',
],
},
],
Expand Down
49 changes: 31 additions & 18 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1087,27 +1087,40 @@ InitializationResult InitializeOncePerProcess(
// CheckEntropy. CheckEntropy will call RAND_status which will now always
// return 0, leading to an endless loop and the node process will appear to
// hang/freeze.

// The section in the OpenSSL configuration file to be loaded.
const char* conf_section_name = "nodejs_conf";
// Passing NULL as the config file will allow the default openssl.cnf file
// to be loaded, but the default section in that file will not be used,
// instead only the section that matches the value of conf_section_name
// will be read from the default configuration file.
const char* conf_file = nullptr;
// Use OPENSSL_CONF environment variable is set.
std::string env_openssl_conf;
credentials::SafeGetenv("OPENSSL_CONF", &env_openssl_conf);
if (!env_openssl_conf.empty()) {
conf_file = env_openssl_conf.c_str();
}
// Use --openssl-conf command line option if specified.
if (!per_process::cli_options->openssl_config.empty()) {
conf_file = per_process::cli_options->openssl_config.c_str();
}

bool has_cli_conf = !per_process::cli_options->openssl_config.empty();
if (has_cli_conf || !env_openssl_conf.empty()) {
OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
OPENSSL_INIT_set_config_file_flags(settings, CONF_MFLAGS_DEFAULT_SECTION);
if (has_cli_conf) {
const char* conf = per_process::cli_options->openssl_config.c_str();
OPENSSL_INIT_set_config_filename(settings, conf);
}
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, settings);
OPENSSL_INIT_free(settings);

if (ERR_peek_error() != 0) {
result.exit_code = ERR_GET_REASON(ERR_peek_error());
result.early_return = true;
fprintf(stderr, "OpenSSL configuration error:\n");
ERR_print_errors_fp(stderr);
return result;
}
OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
OPENSSL_INIT_set_config_filename(settings, conf_file);
OPENSSL_INIT_set_config_appname(settings, conf_section_name);
OPENSSL_INIT_set_config_file_flags(settings,
CONF_MFLAGS_IGNORE_MISSING_FILE);

OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, settings);
OPENSSL_INIT_free(settings);

if (ERR_peek_error() != 0) {
result.exit_code = ERR_GET_REASON(ERR_peek_error());
result.early_return = true;
fprintf(stderr, "OpenSSL configuration error:\n");
ERR_print_errors_fp(stderr);
return result;
}
#else // OPENSSL_VERSION_MAJOR < 3
if (FIPS_mode()) {
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/openssl_fips_disabled.cnf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Skeleton openssl.cnf for testing with FIPS

openssl_conf = openssl_conf_section
nodejs_conf = openssl_conf_section
authorityKeyIdentifier=keyid:always,issuer:always

[openssl_conf_section]
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/openssl_fips_enabled.cnf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Skeleton openssl.cnf for testing with FIPS

openssl_conf = openssl_conf_section
nodejs_conf = openssl_conf_section
authorityKeyIdentifier=keyid:always,issuer:always

[openssl_conf_section]
Expand Down

0 comments on commit 45b7659

Please sign in to comment.