Skip to content

Commit

Permalink
crypto: ability to select cert store at runtime
Browse files Browse the repository at this point in the history
PR-URL: nodejs/node#8334
Backport-PR-URL: nodejs/node#11794
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
  • Loading branch information
AdamMajer authored and andrew749 committed Jul 19, 2017
1 parent 869315e commit 0497a10
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 9 deletions.
36 changes: 36 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,24 @@ 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`.

### `--use-openssl-ca`, `--use-bundled-ca`
<!-- YAML
added: REPLACEME
-->

Use OpenSSL's default CA store or use bundled Mozilla CA store as supplied by
current NodeJS version. The default store is selectable at build-time.

Using OpenSSL store allows for external modifications of the store. For most
Linux and BSD distributions, this store is maintained by the distribution
maintainers and system administrators. OpenSSL CA store location is dependent on
configuration of the OpenSSL library but this can be altered at runtime using
environmental variables.

The bundled CA store, as supplied by NodeJS, is a snapshot of Mozilla CA store
that is fixed at release time. It is identical on all supported platforms.

See `SSL_CERT_DIR` and `SSL_CERT_FILE`.

### `--icu-data-dir=file`
<!-- YAML
Expand Down Expand Up @@ -340,6 +358,24 @@ used to enable FIPS-compliant crypto if Node.js is built with `./configure
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
containing trusted certificates.

Note: Be aware that unless the child environment is explicitly set, this
evironment variable will be inherited by any child processes, and if they use
OpenSSL, it may cause them to trust the same CAs as node.

### `SSL_CERT_FILE=file`

If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's file
containing trusted certificates.

Note: Be aware that unless the child environment is explicitly set, this
evironment variable will be inherited by any child processes, and if they use
OpenSSL, it may cause them to trust the same CAs as node.

[emit_warning]: process.html#process_process_emitwarning_warning_name_ctor
[Buffer]: buffer.html#buffer_buffer
[debugger]: debugger.html
Expand Down
25 changes: 25 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,22 @@ 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.

.TP
.BR \-\-use\-openssl\-ca,\-\-use\-bundled\-ca
Use OpenSSL's default CA store or use bundled Mozilla CA store as supplied by
current NodeJS version. The default store is selectable at build-time.

Using OpenSSL store allows for external modifications of the store. For most
Linux and BSD distributions, this store is maintained by the distribution
maintainers and system administrators. OpenSSL CA store location is dependent on
configuration of the OpenSSL library but this can be altered at runtime using
environmental variables.

The bundled CA store, as supplied by NodeJS, is a snapshot of Mozilla CA store
that is fixed at release time. It is identical on all supported platforms.

See \fBSSL_CERT_DIR\fR and \fBSSL_CERT_FILE\fR.

.TP
.BR \-\-icu\-data\-dir =\fIfile\fR
Specify ICU data load path. (overrides \fBNODE_ICU_DATA\fR)
Expand Down Expand Up @@ -216,6 +232,7 @@ 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
Expand All @@ -225,6 +242,14 @@ If the
\fB\-\-openssl\-config\fR
command line option is used, the environment variable is ignored.

.BR SSL_CERT_DIR = \fIdir\fR
If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's directory
containing trusted certificates.

.TP
.BR SSL_CERT_FILE = \fIfile\fR
If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's
file containing trusted certificates.

.SH BUGS
Bugs are tracked in GitHub Issues:
Expand Down
25 changes: 24 additions & 1 deletion src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ static std::string icu_data_dir; // NOLINT(runtime/string)
bool no_deprecation = false;

#if HAVE_OPENSSL
// use OpenSSL's cert store instead of bundled certs
bool ssl_openssl_cert_store =
#if defined(NODE_OPENSSL_CERT_STORE)
true;
#else
false;
#endif

# if NODE_FIPS_MODE
// used by crypto module
bool enable_fips_crypto = false;
Expand Down Expand Up @@ -3703,7 +3711,18 @@ static void PrintHelp() {
" --v8-options print v8 command line options\n"
" --v8-pool-size=num set v8's thread pool size\n"
#if HAVE_OPENSSL
" --tls-cipher-list=val use an alternative default TLS cipher list\n"
" --tls-cipher-list=val use an alternative default TLS cipher "
"list\n"
" --use-bundled-ca use bundled CA store"
#if !defined(NODE_OPENSSL_CERT_STORE)
" (default)"
#endif
"\n"
" --use-openssl-ca use OpenSSL's default CA store"
#if defined(NODE_OPENSSL_CERT_STORE)
" (default)"
#endif
"\n"
#if NODE_FIPS_MODE
" --enable-fips enable FIPS crypto at startup\n"
" --force-fips force FIPS crypto (cannot be disabled)\n"
Expand Down Expand Up @@ -3872,6 +3891,10 @@ static void ParseArgs(int* argc,
#if HAVE_OPENSSL
} else if (strncmp(arg, "--tls-cipher-list=", 18) == 0) {
default_cipher_list = arg + 18;
} else if (strncmp(arg, "--use-openssl-ca", 16) == 0) {
ssl_openssl_cert_store = true;
} else if (strncmp(arg, "--use-bundled-ca", 16) == 0) {
ssl_openssl_cert_store = false;
#if NODE_FIPS_MODE
} else if (strcmp(arg, "--enable-fips") == 0) {
enable_fips_crypto = true;
Expand Down
5 changes: 4 additions & 1 deletion src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,12 @@ typedef intptr_t ssize_t;
namespace node {

NODE_EXTERN extern bool no_deprecation;
#if HAVE_OPENSSL && NODE_FIPS_MODE
#if HAVE_OPENSSL
NODE_EXTERN extern bool ssl_openssl_cert_store;
# if NODE_FIPS_MODE
NODE_EXTERN extern bool enable_fips_crypto;
NODE_EXTERN extern bool force_fips_crypto;
# endif
#endif

NODE_EXTERN int Start(int argc, char *argv[]);
Expand Down
14 changes: 7 additions & 7 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -708,14 +708,14 @@ static X509_STORE* NewRootCertStore() {
}

X509_STORE* store = X509_STORE_new();
#if defined(NODE_OPENSSL_CERT_STORE)
X509_STORE_set_default_paths(store);
#else
for (X509 *cert : root_certs_vector) {
X509_up_ref(cert);
X509_STORE_add_cert(store, cert);
if (ssl_openssl_cert_store) {
X509_STORE_set_default_paths(store);
} else {
for (X509 *cert : root_certs_vector) {
X509_up_ref(cert);
X509_STORE_add_cert(store, cert);
}
}
#endif

return store;
}
Expand Down

1 comment on commit 0497a10

@aguynamedben
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. There is discussion of a runtime seeking of system CAs over here: nodejs/node#8334 (comment)

Do you know if there's a way to instruct Node.js at runtime to seek system-installed root certs on macOS? My understanding is that macOS centralizes root certs in the Keychain Access app, so I think there would have to be a Node.js native module that uses macOS APIs to get the certificates (i.e. similar to how keytar allows access to passwords in Secure Keychain).

Please sign in to comment.