diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index fba9a67623..410d88300c 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -134,75 +134,6 @@ the character "E" appended to the traditional abbreviations): Ephemeral methods may have some performance drawbacks, because key generation is expensive. -## Modifying the Default Cipher Suite - -Node.js is built with a default suite of enabled and disabled ciphers. -Currently, the default cipher suite is: - - ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH: - !RC4:!MD5:!aNULL - -This default can be overridden entirely using the `--cipher-list` command line -switch or `NODE_CIPHER_LIST` environment variable. For instance: - - node --cipher-list=ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384 - -Setting the environment variable would have the same effect: - - NODE_CIPHER_LIST=ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384 - -CAUTION: The default cipher suite has been carefully selected to reflect current -security best practices and risk mitigation. Changing the default cipher suite -can have a significant impact on the security of an application. The -`--cipher-list` and `NODE_CIPHER_LIST` options should only be used if -absolutely necessary. - -### Using Legacy Default Cipher Suite ### - -It is possible for the built-in default cipher suite to change from one release -of Node.js to another. For instance, v0.10.38 uses a different default than -v0.12.2. Such changes can cause issues with applications written to assume -certain specific defaults. To help buffer applications against such changes, -the `--enable-legacy-cipher-list` command line switch or `NODE_LEGACY_CIPHER_LIST` -environment variable can be set to specify a specific preset default: - - # Use the v0.10.38 defaults - node --enable-legacy-cipher-list=v0.10.38 - // or - NODE_LEGACY_CIPHER_LIST=v0.10.38 - - # Use the v0.12.2 defaults - node --enable-legacy-cipher-list=v0.12.2 - // or - NODE_LEGACY_CIPHER_LIST=v0.12.2 - -Currently, the values supported for the `enable-legacy-cipher-list` switch and -`NODE_LEGACY_CIPHER_LIST` environment variable include: - - v0.10.38 - To enable the default cipher suite used in v0.10.38 - - ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH - - v0.10.39 - To enable the default cipher suite used in v0.10.39 - - ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH - - v0.12.2 - To enable the default cipher suite used in v0.12.2 - - ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4: - HIGH:!MD5:!aNULL - -These legacy cipher suites are also made available for use via the -`getLegacyCiphers()` method: - - var tls = require('tls'); - console.log(tls.getLegacyCiphers('v0.10.38')); - -CAUTION: Changes to the default cipher suite are typically made in order to -strengthen the default security for applications running within Node.js. -Reverting back to the defaults used by older releases can weaken the security -of your applications. The legacy cipher suites should only be used if absolutely -necessary. ## tls.getCiphers() @@ -213,12 +144,6 @@ Example: var ciphers = tls.getCiphers(); console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...] -## tls.getLegacyCiphers(version) - -Returns the legacy default cipher suite for the specified Node.js release. - -Example: - var cipher_suite = tls.getLegacyCiphers('v0.10.38'); ## tls.createServer(options[, secureConnectionListener]) @@ -252,7 +177,7 @@ automatically set as a listener for the [secureConnection][] event. The prioritize the non-CBC cipher. Defaults to - `ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL`. + `ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL`. Consult the [OpenSSL cipher list format documentation] for details on the format. @@ -262,7 +187,10 @@ automatically set as a listener for the [secureConnection][] event. The of OpenSSL. Note that it is still possible for a TLS v1.2 client to negotiate a weaker cipher unless `honorCipherOrder` is enabled. - `RC4` is explicitly switched off by default due to known vulnerabilities. + `RC4` is used as a fallback for clients that speak on older version of + the TLS protocol. `RC4` has in recent years come under suspicion and + should be considered compromised for anything that is truly sensitive. + It is speculated that state-level actors possess the ability to break it. **NOTE**: Previous revisions of this section suggested `AES256-SHA` as an acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore diff --git a/lib/tls.js b/lib/tls.js index 04a41e8e2b..a00fbb9d72 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -19,8 +19,6 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -var _crypto = process.binding('crypto'); - var net = require('net'); var url = require('url'); var util = require('util'); @@ -35,14 +33,16 @@ exports.CLIENT_RENEG_WINDOW = 600; exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; -exports.DEFAULT_CIPHERS = _crypto.DEFAULT_CIPHER_LIST; - -exports.getLegacyCiphers = _crypto.getLegacyCiphers; +exports.DEFAULT_CIPHERS = + // TLS 1.2 + 'ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + + // TLS 1.0 + 'RC4:HIGH:!MD5:!aNULL'; exports.DEFAULT_ECDH_CURVE = 'prime256v1'; exports.getCiphers = function() { - var names = _crypto.getSSLCiphers(); + var names = process.binding('crypto').getSSLCiphers(); // Drop all-caps names in favor of their lowercase aliases, var ctx = {}; names.forEach(function(name) { diff --git a/src/node.cc b/src/node.cc index b8a5b4e756..e669706f12 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2936,9 +2936,6 @@ static void PrintHelp() { #endif " --enable-ssl2 enable ssl2\n" " --enable-ssl3 enable ssl3\n" - " --cipher-list=val specify the default TLS cipher list\n" - " --enable-legacy-cipher-list=val \n" - " val = v0.10.38, v0.10.39, or v0.12.2\n" "\n" "Environment variables:\n" #ifdef _WIN32 @@ -2956,9 +2953,6 @@ static void PrintHelp() { " (will extend linked-in data)\n" #endif #endif - "NODE_CIPHER_LIST Override the default TLS cipher list\n" - "NODE_LEGACY_CIPHER_LIST=val\n" - " val = v0.10.38, v0.10.39, or v0.12.2\n" "\n" "Documentation can be found at http://nodejs.org/\n"); } @@ -2998,7 +2992,6 @@ static void ParseArgs(int* argc, unsigned int new_argc = 1; new_v8_argv[0] = argv[0]; new_argv[0] = argv[0]; - bool using_legacy_cipher_list = false; unsigned int index = 1; while (index < nargs && argv[index][0] == '-') { @@ -3054,20 +3047,6 @@ static void ParseArgs(int* argc, } else if (strcmp(arg, "--v8-options") == 0) { new_v8_argv[new_v8_argc] = "--help"; new_v8_argc += 1; - } else if (strncmp(arg, "--cipher-list=", 14) == 0) { - if (!using_legacy_cipher_list) { - DEFAULT_CIPHER_LIST = arg + 14; - } - } else if (strncmp(arg, "--enable-legacy-cipher-list=", 28) == 0) { - // use the original v0.10.x/v0.12.x cipher lists - const char * legacy_list = legacy_cipher_list(arg+28); - if (legacy_list != NULL) { - using_legacy_cipher_list = true; - DEFAULT_CIPHER_LIST = legacy_list; - } else { - fprintf(stderr, "Error: An unknown legacy cipher list was specified\n"); - exit(9); - } #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { icu_data_dir = arg + 15; @@ -3435,27 +3414,6 @@ void Init(int* argc, } } - const char * cipher_list = getenv("NODE_CIPHER_LIST"); - if (cipher_list != NULL) { - DEFAULT_CIPHER_LIST = cipher_list; - } - // Allow the NODE_LEGACY_CIPHER_LIST envar to override the other - // cipher list options. NODE_LEGACY_CIPHER_LIST=v0.10.38 will use - // the cipher list from v0.10.38, NODE_LEGACY_CIPHER_LIST=v0.12.2 will - // use the cipher list from v0.12.2 - const char * leg_cipher_id = getenv("NODE_LEGACY_CIPHER_LIST"); - if (leg_cipher_id != NULL) { - const char * leg_cipher_list = - legacy_cipher_list(leg_cipher_id); - if (leg_cipher_list != NULL) { - DEFAULT_CIPHER_LIST = leg_cipher_list; - } else { - fprintf(stderr, "Error: An unknown legacy cipher list was specified\n"); - exit(9); - } - } - - #if defined(NODE_HAVE_I18N_SUPPORT) if (icu_data_dir == NULL) { // if the parameter isn't given, use the env variable. diff --git a/src/node.h b/src/node.h index c930928deb..38356ac44f 100644 --- a/src/node.h +++ b/src/node.h @@ -223,19 +223,6 @@ NODE_EXTERN void RunAtExit(Environment* env); } \ while (0) -#define NODE_DEFINE_STRING_CONSTANT(target, constant) \ - do { \ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); \ - v8::Local constant_name = \ - v8::String::NewFromUtf8(isolate, #constant); \ - v8::Local constant_value = \ - v8::String::NewFromUtf8(isolate, constant); \ - v8::PropertyAttribute constant_attributes = \ - static_cast(v8::ReadOnly | v8::DontDelete); \ - (target)->ForceSet(constant_name, constant_value, constant_attributes); \ - } while (0) - - // Used to be a macro, hence the uppercase name. template inline void NODE_SET_METHOD(const TypeName& recv, diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 327bfce131..03650a98c6 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -77,7 +77,6 @@ namespace node { bool SSL2_ENABLE = false; bool SSL3_ENABLE = false; -const char * DEFAULT_CIPHER_LIST = DEFAULT_CIPHER_LIST_HEAD; namespace crypto { @@ -4852,26 +4851,6 @@ static void array_push_back(const TypeName* md, ctx->arr->Set(ctx->arr->Length(), OneByteString(ctx->env()->isolate(), from)); } -// borrowed from v8 -// (see http://v8.googlecode.com/svn/trunk/samples/shell.cc) -const char* ToCString(const String::Utf8Value& value) { - return *value ? *value : ""; -} - -void DefaultCiphers(const v8::FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args.GetIsolate()); - HandleScope scope(env->isolate()); - v8::String::Utf8Value key(args[0]); - const char * list = legacy_cipher_list(ToCString(key)); - if (list != NULL) { - args.GetReturnValue().Set( - v8::String::NewFromUtf8(args.GetIsolate(), list)); - } else { - args.GetReturnValue().Set( - v8::String::NewFromUtf8(args.GetIsolate(), - DEFAULT_CIPHER_LIST_HEAD)); - } -} void GetCiphers(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args.GetIsolate()); @@ -5192,8 +5171,6 @@ void InitCrypto(Handle target, NODE_DEFINE_CONSTANT(target, SSL3_ENABLE); NODE_DEFINE_CONSTANT(target, SSL2_ENABLE); - NODE_DEFINE_STRING_CONSTANT(target, DEFAULT_CIPHER_LIST); - NODE_SET_METHOD(target, "getLegacyCiphers", DefaultCiphers); } } // namespace crypto diff --git a/src/node_crypto.h b/src/node_crypto.h index d6cf9aa218..0a4c34a1f3 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -38,7 +38,6 @@ #include "v8.h" -#include #include #include #include @@ -60,40 +59,10 @@ # define NODE__HAVE_TLSEXT_STATUS_CB #endif // !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_set_tlsext_status_cb) -#define DEFAULT_CIPHER_LIST_V10_38 "ECDHE-RSA-AES128-SHA256:" \ - "AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH" - -#define DEFAULT_CIPHER_LIST_V10_39 "ECDHE-RSA-AES128-SHA256:" \ - "AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH" - -#define DEFAULT_CIPHER_LIST_V12_2 "ECDHE-RSA-AES128-SHA256:" \ - "DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:" \ - "HIGH:!MD5:!aNULL" - -#define DEFAULT_CIPHER_LIST_HEAD "ECDHE-RSA-AES128-SHA256:" \ - "DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH:"\ - "!RC4:!MD5:!aNULL" - -static inline const char * legacy_cipher_list(const char * ver) { - if (ver == NULL) { - return NULL; - } - if (strncmp(ver, "v0.10.38", 8) == 0) { - return DEFAULT_CIPHER_LIST_V10_38; - } else if (strncmp(ver, "v0.10.39", 8) == 0) { - return DEFAULT_CIPHER_LIST_V10_39; - } else if (strncmp(ver, "v0.12.2", 7) == 0) { - return DEFAULT_CIPHER_LIST_V12_2; - } else { - return NULL; - } -} - namespace node { extern bool SSL2_ENABLE; extern bool SSL3_ENABLE; -extern const char * DEFAULT_CIPHER_LIST; namespace crypto { diff --git a/test/simple/test-tls-cipher-list.js b/test/simple/test-tls-cipher-list.js deleted file mode 100644 index 84e76eb5b5..0000000000 --- a/test/simple/test-tls-cipher-list.js +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var spawn = require('child_process').spawn; -var assert = require('assert'); -var tls = require('tls'); - -function doTest(checklist, env, useswitch) { - var options; - if (env && useswitch === 1) { - options = {env:env}; - } - var args = ['-e', 'console.log(require(\'tls\').DEFAULT_CIPHERS)']; - - switch(useswitch) { - case 1: - // Test --cipher-test - args.unshift('--cipher-list=' + env); - break; - case 2: - // Test --enable-legacy-cipher-list - args.unshift('--enable-legacy-cipher-list=' + env); - break; - case 3: - // Test NODE_LEGACY_CIPHER_LIST - if (env) options = {env:{"NODE_LEGACY_CIPHER_LIST": env}}; - break; - default: - // Test NODE_CIPHER_LIST - if (env) options = {env:env}; - } - - var out = ''; - spawn(process.execPath, args, options). - stdout. - on('data', function(data) { - out += data; - }). - on('end', function() { - assert.equal(out.trim(), checklist); - }); -} - -doTest(tls.DEFAULT_CIPHERS); // test the default -doTest('ABC', {'NODE_CIPHER_LIST':'ABC'}); // test the envar -doTest('ABC', 'ABC', 1); // test the --cipher-list switch - -['v0.10.38', 'v0.10.39', 'v0.12.2'].forEach(function(ver) { - doTest(tls.getLegacyCiphers(ver), ver, 2); - doTest(tls.getLegacyCiphers(ver), ver, 3); -}); diff --git a/test/simple/test-tls-getcipher.js b/test/simple/test-tls-getcipher.js index 8fb9d52873..22a280e587 100644 --- a/test/simple/test-tls-getcipher.js +++ b/test/simple/test-tls-getcipher.js @@ -49,7 +49,7 @@ server.listen(common.PORT, '127.0.0.1', function() { rejectUnauthorized: false }, function() { var cipher = client.getCipher(); - assert.equal(cipher.name, cipher_list[1]); + assert.equal(cipher.name, cipher_list[0]); assert(cipher_version_pattern.test(cipher.version)); client.end(); server.close();