diff --git a/doc/api/tls.markdown b/doc/api/tls.markdown index 49b37106e2..fbd97e88a6 100644 --- a/doc/api/tls.markdown +++ b/doc/api/tls.markdown @@ -109,60 +109,6 @@ handshake extensions allowing you: * SNI - to use one TLS server for multiple hostnames with different SSL certificates. -## 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:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH - -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.39 uses a different default than -v0.10.38. 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 - -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 - -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() @@ -205,13 +151,13 @@ automatically set as a listener for the [secureConnection][] event. The conjunction with the `honorCipherOrder` option described below to prioritize the non-CBC cipher. - Defaults to `ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH`. + Defaults to `AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH`. Consult the [OpenSSL cipher list format documentation] for details on the format. ECDH (Elliptic Curve Diffie-Hellman) ciphers are not yet supported. `AES128-GCM-SHA256` is used when node.js is linked against OpenSSL 1.0.1 - or newer and the client speaks TLS 1.2. + or newer and the client speaks TLS 1.2, RC4 is used as a secure fallback. **NOTE**: Previous revisions of this section suggested `AES256-SHA` as an acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore @@ -387,7 +333,7 @@ Here is an example of a client of echo server as described previously: // These are necessary only if using the client certificate authentication key: fs.readFileSync('client-key.pem'), cert: fs.readFileSync('client-cert.pem'), - + // This is necessary only if the server uses the self-signed certificate ca: [ fs.readFileSync('server-cert.pem') ] }; @@ -579,7 +525,7 @@ A ClearTextStream is the `clear` member of a SecurePair object. ### Event: 'secureConnect' -This event is emitted after a new connection has been successfully handshaked. +This event is emitted after a new connection has been successfully handshaked. The listener will be called no matter if the server's certificate was authorized or not. It is up to the user to test `cleartextStream.authorized` to see if the server certificate was signed by one of the specified CAs. @@ -604,14 +550,14 @@ some properties corresponding to the field of the certificate. Example: - { subject: + { subject: { C: 'UK', ST: 'Acknack Ltd', L: 'Rhys Jones', O: 'node.js', OU: 'Test TLS Certificate', CN: 'localhost' }, - issuer: + issuer: { C: 'UK', ST: 'Acknack Ltd', L: 'Rhys Jones', diff --git a/lib/tls.js b/lib/tls.js index 9f53ad82ae..e3b9083223 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 crypto = require('crypto'); var util = require('util'); var net = require('net'); @@ -33,9 +31,8 @@ var constants = require('constants'); var Timer = process.binding('timer_wrap').Timer; -var DEFAULT_CIPHERS = _crypto.DEFAULT_CIPHER_LIST; - -exports.getLegacyCiphers = _crypto.getLegacyCiphers; +var DEFAULT_CIPHERS = 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:' + // TLS 1.2 + 'RC4:HIGH:!MD5:!aNULL:!EDH'; // TLS 1.0 // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more @@ -47,7 +44,7 @@ exports.CLIENT_RENEG_WINDOW = 600; exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024; 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) { @@ -68,7 +65,7 @@ if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) { var Connection = null; try { - Connection = _crypto.Connection; + Connection = process.binding('crypto').Connection; } catch (e) { throw new Error('node.js not compiled with openssl crypto support.'); } @@ -1338,9 +1335,6 @@ exports.connect = function(/* [port, host], options, cb */) { var defaults = { rejectUnauthorized: '0' !== process.env.NODE_TLS_REJECT_UNAUTHORIZED }; - if (DEFAULT_CIPHERS != _crypto.getLegacyCiphers('v0.10.38')) { - defaults.ciphers = DEFAULT_CIPHERS; - } options = util._extend(defaults, options || {}); options.secureOptions = crypto._getSecureOptions(options.secureProtocol, diff --git a/src/node.cc b/src/node.cc index 81e123e571..e80c1a573f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2566,8 +2566,6 @@ static void PrintHelp() { " --max-stack-size=val set max v8 stack size (bytes)\n" " --enable-ssl2 enable ssl2\n" " --enable-ssl3 enable ssl3\n" - " --cipher-list=val specify the default TLS cipher list\n" - " --enable-legacy-cipher-list=v0.10.38 \n" "\n" "Environment variables:\n" #ifdef _WIN32 @@ -2579,8 +2577,6 @@ static void PrintHelp() { "NODE_MODULE_CONTEXTS Set to 1 to load modules in their own\n" " global contexts.\n" "NODE_DISABLE_COLORS Set to 1 to disable colors in the REPL\n" - "NODE_CIPHER_LIST Override the default TLS cipher list\n" - "NODE_LEGACY_CIPHER_LIST=v0.10.38\n" "\n" "Documentation can be found at http://nodejs.org/\n"); } @@ -2588,7 +2584,6 @@ static void PrintHelp() { // Parse node command line arguments. static void ParseArgs(int argc, char **argv) { int i; - bool using_legacy_cipher_list = false; // TODO use parse opts for (i = 1; i < argc; i++) { @@ -2657,21 +2652,6 @@ static void ParseArgs(int argc, char **argv) { } else if (strcmp(arg, "--throw-deprecation") == 0) { argv[i] = const_cast(""); throw_deprecation = true; - } else if (strncmp(arg, "--cipher-list=", 14) == 0) { - if (!using_legacy_cipher_list) { - DEFAULT_CIPHER_LIST = arg + 14; - } - argv[i] = const_cast(""); - } else if (strncmp(arg, "--enable-legacy-cipher-list=", 28) == 0) { - 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); - } - argv[i] = const_cast(""); } else if (argv[i][0] != '-') { break; } @@ -2966,25 +2946,6 @@ char** Init(int argc, char *argv[]) { v8argv[option_end_index + 1] = const_cast("v8debug"); } - 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 - 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); - } - } - // For the normal stack which moves from high to low addresses when frames // are pushed, we can compute the limit as stack_size bytes below the // the address of a stack variable (e.g. &stack_var) as an approximation diff --git a/src/node_crypto.cc b/src/node_crypto.cc index c1e943fef4..7a3922a797 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -71,7 +71,6 @@ const char* root_certs[] = { bool SSL2_ENABLE = false; bool SSL3_ENABLE = false; -const char * DEFAULT_CIPHER_LIST = DEFAULT_CIPHER_LIST_HEAD; namespace crypto { @@ -803,7 +802,7 @@ size_t ClientHelloParser::Write(const uint8_t* data, size_t len) { HandleScope scope; assert(state_ != kEnded); - + // Just accumulate data, everything will be pushed to BIO later if (state_ == kPaused) return 0; @@ -4191,21 +4190,6 @@ static void array_push_back(const TypeName* md, arr->Set(arr->Length(), String::New(from)); } -// borrowed from v8 -// (see http://v8.googlecode.com/svn/trunk/samples/shell.cc) -const char* ToCString(const node::Utf8Value& value) { - return *value ? *value : ""; -} - -Handle DefaultCiphers(const Arguments& args) { - HandleScope scope; - node::Utf8Value key(args[0]); - const char * list = legacy_cipher_list(ToCString(key)); - if (list == NULL) { - list = DEFAULT_CIPHER_LIST_HEAD; - } - return scope.Close(v8::String::New(list)); -} Handle GetCiphers(const Arguments& args) { HandleScope scope; @@ -4280,13 +4264,6 @@ void InitCrypto(Handle target) { NODE_DEFINE_CONSTANT(target, SSL3_ENABLE); NODE_DEFINE_CONSTANT(target, SSL2_ENABLE); - - (target)->ForceSet( - v8::String::New("DEFAULT_CIPHER_LIST"), - v8::String::New(DEFAULT_CIPHER_LIST), - static_cast(v8::ReadOnly | v8::DontDelete)); - - NODE_SET_METHOD(target, "getLegacyCiphers", DefaultCiphers); } } // namespace crypto diff --git a/src/node_crypto.h b/src/node_crypto.h index 0b360cfa36..54b9b88e43 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -27,7 +27,6 @@ #include "node_object_wrap.h" #include "v8.h" -#include #include #include #include @@ -44,29 +43,10 @@ #define EVP_F_EVP_DECRYPTFINAL 101 -#define DEFAULT_CIPHER_LIST_V10_38 "ECDHE-RSA-AES128-SHA256:" \ - "AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH" - -#define DEFAULT_CIPHER_LIST_HEAD "ECDHE-RSA-AES128-SHA256:" \ - "AES128-GCM-SHA256:HIGH:!RC4:!MD5:!aNULL:!EDH" - -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 { - 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 ac2169537b..0000000000 --- a/test/simple/test-tls-cipher-list.js +++ /dev/null @@ -1,70 +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'); -var crypto = process.binding('crypto'); - -function doTest(checklist, env, useswitch) { - var options; - if (env && useswitch === 1) { - options = {env:env}; - } - var args = ['-e', 'console.log(process.binding(\'crypto\').DEFAULT_CIPHER_LIST)']; - - 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(crypto.DEFAULT_CIPHER_LIST); // test the default -doTest('ABC', {'NODE_CIPHER_LIST':'ABC'}); // test the envar -doTest('ABC', 'ABC', 1); // test the --cipher-list switch - -['v0.10.38'].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();